[UXTHEME] -Slightly improve the width of the caption buttons by scaling it based...
[reactos.git] / reactos / dll / win32 / uxtheme / nonclient.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS uxtheme.dll
4 * FILE: dll/win32/uxtheme/nonclient.c
5 * PURPOSE: uxtheme non client area management
6 * PROGRAMMER: Giannis Adamopoulos
7 */
8
9 #include "uxthemep.h"
10
11 HFONT hMenuFont = NULL;
12 HFONT hMenuFontBold = NULL;
13
14 void InitMenuFont(VOID)
15 {
16 NONCLIENTMETRICS ncm;
17
18 ncm.cbSize = sizeof(NONCLIENTMETRICS);
19
20 if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
21 {
22 return;
23 }
24
25 hMenuFont = CreateFontIndirect(&ncm.lfMenuFont);
26
27 ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
28 hMenuFontBold = CreateFontIndirect(&ncm.lfMenuFont);
29 }
30
31 static BOOL
32 IsWindowActive(HWND hWnd, DWORD ExStyle)
33 {
34 BOOL ret;
35
36 if (ExStyle & WS_EX_MDICHILD)
37 {
38 ret = IsChild(GetForegroundWindow(), hWnd);
39 if (ret)
40 ret = (hWnd == (HWND)SendMessageW(GetParent(hWnd), WM_MDIGETACTIVE, 0, 0));
41 }
42 else
43 {
44 ret = (GetForegroundWindow() == hWnd);
45 }
46
47 return ret;
48 }
49
50 static BOOL
51 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
52 {
53 if (Style & WS_MINIMIZE)
54 return TRUE;
55 if (ExStyle & WS_EX_DLGMODALFRAME)
56 return TRUE;
57 if (ExStyle & WS_EX_STATICEDGE)
58 return FALSE;
59 if (Style & WS_THICKFRAME)
60 return TRUE;
61 Style &= WS_CAPTION;
62 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
63 return TRUE;
64 return FALSE;
65 }
66
67 static HICON
68 UserGetWindowIcon(PDRAW_CONTEXT pcontext)
69 {
70 HICON hIcon = NULL;
71
72 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
73
74 if (!hIcon)
75 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
76
77 if (!hIcon)
78 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
79
80 if (!hIcon)
81 hIcon = (HICON)GetClassLong(pcontext->hWnd, GCL_HICONSM);
82
83 if (!hIcon)
84 hIcon = (HICON)GetClassLong(pcontext->hWnd, GCL_HICON);
85
86 // See also win32ss/user/ntuser/nonclient.c!NC_IconForWindow
87 if (!hIcon && !(pcontext->wi.dwExStyle & WS_EX_DLGMODALFRAME))
88 hIcon = LoadIconW(NULL, (LPCWSTR)IDI_WINLOGO);
89
90 return hIcon;
91 }
92
93 WCHAR *UserGetWindowCaption(HWND hwnd)
94 {
95 INT len = 512;
96 WCHAR *text;
97 text = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
98 if (text) InternalGetWindowText(hwnd, text, len);
99 return text;
100 }
101
102 static void
103 ThemeDrawTitle(PDRAW_CONTEXT context, RECT* prcCurrent)
104 {
105
106 }
107
108 HRESULT WINAPI ThemeDrawCaptionText(HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
109 LPCWSTR pszText, int iCharCount, DWORD dwTextFlags,
110 DWORD dwTextFlags2, const RECT *pRect, BOOL Active)
111 {
112 HRESULT hr;
113 HFONT hFont = NULL;
114 HGDIOBJ oldFont = NULL;
115 LOGFONTW logfont;
116 COLORREF textColor;
117 COLORREF oldTextColor;
118 int oldBkMode;
119 RECT rt;
120
121 hr = GetThemeSysFont(0,TMT_CAPTIONFONT,&logfont);
122
123 if(SUCCEEDED(hr)) {
124 hFont = CreateFontIndirectW(&logfont);
125 }
126 CopyRect(&rt, pRect);
127 if(hFont)
128 oldFont = SelectObject(hdc, hFont);
129
130 if(dwTextFlags2 & DTT_GRAYED)
131 textColor = GetSysColor(COLOR_GRAYTEXT);
132 else if (!Active)
133 textColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
134 else
135 textColor = GetSysColor(COLOR_CAPTIONTEXT);
136
137 oldTextColor = SetTextColor(hdc, textColor);
138 oldBkMode = SetBkMode(hdc, TRANSPARENT);
139 DrawThemeText(hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags, pRect);
140 SetBkMode(hdc, oldBkMode);
141 SetTextColor(hdc, oldTextColor);
142
143 if(hFont) {
144 SelectObject(hdc, oldFont);
145 DeleteObject(hFont);
146 }
147 return S_OK;
148 }
149
150 void
151 ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
152 HWND hWnd,
153 HRGN hRgn)
154 {
155 pcontext->wi.cbSize = sizeof(pcontext->wi);
156 GetWindowInfo(hWnd, &pcontext->wi);
157 pcontext->hWnd = hWnd;
158 pcontext->Active = IsWindowActive(hWnd, pcontext->wi.dwExStyle);
159 pcontext->theme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL, L"WINDOW");
160 pcontext->scrolltheme = MSSTYLES_OpenThemeClass(ActiveThemeFile, NULL, L"SCROLLBAR");
161
162 pcontext->CaptionHeight = pcontext->wi.cyWindowBorders;
163 pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
164
165 if(hRgn <= (HRGN)1)
166 {
167 hRgn = CreateRectRgnIndirect(&pcontext->wi.rcWindow);
168 }
169 pcontext->hRgn = hRgn;
170
171 pcontext->hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
172 }
173
174 void
175 ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext)
176 {
177 ReleaseDC(pcontext->hWnd ,pcontext->hDC);
178
179 CloseThemeData (pcontext->theme);
180 CloseThemeData (pcontext->scrolltheme);
181
182 if(pcontext->hRgn != NULL)
183 {
184 DeleteObject(pcontext->hRgn);
185 }
186 }
187
188 static void
189 ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext, int cx, int cy)
190 {
191 HBITMAP hbmp;
192
193 pcontext->hDCScreen = pcontext->hDC;
194 pcontext->hDC = CreateCompatibleDC(pcontext->hDCScreen);
195 hbmp = CreateCompatibleBitmap(pcontext->hDCScreen, cx, cy);
196 pcontext->hbmpOld = (HBITMAP)SelectObject(pcontext->hDC, hbmp);
197 }
198
199 static void
200 ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext, int x, int y, int cx, int cy)
201 {
202 HBITMAP hbmp;
203 BitBlt(pcontext->hDCScreen, 0, 0, cx, cy, pcontext->hDC, x, y, SRCCOPY);
204 hbmp = (HBITMAP) SelectObject(pcontext->hDC, pcontext->hbmpOld);
205 DeleteObject(pcontext->hDC);
206 DeleteObject(hbmp);
207
208 pcontext->hDC = pcontext->hDCScreen;
209 }
210
211 static void
212 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext,
213 RECT* prcCurrent,
214 CAPTIONBUTTON buttonId,
215 INT iStateId)
216 {
217 RECT rcPart;
218 INT ButtonWidth, ButtonHeight, iPartId;
219 SIZE ButtonSize;
220
221 switch(buttonId)
222 {
223 case CLOSEBUTTON:
224 iPartId = pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
225 break;
226
227 case MAXBUTTON:
228 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
229 {
230 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
231 return;
232 else
233 iStateId = BUTTON_DISABLED;
234 }
235
236 iPartId = pcontext->wi.dwStyle & WS_MAXIMIZE ? WP_RESTOREBUTTON : WP_MAXBUTTON;
237 break;
238
239 case MINBUTTON:
240 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX))
241 {
242 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX))
243 return;
244 else
245 iStateId = BUTTON_DISABLED;
246 }
247
248 iPartId = WP_MINBUTTON;
249 break;
250
251 default:
252 //FIXME: Implement Help Button
253 return;
254 }
255
256 GetThemePartSize(pcontext->theme, pcontext->hDC, iPartId, 0, NULL, TS_MIN, &ButtonSize);
257
258 ButtonHeight = GetSystemMetrics( pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMSIZE : SM_CYSIZE);
259 ButtonWidth = MulDiv(ButtonSize.cx, ButtonHeight, ButtonSize.cy);
260
261 ButtonHeight -= 4;
262 ButtonWidth -= 4;
263
264 /* Calculate the position */
265 rcPart.top = prcCurrent->top;
266 rcPart.right = prcCurrent->right;
267 rcPart.bottom = rcPart.top + ButtonHeight ;
268 rcPart.left = rcPart.right - ButtonWidth ;
269 prcCurrent->right -= ButtonWidth + BUTTON_GAP_SIZE;
270
271 DrawThemeBackground(pcontext->theme, pcontext->hDC, iPartId, iStateId, &rcPart, NULL);
272 }
273
274 static DWORD
275 ThemeGetButtonState(DWORD htCurrect, DWORD htHot, DWORD htDown, BOOL Active)
276 {
277 if (htHot == htCurrect)
278 return BUTTON_HOT;
279 if (!Active)
280 return BUTTON_INACTIVE;
281 if (htDown == htCurrect)
282 return BUTTON_PRESSED;
283
284 return BUTTON_NORMAL;
285 }
286
287 /* Used only from mouse event handlers */
288 static void
289 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext, DWORD htHot, DWORD htDown)
290 {
291 RECT rcCurrent;
292
293 /* Calculate the area of the caption */
294 rcCurrent.top = rcCurrent.left = 0;
295 rcCurrent.right = pcontext->wi.rcWindow.right - pcontext->wi.rcWindow.left;
296 rcCurrent.bottom = pcontext->CaptionHeight;
297
298 /* Add a padding around the objects of the caption */
299 InflateRect(&rcCurrent, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE,
300 -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE);
301
302 /* Draw the buttons */
303 ThemeDrawCaptionButton(pcontext, &rcCurrent, CLOSEBUTTON,
304 ThemeGetButtonState(HTCLOSE, htHot, htDown, pcontext->Active));
305 ThemeDrawCaptionButton(pcontext, &rcCurrent, MAXBUTTON,
306 ThemeGetButtonState(HTMAXBUTTON, htHot, htDown, pcontext->Active));
307 ThemeDrawCaptionButton(pcontext, &rcCurrent, MINBUTTON,
308 ThemeGetButtonState(HTMINBUTTON, htHot, htDown, pcontext->Active));
309 ThemeDrawCaptionButton(pcontext, &rcCurrent, HELPBUTTON,
310 ThemeGetButtonState(HTHELP, htHot, htDown, pcontext->Active));
311 }
312
313 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
314 static void
315 ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
316 {
317 RECT rcPart;
318 int iPart, iState;
319 HICON hIcon;
320 WCHAR *CaptionText;
321
322 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
323 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
324 if ((pcontext->wi.dwStyle & WS_SYSMENU) && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW))
325 hIcon = UserGetWindowIcon(pcontext);
326 else
327 hIcon = NULL;
328
329 CaptionText = UserGetWindowCaption(pcontext->hWnd);
330
331 /* Get the caption part and state id */
332 if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)
333 iPart = WP_SMALLCAPTION;
334 else if (pcontext->wi.dwStyle & WS_MAXIMIZE)
335 iPart = WP_MAXCAPTION;
336 else
337 iPart = WP_CAPTION;
338
339 iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
340
341 /* Draw the caption background */
342 rcPart = *prcCurrent;
343 rcPart.bottom = rcPart.top + pcontext->CaptionHeight;
344 prcCurrent->top = rcPart.bottom;
345 DrawThemeBackground(pcontext->theme, pcontext->hDC,iPart,iState,&rcPart,NULL);
346
347 /* Add a padding around the objects of the caption */
348 InflateRect(&rcPart, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE,
349 -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE);
350
351 /* Draw the caption buttons */
352 if (pcontext->wi.dwStyle & WS_SYSMENU)
353 {
354 iState = pcontext->Active ? BUTTON_NORMAL : BUTTON_INACTIVE;
355
356 ThemeDrawCaptionButton(pcontext, &rcPart, CLOSEBUTTON, iState);
357 ThemeDrawCaptionButton(pcontext, &rcPart, MAXBUTTON, iState);
358 ThemeDrawCaptionButton(pcontext, &rcPart, MINBUTTON, iState);
359 ThemeDrawCaptionButton(pcontext, &rcPart, HELPBUTTON, iState);
360 }
361
362 rcPart.top += 3 ;
363
364 /* Draw the icon */
365 if (hIcon)
366 {
367 int IconHeight = GetSystemMetrics(SM_CYSMICON);
368 int IconWidth = GetSystemMetrics(SM_CXSMICON);
369 DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, IconHeight, 0, NULL, DI_NORMAL);
370 rcPart.left += IconWidth + 4;
371 }
372
373 rcPart.right -= 4;
374
375 /* Draw the caption */
376 if (CaptionText)
377 {
378 /* FIXME: Use DrawThemeTextEx */
379 ThemeDrawCaptionText(pcontext->theme,
380 pcontext->hDC,
381 iPart,
382 iState,
383 CaptionText,
384 lstrlenW(CaptionText),
385 DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS,
386 0,
387 &rcPart,
388 pcontext->Active);
389 HeapFree(GetProcessHeap(), 0, CaptionText);
390 }
391 }
392
393 static void
394 ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
395 {
396 RECT rcPart;
397 int iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
398
399 /* Draw the bottom border */
400 rcPart = *prcCurrent;
401 rcPart.top = rcPart.bottom - pcontext->wi.cyWindowBorders;
402 prcCurrent->bottom = rcPart.top;
403 DrawThemeBackground(pcontext->theme, pcontext->hDC, WP_FRAMEBOTTOM, iState, &rcPart, NULL);
404
405 /* Draw the left border */
406 rcPart = *prcCurrent;
407 rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ;
408 prcCurrent->left = rcPart.right;
409 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL);
410
411 /* Draw the right border */
412 rcPart = *prcCurrent;
413 rcPart.left = rcPart.right - pcontext->wi.cxWindowBorders;
414 prcCurrent->right = rcPart.left;
415 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMERIGHT, iState, &rcPart, NULL);
416 }
417
418 static void
419 DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
420 {
421 /* Draw outer edge */
422 if (UserHasWindowEdge(context->wi.dwStyle, context->wi.dwExStyle))
423 {
424 DrawEdge(context->hDC, prcCurrent, EDGE_RAISED, BF_RECT | BF_ADJUST);
425 }
426 else if (context->wi.dwExStyle & WS_EX_STATICEDGE)
427 {
428 DrawEdge(context->hDC, prcCurrent, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
429 }
430
431 /* Firstly the "thick" frame */
432 if ((context->wi.dwStyle & WS_THICKFRAME) && !(context->wi.dwStyle & WS_MINIMIZE))
433 {
434 INT Width =
435 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
436 GetSystemMetrics(SM_CXBORDER);
437 INT Height =
438 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
439 GetSystemMetrics(SM_CYBORDER);
440
441 SelectObject(context->hDC, GetSysColorBrush(
442 context->Active ? COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER));
443
444 /* Draw frame */
445 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
446 prcCurrent->right - prcCurrent->left, Height, PATCOPY);
447 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
448 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
449 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1,
450 prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
451 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top,
452 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
453
454 InflateRect(prcCurrent, -Width, -Height);
455 }
456
457 /* Now the other bit of the frame */
458 if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || (context->wi.dwExStyle & WS_EX_DLGMODALFRAME))
459 {
460 INT Width = GetSystemMetrics(SM_CXBORDER);
461 INT Height = GetSystemMetrics(SM_CYBORDER);
462
463 SelectObject(context->hDC, GetSysColorBrush(
464 (context->wi.dwExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
465 (context->wi.dwExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
466 (context->wi.dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
467 COLOR_WINDOWFRAME));
468
469 /* Draw frame */
470 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
471 prcCurrent->right - prcCurrent->left, Height, PATCOPY);
472 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
473 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
474 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1,
475 prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
476 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top,
477 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
478
479 InflateRect(prcCurrent, -Width, -Height);
480 }
481
482 if (context->wi.dwExStyle & WS_EX_CLIENTEDGE)
483 {
484 DrawEdge(context->hDC, prcCurrent, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
485 }
486 }
487
488 static void
489 ThemeDrawMenuItem(PDRAW_CONTEXT pcontext, HMENU Menu, int imenu)
490 {
491 PWCHAR Text;
492 BOOL flat_menu = FALSE;
493 MENUITEMINFOW Item;
494 RECT Rect,rcCalc;
495 WCHAR wstrItemText[20];
496 register int i = 0;
497 HFONT FontOld = NULL;
498 UINT uFormat = DT_CENTER | DT_VCENTER | DT_SINGLELINE;
499
500 Item.cbSize = sizeof(MENUITEMINFOW);
501 Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
502 Item.dwTypeData = wstrItemText;
503 Item.cch = 20;
504 if (!GetMenuItemInfoW(Menu, imenu, TRUE, &Item))
505 return;
506
507 if(Item.fType & MF_SEPARATOR)
508 return;
509
510 if(Item.cch >= 20)
511 {
512 Item.cch++;
513 Item.dwTypeData = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, Item.cch * sizeof(WCHAR));
514 Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
515 GetMenuItemInfoW(Menu, imenu, TRUE, &Item);
516 }
517
518 if(Item.cch == 0)
519 return;
520
521 flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
522
523 GetMenuItemRect(pcontext->hWnd, Menu, imenu, &Rect);
524
525 OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
526
527 SetBkColor(pcontext->hDC, GetSysColor(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
528 SetTextColor(pcontext->hDC, GetSysColor(Item.fState & MF_GRAYED ? COLOR_GRAYTEXT : COLOR_MENUTEXT));
529
530 if (0 != (Item.fState & MFS_DEFAULT))
531 {
532 FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFontBold);
533 }
534
535 Rect.left += MENU_BAR_ITEMS_SPACE / 2;
536 Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
537
538 Text = (PWCHAR) Item.dwTypeData;
539 if(Text)
540 {
541 for (i = 0; L'\0' != Text[i]; i++)
542 {
543 if (L'\t' == Text[i] || L'\b' == Text[i])
544 {
545 break;
546 }
547 }
548 }
549
550 SetBkMode(pcontext->hDC, OPAQUE);
551
552 if (0 != (Item.fState & MF_GRAYED))
553 {
554 if (0 == (Item.fState & MF_HILITE))
555 {
556 ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
557 SetTextColor(pcontext->hDC, RGB(0xff, 0xff, 0xff));
558 DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
559 --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
560 }
561 SetTextColor(pcontext->hDC, RGB(0x80, 0x80, 0x80));
562 SetBkMode(pcontext->hDC, TRANSPARENT);
563 }
564
565 DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
566
567 /* Exclude from the clip region the area drawn by DrawText */
568 SetRect(&rcCalc, 0,0,0,0);
569 DrawTextW(pcontext->hDC, Text, i, &rcCalc, uFormat | DT_CALCRECT);
570 InflateRect( &Rect, 0, -(rcCalc.bottom+1)/2);
571 ExcludeClipRect(pcontext->hDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
572
573 if (NULL != FontOld)
574 {
575 SelectObject(pcontext->hDC, FontOld);
576 }
577 }
578
579 void WINAPI
580 ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, PRECT prcCurrent)
581 {
582 HMENU Menu;
583 MENUBARINFO MenuBarInfo;
584 int i;
585 HFONT FontOld = NULL;
586 BOOL flat_menu;
587 RECT Rect;
588 HPEN oldPen ;
589
590 if (!hMenuFont)
591 InitMenuFont();
592
593 flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
594
595 MenuBarInfo.cbSize = sizeof(MENUBARINFO);
596 if (! GetMenuBarInfo(pcontext->hWnd, OBJID_MENU, 0, &MenuBarInfo))
597 return;
598
599 Menu = GetMenu(pcontext->hWnd);
600 if (GetMenuItemCount(Menu) == 0)
601 return;
602
603 Rect = MenuBarInfo.rcBar;
604 OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
605
606 /* Draw a line under the menu */
607 oldPen = (HPEN)SelectObject(pcontext->hDC, GetStockObject(DC_PEN));
608 SetDCPenColor(pcontext->hDC, GetSysColor(COLOR_3DFACE));
609 MoveToEx(pcontext->hDC, Rect.left, Rect.bottom, NULL);
610 LineTo(pcontext->hDC, Rect.right, Rect.bottom);
611 SelectObject(pcontext->hDC, oldPen);
612
613 /* Draw menu items */
614 FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFont);
615
616 for (i = 0; i < GetMenuItemCount(Menu); i++)
617 {
618 ThemeDrawMenuItem(pcontext, Menu, i);
619 }
620
621 SelectObject(pcontext->hDC, FontOld);
622
623 /* Fill the menu background area that isn't painted yet */
624 FillRect(pcontext->hDC, &Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
625 }
626
627 static void
628 ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent, BOOL bDoDoubleBuffering)
629 {
630 if(!(pcontext->wi.dwStyle & WS_VISIBLE))
631 return;
632
633 if(pcontext->wi.dwStyle & WS_MINIMIZE)
634 {
635 ThemeDrawTitle(pcontext, prcCurrent);
636 return;
637 }
638
639 if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION)
640 {
641 if (bDoDoubleBuffering)
642 ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight);
643 ThemeDrawCaption(pcontext, prcCurrent);
644 if (bDoDoubleBuffering)
645 ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight);
646 ThemeDrawBorders(pcontext, prcCurrent);
647 }
648 else
649 {
650 DrawClassicFrame(pcontext, prcCurrent);
651 }
652
653 if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle))
654 ThemeDrawMenuBar(pcontext, prcCurrent);
655
656 if(pcontext->wi.dwStyle & WS_HSCROLL)
657 ThemeDrawScrollBar(pcontext, SB_HORZ , NULL);
658
659 if(pcontext->wi.dwStyle & WS_VSCROLL)
660 ThemeDrawScrollBar(pcontext, SB_VERT, NULL);
661 }
662
663 /*
664 * Message handlers
665 */
666
667 static LRESULT
668 ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)
669 {
670 DRAW_CONTEXT context;
671 RECT rcCurrent;
672
673 ThemeInitDrawContext(&context, hWnd, hRgn);
674
675 rcCurrent = context.wi.rcWindow;
676 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
677
678 ThemePaintWindow(&context, &rcCurrent, TRUE);
679 ThemeCleanupDrawContext(&context);
680
681 return 0;
682 }
683
684 static LRESULT
685 ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt)
686 {
687 DRAW_CONTEXT context;
688 TRACKMOUSEEVENT tme;
689 DWORD style;
690 PWND_CONTEXT pcontext;
691
692 /* First of all check if we have something to do here */
693 style = GetWindowLongW(hWnd, GWL_STYLE);
694 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
695 return 0;
696
697 /* Get theme data for this window */
698 pcontext = ThemeGetWndContext(hWnd);
699 if (pcontext == NULL)
700 return 0;
701
702 /* Begin tracking in the non client area if we are not tracking yet */
703 tme.cbSize = sizeof(TRACKMOUSEEVENT);
704 tme.dwFlags = TME_QUERY;
705 tme.hwndTrack = hWnd;
706 TrackMouseEvent(&tme);
707 if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
708 {
709 tme.hwndTrack = hWnd;
710 tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
711 TrackMouseEvent(&tme);
712 }
713
714 ThemeInitDrawContext(&context, hWnd, 0);
715 if (context.wi.dwStyle & WS_SYSMENU)
716 {
717 if (HT_ISBUTTON(ht) || HT_ISBUTTON(pcontext->lastHitTest))
718 ThemeDrawCaptionButtons(&context, ht, 0);
719 }
720
721 if (context.wi.dwStyle & WS_HSCROLL)
722 {
723 if (ht == HTHSCROLL || pcontext->lastHitTest == HTHSCROLL)
724 ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
725 }
726
727 if (context.wi.dwStyle & WS_VSCROLL)
728 {
729 if (ht == HTVSCROLL || pcontext->lastHitTest == HTVSCROLL)
730 ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
731 }
732 ThemeCleanupDrawContext(&context);
733
734 pcontext->lastHitTest = ht;
735
736 return 0;
737 }
738
739 static LRESULT
740 ThemeHandleNcMouseLeave(HWND hWnd)
741 {
742 DRAW_CONTEXT context;
743 DWORD style;
744 PWND_CONTEXT pWndContext;
745
746 /* First of all check if we have something to do here */
747 style = GetWindowLongW(hWnd, GWL_STYLE);
748 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
749 return 0;
750
751 /* Get theme data for this window */
752 pWndContext = ThemeGetWndContext(hWnd);
753 if (pWndContext == NULL)
754 return 0;
755
756 ThemeInitDrawContext(&context, hWnd, 0);
757 if (context.wi.dwStyle & WS_SYSMENU && HT_ISBUTTON(pWndContext->lastHitTest))
758 ThemeDrawCaptionButtons(&context, 0, 0);
759
760 if (context.wi.dwStyle & WS_HSCROLL && pWndContext->lastHitTest == HTHSCROLL)
761 ThemeDrawScrollBar(&context, SB_HORZ, NULL);
762
763 if (context.wi.dwStyle & WS_VSCROLL && pWndContext->lastHitTest == HTVSCROLL)
764 ThemeDrawScrollBar(&context, SB_VERT, NULL);
765
766 ThemeCleanupDrawContext(&context);
767
768 pWndContext->lastHitTest = HTNOWHERE;
769
770 return 0;
771 }
772
773 static VOID
774 ThemeHandleButton(HWND hWnd, WPARAM wParam)
775 {
776 MSG Msg;
777 BOOL Pressed = TRUE;
778 WPARAM SCMsg, ht;
779 ULONG Style;
780 DRAW_CONTEXT context;
781 PWND_CONTEXT pWndContext;
782
783 Style = GetWindowLongW(hWnd, GWL_STYLE);
784 if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU)))
785 return ;
786
787 switch (wParam)
788 {
789 case HTCLOSE:
790 SCMsg = SC_CLOSE;
791 break;
792 case HTMINBUTTON:
793 if (!(Style & WS_MINIMIZEBOX))
794 return;
795 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
796 break;
797 case HTMAXBUTTON:
798 if (!(Style & WS_MAXIMIZEBOX))
799 return;
800 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
801 break;
802 default :
803 return;
804 }
805
806 /* Get theme data for this window */
807 pWndContext = ThemeGetWndContext(hWnd);
808 if (pWndContext == NULL)
809 return;
810
811 ThemeInitDrawContext(&context, hWnd, 0);
812 ThemeDrawCaptionButtons(&context, 0, wParam);
813 pWndContext->lastHitTest = wParam;
814
815 SetCapture(hWnd);
816
817 for (;;)
818 {
819 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
820 break;
821
822 if (Msg.message == WM_LBUTTONUP)
823 break;
824
825 if (Msg.message != WM_MOUSEMOVE)
826 continue;
827
828 ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y));
829 Pressed = (ht == wParam);
830
831 /* Only draw the buttons if the hit test changed */
832 if (ht != pWndContext->lastHitTest &&
833 (HT_ISBUTTON(ht) || HT_ISBUTTON(pWndContext->lastHitTest)))
834 {
835 ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
836 pWndContext->lastHitTest = ht;
837 }
838 }
839
840 ThemeDrawCaptionButtons(&context, ht, 0);
841 ThemeCleanupDrawContext(&context);
842
843 ReleaseCapture();
844
845 if (Pressed)
846 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
847 }
848
849
850 static LRESULT
851 DefWndNCHitTest(HWND hWnd, POINT Point)
852 {
853 RECT WindowRect;
854 POINT ClientPoint;
855 WINDOWINFO wi;
856
857 wi.cbSize = sizeof(wi);
858 GetWindowInfo(hWnd, &wi);
859
860 if (!PtInRect(&wi.rcWindow, Point))
861 {
862 return HTNOWHERE;
863 }
864 WindowRect = wi.rcWindow;
865
866 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle))
867 {
868 LONG XSize, YSize;
869
870 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders);
871 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
872 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
873 if (!PtInRect(&WindowRect, Point))
874 {
875 BOOL ThickFrame;
876
877 ThickFrame = (wi.dwStyle & WS_THICKFRAME);
878 if (Point.y < WindowRect.top)
879 {
880 if(wi.dwStyle & WS_MINIMIZE)
881 return HTCAPTION;
882 if(!ThickFrame)
883 return HTBORDER;
884 if (Point.x < (WindowRect.left + XSize))
885 return HTTOPLEFT;
886 if (Point.x >= (WindowRect.right - XSize))
887 return HTTOPRIGHT;
888 return HTTOP;
889 }
890 if (Point.y >= WindowRect.bottom)
891 {
892 if(wi.dwStyle & WS_MINIMIZE)
893 return HTCAPTION;
894 if(!ThickFrame)
895 return HTBORDER;
896 if (Point.x < (WindowRect.left + XSize))
897 return HTBOTTOMLEFT;
898 if (Point.x >= (WindowRect.right - XSize))
899 return HTBOTTOMRIGHT;
900 return HTBOTTOM;
901 }
902 if (Point.x < WindowRect.left)
903 {
904 if(wi.dwStyle & WS_MINIMIZE)
905 return HTCAPTION;
906 if(!ThickFrame)
907 return HTBORDER;
908 if (Point.y < (WindowRect.top + YSize))
909 return HTTOPLEFT;
910 if (Point.y >= (WindowRect.bottom - YSize))
911 return HTBOTTOMLEFT;
912 return HTLEFT;
913 }
914 if (Point.x >= WindowRect.right)
915 {
916 if(wi.dwStyle & WS_MINIMIZE)
917 return HTCAPTION;
918 if(!ThickFrame)
919 return HTBORDER;
920 if (Point.y < (WindowRect.top + YSize))
921 return HTTOPRIGHT;
922 if (Point.y >= (WindowRect.bottom - YSize))
923 return HTBOTTOMRIGHT;
924 return HTRIGHT;
925 }
926 }
927 }
928 else
929 {
930 if (wi.dwExStyle & WS_EX_STATICEDGE)
931 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
932 -GetSystemMetrics(SM_CYBORDER));
933 if (!PtInRect(&WindowRect, Point))
934 return HTBORDER;
935 }
936
937 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION)
938 {
939 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
940 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
941 else
942 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
943
944 if (!PtInRect(&WindowRect, Point))
945 {
946 INT ButtonWidth;
947
948 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
949 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE);
950 else
951 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
952
953 ButtonWidth -= 4;
954 ButtonWidth += BUTTON_GAP_SIZE;
955
956 if (wi.dwStyle & WS_SYSMENU)
957 {
958 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
959 {
960 WindowRect.right -= ButtonWidth;
961 }
962 else
963 {
964 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
965 // FIXME: The real test should check whether there is
966 // an icon for the system window, and if so, do the
967 // rect.left increase.
968 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
969 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
970 // the test better.
971 WindowRect.left += ButtonWidth;
972 WindowRect.right -= ButtonWidth;
973 }
974 }
975 if (Point.x < WindowRect.left)
976 return HTSYSMENU;
977 if (WindowRect.right <= Point.x)
978 return HTCLOSE;
979 if (wi.dwStyle & WS_MAXIMIZEBOX || wi.dwStyle & WS_MINIMIZEBOX)
980 WindowRect.right -= ButtonWidth;
981 if (Point.x >= WindowRect.right)
982 return HTMAXBUTTON;
983 if (wi.dwStyle & WS_MINIMIZEBOX)
984 WindowRect.right -= ButtonWidth;
985 if (Point.x >= WindowRect.right)
986 return HTMINBUTTON;
987 return HTCAPTION;
988 }
989 }
990
991 if(!(wi.dwStyle & WS_MINIMIZE))
992 {
993 HMENU menu;
994
995 ClientPoint = Point;
996 ScreenToClient(hWnd, &ClientPoint);
997 GetClientRect(hWnd, &wi.rcClient);
998
999 if (PtInRect(&wi.rcClient, ClientPoint))
1000 {
1001 return HTCLIENT;
1002 }
1003
1004 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD))
1005 {
1006 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
1007 return HTMENU;
1008 }
1009
1010 if (wi.dwExStyle & WS_EX_CLIENTEDGE)
1011 {
1012 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
1013 -2 * GetSystemMetrics(SM_CYBORDER));
1014 }
1015
1016 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) &&
1017 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
1018 {
1019 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
1020 HWND Parent = GetParent(hWnd);
1021
1022 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
1023 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1024 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1025 else
1026 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1027 if (PtInRect(&TempRect, Point))
1028 return HTVSCROLL;
1029
1030 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
1031 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1032 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
1033 else
1034 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
1035 if (PtInRect(&TempRect2, Point))
1036 return HTHSCROLL;
1037
1038 TempRect.top = TempRect2.top;
1039 TempRect.bottom = TempRect2.bottom;
1040 if(Parent)
1041 GetClientRect(Parent, &ParentRect);
1042 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle,
1043 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect))
1044 {
1045 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1046 return HTBOTTOMLEFT;
1047 else
1048 return HTBOTTOMRIGHT;
1049 }
1050 }
1051 else
1052 {
1053 if (wi.dwStyle & WS_VSCROLL)
1054 {
1055 RECT TempRect = WindowRect;
1056
1057 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1058 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1059 else
1060 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1061 if (PtInRect(&TempRect, Point))
1062 return HTVSCROLL;
1063 }
1064 else if (wi.dwStyle & WS_HSCROLL)
1065 {
1066 RECT TempRect = WindowRect;
1067 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
1068 if (PtInRect(&TempRect, Point))
1069 return HTHSCROLL;
1070 }
1071 }
1072 }
1073
1074 return HTNOWHERE;
1075 }
1076
1077 LRESULT CALLBACK
1078 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc)
1079 {
1080 switch(Msg)
1081 {
1082 case WM_NCPAINT:
1083 return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
1084 //
1085 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1086 //
1087 case WM_NCUAHDRAWCAPTION:
1088 //
1089 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1090 //
1091 case WM_NCUAHDRAWFRAME:
1092 case WM_NCACTIVATE:
1093
1094 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) != WS_CAPTION)
1095 return TRUE;
1096
1097 ThemeHandleNCPaint(hWnd, (HRGN)1);
1098 return TRUE;
1099 case WM_NCMOUSEMOVE:
1100 {
1101 POINT Point;
1102 Point.x = GET_X_LPARAM(lParam);
1103 Point.y = GET_Y_LPARAM(lParam);
1104 return ThemeHandleNcMouseMove(hWnd, wParam, &Point);
1105 }
1106 case WM_NCMOUSELEAVE:
1107 return ThemeHandleNcMouseLeave(hWnd);
1108 case WM_NCLBUTTONDOWN:
1109 switch (wParam)
1110 {
1111 case HTMINBUTTON:
1112 case HTMAXBUTTON:
1113 case HTCLOSE:
1114 {
1115 ThemeHandleButton(hWnd, wParam);
1116 return 0;
1117 }
1118 default:
1119 return DefWndProc(hWnd, Msg, wParam, lParam);
1120 }
1121 case WM_NCHITTEST:
1122 {
1123 POINT Point;
1124 Point.x = GET_X_LPARAM(lParam);
1125 Point.y = GET_Y_LPARAM(lParam);
1126 return DefWndNCHitTest(hWnd, Point);
1127 }
1128 case WM_SYSCOMMAND:
1129 {
1130 if((wParam & 0xfff0) == SC_VSCROLL ||
1131 (wParam & 0xfff0) == SC_HSCROLL)
1132 {
1133 POINT Pt;
1134 Pt.x = (short)LOWORD(lParam);
1135 Pt.y = (short)HIWORD(lParam);
1136 NC_TrackScrollBar(hWnd, wParam, Pt);
1137 return 0;
1138 }
1139 else
1140 {
1141 return DefWndProc(hWnd, Msg, wParam, lParam);
1142 }
1143 }
1144 default:
1145 return DefWndProc(hWnd, Msg, wParam, lParam);
1146 }
1147 }
1148
1149 HRESULT WINAPI DrawNCPreview(HDC hDC,
1150 DWORD DNCP_Flag,
1151 LPRECT prcPreview,
1152 LPCWSTR pszThemeFileName,
1153 LPCWSTR pszColorName,
1154 LPCWSTR pszSizeName,
1155 PNONCLIENTMETRICSW pncMetrics,
1156 COLORREF* lpaRgbValues)
1157 {
1158 WNDCLASSEXW DummyPreviewWindowClass;
1159 HWND hwndDummy;
1160 HRESULT hres;
1161 HTHEMEFILE hThemeFile;
1162 DRAW_CONTEXT context;
1163 RECT rcCurrent;
1164
1165 /* FIXME: We also need to implement drawing the rest of the preview windows
1166 * and make use of the ncmetrics and colors passed as parameters */
1167
1168 /* Create a dummy window that will be used to trick the paint funtions */
1169 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass));
1170 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass);
1171 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass";
1172 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1173 DummyPreviewWindowClass.hInstance = hDllInst;
1174 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW;
1175 if (!RegisterClassExW(&DummyPreviewWindowClass))
1176 return E_FAIL;
1177
1178 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL);
1179 if (!hwndDummy)
1180 return E_FAIL;
1181
1182 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0);
1183 if (FAILED(hres))
1184 return hres;
1185
1186 /* Initialize the special draw context for the preview */
1187 context.hDC = hDC;
1188 context.hWnd = hwndDummy;
1189 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0);
1190 if (!context.theme)
1191 return E_FAIL;
1192 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0);
1193 if (!context.theme)
1194 return E_FAIL;
1195 context.Active = TRUE;
1196 context.wi.cbSize = sizeof(context.wi);
1197 if (!GetWindowInfo(hwndDummy, &context.wi))
1198 return E_FAIL;
1199 context.wi.dwStyle |= WS_VISIBLE;
1200 context.CaptionHeight = context.wi.cyWindowBorders;
1201 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
1202 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow);
1203
1204 /* Paint the window on the preview hDC */
1205 rcCurrent = context.wi.rcWindow;
1206 ThemePaintWindow(&context, &rcCurrent, FALSE);
1207 context.hDC = NULL;
1208 ThemeCleanupDrawContext(&context);
1209
1210 /* Cleanup */
1211 DestroyWindow(hwndDummy);
1212 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst);
1213
1214 return S_OK;
1215 }