Merge r68232 to get Windows' rpcrt4.dll to work under ReactOS.
[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 {
357 int IconHeight = GetSystemMetrics(SM_CYSMICON);
358 int IconWidth = GetSystemMetrics(SM_CXSMICON);
359 DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, IconHeight, 0, NULL, DI_NORMAL);
360 rcPart.left += IconWidth + 4;
361 }
362
363 rcPart.right -= 4;
364
365 /* Draw the caption */
366 if(CaptionText)
367 {
368 /*FIXME: Use DrawThemeTextEx*/
369 ThemeDrawCaptionText(pcontext->theme,
370 pcontext->hDC,
371 iPart,
372 iState,
373 CaptionText,
374 lstrlenW(CaptionText),
375 DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS,
376 0,
377 &rcPart ,
378 pcontext->Active);
379 HeapFree(GetProcessHeap(), 0, CaptionText);
380 }
381 }
382
383 static void
384 ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent)
385 {
386 RECT rcPart;
387 int iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE;
388
389 /* Draw the bottom border */
390 rcPart = *prcCurrent;
391 rcPart.top = rcPart.bottom - pcontext->wi.cyWindowBorders;
392 prcCurrent->bottom = rcPart.top;
393 DrawThemeBackground(pcontext->theme, pcontext->hDC, WP_FRAMEBOTTOM, iState, &rcPart, NULL);
394
395 /* Draw the left border */
396 rcPart = *prcCurrent;
397 rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ;
398 prcCurrent->left = rcPart.right;
399 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL);
400
401 /* Draw the right border */
402 rcPart = *prcCurrent;
403 rcPart.left = rcPart.right - pcontext->wi.cxWindowBorders;
404 prcCurrent->right = rcPart.left;
405 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMERIGHT, iState, &rcPart, NULL);
406 }
407
408 static void
409 DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent)
410 {
411 /* Draw outer edge */
412 if (UserHasWindowEdge(context->wi.dwStyle, context->wi.dwExStyle))
413 {
414 DrawEdge(context->hDC, prcCurrent, EDGE_RAISED, BF_RECT | BF_ADJUST);
415 }
416 else if (context->wi.dwExStyle & WS_EX_STATICEDGE)
417 {
418 DrawEdge(context->hDC, prcCurrent, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
419 }
420
421 /* Firstly the "thick" frame */
422 if ((context->wi.dwStyle & WS_THICKFRAME) && !(context->wi.dwStyle & WS_MINIMIZE))
423 {
424 INT Width =
425 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
426 GetSystemMetrics(SM_CXBORDER);
427 INT Height =
428 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
429 GetSystemMetrics(SM_CYBORDER);
430
431 SelectObject(context->hDC, GetSysColorBrush(
432 context->Active ? COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER));
433
434 /* Draw frame */
435 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
436 prcCurrent->right - prcCurrent->left, Height, PATCOPY);
437 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
438 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
439 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom,
440 prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
441 PatBlt(context->hDC, prcCurrent->right, prcCurrent->top,
442 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
443
444 InflateRect(prcCurrent, -Width, -Height);
445 }
446
447 /* Now the other bit of the frame */
448 if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || context->wi.dwExStyle & WS_EX_DLGMODALFRAME)
449 {
450 INT Width = GetSystemMetrics(SM_CXBORDER);
451 INT Height = GetSystemMetrics(SM_CYBORDER);
452
453 SelectObject(context->hDC, GetSysColorBrush(
454 (context->wi.dwExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
455 (context->wi.dwExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
456 (context->wi.dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
457 COLOR_WINDOWFRAME));
458
459 /* Draw frame */
460 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
461 prcCurrent->right - prcCurrent->left, Height, PATCOPY);
462 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top,
463 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
464 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom,
465 prcCurrent->right - prcCurrent->left, -Height, PATCOPY);
466 PatBlt(context->hDC, prcCurrent->right, prcCurrent->top,
467 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY);
468
469 InflateRect(prcCurrent, -Width, -Height);
470 }
471
472 if (context->wi.dwExStyle & WS_EX_CLIENTEDGE)
473 {
474 DrawEdge(context->hDC, prcCurrent, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
475 }
476 }
477
478 static void
479 ThemeDrawMenuItem(PDRAW_CONTEXT pcontext, HMENU Menu, int imenu)
480 {
481 PWCHAR Text;
482 BOOL flat_menu = FALSE;
483 MENUITEMINFOW Item;
484 RECT Rect,rcCalc;
485 WCHAR wstrItemText[20];
486 register int i = 0;
487 HFONT FontOld = NULL;
488 UINT uFormat = DT_CENTER | DT_VCENTER | DT_SINGLELINE;
489
490 Item.cbSize = sizeof(MENUITEMINFOW);
491 Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
492 Item.dwTypeData = wstrItemText;
493 Item.cch = 20;
494 if (!GetMenuItemInfoW(Menu, imenu, TRUE, &Item))
495 return;
496
497 if(Item.fType & MF_SEPARATOR)
498 return;
499
500 if(Item.cch >= 20)
501 {
502 Item.cch++;
503 Item.dwTypeData = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, Item.cch * sizeof(WCHAR));
504 Item.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
505 GetMenuItemInfoW(Menu, imenu, TRUE, &Item);
506 }
507
508 if(Item.cch == 0)
509 return;
510
511 flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
512
513 GetMenuItemRect(pcontext->hWnd, Menu, imenu, &Rect);
514
515 #ifdef __REACTOS__
516 OffsetRect(&Rect, -pcontext->wi.rcClient.left, -pcontext->wi.rcClient.top);
517 #else
518 OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
519 #endif
520
521 SetBkColor(pcontext->hDC, GetSysColor(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
522 SetTextColor(pcontext->hDC, GetSysColor(Item.fState & MF_GRAYED ? COLOR_GRAYTEXT : COLOR_MENUTEXT));
523
524 if (0 != (Item.fState & MFS_DEFAULT))
525 {
526 FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFontBold);
527 }
528
529 Rect.left += MENU_BAR_ITEMS_SPACE / 2;
530 Rect.right -= MENU_BAR_ITEMS_SPACE / 2;
531
532 Text = (PWCHAR) Item.dwTypeData;
533 if(Text)
534 {
535 for (i = 0; L'\0' != Text[i]; i++)
536 {
537 if (L'\t' == Text[i] || L'\b' == Text[i])
538 {
539 break;
540 }
541 }
542 }
543
544 SetBkMode(pcontext->hDC, OPAQUE);
545
546 if (0 != (Item.fState & MF_GRAYED))
547 {
548 if (0 == (Item.fState & MF_HILITE))
549 {
550 ++Rect.left; ++Rect.top; ++Rect.right; ++Rect.bottom;
551 SetTextColor(pcontext->hDC, RGB(0xff, 0xff, 0xff));
552 DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
553 --Rect.left; --Rect.top; --Rect.right; --Rect.bottom;
554 }
555 SetTextColor(pcontext->hDC, RGB(0x80, 0x80, 0x80));
556 SetBkMode(pcontext->hDC, TRANSPARENT);
557 }
558
559 DrawTextW(pcontext->hDC, Text, i, &Rect, uFormat);
560
561 /* Exclude from the clip region the area drawn by DrawText */
562 SetRect(&rcCalc, 0,0,0,0);
563 DrawTextW(pcontext->hDC, Text, i, &rcCalc, uFormat | DT_CALCRECT);
564 InflateRect( &Rect, 0, -(rcCalc.bottom+1)/2);
565 ExcludeClipRect(pcontext->hDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
566
567 if (NULL != FontOld)
568 {
569 SelectObject(pcontext->hDC, FontOld);
570 }
571 }
572
573 void WINAPI
574 ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, PRECT prcCurrent)
575 {
576 HMENU Menu;
577 MENUBARINFO MenuBarInfo;
578 int i;
579 HFONT FontOld = NULL;
580 BOOL flat_menu;
581 RECT Rect;
582 HPEN oldPen ;
583
584 if (!hMenuFont)
585 InitMenuFont();
586
587 flat_menu = GetThemeSysBool(pcontext->theme, TMT_FLATMENUS);
588
589 MenuBarInfo.cbSize = sizeof(MENUBARINFO);
590 if (! GetMenuBarInfo(pcontext->hWnd, OBJID_MENU, 0, &MenuBarInfo))
591 return;
592
593 Menu = GetMenu(pcontext->hWnd);
594 if (GetMenuItemCount(Menu) == 0)
595 return;
596
597 Rect = MenuBarInfo.rcBar;
598 OffsetRect(&Rect, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top);
599
600 /* Draw a line under the menu*/
601 oldPen = (HPEN)SelectObject(pcontext->hDC, GetStockObject(DC_PEN));
602 SetDCPenColor(pcontext->hDC, GetSysColor(COLOR_3DFACE));
603 MoveToEx(pcontext->hDC, Rect.left, Rect.bottom, NULL);
604 LineTo(pcontext->hDC, Rect.right, Rect.bottom);
605 SelectObject(pcontext->hDC, oldPen);
606
607 /* Draw menu items */
608 FontOld = (HFONT)SelectObject(pcontext->hDC, hMenuFont);
609
610 for (i = 0; i < GetMenuItemCount(Menu); i++)
611 {
612 ThemeDrawMenuItem(pcontext, Menu, i);
613 }
614
615 SelectObject(pcontext->hDC, FontOld);
616
617 /* Fill the menu background area that isn't painted yet*/
618 FillRect(pcontext->hDC, &Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU));
619 }
620
621 static void
622 ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent, BOOL bDoDoubleBuffering)
623 {
624 if(!(pcontext->wi.dwStyle & WS_VISIBLE))
625 return;
626
627 if(pcontext->wi.dwStyle & WS_MINIMIZE)
628 {
629 ThemeDrawTitle(pcontext, prcCurrent);
630 return;
631 }
632
633 if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION)
634 {
635 if (bDoDoubleBuffering)
636 ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight);
637 ThemeDrawCaption(pcontext, prcCurrent);
638 if (bDoDoubleBuffering)
639 ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight);
640 ThemeDrawBorders(pcontext, prcCurrent);
641 }
642 else
643 {
644 DrawClassicFrame(pcontext, prcCurrent);
645 }
646
647 if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle))
648 ThemeDrawMenuBar(pcontext, prcCurrent);
649
650 if(pcontext->wi.dwStyle & WS_HSCROLL)
651 ThemeDrawScrollBar(pcontext, SB_HORZ , NULL);
652
653 if(pcontext->wi.dwStyle & WS_VSCROLL)
654 ThemeDrawScrollBar(pcontext, SB_VERT, NULL);
655 }
656
657 /*
658 Message handlers
659 */
660
661 static LRESULT
662 ThemeHandleNCPaint(HWND hWnd, HRGN hRgn)
663 {
664 DRAW_CONTEXT context;
665 RECT rcCurrent;
666
667 ThemeInitDrawContext(&context, hWnd, hRgn);
668
669 rcCurrent = context.wi.rcWindow;
670 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top);
671
672 ThemePaintWindow(&context, &rcCurrent, TRUE);
673 ThemeCleanupDrawContext(&context);
674
675 return 0;
676 }
677
678 static LRESULT
679 ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt)
680 {
681 DRAW_CONTEXT context;
682 TRACKMOUSEEVENT tme;
683 DWORD style;
684 PWND_CONTEXT pcontext;
685
686 /* First of all check if we have something to do here */
687 style = GetWindowLongW(hWnd, GWL_STYLE);
688 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
689 return 0;
690
691 /* Get theme data for this window */
692 pcontext = ThemeGetWndContext(hWnd);
693 if (pcontext == NULL)
694 return 0;
695
696 /* Begin tracking in the non client area if we are not tracking yet */
697 tme.cbSize = sizeof(TRACKMOUSEEVENT);
698 tme.dwFlags = TME_QUERY;
699 tme.hwndTrack = hWnd;
700 TrackMouseEvent(&tme);
701 if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT))
702 {
703 tme.hwndTrack = hWnd;
704 tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
705 TrackMouseEvent(&tme);
706 }
707
708 /* Dont do any drawing if the hit test wasn't changed */
709 if (ht == pcontext->lastHitTest)
710 return 0;
711
712 ThemeInitDrawContext(&context, hWnd, 0);
713 if (context.wi.dwStyle & WS_SYSMENU)
714 {
715 if (HT_ISBUTTON(ht) || HT_ISBUTTON(pcontext->lastHitTest))
716 ThemeDrawCaptionButtons(&context, ht, 0);
717 }
718
719 if (context.wi.dwStyle & WS_HSCROLL)
720 {
721 if (ht == HTHSCROLL || pcontext->lastHitTest == HTHSCROLL)
722 ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL);
723 }
724
725 if (context.wi.dwStyle & WS_VSCROLL)
726 {
727 if (ht == HTVSCROLL || pcontext->lastHitTest == HTVSCROLL)
728 ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL);
729 }
730 ThemeCleanupDrawContext(&context);
731
732 pcontext->lastHitTest = ht;
733
734 return 0;
735 }
736
737 static LRESULT
738 ThemeHandleNcMouseLeave(HWND hWnd)
739 {
740 DRAW_CONTEXT context;
741 DWORD style;
742 PWND_CONTEXT pWndContext;
743
744 /* First of all check if we have something to do here */
745 style = GetWindowLongW(hWnd, GWL_STYLE);
746 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0)
747 return 0;
748
749 /* Get theme data for this window */
750 pWndContext = ThemeGetWndContext(hWnd);
751 if (pWndContext == NULL)
752 return 0;
753
754 ThemeInitDrawContext(&context, hWnd, 0);
755 if (context.wi.dwStyle & WS_SYSMENU && HT_ISBUTTON(pWndContext->lastHitTest))
756 ThemeDrawCaptionButtons(&context, 0, 0);
757
758 if (context.wi.dwStyle & WS_HSCROLL && pWndContext->lastHitTest == HTHSCROLL)
759 ThemeDrawScrollBar(&context, SB_HORZ, NULL);
760
761 if (context.wi.dwStyle & WS_VSCROLL && pWndContext->lastHitTest == HTVSCROLL)
762 ThemeDrawScrollBar(&context, SB_VERT, NULL);
763
764 ThemeCleanupDrawContext(&context);
765
766 pWndContext->lastHitTest = HTNOWHERE;
767
768 return 0;
769 }
770
771 static VOID
772 ThemeHandleButton(HWND hWnd, WPARAM wParam)
773 {
774 MSG Msg;
775 BOOL Pressed = TRUE;
776 WPARAM SCMsg, ht;
777 ULONG Style;
778 DRAW_CONTEXT context;
779 PWND_CONTEXT pWndContext;
780
781 Style = GetWindowLongW(hWnd, GWL_STYLE);
782 if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU)))
783 return ;
784
785 switch (wParam)
786 {
787 case HTCLOSE:
788 SCMsg = SC_CLOSE;
789 break;
790 case HTMINBUTTON:
791 if (!(Style & WS_MINIMIZEBOX))
792 return;
793 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
794 break;
795 case HTMAXBUTTON:
796 if (!(Style & WS_MAXIMIZEBOX))
797 return;
798 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
799 break;
800 default :
801 return;
802 }
803
804 /* Get theme data for this window */
805 pWndContext = ThemeGetWndContext(hWnd);
806 if (pWndContext == NULL)
807 return;
808
809 ThemeInitDrawContext(&context, hWnd, 0);
810 ThemeDrawCaptionButtons(&context, 0, wParam);
811 pWndContext->lastHitTest = wParam;
812
813 SetCapture(hWnd);
814
815 for (;;)
816 {
817 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
818 break;
819
820 if (Msg.message == WM_LBUTTONUP)
821 break;
822
823 if (Msg.message != WM_MOUSEMOVE)
824 continue;
825
826 ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y));
827 Pressed = (ht == wParam);
828
829 /* Only draw the buttons if the hit test changed */
830 if (ht != pWndContext->lastHitTest &&
831 (HT_ISBUTTON(ht) || HT_ISBUTTON(pWndContext->lastHitTest)))
832 {
833 ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0);
834 pWndContext->lastHitTest = ht;
835 }
836 }
837
838 ThemeDrawCaptionButtons(&context, ht, 0);
839 ThemeCleanupDrawContext(&context);
840
841 ReleaseCapture();
842
843 if (Pressed)
844 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
845 }
846
847
848 static LRESULT
849 DefWndNCHitTest(HWND hWnd, POINT Point)
850 {
851 RECT WindowRect;
852 POINT ClientPoint;
853 WINDOWINFO wi;
854
855 GetWindowInfo(hWnd, &wi);
856
857 if (!PtInRect(&wi.rcWindow, Point))
858 {
859 return HTNOWHERE;
860 }
861 WindowRect = wi.rcWindow;
862
863 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle))
864 {
865 LONG XSize, YSize;
866
867 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders);
868 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
869 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
870 if (!PtInRect(&WindowRect, Point))
871 {
872 BOOL ThickFrame;
873
874 ThickFrame = (wi.dwStyle & WS_THICKFRAME);
875 if (Point.y < WindowRect.top)
876 {
877 if(wi.dwStyle & WS_MINIMIZE)
878 return HTCAPTION;
879 if(!ThickFrame)
880 return HTBORDER;
881 if (Point.x < (WindowRect.left + XSize))
882 return HTTOPLEFT;
883 if (Point.x >= (WindowRect.right - XSize))
884 return HTTOPRIGHT;
885 return HTTOP;
886 }
887 if (Point.y >= WindowRect.bottom)
888 {
889 if(wi.dwStyle & WS_MINIMIZE)
890 return HTCAPTION;
891 if(!ThickFrame)
892 return HTBORDER;
893 if (Point.x < (WindowRect.left + XSize))
894 return HTBOTTOMLEFT;
895 if (Point.x >= (WindowRect.right - XSize))
896 return HTBOTTOMRIGHT;
897 return HTBOTTOM;
898 }
899 if (Point.x < WindowRect.left)
900 {
901 if(wi.dwStyle & WS_MINIMIZE)
902 return HTCAPTION;
903 if(!ThickFrame)
904 return HTBORDER;
905 if (Point.y < (WindowRect.top + YSize))
906 return HTTOPLEFT;
907 if (Point.y >= (WindowRect.bottom - YSize))
908 return HTBOTTOMLEFT;
909 return HTLEFT;
910 }
911 if (Point.x >= WindowRect.right)
912 {
913 if(wi.dwStyle & WS_MINIMIZE)
914 return HTCAPTION;
915 if(!ThickFrame)
916 return HTBORDER;
917 if (Point.y < (WindowRect.top + YSize))
918 return HTTOPRIGHT;
919 if (Point.y >= (WindowRect.bottom - YSize))
920 return HTBOTTOMRIGHT;
921 return HTRIGHT;
922 }
923 }
924 }
925 else
926 {
927 if (wi.dwExStyle & WS_EX_STATICEDGE)
928 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
929 -GetSystemMetrics(SM_CYBORDER));
930 if (!PtInRect(&WindowRect, Point))
931 return HTBORDER;
932 }
933
934 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION)
935 {
936 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
937 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
938 else
939 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
940
941 if (!PtInRect(&WindowRect, Point))
942 {
943
944 INT ButtonWidth;
945
946 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
947 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE);
948 else
949 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
950
951 ButtonWidth -= 4;
952 ButtonWidth+= BUTTON_GAP_SIZE;
953
954 if (wi.dwStyle & WS_SYSMENU)
955 {
956 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
957 {
958 WindowRect.right -= ButtonWidth;
959 }
960 else
961 {
962 if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
963 WindowRect.left += ButtonWidth;
964 WindowRect.right -= ButtonWidth;
965 }
966 }
967 if (Point.x < WindowRect.left)
968 return HTSYSMENU;
969 if (WindowRect.right <= Point.x)
970 return HTCLOSE;
971 if (wi.dwStyle & WS_MAXIMIZEBOX || wi.dwStyle & WS_MINIMIZEBOX)
972 WindowRect.right -= ButtonWidth;
973 if (Point.x >= WindowRect.right)
974 return HTMAXBUTTON;
975 if (wi.dwStyle & WS_MINIMIZEBOX)
976 WindowRect.right -= ButtonWidth;
977 if (Point.x >= WindowRect.right)
978 return HTMINBUTTON;
979 return HTCAPTION;
980 }
981 }
982
983 if(!(wi.dwStyle & WS_MINIMIZE))
984 {
985 HMENU menu;
986
987 ClientPoint = Point;
988 ScreenToClient(hWnd, &ClientPoint);
989 GetClientRect(hWnd, &wi.rcClient);
990
991 if (PtInRect(&wi.rcClient, ClientPoint))
992 {
993 return HTCLIENT;
994 }
995
996 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD))
997 {
998 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
999 return HTMENU;
1000 }
1001
1002 if (wi.dwExStyle & WS_EX_CLIENTEDGE)
1003 {
1004 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
1005 -2 * GetSystemMetrics(SM_CYBORDER));
1006 }
1007
1008 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) &&
1009 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
1010 {
1011 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
1012 HWND Parent = GetParent(hWnd);
1013
1014 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
1015 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1016 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1017 else
1018 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1019 if (PtInRect(&TempRect, Point))
1020 return HTVSCROLL;
1021
1022 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
1023 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1024 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
1025 else
1026 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
1027 if (PtInRect(&TempRect2, Point))
1028 return HTHSCROLL;
1029
1030 TempRect.top = TempRect2.top;
1031 TempRect.bottom = TempRect2.bottom;
1032 if(Parent)
1033 GetClientRect(Parent, &ParentRect);
1034 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle,
1035 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect))
1036 {
1037 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1038 return HTBOTTOMLEFT;
1039 else
1040 return HTBOTTOMRIGHT;
1041 }
1042 }
1043 else
1044 {
1045 if (wi.dwStyle & WS_VSCROLL)
1046 {
1047 RECT TempRect = WindowRect;
1048
1049 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1050 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1051 else
1052 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1053 if (PtInRect(&TempRect, Point))
1054 return HTVSCROLL;
1055 }
1056 else if (wi.dwStyle & WS_HSCROLL)
1057 {
1058 RECT TempRect = WindowRect;
1059 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
1060 if (PtInRect(&TempRect, Point))
1061 return HTHSCROLL;
1062 }
1063 }
1064 }
1065
1066 return HTNOWHERE;
1067 }
1068
1069 LRESULT CALLBACK
1070 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc)
1071 {
1072 switch(Msg)
1073 {
1074 case WM_NCPAINT:
1075 return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
1076 case WM_NCUAHDRAWCAPTION:
1077 case WM_NCUAHDRAWFRAME:
1078 case WM_NCACTIVATE:
1079 ThemeHandleNCPaint(hWnd, (HRGN)1);
1080 return TRUE;
1081 case WM_NCMOUSEMOVE:
1082 {
1083 POINT Point;
1084 Point.x = GET_X_LPARAM(lParam);
1085 Point.y = GET_Y_LPARAM(lParam);
1086 return ThemeHandleNcMouseMove(hWnd, wParam, &Point);
1087 }
1088 case WM_NCMOUSELEAVE:
1089 return ThemeHandleNcMouseLeave(hWnd);
1090 case WM_NCLBUTTONDOWN:
1091 switch (wParam)
1092 {
1093 case HTMINBUTTON:
1094 case HTMAXBUTTON:
1095 case HTCLOSE:
1096 {
1097 ThemeHandleButton(hWnd, wParam);
1098 return 0;
1099 }
1100 default:
1101 return DefWndProc(hWnd, Msg, wParam, lParam);
1102 }
1103 case WM_NCHITTEST:
1104 {
1105 POINT Point;
1106 Point.x = GET_X_LPARAM(lParam);
1107 Point.y = GET_Y_LPARAM(lParam);
1108 return DefWndNCHitTest(hWnd, Point);
1109 }
1110 case WM_SYSCOMMAND:
1111 {
1112 if((wParam & 0xfff0) == SC_VSCROLL ||
1113 (wParam & 0xfff0) == SC_HSCROLL)
1114 {
1115 POINT Pt;
1116 Pt.x = (short)LOWORD(lParam);
1117 Pt.y = (short)HIWORD(lParam);
1118 NC_TrackScrollBar(hWnd, wParam, Pt);
1119 return 0;
1120 }
1121 else
1122 {
1123 return DefWndProc(hWnd, Msg, wParam, lParam);
1124 }
1125 }
1126 default:
1127 return DefWndProc(hWnd, Msg, wParam, lParam);
1128 }
1129 }
1130
1131 HRESULT WINAPI DrawNCPreview(HDC hDC,
1132 DWORD DNCP_Flag,
1133 LPRECT prcPreview,
1134 LPCWSTR pszThemeFileName,
1135 LPCWSTR pszColorName,
1136 LPCWSTR pszSizeName,
1137 PNONCLIENTMETRICSW pncMetrics,
1138 COLORREF* lpaRgbValues)
1139 {
1140 WNDCLASSEXW DummyPreviewWindowClass;
1141 HWND hwndDummy;
1142 HRESULT hres;
1143 HTHEMEFILE hThemeFile;
1144 DRAW_CONTEXT context;
1145 RECT rcCurrent;
1146
1147 /* FIXME: We also need to implement drawing the rest of the preview windows
1148 * and make use of the ncmetrics and colors passed as parameters */
1149
1150 /* Create a dummy window that will be used to trick the paint funtions */
1151 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass));
1152 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass);
1153 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass";
1154 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1155 DummyPreviewWindowClass.hInstance = hDllInst;
1156 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW;
1157 if (!RegisterClassExW(&DummyPreviewWindowClass))
1158 return E_FAIL;
1159
1160 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL);
1161 if (!hwndDummy)
1162 return E_FAIL;
1163
1164 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0);
1165 if (FAILED(hres))
1166 return hres;
1167
1168 /* Initialize the special draw context for the preview */
1169 context.hDC = hDC;
1170 context.hWnd = hwndDummy;
1171 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0);
1172 if (!context.theme)
1173 return E_FAIL;
1174 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0);
1175 if (!context.theme)
1176 return E_FAIL;
1177 context.Active = TRUE;
1178 if (!GetWindowInfo(hwndDummy, &context.wi))
1179 return E_FAIL;
1180 context.wi.dwStyle |= WS_VISIBLE;
1181 context.CaptionHeight = context.wi.cyWindowBorders;
1182 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
1183 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow);
1184
1185 /* Paint the window on the preview hDC */
1186 rcCurrent = context.wi.rcWindow;
1187 ThemePaintWindow(&context, &rcCurrent, FALSE);
1188 context.hDC = NULL;
1189 ThemeCleanupDrawContext(&context);
1190
1191 /* Cleanup */
1192 DestroyWindow(hwndDummy);
1193 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst);
1194
1195 return S_OK;
1196 }