ResizableGrip.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:8k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // ResizableGrip.cpp: implementation of the CResizableGrip class.
  2. //
  3. /////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright (C) 2000-2002 by Paolo Messina
  6. // (http://www.geocities.com/ppescher - ppescher@yahoo.com)
  7. //
  8. // The contents of this file are subject to the Artistic License (the "License").
  9. // You may not use this file except in compliance with the License. 
  10. // You may obtain a copy of the License at:
  11. // http://www.opensource.org/licenses/artistic-license.html
  12. //
  13. // If you find this code useful, credits would be nice!
  14. //
  15. /////////////////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. #include "ResizableGrip.h"
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[]=__FILE__;
  21. #define new DEBUG_NEW
  22. #endif
  23. //////////////////////////////////////////////////////////////////////
  24. // Construction/Destruction
  25. //////////////////////////////////////////////////////////////////////
  26. CResizableGrip::CResizableGrip()
  27. {
  28. m_nShowCount = 0;
  29. }
  30. CResizableGrip::~CResizableGrip()
  31. {
  32. }
  33. void CResizableGrip::UpdateSizeGrip()
  34. {
  35. ASSERT(::IsWindow(m_wndGrip.m_hWnd));
  36. // size-grip goes bottom right in the client area
  37. // (any right-to-left adjustment should go here)
  38. RECT rect;
  39. GetResizableWnd()->GetClientRect(&rect);
  40. rect.left = rect.right - m_wndGrip.m_size.cx;
  41. rect.top = rect.bottom - m_wndGrip.m_size.cy;
  42. // must stay below other children
  43. m_wndGrip.SetWindowPos(&CWnd::wndBottom, rect.left, rect.top, 0, 0,
  44. SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREPOSITION
  45. | (IsSizeGripVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  46. }
  47. // pbStatus points to a variable, maintained by the caller, that
  48. // holds its visibility status. Initialize the variable with 1
  49. // to allow to temporarily hide the grip, 0 to allow to
  50. // temporarily show the grip (with respect to the dwMask bit).
  51. // NB: visibility is effective only after an update
  52. void CResizableGrip::ShowSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
  53. {
  54. ASSERT(pStatus != NULL);
  55. if (!(*pStatus & dwMask))
  56. {
  57. m_nShowCount++;
  58. (*pStatus) |= dwMask;
  59. }
  60. }
  61. void CResizableGrip::HideSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
  62. {
  63. ASSERT(pStatus != NULL);
  64. if (*pStatus & dwMask)
  65. {
  66. m_nShowCount--;
  67. (*pStatus) &= ~dwMask;
  68. }
  69. }
  70. BOOL CResizableGrip::IsSizeGripVisible()
  71. {
  72. // NB: visibility is effective only after an update
  73. return (m_nShowCount > 0);
  74. }
  75. void CResizableGrip::SetSizeGripVisibility(BOOL bVisible)
  76. {
  77. if (bVisible)
  78. m_nShowCount = 1;
  79. else
  80. m_nShowCount = 0;
  81. }
  82. BOOL CResizableGrip::SetSizeGripBkMode(int nBkMode)
  83. {
  84. if (::IsWindow(m_wndGrip.m_hWnd))
  85. {
  86. if (nBkMode == OPAQUE)
  87. m_wndGrip.SetTransparency(FALSE);
  88. else if (nBkMode == TRANSPARENT)
  89. m_wndGrip.SetTransparency(TRUE);
  90. else
  91. return FALSE;
  92. return TRUE;
  93. }
  94. return FALSE;
  95. }
  96. void CResizableGrip::SetSizeGripShape(BOOL bTriangular)
  97. {
  98. m_wndGrip.SetTriangularShape(bTriangular);
  99. }
  100. BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible /*= TRUE*/,
  101. BOOL bTriangular /*= TRUE*/, BOOL bTransparent /*= FALSE*/)
  102. {
  103. // create grip
  104. CRect rect(0 , 0, m_wndGrip.m_size.cx, m_wndGrip.m_size.cy);
  105. BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS
  106. | SBS_SIZEGRIP, rect, GetResizableWnd(), 0);
  107. if (bRet)
  108. {
  109. // set options
  110. m_wndGrip.SetTriangularShape(bTriangular);
  111. m_wndGrip.SetTransparency(bTransparent);
  112. SetSizeGripVisibility(bVisible);
  113. // update position
  114. UpdateSizeGrip();
  115. }
  116. return bRet;
  117. }
  118. /////////////////////////////////////////////////////////////////////////////
  119. // CSizeGrip implementation
  120. BOOL CResizableGrip::CSizeGrip::IsRTL()
  121. {
  122. return GetExStyle() & 0x00400000L/*WS_EX_LAYOUTRTL*/;
  123. }
  124. BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT& cs) 
  125. {
  126. // set window size
  127. m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
  128. m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
  129. cs.cx = m_size.cx;
  130. cs.cy = m_size.cy;
  131. return CScrollBar::PreCreateWindow(cs);
  132. }
  133. LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message,
  134.   WPARAM wParam, LPARAM lParam)
  135. {
  136. switch (message)
  137. {
  138. case WM_GETDLGCODE:
  139. // fix to prevent the control to gain focus, using arrow keys
  140. // (standard grip returns DLGC_WANTARROWS, like any standard scrollbar)
  141. return DLGC_STATIC;
  142. case WM_NCHITTEST:
  143. // choose proper cursor shape
  144. if (IsRTL())
  145. return HTBOTTOMLEFT;
  146. else
  147. return HTBOTTOMRIGHT;
  148. break;
  149. case WM_SETTINGCHANGE:
  150. {
  151. // update grip's size
  152. CSize sizeOld = m_size;
  153. m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
  154. m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
  155. // resize transparency bitmaps
  156. if (m_bTransparent)
  157. {
  158. CClientDC dc(this);
  159. // destroy bitmaps
  160. m_bmGrip.DeleteObject();
  161. m_bmMask.DeleteObject();
  162. // re-create bitmaps
  163. m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
  164. m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
  165. }
  166. // re-calc shape
  167. if (m_bTriangular)
  168. SetTriangularShape(m_bTriangular);
  169. // reposition the grip
  170. CRect rect;
  171. GetWindowRect(rect);
  172. rect.InflateRect(m_size.cx - sizeOld.cx, m_size.cy - sizeOld.cy, 0, 0);
  173. ::MapWindowPoints(NULL, GetParent()->GetSafeHwnd(), (LPPOINT)&rect, 2);
  174. MoveWindow(rect, TRUE);
  175. }
  176. break;
  177. case WM_DESTROY:
  178. // perform clean up
  179. if (m_bTransparent)
  180. SetTransparency(FALSE);
  181. break;
  182. case WM_PAINT:
  183. if (m_bTransparent)
  184. {
  185. CPaintDC dc(this);
  186. // select bitmaps
  187. CBitmap *pOldGrip, *pOldMask;
  188. pOldGrip = m_dcGrip.SelectObject(&m_bmGrip);
  189. pOldMask = m_dcMask.SelectObject(&m_bmMask);
  190. // obtain original grip bitmap, make the mask and prepare masked bitmap
  191. CScrollBar::WindowProc(WM_PAINT, (WPARAM)m_dcGrip.GetSafeHdc(), lParam);
  192. m_dcGrip.SetBkColor(m_dcGrip.GetPixel(0, 0));
  193. m_dcMask.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCCOPY);
  194. m_dcGrip.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, 0x00220326);
  195. // draw transparently
  196. dc.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, SRCAND);
  197. dc.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCPAINT);
  198. // unselect bitmaps
  199. m_dcGrip.SelectObject(pOldGrip);
  200. m_dcMask.SelectObject(pOldMask);
  201. return 0;
  202. }
  203. break;
  204. }
  205. return CScrollBar::WindowProc(message, wParam, lParam);
  206. }
  207. void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate)
  208. {
  209. // creates or deletes DCs and Bitmaps used for
  210. // implementing a transparent size grip
  211. if (bActivate && !m_bTransparent)
  212. {
  213. m_bTransparent = TRUE;
  214. CClientDC dc(this);
  215. // create memory DCs and bitmaps
  216. m_dcGrip.CreateCompatibleDC(&dc);
  217. m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
  218. m_dcMask.CreateCompatibleDC(&dc);
  219. m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
  220. }
  221. else if (!bActivate && m_bTransparent)
  222. {
  223. m_bTransparent = FALSE;
  224. // destroy memory DCs and bitmaps
  225. m_dcGrip.DeleteDC();
  226. m_bmGrip.DeleteObject();
  227. m_dcMask.DeleteDC();
  228. m_bmMask.DeleteObject();
  229. }
  230. }
  231. void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable)
  232. {
  233. m_bTriangular = bEnable;
  234. if (bEnable)
  235. {
  236. // set a triangular window region
  237. CRect rect;
  238. GetWindowRect(rect);
  239. rect.OffsetRect(-rect.TopLeft());
  240. POINT arrPoints[] =
  241. {
  242. { rect.left, rect.bottom },
  243. { rect.right, rect.bottom },
  244. { rect.right, rect.top }
  245. };
  246. CRgn rgnGrip;
  247. rgnGrip.CreatePolygonRgn(arrPoints, 3, WINDING);
  248. SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible());
  249. }
  250. else
  251. {
  252. SetWindowRgn((HRGN)NULL, IsWindowVisible());
  253. }
  254. }