- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 - ppescher@yahoo.com)
    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 }