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