ResizableGrip.cpp

00001 // ResizableGrip.cpp: implementation of the CResizableGrip class.
00002 //
00004 //
00005 // Copyright (C) 2000-2002 by Paolo Messina
00006 // (http://www.geocities.com/ppescher - [email protected])
00007 //
00008 // The contents of this file are subject to the Artistic License (the "License").
00009 // You may not use this file except in compliance with the License. 
00010 // You may obtain a copy of the License at:
00011 // http://www.opensource.org/licenses/artistic-license.html
00012 //
00013 // If you find this code useful, credits would be nice!
00014 //
00016 
00017 #include "stdafx.h"
00018 #include "ResizableGrip.h"
00019 
00020 #ifdef _DEBUG
00021 #undef THIS_FILE
00022 static char THIS_FILE[]=__FILE__;
00023 #define new DEBUG_NEW
00024 #endif
00025 
00027 // Construction/Destruction
00029 
00030 CResizableGrip::CResizableGrip()
00031 {
00032         m_nShowCount = 0;
00033 }
00034 
00035 CResizableGrip::~CResizableGrip()
00036 {
00037 
00038 }
00039 
00040 void CResizableGrip::UpdateSizeGrip()
00041 {
00042         ASSERT(::IsWindow(m_wndGrip.m_hWnd));
00043 
00044         // size-grip goes bottom right in the client area
00045         // (any right-to-left adjustment should go here)
00046 
00047         RECT rect;
00048         GetResizableWnd()->GetClientRect(&rect);
00049 
00050         rect.left = rect.right - m_wndGrip.m_size.cx;
00051         rect.top = rect.bottom - m_wndGrip.m_size.cy;
00052 
00053         // must stay below other children
00054         m_wndGrip.SetWindowPos(&CWnd::wndBottom, rect.left, rect.top, 0, 0,
00055                 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREPOSITION
00056                 | (IsSizeGripVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
00057 }
00058 
00059 // pbStatus points to a variable, maintained by the caller, that
00060 // holds its visibility status. Initialize the variable with 1
00061 // to allow to temporarily hide the grip, 0 to allow to
00062 // temporarily show the grip (with respect to the dwMask bit).
00063 
00064 // NB: visibility is effective only after an update
00065 
00066 void CResizableGrip::ShowSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
00067 {
00068         ASSERT(pStatus != NULL);
00069 
00070         if (!(*pStatus & dwMask))
00071         {
00072                 m_nShowCount++;
00073                 (*pStatus) |= dwMask;
00074         }
00075 }
00076 
00077 void CResizableGrip::HideSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/)
00078 {
00079         ASSERT(pStatus != NULL);
00080 
00081         if (*pStatus & dwMask)
00082         {
00083                 m_nShowCount--;
00084                 (*pStatus) &= ~dwMask;
00085         }
00086 }
00087 
00088 BOOL CResizableGrip::IsSizeGripVisible()
00089 {
00090         // NB: visibility is effective only after an update
00091         return (m_nShowCount > 0);
00092 }
00093 
00094 void CResizableGrip::SetSizeGripVisibility(BOOL bVisible)
00095 {
00096         if (bVisible)
00097                 m_nShowCount = 1;
00098         else
00099                 m_nShowCount = 0;
00100 }
00101 
00102 BOOL CResizableGrip::SetSizeGripBkMode(int nBkMode)
00103 {
00104         if (::IsWindow(m_wndGrip.m_hWnd))
00105         {
00106                 if (nBkMode == OPAQUE)
00107                         m_wndGrip.SetTransparency(FALSE);
00108                 else if (nBkMode == TRANSPARENT)
00109                         m_wndGrip.SetTransparency(TRUE);
00110                 else
00111                         return FALSE;
00112                 return TRUE;
00113         }
00114         return FALSE;
00115 }
00116 
00117 void CResizableGrip::SetSizeGripShape(BOOL bTriangular)
00118 {
00119         m_wndGrip.SetTriangularShape(bTriangular);
00120 }
00121 
00122 BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible /*= TRUE*/,
00123                 BOOL bTriangular /*= TRUE*/, BOOL bTransparent /*= FALSE*/)
00124 {
00125         // create grip
00126         CRect rect(0 , 0, m_wndGrip.m_size.cx, m_wndGrip.m_size.cy);
00127         BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS
00128                 | SBS_SIZEGRIP, rect, GetResizableWnd(), 0);
00129 
00130         if (bRet)
00131         {
00132                 // set options
00133                 m_wndGrip.SetTriangularShape(bTriangular);
00134                 m_wndGrip.SetTransparency(bTransparent);
00135                 SetSizeGripVisibility(bVisible);
00136         
00137                 // update position
00138                 UpdateSizeGrip();
00139         }
00140 
00141         return bRet;
00142 }
00143 
00145 // CSizeGrip implementation
00146 
00147 BOOL CResizableGrip::CSizeGrip::IsRTL()
00148 {
00149         return GetExStyle() & 0x00400000L/*WS_EX_LAYOUTRTL*/;
00150 }
00151 
00152 BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT& cs) 
00153 {
00154         // set window size
00155         m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
00156         m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
00157 
00158         cs.cx = m_size.cx;
00159         cs.cy = m_size.cy;
00160         
00161         return CScrollBar::PreCreateWindow(cs);
00162 }
00163 
00164 LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message,
00165                                                                                           WPARAM wParam, LPARAM lParam)
00166 {
00167         switch (message)
00168         {
00169         case WM_GETDLGCODE:
00170                 // fix to prevent the control to gain focus, using arrow keys
00171                 // (standard grip returns DLGC_WANTARROWS, like any standard scrollbar)
00172                 return DLGC_STATIC;
00173 
00174         case WM_NCHITTEST:
00175                 // choose proper cursor shape
00176                 if (IsRTL())
00177                         return HTBOTTOMLEFT;
00178                 else
00179                         return HTBOTTOMRIGHT;
00180                 break;
00181 
00182         case WM_SETTINGCHANGE:
00183                 {
00184                         // update grip's size
00185                         CSize sizeOld = m_size;
00186                         m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
00187                         m_size.cy = GetSystemMetrics(SM_CYHSCROLL);
00188 
00189                         // resize transparency bitmaps
00190                         if (m_bTransparent)
00191                         {
00192                                 CClientDC dc(this);
00193 
00194                                 // destroy bitmaps
00195                                 m_bmGrip.DeleteObject();
00196                                 m_bmMask.DeleteObject();
00197 
00198                                 // re-create bitmaps
00199                                 m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
00200                                 m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
00201                         }
00202 
00203                         // re-calc shape
00204                         if (m_bTriangular)
00205                                 SetTriangularShape(m_bTriangular);
00206 
00207                         // reposition the grip
00208                         CRect rect;
00209                         GetWindowRect(rect);
00210                         rect.InflateRect(m_size.cx - sizeOld.cx, m_size.cy - sizeOld.cy, 0, 0);
00211                         ::MapWindowPoints(NULL, GetParent()->GetSafeHwnd(), (LPPOINT)&rect, 2);
00212                         MoveWindow(rect, TRUE);
00213                 }
00214                 break;
00215 
00216         case WM_DESTROY:
00217                 // perform clean up
00218                 if (m_bTransparent)
00219                         SetTransparency(FALSE);
00220                 break;
00221 
00222         case WM_PAINT:
00223                 if (m_bTransparent)
00224                 {
00225                         CPaintDC dc(this);
00226 
00227                         // select bitmaps
00228                         CBitmap *pOldGrip, *pOldMask;
00229 
00230                         pOldGrip = m_dcGrip.SelectObject(&m_bmGrip);
00231                         pOldMask = m_dcMask.SelectObject(&m_bmMask);
00232 
00233                         // obtain original grip bitmap, make the mask and prepare masked bitmap
00234                         CScrollBar::WindowProc(WM_PAINT, (WPARAM)m_dcGrip.GetSafeHdc(), lParam);
00235                         m_dcGrip.SetBkColor(m_dcGrip.GetPixel(0, 0));
00236                         m_dcMask.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCCOPY);
00237                         m_dcGrip.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, 0x00220326);
00238                         
00239                         // draw transparently
00240                         dc.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, SRCAND);
00241                         dc.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCPAINT);
00242 
00243                         // unselect bitmaps
00244                         m_dcGrip.SelectObject(pOldGrip);
00245                         m_dcMask.SelectObject(pOldMask);
00246 
00247                         return 0;
00248                 }
00249                 break;
00250         }
00251 
00252         return CScrollBar::WindowProc(message, wParam, lParam);
00253 }
00254 
00255 void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate)
00256 {
00257         // creates or deletes DCs and Bitmaps used for
00258         // implementing a transparent size grip
00259 
00260         if (bActivate && !m_bTransparent)
00261         {
00262                 m_bTransparent = TRUE;
00263 
00264                 CClientDC dc(this);
00265 
00266                 // create memory DCs and bitmaps
00267                 m_dcGrip.CreateCompatibleDC(&dc);
00268                 m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
00269 
00270                 m_dcMask.CreateCompatibleDC(&dc);
00271                 m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
00272         }
00273         else if (!bActivate && m_bTransparent)
00274         {
00275                 m_bTransparent = FALSE;
00276 
00277                 // destroy memory DCs and bitmaps
00278                 m_dcGrip.DeleteDC();
00279                 m_bmGrip.DeleteObject();
00280 
00281                 m_dcMask.DeleteDC();
00282                 m_bmMask.DeleteObject();
00283         }
00284 }
00285 
00286 void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable)
00287 {
00288         m_bTriangular = bEnable;
00289 
00290         if (bEnable)
00291         {
00292                 // set a triangular window region
00293                 CRect rect;
00294                 GetWindowRect(rect);
00295                 rect.OffsetRect(-rect.TopLeft());
00296                 POINT arrPoints[] =
00297                 {
00298                         { rect.left, rect.bottom },
00299                         { rect.right, rect.bottom },
00300                         { rect.right, rect.top }
00301                 };
00302                 CRgn rgnGrip;
00303                 rgnGrip.CreatePolygonRgn(arrPoints, 3, WINDING);
00304                 SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible());
00305         }
00306         else
00307         {
00308                 SetWindowRgn((HRGN)NULL, IsWindowVisible());
00309         }
00310 }

Generated on Tue Dec 13 14:47:57 2005 for guliverkli by  doxygen 1.4.5