Sync with trunk (r48008)
[reactos.git] / dll / cpl / desk / draw.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: lib/cpl/desk/draw.c
5 * PURPOSE: Providing drawing functions
6 *
7 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
8 */
9
10 /* #define NTOS_MODE_USER */
11 /* #define WIN32_NO_STATUS */
12 #include "desk.h"
13 #include "theme.h"
14 #include "draw.h"
15 /* #include <ndk/ntndk.h> */
16 /* #include <win32k/ntuser.h> */
17
18 /******************************************************************************/
19
20 static const signed char LTInnerNormal[] = {
21 -1, -1, -1, -1,
22 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
23 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1,
24 -1, -1, -1, -1
25 };
26
27 static const signed char LTOuterNormal[] = {
28 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
29 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
30 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
31 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1
32 };
33
34 static const signed char RBInnerNormal[] = {
35 -1, -1, -1, -1,
36 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
37 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
38 -1, -1, -1, -1
39 };
40
41 static const signed char RBOuterNormal[] = {
42 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
43 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
44 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
45 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1
46 };
47
48 static BOOL
49 MyIntDrawRectEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags, THEME *theme)
50 {
51 signed char LTInnerI, LTOuterI;
52 signed char RBInnerI, RBOuterI;
53 HPEN LTInnerPen, LTOuterPen;
54 HPEN RBInnerPen, RBOuterPen;
55 RECT InnerRect = *rc;
56 POINT SavePoint;
57 HPEN SavePen;
58 int LBpenplus = 0;
59 int LTpenplus = 0;
60 int RTpenplus = 0;
61 int RBpenplus = 0;
62 /* Init some vars */
63 LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
64 SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
65
66 /* Determine the colors of the edges */
67 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
68 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
69 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
70 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
71
72 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)
73 LBpenplus = 1;
74 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)
75 RTpenplus = 1;
76 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT)
77 RBpenplus = 1;
78 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)
79 LTpenplus = 1;
80
81 if(LTInnerI != -1)
82 LTInnerPen = GetStockObject(DC_PEN);
83 if(LTOuterI != -1)
84 LTOuterPen = GetStockObject(DC_PEN);
85 if(RBInnerI != -1)
86 RBInnerPen = GetStockObject(DC_PEN);
87 if(RBOuterI != -1)
88 RBOuterPen = GetStockObject(DC_PEN);
89 {
90 HBRUSH hbr;
91 hbr = CreateSolidBrush(theme->crColor[COLOR_BTNFACE]);
92 FillRect(hdc, &InnerRect, hbr);
93 DeleteObject(hbr);
94 }
95 MoveToEx(hdc, 0, 0, &SavePoint);
96
97 /* Draw the outer edge */
98 SelectObject(hdc, LTOuterPen);
99 SetDCPenColor(hdc, theme->crColor[LTOuterI]);
100 if(uFlags & BF_TOP)
101 {
102 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
103 LineTo(hdc, InnerRect.right, InnerRect.top);
104 }
105 if(uFlags & BF_LEFT)
106 {
107 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
108 LineTo(hdc, InnerRect.left, InnerRect.bottom);
109 }
110 SelectObject(hdc, RBOuterPen);
111 SetDCPenColor(hdc, theme->crColor[RBOuterI]);
112 if(uFlags & BF_BOTTOM)
113 {
114 MoveToEx(hdc, InnerRect.left, InnerRect.bottom-1, NULL);
115 LineTo(hdc, InnerRect.right, InnerRect.bottom-1);
116 }
117 if(uFlags & BF_RIGHT)
118 {
119 MoveToEx(hdc, InnerRect.right-1, InnerRect.top, NULL);
120 LineTo(hdc, InnerRect.right-1, InnerRect.bottom);
121 }
122
123 /* Draw the inner edge */
124 SelectObject(hdc, LTInnerPen);
125 SetDCPenColor(hdc, theme->crColor[LTInnerI]);
126 if(uFlags & BF_TOP)
127 {
128 MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
129 LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
130 }
131 if(uFlags & BF_LEFT)
132 {
133 MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
134 LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
135 }
136 SelectObject(hdc, RBInnerPen);
137 SetDCPenColor(hdc, theme->crColor[RBInnerI]);
138 if(uFlags & BF_BOTTOM)
139 {
140 MoveToEx(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2, NULL);
141 LineTo(hdc, InnerRect.right-RBpenplus, InnerRect.bottom-2);
142 }
143 if(uFlags & BF_RIGHT)
144 {
145 MoveToEx(hdc, InnerRect.right-2, InnerRect.top+RTpenplus, NULL);
146 LineTo(hdc, InnerRect.right-2, InnerRect.bottom-RBpenplus);
147 }
148
149 /* Cleanup */
150 SelectObject(hdc, SavePen);
151 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
152 return TRUE;
153 }
154
155 static BOOL
156 MyDrawFrameButton(HDC hdc, LPRECT rc, UINT uState, THEME *theme)
157 {
158 UINT edge;
159 if(uState & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
160 edge = EDGE_SUNKEN;
161 else
162 edge = EDGE_RAISED;
163 return MyIntDrawRectEdge(hdc, rc, edge, (uState & DFCS_FLAT) | BF_RECT | BF_SOFT, theme);
164 }
165
166 static int
167 MyMakeSquareRect(LPRECT src, LPRECT dst)
168 {
169 int Width = src->right - src->left;
170 int Height = src->bottom - src->top;
171 int SmallDiam = Width > Height ? Height : Width;
172
173 *dst = *src;
174
175 /* Make it a square box */
176 if (Width < Height) /* SmallDiam == Width */
177 {
178 dst->top += (Height-Width)/2;
179 dst->bottom = dst->top + SmallDiam;
180 }
181 else if(Width > Height) /* SmallDiam == Height */
182 {
183 dst->left += (Width-Height)/2;
184 dst->right = dst->left + SmallDiam;
185 }
186
187 return SmallDiam;
188 }
189
190 static BOOL
191 MyDrawFrameCaption(HDC dc, LPRECT r, UINT uFlags, THEME *theme)
192 {
193 LOGFONT lf;
194 HFONT hFont, hOldFont;
195 COLORREF clrsave;
196 RECT myr;
197 INT bkmode;
198 TCHAR Symbol;
199 switch(uFlags & 0xff)
200 {
201 case DFCS_CAPTIONCLOSE:
202 Symbol = 'r';
203 break;
204 case DFCS_CAPTIONHELP:
205 Symbol = 's';
206 break;
207 case DFCS_CAPTIONMIN:
208 Symbol = '0';
209 break;
210 case DFCS_CAPTIONMAX:
211 Symbol = '1';
212 break;
213 case DFCS_CAPTIONRESTORE:
214 Symbol = '2';
215 break;
216 }
217 MyIntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT, theme);
218 ZeroMemory(&lf, sizeof(LOGFONT));
219 MyMakeSquareRect(r, &myr);
220 myr.left += 1;
221 myr.top += 1;
222 myr.right -= 1;
223 myr.bottom -= 1;
224 if(uFlags & DFCS_PUSHED)
225 OffsetRect(&myr,1,1);
226 lf.lfHeight = myr.bottom - myr.top;
227 lf.lfWidth = 0;
228 lf.lfWeight = FW_NORMAL;
229 lf.lfCharSet = DEFAULT_CHARSET;
230 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
231 hFont = CreateFontIndirect(&lf);
232 /* save font and text color */
233 hOldFont = SelectObject(dc, hFont);
234 clrsave = GetTextColor(dc);
235 bkmode = GetBkMode(dc);
236 /* set color and drawing mode */
237 SetBkMode(dc, TRANSPARENT);
238 if(uFlags & DFCS_INACTIVE)
239 {
240 /* draw shadow */
241 SetTextColor(dc, theme->crColor[COLOR_BTNHIGHLIGHT]);
242 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
243 }
244 SetTextColor(dc, theme->crColor[(uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT]);
245 /* draw selected symbol */
246 TextOut(dc, myr.left, myr.top, &Symbol, 1);
247 /* restore previous settings */
248 SetTextColor(dc, clrsave);
249 SelectObject(dc, hOldFont);
250 SetBkMode(dc, bkmode);
251 DeleteObject(hFont);
252 return TRUE;
253 }
254
255 /******************************************************************************/
256
257 static BOOL
258 MyDrawFrameScroll(HDC dc, LPRECT r, UINT uFlags, THEME *theme)
259 {
260 LOGFONT lf;
261 HFONT hFont, hOldFont;
262 COLORREF clrsave;
263 RECT myr;
264 INT bkmode;
265 TCHAR Symbol;
266 switch(uFlags & 0xff)
267 {
268 case DFCS_SCROLLCOMBOBOX:
269 case DFCS_SCROLLDOWN:
270 Symbol = '6';
271 break;
272
273 case DFCS_SCROLLUP:
274 Symbol = '5';
275 break;
276
277 case DFCS_SCROLLLEFT:
278 Symbol = '3';
279 break;
280
281 case DFCS_SCROLLRIGHT:
282 Symbol = '4';
283 break;
284 }
285 MyIntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT, theme);
286 ZeroMemory(&lf, sizeof(LOGFONT));
287 MyMakeSquareRect(r, &myr);
288 myr.left += 1;
289 myr.top += 1;
290 myr.right -= 1;
291 myr.bottom -= 1;
292 if(uFlags & DFCS_PUSHED)
293 OffsetRect(&myr,1,1);
294 lf.lfHeight = myr.bottom - myr.top;
295 lf.lfWidth = 0;
296 lf.lfWeight = FW_NORMAL;
297 lf.lfCharSet = DEFAULT_CHARSET;
298 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
299 hFont = CreateFontIndirect(&lf);
300 /* save font and text color */
301 hOldFont = SelectObject(dc, hFont);
302 clrsave = GetTextColor(dc);
303 bkmode = GetBkMode(dc);
304 /* set color and drawing mode */
305 SetBkMode(dc, TRANSPARENT);
306 if(uFlags & DFCS_INACTIVE)
307 {
308 /* draw shadow */
309 SetTextColor(dc, theme->crColor[COLOR_BTNHIGHLIGHT]);
310 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
311 }
312 SetTextColor(dc, theme->crColor[(uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT]);
313 /* draw selected symbol */
314 TextOut(dc, myr.left, myr.top, &Symbol, 1);
315 /* restore previous settings */
316 SetTextColor(dc, clrsave);
317 SelectObject(dc, hOldFont);
318 SetBkMode(dc, bkmode);
319 DeleteObject(hFont);
320 return TRUE;
321 }
322
323 BOOL
324 MyDrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState, THEME *theme)
325 {
326 switch(uType)
327 {
328 case DFC_BUTTON:
329 return MyDrawFrameButton(hDC, rc, uState, theme);
330 case DFC_CAPTION:
331 return MyDrawFrameCaption(hDC, rc, uState, theme);
332 case DFC_SCROLL:
333 return MyDrawFrameScroll(hDC, rc, uState, theme);
334 }
335 return FALSE;
336 }
337
338 BOOL
339 MyDrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags, THEME *theme)
340 {
341 return MyIntDrawRectEdge(hDC, rc, edge, flags, theme);
342 }
343
344 VOID
345 MyDrawCaptionButtons(HDC hdc, LPRECT lpRect, BOOL bMinMax, int x, THEME *theme)
346 {
347 RECT rc3;
348 RECT rc4;
349 RECT rc5;
350
351 rc3.left = lpRect->right - 2 - x;
352 rc3.top = lpRect->top + 2;
353 rc3.right = lpRect->right - 2;
354 rc3.bottom = lpRect->bottom - 2;
355
356 MyDrawFrameControl(hdc, &rc3, DFC_CAPTION, DFCS_CAPTIONCLOSE, theme);
357
358 if (bMinMax)
359 {
360 rc4.left = rc3.left - x - 2;
361 rc4.top = rc3.top;
362 rc4.right = rc3.right - x - 2;
363 rc4.bottom = rc3.bottom;
364
365 MyDrawFrameControl(hdc, &rc4, DFC_CAPTION, DFCS_CAPTIONMAX, theme);
366
367 rc5.left = rc4.left - x;
368 rc5.top = rc4.top;
369 rc5.right = rc4.right - x;
370 rc5.bottom = rc4.bottom;
371
372 MyDrawFrameControl(hdc, &rc5, DFC_CAPTION, DFCS_CAPTIONMIN, theme);
373 }
374 }
375
376 VOID
377 MyDrawScrollbar(HDC hdc, LPRECT rc, HBRUSH hbrScrollbar, THEME *theme)
378 {
379 RECT rcTop;
380 RECT rcBottom;
381 RECT rcMiddle;
382 int width;
383
384 width = rc->right - rc->left;
385
386 rcTop.left = rc->left;
387 rcTop.right = rc->right;
388 rcTop.top = rc->top;
389 rcTop.bottom = rc->top + width;
390
391 rcMiddle.left = rc->left;
392 rcMiddle.right = rc->right;
393 rcMiddle.top = rc->top + width;
394 rcMiddle.bottom = rc->bottom - width;
395
396 rcBottom.left = rc->left;
397 rcBottom.right = rc->right;
398 rcBottom.top = rc->bottom - width;
399 rcBottom.bottom = rc->bottom;
400
401 MyDrawFrameControl(hdc, &rcTop, DFC_SCROLL, DFCS_SCROLLUP, theme);
402 MyDrawFrameControl(hdc, &rcBottom, DFC_SCROLL, DFCS_SCROLLDOWN, theme);
403
404 FillRect(hdc, &rcMiddle, hbrScrollbar);
405 }
406
407 /******************************************************************************/
408
409 BOOL
410 MyDrawCaptionTemp(HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont, HICON hIcon, LPCWSTR str, UINT uFlags, THEME *theme)
411 {
412 /* FIXME */
413 return DrawCaptionTemp(hwnd, hdc, rect, hFont, hIcon, str, uFlags);
414 }
415
416 /******************************************************************************/
417
418 DWORD
419 MyDrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font, THEME *theme)
420 {
421 /* FIXME */
422 return DrawMenuBarTemp(Wnd, DC, Rect, Menu, Font);
423 }