1 /////////////////////////////////////////////////////////////////////////////
\r
3 // This file is part of ResizableLib
\r
4 // http://sourceforge.net/projects/resizablelib
\r
6 // Copyright (C) 2000-2004 by Paolo Messina
\r
7 // http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com
\r
9 // The contents of this file are subject to the Artistic License (the "License").
\r
10 // You may not use this file except in compliance with the License.
\r
11 // You may obtain a copy of the License at:
\r
12 // http://www.opensource.org/licenses/artistic-license.html
\r
14 // If you find this code useful, credits would be nice!
\r
16 /////////////////////////////////////////////////////////////////////////////
\r
20 * @brief Implementation of the CResizableGrip class.
\r
24 #include "ResizableGrip.h"
\r
28 static char THIS_FILE[]=__FILE__;
\r
29 #define new DEBUG_NEW
\r
32 //////////////////////////////////////////////////////////////////////
\r
33 // Construction/Destruction
\r
34 //////////////////////////////////////////////////////////////////////
\r
36 CResizableGrip::CResizableGrip()
\r
41 CResizableGrip::~CResizableGrip()
\r
46 void CResizableGrip::UpdateSizeGrip()
\r
48 if (!::IsWindow(m_wndGrip.m_hWnd))
\r
51 // size-grip goes bottom right in the client area
\r
52 // (any right-to-left adjustment should go here)
\r
55 GetResizableWnd()->GetClientRect(&rect);
\r
57 rect.left = rect.right - m_wndGrip.m_size.cx;
\r
58 rect.top = rect.bottom - m_wndGrip.m_size.cy;
\r
60 // must stay below other children
\r
61 m_wndGrip.SetWindowPos(&CWnd::wndBottom, rect.left, rect.top, 0, 0,
\r
62 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREPOSITION
\r
63 | (IsSizeGripVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
\r
66 // pbStatus points to a variable, maintained by the caller, that
\r
67 // holds its visibility status. Initialize the variable with 1
\r
68 // to allow to temporarily hide the grip, 0 to allow to
\r
69 // temporarily show the grip (with respect to the dwMask bit).
\r
71 // NB: visibility is effective only after an update
\r
73 void CResizableGrip::ShowSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
\r
75 ASSERT(pStatus != NULL);
\r
77 if (!(*pStatus & dwMask))
\r
80 (*pStatus) |= dwMask;
\r
84 void CResizableGrip::HideSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
\r
86 ASSERT(pStatus != NULL);
\r
88 if (*pStatus & dwMask)
\r
91 (*pStatus) &= ~dwMask;
\r
95 BOOL CResizableGrip::IsSizeGripVisible()
\r
97 // NB: visibility is effective only after an update
\r
98 return (m_nShowCount > 0);
\r
101 void CResizableGrip::SetSizeGripVisibility(BOOL bVisible)
\r
109 BOOL CResizableGrip::SetSizeGripBkMode(int nBkMode)
\r
111 if (::IsWindow(m_wndGrip.m_hWnd))
\r
113 if (nBkMode == OPAQUE)
\r
114 m_wndGrip.SetTransparency(FALSE);
\r
115 else if (nBkMode == TRANSPARENT)
\r
116 m_wndGrip.SetTransparency(TRUE);
\r
124 void CResizableGrip::SetSizeGripShape(BOOL bTriangular)
\r
126 if (::IsWindow(m_wndGrip.m_hWnd))
\r
127 m_wndGrip.SetTriangularShape(bTriangular);
\r
130 BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible /*= TRUE*/,
\r
131 BOOL bTriangular /*= TRUE*/, BOOL bTransparent /*= FALSE*/)
\r
134 CRect rect(0 , 0, m_wndGrip.m_size.cx, m_wndGrip.m_size.cy);
\r
135 BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS
\r
136 | SBS_SIZEGRIP, rect, GetResizableWnd(), 0);
\r
141 m_wndGrip.SetTriangularShape(bTriangular);
\r
142 m_wndGrip.SetTransparency(bTransparent);
\r
143 SetSizeGripVisibility(bVisible);
\r
152 /////////////////////////////////////////////////////////////////////////////
\r
153 // CSizeGrip implementation
\r
155 BOOL CResizableGrip::CSizeGrip::IsRTL()
\r
157 return GetExStyle() & WS_EX_LAYOUTRTL;
\r
160 BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT& cs)
\r
163 m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
\r
164 m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
\r
169 return CScrollBar::PreCreateWindow(cs);
\r
172 LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message,
\r
173 WPARAM wParam, LPARAM lParam)
\r
177 case WM_GETDLGCODE:
\r
178 // fix to prevent the control to gain focus, using arrow keys
\r
179 // (standard grip returns DLGC_WANTARROWS, like any standard scrollbar)
\r
180 return DLGC_STATIC;
\r
183 // fix to prevent the control to gain focus, if set directly
\r
184 // (for example when it's the only one control in a dialog)
\r
188 // choose proper cursor shape
\r
190 return HTBOTTOMLEFT;
\r
192 return HTBOTTOMRIGHT;
\r
195 case WM_SETTINGCHANGE:
\r
197 // update grip's size
\r
198 CSize sizeOld = m_size;
\r
199 m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
\r
200 m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
\r
202 // resize transparency bitmaps
\r
203 if (m_bTransparent)
\r
205 CClientDC dc(this);
\r
208 m_bmGrip.DeleteObject();
\r
209 m_bmMask.DeleteObject();
\r
211 // re-create bitmaps
\r
212 m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
\r
213 m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
\r
218 SetTriangularShape(m_bTriangular);
\r
220 // reposition the grip
\r
222 GetWindowRect(rect);
\r
223 rect.InflateRect(m_size.cx - sizeOld.cx, m_size.cy - sizeOld.cy, 0, 0);
\r
224 ::MapWindowPoints(NULL, GetParent()->GetSafeHwnd(), (LPPOINT)&rect, 2);
\r
225 MoveWindow(rect, TRUE);
\r
230 // perform clean up
\r
231 if (m_bTransparent)
\r
232 SetTransparency(FALSE);
\r
236 case WM_PRINTCLIENT:
\r
237 if (m_bTransparent)
\r
240 CDC* pDC = (message == WM_PAINT && wParam == 0) ?
\r
241 BeginPaint(&ps) : CDC::FromHandle((HDC)wParam);
\r
244 CBitmap *pOldGrip, *pOldMask;
\r
246 pOldGrip = m_dcGrip.SelectObject(&m_bmGrip);
\r
247 pOldMask = m_dcMask.SelectObject(&m_bmMask);
\r
249 // obtain original grip bitmap, make the mask and prepare masked bitmap
\r
250 CScrollBar::WindowProc(message, (WPARAM)m_dcGrip.GetSafeHdc(), lParam);
\r
251 m_dcGrip.SetBkColor(m_dcGrip.GetPixel(0, 0));
\r
252 m_dcMask.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCCOPY);
\r
253 m_dcGrip.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, 0x00220326);
\r
255 // draw transparently
\r
256 pDC->BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, SRCAND);
\r
257 pDC->BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCPAINT);
\r
259 // unselect bitmaps
\r
260 m_dcGrip.SelectObject(pOldGrip);
\r
261 m_dcMask.SelectObject(pOldMask);
\r
263 if (message == WM_PAINT && wParam == 0)
\r
270 return CScrollBar::WindowProc(message, wParam, lParam);
\r
273 void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate)
\r
275 // creates or deletes DCs and Bitmaps used for
\r
276 // implementing a transparent size grip
\r
278 if (bActivate && !m_bTransparent)
\r
280 m_bTransparent = TRUE;
\r
282 CClientDC dc(this);
\r
284 // create memory DCs and bitmaps
\r
285 m_dcGrip.CreateCompatibleDC(&dc);
\r
286 m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
\r
288 m_dcMask.CreateCompatibleDC(&dc);
\r
289 m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
\r
291 else if (!bActivate && m_bTransparent)
\r
293 m_bTransparent = FALSE;
\r
295 // destroy memory DCs and bitmaps
\r
296 m_dcGrip.DeleteDC();
\r
297 m_bmGrip.DeleteObject();
\r
299 m_dcMask.DeleteDC();
\r
300 m_bmMask.DeleteObject();
\r
304 void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable)
\r
306 m_bTriangular = bEnable;
\r
310 // set a triangular window region
\r
312 GetWindowRect(rect);
\r
313 rect.OffsetRect(-rect.TopLeft());
\r
314 POINT arrPoints[] =
\r
316 { rect.left, rect.bottom },
\r
317 { rect.right, rect.bottom },
\r
318 { rect.right, rect.top }
\r
321 rgnGrip.CreatePolygonRgn(arrPoints, 3, WINDING);
\r
322 SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible());
\r
326 SetWindowRgn((HRGN)NULL, IsWindowVisible());
\r