ColourPicker.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // ColourPicker.cpp : implementation file
  2. //
  3. // ColourPicker is a drop-in colour picker control. Check out the
  4. // header file or the accompanying HTML doc file for details.
  5. //
  6. // Written by Chris Maunder ([email protected])
  7. // Extended by Alexander Bischofberger ([email protected])
  8. // Copyright (c) 1998.
  9. //
  10. // This code may be used in compiled form in any way you desire. This
  11. // file may be redistributed unmodified by any means PROVIDING it is
  12. // not sold for profit without the authors written consent, and
  13. // providing that this notice and the authors name is included. If
  14. // the source code in this file is used in any commercial application
  15. // then a simple email would be nice.
  16. //
  17. // This file is provided "as is" with no expressed or implied warranty.
  18. // The author accepts no liability if it causes any damage to your
  19. // computer, causes your pet cat to fall ill, increases baldness or
  20. // makes you car start emitting strange noises when you start it up.
  21. //
  22. // Expect bugs.
  23. //
  24. // Please use and enjoy. Please let me know of any bugs/mods/improvements
  25. // that you have found/implemented and I will fix/incorporate them into this
  26. // file.
  27. //
  28. // Updated 16 May 1998
  29. // 31 May 1998 - added Default text (CJM)
  30. // 9 Jan 1999 - minor vis update
  31. #include "stdafx.h"
  32. #include "ColourPopup.h"
  33. #include "ColourPicker.h"
  34. #ifdef _DEBUG
  35. #define new DEBUG_NEW
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. void AFXAPI DDX_ColourPicker(CDataExchange *pDX, int nIDC, COLORREF& crColour)
  40. {
  41. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  42. ASSERT (hWndCtrl != NULL);
  43. CColourPicker* pColourPicker = (CColourPicker*) CWnd::FromHandle(hWndCtrl);
  44. if (pDX->m_bSaveAndValidate)
  45. {
  46. crColour = pColourPicker->GetColour();
  47. }
  48. else // initializing
  49. {
  50. pColourPicker->SetColour(crColour);
  51. }
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CColourPicker
  55. CColourPicker::CColourPicker()
  56. {
  57. SetBkColour(GetSysColor(COLOR_3DFACE));
  58. SetTextColour(GetSysColor(COLOR_BTNTEXT));
  59. m_bTrackSelection = FALSE;
  60. m_nSelectionMode = CP_MODE_BK;
  61. m_bActive = FALSE;
  62. m_strDefaultText = _T("Automatic");
  63. m_strCustomText = _T("More Colours...");
  64. }
  65. CColourPicker::~CColourPicker()
  66. {
  67. }
  68. IMPLEMENT_DYNCREATE(CColourPicker, CButton)
  69. BEGIN_MESSAGE_MAP(CColourPicker, CButton)
  70. //{{AFX_MSG_MAP(CColourPicker)
  71. ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
  72. ON_WM_CREATE()
  73. //}}AFX_MSG_MAP
  74. ON_MESSAGE(CPN_SELENDOK, OnSelEndOK)
  75. ON_MESSAGE(CPN_SELENDCANCEL, OnSelEndCancel)
  76. ON_MESSAGE(CPN_SELCHANGE, OnSelChange)
  77. END_MESSAGE_MAP()
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CColourPicker message handlers
  80. LONG CColourPicker::OnSelEndOK(UINT lParam, LONG /*wParam*/)
  81. {
  82. COLORREF crNewColour = (COLORREF) lParam;
  83. m_bActive = FALSE;
  84. SetColour(crNewColour);
  85. CWnd *pParent = GetParent();
  86. if (pParent) {
  87. pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
  88. pParent->SendMessage(CPN_SELENDOK, lParam, (WPARAM) GetDlgCtrlID());
  89. }
  90. if (crNewColour != GetColour())
  91. if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
  92. return TRUE;
  93. }
  94. LONG CColourPicker::OnSelEndCancel(UINT lParam, LONG /*wParam*/)
  95. {
  96. m_bActive = FALSE;
  97. SetColour((COLORREF) lParam);
  98. CWnd *pParent = GetParent();
  99. if (pParent) {
  100. pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
  101. pParent->SendMessage(CPN_SELENDCANCEL, lParam, (WPARAM) GetDlgCtrlID());
  102. }
  103. return TRUE;
  104. }
  105. LONG CColourPicker::OnSelChange(UINT lParam, LONG /*wParam*/)
  106. {
  107. if (m_bTrackSelection) SetColour((COLORREF) lParam);
  108. CWnd *pParent = GetParent();
  109. if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
  110. return TRUE;
  111. }
  112. int CColourPicker::OnCreate(LPCREATESTRUCT lpCreateStruct)
  113. {
  114. if (CButton::OnCreate(lpCreateStruct) == -1)
  115. return -1;
  116. SetWindowSize(); // resize appropriately
  117. return 0;
  118. }
  119. // On mouse click, create and show a CColourPopup window for colour selection
  120. BOOL CColourPicker::OnClicked()
  121. {
  122. m_bActive = TRUE;
  123. CRect rect;
  124. GetWindowRect(rect);
  125. new CColourPopup(CPoint(rect.left, rect.bottom), // Point to display popup
  126. GetColour(), // Selected colour
  127. this, // parent
  128. m_strDefaultText, // "Default" text area
  129. m_strCustomText); // Custom Text
  130. CWnd *pParent = GetParent();
  131. if (pParent)
  132. pParent->SendMessage(CPN_DROPDOWN, (LPARAM)GetColour(), (WPARAM) GetDlgCtrlID());
  133. // Docs say I should return FALSE to stop the parent also getting the message.
  134. // HA! What a joke.
  135. return TRUE;
  136. }
  137. void CColourPicker::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  138. {
  139. ASSERT(lpDrawItemStruct);
  140. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  141. CRect rect = lpDrawItemStruct->rcItem;
  142. UINT state = lpDrawItemStruct->itemState;
  143. CString m_strText;
  144. CSize Margins(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
  145. // Draw arrow
  146. if (m_bActive) state |= ODS_SELECTED;
  147. pDC->DrawFrameControl(&m_ArrowRect, DFC_SCROLL, DFCS_SCROLLDOWN |
  148. ((state & ODS_SELECTED) ? DFCS_PUSHED : 0) |
  149. ((state & ODS_DISABLED) ? DFCS_INACTIVE : 0));
  150. pDC->DrawEdge(rect, EDGE_SUNKEN, BF_RECT);
  151. // Must reduce the size of the "client" area of the button due to edge thickness.
  152. rect.DeflateRect(Margins.cx, Margins.cy);
  153. // Fill remaining area with colour
  154. rect.right -= m_ArrowRect.Width();
  155. CBrush brush( ((state & ODS_DISABLED) || m_crColourBk == CLR_DEFAULT)?
  156. ::GetSysColor(COLOR_3DFACE) : m_crColourBk);
  157. CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush);
  158. pDC->SelectStockObject(NULL_PEN);
  159. pDC->Rectangle(rect);
  160. pDC->SelectObject(pOldBrush);
  161. // Draw the window text (if any)
  162. GetWindowText(m_strText);
  163. if (m_strText.GetLength())
  164. {
  165. pDC->SetBkMode(TRANSPARENT);
  166. if (state & ODS_DISABLED)
  167. {
  168. rect.OffsetRect(1,1);
  169. pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
  170. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  171. rect.OffsetRect(-1,-1);
  172. pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
  173. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  174. }
  175. else
  176. {
  177. pDC->SetTextColor((m_crColourText == CLR_DEFAULT)? 0 : m_crColourText);
  178. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  179. }
  180. }
  181. // Draw focus rect
  182. if (state & ODS_FOCUS)
  183. {
  184. rect.DeflateRect(1,1);
  185. pDC->DrawFocusRect(rect);
  186. }
  187. }
  188. /////////////////////////////////////////////////////////////////////////////
  189. // CColourPicker overrides
  190. void CColourPicker::PreSubclassWindow()
  191. {
  192. ModifyStyle(0, BS_OWNERDRAW); // Make it owner drawn
  193. CButton::PreSubclassWindow();
  194. SetWindowSize(); // resize appropriately
  195. }
  196. /////////////////////////////////////////////////////////////////////////////
  197. // CColourPicker attributes
  198. COLORREF CColourPicker::GetColour()
  199. {
  200. return (m_nSelectionMode == CP_MODE_TEXT)?
  201. GetTextColour(): GetBkColour();
  202. }
  203. void CColourPicker::SetColour(COLORREF crColour)
  204. {
  205. (m_nSelectionMode == CP_MODE_TEXT)?
  206. SetTextColour(crColour): SetBkColour(crColour);
  207. }
  208. void CColourPicker::SetBkColour(COLORREF crColourBk)
  209. {
  210. m_crColourBk = crColourBk;
  211. if (IsWindow(m_hWnd))
  212. RedrawWindow();
  213. }
  214. void CColourPicker::SetTextColour(COLORREF crColourText)
  215. {
  216. m_crColourText = crColourText;
  217. if (IsWindow(m_hWnd))
  218. RedrawWindow();
  219. }
  220. void CColourPicker::SetDefaultText(LPCTSTR szDefaultText)
  221. {
  222. m_strDefaultText = (szDefaultText)? szDefaultText : _T("");
  223. }
  224. void CColourPicker::SetCustomText(LPCTSTR szCustomText)
  225. {
  226. m_strCustomText = (szCustomText)? szCustomText : _T("");
  227. }
  228. /////////////////////////////////////////////////////////////////////////////
  229. // CColourPicker implementation
  230. void CColourPicker::SetWindowSize()
  231. {
  232. // Get size dimensions of edges
  233. CSize MarginSize(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
  234. // Get size of dropdown arrow
  235. int nArrowWidth = max(::GetSystemMetrics(SM_CXHTHUMB), 5*MarginSize.cx);
  236. int nArrowHeight = max(::GetSystemMetrics(SM_CYVTHUMB), 5*MarginSize.cy);
  237. CSize ArrowSize(max(nArrowWidth, nArrowHeight), max(nArrowWidth, nArrowHeight));
  238. // Get window size
  239. CRect rect;
  240. GetWindowRect(rect);
  241. CWnd* pParent = GetParent();
  242. if (pParent)
  243. pParent->ScreenToClient(rect);
  244. // Set window size at least as wide as 2 arrows, and as high as arrow + margins
  245. int nWidth = max(rect.Width(), 2*ArrowSize.cx + 2*MarginSize.cx);
  246. int nHeight = max( rect.Height(), ArrowSize.cy+2*MarginSize.cy);
  247. MoveWindow(rect.left, rect.top, nWidth, nHeight, TRUE);
  248. // Get the new coords of this window
  249. GetWindowRect(rect);
  250. ScreenToClient(rect);
  251. // Get the rect where the arrow goes, and convert to client coords.
  252. m_ArrowRect.SetRect(rect.right - ArrowSize.cx - MarginSize.cx,
  253. rect.top + MarginSize.cy, rect.right - MarginSize.cx,
  254. rect.bottom - MarginSize.cy);
  255. }