OSDN Git Service

merge original branch.
[tortoisegit/TortoiseGitJp.git] / ext / ResizableLib / ResizableGrip.cpp
1 /////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 // This file is part of ResizableLib\r
4 // http://sourceforge.net/projects/resizablelib\r
5 //\r
6 // Copyright (C) 2000-2004 by Paolo Messina\r
7 // http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com\r
8 //\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
13 //\r
14 // If you find this code useful, credits would be nice!\r
15 //\r
16 /////////////////////////////////////////////////////////////////////////////\r
17 \r
18 /*!\r
19  *  @file\r
20  *  @brief Implementation of the CResizableGrip class.\r
21  */\r
22 \r
23 #include "stdafx.h"\r
24 #include "ResizableGrip.h"\r
25 \r
26 #ifdef _DEBUG\r
27 #undef THIS_FILE\r
28 static char THIS_FILE[]=__FILE__;\r
29 #define new DEBUG_NEW\r
30 #endif\r
31 \r
32 //////////////////////////////////////////////////////////////////////\r
33 // Construction/Destruction\r
34 //////////////////////////////////////////////////////////////////////\r
35 \r
36 CResizableGrip::CResizableGrip()\r
37 {\r
38         m_nShowCount = 0;\r
39 }\r
40 \r
41 CResizableGrip::~CResizableGrip()\r
42 {\r
43 \r
44 }\r
45 \r
46 void CResizableGrip::UpdateSizeGrip()\r
47 {\r
48         if (!::IsWindow(m_wndGrip.m_hWnd))\r
49                 return;\r
50 \r
51         // size-grip goes bottom right in the client area\r
52         // (any right-to-left adjustment should go here)\r
53 \r
54         RECT rect;\r
55         GetResizableWnd()->GetClientRect(&rect);\r
56 \r
57         rect.left = rect.right - m_wndGrip.m_size.cx;\r
58         rect.top = rect.bottom - m_wndGrip.m_size.cy;\r
59 \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
64 }\r
65 \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
70 \r
71 // NB: visibility is effective only after an update\r
72 \r
73 void CResizableGrip::ShowSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)\r
74 {\r
75         ASSERT(pStatus != NULL);\r
76 \r
77         if (!(*pStatus & dwMask))\r
78         {\r
79                 m_nShowCount++;\r
80                 (*pStatus) |= dwMask;\r
81         }\r
82 }\r
83 \r
84 void CResizableGrip::HideSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)\r
85 {\r
86         ASSERT(pStatus != NULL);\r
87 \r
88         if (*pStatus & dwMask)\r
89         {\r
90                 m_nShowCount--;\r
91                 (*pStatus) &= ~dwMask;\r
92         }\r
93 }\r
94 \r
95 BOOL CResizableGrip::IsSizeGripVisible()\r
96 {\r
97         // NB: visibility is effective only after an update\r
98         return (m_nShowCount > 0);\r
99 }\r
100 \r
101 void CResizableGrip::SetSizeGripVisibility(BOOL bVisible)\r
102 {\r
103         if (bVisible)\r
104                 m_nShowCount = 1;\r
105         else\r
106                 m_nShowCount = 0;\r
107 }\r
108 \r
109 BOOL CResizableGrip::SetSizeGripBkMode(int nBkMode)\r
110 {\r
111         if (::IsWindow(m_wndGrip.m_hWnd))\r
112         {\r
113                 if (nBkMode == OPAQUE)\r
114                         m_wndGrip.SetTransparency(FALSE);\r
115                 else if (nBkMode == TRANSPARENT)\r
116                         m_wndGrip.SetTransparency(TRUE);\r
117                 else\r
118                         return FALSE;\r
119                 return TRUE;\r
120         }\r
121         return FALSE;\r
122 }\r
123 \r
124 void CResizableGrip::SetSizeGripShape(BOOL bTriangular)\r
125 {\r
126         if (::IsWindow(m_wndGrip.m_hWnd))\r
127                 m_wndGrip.SetTriangularShape(bTriangular);\r
128 }\r
129 \r
130 BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible /*= TRUE*/,\r
131                 BOOL bTriangular /*= TRUE*/, BOOL bTransparent /*= FALSE*/)\r
132 {\r
133         // create grip\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
137 \r
138         if (bRet)\r
139         {\r
140                 // set options\r
141                 m_wndGrip.SetTriangularShape(bTriangular);\r
142                 m_wndGrip.SetTransparency(bTransparent);\r
143                 SetSizeGripVisibility(bVisible);\r
144         \r
145                 // update position\r
146                 UpdateSizeGrip();\r
147         }\r
148 \r
149         return bRet;\r
150 }\r
151 \r
152 /////////////////////////////////////////////////////////////////////////////\r
153 // CSizeGrip implementation\r
154 \r
155 BOOL CResizableGrip::CSizeGrip::IsRTL()\r
156 {\r
157         return GetExStyle() & WS_EX_LAYOUTRTL;\r
158 }\r
159 \r
160 BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT& cs) \r
161 {\r
162         // set window size\r
163         m_size.cx = GetSystemMetrics(SM_CXVSCROLL);\r
164         m_size.cy = GetSystemMetrics(SM_CYHSCROLL);\r
165 \r
166         cs.cx = m_size.cx;\r
167         cs.cy = m_size.cy;\r
168         \r
169         return CScrollBar::PreCreateWindow(cs);\r
170 }\r
171 \r
172 LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message,\r
173                                                                                           WPARAM wParam, LPARAM lParam)\r
174 {\r
175         switch (message)\r
176         {\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
181 \r
182         case WM_SETFOCUS:\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
185                 return 0;\r
186 \r
187         case WM_NCHITTEST:\r
188                 // choose proper cursor shape\r
189                 if (IsRTL())\r
190                         return HTBOTTOMLEFT;\r
191                 else\r
192                         return HTBOTTOMRIGHT;\r
193                 break;\r
194 \r
195         case WM_SETTINGCHANGE:\r
196                 {\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
201 \r
202                         // resize transparency bitmaps\r
203                         if (m_bTransparent)\r
204                         {\r
205                                 CClientDC dc(this);\r
206 \r
207                                 // destroy bitmaps\r
208                                 m_bmGrip.DeleteObject();\r
209                                 m_bmMask.DeleteObject();\r
210 \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
214                         }\r
215 \r
216                         // re-calc shape\r
217                         if (m_bTriangular)\r
218                                 SetTriangularShape(m_bTriangular);\r
219 \r
220                         // reposition the grip\r
221                         CRect rect;\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
226                 }\r
227                 break;\r
228 \r
229         case WM_DESTROY:\r
230                 // perform clean up\r
231                 if (m_bTransparent)\r
232                         SetTransparency(FALSE);\r
233                 break;\r
234 \r
235         case WM_PAINT:\r
236         case WM_PRINTCLIENT:\r
237                 if (m_bTransparent)\r
238                 {\r
239                         PAINTSTRUCT ps;\r
240                         CDC* pDC = (message == WM_PAINT && wParam == 0) ?\r
241                                 BeginPaint(&ps) : CDC::FromHandle((HDC)wParam);\r
242 \r
243                         // select bitmaps\r
244                         CBitmap *pOldGrip, *pOldMask;\r
245 \r
246                         pOldGrip = m_dcGrip.SelectObject(&m_bmGrip);\r
247                         pOldMask = m_dcMask.SelectObject(&m_bmMask);\r
248 \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
254                         \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
258 \r
259                         // unselect bitmaps\r
260                         m_dcGrip.SelectObject(pOldGrip);\r
261                         m_dcMask.SelectObject(pOldMask);\r
262 \r
263                         if (message == WM_PAINT && wParam == 0)\r
264                                 EndPaint(&ps);\r
265                         return 0;\r
266                 }\r
267                 break;\r
268         }\r
269 \r
270         return CScrollBar::WindowProc(message, wParam, lParam);\r
271 }\r
272 \r
273 void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate)\r
274 {\r
275         // creates or deletes DCs and Bitmaps used for\r
276         // implementing a transparent size grip\r
277 \r
278         if (bActivate && !m_bTransparent)\r
279         {\r
280                 m_bTransparent = TRUE;\r
281 \r
282                 CClientDC dc(this);\r
283 \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
287 \r
288                 m_dcMask.CreateCompatibleDC(&dc);\r
289                 m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);\r
290         }\r
291         else if (!bActivate && m_bTransparent)\r
292         {\r
293                 m_bTransparent = FALSE;\r
294 \r
295                 // destroy memory DCs and bitmaps\r
296                 m_dcGrip.DeleteDC();\r
297                 m_bmGrip.DeleteObject();\r
298 \r
299                 m_dcMask.DeleteDC();\r
300                 m_bmMask.DeleteObject();\r
301         }\r
302 }\r
303 \r
304 void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable)\r
305 {\r
306         m_bTriangular = bEnable;\r
307 \r
308         if (bEnable)\r
309         {\r
310                 // set a triangular window region\r
311                 CRect rect;\r
312                 GetWindowRect(rect);\r
313                 rect.OffsetRect(-rect.TopLeft());\r
314                 POINT arrPoints[] =\r
315                 {\r
316                         { rect.left, rect.bottom },\r
317                         { rect.right, rect.bottom },\r
318                         { rect.right, rect.top }\r
319                 };\r
320                 CRgn rgnGrip;\r
321                 rgnGrip.CreatePolygonRgn(arrPoints, 3, WINDING);\r
322                 SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible());\r
323         }\r
324         else\r
325         {\r
326                 SetWindowRgn((HRGN)NULL, IsWindowVisible());\r
327         }\r
328 }\r