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.

541 lines
12 KiB

  1. //
  2. // CGRP.CPP
  3. // Color Group
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. // PRECOMP
  8. #include "precomp.h"
  9. static const TCHAR szCGClassName[] = "T126WB_CGRP";
  10. // These default colors are the same as MSPaint
  11. COLORREF g_crDefaultColors[NUMCLRPANES] =
  12. {
  13. PALETTERGB( 0, 0, 0 ),
  14. PALETTERGB( 128,128,128 ),
  15. PALETTERGB( 128, 0, 0 ),
  16. PALETTERGB( 128,128, 0 ),
  17. PALETTERGB( 0,128, 0 ),
  18. PALETTERGB( 0,128,128 ),
  19. PALETTERGB( 0, 0,128 ),
  20. PALETTERGB( 128, 0,128 ),
  21. PALETTERGB( 128,128, 64 ),
  22. PALETTERGB( 0, 64, 64 ),
  23. PALETTERGB( 0,128,255 ),
  24. PALETTERGB( 0, 64,128 ),
  25. PALETTERGB( 64, 0,255 ),
  26. PALETTERGB( 128, 64, 0 ),
  27. PALETTERGB( 255,255,255 ),
  28. PALETTERGB( 192,192,192 ),
  29. PALETTERGB( 255, 0, 0 ),
  30. PALETTERGB( 255,255, 0 ),
  31. PALETTERGB( 0,255, 0 ),
  32. PALETTERGB( 0,255,255 ),
  33. PALETTERGB( 0, 0,255 ),
  34. PALETTERGB( 255, 0,255 ),
  35. PALETTERGB( 255,255,128 ),
  36. PALETTERGB( 0,255,128 ),
  37. PALETTERGB( 128,255,255 ),
  38. PALETTERGB( 128,128,255 ),
  39. PALETTERGB( 255, 0,128 ),
  40. PALETTERGB( 255,128, 64 ),
  41. PALETTERGB( 0, 0, 0 ) // Current color
  42. };
  43. //
  44. // WbColorsGroup()
  45. //
  46. WbColorsGroup::WbColorsGroup()
  47. {
  48. int i;
  49. m_hwnd = NULL;
  50. for (i = 0; i < NUMCLRPANES; i++)
  51. {
  52. m_crColors[i] = g_crDefaultColors[i];
  53. m_hBrushes[i] = NULL;
  54. }
  55. for (i = 0; i < NUMCUSTCOLORS; i++)
  56. {
  57. m_crCustomColors[i] = CLRPANE_WHITE;
  58. }
  59. m_nLastColor = 0;
  60. }
  61. WbColorsGroup::~WbColorsGroup(void)
  62. {
  63. int i;
  64. // clean up
  65. for (i = 0; i < NUMCLRPANES; i++)
  66. {
  67. if (m_hBrushes[i] != NULL)
  68. {
  69. ::DeleteBrush(m_hBrushes[i]);
  70. m_hBrushes[i] = NULL;
  71. }
  72. }
  73. if (m_hwnd != NULL)
  74. {
  75. ::DestroyWindow(m_hwnd);
  76. ASSERT(m_hwnd == NULL);
  77. }
  78. // Unregister our class
  79. ::UnregisterClass(szCGClassName, g_hInstance);
  80. }
  81. BOOL WbColorsGroup::Create(HWND hwndParent, LPCRECT lprect)
  82. {
  83. int i;
  84. HDC hdc;
  85. HPALETTE hPal;
  86. HPALETTE hOldPal = NULL;
  87. WNDCLASSEX wc;
  88. ASSERT(m_hwnd == NULL);
  89. // Register our class
  90. ZeroMemory(&wc, sizeof(wc));
  91. wc.cbSize = sizeof(wc);
  92. wc.style = CS_DBLCLKS;
  93. wc.lpfnWndProc = CGWndProc;
  94. wc.hInstance = g_hInstance;
  95. wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
  96. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  97. wc.lpszClassName = szCGClassName;
  98. if (!::RegisterClassEx(&wc))
  99. {
  100. ERROR_OUT(("WbColorsGroup::Create register class failed"));
  101. return(FALSE);
  102. }
  103. //
  104. // We should be created the right siez
  105. //
  106. ASSERT(lprect->right - lprect->left == CLRCHOICE_WIDTH + NUMCOLS*CLRPANE_WIDTH);
  107. ASSERT(lprect->bottom - lprect->top == CLRCHOICE_HEIGHT);
  108. //
  109. // Calculate our item colors, then figure out our size.
  110. //
  111. hdc = ::GetDC(hwndParent);
  112. hPal = PG_GetPalette();
  113. if (hPal != NULL)
  114. {
  115. hOldPal = ::SelectPalette(hdc, hPal, FALSE);
  116. ::RealizePalette(hdc);
  117. }
  118. // load the colors from last time
  119. OPT_GetDataOption(OPT_MAIN_COLORPALETTE,
  120. sizeof m_crColors,
  121. (BYTE *)m_crColors );
  122. OPT_GetDataOption(OPT_MAIN_CUSTOMCOLORS,
  123. sizeof m_crCustomColors,
  124. (BYTE *)m_crCustomColors );
  125. // make brushes.
  126. for (i = 0; i < NUMCLRPANES; i++)
  127. {
  128. // force color matching
  129. m_crColors[i] = SET_PALETTERGB( m_crColors[i] );
  130. m_hBrushes[i] = ::CreateSolidBrush(m_crColors[i]);
  131. }
  132. for (i = 0; i < NUMCUSTCOLORS; i++)
  133. {
  134. // force color matching
  135. m_crCustomColors[i] = SET_PALETTERGB( m_crCustomColors[i] );
  136. }
  137. if (hOldPal != NULL)
  138. {
  139. ::SelectPalette(hdc, hOldPal, TRUE);
  140. }
  141. ::ReleaseDC(hwndParent, hdc);
  142. //
  143. // Here's our layout:
  144. // * The colors window is CHOICEFRAME_HEIGHT pixels high
  145. // * The current choice is a rect of CHOICEFRAME_WIDTH by
  146. // CHOICEFRAME_HEIGHT pixels, on the left side. This includes
  147. // a sunken EDGE.
  148. // * There is no gap horizontally or vertically among panes.
  149. //
  150. // Create our window -- we're always visible. The attribute group
  151. // shows/hides colors by showing/hiding itself.
  152. //
  153. if (!::CreateWindowEx(0, szCGClassName, NULL, WS_CHILD | WS_VISIBLE,
  154. lprect->left, lprect->top,
  155. lprect->right - lprect->left,
  156. lprect->bottom - lprect->top,
  157. hwndParent, NULL, g_hInstance, this))
  158. {
  159. ERROR_OUT(("Can't create WbColorsGroup"));
  160. return(FALSE);
  161. }
  162. ASSERT(m_hwnd != NULL);
  163. return(TRUE);
  164. }
  165. LRESULT CALLBACK CGWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  166. {
  167. LRESULT lResult = 0;
  168. WbColorsGroup * pcg;
  169. pcg = (WbColorsGroup *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  170. switch (message)
  171. {
  172. case WM_NCCREATE:
  173. pcg = (WbColorsGroup *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  174. ASSERT(pcg);
  175. pcg->m_hwnd = hwnd;
  176. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pcg);
  177. goto DefWndProc;
  178. break;
  179. case WM_NCDESTROY:
  180. ASSERT(pcg);
  181. pcg->m_hwnd = NULL;
  182. break;
  183. case WM_PAINT:
  184. ASSERT(pcg);
  185. pcg->OnPaint();
  186. break;
  187. case WM_LBUTTONDOWN:
  188. pcg->OnLButtonDown((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  189. break;
  190. case WM_LBUTTONDBLCLK:
  191. pcg->OnLButtonDblClk((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  192. break;
  193. default:
  194. DefWndProc:
  195. lResult = DefWindowProc(hwnd, message, wParam, lParam);
  196. break;
  197. }
  198. return(lResult);
  199. }
  200. void WbColorsGroup::GetNaturalSize(LPSIZE lpsize)
  201. {
  202. lpsize->cx = CLRCHOICE_WIDTH + NUMCOLS*CLRPANE_WIDTH;
  203. lpsize->cy = CLRCHOICE_HEIGHT;
  204. }
  205. COLORREF WbColorsGroup::GetCurColor(void)
  206. {
  207. return(GetColorOfBrush(INDEX_CHOICE));
  208. }
  209. void WbColorsGroup::SetCurColor(COLORREF clr)
  210. {
  211. SetColorOfPane(INDEX_CHOICE, clr);
  212. }
  213. //
  214. // OnPaint()
  215. //
  216. // MFC message handler for WM_PAINT
  217. //
  218. void WbColorsGroup::OnPaint(void)
  219. {
  220. PAINTSTRUCT ps;
  221. RECT rc;
  222. RECT rcClient;
  223. int dx, dy;
  224. int i;
  225. HPALETTE hPal;
  226. HPALETTE hOldPal = NULL;
  227. ::BeginPaint(m_hwnd, &ps);
  228. hPal = PG_GetPalette();
  229. if (hPal != NULL)
  230. {
  231. hOldPal = ::SelectPalette(ps.hdc, hPal, FALSE);
  232. ::RealizePalette(ps.hdc);
  233. }
  234. dx = ::GetSystemMetrics(SM_CXEDGE);
  235. dy = ::GetSystemMetrics(SM_CYEDGE);
  236. ::GetClientRect(m_hwnd, &rcClient);
  237. // Draw the current choice
  238. rc = rcClient;
  239. rc.right = rc.left + CLRCHOICE_WIDTH;
  240. ::DrawEdge(ps.hdc, &rc, EDGE_SUNKEN, BF_ADJUST | BF_RECT);
  241. ::FillRect(ps.hdc, &rc, m_hBrushes[INDEX_CHOICE]);
  242. // Draw the colors
  243. rcClient.left += CLRCHOICE_WIDTH;
  244. rc = rcClient;
  245. rc.right = rc.left + CLRPANE_WIDTH;
  246. rc.bottom = rc.top + CLRPANE_HEIGHT;
  247. for (i = 0; i < NUMCLRPANES; i++)
  248. {
  249. ::DrawEdge(ps.hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  250. ::FillRect(ps.hdc, &rc, m_hBrushes[i]);
  251. ::InflateRect(&rc, dx, dy);
  252. if (i == NUMCOLS - 1)
  253. {
  254. ::OffsetRect(&rc, - (NUMCOLS-1)*CLRPANE_WIDTH, CLRPANE_HEIGHT);
  255. }
  256. else
  257. {
  258. ::OffsetRect(&rc, CLRPANE_WIDTH, 0);
  259. }
  260. }
  261. if (hOldPal != NULL)
  262. {
  263. ::SelectPalette(ps.hdc, hOldPal, TRUE);
  264. }
  265. ::EndPaint(m_hwnd, &ps);
  266. }
  267. //
  268. // OnLButtonDown()
  269. //
  270. void WbColorsGroup::OnLButtonDown(UINT nFlags, int x, int y)
  271. {
  272. //
  273. // If this is the current choice, do nothing. Otherwise, change the
  274. // current color.
  275. //
  276. if (x >= CLRCHOICE_WIDTH)
  277. {
  278. int pane;
  279. pane = 0;
  280. if (y >= CLRPANE_HEIGHT)
  281. pane += NUMCOLS;
  282. pane += (x - CLRCHOICE_WIDTH) / CLRPANE_WIDTH;
  283. // Set the current color
  284. SetColorOfPane(INDEX_CHOICE, GetColorOfBrush(pane));
  285. m_nLastColor = pane;
  286. // tell Whiteboard about it.
  287. ClickOwner();
  288. }
  289. }
  290. //
  291. // OnLButtonDblClk()
  292. //
  293. void WbColorsGroup::OnLButtonDblClk(UINT nFlags, int x, int y)
  294. // Invoke color dialog to edit this color
  295. {
  296. if (x >= CLRCHOICE_WIDTH)
  297. {
  298. int pane;
  299. pane = 0;
  300. if (y >= CLRPANE_HEIGHT)
  301. pane += NUMCOLS;
  302. pane += (x - CLRCHOICE_WIDTH) / CLRPANE_WIDTH;
  303. DoColorDialog(pane);
  304. }
  305. }
  306. // Returns COLORREF of Brushes[] or BLACK if no brush
  307. COLORREF WbColorsGroup::GetColorOfBrush( int nColor )
  308. {
  309. ASSERT(nColor >= 0);
  310. ASSERT(nColor < NUMCLRPANES);
  311. if (m_hBrushes[nColor] != NULL)
  312. {
  313. return(m_crColors[nColor]);
  314. }
  315. else
  316. {
  317. return(CLRPANE_BLACK);
  318. }
  319. }
  320. // Recreates the nColor-th brush, using the new color
  321. void WbColorsGroup::SetColorOfBrush( int nColor, COLORREF crNewColor )
  322. {
  323. HBRUSH hNewBrush;
  324. // force color matching
  325. crNewColor = SET_PALETTERGB( crNewColor );
  326. // check if we need to do anything
  327. if ((nColor > -1) && (crNewColor != GetColorOfBrush(nColor)))
  328. {
  329. // new color is different from old color, make a new brush
  330. hNewBrush = ::CreateSolidBrush(crNewColor);
  331. if (hNewBrush != NULL)
  332. {
  333. // We managed to create the new brush. Delete the old one
  334. if (m_hBrushes[nColor] != NULL)
  335. {
  336. ::DeleteBrush(m_hBrushes[nColor]);
  337. }
  338. m_hBrushes[nColor] = hNewBrush;
  339. m_crColors[nColor] = crNewColor;
  340. }
  341. }
  342. }
  343. //
  344. // SetColorOfPane()
  345. //
  346. // Replaces brush associated with nPaneId.
  347. //
  348. void WbColorsGroup::SetColorOfPane(int pane, COLORREF crNewColor )
  349. {
  350. RECT rcClient;
  351. // make a new brush
  352. SetColorOfBrush(pane, crNewColor);
  353. // update pane
  354. ::GetClientRect(m_hwnd, &rcClient);
  355. if (pane == INDEX_CHOICE)
  356. {
  357. rcClient.right = rcClient.left + CLRCHOICE_WIDTH;
  358. }
  359. else
  360. {
  361. rcClient.left += CLRCHOICE_WIDTH;
  362. rcClient.top += (pane / NUMCOLS) * CLRPANE_HEIGHT;
  363. rcClient.bottom = rcClient.top + CLRPANE_HEIGHT;
  364. rcClient.left += (pane % NUMCOLS) * CLRPANE_WIDTH;
  365. rcClient.right = rcClient.left + CLRPANE_WIDTH;
  366. }
  367. ::InvalidateRect(m_hwnd, &rcClient, FALSE);
  368. }
  369. void WbColorsGroup::SaveSettings( void )
  370. // Saves stuff in registry because we're shutting down
  371. {
  372. // load the colors from last time
  373. OPT_SetDataOption(OPT_MAIN_COLORPALETTE,
  374. sizeof m_crColors,
  375. (BYTE *)m_crColors );
  376. OPT_SetDataOption(OPT_MAIN_CUSTOMCOLORS,
  377. sizeof m_crCustomColors,
  378. (BYTE *)m_crCustomColors );
  379. }
  380. LRESULT WbColorsGroup::OnEditColors( void )
  381. {
  382. DoColorDialog( m_nLastColor );
  383. return S_OK;
  384. }
  385. //
  386. // DoColorDialog()
  387. // Put up ComDlg color picker to edit the pane's color value
  388. //
  389. COLORREF WbColorsGroup::DoColorDialog( int nColor )
  390. {
  391. CHOOSECOLOR cc;
  392. memset(&cc, 0, sizeof(cc));
  393. cc.lStructSize = sizeof(cc);
  394. cc.lpCustColors = m_crCustomColors;
  395. cc.Flags = CC_RGBINIT;
  396. cc.rgbResult = GetColorOfBrush(nColor);
  397. cc.hwndOwner = m_hwnd;
  398. ::ChooseColor(&cc);
  399. // force color matching
  400. cc.rgbResult = SET_PALETTERGB(cc.rgbResult);
  401. // use the new color
  402. SetColorOfPane(nColor, cc.rgbResult );
  403. // set choice pane
  404. SetColorOfPane(INDEX_CHOICE, cc.rgbResult );
  405. m_nLastColor = nColor;
  406. // tell Whiteboard about it.
  407. ClickOwner();
  408. return(cc.rgbResult );
  409. }
  410. void WbColorsGroup::ClickOwner( void )
  411. {
  412. ::PostMessage(g_pMain->m_hwnd, WM_COMMAND,
  413. (WPARAM)MAKELONG( IDM_COLOR, BN_CLICKED ),
  414. (LPARAM)m_hwnd);
  415. }