[UXTHEME} -Fix usage of uninitialized variable. CORE-11204
[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 ht = wParam;
818
819 for (;;)
820 {
821 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
822 break;
823
824 if (Msg.message == WM_LBUTTONUP)
825 break;
826
827 if (Msg.message != WM_MOUSEMOVE)
828 continue;
829
830 ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y));
831 Pressed = (ht == wParam);
832
833 /* Only draw the buttons if the hit test changed */
834 if (ht != pWndContext->lastHitTest &&
835 (HT_ISBUTTON(ht) || HT_ISBUTTON(pWndContext->lastHitTest)))
836 {
837 ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
838 pWndContext->lastHitTest = ht;
839 }
840 }
841
842 ThemeDrawCaptionButtons(&context, ht, 0);
843 ThemeCleanupDrawContext(&context);
844
845 ReleaseCapture();
846
847 if (Pressed)
848 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
849 }
850
851
852 static LRESULT
853 DefWndNCHitTest(HWND hWnd, POINT Point)
854 {
855 RECT WindowRect;
856 POINT ClientPoint;
857 WINDOWINFO wi;
858
859 wi.cbSize = sizeof(wi);
860 GetWindowInfo(hWnd, &wi);
861
862 if (!PtInRect(&wi.rcWindow, Point))
863 {
864 return HTNOWHERE;
865 }
866 WindowRect = wi.rcWindow;
867
868 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle))
869 {
870 LONG XSize, YSize;
871
872 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders);
873 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
874 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
875 if (!PtInRect(&WindowRect, Point))
876 {
877 BOOL ThickFrame;
878
879 ThickFrame = (wi.dwStyle & WS_THICKFRAME);
880 if (Point.y < WindowRect.top)
881 {
882 if(wi.dwStyle & WS_MINIMIZE)
883 return HTCAPTION;
884 if(!ThickFrame)
885 return HTBORDER;
886 if (Point.x < (WindowRect.left + XSize))
887 return HTTOPLEFT;
888 if (Point.x >= (WindowRect.right - XSize))
889 return HTTOPRIGHT;
890 return HTTOP;
891 }
892 if (Point.y >= WindowRect.bottom)
893 {
894 if(wi.dwStyle & WS_MINIMIZE)
895 return HTCAPTION;
896 if(!ThickFrame)
897 return HTBORDER;
898 if (Point.x < (WindowRect.left + XSize))
899 return HTBOTTOMLEFT;
900 if (Point.x >= (WindowRect.right - XSize))
901 return HTBOTTOMRIGHT;
902 return HTBOTTOM;
903 }
904 if (Point.x < WindowRect.left)
905 {
906 if(wi.dwStyle & WS_MINIMIZE)
907 return HTCAPTION;
908 if(!ThickFrame)
909 return HTBORDER;
910 if (Point.y < (WindowRect.top + YSize))
911 return HTTOPLEFT;
912 if (Point.y >= (WindowRect.bottom - YSize))
913 return HTBOTTOMLEFT;
914 return HTLEFT;
915 }
916 if (Point.x >= WindowRect.right)
917 {
918 if(wi.dwStyle & WS_MINIMIZE)
919 return HTCAPTION;
920 if(!ThickFrame)
921 return HTBORDER;
922 if (Point.y < (WindowRect.top + YSize))
923 return HTTOPRIGHT;
924 if (Point.y >= (WindowRect.bottom - YSize))
925 return HTBOTTOMRIGHT;
926 return HTRIGHT;
927 }
928 }
929 }
930 else
931 {
932 if (wi.dwExStyle & WS_EX_STATICEDGE)
933 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
934 -GetSystemMetrics(SM_CYBORDER));
935 if (!PtInRect(&WindowRect, Point))
936 return HTBORDER;
937 }
938
939 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION)
940 {
941 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
942 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
943 else
944 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
945
946 if (!PtInRect(&WindowRect, Point))
947 {
948 INT ButtonWidth;
949
950 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
951 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE);
952 else
953 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
954
955 ButtonWidth -= 4;
956 ButtonWidth += BUTTON_GAP_SIZE;
957
958 if (wi.dwStyle & WS_SYSMENU)
959 {
960 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
961 {
962 WindowRect.right -= ButtonWidth;
963 }
964 else
965 {
966 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
967 // FIXME: The real test should check whether there is
968 // an icon for the system window, and if so, do the
969 // rect.left increase.
970 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
971 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
972 // the test better.
973 WindowRect.left += ButtonWidth;
974 WindowRect.right -= ButtonWidth;
975 }
976 }
977 if (Point.x < WindowRect.left)
978 return HTSYSMENU;
979 if (WindowRect.right <= Point.x)
980 return HTCLOSE;
981 if (wi.dwStyle & WS_MAXIMIZEBOX || wi.dwStyle & WS_MINIMIZEBOX)
982 WindowRect.right -= ButtonWidth;
983 if (Point.x >= WindowRect.right)
984 return HTMAXBUTTON;
985 if (wi.dwStyle & WS_MINIMIZEBOX)
986 WindowRect.right -= ButtonWidth;
987 if (Point.x >= WindowRect.right)
988 return HTMINBUTTON;
989 return HTCAPTION;
990 }
991 }
992
993 if(!(wi.dwStyle & WS_MINIMIZE))
994 {
995 HMENU menu;
996
997 ClientPoint = Point;
998 ScreenToClient(hWnd, &ClientPoint);
999 GetClientRect(hWnd, &wi.rcClient);
1000
1001 if (PtInRect(&wi.rcClient, ClientPoint))
1002 {
1003 return HTCLIENT;
1004 }
1005
1006 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD))
1007 {
1008 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
1009 return HTMENU;
1010 }
1011
1012 if (wi.dwExStyle & WS_EX_CLIENTEDGE)
1013 {
1014 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
1015 -2 * GetSystemMetrics(SM_CYBORDER));
1016 }
1017
1018 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) &&
1019 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
1020 {
1021 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
1022 HWND Parent = GetParent(hWnd);
1023
1024 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
1025 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1026 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1027 else
1028 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1029 if (PtInRect(&TempRect, Point))
1030 return HTVSCROLL;
1031
1032 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
1033 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1034 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
1035 else
1036 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
1037 if (PtInRect(&TempRect2, Point))
1038 return HTHSCROLL;
1039
1040 TempRect.top = TempRect2.top;
1041 TempRect.bottom = TempRect2.bottom;
1042 if(Parent)
1043 GetClientRect(Parent, &ParentRect);
1044 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle,
1045 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect))
1046 {
1047 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1048 return HTBOTTOMLEFT;
1049 else
1050 return HTBOTTOMRIGHT;
1051 }
1052 }
1053 else
1054 {
1055 if (wi.dwStyle & WS_VSCROLL)
1056 {
1057 RECT TempRect = WindowRect;
1058
1059 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1060 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1061 else
1062 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1063 if (PtInRect(&TempRect, Point))
1064 return HTVSCROLL;
1065 }
1066 else if (wi.dwStyle & WS_HSCROLL)
1067 {
1068 RECT TempRect = WindowRect;
1069 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
1070 if (PtInRect(&TempRect, Point))
1071 return HTHSCROLL;
1072 }
1073 }
1074 }
1075
1076 return HTNOWHERE;
1077 }
1078
1079 LRESULT CALLBACK
1080 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc)
1081 {
1082 switch(Msg)
1083 {
1084 case WM_NCPAINT:
1085 return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
1086 //
1087 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1088 //
1089 case WM_NCUAHDRAWCAPTION:
1090 //
1091 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1092 //
1093 case WM_NCUAHDRAWFRAME:
1094 case WM_NCACTIVATE:
1095
1096 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) != WS_CAPTION)
1097 return TRUE;
1098
1099 ThemeHandleNCPaint(hWnd, (HRGN)1);
1100 return TRUE;
1101 case WM_NCMOUSEMOVE:
1102 {
1103 POINT Point;
1104 Point.x = GET_X_LPARAM(lParam);
1105 Point.y = GET_Y_LPARAM(lParam);
1106 return ThemeHandleNcMouseMove(hWnd, wParam, &Point);
1107 }
1108 case WM_NCMOUSELEAVE:
1109 return ThemeHandleNcMouseLeave(hWnd);
1110 case WM_NCLBUTTONDOWN:
1111 switch (wParam)
1112 {
1113 case HTMINBUTTON:
1114 case HTMAXBUTTON:
1115 case HTCLOSE:
1116 {
1117 ThemeHandleButton(hWnd, wParam);
1118 return 0;
1119 }
1120 default:
1121 return DefWndProc(hWnd, Msg, wParam, lParam);
1122 }
1123 case WM_NCHITTEST:
1124 {
1125 POINT Point;
1126 Point.x = GET_X_LPARAM(lParam);
1127 Point.y = GET_Y_LPARAM(lParam);
1128 return DefWndNCHitTest(hWnd, Point);
1129 }
1130 case WM_SYSCOMMAND:
1131 {
1132 if((wParam & 0xfff0) == SC_VSCROLL ||
1133 (wParam & 0xfff0) == SC_HSCROLL)
1134 {
1135 POINT Pt;
1136 Pt.x = (short)LOWORD(lParam);
1137 Pt.y = (short)HIWORD(lParam);
1138 NC_TrackScrollBar(hWnd, wParam, Pt);
1139 return 0;
1140 }
1141 else
1142 {
1143 return DefWndProc(hWnd, Msg, wParam, lParam);
1144 }
1145 }
1146 default:
1147 return DefWndProc(hWnd, Msg, wParam, lParam);
1148 }
1149 }
1150
1151 HRESULT WINAPI DrawNCPreview(HDC hDC,
1152 DWORD DNCP_Flag,
1153 LPRECT prcPreview,
1154 LPCWSTR pszThemeFileName,
1155 LPCWSTR pszColorName,
1156 LPCWSTR pszSizeName,
1157 PNONCLIENTMETRICSW pncMetrics,
1158 COLORREF* lpaRgbValues)
1159 {
1160 WNDCLASSEXW DummyPreviewWindowClass;
1161 HWND hwndDummy;
1162 HRESULT hres;
1163 HTHEMEFILE hThemeFile;
1164 DRAW_CONTEXT context;
1165 RECT rcCurrent;
1166
1167 /* FIXME: We also need to implement drawing the rest of the preview windows
1168 * and make use of the ncmetrics and colors passed as parameters */
1169
1170 /* Create a dummy window that will be used to trick the paint funtions */
1171 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass));
1172 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass);
1173 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass";
1174 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1175 DummyPreviewWindowClass.hInstance = hDllInst;
1176 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW;
1177 if (!RegisterClassExW(&DummyPreviewWindowClass))
1178 return E_FAIL;
1179
1180 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL);
1181 if (!hwndDummy)
1182 return E_FAIL;
1183
1184 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0);
1185 if (FAILED(hres))
1186 return hres;
1187
1188 /* Initialize the special draw context for the preview */
1189 context.hDC = hDC;
1190 context.hWnd = hwndDummy;
1191 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0);
1192 if (!context.theme)
1193 return E_FAIL;
1194 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0);
1195 if (!context.theme)
1196 return E_FAIL;
1197 context.Active = TRUE;
1198 context.wi.cbSize = sizeof(context.wi);
1199 if (!GetWindowInfo(hwndDummy, &context.wi))
1200 return E_FAIL;
1201 context.wi.dwStyle |= WS_VISIBLE;
1202 context.CaptionHeight = context.wi.cyWindowBorders;
1203 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
1204 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow);
1205
1206 /* Paint the window on the preview hDC */
1207 rcCurrent = context.wi.rcWindow;
1208 ThemePaintWindow(&context, &rcCurrent, FALSE);
1209 context.hDC = NULL;
1210 ThemeCleanupDrawContext(&context);
1211
1212 /* Cleanup */
1213 DestroyWindow(hwndDummy);
1214 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst);
1215
1216 return S_OK;
1217 }