GME  13
ColourPicker.cpp
Go to the documentation of this file.
00001 // ColourPicker.cpp : implementation file
00002 //
00003 // ColourPicker is a drop-in colour picker control. Check out the 
00004 // header file or the accompanying HTML doc file for details.
00005 //
00006 // Written by Chris Maunder (chrismaunder@codeguru.com)
00007 // Extended by Alexander Bischofberger (bischofb@informatik.tu-muenchen.de)
00008 // Copyright (c) 1998.
00009 //
00010 // This code may be used in compiled form in any way you desire. This
00011 // file may be redistributed unmodified by any means PROVIDING it is 
00012 // not sold for profit without the authors written consent, and 
00013 // providing that this notice and the authors name is included. If 
00014 // the source code in  this file is used in any commercial application 
00015 // then a simple email would be nice.
00016 //
00017 // This file is provided "as is" with no expressed or implied warranty.
00018 // The author accepts no liability if it causes any damage to your
00019 // computer, causes your pet cat to fall ill, increases baldness or
00020 // makes you car start emitting strange noises when you start it up.
00021 //
00022 // Expect bugs.
00023 // 
00024 // Please use and enjoy. Please let me know of any bugs/mods/improvements 
00025 // that you have found/implemented and I will fix/incorporate them into this
00026 // file. 
00027 //
00028 // Updated 16 May 1998
00029 //         31 May 1998 - added Default text (CJM)
00030 //          9 Jan 1999 - minor vis update
00031 
00032 #include "stdafx.h"
00033 #include "ColourPopup.h"
00034 #include "ColourPicker.h"
00035 
00036 #ifdef _DEBUG
00037 #define new DEBUG_NEW
00038 #undef THIS_FILE
00039 static char THIS_FILE[] = __FILE__;
00040 #endif
00041 
00042 void AFXAPI DDX_ColourPicker(CDataExchange *pDX, int nIDC, COLORREF& crColour)
00043 {
00044     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
00045     ASSERT (hWndCtrl != NULL);                
00046     
00047     CColourPicker* pColourPicker = (CColourPicker*) CWnd::FromHandle(hWndCtrl);
00048     if (pDX->m_bSaveAndValidate)
00049     {
00050         crColour = pColourPicker->GetColour();
00051     }
00052     else // initializing
00053     {
00054         pColourPicker->SetColour(crColour);
00055     }
00056 }
00057 
00059 // CColourPicker
00060 
00061 CColourPicker::CColourPicker()
00062 {
00063     SetBkColour(GetSysColor(COLOR_3DFACE));
00064     SetTextColour(GetSysColor(COLOR_BTNTEXT));
00065 
00066     m_bTrackSelection = FALSE;
00067     m_nSelectionMode = CP_MODE_BK;
00068     m_bActive = FALSE;
00069 
00070     m_strDefaultText = _T("Default");
00071     m_strCustomText  = _T("More Colors...");
00072 }
00073 
00074 CColourPicker::~CColourPicker()
00075 {
00076 }
00077 
00078 IMPLEMENT_DYNCREATE(CColourPicker, CButton)
00079 
00080 BEGIN_MESSAGE_MAP(CColourPicker, CButton)
00081     //{{AFX_MSG_MAP(CColourPicker)
00082     ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
00083     ON_WM_CREATE()
00084     //}}AFX_MSG_MAP
00085     ON_MESSAGE(CPN_SELENDOK,     OnSelEndOK)
00086     ON_MESSAGE(CPN_SELENDCANCEL, OnSelEndCancel)
00087     ON_MESSAGE(CPN_SELCHANGE,    OnSelChange)
00088 END_MESSAGE_MAP()
00089 
00091 // CColourPicker message handlers
00092 
00093 LONG CColourPicker::OnSelEndOK(UINT lParam, LONG /*wParam*/)
00094 {
00095     COLORREF crNewColour = (COLORREF) lParam;
00096     m_bActive = FALSE;
00097     SetColour(crNewColour);
00098 
00099     CWnd *pParent = GetParent();
00100     if (pParent) {
00101         pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
00102         pParent->SendMessage(CPN_SELENDOK, lParam, (WPARAM) GetDlgCtrlID());
00103     }
00104 
00105     if (crNewColour != GetColour())
00106         if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
00107 
00108     return TRUE;
00109 }
00110 
00111 LONG CColourPicker::OnSelEndCancel(UINT lParam, LONG /*wParam*/)
00112 {
00113     m_bActive = FALSE;
00114     SetColour((COLORREF) lParam);
00115 
00116     CWnd *pParent = GetParent();
00117     if (pParent) {
00118         pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
00119         pParent->SendMessage(CPN_SELENDCANCEL, lParam, (WPARAM) GetDlgCtrlID());
00120     }
00121 
00122     return TRUE;
00123 }
00124 
00125 LONG CColourPicker::OnSelChange(UINT lParam, LONG /*wParam*/)
00126 {
00127     if (m_bTrackSelection) SetColour((COLORREF) lParam);
00128 
00129     CWnd *pParent = GetParent();
00130     if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
00131 
00132     return TRUE;
00133 }
00134 
00135 int CColourPicker::OnCreate(LPCREATESTRUCT lpCreateStruct) 
00136 {
00137     if (CButton::OnCreate(lpCreateStruct) == -1)
00138         return -1;
00139     
00140     SetWindowSize();    // resize appropriately
00141     return 0;
00142 }
00143 
00144 // On mouse click, create and show a CColourPopup window for colour selection
00145 BOOL CColourPicker::OnClicked()
00146 {
00147     m_bActive = TRUE;
00148     CRect rect;
00149     GetWindowRect(rect);
00150     new CColourPopup(CPoint(rect.left, rect.bottom),    // Point to display popup
00151                      GetColour(),                       // Selected colour
00152                      this,                              // parent
00153                      m_strDefaultText,                  // "Default" text area
00154                      m_strCustomText);                  // Custom Text
00155 
00156     CWnd *pParent = GetParent();
00157     if (pParent)
00158         pParent->SendMessage(CPN_DROPDOWN, (LPARAM)GetColour(), (WPARAM) GetDlgCtrlID());
00159 
00160     // Docs say I should return FALSE to stop the parent also getting the message.
00161     // HA! What a joke.
00162 
00163     return TRUE;
00164 }
00165 
00166 void CColourPicker::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
00167 {
00168     ASSERT(lpDrawItemStruct);
00169     
00170     CDC*    pDC     = CDC::FromHandle(lpDrawItemStruct->hDC);
00171     CRect   rect    = lpDrawItemStruct->rcItem;
00172     UINT    state   = lpDrawItemStruct->itemState;
00173     CString m_strText;
00174 
00175     CSize Margins(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
00176 
00177     // Draw arrow
00178     if (m_bActive) state |= ODS_SELECTED;
00179     pDC->DrawFrameControl(&m_ArrowRect, DFC_SCROLL, DFCS_SCROLLDOWN  | 
00180                           ((state & ODS_SELECTED) ? DFCS_PUSHED : 0) |
00181                           ((state & ODS_DISABLED) ? DFCS_INACTIVE : 0));
00182 
00183    // @T. L. pDC->DrawEdge(rect, EDGE_SUNKEN, BF_RECT);
00184 
00185     // Must reduce the size of the "client" area of the button due to edge thickness.
00186    // rect.DeflateRect(Margins.cx, Margins.cy);
00187 
00188     // Fill remaining area with colour
00189     rect.right -= m_ArrowRect.Width();
00190 
00191     CBrush brush( ((state & ODS_DISABLED) || m_crColourBk == CLR_DEFAULT)? 
00192                   ::GetSysColor(COLOR_3DFACE) : m_crColourBk);
00193     CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush);
00194         pDC->SelectStockObject(NULL_PEN);
00195     pDC->Rectangle(rect);
00196     pDC->SelectObject(pOldBrush);
00197 
00198     // Draw the window text (if any)
00199     GetWindowText(m_strText);
00200     if (m_strText.GetLength())
00201     {
00202         pDC->SetBkMode(TRANSPARENT);
00203         if (state & ODS_DISABLED)
00204         {
00205             rect.OffsetRect(1,1);
00206             pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
00207             pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
00208             rect.OffsetRect(-1,-1);
00209             pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
00210             pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
00211         }
00212         else
00213         {
00214             pDC->SetTextColor((m_crColourText == CLR_DEFAULT)? 0 : m_crColourText);
00215             pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
00216         }
00217     }
00218 
00219     // Draw focus rect
00220     if (state & ODS_FOCUS) 
00221     {
00222         rect.DeflateRect(1,1);
00223         pDC->DrawFocusRect(rect);
00224     }
00225 }
00226 
00228 // CColourPicker overrides
00229 
00230 void CColourPicker::PreSubclassWindow() 
00231 {
00232     ModifyStyle(0, BS_OWNERDRAW);        // Make it owner drawn
00233     CButton::PreSubclassWindow();
00234     SetWindowSize();                     // resize appropriately
00235 }
00236 
00238 // CColourPicker attributes
00239 
00240 COLORREF CColourPicker::GetColour()
00241 { 
00242     return (m_nSelectionMode == CP_MODE_TEXT)? 
00243         GetTextColour(): GetBkColour(); 
00244 }
00245 
00246 void CColourPicker::SetColour(COLORREF crColour)
00247 { 
00248     (m_nSelectionMode == CP_MODE_TEXT)? 
00249         SetTextColour(crColour): SetBkColour(crColour); 
00250 }
00251 
00252 void CColourPicker::SetBkColour(COLORREF crColourBk)
00253 {
00254     m_crColourBk = crColourBk;
00255     if (IsWindow(m_hWnd))
00256         RedrawWindow();
00257 }
00258 
00259 void CColourPicker::SetTextColour(COLORREF crColourText)
00260 {
00261     m_crColourText = crColourText;
00262     if (IsWindow(m_hWnd)) 
00263         RedrawWindow();
00264 }
00265 
00266 void CColourPicker::SetDefaultText(LPCTSTR szDefaultText)
00267 {
00268     m_strDefaultText = (szDefaultText)? szDefaultText : _T("");
00269 }
00270 
00271 void CColourPicker::SetCustomText(LPCTSTR szCustomText)
00272 {
00273     m_strCustomText = (szCustomText)? szCustomText : _T("");
00274 }
00275 
00277 // CColourPicker implementation
00278 
00279 void CColourPicker::SetWindowSize()
00280 {
00281     // Get size dimensions of edges
00282     CSize MarginSize(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
00283 
00284     // Get size of dropdown arrow
00285         // @ Tihamer Levendovszky
00286    // int nArrowWidth = 14;//max(::GetSystemMetrics(SM_CXHTHUMB), 5*MarginSize.cx);
00287    // int nArrowHeight = 14;//max(::GetSystemMetrics(SM_CYVTHUMB), 5*MarginSize.cy);
00288     //CSize ArrowSize(max(nArrowWidth, nArrowHeight), max(nArrowWidth, nArrowHeight));
00289 
00290     // Get window size
00291     CRect rect;
00292     GetWindowRect(rect);
00293 
00294         // Set Arrow size @Tihamer Levendovszky
00295         CSize ArrowSize(rect.Height(),rect.Height());
00296 
00297     CWnd* pParent = GetParent();
00298     if (pParent)
00299         pParent->ScreenToClient(rect);
00300 
00301     // Set window size at least as wide as 2 arrows, and as high as arrow + margins
00302     int nWidth = max(rect.Width(), 2*ArrowSize.cx + 2*MarginSize.cx);
00303     
00304         // @Tihamer Levendovszky
00305         //MoveWindow(rect.left, rect.top, nWidth, ArrowSize.cy+2*MarginSize.cy, TRUE);
00306         MoveWindow(rect.left, rect.top, nWidth, rect.Height(), TRUE);
00307 
00308     // Get the new coords of this window
00309     GetWindowRect(rect);
00310     ScreenToClient(rect);
00311 
00312     // Get the rect where the arrow goes, and convert to client coords.
00313   /*  m_ArrowRect.SetRect(rect.right - ArrowSize.cx - MarginSize.cx, 
00314                         rect.top + MarginSize.cy, rect.right - MarginSize.cx,
00315                         rect.bottom - MarginSize.cy);
00316                                         */
00317         // @Tihamer Levendovszky
00318          m_ArrowRect.SetRect(rect.right - ArrowSize.cx,rect.top-1,rect.right,rect.bottom-1 );
00319 }