BOOL CToolTipCtrlX::OnTTShow(NMHDR *pNMHDR, LRESULT *pResult) { //DebugLog(_T("OnTTShow: rcScreen: %d,%d-%d,%d: styles=%08x exStyles=%08x"), m_rcScreen, GetStyle(), GetWindowLong(m_hWnd, GWL_EXSTYLE)); // Win98/Win2000: The only chance to resize a tooltip window is to do it within the TTN_SHOW notification. if (theApp.m_ullComCtrlVer <= MAKEDLLVERULL(5,81,0,0)) { NMTTCUSTOMDRAW nmttcd = {0}; nmttcd.uDrawFlags = DT_NOPREFIX | DT_CALCRECT | DT_EXTERNALLEADING | DT_EXPANDTABS | DT_WORDBREAK; nmttcd.nmcd.hdr = *pNMHDR; nmttcd.nmcd.dwDrawStage = CDDS_PREPAINT; nmttcd.nmcd.hdc = ::GetDC(pNMHDR->hwndFrom); CustomPaint(&nmttcd); ::ReleaseDC(pNMHDR->hwndFrom, nmttcd.nmcd.hdc); CRect rcWnd(nmttcd.nmcd.rc); AdjustRect(&rcWnd); // Win98/Win2000: We have to explicitly ensure that the tooltip window remains within the visible desktop window. EnsureWindowVisible(m_rcScreen, rcWnd); // Win98/Win2000: The only chance to resize a tooltip window is to do it within the TTN_SHOW notification. // Win98/Win2000: Must *not* specify 'SWP_NOZORDER' - some of the tooltip windows may get drawn behind(!) the application window! ::SetWindowPos(pNMHDR->hwndFrom, NULL, rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(), SWP_NOACTIVATE /*| SWP_NOZORDER*/); *pResult = TRUE; // Windows API: Suppress default positioning return TRUE; // MFC API: Suppress further routing of this message } // If the TTN_SHOW notification is not sent to the subclassed tooltip control, we would loose the // exact positioning of in-place tooltips which is performed by the tooltip control by default. // Thus it is important that we tell MFC (not the Windows API in that case) to further route this message. *pResult = FALSE; // Windows API: Perform default positioning return FALSE; // MFC API. Perform further routing of this message (to the subclassed tooltip control) }
bool IsCursorOverWindow(HWND hwnd) { POINT pt; GetCursorPos(&pt); WindowRect rcWnd(hwnd); return rcWnd.Contains(PointI(pt.x, pt.y)); }
/**< display image full fit wnd */ bool ImagePanel::ImgZoomFit() { if (!m_img.IsOk()) return false; wxRect2DDouble rcWnd(0.0, 0.0, 0.0, 0.0); // wnd rect wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // img rect do { wxSize szWnd = GetClientSize(); wxSize szImg = m_img.GetSize(); rcWnd.m_width = szWnd.GetWidth(); rcWnd.m_height = szWnd.GetHeight(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // image is full displayed m_rcSrc.m_x = 0.0; m_rcSrc.m_y = 0.0; m_rcSrc.m_width = rcImg.m_width; m_rcSrc.m_height = rcImg.m_height; // calculation scale and dest rect if (rcWnd.m_width/rcWnd.m_height > rcImg.m_width/rcImg.m_height) // wnd is wide then image, or image is heigher then wnd { wxDouble dTmp = 0.0; m_dScale = rcWnd.m_height/rcImg.m_height; dTmp = rcImg.m_width*m_dScale; // image scale width m_rcDest.m_x = (rcWnd.m_width - dTmp)/2.0; m_rcDest.m_y = 0.0; m_rcDest.m_width = dTmp; m_rcDest.m_height = rcWnd.m_height; } else // wnd is heigher than image, or image is wide than wnd { wxDouble dTmp = 0.0; m_dScale = rcWnd.m_width/rcImg.m_width; dTmp = rcImg.m_height*m_dScale; // image scale height m_rcDest.m_x = 0.0; m_rcDest.m_y = (rcWnd.m_height - dTmp)/2.0; m_rcDest.m_width = rcWnd.m_width; m_rcDest.m_height = dTmp; } // update panel Refresh(false); return true; }
// CSimpleAnimationDlg message handlers bool CSimpleAnimationDlg::Create( CWnd * pWndParent ) { ASSERT_VALID( this ); ASSERT( GetSafeHwnd() == NULL ); CRect rcDesktop; VERIFY( ::SystemParametersInfo( SPI_GETWORKAREA, 0, PVOID(&rcDesktop), 0 ) ); if(!CDialog::Create(MAKEINTRESOURCE(IDD_SIMPLE_ANIMATION) , pWndParent)) { ASSERT( FALSE ); return false; } if(NULL != pWndParent) pWndParent->GetWindowRect(&rcDesktop); CRect rcWnd( 0, 0, 0, 0); GetWindowRect(&rcWnd); rcWnd.OffsetRect( ( rcDesktop.Width() - rcWnd.Width() ) * 0.5, ( rcDesktop.Height() - rcWnd.Height() ) * 0.5 ); VERIFY( ::SetWindowPos(m_hWnd , (NULL != pWndParent) ? pWndParent->GetSafeHwnd() : HWND_TOP , rcWnd.left , rcWnd.top , rcWnd.Width() , rcWnd.Height() , SWP_NOSIZE | SWP_SHOWWINDOW) ); ///CSimpleAnimationDlg::PassMsgLoop( false ); return true; }
void CExtMiniDockFrameWnd::_ResizingUpdateState( const CPoint & point ) { if( g_bInResizingUpdateState || m_ptLastResizing == point ) return; m_ptLastResizing = point; g_bInResizingUpdateState = true; CPoint _pt( point ); ASSERT( m_nResizingMode != HTNOWHERE ); CExtControlBar * pExtBar = GetControlBarExt(); ASSERT_VALID( pExtBar ); //BringWindowToTop(); CRect rcClient, rcClientOrg, rcWnd, rcWndOrg; GetClientRect( &rcClient ); GetWindowRect( &rcWnd ); rcClientOrg = rcClient; rcWndOrg = rcWnd; CSize sizeDiff = rcWnd.Size() - rcClient.Size(); ASSERT( sizeDiff.cx >= 0 && sizeDiff.cy >= 0 ); CSize sizeNcDiff( sizeDiff ); int nCalcMinHW = pExtBar->_CalcDesiredMinHW(); int nCalcMinVH = pExtBar->_CalcDesiredMinVH(); if( sizeDiff.cx < nCalcMinHW ) sizeDiff.cx = nCalcMinHW; if( sizeDiff.cy < nCalcMinVH ) sizeDiff.cy = nCalcMinVH; UINT nHit = m_nResizingMode; bool bLeft = false, bTop = false, bHorz = false, bInvTop = false, bInvLeft = false; CPoint ptOffsetWnd( 0, 0 ); if( pExtBar->IsFixedMode() ) { switch( nHit ) { case HTTOPLEFT: case HTTOPRIGHT: nHit = HTTOP; break; case HTBOTTOMLEFT: case HTBOTTOMRIGHT: nHit = HTBOTTOM; break; } // switch( nHit ) switch( nHit ) { case HTTOP: _pt.y = rcWndOrg.bottom + rcWndOrg.top - _pt.y; nHit = HTBOTTOM; bInvLeft = true; bInvTop = true; break; case HTLEFT: _pt.x = rcWndOrg.right + rcWndOrg.left - _pt.x; nHit = HTRIGHT; bInvLeft = true; bInvTop = true; break; } // switch( nHit ) } // if( pExtBar->IsFixedMode() ) if( bInvLeft || bInvTop || (!pExtBar->IsFixedMode()) ) { CRect rcWnd( rcWndOrg ); ScreenToClient( & rcWnd ); if( bInvLeft || (!pExtBar->IsFixedMode()) ) ptOffsetWnd.x = abs( rcWnd.left - rcClientOrg.left ); if( bInvTop || (!pExtBar->IsFixedMode()) ) ptOffsetWnd.y = abs( rcWnd.top - rcClientOrg.top ); } // if( bInvLeft || bInvTop ) switch( nHit ) { case HTLEFT: bHorz = true; rcWnd.left = min( _pt.x, rcWnd.right ); bLeft = true; break; case HTRIGHT: bHorz = true; rcWnd.right = max( _pt.x, rcWnd.left ); break; case HTTOP: rcWnd.top = min( _pt.y, rcWnd.bottom ); bTop = true; break; case HTTOPLEFT: rcWnd.left = min( _pt.x, rcWnd.right ); rcWnd.top = min( _pt.y, rcWnd.bottom ); bLeft = true; bTop = true; break; case HTTOPRIGHT: rcWnd.right = max( _pt.x, rcWnd.left ); rcWnd.top = min( _pt.y, rcWnd.bottom ); bTop = true; break; case HTBOTTOM: rcWnd.bottom = max( _pt.y, rcWnd.top ); break; case HTBOTTOMLEFT: rcWnd.left = min( _pt.x, rcWnd.right ); rcWnd.bottom = max( _pt.y, rcWnd.top ); bLeft = true; break; case HTBOTTOMRIGHT: rcWnd.right = max( _pt.x, rcWnd.left ); rcWnd.bottom = max( _pt.y, rcWnd.top ); break; default: ASSERT( FALSE ); g_bInResizingUpdateState = false; return; } // switch( nHit ) if( rcWnd.Width() < sizeDiff.cx ) rcWnd.right = rcWnd.left + sizeDiff.cx; if( rcWnd.Height() < sizeDiff.cy ) rcWnd.bottom = rcWnd.top + sizeDiff.cy; if( rcWnd.right > rcWndOrg.right && bLeft ) rcWnd.OffsetRect( rcWndOrg.right - rcWnd.right, 0 ); if( rcWnd.bottom > rcWndOrg.bottom && bTop ) rcWnd.OffsetRect( 0, rcWndOrg.bottom - rcWnd.bottom ); rcClient.SetRect( rcWnd.left - (rcClient.left-rcWndOrg.left), rcWnd.top - (rcClient.top-rcWndOrg.top), rcWnd.right - (rcClient.right-rcWndOrg.right), rcWnd.bottom - (rcClient.bottom-rcWndOrg.bottom) ); if( !pExtBar->IsFixedMode() ) { ASSERT( (GetStyle() & __REMOVED_NONFIXMODE_STYLES) == 0 ); CSize _sizeMinFloated = pExtBar->_CalcDesiredMinFloatedSize(); CSize _size = rcWnd.Size(); if( _size.cx < _sizeMinFloated.cx ) _size.cx = _sizeMinFloated.cx; if( _size.cy < _sizeMinFloated.cy ) _size.cy = _sizeMinFloated.cy; CExtPaintManager::monitor_parms_t _mp; CExtPaintManager::stat_GetMonitorParms( _mp, this ); CSize _sizeMaxFloated = _mp.m_rcWorkArea.Size(); if( _size.cx > _sizeMaxFloated.cx ) _size.cx = _sizeMaxFloated.cx; if( _size.cy > _sizeMaxFloated.cy ) _size.cy = _sizeMaxFloated.cy; CRect rcWndValidated( rcWnd.TopLeft(), _size ); pExtBar->m_sizeFloated = _size - ptOffsetWnd; MoveWindow( &rcWndValidated ); SetTimer( 3, 1, NULL ); g_bInResizingUpdateState = false; return; } // if( !pExtBar->IsFixedMode() ) int nWinResizingFrameDX = ::GetSystemMetrics( SM_CXSIZEFRAME ); int nWinResizingFrameDY = ::GetSystemMetrics( SM_CYSIZEFRAME ); DWORD dwMode = LM_HORZ|LM_COMMIT; LONG nLendth = 0; if( bHorz ) nLendth = rcClient.Width(); else { dwMode |= LM_LENGTHY; nLendth = rcClient.Height() - nWinResizingFrameDY; } // else from if( bHorz ) CSize _sizeFloatedPrev = pExtBar->m_sizeFloated; CSize _size = pExtBar->CalcDynamicLayout( nLendth, dwMode ); if( _sizeFloatedPrev == _size ) { g_bInResizingUpdateState = false; return; } // if( _size.cx < _sizeMinFloated.cx ) // _size.cx = _sizeMinFloated.cx; // if( _size.cy < _sizeMinFloated.cy ) // _size.cy = _sizeMinFloated.cy; pExtBar->m_sizeFloated = _size; if( bInvTop ) { ASSERT( rcWnd.top == rcWndOrg.top ); rcWnd.bottom = m_rcWndResizingStart.bottom; rcWnd.top = rcWnd.bottom - _size.cy - ptOffsetWnd.y; } if( bInvLeft ) { ASSERT( rcWnd.left == rcWndOrg.left ); rcWnd.right = m_rcWndResizingStart.right; rcWnd.left = rcWnd.right - _size.cx - ptOffsetWnd.x; } ASSERT( pExtBar->m_pDockSite != NULL ); ASSERT( pExtBar->m_pDockBar != NULL ); pExtBar->m_ptFloatHelper = rcWnd.TopLeft(); _size += sizeNcDiff; _size.cx -= nWinResizingFrameDX; // (+ v.2.22) _size.cy -= nWinResizingFrameDY; CRect rcToMoveMinFrame( pExtBar->m_ptFloatHelper, _size ); MoveWindow( &rcToMoveMinFrame); SendMessage( WM_NCPAINT ); RecalcLayout(); pExtBar->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW |RDW_ERASE|RDW_ERASENOW |RDW_ALLCHILDREN ); g_bInResizingUpdateState = false; }
/**< move image */ bool ImagePanel::ImgMove(wxSize szMove) { if (!m_img.IsOk()) return false; // the move size must be valid if (szMove.x == 0 || szMove.y == 0) return false; wxPoint2DDouble ptMove(szMove.x, szMove.y); wxRect2DDouble rcWnd(0.0, 0.0, 0.0, 0.0); // wnd rect wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // img rect do { wxSize szWnd = GetClientSize(); wxSize szImg = m_img.GetSize(); rcWnd.m_width = szWnd.GetWidth(); rcWnd.m_height = szWnd.GetHeight(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // current image rect in wnd coordinate wxRect2DDouble rcNew; rcNew.m_x = m_rcDest.m_x - m_rcSrc.m_x*m_dScale; rcNew.m_y = m_rcDest.m_y - m_rcSrc.m_y*m_dScale; rcNew.m_width = rcImg.m_width*m_dScale; rcNew.m_height = rcImg.m_height*m_dScale; // then horizontal move the rect if ((rcNew.m_x + ptMove.m_x) > rcWnd.m_width/2.0) ptMove.m_x = (int)(rcWnd.m_width/2.0 - rcNew.m_x); else if ((rcNew.GetRight() + ptMove.m_x) <= rcWnd.m_width/2.0) ptMove.m_x = (int)(rcWnd.m_width/2.0 - rcNew.GetRight()); // and then vertical move the rect if ((rcNew.m_y + ptMove.m_y) > rcWnd.m_height/2.0) ptMove.m_y = (int)(rcWnd.m_height/2.0 - rcNew.m_y); else if ((rcNew.GetBottom() + ptMove.m_y) <= rcWnd.m_height/2.0) ptMove.m_y = (int)(rcWnd.m_height/2.0 - rcNew.GetBottom()); rcNew.Offset(ptMove); // the dest rect is the intersection of new rect and wnd rect wxRect2DDouble::Intersect(rcNew, rcWnd, &m_rcDest); // calculate the src rect m_rcSrc.m_x = (m_rcDest.m_x - rcNew.m_x)/m_dScale; m_rcSrc.m_y = (m_rcDest.m_y - rcNew.m_y)/m_dScale; m_rcSrc.m_width = m_rcDest.m_width/m_dScale; m_rcSrc.m_height = m_rcDest.m_height/m_dScale; // ensure the src rect is valid if (m_rcSrc.m_x < 0.0) m_rcSrc.m_x = 0.0; if (m_rcSrc.m_y < 0.0) m_rcSrc.m_y = 0.0; if (m_rcSrc.GetRight() > rcImg.m_width) m_rcSrc.m_width = rcImg.m_width - m_rcSrc.m_x; if (m_rcSrc.GetBottom() > rcImg.m_height) m_rcSrc.m_height = rcImg.m_height - m_rcSrc.m_y; // update panel Refresh(false); return true; }
/**< dispaly image in real size */ bool ImagePanel::ImgZoomActual() { if (!m_img.IsOk()) return false; wxRect2DDouble rcWnd(0.0, 0.0, 0.0, 0.0); // wnd rect wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // img rect do { wxSize szWnd = GetClientSize(); wxSize szImg = m_img.GetSize(); rcWnd.m_width = szWnd.GetWidth(); rcWnd.m_height = szWnd.GetHeight(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // image is actual size displayed m_dScale = 1.0; // Horizontal positioning if (rcWnd.m_width > rcImg.m_width) { m_rcSrc.m_x = 0.0; m_rcSrc.m_width = rcImg.m_width; // wnd left and right have space m_rcDest.m_x = (rcWnd.m_width - rcImg.m_width)/2.0; m_rcDest.m_width = rcImg.m_width; } else { // only part of image be displayed m_rcSrc.m_x = (rcImg.m_width - rcWnd.m_width)/2.0; m_rcSrc.m_width = rcWnd.m_width; // wnd is filled width m_rcDest.m_x = 0.0; m_rcDest.m_width = rcWnd.m_width; } // Vertical positioning if (rcWnd.m_height > rcImg.m_height) { m_rcSrc.m_y = 0.0; m_rcSrc.m_height = rcImg.m_height; // wnd's top and bottom have space m_rcDest.m_y = (rcWnd.m_height - rcImg.m_height)/2.0; m_rcDest.m_height = rcImg.m_height; } else { // only part image be displayed m_rcSrc.m_y = (rcImg.m_height - rcWnd.m_height)/2.0; m_rcSrc.m_height = rcWnd.m_height; // wnd is fill height m_rcDest.m_y = 0.0; m_rcDest.m_height = rcWnd.m_height; } // update panel Refresh(false); return true; }
/**< display image of sel rect full fit wnd */ bool ImagePanel::ImgZoomRect(wxRect rcSel) { if (!m_img.IsOk()) return false; // the rect must be regular if (rcSel.width <= 2 || rcSel.height < 2) return false; wxRect2DDouble rcWnd(0.0, 0.0, 0.0, 0.0); // wnd rect wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // image rect do { wxSize szWnd = GetClientSize(); wxSize szImg = m_img.GetSize(); rcWnd.m_width = szWnd.GetWidth(); rcWnd.m_height = szWnd.GetHeight(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // calculate the new scale wxDouble dScale = 1.0; if (rcWnd.m_width/rcWnd.m_height > rcSel.width/(wxDouble)rcSel.height) dScale = rcWnd.m_height/rcSel.height; else dScale = rcWnd.m_width/rcSel.width; dScale *= m_dScale; if (dScale > 20.0) dScale = 20.0; // sel rect center point wxPoint2DDouble ptV0, ptI0; ptV0.m_x = rcSel.x + rcSel.width/2.0; ptV0.m_y = rcSel.y + rcSel.height/2.0; ptI0.m_x = m_rcSrc.m_x + (ptV0.m_x - m_rcDest.m_x)/m_dScale; ptI0.m_y = m_rcSrc.m_y + (ptV0.m_y - m_rcDest.m_y)/m_dScale; // calculate the new image rect in wnd coordinate wxRect2DDouble rcNew; rcNew.m_x = ptV0.m_x - ptI0.m_x*dScale; rcNew.m_y = ptV0.m_y - ptI0.m_y*dScale; rcNew.m_width = rcImg.m_width*dScale; rcNew.m_height = rcImg.m_height*dScale; // move the sel rect center to the wnd center rcNew.m_x -= ptV0.m_x - rcWnd.m_width/2.0; rcNew.m_y -= ptV0.m_y - rcWnd.m_height/2.0; ptV0.m_x = rcWnd.m_width/2.0; ptV0.m_y = rcWnd.m_height/2.0; // the dest rect is the intersection of the new image view rect & wnd rect wxRect2DDouble::Intersect(rcWnd, rcNew, &m_rcDest); // calculate the src rect m_rcSrc.m_x = ptI0.m_x + (m_rcDest.m_x - ptV0.m_x)/dScale; m_rcSrc.m_y = ptI0.m_y + (m_rcDest.m_y - ptV0.m_y)/dScale; m_rcSrc.m_width = m_rcDest.m_width/dScale; m_rcSrc.m_height = m_rcDest.m_height/dScale; // ensure the src rect is valid if (m_rcSrc.m_x < 0.0) m_rcSrc.m_x = 0.0; if (m_rcSrc.m_y < 0.0) m_rcSrc.m_y = 0.0; if (m_rcSrc.GetRight() > rcImg.m_width) m_rcSrc.m_width = rcImg.m_width - m_rcSrc.m_x; if (m_rcSrc.GetBottom() > rcImg.m_height) m_rcSrc.m_height = rcImg.m_height - m_rcSrc.m_y; // the new scale m_dScale = dScale; // update ui Refresh(false); return true; }
/**< on wnd resized */ void ImagePanel::OnSize(wxSizeEvent& event) { if (!m_img.IsOk()) return; // ensure the new size is valid if (event.m_size.x < 2 || event.m_size.y < 2) return; // the center move of the wnd wxPoint2DDouble szMove; szMove.m_x = (event.m_size.x - m_szClient.x)/2.0; szMove.m_y = (event.m_size.y - m_szClient.y)/2.0; wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // img rect wxRect2DDouble rcWnd(0.0, 0.0, event.m_size.x, event.m_size.y); // new wnd rect do { wxSize szImg = m_img.GetSize(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // current image rect in wnd coordinate wxRect2DDouble rcNew; rcNew.m_x = m_rcDest.m_x - m_rcSrc.m_x*m_dScale; rcNew.m_y = m_rcDest.m_y - m_rcSrc.m_y*m_dScale; rcNew.m_width = rcImg.m_width*m_dScale; rcNew.m_height = rcImg.m_height*m_dScale; // then horizontal move the rect if ((rcNew.m_x + szMove.m_x) > rcWnd.m_width/2.0) szMove.m_x = (int)(rcWnd.m_width/2.0 - rcNew.m_x); else if ((rcNew.GetRight() + szMove.m_x) <= rcWnd.m_width/2.0) szMove.m_x = (int)(rcWnd.m_width/2.0 - rcNew.GetRight()); // and then vertical move the rect if ((rcNew.m_y + szMove.m_y) > rcWnd.m_height/2.0) szMove.m_y = (int)(rcWnd.m_height/2.0 - rcNew.m_y); else if ((rcNew.GetBottom() + szMove.m_y) <= rcWnd.m_height/2.0) szMove.m_y = (int)(rcWnd.m_height/2.0 - rcNew.GetBottom()); rcNew.Offset(szMove); // the dest rect is the intersection of new rect and wnd rect wxRect2DDouble::Intersect(rcNew, rcWnd, &m_rcDest); // calculate the src rect m_rcSrc.m_x = (m_rcDest.m_x - rcNew.m_x)/m_dScale; m_rcSrc.m_y = (m_rcDest.m_y - rcNew.m_y)/m_dScale; m_rcSrc.m_width = m_rcDest.m_width/m_dScale; m_rcSrc.m_height = m_rcDest.m_height/m_dScale; // ensure the src rect is valid if (m_rcSrc.m_x < 0.0) m_rcSrc.m_x = 0.0; if (m_rcSrc.m_y < 0.0) m_rcSrc.m_y = 0.0; if (m_rcSrc.GetRight() > rcImg.m_width) m_rcSrc.m_width = rcImg.m_width - m_rcSrc.m_x; if (m_rcSrc.GetBottom() > rcImg.m_height) m_rcSrc.m_height = rcImg.m_height - m_rcSrc.m_y; // log the size m_szClient = event.m_size; // update panel //Refresh(false); }
/**< according to the specified zoom percentage */ bool ImagePanel::ImgZoomScale(wxDouble dScale, wxPoint* pPt /*= nullptr*/) { if (!m_img.IsOk()) return false; if (dScale <= 0.0) return false; if (dScale > 20.0) dScale = 20.0; wxRect2DDouble rcWnd(0.0, 0.0, 0.0, 0.0); // wnd rect wxRect2DDouble rcImg(0.0, 0.0, 0.0, 0.0); // img rect do { wxSize szWnd = GetClientSize(); wxSize szImg = m_img.GetSize(); rcWnd.m_width = szWnd.GetWidth(); rcWnd.m_height = szWnd.GetHeight(); rcImg.m_width = szImg.GetWidth(); rcImg.m_height = szImg.GetHeight(); } while(false); // default image pix in wnd center as the fixed point wxPoint2DDouble ptV0, ptI0; wxDouble dTmp = 0.0; if (pPt == nullptr) { ptV0.m_x = rcWnd.m_width/2.0; ptV0.m_y = rcWnd.m_height/2.0; } else { ptV0.m_x = pPt->x; ptV0.m_y = pPt->y; } dTmp = (ptV0.m_x - m_rcDest.m_x)/m_dScale; // V2I ptI0.m_x = m_rcSrc.m_x + dTmp; dTmp = (ptV0.m_y - m_rcDest.m_y)/m_dScale; ptI0.m_y = m_rcSrc.m_y + dTmp; // the image view rect in new scale wxRect2DDouble rcNew; rcNew.m_x = ptV0.m_x - ptI0.m_x*dScale; rcNew.m_y = ptV0.m_y - ptI0.m_y*dScale; rcNew.m_width = rcImg.m_width*dScale; rcNew.m_height = rcImg.m_height*dScale; // Dest rect is the intersection of new image view rect & wnd rect wxRect2DDouble::Intersect(rcWnd, rcNew, &m_rcDest); // the src rect in new scale m_rcSrc.m_x = ptI0.m_x + (m_rcDest.m_x - ptV0.m_x)/dScale; m_rcSrc.m_y = ptI0.m_y + (m_rcDest.m_y - ptV0.m_y)/dScale; m_rcSrc.m_width = m_rcDest.m_width/dScale; m_rcSrc.m_height = m_rcDest.m_height/dScale; // ensure the src rect is valid if (m_rcSrc.m_x < 0.0) m_rcSrc.m_x = 0.0; if (m_rcSrc.m_y < 0.0) m_rcSrc.m_y = 0.0; if (m_rcSrc.GetRight() > rcImg.m_width) m_rcSrc.m_width = rcImg.m_width - m_rcSrc.m_x; if (m_rcSrc.GetBottom() > rcImg.m_height) m_rcSrc.m_height = rcImg.m_height - m_rcSrc.m_y; // new zoom scale m_dScale = dScale; // update panel Refresh(false); return true; }