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