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