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
11 HFONT hMenuFont
= NULL
;
12 HFONT hMenuFontBold
= NULL
;
14 void InitMenuFont(VOID
)
18 ncm
.cbSize
= sizeof(NONCLIENTMETRICS
);
20 if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, sizeof(ncm
), &ncm
, 0))
25 hMenuFont
= CreateFontIndirect(&ncm
.lfMenuFont
);
27 ncm
.lfMenuFont
.lfWeight
= max(ncm
.lfMenuFont
.lfWeight
+ 300, 1000);
28 hMenuFontBold
= CreateFontIndirect(&ncm
.lfMenuFont
);
32 IsWindowActive(HWND hWnd
, DWORD ExStyle
)
36 if (ExStyle
& WS_EX_MDICHILD
)
38 ret
= IsChild(GetForegroundWindow(), hWnd
);
40 ret
= (hWnd
== (HWND
)SendMessageW(GetParent(hWnd
), WM_MDIGETACTIVE
, 0, 0));
44 ret
= (GetForegroundWindow() == hWnd
);
51 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
53 if (Style
& WS_MINIMIZE
)
55 if (ExStyle
& WS_EX_DLGMODALFRAME
)
57 if (ExStyle
& WS_EX_STATICEDGE
)
59 if (Style
& WS_THICKFRAME
)
62 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
68 UserGetWindowIcon(PDRAW_CONTEXT pcontext
)
72 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
75 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
78 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
81 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICONSM
);
84 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICON
);
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
);
93 WCHAR
*UserGetWindowCaption(HWND hwnd
)
97 text
= (WCHAR
*)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
98 if (text
) InternalGetWindowText(hwnd
, text
, len
);
102 HRESULT WINAPI
ThemeDrawCaptionText(HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
,
103 LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
,
104 DWORD dwTextFlags2
, const RECT
*pRect
, BOOL Active
)
108 HGDIOBJ oldFont
= NULL
;
111 COLORREF oldTextColor
;
115 hr
= GetThemeSysFont(0,TMT_CAPTIONFONT
,&logfont
);
118 hFont
= CreateFontIndirectW(&logfont
);
120 CopyRect(&rt
, pRect
);
122 oldFont
= SelectObject(hdc
, hFont
);
124 if(dwTextFlags2
& DTT_GRAYED
)
125 textColor
= GetSysColor(COLOR_GRAYTEXT
);
127 textColor
= GetSysColor(COLOR_INACTIVECAPTIONTEXT
);
129 textColor
= GetSysColor(COLOR_CAPTIONTEXT
);
131 oldTextColor
= SetTextColor(hdc
, textColor
);
132 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
133 DrawThemeText(hTheme
, hdc
, iPartId
, iStateId
, pszText
, iCharCount
, dwTextFlags
, dwTextFlags
, pRect
);
134 SetBkMode(hdc
, oldBkMode
);
135 SetTextColor(hdc
, oldTextColor
);
138 SelectObject(hdc
, oldFont
);
145 ThemeInitDrawContext(PDRAW_CONTEXT pcontext
,
149 pcontext
->wi
.cbSize
= sizeof(pcontext
->wi
);
150 GetWindowInfo(hWnd
, &pcontext
->wi
);
151 pcontext
->hWnd
= hWnd
;
152 pcontext
->Active
= IsWindowActive(hWnd
, pcontext
->wi
.dwExStyle
);
153 pcontext
->theme
= MSSTYLES_OpenThemeClass(ActiveThemeFile
, NULL
, L
"WINDOW");
154 pcontext
->scrolltheme
= MSSTYLES_OpenThemeClass(ActiveThemeFile
, NULL
, L
"SCROLLBAR");
156 pcontext
->CaptionHeight
= pcontext
->wi
.cyWindowBorders
;
157 pcontext
->CaptionHeight
+= GetSystemMetrics(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
161 hRgn
= CreateRectRgnIndirect(&pcontext
->wi
.rcWindow
);
163 pcontext
->hRgn
= hRgn
;
165 pcontext
->hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
169 ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext
)
171 ReleaseDC(pcontext
->hWnd
,pcontext
->hDC
);
173 CloseThemeData (pcontext
->theme
);
174 CloseThemeData (pcontext
->scrolltheme
);
176 if(pcontext
->hRgn
!= NULL
)
178 DeleteObject(pcontext
->hRgn
);
183 ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext
, int cx
, int cy
)
187 pcontext
->hDCScreen
= pcontext
->hDC
;
188 pcontext
->hDC
= CreateCompatibleDC(pcontext
->hDCScreen
);
189 hbmp
= CreateCompatibleBitmap(pcontext
->hDCScreen
, cx
, cy
);
190 pcontext
->hbmpOld
= (HBITMAP
)SelectObject(pcontext
->hDC
, hbmp
);
194 ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext
, int x
, int y
, int cx
, int cy
)
197 BitBlt(pcontext
->hDCScreen
, 0, 0, cx
, cy
, pcontext
->hDC
, x
, y
, SRCCOPY
);
198 hbmp
= (HBITMAP
) SelectObject(pcontext
->hDC
, pcontext
->hbmpOld
);
199 DeleteObject(pcontext
->hDC
);
202 pcontext
->hDC
= pcontext
->hDCScreen
;
206 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext
,
208 CAPTIONBUTTON buttonId
,
212 INT ButtonWidth
, ButtonHeight
, iPartId
;
218 iPartId
= pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
222 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
224 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
227 iStateId
= BUTTON_DISABLED
;
230 iPartId
= pcontext
->wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
234 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
236 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
239 iStateId
= BUTTON_DISABLED
;
242 iPartId
= pcontext
->wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
246 //FIXME: Implement Help Button
250 GetThemePartSize(pcontext
->theme
, pcontext
->hDC
, iPartId
, 0, NULL
, TS_MIN
, &ButtonSize
);
252 ButtonHeight
= GetSystemMetrics( pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMSIZE
: SM_CYSIZE
);
253 ButtonWidth
= MulDiv(ButtonSize
.cx
, ButtonHeight
, ButtonSize
.cy
);
258 /* Calculate the position */
259 rcPart
.top
= prcCurrent
->top
;
260 rcPart
.right
= prcCurrent
->right
;
261 rcPart
.bottom
= rcPart
.top
+ ButtonHeight
;
262 rcPart
.left
= rcPart
.right
- ButtonWidth
;
263 prcCurrent
->right
-= ButtonWidth
+ BUTTON_GAP_SIZE
;
265 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, iPartId
, iStateId
, &rcPart
, NULL
);
269 ThemeGetButtonState(DWORD htCurrect
, DWORD htHot
, DWORD htDown
, BOOL Active
)
271 if (htHot
== htCurrect
)
274 return BUTTON_INACTIVE
;
275 if (htDown
== htCurrect
)
276 return BUTTON_PRESSED
;
278 return BUTTON_NORMAL
;
281 /* Used only from mouse event handlers */
283 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext
, DWORD htHot
, DWORD htDown
)
287 /* Calculate the area of the caption */
288 rcCurrent
.top
= rcCurrent
.left
= 0;
289 rcCurrent
.right
= pcontext
->wi
.rcWindow
.right
- pcontext
->wi
.rcWindow
.left
;
290 rcCurrent
.bottom
= pcontext
->CaptionHeight
;
292 /* Add a padding around the objects of the caption */
293 InflateRect(&rcCurrent
, -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
294 -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
296 /* Draw the buttons */
297 ThemeDrawCaptionButton(pcontext
, &rcCurrent
, CLOSEBUTTON
,
298 ThemeGetButtonState(HTCLOSE
, htHot
, htDown
, pcontext
->Active
));
299 ThemeDrawCaptionButton(pcontext
, &rcCurrent
, MAXBUTTON
,
300 ThemeGetButtonState(HTMAXBUTTON
, htHot
, htDown
, pcontext
->Active
));
301 ThemeDrawCaptionButton(pcontext
, &rcCurrent
, MINBUTTON
,
302 ThemeGetButtonState(HTMINBUTTON
, htHot
, htDown
, pcontext
->Active
));
303 ThemeDrawCaptionButton(pcontext
, &rcCurrent
, HELPBUTTON
,
304 ThemeGetButtonState(HTHELP
, htHot
, htDown
, pcontext
->Active
));
307 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
309 ThemeDrawCaption(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
316 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
317 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
318 if ((pcontext
->wi
.dwStyle
& WS_SYSMENU
) && !(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
319 hIcon
= UserGetWindowIcon(pcontext
);
323 CaptionText
= UserGetWindowCaption(pcontext
->hWnd
);
325 /* Get the caption part and state id */
326 if (pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
327 iPart
= WP_MINCAPTION
;
328 else if (pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
329 iPart
= WP_SMALLCAPTION
;
330 else if (pcontext
->wi
.dwStyle
& WS_MAXIMIZE
)
331 iPart
= WP_MAXCAPTION
;
335 iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
337 /* Draw the caption background */
338 rcPart
= *prcCurrent
;
339 rcPart
.bottom
= rcPart
.top
+ pcontext
->CaptionHeight
;
340 prcCurrent
->top
= rcPart
.bottom
;
341 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,iPart
,iState
,&rcPart
,NULL
);
343 /* Add a padding around the objects of the caption */
344 InflateRect(&rcPart
, -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
345 -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
347 /* Draw the caption buttons */
348 if (pcontext
->wi
.dwStyle
& WS_SYSMENU
)
350 iState
= pcontext
->Active
? BUTTON_NORMAL
: BUTTON_INACTIVE
;
352 ThemeDrawCaptionButton(pcontext
, &rcPart
, CLOSEBUTTON
, iState
);
353 ThemeDrawCaptionButton(pcontext
, &rcPart
, MAXBUTTON
, iState
);
354 ThemeDrawCaptionButton(pcontext
, &rcPart
, MINBUTTON
, iState
);
355 ThemeDrawCaptionButton(pcontext
, &rcPart
, HELPBUTTON
, iState
);
363 int IconHeight
= GetSystemMetrics(SM_CYSMICON
);
364 int IconWidth
= GetSystemMetrics(SM_CXSMICON
);
365 DrawIconEx(pcontext
->hDC
, rcPart
.left
, rcPart
.top
, hIcon
, IconWidth
, IconHeight
, 0, NULL
, DI_NORMAL
);
366 rcPart
.left
+= IconWidth
+ 4;
371 /* Draw the caption */
374 /* FIXME: Use DrawThemeTextEx */
375 ThemeDrawCaptionText(pcontext
->theme
,
380 lstrlenW(CaptionText
),
381 DT_VCENTER
| DT_SINGLELINE
| DT_END_ELLIPSIS
,
385 HeapFree(GetProcessHeap(), 0, CaptionText
);
390 ThemeDrawBorders(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
393 int iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
395 /* Draw the bottom border */
396 rcPart
= *prcCurrent
;
397 rcPart
.top
= rcPart
.bottom
- pcontext
->wi
.cyWindowBorders
;
398 prcCurrent
->bottom
= rcPart
.top
;
399 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, WP_FRAMEBOTTOM
, iState
, &rcPart
, NULL
);
401 /* Draw the left border */
402 rcPart
= *prcCurrent
;
403 rcPart
.right
= rcPart
.left
+ pcontext
->wi
.cxWindowBorders
;
404 prcCurrent
->left
= rcPart
.right
;
405 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMELEFT
, iState
, &rcPart
, NULL
);
407 /* Draw the right border */
408 rcPart
= *prcCurrent
;
409 rcPart
.left
= rcPart
.right
- pcontext
->wi
.cxWindowBorders
;
410 prcCurrent
->right
= rcPart
.left
;
411 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMERIGHT
, iState
, &rcPart
, NULL
);
415 DrawClassicFrame(PDRAW_CONTEXT context
, RECT
* prcCurrent
)
417 /* Draw outer edge */
418 if (UserHasWindowEdge(context
->wi
.dwStyle
, context
->wi
.dwExStyle
))
420 DrawEdge(context
->hDC
, prcCurrent
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
422 else if (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
)
424 DrawEdge(context
->hDC
, prcCurrent
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
427 /* Firstly the "thick" frame */
428 if ((context
->wi
.dwStyle
& WS_THICKFRAME
) && !(context
->wi
.dwStyle
& WS_MINIMIZE
))
431 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
432 GetSystemMetrics(SM_CXBORDER
);
434 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
435 GetSystemMetrics(SM_CYBORDER
);
437 SelectObject(context
->hDC
, GetSysColorBrush(
438 context
->Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
441 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
442 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
443 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
444 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
445 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
446 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
447 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
448 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
450 InflateRect(prcCurrent
, -Width
, -Height
);
453 /* Now the other bit of the frame */
454 if (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_BORDER
) || (context
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
456 INT Width
= GetSystemMetrics(SM_CXBORDER
);
457 INT Height
= GetSystemMetrics(SM_CYBORDER
);
459 SelectObject(context
->hDC
, GetSysColorBrush(
460 (context
->wi
.dwExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
461 (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
462 (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
466 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
467 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
468 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
469 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
470 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
471 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
472 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
473 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
475 InflateRect(prcCurrent
, -Width
, -Height
);
478 if (context
->wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
480 DrawEdge(context
->hDC
, prcCurrent
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
485 ThemePaintWindow(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
, BOOL bDoDoubleBuffering
)
487 if(!(pcontext
->wi
.dwStyle
& WS_VISIBLE
))
490 if((pcontext
->wi
.dwStyle
& WS_CAPTION
)==WS_CAPTION
)
492 if (bDoDoubleBuffering
)
493 ThemeStartBufferedPaint(pcontext
, prcCurrent
->right
, pcontext
->CaptionHeight
);
494 ThemeDrawCaption(pcontext
, prcCurrent
);
495 if (bDoDoubleBuffering
)
496 ThemeEndBufferedPaint(pcontext
, 0, 0, prcCurrent
->right
, pcontext
->CaptionHeight
);
497 ThemeDrawBorders(pcontext
, prcCurrent
);
501 DrawClassicFrame(pcontext
, prcCurrent
);
504 if(pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
507 if(HAS_MENU(pcontext
->hWnd
, pcontext
->wi
.dwStyle
))
508 PaintMenuBar(pcontext
->hWnd
, pcontext
->hDC
, prcCurrent
->left
, prcCurrent
->right
, prcCurrent
->top
, pcontext
->Active
);
510 if(pcontext
->wi
.dwStyle
& WS_HSCROLL
)
511 ThemeDrawScrollBar(pcontext
, SB_HORZ
, NULL
);
513 if(pcontext
->wi
.dwStyle
& WS_VSCROLL
)
514 ThemeDrawScrollBar(pcontext
, SB_VERT
, NULL
);
522 ThemeHandleNCPaint(HWND hWnd
, HRGN hRgn
)
524 DRAW_CONTEXT context
;
527 ThemeInitDrawContext(&context
, hWnd
, hRgn
);
529 rcCurrent
= context
.wi
.rcWindow
;
530 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
532 ThemePaintWindow(&context
, &rcCurrent
, TRUE
);
533 ThemeCleanupDrawContext(&context
);
539 ThemeHandleNcMouseMove(HWND hWnd
, DWORD ht
, POINT
* pt
)
541 DRAW_CONTEXT context
;
544 PWND_CONTEXT pcontext
;
546 /* First of all check if we have something to do here */
547 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
548 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
551 /* Get theme data for this window */
552 pcontext
= ThemeGetWndContext(hWnd
);
553 if (pcontext
== NULL
)
556 /* Begin tracking in the non client area if we are not tracking yet */
557 tme
.cbSize
= sizeof(TRACKMOUSEEVENT
);
558 tme
.dwFlags
= TME_QUERY
;
559 tme
.hwndTrack
= hWnd
;
560 TrackMouseEvent(&tme
);
561 if (tme
.dwFlags
!= (TME_LEAVE
| TME_NONCLIENT
))
563 tme
.hwndTrack
= hWnd
;
564 tme
.dwFlags
= TME_LEAVE
| TME_NONCLIENT
;
565 TrackMouseEvent(&tme
);
568 ThemeInitDrawContext(&context
, hWnd
, 0);
569 if (context
.wi
.dwStyle
& WS_SYSMENU
)
571 if (HT_ISBUTTON(ht
) || HT_ISBUTTON(pcontext
->lastHitTest
))
572 ThemeDrawCaptionButtons(&context
, ht
, 0);
575 if (context
.wi
.dwStyle
& WS_HSCROLL
)
577 if (ht
== HTHSCROLL
|| pcontext
->lastHitTest
== HTHSCROLL
)
578 ThemeDrawScrollBar(&context
, SB_HORZ
, ht
== HTHSCROLL
? pt
: NULL
);
581 if (context
.wi
.dwStyle
& WS_VSCROLL
)
583 if (ht
== HTVSCROLL
|| pcontext
->lastHitTest
== HTVSCROLL
)
584 ThemeDrawScrollBar(&context
, SB_VERT
, ht
== HTVSCROLL
? pt
: NULL
);
586 ThemeCleanupDrawContext(&context
);
588 pcontext
->lastHitTest
= ht
;
594 ThemeHandleNcMouseLeave(HWND hWnd
)
596 DRAW_CONTEXT context
;
598 PWND_CONTEXT pWndContext
;
600 /* First of all check if we have something to do here */
601 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
602 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
605 /* Get theme data for this window */
606 pWndContext
= ThemeGetWndContext(hWnd
);
607 if (pWndContext
== NULL
)
610 ThemeInitDrawContext(&context
, hWnd
, 0);
611 if (context
.wi
.dwStyle
& WS_SYSMENU
&& HT_ISBUTTON(pWndContext
->lastHitTest
))
612 ThemeDrawCaptionButtons(&context
, 0, 0);
614 if (context
.wi
.dwStyle
& WS_HSCROLL
&& pWndContext
->lastHitTest
== HTHSCROLL
)
615 ThemeDrawScrollBar(&context
, SB_HORZ
, NULL
);
617 if (context
.wi
.dwStyle
& WS_VSCROLL
&& pWndContext
->lastHitTest
== HTVSCROLL
)
618 ThemeDrawScrollBar(&context
, SB_VERT
, NULL
);
620 ThemeCleanupDrawContext(&context
);
622 pWndContext
->lastHitTest
= HTNOWHERE
;
628 ThemeHandleButton(HWND hWnd
, WPARAM wParam
)
634 DRAW_CONTEXT context
;
635 PWND_CONTEXT pWndContext
;
637 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
638 if (!((Style
& WS_CAPTION
) && (Style
& WS_SYSMENU
)))
647 if (!(Style
& WS_MINIMIZEBOX
))
649 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
652 if (!(Style
& WS_MAXIMIZEBOX
))
654 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
660 /* Get theme data for this window */
661 pWndContext
= ThemeGetWndContext(hWnd
);
662 if (pWndContext
== NULL
)
665 ThemeInitDrawContext(&context
, hWnd
, 0);
666 ThemeDrawCaptionButtons(&context
, 0, wParam
);
667 pWndContext
->lastHitTest
= wParam
;
675 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
678 if (Msg
.message
== WM_LBUTTONUP
)
681 if (Msg
.message
!= WM_MOUSEMOVE
)
684 ht
= SendMessage(hWnd
, WM_NCHITTEST
, 0, MAKELPARAM(Msg
.pt
.x
, Msg
.pt
.y
));
685 Pressed
= (ht
== wParam
);
687 /* Only draw the buttons if the hit test changed */
688 if (ht
!= pWndContext
->lastHitTest
&&
689 (HT_ISBUTTON(ht
) || HT_ISBUTTON(pWndContext
->lastHitTest
)))
691 ThemeDrawCaptionButtons(&context
, 0, Pressed
? wParam
: 0);
692 pWndContext
->lastHitTest
= ht
;
696 ThemeDrawCaptionButtons(&context
, ht
, 0);
697 ThemeCleanupDrawContext(&context
);
702 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
707 DefWndNCHitTest(HWND hWnd
, POINT Point
)
713 wi
.cbSize
= sizeof(wi
);
714 GetWindowInfo(hWnd
, &wi
);
716 if (!PtInRect(&wi
.rcWindow
, Point
))
720 WindowRect
= wi
.rcWindow
;
722 if (UserHasWindowEdge(wi
.dwStyle
, wi
.dwExStyle
))
726 InflateRect(&WindowRect
, -(int)wi
.cxWindowBorders
, -(int)wi
.cyWindowBorders
);
727 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
728 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
729 if (!PtInRect(&WindowRect
, Point
))
733 ThickFrame
= (wi
.dwStyle
& WS_THICKFRAME
);
734 if (Point
.y
< WindowRect
.top
)
736 if(wi
.dwStyle
& WS_MINIMIZE
)
740 if (Point
.x
< (WindowRect
.left
+ XSize
))
742 if (Point
.x
>= (WindowRect
.right
- XSize
))
746 if (Point
.y
>= WindowRect
.bottom
)
748 if(wi
.dwStyle
& WS_MINIMIZE
)
752 if (Point
.x
< (WindowRect
.left
+ XSize
))
754 if (Point
.x
>= (WindowRect
.right
- XSize
))
755 return HTBOTTOMRIGHT
;
758 if (Point
.x
< WindowRect
.left
)
760 if(wi
.dwStyle
& WS_MINIMIZE
)
764 if (Point
.y
< (WindowRect
.top
+ YSize
))
766 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
770 if (Point
.x
>= WindowRect
.right
)
772 if(wi
.dwStyle
& WS_MINIMIZE
)
776 if (Point
.y
< (WindowRect
.top
+ YSize
))
778 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
779 return HTBOTTOMRIGHT
;
786 if (wi
.dwExStyle
& WS_EX_STATICEDGE
)
787 InflateRect(&WindowRect
, -GetSystemMetrics(SM_CXBORDER
),
788 -GetSystemMetrics(SM_CYBORDER
));
789 if (!PtInRect(&WindowRect
, Point
))
793 if ((wi
.dwStyle
& WS_CAPTION
) == WS_CAPTION
)
795 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
796 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
798 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
800 if (!PtInRect(&WindowRect
, Point
))
804 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
805 ButtonWidth
= GetSystemMetrics(SM_CXSMSIZE
);
807 ButtonWidth
= GetSystemMetrics(SM_CXSIZE
);
810 ButtonWidth
+= BUTTON_GAP_SIZE
;
812 if (wi
.dwStyle
& WS_SYSMENU
)
814 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
816 WindowRect
.right
-= ButtonWidth
;
820 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
821 // FIXME: The real test should check whether there is
822 // an icon for the system window, and if so, do the
823 // rect.left increase.
824 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
825 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
827 WindowRect
.left
+= ButtonWidth
;
828 WindowRect
.right
-= ButtonWidth
;
831 if (Point
.x
< WindowRect
.left
)
833 if (WindowRect
.right
<= Point
.x
)
835 if (wi
.dwStyle
& WS_MAXIMIZEBOX
|| wi
.dwStyle
& WS_MINIMIZEBOX
)
836 WindowRect
.right
-= ButtonWidth
;
837 if (Point
.x
>= WindowRect
.right
)
839 if (wi
.dwStyle
& WS_MINIMIZEBOX
)
840 WindowRect
.right
-= ButtonWidth
;
841 if (Point
.x
>= WindowRect
.right
)
847 if(!(wi
.dwStyle
& WS_MINIMIZE
))
852 ScreenToClient(hWnd
, &ClientPoint
);
853 GetClientRect(hWnd
, &wi
.rcClient
);
855 if (PtInRect(&wi
.rcClient
, ClientPoint
))
860 if ((menu
= GetMenu(hWnd
)) && !(wi
.dwStyle
& WS_CHILD
))
862 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
866 if (wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
868 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
869 -2 * GetSystemMetrics(SM_CYBORDER
));
872 if ((wi
.dwStyle
& WS_VSCROLL
) && (wi
.dwStyle
& WS_HSCROLL
) &&
873 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
875 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
876 HWND Parent
= GetParent(hWnd
);
878 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
879 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
880 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
882 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
883 if (PtInRect(&TempRect
, Point
))
886 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
887 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
888 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
890 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
891 if (PtInRect(&TempRect2
, Point
))
894 TempRect
.top
= TempRect2
.top
;
895 TempRect
.bottom
= TempRect2
.bottom
;
897 GetClientRect(Parent
, &ParentRect
);
898 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(wi
.dwStyle
, wi
.dwExStyle
,
899 GetWindowLongW(Parent
, GWL_STYLE
), wi
.rcWindow
, ParentRect
))
901 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
904 return HTBOTTOMRIGHT
;
909 if (wi
.dwStyle
& WS_VSCROLL
)
911 RECT TempRect
= WindowRect
;
913 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
914 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
916 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
917 if (PtInRect(&TempRect
, Point
))
920 else if (wi
.dwStyle
& WS_HSCROLL
)
922 RECT TempRect
= WindowRect
;
923 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
924 if (PtInRect(&TempRect
, Point
))
934 ThemeWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, WNDPROC DefWndProc
)
939 return ThemeHandleNCPaint(hWnd
, (HRGN
)wParam
);
941 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
943 case WM_NCUAHDRAWCAPTION
:
945 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
947 case WM_NCUAHDRAWFRAME
:
950 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) != WS_CAPTION
)
953 ThemeHandleNCPaint(hWnd
, (HRGN
)1);
958 Point
.x
= GET_X_LPARAM(lParam
);
959 Point
.y
= GET_Y_LPARAM(lParam
);
960 return ThemeHandleNcMouseMove(hWnd
, wParam
, &Point
);
962 case WM_NCMOUSELEAVE
:
963 return ThemeHandleNcMouseLeave(hWnd
);
964 case WM_NCLBUTTONDOWN
:
971 ThemeHandleButton(hWnd
, wParam
);
975 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
980 Point
.x
= GET_X_LPARAM(lParam
);
981 Point
.y
= GET_Y_LPARAM(lParam
);
982 return DefWndNCHitTest(hWnd
, Point
);
986 if((wParam
& 0xfff0) == SC_VSCROLL
||
987 (wParam
& 0xfff0) == SC_HSCROLL
)
990 Pt
.x
= (short)LOWORD(lParam
);
991 Pt
.y
= (short)HIWORD(lParam
);
992 NC_TrackScrollBar(hWnd
, wParam
, Pt
);
997 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1001 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1005 HRESULT WINAPI
DrawNCPreview(HDC hDC
,
1008 LPCWSTR pszThemeFileName
,
1009 LPCWSTR pszColorName
,
1010 LPCWSTR pszSizeName
,
1011 PNONCLIENTMETRICSW pncMetrics
,
1012 COLORREF
* lpaRgbValues
)
1014 WNDCLASSEXW DummyPreviewWindowClass
;
1017 HTHEMEFILE hThemeFile
;
1018 DRAW_CONTEXT context
;
1021 /* FIXME: We also need to implement drawing the rest of the preview windows
1022 * and make use of the ncmetrics and colors passed as parameters */
1024 /* Create a dummy window that will be used to trick the paint funtions */
1025 memset(&DummyPreviewWindowClass
, 0, sizeof(DummyPreviewWindowClass
));
1026 DummyPreviewWindowClass
.cbSize
= sizeof(DummyPreviewWindowClass
);
1027 DummyPreviewWindowClass
.lpszClassName
= L
"DummyPreviewWindowClass";
1028 DummyPreviewWindowClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
1029 DummyPreviewWindowClass
.hInstance
= hDllInst
;
1030 DummyPreviewWindowClass
.lpfnWndProc
= DefWindowProcW
;
1031 if (!RegisterClassExW(&DummyPreviewWindowClass
))
1034 hwndDummy
= CreateWindowExW(0, L
"DummyPreviewWindowClass", L
"Active window", WS_OVERLAPPEDWINDOW
,30,30,300,150,0,0,hDllInst
,NULL
);
1038 hres
= OpenThemeFile(pszThemeFileName
, pszColorName
, pszSizeName
, &hThemeFile
,0);
1042 /* Initialize the special draw context for the preview */
1044 context
.hWnd
= hwndDummy
;
1045 context
.theme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"WINDOW", 0);
1048 context
.scrolltheme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"SCROLLBAR", 0);
1051 context
.Active
= TRUE
;
1052 context
.wi
.cbSize
= sizeof(context
.wi
);
1053 if (!GetWindowInfo(hwndDummy
, &context
.wi
))
1055 context
.wi
.dwStyle
|= WS_VISIBLE
;
1056 context
.CaptionHeight
= context
.wi
.cyWindowBorders
;
1057 context
.CaptionHeight
+= GetSystemMetrics(context
.wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
1058 context
.hRgn
= CreateRectRgnIndirect(&context
.wi
.rcWindow
);
1060 /* Paint the window on the preview hDC */
1061 rcCurrent
= context
.wi
.rcWindow
;
1062 ThemePaintWindow(&context
, &rcCurrent
, FALSE
);
1064 ThemeCleanupDrawContext(&context
);
1067 DestroyWindow(hwndDummy
);
1068 UnregisterClassW(L
"DummyPreviewWindowClass", hDllInst
);