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