Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

798 lines
23 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: sysclrctrl.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // SysColorCtrl.cpp : Implementation of CSysColorCtrl
  11. #include "stdafx.h"
  12. #include "cic.h"
  13. #include "SysColorCtrl.h"
  14. #ifndef ASSERT
  15. #define ASSERT _ASSERT
  16. #endif
  17. #include <mmctempl.h>
  18. // CPlex::Create and CPlex::FreeDataChain are needed to use CList.
  19. // These should be moved to core.lib. I copied them from nodemgr\plex.cpp
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CPlex
  22. CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT nMax, UINT cbElement)
  23. {
  24. DECLARE_SC(sc, TEXT("CPlex::Create"));
  25. if ( (nMax <=0) || (cbElement <= 0))
  26. {
  27. sc = E_INVALIDARG;
  28. return NULL;
  29. }
  30. CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
  31. // may throw exception
  32. if (!p)
  33. {
  34. sc = E_OUTOFMEMORY;
  35. return NULL;
  36. }
  37. p->pNext = pHead;
  38. pHead = p; // change head (adds in reverse order for simplicity)
  39. return p;
  40. }
  41. void CPlex::FreeDataChain() // free this one and links
  42. {
  43. CPlex* p = this;
  44. while (p != NULL)
  45. {
  46. BYTE* bytes = (BYTE*) p;
  47. CPlex* pNext = p->pNext;
  48. delete[] bytes;
  49. p = pNext;
  50. }
  51. }
  52. // need to subclass the top-level window hosting this control so that
  53. // I can be assured of receiving the WM_SYSCOLORCHANGE message
  54. static WNDPROC g_OriginalWndProc;
  55. static HWND g_hwndTop;
  56. // need a list of HWNDs (one for each SysColorCtrl) so that I can notify each
  57. // one of WM_SYSCOLORCHANGE
  58. static CList<HWND, HWND> g_listHWND;
  59. static LRESULT SubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  60. {
  61. if (uMsg == WM_SYSCOLORCHANGE) {
  62. // post message to all SysColor controls
  63. POSITION pos = g_listHWND.GetHeadPosition();
  64. while (pos) {
  65. HWND hwndSysColor = g_listHWND.GetNext(pos);
  66. if (hwndSysColor != NULL)
  67. PostMessage(hwndSysColor, uMsg, wParam, lParam);
  68. }
  69. }
  70. return CallWindowProc(g_OriginalWndProc, hwnd, uMsg, wParam, lParam);
  71. }
  72. static long GetHTMLColor(int nIndex)
  73. {
  74. long rgb = GetSysColor(nIndex);
  75. // now swap the red and the blue so HTML hosts display the color properly
  76. return ((rgb & 0xff) << 16) + (rgb & 0xff00) + ((rgb & 0xff0000) >> 16);
  77. }
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CSysColorCtrl
  80. LRESULT CSysColorCtrl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  81. {
  82. // if no sys color controls currently exist, subclass the top level window
  83. if (g_listHWND.IsEmpty()) {
  84. g_hwndTop = GetTopLevelParent();
  85. g_OriginalWndProc = (WNDPROC)::SetWindowLongPtr(g_hwndTop, GWLP_WNDPROC, (LONG_PTR)&SubclassWndProc);
  86. }
  87. else {
  88. _ASSERT(g_hwndTop && g_OriginalWndProc);
  89. }
  90. // add this window to the list of SysColor control windows
  91. g_listHWND.AddTail(m_hWnd);
  92. bHandled = FALSE;
  93. return 0;
  94. }
  95. LRESULT CSysColorCtrl::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  96. {
  97. // remove me from the list
  98. POSITION pos = g_listHWND.Find(m_hWnd);
  99. if (pos != NULL) {
  100. g_listHWND.RemoveAt(pos);
  101. }
  102. // if hwnd list is empty and we've subclassed a window, undo that.
  103. if (g_listHWND.IsEmpty() && g_hwndTop && g_OriginalWndProc) {
  104. ::SetWindowLongPtr(g_hwndTop, GWLP_WNDPROC, (LONG_PTR)g_OriginalWndProc);
  105. g_OriginalWndProc = NULL;
  106. g_hwndTop = NULL;
  107. }
  108. bHandled = FALSE;
  109. return 0;
  110. }
  111. // need to post a user defined message to handle WM_SYSCOLORCHANGE to work
  112. // around a Win95 hang when using this control inside IE.
  113. LRESULT CSysColorCtrl::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  114. {
  115. PostMessage(WM_MYSYSCOLORCHANGE);
  116. return 0;
  117. }
  118. LRESULT CSysColorCtrl::OnMySysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  119. {
  120. Fire_SysColorChange();
  121. return 0;
  122. }
  123. //
  124. // Utility Methods
  125. //
  126. STDMETHODIMP CSysColorCtrl::ConvertRGBToHex(long rgb, BSTR * pszHex)
  127. {
  128. DECLARE_SC(sc, TEXT("CSysColorCtrl::ConvertRGBToHex"));
  129. sc = ScCheckPointers(pszHex);
  130. if (sc)
  131. return sc.ToHr();
  132. SysFreeString(*pszHex);
  133. *pszHex = SysAllocString(L"xxxxxx");
  134. if (NULL == *pszHex)
  135. return (sc = E_OUTOFMEMORY).ToHr();
  136. WCHAR wszPossibles[] = L"0123456789abcdef";
  137. int i = 0;
  138. (*pszHex)[i++] = wszPossibles[(rgb & 0xf00000) >> 20];
  139. (*pszHex)[i++] = wszPossibles[(rgb & 0x0f0000) >> 16];
  140. (*pszHex)[i++] = wszPossibles[(rgb & 0x00f000) >> 12];
  141. (*pszHex)[i++] = wszPossibles[(rgb & 0x000f00) >> 8];
  142. (*pszHex)[i++] = wszPossibles[(rgb & 0x0000f0) >> 4];
  143. (*pszHex)[i++] = wszPossibles[(rgb & 0x00000f)];
  144. (*pszHex)[i] = 0;
  145. return sc.ToHr();
  146. }
  147. STDMETHODIMP CSysColorCtrl::ConvertHexToRGB(BSTR szHex, long * pRGB)
  148. {
  149. if (pRGB == NULL)
  150. return E_POINTER;
  151. // Hex string must be perfectly formatted 6 digits
  152. // probably should implement ISystemErrorInfo to give user more info
  153. // on usage errors
  154. if (6 != wcslen(szHex))
  155. return E_INVALIDARG;
  156. long nRed, nGreen, nBlue;
  157. nRed = nGreen = nBlue = 0;
  158. nRed += ValueOfHexDigit(szHex[0]) * 16;
  159. nRed += ValueOfHexDigit(szHex[1]);
  160. nGreen += ValueOfHexDigit(szHex[2]) * 16;
  161. nGreen += ValueOfHexDigit(szHex[3]);
  162. nBlue += ValueOfHexDigit(szHex[4]) * 16;
  163. nBlue += ValueOfHexDigit(szHex[5]);
  164. *pRGB = (nRed << 16) + (nGreen << 8) + nBlue;
  165. return S_OK;
  166. }
  167. STDMETHODIMP CSysColorCtrl::GetRedFromRGB(long rgb, short * pVal)
  168. {
  169. if (pVal == NULL)
  170. return E_POINTER;
  171. // for html, rgb is 00RR GGBB, not 00BB GGRR
  172. *pVal = LOWORD ((rgb & 0xff0000) >> 16);
  173. return S_OK;
  174. }
  175. STDMETHODIMP CSysColorCtrl::GetGreenFromRGB(long rgb, short * pVal)
  176. {
  177. if (pVal == NULL)
  178. return E_POINTER;
  179. // for html, rgb is 00RR GGBB, not 00BB GGRR
  180. *pVal = LOWORD ((rgb & 0x00ff00) >> 8);
  181. return S_OK;
  182. }
  183. STDMETHODIMP CSysColorCtrl::GetBlueFromRGB(long rgb, short * pVal)
  184. {
  185. if (pVal == NULL)
  186. return E_POINTER;
  187. // for html, rgb is 00RR GGBB, not 00BB GGRR
  188. *pVal = LOWORD ((rgb & 0x0000ff));
  189. return S_OK;
  190. }
  191. // strings supported for format
  192. #define CSS_FORMAT L"CSS"
  193. #define HEX_FORMAT L"HEX"
  194. #define RGB_FORMAT L"RGB"
  195. //
  196. // private utility method for getting rgb from string based on format
  197. //
  198. HRESULT CSysColorCtrl::RGBFromString(BSTR pszColor, BSTR pszFormat, long * pRGB)
  199. {
  200. DECLARE_SC(sc, TEXT("CSysColorCtrl::RGBFromString"));
  201. sc = ScCheckPointers(pRGB);
  202. if (sc)
  203. return sc.ToHr();
  204. LPWSTR pszDupFormat = _wcsdup(pszFormat);
  205. if (!pszDupFormat)
  206. return (sc = E_OUTOFMEMORY).ToHr();
  207. LPWSTR pszUpper = NULL;
  208. LPWSTR pszLower = NULL;
  209. pszUpper = _wcsupr(pszDupFormat);
  210. *pRGB = -1;
  211. if (0 == wcscmp(pszUpper, RGB_FORMAT)) {
  212. *pRGB = _wtol(pszColor);
  213. }
  214. else if (0 == wcscmp(pszUpper, HEX_FORMAT)) {
  215. sc = ConvertHexToRGB(pszColor, pRGB);
  216. if (sc.ToHr() != S_OK)
  217. goto Cleanup;
  218. }
  219. else if (0 == wcscmp(pszUpper, CSS_FORMAT)) {
  220. LPWSTR pszDupColor = _wcsdup(pszColor);
  221. if (!pszDupColor)
  222. {
  223. sc = E_OUTOFMEMORY;
  224. goto Cleanup;
  225. }
  226. pszLower = _wcslwr(pszDupColor);
  227. if (0 == wcscmp(L"activeborder", pszLower)) {
  228. get_RGBactiveborder(pRGB);
  229. }
  230. else if (0 == wcscmp(L"activecaption", pszLower)) {
  231. get_RGBactivecaption(pRGB);
  232. }
  233. else if (0 == wcscmp(L"appworkspace", pszLower)) {
  234. get_RGBappworkspace(pRGB);
  235. }
  236. else if (0 == wcscmp(L"background", pszLower)) {
  237. get_RGBbackground(pRGB);
  238. }
  239. else if (0 == wcscmp(L"buttonface", pszLower)) {
  240. get_RGBbuttonface(pRGB);
  241. }
  242. else if (0 == wcscmp(L"buttonhighlight", pszLower)) {
  243. get_RGBbuttonhighlight(pRGB);
  244. }
  245. else if (0 == wcscmp(L"buttonshadow", pszLower)) {
  246. get_RGBbuttonshadow(pRGB);
  247. }
  248. else if (0 == wcscmp(L"buttontext", pszLower)) {
  249. get_RGBbuttontext(pRGB);
  250. }
  251. else if (0 == wcscmp(L"captiontext", pszLower)) {
  252. get_RGBcaptiontext(pRGB);
  253. }
  254. else if (0 == wcscmp(L"graytext", pszLower)) {
  255. get_RGBgraytext(pRGB);
  256. }
  257. else if (0 == wcscmp(L"highlight", pszLower)) {
  258. get_RGBhighlight(pRGB);
  259. }
  260. else if (0 == wcscmp(L"highlighttext", pszLower)) {
  261. get_RGBhighlighttext(pRGB);
  262. }
  263. else if (0 == wcscmp(L"inactiveborder", pszLower)) {
  264. get_RGBinactiveborder(pRGB);
  265. }
  266. else if (0 == wcscmp(L"inactivecaption", pszLower)) {
  267. get_RGBinactivecaption(pRGB);
  268. }
  269. else if (0 == wcscmp(L"inactivecaptiontext", pszLower)) {
  270. get_RGBinactivecaptiontext(pRGB);
  271. }
  272. else if (0 == wcscmp(L"infobackground", pszLower)) {
  273. get_RGBinfobackground(pRGB);
  274. }
  275. else if (0 == wcscmp(L"infotext", pszLower)) {
  276. get_RGBinfotext(pRGB);
  277. }
  278. else if (0 == wcscmp(L"menu", pszLower)) {
  279. get_RGBmenu(pRGB);
  280. }
  281. else if (0 == wcscmp(L"menutext", pszLower)) {
  282. get_RGBmenutext(pRGB);
  283. }
  284. else if (0 == wcscmp(L"scrollbar", pszLower)) {
  285. get_RGBscrollbar(pRGB);
  286. }
  287. else if (0 == wcscmp(L"threeddarkshadow", pszLower)) {
  288. get_RGBthreeddarkshadow(pRGB);
  289. }
  290. else if (0 == wcscmp(L"threedface", pszLower)) {
  291. get_RGBthreedface(pRGB);
  292. }
  293. else if (0 == wcscmp(L"threedhighlight", pszLower)) {
  294. get_RGBthreedhighlight(pRGB);
  295. }
  296. else if (0 == wcscmp(L"threedlightshadow", pszLower)) {
  297. get_RGBthreedlightshadow(pRGB);
  298. }
  299. else if (0 == wcscmp(L"threedshadow", pszLower)) {
  300. get_RGBthreedshadow(pRGB);
  301. }
  302. else if (0 == wcscmp(L"window", pszLower)) {
  303. get_RGBwindow(pRGB);
  304. }
  305. else if (0 == wcscmp(L"windowframe", pszLower)) {
  306. get_RGBwindowframe(pRGB);
  307. }
  308. else if (0 == wcscmp(L"windowtext", pszLower)) {
  309. get_RGBwindowtext(pRGB);
  310. }
  311. else {
  312. sc = E_INVALIDARG;
  313. goto Cleanup;
  314. }
  315. }
  316. else {
  317. // should set some error here such as through ISystemErrorInfo
  318. sc = E_INVALIDARG;
  319. goto Cleanup;
  320. }
  321. Cleanup:
  322. if (pszUpper)
  323. free(pszUpper);
  324. if (pszLower)
  325. free(pszLower);
  326. return sc.ToHr();
  327. }
  328. //
  329. // Private utility method using only RGB format for deriving colors based
  330. // on a starting color, a color to move towards, and a percentage to move
  331. // towards that color.
  332. //
  333. HRESULT CSysColorCtrl::GetDerivedRGBFromRGB(long rgbFrom,
  334. long rgbTo,
  335. short nPercent,
  336. long * pVal)
  337. {
  338. if (pVal == NULL)
  339. return E_POINTER;
  340. // nPercent must be between 0 and 100
  341. // probably should implement ISystemErrorInfo to give user more info
  342. // on usage errors
  343. if (nPercent < 0 || nPercent > 100)
  344. return E_INVALIDARG;
  345. // get the derived color based on starting color, ending color, and percentage
  346. // color = color + (colorTo - colorFrom) * (nPercent/100);
  347. long nRedFrom = (rgbFrom & 0xff0000) >> 16;
  348. long nRedTo = (rgbTo & 0xff0000) >> 16;
  349. long nRed = nRedFrom + ((nRedTo - nRedFrom)*nPercent/100);
  350. long nGreenFrom = (rgbFrom & 0x00ff00) >> 8;
  351. long nGreenTo = (rgbTo & 0x00ff00) >> 8;
  352. long nGreen = nGreenFrom + ((nGreenTo - nGreenFrom)*nPercent/100);
  353. long nBlueFrom = (rgbFrom & 0x0000ff);
  354. long nBlueTo = (rgbTo & 0x0000ff);
  355. long nBlue = nBlueFrom + ((nBlueTo - nBlueFrom)*nPercent/100);
  356. *pVal = (nRed << 16) + (nGreen << 8) + nBlue;
  357. return S_OK;
  358. }
  359. //
  360. // Method for Deriving colors based on a starting color,
  361. // a color to move towards, and a percentage to move towards that color.
  362. //
  363. STDMETHODIMP CSysColorCtrl::GetDerivedRGB(/*[in]*/ BSTR pszFrom,
  364. /*[in]*/ BSTR pszTo,
  365. /*[in]*/ BSTR pszFormat,
  366. /*[in]*/ short nPercent,
  367. /*[out, retval]*/ long * pVal)
  368. {
  369. if (pVal == NULL)
  370. return E_POINTER;
  371. //
  372. // get everything into RGB format, then calculate derived color
  373. //
  374. // convert from String to long using correct format to interpret from
  375. long rgbFrom = -1, rgbTo = -1;
  376. HRESULT hr;
  377. hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  378. if (hr != S_OK)
  379. return hr;
  380. hr = RGBFromString(pszTo, pszFormat, &rgbTo);
  381. if (hr != S_OK)
  382. return hr;
  383. return GetDerivedRGBFromRGB(rgbFrom, rgbTo, nPercent, pVal);
  384. }
  385. STDMETHODIMP CSysColorCtrl::GetDerivedHex(/*[in]*/ BSTR pszFrom,
  386. /*[in]*/ BSTR pszTo,
  387. /*[in]*/ BSTR pszFormat,
  388. /*[in]*/ short nPercent,
  389. /*[out, retval]*/ BSTR * pVal)
  390. {
  391. if (pVal == NULL)
  392. return E_POINTER;
  393. long rgb;
  394. HRESULT hr = GetDerivedRGB(pszFrom, pszTo, pszFormat, nPercent, &rgb);
  395. if (hr != S_OK)
  396. return hr;
  397. return ConvertRGBToHex(rgb, pVal);
  398. }
  399. STDMETHODIMP CSysColorCtrl::Get3QuarterLightRGB(/*[in]*/ BSTR pszFrom,
  400. /*[in]*/ BSTR pszFormat,
  401. /*[out, retval]*/ long * pVal)
  402. {
  403. if (pVal == NULL)
  404. return E_POINTER;
  405. // convert from String to long using correct format to interpret from
  406. long rgbFrom = -1;
  407. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  408. if (hr != S_OK)
  409. return hr;
  410. return GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 75, pVal);
  411. }
  412. STDMETHODIMP CSysColorCtrl::Get3QuarterLightHex(/*[in]*/ BSTR pszFrom,
  413. /*[in]*/ BSTR pszFormat,
  414. /*[out, retval]*/ BSTR * pVal)
  415. {
  416. if (pVal == NULL)
  417. return E_POINTER;
  418. // convert from String to long using correct format to interpret from
  419. long rgbFrom = -1;
  420. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  421. if (hr != S_OK)
  422. return hr;
  423. long rgb;
  424. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 75, &rgb);
  425. if (S_OK != hr)
  426. return hr;
  427. return ConvertRGBToHex(rgb, pVal);
  428. }
  429. STDMETHODIMP CSysColorCtrl::GetHalfLightRGB(/*[in]*/ BSTR pszFrom,
  430. /*[in]*/ BSTR pszFormat,
  431. /*[out, retval]*/ long * pVal)
  432. {
  433. if (pVal == NULL)
  434. return E_POINTER;
  435. // convert from String to long using correct format to interpret from
  436. long rgbFrom = -1;
  437. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  438. if (hr != S_OK)
  439. return hr;
  440. return GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 50, pVal);
  441. }
  442. STDMETHODIMP CSysColorCtrl::GetHalfLightHex(/*[in]*/ BSTR pszFrom,
  443. /*[in]*/ BSTR pszFormat,
  444. /*[out, retval]*/ BSTR * pVal)
  445. {
  446. if (pVal == NULL)
  447. return E_POINTER;
  448. // convert from String to long using correct format to interpret from
  449. long rgbFrom = -1;
  450. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  451. if (hr != S_OK)
  452. return hr;
  453. long rgb;
  454. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 50, &rgb);
  455. if (S_OK != hr)
  456. return hr;
  457. return ConvertRGBToHex(rgb, pVal);
  458. }
  459. STDMETHODIMP CSysColorCtrl::GetQuarterLightRGB(/*[in]*/ BSTR pszFrom,
  460. /*[in]*/ BSTR pszFormat,
  461. /*[out, retval]*/ long * pVal)
  462. {
  463. if (pVal == NULL)
  464. return E_POINTER;
  465. // convert from String to long using correct format to interpret from
  466. long rgbFrom = -1;
  467. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  468. if (hr != S_OK)
  469. return hr;
  470. return GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 25, pVal);
  471. }
  472. STDMETHODIMP CSysColorCtrl::GetQuarterLightHex(/*[in]*/ BSTR pszFrom,
  473. /*[in]*/ BSTR pszFormat,
  474. /*[out, retval]*/ BSTR * pVal)
  475. {
  476. if (pVal == NULL)
  477. return E_POINTER;
  478. // convert from String to long using correct format to interpret from
  479. long rgbFrom = -1;
  480. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  481. if (hr != S_OK)
  482. return hr;
  483. long rgb;
  484. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(255,255,255), 25, &rgb);
  485. if (S_OK != hr)
  486. return hr;
  487. return ConvertRGBToHex(rgb, pVal);
  488. }
  489. STDMETHODIMP CSysColorCtrl::Get3QuarterDarkRGB(/*[in]*/ BSTR pszFrom,
  490. /*[in]*/ BSTR pszFormat,
  491. /*[out, retval]*/ long * pVal)
  492. {
  493. if (pVal == NULL)
  494. return E_POINTER;
  495. // convert from String to long using correct format to interpret from
  496. long rgbFrom = -1;
  497. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  498. if (hr != S_OK)
  499. return hr;
  500. return GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 75, pVal);
  501. }
  502. STDMETHODIMP CSysColorCtrl::Get3QuarterDarkHex(/*[in]*/ BSTR pszFrom,
  503. /*[in]*/ BSTR pszFormat,
  504. /*[out, retval]*/ BSTR * pVal)
  505. {
  506. if (pVal == NULL)
  507. return E_POINTER;
  508. // convert from String to long using correct format to interpret from
  509. long rgbFrom = -1;
  510. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  511. if (hr != S_OK)
  512. return hr;
  513. long rgb;
  514. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 75, &rgb);
  515. if (S_OK != hr)
  516. return hr;
  517. return ConvertRGBToHex(rgb, pVal);
  518. }
  519. STDMETHODIMP CSysColorCtrl::GetHalfDarkRGB(/*[in]*/ BSTR pszFrom,
  520. /*[in]*/ BSTR pszFormat,
  521. /*[out, retval]*/ long * pVal)
  522. {
  523. if (pVal == NULL)
  524. return E_POINTER;
  525. // convert from String to long using correct format to interpret from
  526. long rgbFrom = -1;
  527. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  528. if (hr != S_OK)
  529. return hr;
  530. return GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 50, pVal);
  531. }
  532. STDMETHODIMP CSysColorCtrl::GetHalfDarkHex(/*[in]*/ BSTR pszFrom,
  533. /*[in]*/ BSTR pszFormat,
  534. /*[out, retval]*/ BSTR * pVal)
  535. {
  536. if (pVal == NULL)
  537. return E_POINTER;
  538. // convert from String to long using correct format to interpret from
  539. long rgbFrom = -1;
  540. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  541. if (hr != S_OK)
  542. return hr;
  543. long rgb;
  544. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 50, &rgb);
  545. if (S_OK != hr)
  546. return hr;
  547. return ConvertRGBToHex(rgb, pVal);
  548. }
  549. STDMETHODIMP CSysColorCtrl::GetQuarterDarkRGB(/*[in]*/ BSTR pszFrom,
  550. /*[in]*/ BSTR pszFormat,
  551. /*[out, retval]*/ long * pVal)
  552. {
  553. if (pVal == NULL)
  554. return E_POINTER;
  555. // convert from String to long using correct format to interpret from
  556. long rgbFrom = -1;
  557. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  558. if (hr != S_OK)
  559. return hr;
  560. return GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 25, pVal);
  561. }
  562. STDMETHODIMP CSysColorCtrl::GetQuarterDarkHex(/*[in]*/ BSTR pszFrom,
  563. /*[in]*/ BSTR pszFormat,
  564. /*[out, retval]*/ BSTR * pVal)
  565. {
  566. if (pVal == NULL)
  567. return E_POINTER;
  568. // convert from String to long using correct format to interpret from
  569. long rgbFrom = -1;
  570. HRESULT hr = RGBFromString(pszFrom, pszFormat, &rgbFrom);
  571. if (hr != S_OK)
  572. return hr;
  573. long rgb;
  574. hr = GetDerivedRGBFromRGB(rgbFrom, RGB(0,0,0), 25, &rgb);
  575. if (S_OK != hr)
  576. return hr;
  577. return ConvertRGBToHex(rgb, pVal);
  578. }
  579. //
  580. // Properties
  581. //
  582. // use macro so this is easily extensible to include more properties
  583. // Should probably move this whole thing to header to be in-line
  584. // for even easier extensibility
  585. #define GETPROPSIMPL(methodname, color_value) \
  586. STDMETHODIMP CSysColorCtrl::get_HEX##methodname(BSTR * pVal) { \
  587. return ConvertRGBToHex(GetHTMLColor(color_value), pVal); \
  588. } \
  589. STDMETHODIMP CSysColorCtrl::get_RGB##methodname(long * pVal) { \
  590. if (pVal == NULL) return E_POINTER; \
  591. *pVal = GetHTMLColor(color_value); \
  592. return S_OK; \
  593. }
  594. GETPROPSIMPL(activeborder, COLOR_ACTIVEBORDER)
  595. GETPROPSIMPL(activecaption, COLOR_ACTIVECAPTION)
  596. GETPROPSIMPL(appworkspace, COLOR_APPWORKSPACE)
  597. GETPROPSIMPL(background, COLOR_BACKGROUND)
  598. GETPROPSIMPL(buttonface, COLOR_BTNFACE)
  599. GETPROPSIMPL(buttonhighlight, COLOR_BTNHIGHLIGHT)
  600. GETPROPSIMPL(buttonshadow, COLOR_BTNSHADOW)
  601. GETPROPSIMPL(buttontext, COLOR_BTNTEXT)
  602. GETPROPSIMPL(captiontext, COLOR_CAPTIONTEXT)
  603. GETPROPSIMPL(graytext, COLOR_GRAYTEXT)
  604. GETPROPSIMPL(highlight, COLOR_HIGHLIGHT)
  605. GETPROPSIMPL(highlighttext, COLOR_HIGHLIGHTTEXT)
  606. GETPROPSIMPL(inactiveborder, COLOR_INACTIVEBORDER)
  607. GETPROPSIMPL(inactivecaption, COLOR_INACTIVECAPTION)
  608. GETPROPSIMPL(inactivecaptiontext, COLOR_INACTIVECAPTIONTEXT)
  609. GETPROPSIMPL(infobackground, COLOR_INFOBK)
  610. GETPROPSIMPL(infotext, COLOR_INFOTEXT)
  611. GETPROPSIMPL(menu, COLOR_MENU)
  612. GETPROPSIMPL(menutext, COLOR_MENUTEXT)
  613. GETPROPSIMPL(scrollbar, COLOR_SCROLLBAR)
  614. GETPROPSIMPL(threeddarkshadow, COLOR_3DDKSHADOW)
  615. GETPROPSIMPL(threedface, COLOR_3DFACE)
  616. GETPROPSIMPL(threedhighlight, COLOR_3DHIGHLIGHT)
  617. GETPROPSIMPL(threedlightshadow, COLOR_3DLIGHT) // Is this correct?
  618. GETPROPSIMPL(threedshadow, COLOR_3DSHADOW)
  619. GETPROPSIMPL(window, COLOR_WINDOW)
  620. GETPROPSIMPL(windowframe, COLOR_WINDOWFRAME)
  621. GETPROPSIMPL(windowtext, COLOR_WINDOWTEXT)
  622. //
  623. // Protected methods
  624. //
  625. int CSysColorCtrl::ValueOfHexDigit(WCHAR wch)
  626. {
  627. switch (wch) {
  628. case L'0':
  629. return 0;
  630. case L'1':
  631. return 1;
  632. case L'2':
  633. return 2;
  634. case L'3':
  635. return 3;
  636. case L'4':
  637. return 4;
  638. case L'5':
  639. return 5;
  640. case L'6':
  641. return 6;
  642. case L'7':
  643. return 7;
  644. case L'8':
  645. return 8;
  646. case L'9':
  647. return 9;
  648. case L'a':
  649. case L'A':
  650. return 10;
  651. case L'b':
  652. case L'B':
  653. return 11;
  654. case L'c':
  655. case L'C':
  656. return 12;
  657. case L'd':
  658. case L'D':
  659. return 13;
  660. case L'e':
  661. case L'E':
  662. return 14;
  663. case L'f':
  664. case L'F':
  665. return 15;
  666. }
  667. ATLTRACE(_T("Unrecognized Hex Digit: '%c'"), wch);
  668. return 0;
  669. } // ValueOfHexDigit()