1 // ResizableGrip.cpp: implementation of the CResizableGrip class.
3 /////////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2000-2002 by Paolo Messina
6 // (http://www.geocities.com/ppescher - ppescher@yahoo.com)
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
13 // If you find this code useful, credits would be nice!
15 /////////////////////////////////////////////////////////////////////////////
18 #include "ResizableGrip.h"
22 static char THIS_FILE
[]=__FILE__
;
26 //////////////////////////////////////////////////////////////////////
27 // Construction/Destruction
28 //////////////////////////////////////////////////////////////////////
30 CResizableGrip::CResizableGrip()
35 CResizableGrip::~CResizableGrip()
40 void CResizableGrip::UpdateSizeGrip()
42 ASSERT(::IsWindow(m_wndGrip
.m_hWnd
));
44 // size-grip goes bottom right in the client area
45 // (any right-to-left adjustment should go here)
48 GetResizableWnd()->GetClientRect(&rect
);
50 rect
.left
= rect
.right
- m_wndGrip
.m_size
.cx
;
51 rect
.top
= rect
.bottom
- m_wndGrip
.m_size
.cy
;
53 // must stay below other children
54 m_wndGrip
.SetWindowPos(&CWnd::wndBottom
, rect
.left
, rect
.top
, 0, 0,
55 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREPOSITION
56 | (IsSizeGripVisible() ? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
59 // pbStatus points to a variable, maintained by the caller, that
60 // holds its visibility status. Initialize the variable with 1
61 // to allow to temporarily hide the grip, 0 to allow to
62 // temporarily show the grip (with respect to the dwMask bit).
64 // NB: visibility is effective only after an update
66 void CResizableGrip::ShowSizeGrip(DWORD
* pStatus
, DWORD dwMask
/*= 1*/)
68 ASSERT(pStatus
!= NULL
);
70 if (!(*pStatus
& dwMask
))
77 void CResizableGrip::HideSizeGrip(DWORD
* pStatus
, DWORD dwMask
/*= 1*/)
79 ASSERT(pStatus
!= NULL
);
81 if (*pStatus
& dwMask
)
84 (*pStatus
) &= ~dwMask
;
88 BOOL
CResizableGrip::IsSizeGripVisible()
90 // NB: visibility is effective only after an update
91 return (m_nShowCount
> 0);
94 void CResizableGrip::SetSizeGripVisibility(BOOL bVisible
)
102 BOOL
CResizableGrip::SetSizeGripBkMode(int nBkMode
)
104 if (::IsWindow(m_wndGrip
.m_hWnd
))
106 if (nBkMode
== OPAQUE
)
107 m_wndGrip
.SetTransparency(FALSE
);
108 else if (nBkMode
== TRANSPARENT
)
109 m_wndGrip
.SetTransparency(TRUE
);
117 void CResizableGrip::SetSizeGripShape(BOOL bTriangular
)
119 m_wndGrip
.SetTriangularShape(bTriangular
);
122 BOOL
CResizableGrip::CreateSizeGrip(BOOL bVisible
/*= TRUE*/,
123 BOOL bTriangular
/*= TRUE*/, BOOL bTransparent
/*= FALSE*/)
126 CRect
rect(0 , 0, m_wndGrip
.m_size
.cx
, m_wndGrip
.m_size
.cy
);
127 BOOL bRet
= m_wndGrip
.Create(WS_CHILD
| WS_CLIPSIBLINGS
128 | SBS_SIZEGRIP
, rect
, GetResizableWnd(), 0);
133 m_wndGrip
.SetTriangularShape(bTriangular
);
134 m_wndGrip
.SetTransparency(bTransparent
);
135 SetSizeGripVisibility(bVisible
);
144 /////////////////////////////////////////////////////////////////////////////
145 // CSizeGrip implementation
147 BOOL
CResizableGrip::CSizeGrip::IsRTL()
149 return GetExStyle() & 0x00400000L
/*WS_EX_LAYOUTRTL*/;
152 BOOL
CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT
& cs
)
155 m_size
.cx
= GetSystemMetrics(SM_CXVSCROLL
);
156 m_size
.cy
= GetSystemMetrics(SM_CYHSCROLL
);
161 return CScrollBar::PreCreateWindow(cs
);
164 LRESULT
CResizableGrip::CSizeGrip::WindowProc(UINT message
,
165 WPARAM wParam
, LPARAM lParam
)
170 // fix to prevent the control to gain focus, using arrow keys
171 // (standard grip returns DLGC_WANTARROWS, like any standard scrollbar)
175 // choose proper cursor shape
179 return HTBOTTOMRIGHT
;
182 case WM_SETTINGCHANGE
:
184 // update grip's size
185 CSize sizeOld
= m_size
;
186 m_size
.cx
= GetSystemMetrics(SM_CXVSCROLL
);
187 m_size
.cy
= GetSystemMetrics(SM_CYHSCROLL
);
189 // resize transparency bitmaps
195 m_bmGrip
.DeleteObject();
196 m_bmMask
.DeleteObject();
199 m_bmGrip
.CreateCompatibleBitmap(&dc
, m_size
.cx
, m_size
.cy
);
200 m_bmMask
.CreateBitmap(m_size
.cx
, m_size
.cy
, 1, 1, NULL
);
205 SetTriangularShape(m_bTriangular
);
207 // reposition the grip
210 rect
.InflateRect(m_size
.cx
- sizeOld
.cx
, m_size
.cy
- sizeOld
.cy
, 0, 0);
211 ::MapWindowPoints(NULL
, GetParent()->GetSafeHwnd(), (LPPOINT
)&rect
, 2);
212 MoveWindow(rect
, TRUE
);
219 SetTransparency(FALSE
);
228 CBitmap
*pOldGrip
, *pOldMask
;
230 pOldGrip
= m_dcGrip
.SelectObject(&m_bmGrip
);
231 pOldMask
= m_dcMask
.SelectObject(&m_bmMask
);
233 // obtain original grip bitmap, make the mask and prepare masked bitmap
234 CScrollBar::WindowProc(WM_PAINT
, (WPARAM
)m_dcGrip
.GetSafeHdc(), lParam
);
235 m_dcGrip
.SetBkColor(m_dcGrip
.GetPixel(0, 0));
236 m_dcMask
.BitBlt(0, 0, m_size
.cx
, m_size
.cy
, &m_dcGrip
, 0, 0, SRCCOPY
);
237 m_dcGrip
.BitBlt(0, 0, m_size
.cx
, m_size
.cy
, &m_dcMask
, 0, 0, 0x00220326);
239 // draw transparently
240 dc
.BitBlt(0, 0, m_size
.cx
, m_size
.cy
, &m_dcMask
, 0, 0, SRCAND
);
241 dc
.BitBlt(0, 0, m_size
.cx
, m_size
.cy
, &m_dcGrip
, 0, 0, SRCPAINT
);
244 m_dcGrip
.SelectObject(pOldGrip
);
245 m_dcMask
.SelectObject(pOldMask
);
252 return CScrollBar::WindowProc(message
, wParam
, lParam
);
255 void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate
)
257 // creates or deletes DCs and Bitmaps used for
258 // implementing a transparent size grip
260 if (bActivate
&& !m_bTransparent
)
262 m_bTransparent
= TRUE
;
266 // create memory DCs and bitmaps
267 m_dcGrip
.CreateCompatibleDC(&dc
);
268 m_bmGrip
.CreateCompatibleBitmap(&dc
, m_size
.cx
, m_size
.cy
);
270 m_dcMask
.CreateCompatibleDC(&dc
);
271 m_bmMask
.CreateBitmap(m_size
.cx
, m_size
.cy
, 1, 1, NULL
);
273 else if (!bActivate
&& m_bTransparent
)
275 m_bTransparent
= FALSE
;
277 // destroy memory DCs and bitmaps
279 m_bmGrip
.DeleteObject();
282 m_bmMask
.DeleteObject();
286 void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable
)
288 m_bTriangular
= bEnable
;
292 // set a triangular window region
295 rect
.OffsetRect(-rect
.TopLeft());
298 { rect
.left
, rect
.bottom
},
299 { rect
.right
, rect
.bottom
},
300 { rect
.right
, rect
.top
}
303 rgnGrip
.CreatePolygonRgn(arrPoints
, 3, WINDING
);
304 SetWindowRgn((HRGN
)rgnGrip
.Detach(), IsWindowVisible());
308 SetWindowRgn((HRGN
)NULL
, IsWindowVisible());