GME
13
|
00001 // PannButton.cpp : implementation file 00002 // 00003 00004 #include "stdafx.h" 00005 #include "PanningButton.h" 00006 #include "PanningViewCtrl.h" 00007 00008 #ifdef _DEBUG 00009 #define new DEBUG_NEW 00010 #undef THIS_FILE 00011 static char THIS_FILE[] = __FILE__; 00012 #endif 00013 00015 // CPanningButton 00016 00017 CPanningButton::CPanningButton() 00018 { 00019 m_viewRectOnScreen = CRect(0, 0, 0, 0); 00020 m_viewRectInMove = CRect(0, 0, 0, 0); 00021 m_viewRectOnStored = CRect(0, 0, 0, 0); 00022 m_bitmapDC = NULL; 00023 m_oldBmp = NULL; 00024 m_bitmapSizeStored = CRect(0, 0, 0, 0); 00025 m_bitmapSizeOri = CRect(0, 0, 0, 0); 00026 m_owner = NULL; 00027 m_backgorund = RGB(255, 255, 255); 00028 m_sizeallh = NULL; 00029 m_arrowh = NULL; 00030 m_inMove = false; 00031 m_storedToScreenRx = 0; 00032 m_storedToScreenRy = 0; 00033 m_oriToStoredRx = 0; 00034 m_oriToStoredRy = 0; 00035 } 00036 00037 CPanningButton::~CPanningButton() 00038 { 00039 if (m_bitmapDC != NULL) 00040 DeleteDeviceContext(m_bitmapDC, m_oldBmp); 00041 } 00042 00043 00044 BEGIN_MESSAGE_MAP(CPanningButton, CWnd) 00045 //{{AFX_MSG_MAP(CPanningButton) 00046 ON_WM_PAINT() 00047 ON_WM_ERASEBKGND() 00048 ON_WM_MOUSEMOVE() 00049 ON_WM_LBUTTONDOWN() 00050 ON_WM_LBUTTONUP() 00051 //}}AFX_MSG_MAP 00052 END_MESSAGE_MAP() 00053 00055 // CPanningButton message handlers 00056 00057 bool CPanningButton::Create() 00058 { 00059 m_sizeallh = ::LoadCursor(NULL, IDC_SIZEALL); 00060 m_arrowh = ::LoadCursor(NULL, IDC_ARROW); 00061 return true; 00062 } 00063 00064 void CPanningButton::SetBitmapDC(HWND owner, HDC bdc, HBITMAP oldBmp, CRect& orisize, CRect& actsize, COLORREF& bkgrnd) // may be empty 00065 { 00066 if (m_bitmapDC != NULL) 00067 DeleteDeviceContext(m_bitmapDC, m_oldBmp); 00068 m_owner = owner; 00069 m_bitmapDC = bdc; 00070 m_oldBmp = oldBmp; 00071 m_bitmapSizeOri = orisize; 00072 m_bitmapSizeStored = actsize; 00073 m_backgorund = bkgrnd; 00074 00075 Invalidate(); 00076 UpdateWindow(); 00077 } 00078 00079 void CPanningButton::SetViewRect(CRect irect) 00080 { 00081 // the method can be called even if the panning window is not visible 00082 if (m_bitmapSizeOri.IsRectEmpty() || m_bitmapSizeStored.IsRectEmpty()) 00083 return; 00084 if (!::IsWindow(GetSafeHwnd())) 00085 return; 00086 00087 m_oriToStoredRx = (double)(m_bitmapSizeStored.Width()) / m_bitmapSizeOri.Width(); 00088 m_oriToStoredRy = (double)(m_bitmapSizeStored.Height()) / m_bitmapSizeOri.Height(); 00089 CRect newViewRectOnStored; 00090 newViewRectOnStored.left = (int)(irect.left * m_oriToStoredRx); 00091 newViewRectOnStored.right = (int)(irect.right * m_oriToStoredRx); 00092 newViewRectOnStored.top = (int)(irect.top * m_oriToStoredRy); 00093 newViewRectOnStored.bottom = (int)(irect.bottom * m_oriToStoredRy); 00094 if (m_viewRectOnStored.EqualRect(&newViewRectOnStored)) 00095 return; 00096 else 00097 m_viewRectOnStored = newViewRectOnStored; 00098 00099 CRect vRect(0, 0, 0, 0); 00100 CRect client; 00101 GetParent()->GetClientRect(&client); 00102 00103 BmpToScreen(client); 00104 ViewRectToScreen(vRect); 00105 00106 InvalidateRect(&m_viewRectOnScreen, FALSE); 00107 m_viewRectOnScreen = vRect; 00108 InvalidateRect(&vRect, FALSE); 00109 UpdateWindow(); 00110 } 00111 00112 void CPanningButton::BmpToScreen(CRect clientr) 00113 { 00114 double dx = (double)(clientr.Width()) / m_bitmapSizeStored.Width(); 00115 double dy = (double)(clientr.Height()) / m_bitmapSizeStored.Height(); 00116 double dd = (dx <= dy) ? dx: dy; 00117 dd = (dd < 1)? dd: 1; 00118 00119 clientr.right = min(clientr.right, (LONG)(dd * m_bitmapSizeStored.Width())); 00120 clientr.bottom = min(clientr.bottom, (LONG)(dd * m_bitmapSizeStored.Height())); 00121 m_bitmapOnScreen = clientr; 00122 } 00123 00124 void CPanningButton::ViewRectToScreen(CRect &vRect) 00125 { 00126 m_storedToScreenRx = (double)(m_bitmapOnScreen.Width()) / m_bitmapSizeStored.Width(); 00127 m_storedToScreenRy = (double)(m_bitmapOnScreen.Height()) / m_bitmapSizeStored.Height(); 00128 vRect = CRect(0, 0, 0, 0); 00129 vRect.left = (LONG)(m_viewRectOnStored.left * m_storedToScreenRx); 00130 vRect.right = (LONG)(m_viewRectOnStored.right * m_storedToScreenRx); 00131 vRect.top = (LONG)(m_viewRectOnStored.top * m_storedToScreenRy); 00132 vRect.bottom = (LONG)(m_viewRectOnStored.bottom * m_storedToScreenRy); 00133 vRect.right = min(vRect.right, m_bitmapOnScreen.right); 00134 vRect.bottom = min(vRect.bottom, m_bitmapOnScreen.bottom); 00135 } 00136 00137 void CPanningButton::DeleteDeviceContext(HDC bDC, HBITMAP oldBmp) 00138 { 00139 HBITMAP hBmp = (HBITMAP)::SelectObject(bDC, (HBITMAP)oldBmp); 00140 BOOL succ = FALSE; 00141 if (hBmp != NULL) { 00142 succ = ::DeleteObject(hBmp); 00143 ASSERT(succ != FALSE); 00144 } 00145 succ = ::DeleteDC(bDC); 00146 ASSERT(succ != FALSE); 00147 } 00148 00149 void CPanningButton::OnPaint() 00150 { 00151 CPaintDC dc(this); // device context for painting 00152 dc.SetMapMode(MM_TEXT); 00153 00154 // clear it 00155 CRect clientr; 00156 GetParent()->GetClientRect(&clientr); 00157 CBrush brush; 00158 COLORREF col; 00159 if (m_bitmapDC == NULL) { 00160 DWORD dw = ::GetSysColor(COLOR_3DFACE); 00161 BYTE r = GetRValue(dw); 00162 BYTE g = GetGValue(dw); 00163 BYTE b = GetBValue(dw); 00164 col = RGB(r,g,b); 00165 } else { 00166 col = m_backgorund; 00167 } 00168 brush.CreateSolidBrush(col); 00169 dc.FillRect(&clientr, &brush); 00170 00171 // no bitmap - return 00172 if (m_bitmapDC == NULL) 00173 return; 00174 00175 ::SetMapMode(m_bitmapDC, MM_TEXT); 00176 00177 // transform bitmap to screen 00178 BmpToScreen(clientr); 00179 BOOL ret = ::StretchBlt(dc.m_hDC, 0, 0, m_bitmapOnScreen.Width(), m_bitmapOnScreen.Height(), m_bitmapDC, 00180 0, 0, m_bitmapSizeStored.Width(), m_bitmapSizeStored.Height(), SRCCOPY); 00181 if (!ret) 00182 return; 00183 00184 CBrush brush1; 00185 DWORD dw1 = GetSysColor(COLOR_WINDOWTEXT); 00186 BYTE r1 = GetRValue(dw1); 00187 BYTE g1 = GetGValue(dw1); 00188 BYTE b1 = GetBValue(dw1); 00189 brush1.CreateSolidBrush(RGB(r1, g1, b1)); 00190 if (!m_viewRectOnStored.IsRectEmpty() && m_viewRectOnScreen != m_bitmapOnScreen && 00191 !m_viewRectOnScreen.IsRectEmpty()) 00192 { 00193 if (!m_inMove) { 00194 CRect vRect(0, 0, 0, 0); 00195 ViewRectToScreen(vRect); 00196 m_viewRectOnScreen = vRect; 00197 dc.FrameRect(&m_viewRectOnScreen, &brush1); 00198 } else { 00199 dc.FrameRect(&m_viewRectInMove, &brush1); 00200 } 00201 } 00202 } 00203 00204 BOOL CPanningButton::OnEraseBkgnd(CDC* pDC) 00205 { 00206 return TRUE; 00207 } 00208 00209 void CPanningButton::OnMouseMove(UINT nFlags, CPoint point) 00210 { 00211 if (m_viewRectOnScreen.PtInRect(point) || m_inMove) 00212 SetCursor(m_sizeallh); 00213 else 00214 SetCursor(m_arrowh); 00215 00216 if (m_inMove) { 00217 // move panning frame only 00218 int dx = point.x - m_moveStartPoint.x; 00219 int dy = point.y - m_moveStartPoint.y; 00220 CRect trackRect = m_viewRectOnScreen; 00221 trackRect.OffsetRect(dx, dy); 00222 CRect shadow; 00223 shadow.IntersectRect(&trackRect, &m_bitmapOnScreen); 00224 if (shadow.Width() != trackRect.Width() && shadow.Height() != trackRect.Height()) 00225 return; 00226 if (m_viewRectInMove.IsRectEmpty()) 00227 InvalidateRect(&m_viewRectOnScreen, FALSE); 00228 else 00229 InvalidateRect(&m_viewRectInMove, FALSE); 00230 00231 if (shadow.Width() != trackRect.Width()) { 00232 if (trackRect.left < 0) 00233 trackRect.OffsetRect(-trackRect.left, 0); 00234 else 00235 trackRect.OffsetRect(m_bitmapOnScreen.right - trackRect.right, 0); 00236 } else if (shadow.Height() != trackRect.Height()) { 00237 if (trackRect.top < 0) 00238 trackRect.OffsetRect(0, -trackRect.top); 00239 else 00240 trackRect.OffsetRect(0, m_bitmapOnScreen.bottom - trackRect.bottom); 00241 } 00242 m_viewRectInMove = trackRect; 00243 00244 InvalidateRect(&m_viewRectInMove, FALSE); 00245 UpdateWindow(); 00246 } 00247 CWnd::OnMouseMove(nFlags, point); 00248 } 00249 00250 void CPanningButton::OnLButtonDown(UINT nFlags, CPoint point) 00251 { 00252 // TODO: Add your message handler code here and/or call default 00253 if (m_viewRectOnScreen.PtInRect(point)) { 00254 SetCursor(m_sizeallh); 00255 SetCapture(); 00256 m_inMove = true; 00257 m_moveStartPoint = point; 00258 m_moveStartRect = m_viewRectOnScreen; 00259 } else { 00260 SetCursor(m_arrowh); 00261 } 00262 CWnd::OnLButtonDown(nFlags, point); 00263 } 00264 00265 void CPanningButton::OnLButtonUp(UINT nFlags, CPoint point) 00266 { 00267 // TODO: Add your message handler code here and/or call default 00268 if (m_inMove) { 00269 ReleaseCapture(); 00270 m_inMove = false; 00271 // CWnd* mainw = AfxGetMainWnd(); 00272 if (m_owner) { // mainw) 00273 double dx = point.x - m_moveStartPoint.x; 00274 double dy = point.y - m_moveStartPoint.y; 00275 // dx, dy in pann win screen coordinates 00276 // calculate real screen coordinates 00277 dx /= m_storedToScreenRx; 00278 dy /= m_storedToScreenRy; 00279 dx /= m_oriToStoredRx; 00280 dy /= m_oriToStoredRy; 00281 ::PostMessage(m_owner, WM_PANN_SCROLL, (WPARAM)(int)dx, (LPARAM)(int)dy); 00282 Invalidate(); 00283 } 00284 m_viewRectInMove = CRect(0, 0, 0, 0); 00285 m_moveStartPoint = CPoint(0, 0); 00286 m_moveStartRect = CRect(0, 0, 0, 0); 00287 } 00288 00289 CWnd::OnLButtonUp(nFlags, point); 00290 }