3c3da3ead77b7ddb26ea9dcd6faa67c200f3b4b8
[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 wi.cbSize = sizeof(wi);
855 GetWindowInfo(hWnd, &wi);
856
857 if (!PtInRect(&wi.rcWindow, Point))
858 {
859 return HTNOWHERE;
860 }
861 WindowRect = wi.rcWindow;
862
863 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle))
864 {
865 LONG XSize, YSize;
866
867 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders);
868 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
869 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
870 if (!PtInRect(&WindowRect, Point))
871 {
872 BOOL ThickFrame;
873
874 ThickFrame = (wi.dwStyle & WS_THICKFRAME);
875 if (Point.y < WindowRect.top)
876 {
877 if(wi.dwStyle & WS_MINIMIZE)
878 return HTCAPTION;
879 if(!ThickFrame)
880 return HTBORDER;
881 if (Point.x < (WindowRect.left + XSize))
882 return HTTOPLEFT;
883 if (Point.x >= (WindowRect.right - XSize))
884 return HTTOPRIGHT;
885 return HTTOP;
886 }
887 if (Point.y >= WindowRect.bottom)
888 {
889 if(wi.dwStyle & WS_MINIMIZE)
890 return HTCAPTION;
891 if(!ThickFrame)
892 return HTBORDER;
893 if (Point.x < (WindowRect.left + XSize))
894 return HTBOTTOMLEFT;
895 if (Point.x >= (WindowRect.right - XSize))
896 return HTBOTTOMRIGHT;
897 return HTBOTTOM;
898 }
899 if (Point.x < WindowRect.left)
900 {
901 if(wi.dwStyle & WS_MINIMIZE)
902 return HTCAPTION;
903 if(!ThickFrame)
904 return HTBORDER;
905 if (Point.y < (WindowRect.top + YSize))
906 return HTTOPLEFT;
907 if (Point.y >= (WindowRect.bottom - YSize))
908 return HTBOTTOMLEFT;
909 return HTLEFT;
910 }
911 if (Point.x >= WindowRect.right)
912 {
913 if(wi.dwStyle & WS_MINIMIZE)
914 return HTCAPTION;
915 if(!ThickFrame)
916 return HTBORDER;
917 if (Point.y < (WindowRect.top + YSize))
918 return HTTOPRIGHT;
919 if (Point.y >= (WindowRect.bottom - YSize))
920 return HTBOTTOMRIGHT;
921 return HTRIGHT;
922 }
923 }
924 }
925 else
926 {
927 if (wi.dwExStyle & WS_EX_STATICEDGE)
928 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
929 -GetSystemMetrics(SM_CYBORDER));
930 if (!PtInRect(&WindowRect, Point))
931 return HTBORDER;
932 }
933
934 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION)
935 {
936 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
937 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
938 else
939 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
940
941 if (!PtInRect(&WindowRect, Point))
942 {
943 INT ButtonWidth;
944
945 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
946 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE);
947 else
948 ButtonWidth = GetSystemMetrics(SM_CXSIZE);
949
950 ButtonWidth -= 4;
951 ButtonWidth += BUTTON_GAP_SIZE;
952
953 if (wi.dwStyle & WS_SYSMENU)
954 {
955 if (wi.dwExStyle & WS_EX_TOOLWINDOW)
956 {
957 WindowRect.right -= ButtonWidth;
958 }
959 else
960 {
961 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
962 // FIXME: The real test should check whether there is
963 // an icon for the system window, and if so, do the
964 // rect.left increase.
965 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
966 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
967 // the test better.
968 WindowRect.left += ButtonWidth;
969 WindowRect.right -= ButtonWidth;
970 }
971 }
972 if (Point.x < WindowRect.left)
973 return HTSYSMENU;
974 if (WindowRect.right <= Point.x)
975 return HTCLOSE;
976 if (wi.dwStyle & WS_MAXIMIZEBOX || wi.dwStyle & WS_MINIMIZEBOX)
977 WindowRect.right -= ButtonWidth;
978 if (Point.x >= WindowRect.right)
979 return HTMAXBUTTON;
980 if (wi.dwStyle & WS_MINIMIZEBOX)
981 WindowRect.right -= ButtonWidth;
982 if (Point.x >= WindowRect.right)
983 return HTMINBUTTON;
984 return HTCAPTION;
985 }
986 }
987
988 if(!(wi.dwStyle & WS_MINIMIZE))
989 {
990 HMENU menu;
991
992 ClientPoint = Point;
993 ScreenToClient(hWnd, &ClientPoint);
994 GetClientRect(hWnd, &wi.rcClient);
995
996 if (PtInRect(&wi.rcClient, ClientPoint))
997 {
998 return HTCLIENT;
999 }
1000
1001 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD))
1002 {
1003 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
1004 return HTMENU;
1005 }
1006
1007 if (wi.dwExStyle & WS_EX_CLIENTEDGE)
1008 {
1009 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
1010 -2 * GetSystemMetrics(SM_CYBORDER));
1011 }
1012
1013 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) &&
1014 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
1015 {
1016 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
1017 HWND Parent = GetParent(hWnd);
1018
1019 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
1020 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1021 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1022 else
1023 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1024 if (PtInRect(&TempRect, Point))
1025 return HTVSCROLL;
1026
1027 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
1028 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1029 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
1030 else
1031 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
1032 if (PtInRect(&TempRect2, Point))
1033 return HTHSCROLL;
1034
1035 TempRect.top = TempRect2.top;
1036 TempRect.bottom = TempRect2.bottom;
1037 if(Parent)
1038 GetClientRect(Parent, &ParentRect);
1039 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle,
1040 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect))
1041 {
1042 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1043 return HTBOTTOMLEFT;
1044 else
1045 return HTBOTTOMRIGHT;
1046 }
1047 }
1048 else
1049 {
1050 if (wi.dwStyle & WS_VSCROLL)
1051 {
1052 RECT TempRect = WindowRect;
1053
1054 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1055 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
1056 else
1057 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
1058 if (PtInRect(&TempRect, Point))
1059 return HTVSCROLL;
1060 }
1061 else if (wi.dwStyle & WS_HSCROLL)
1062 {
1063 RECT TempRect = WindowRect;
1064 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
1065 if (PtInRect(&TempRect, Point))
1066 return HTHSCROLL;
1067 }
1068 }
1069 }
1070
1071 return HTNOWHERE;
1072 }
1073
1074 LRESULT CALLBACK
1075 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc)
1076 {
1077 switch(Msg)
1078 {
1079 case WM_NCPAINT:
1080 return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
1081 //
1082 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1083 //
1084 case WM_NCUAHDRAWCAPTION:
1085 //
1086 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1087 //
1088 case WM_NCUAHDRAWFRAME:
1089 case WM_NCACTIVATE:
1090 ThemeHandleNCPaint(hWnd, (HRGN)1);
1091 return TRUE;
1092 case WM_NCMOUSEMOVE:
1093 {
1094 POINT Point;
1095 Point.x = GET_X_LPARAM(lParam);
1096 Point.y = GET_Y_LPARAM(lParam);
1097 return ThemeHandleNcMouseMove(hWnd, wParam, &Point);
1098 }
1099 case WM_NCMOUSELEAVE:
1100 return ThemeHandleNcMouseLeave(hWnd);
1101 case WM_NCLBUTTONDOWN:
1102 switch (wParam)
1103 {
1104 case HTMINBUTTON:
1105 case HTMAXBUTTON:
1106 case HTCLOSE:
1107 {
1108 ThemeHandleButton(hWnd, wParam);
1109 return 0;
1110 }
1111 default:
1112 return DefWndProc(hWnd, Msg, wParam, lParam);
1113 }
1114 case WM_NCHITTEST:
1115 {
1116 POINT Point;
1117 Point.x = GET_X_LPARAM(lParam);
1118 Point.y = GET_Y_LPARAM(lParam);
1119 return DefWndNCHitTest(hWnd, Point);
1120 }
1121 case WM_SYSCOMMAND:
1122 {
1123 if((wParam & 0xfff0) == SC_VSCROLL ||
1124 (wParam & 0xfff0) == SC_HSCROLL)
1125 {
1126 POINT Pt;
1127 Pt.x = (short)LOWORD(lParam);
1128 Pt.y = (short)HIWORD(lParam);
1129 NC_TrackScrollBar(hWnd, wParam, Pt);
1130 return 0;
1131 }
1132 else
1133 {
1134 return DefWndProc(hWnd, Msg, wParam, lParam);
1135 }
1136 }
1137 default:
1138 return DefWndProc(hWnd, Msg, wParam, lParam);
1139 }
1140 }
1141
1142 HRESULT WINAPI DrawNCPreview(HDC hDC,
1143 DWORD DNCP_Flag,
1144 LPRECT prcPreview,
1145 LPCWSTR pszThemeFileName,
1146 LPCWSTR pszColorName,
1147 LPCWSTR pszSizeName,
1148 PNONCLIENTMETRICSW pncMetrics,
1149 COLORREF* lpaRgbValues)
1150 {
1151 WNDCLASSEXW DummyPreviewWindowClass;
1152 HWND hwndDummy;
1153 HRESULT hres;
1154 HTHEMEFILE hThemeFile;
1155 DRAW_CONTEXT context;
1156 RECT rcCurrent;
1157
1158 /* FIXME: We also need to implement drawing the rest of the preview windows
1159 * and make use of the ncmetrics and colors passed as parameters */
1160
1161 /* Create a dummy window that will be used to trick the paint funtions */
1162 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass));
1163 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass);
1164 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass";
1165 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1166 DummyPreviewWindowClass.hInstance = hDllInst;
1167 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW;
1168 if (!RegisterClassExW(&DummyPreviewWindowClass))
1169 return E_FAIL;
1170
1171 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL);
1172 if (!hwndDummy)
1173 return E_FAIL;
1174
1175 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0);
1176 if (FAILED(hres))
1177 return hres;
1178
1179 /* Initialize the special draw context for the preview */
1180 context.hDC = hDC;
1181 context.hWnd = hwndDummy;
1182 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0);
1183 if (!context.theme)
1184 return E_FAIL;
1185 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0);
1186 if (!context.theme)
1187 return E_FAIL;
1188 context.Active = TRUE;
1189 context.wi.cbSize = sizeof(context.wi);
1190 if (!GetWindowInfo(hwndDummy, &context.wi))
1191 return E_FAIL;
1192 context.wi.dwStyle |= WS_VISIBLE;
1193 context.CaptionHeight = context.wi.cyWindowBorders;
1194 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
1195 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow);
1196
1197 /* Paint the window on the preview hDC */
1198 rcCurrent = context.wi.rcWindow;
1199 ThemePaintWindow(&context, &rcCurrent, FALSE);
1200 context.hDC = NULL;
1201 ThemeCleanupDrawContext(&context);
1202
1203 /* Cleanup */
1204 DestroyWindow(hwndDummy);
1205 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst);
1206
1207 return S_OK;
1208 }