ColourPicker.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. ON_MESSAGE(CPN_SELENDOK, OnColorButton)
  74. //}}AFX_MSG_MAP
  75. //ON_MESSAGE(CPN_SELENDOK, OnSelEndOK)
  76. //ON_MESSAGE(CPN_SELENDCANCEL, OnSelEndCancel)
  77. //ON_MESSAGE(CPN_SELCHANGE, OnSelChange)
  78. END_MESSAGE_MAP()
  79. LRESULT CColourPicker::OnColorButton(WPARAM w, LPARAM l)
  80. {
  81. GetParent()->SendMessage(CPN_SELENDOK, w, (LPARAM)l);
  82. return 0;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CColourPicker message handlers
  86. //LRESULT CColourPicker::OnSelEndOK(LPARAM lParam, WPARAM wParam)
  87. //{
  88. // COLORREF crNewColour = (COLORREF) lParam;
  89. // m_bActive = FALSE;
  90. // SetColour(crNewColour);
  91. //
  92. // CWnd *pParent = GetParent();
  93. // if (pParent) {
  94. // pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
  95. // pParent->SendMessage(CPN_SELENDOK, lParam, (WPARAM) GetDlgCtrlID());
  96. // }
  97. //
  98. // if (crNewColour != GetColour())
  99. // if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
  100. //
  101. // return TRUE;
  102. //}
  103. //
  104. //LRESULT CColourPicker::OnSelEndCancel(LPARAM lParam, WPARAM wParam)
  105. //{
  106. // m_bActive = FALSE;
  107. // SetColour((COLORREF) lParam);
  108. //
  109. // CWnd *pParent = GetParent();
  110. // if (pParent) {
  111. // pParent->SendMessage(CPN_CLOSEUP, lParam, (WPARAM) GetDlgCtrlID());
  112. // pParent->SendMessage(CPN_SELENDCANCEL, lParam, (WPARAM) GetDlgCtrlID());
  113. // }
  114. //
  115. // return TRUE;
  116. //}
  117. //
  118. //LRESULT CColourPicker::OnSelChange(LPARAM lParam, WPARAM wParam)
  119. //{
  120. // if (m_bTrackSelection) SetColour((COLORREF) lParam);
  121. //
  122. // CWnd *pParent = GetParent();
  123. // if (pParent) pParent->SendMessage(CPN_SELCHANGE, lParam, (WPARAM) GetDlgCtrlID());
  124. //
  125. // return TRUE;
  126. //}
  127. int CColourPicker::OnCreate(LPCREATESTRUCT lpCreateStruct)
  128. {
  129. if (CButton::OnCreate(lpCreateStruct) == -1)
  130. return -1;
  131. SetWindowSize(); // resize appropriately
  132. return 0;
  133. }
  134. // On mouse click, create and show a CColourPopup window for colour selection
  135. BOOL CColourPicker::OnClicked()
  136. {
  137. m_bActive = TRUE;
  138. CRect rect;
  139. GetWindowRect(rect);
  140. new CColourPopup(CPoint(rect.left, rect.bottom), // Point to display popup
  141. GetColour(), // Selected colour
  142. this, // parent
  143. m_strDefaultText, // "Default" text area
  144. m_strCustomText); // Custom Text
  145. CWnd *pParent = GetParent();
  146. if (pParent)
  147. pParent->SendMessage(CPN_DROPDOWN, (LPARAM)GetColour(), (WPARAM) GetDlgCtrlID());
  148. // Docs say I should return FALSE to stop the parent also getting the message.
  149. // HA! What a joke.
  150. return TRUE;
  151. }
  152. void CColourPicker::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  153. {
  154. ASSERT(lpDrawItemStruct);
  155. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  156. CRect rect = lpDrawItemStruct->rcItem;
  157. UINT state = lpDrawItemStruct->itemState;
  158. CString m_strText;
  159. CSize Margins(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
  160. // Draw arrow
  161. if (m_bActive) state |= ODS_SELECTED;
  162. pDC->DrawFrameControl(&m_ArrowRect, DFC_SCROLL, DFCS_SCROLLDOWN |
  163. ((state & ODS_SELECTED) ? DFCS_PUSHED : 0) |
  164. ((state & ODS_DISABLED) ? DFCS_INACTIVE : 0));
  165. pDC->DrawEdge(rect, EDGE_SUNKEN, BF_RECT);
  166. // Must reduce the size of the "client" area of the button due to edge thickness.
  167. rect.DeflateRect(Margins.cx, Margins.cy);
  168. // Fill remaining area with colour
  169. rect.right -= m_ArrowRect.Width();
  170. CBrush brush( ((state & ODS_DISABLED) || m_crColourBk == CLR_DEFAULT)?
  171. ::GetSysColor(COLOR_3DFACE) : m_crColourBk);
  172. CBrush* pOldBrush = (CBrush*) pDC->SelectObject(&brush);
  173. pDC->SelectStockObject(NULL_PEN);
  174. pDC->Rectangle(rect);
  175. pDC->SelectObject(pOldBrush);
  176. // Draw the window text (if any)
  177. GetWindowText(m_strText);
  178. if (m_strText.GetLength())
  179. {
  180. pDC->SetBkMode(TRANSPARENT);
  181. if (state & ODS_DISABLED)
  182. {
  183. rect.OffsetRect(1,1);
  184. pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
  185. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  186. rect.OffsetRect(-1,-1);
  187. pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
  188. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  189. }
  190. else
  191. {
  192. pDC->SetTextColor((m_crColourText == CLR_DEFAULT)? 0 : m_crColourText);
  193. pDC->DrawText(m_strText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  194. }
  195. }
  196. // Draw focus rect
  197. if (state & ODS_FOCUS)
  198. {
  199. rect.DeflateRect(1,1);
  200. pDC->DrawFocusRect(rect);
  201. }
  202. }
  203. /////////////////////////////////////////////////////////////////////////////
  204. // CColourPicker overrides
  205. void CColourPicker::PreSubclassWindow()
  206. {
  207. ModifyStyle(0, BS_OWNERDRAW); // Make it owner drawn
  208. CButton::PreSubclassWindow();
  209. SetWindowSize(); // resize appropriately
  210. }
  211. /////////////////////////////////////////////////////////////////////////////
  212. // CColourPicker attributes
  213. COLORREF CColourPicker::GetColour()
  214. {
  215. return (m_nSelectionMode == CP_MODE_TEXT)?
  216. GetTextColour(): GetBkColour();
  217. }
  218. void CColourPicker::SetColour(COLORREF crColour)
  219. {
  220. (m_nSelectionMode == CP_MODE_TEXT)?
  221. SetTextColour(crColour): SetBkColour(crColour);
  222. }
  223. void CColourPicker::SetBkColour(COLORREF crColourBk)
  224. {
  225. m_crColourBk = crColourBk;
  226. if (IsWindow(m_hWnd))
  227. RedrawWindow();
  228. }
  229. void CColourPicker::SetTextColour(COLORREF crColourText)
  230. {
  231. m_crColourText = crColourText;
  232. if (IsWindow(m_hWnd))
  233. RedrawWindow();
  234. }
  235. void CColourPicker::SetDefaultText(LPCTSTR szDefaultText)
  236. {
  237. m_strDefaultText = (szDefaultText)? szDefaultText : _T("");
  238. }
  239. void CColourPicker::SetCustomText(LPCTSTR szCustomText)
  240. {
  241. m_strCustomText = (szCustomText)? szCustomText : _T("");
  242. }
  243. /////////////////////////////////////////////////////////////////////////////
  244. // CColourPicker implementation
  245. void CColourPicker::SetWindowSize()
  246. {
  247. // Get size dimensions of edges
  248. CSize MarginSize(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
  249. // Get size of dropdown arrow
  250. int nArrowWidth = max(::GetSystemMetrics(SM_CXHTHUMB), 5*MarginSize.cx);
  251. int nArrowHeight = max(::GetSystemMetrics(SM_CYVTHUMB), 5*MarginSize.cy);
  252. CSize ArrowSize(max(nArrowWidth, nArrowHeight), max(nArrowWidth, nArrowHeight));
  253. // Get window size
  254. CRect rect;
  255. GetWindowRect(rect);
  256. CWnd* pParent = GetParent();
  257. if (pParent)
  258. pParent->ScreenToClient(rect);
  259. // Set window size at least as wide as 2 arrows, and as high as arrow + margins
  260. int nWidth = max(rect.Width(), 2*ArrowSize.cx + 2*MarginSize.cx);
  261. int nHeight = max( rect.Height(), ArrowSize.cy+2*MarginSize.cy);
  262. MoveWindow(rect.left, rect.top, nWidth, nHeight, TRUE);
  263. // Get the new coords of this window
  264. GetWindowRect(rect);
  265. ScreenToClient(rect);
  266. // Get the rect where the arrow goes, and convert to client coords.
  267. m_ArrowRect.SetRect(rect.right - ArrowSize.cx - MarginSize.cx,
  268. rect.top + MarginSize.cy, rect.right - MarginSize.cx,
  269. rect.bottom - MarginSize.cy);
  270. }