Process Hacker
colorbox.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * color picker
4  *
5  * Copyright (C) 2010 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phgui.h>
24 #include <colorbox.h>
25 
26 typedef struct _PHP_COLORBOX_CONTEXT
27 {
28  COLORREF SelectedColor;
29  BOOLEAN Hot;
30  BOOLEAN HasFocus;
32 
33 LRESULT CALLBACK PhpColorBoxWndProc(
34  _In_ HWND hwnd,
35  _In_ UINT uMsg,
36  _In_ WPARAM wParam,
37  _In_ LPARAM lParam
38  );
39 
41  VOID
42  )
43 {
44  WNDCLASSEX c = { sizeof(c) };
45 
46  c.style = CS_GLOBALCLASS;
47  c.lpfnWndProc = PhpColorBoxWndProc;
48  c.cbClsExtra = 0;
49  c.cbWndExtra = sizeof(PVOID);
50  c.hInstance = PhLibImageBase;
51  c.hIcon = NULL;
52  c.hCursor = LoadCursor(NULL, IDC_ARROW);
53  c.hbrBackground = NULL;
54  c.lpszMenuName = NULL;
55  c.lpszClassName = PH_COLORBOX_CLASSNAME;
56  c.hIconSm = NULL;
57 
58  if (!RegisterClassEx(&c))
59  return FALSE;
60 
61  return TRUE;
62 }
63 
65  _Out_ PPHP_COLORBOX_CONTEXT *Context
66  )
67 {
68  PPHP_COLORBOX_CONTEXT context;
69 
70  context = PhAllocate(sizeof(PHP_COLORBOX_CONTEXT));
71  memset(context, 0, sizeof(PHP_COLORBOX_CONTEXT));
72  *Context = context;
73 }
74 
76  _In_ _Post_invalid_ PPHP_COLORBOX_CONTEXT Context
77  )
78 {
79  PhFree(Context);
80 }
81 
83  _In_ HWND hwnd,
84  _In_ PPHP_COLORBOX_CONTEXT Context
85  )
86 {
87  CHOOSECOLOR chooseColor = { sizeof(chooseColor) };
88  COLORREF customColors[16] = { 0 };
89 
90  chooseColor.hwndOwner = hwnd;
91  chooseColor.rgbResult = Context->SelectedColor;
92  chooseColor.lpCustColors = customColors;
93  chooseColor.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
94 
95  if (ChooseColor(&chooseColor))
96  {
97  Context->SelectedColor = chooseColor.rgbResult;
98  InvalidateRect(hwnd, NULL, TRUE);
99  }
100 }
101 
102 LRESULT CALLBACK PhpColorBoxWndProc(
103  _In_ HWND hwnd,
104  _In_ UINT uMsg,
105  _In_ WPARAM wParam,
106  _In_ LPARAM lParam
107  )
108 {
109  PPHP_COLORBOX_CONTEXT context;
110 
111  context = (PPHP_COLORBOX_CONTEXT)GetWindowLongPtr(hwnd, 0);
112 
113  if (uMsg == WM_CREATE)
114  {
115  PhpCreateColorBoxContext(&context);
116  SetWindowLongPtr(hwnd, 0, (LONG_PTR)context);
117  }
118 
119  if (!context)
120  return DefWindowProc(hwnd, uMsg, wParam, lParam);
121 
122  switch (uMsg)
123  {
124  case WM_CREATE:
125  {
126  // Nothing
127  }
128  break;
129  case WM_DESTROY:
130  {
131  PhpFreeColorBoxContext(context);
132  SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL);
133  }
134  break;
135  case WM_PAINT:
136  {
137  PAINTSTRUCT paintStruct;
138  RECT clientRect;
139  HDC hdc;
140 
141  if (hdc = BeginPaint(hwnd, &paintStruct))
142  {
143  GetClientRect(hwnd, &clientRect);
144 
145  // Border color
146  SetDCPenColor(hdc, RGB(0x44, 0x44, 0x44));
147 
148  // Fill color
149  if (!context->Hot && !context->HasFocus)
150  SetDCBrushColor(hdc, context->SelectedColor);
151  else
152  SetDCBrushColor(hdc, PhMakeColorBrighter(context->SelectedColor, 64));
153 
154  // Draw the rectangle.
155  SelectObject(hdc, GetStockObject(DC_PEN));
156  SelectObject(hdc, GetStockObject(DC_BRUSH));
157  Rectangle(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom);
158 
159  EndPaint(hwnd, &paintStruct);
160  }
161  }
162  return 0;
163  case WM_ERASEBKGND:
164  return 1;
165  case WM_MOUSEMOVE:
166  {
167  if (!context->Hot)
168  {
169  TRACKMOUSEEVENT trackMouseEvent = { sizeof(trackMouseEvent) };
170 
171  context->Hot = TRUE;
172  InvalidateRect(hwnd, NULL, TRUE);
173 
174  trackMouseEvent.dwFlags = TME_LEAVE;
175  trackMouseEvent.hwndTrack = hwnd;
176  TrackMouseEvent(&trackMouseEvent);
177  }
178  }
179  break;
180  case WM_MOUSELEAVE:
181  {
182  context->Hot = FALSE;
183  InvalidateRect(hwnd, NULL, TRUE);
184  }
185  break;
186  case WM_LBUTTONDOWN:
187  {
188  PhpChooseColor(hwnd, context);
189  }
190  break;
191  case WM_SETFOCUS:
192  {
193  context->HasFocus = TRUE;
194  InvalidateRect(hwnd, NULL, TRUE);
195  }
196  return 0;
197  case WM_KILLFOCUS:
198  {
199  context->HasFocus = FALSE;
200  InvalidateRect(hwnd, NULL, TRUE);
201  }
202  return 0;
203  case WM_GETDLGCODE:
204  if (wParam == VK_RETURN)
205  return DLGC_WANTMESSAGE;
206  return 0;
207  case WM_KEYDOWN:
208  {
209  switch (wParam)
210  {
211  case VK_SPACE:
212  case VK_RETURN:
213  PhpChooseColor(hwnd, context);
214  break;
215  }
216  }
217  break;
218  case CBCM_SETCOLOR:
219  context->SelectedColor = (COLORREF)wParam;
220  return TRUE;
221  case CBCM_GETCOLOR:
222  return (LRESULT)context->SelectedColor;
223  }
224 
225  return DefWindowProc(hwnd, uMsg, wParam, lParam);
226 }