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