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
12 IsWindowActive(HWND hWnd
, DWORD ExStyle
)
16 if (ExStyle
& WS_EX_MDICHILD
)
18 ret
= IsChild(GetForegroundWindow(), hWnd
);
20 ret
= (hWnd
== (HWND
)SendMessageW(GetParent(hWnd
), WM_MDIGETACTIVE
, 0, 0));
24 ret
= (GetForegroundWindow() == hWnd
);
31 IsScrollBarVisible(HWND hWnd
, INT hBar
)
33 SCROLLBARINFO sbi
= {sizeof(SCROLLBARINFO
)};
34 if(!GetScrollBarInfo(hWnd
, hBar
, &sbi
))
37 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
41 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
43 if (Style
& WS_MINIMIZE
)
45 if (ExStyle
& WS_EX_DLGMODALFRAME
)
47 if (ExStyle
& WS_EX_STATICEDGE
)
49 if (Style
& WS_THICKFRAME
)
52 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
58 UserGetWindowIcon(PDRAW_CONTEXT pcontext
)
62 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
65 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
68 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
71 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICONSM
);
74 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICON
);
76 // See also win32ss/user/ntuser/nonclient.c!NC_IconForWindow
77 if (!hIcon
&& !(pcontext
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
78 hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_WINLOGO
);
83 HRESULT WINAPI
ThemeDrawCaptionText(PDRAW_CONTEXT pcontext
, RECT
* pRect
, int iPartId
, int iStateId
)
87 HGDIOBJ oldFont
= NULL
;
90 COLORREF oldTextColor
;
92 int drawStyles
= DT_VCENTER
| DT_SINGLELINE
| DT_END_ELLIPSIS
;
95 WCHAR
*pszText
= buffer
;
98 len
= InternalGetWindowText(pcontext
->hWnd
, NULL
, 0);
102 len
++; /* From now on this is the size of the buffer so include the null */
104 if (len
> ARRAYSIZE(buffer
))
106 pszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
108 return E_OUTOFMEMORY
;
111 InternalGetWindowText(pcontext
->hWnd
, pszText
, len
);
113 hr
= GetThemeSysFont(0,TMT_CAPTIONFONT
,&logfont
);
115 hFont
= CreateFontIndirectW(&logfont
);
118 oldFont
= SelectObject(pcontext
->hDC
, hFont
);
120 if (!pcontext
->Active
)
121 textColor
= GetSysColor(COLOR_INACTIVECAPTIONTEXT
);
123 textColor
= GetSysColor(COLOR_CAPTIONTEXT
);
125 GetThemeEnumValue(pcontext
->theme
, iPartId
, iStateId
, TMT_CONTENTALIGNMENT
, &align
);
126 if (align
== CA_CENTER
)
127 drawStyles
|= DT_CENTER
;
128 else if (align
== CA_RIGHT
)
129 drawStyles
|= DT_RIGHT
;
131 oldTextColor
= SetTextColor(pcontext
->hDC
, textColor
);
132 DrawThemeText(pcontext
->theme
,
141 SetTextColor(pcontext
->hDC
, oldTextColor
);
145 SelectObject(pcontext
->hDC
, oldFont
);
148 if (pszText
!= buffer
)
150 HeapFree(GetProcessHeap(), 0, pszText
);
156 ThemeInitDrawContext(PDRAW_CONTEXT pcontext
,
160 pcontext
->wi
.cbSize
= sizeof(pcontext
->wi
);
161 GetWindowInfo(hWnd
, &pcontext
->wi
);
162 pcontext
->hWnd
= hWnd
;
163 pcontext
->Active
= IsWindowActive(hWnd
, pcontext
->wi
.dwExStyle
);
164 pcontext
->theme
= GetNCCaptionTheme(hWnd
, pcontext
->wi
.dwStyle
);
165 pcontext
->scrolltheme
= GetNCScrollbarTheme(hWnd
, pcontext
->wi
.dwStyle
);
167 pcontext
->CaptionHeight
= pcontext
->wi
.cyWindowBorders
;
168 pcontext
->CaptionHeight
+= GetSystemMetrics(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
172 hRgn
= CreateRectRgnIndirect(&pcontext
->wi
.rcWindow
);
174 pcontext
->hRgn
= hRgn
;
176 pcontext
->hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
180 ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext
)
182 ReleaseDC(pcontext
->hWnd
,pcontext
->hDC
);
184 if(pcontext
->hRgn
!= NULL
)
186 DeleteObject(pcontext
->hRgn
);
191 ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext
, int cx
, int cy
)
195 pcontext
->hDCScreen
= pcontext
->hDC
;
196 pcontext
->hDC
= CreateCompatibleDC(pcontext
->hDCScreen
);
197 hbmp
= CreateCompatibleBitmap(pcontext
->hDCScreen
, cx
, cy
);
198 pcontext
->hbmpOld
= (HBITMAP
)SelectObject(pcontext
->hDC
, hbmp
);
202 ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext
, int x
, int y
, int cx
, int cy
)
205 BitBlt(pcontext
->hDCScreen
, 0, 0, cx
, cy
, pcontext
->hDC
, x
, y
, SRCCOPY
);
206 hbmp
= (HBITMAP
) SelectObject(pcontext
->hDC
, pcontext
->hbmpOld
);
207 DeleteObject(pcontext
->hDC
);
210 pcontext
->hDC
= pcontext
->hDCScreen
;
213 void ThemeCalculateCaptionButtonsPos(HWND hWnd
, HTHEME htheme
)
217 INT ButtonWidth
, ButtonHeight
, iPartId
, i
;
218 WINDOWINFO wi
= {sizeof(wi
)};
221 /* First of all check if we have something to do here */
222 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
223 if((style
& (WS_CAPTION
| WS_SYSMENU
)) != (WS_CAPTION
| WS_SYSMENU
))
226 /* Get theme data for this window */
227 pwndData
= ThemeGetWndData(hWnd
);
228 if (pwndData
== NULL
)
232 htheme
= pwndData
->hthemeWindow
;
234 if(!GetWindowInfo(hWnd
, &wi
))
237 /* Calculate the area of the caption */
238 rcCurrent
.top
= rcCurrent
.left
= 0;
239 rcCurrent
.right
= wi
.rcWindow
.right
- wi
.rcWindow
.left
;
240 rcCurrent
.bottom
= wi
.rcWindow
.bottom
- wi
.rcWindow
.top
;
242 /* Add a padding around the objects of the caption */
243 InflateRect(&rcCurrent
, -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
244 -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
246 for (i
= CLOSEBUTTON
; i
<= HELPBUTTON
; i
++)
253 iPartId
= wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
257 iPartId
= wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
261 iPartId
= wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
265 iPartId
= WP_HELPBUTTON
;
268 GetThemePartSize(htheme
, NULL
, iPartId
, 0, NULL
, TS_MIN
, &ButtonSize
);
270 ButtonHeight
= GetSystemMetrics( wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMSIZE
: SM_CYSIZE
);
271 ButtonWidth
= MulDiv(ButtonSize
.cx
, ButtonHeight
, ButtonSize
.cy
);
276 SetRect(&pwndData
->rcCaptionButtons
[i
],
277 rcCurrent
.right
- ButtonWidth
,
280 rcCurrent
.top
+ ButtonHeight
);
282 rcCurrent
.right
-= ButtonWidth
+ BUTTON_GAP_SIZE
;
287 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext
,
289 CAPTIONBUTTON buttonId
,
293 PWND_DATA pwndData
= ThemeGetWndData(pcontext
->hWnd
);
300 iPartId
= pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
304 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
306 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
309 iStateId
= BUTTON_DISABLED
;
312 iPartId
= pcontext
->wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
316 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
318 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
321 iStateId
= BUTTON_DISABLED
;
324 iPartId
= pcontext
->wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
328 //FIXME: Implement Help Button
333 prcCurrent
->right
= pwndData
->rcCaptionButtons
[buttonId
].left
;
335 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, iPartId
, iStateId
, &pwndData
->rcCaptionButtons
[buttonId
], NULL
);
339 ThemeGetButtonState(DWORD htCurrect
, DWORD htHot
, DWORD htDown
, BOOL Active
)
341 if (htHot
== htCurrect
)
344 return BUTTON_INACTIVE
;
345 if (htDown
== htCurrect
)
346 return BUTTON_PRESSED
;
348 return BUTTON_NORMAL
;
351 /* Used only from mouse event handlers */
353 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext
, DWORD htHot
, DWORD htDown
)
355 /* Draw the buttons */
356 ThemeDrawCaptionButton(pcontext
, NULL
, CLOSEBUTTON
,
357 ThemeGetButtonState(HTCLOSE
, htHot
, htDown
, pcontext
->Active
));
358 ThemeDrawCaptionButton(pcontext
, NULL
, MAXBUTTON
,
359 ThemeGetButtonState(HTMAXBUTTON
, htHot
, htDown
, pcontext
->Active
));
360 ThemeDrawCaptionButton(pcontext
, NULL
, MINBUTTON
,
361 ThemeGetButtonState(HTMINBUTTON
, htHot
, htDown
, pcontext
->Active
));
362 ThemeDrawCaptionButton(pcontext
, NULL
, HELPBUTTON
,
363 ThemeGetButtonState(HTHELP
, htHot
, htDown
, pcontext
->Active
));
366 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
368 ThemeDrawCaption(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
374 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
375 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
376 if ((pcontext
->wi
.dwStyle
& WS_SYSMENU
) && !(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
377 hIcon
= UserGetWindowIcon(pcontext
);
381 /* Get the caption part and state id */
382 if (pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
383 iPart
= WP_MINCAPTION
;
384 else if (pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
385 iPart
= WP_SMALLCAPTION
;
386 else if (pcontext
->wi
.dwStyle
& WS_MAXIMIZE
)
387 iPart
= WP_MAXCAPTION
;
391 iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
393 /* Draw the caption background */
394 rcPart
= *prcCurrent
;
395 rcPart
.bottom
= rcPart
.top
+ pcontext
->CaptionHeight
;
396 prcCurrent
->top
= rcPart
.bottom
;
397 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,iPart
,iState
,&rcPart
,NULL
);
399 /* Add a padding around the objects of the caption */
400 InflateRect(&rcPart
, -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
401 -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
403 /* Draw the caption buttons */
404 if (pcontext
->wi
.dwStyle
& WS_SYSMENU
)
406 iState
= pcontext
->Active
? BUTTON_NORMAL
: BUTTON_INACTIVE
;
408 ThemeDrawCaptionButton(pcontext
, &rcPart
, CLOSEBUTTON
, iState
);
409 ThemeDrawCaptionButton(pcontext
, &rcPart
, MAXBUTTON
, iState
);
410 ThemeDrawCaptionButton(pcontext
, &rcPart
, MINBUTTON
, iState
);
411 ThemeDrawCaptionButton(pcontext
, &rcPart
, HELPBUTTON
, iState
);
419 int IconHeight
= GetSystemMetrics(SM_CYSMICON
);
420 int IconWidth
= GetSystemMetrics(SM_CXSMICON
);
421 DrawIconEx(pcontext
->hDC
, rcPart
.left
, rcPart
.top
, hIcon
, IconWidth
, IconHeight
, 0, NULL
, DI_NORMAL
);
422 rcPart
.left
+= IconWidth
+ 4;
427 /* Draw the caption */
428 ThemeDrawCaptionText(pcontext
, &rcPart
, iPart
, iState
);
432 ThemeDrawBorders(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
435 int iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
437 /* Draw the bottom border */
438 rcPart
= *prcCurrent
;
439 rcPart
.top
= rcPart
.bottom
- pcontext
->wi
.cyWindowBorders
;
440 prcCurrent
->bottom
= rcPart
.top
;
441 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, WP_FRAMEBOTTOM
, iState
, &rcPart
, NULL
);
443 /* Draw the left border */
444 rcPart
= *prcCurrent
;
445 rcPart
.right
= rcPart
.left
+ pcontext
->wi
.cxWindowBorders
;
446 prcCurrent
->left
= rcPart
.right
;
447 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMELEFT
, iState
, &rcPart
, NULL
);
449 /* Draw the right border */
450 rcPart
= *prcCurrent
;
451 rcPart
.left
= rcPart
.right
- pcontext
->wi
.cxWindowBorders
;
452 prcCurrent
->right
= rcPart
.left
;
453 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMERIGHT
, iState
, &rcPart
, NULL
);
457 DrawClassicFrame(PDRAW_CONTEXT context
, RECT
* prcCurrent
)
459 /* Draw outer edge */
460 if (UserHasWindowEdge(context
->wi
.dwStyle
, context
->wi
.dwExStyle
))
462 DrawEdge(context
->hDC
, prcCurrent
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
464 else if (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
)
466 DrawEdge(context
->hDC
, prcCurrent
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
469 /* Firstly the "thick" frame */
470 if ((context
->wi
.dwStyle
& WS_THICKFRAME
) && !(context
->wi
.dwStyle
& WS_MINIMIZE
))
473 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
474 GetSystemMetrics(SM_CXBORDER
);
476 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
477 GetSystemMetrics(SM_CYBORDER
);
479 SelectObject(context
->hDC
, GetSysColorBrush(
480 context
->Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
483 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
484 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
485 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
486 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
487 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
488 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
489 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
490 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
492 InflateRect(prcCurrent
, -Width
, -Height
);
495 /* Now the other bit of the frame */
496 if (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_BORDER
) || (context
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
498 INT Width
= GetSystemMetrics(SM_CXBORDER
);
499 INT Height
= GetSystemMetrics(SM_CYBORDER
);
501 SelectObject(context
->hDC
, GetSysColorBrush(
502 (context
->wi
.dwExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
503 (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
504 (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
508 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
509 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
510 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
511 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
512 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
513 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
514 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
515 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
517 InflateRect(prcCurrent
, -Width
, -Height
);
521 static void ThemeDrawMenuBar(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
523 /* Let the window manager paint the menu */
524 prcCurrent
->top
+= PaintMenuBar(pcontext
->hWnd
,
526 pcontext
->wi
.cxWindowBorders
,
527 pcontext
->wi
.cxWindowBorders
,
532 static void ThemeDrawScrollBarsGrip(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
536 RECT ParentClientRect
;
539 rcPart
= *prcCurrent
;
541 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
542 rcPart
.right
= rcPart
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
544 rcPart
.left
= rcPart
.right
- GetSystemMetrics(SM_CXVSCROLL
);
546 rcPart
.top
= rcPart
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
548 FillRect(pcontext
->hDC
, &rcPart
, GetSysColorBrush(COLOR_BTNFACE
));
550 hwndParent
= GetParent(pcontext
->hWnd
);
551 GetClientRect(hwndParent
, &ParentClientRect
);
552 ParentStyle
= GetWindowLongW(hwndParent
, GWL_STYLE
);
554 if (HASSIZEGRIP(pcontext
->wi
.dwStyle
, pcontext
->wi
.dwExStyle
, ParentStyle
, pcontext
->wi
.rcWindow
, ParentClientRect
))
557 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
558 iState
= pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
;
560 iState
= SZB_RIGHTALIGN
;
561 DrawThemeBackground(pcontext
->scrolltheme
, pcontext
->hDC
, SBP_SIZEBOX
, iState
, &rcPart
, NULL
);
566 ThemePaintWindow(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
, BOOL bDoDoubleBuffering
)
568 if(!(pcontext
->wi
.dwStyle
& WS_VISIBLE
))
571 if((pcontext
->wi
.dwStyle
& WS_CAPTION
)==WS_CAPTION
)
573 if (bDoDoubleBuffering
)
574 ThemeStartBufferedPaint(pcontext
, prcCurrent
->right
, pcontext
->CaptionHeight
);
575 ThemeDrawCaption(pcontext
, prcCurrent
);
576 if (bDoDoubleBuffering
)
577 ThemeEndBufferedPaint(pcontext
, 0, 0, prcCurrent
->right
, pcontext
->CaptionHeight
);
578 ThemeDrawBorders(pcontext
, prcCurrent
);
582 DrawClassicFrame(pcontext
, prcCurrent
);
585 if(pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
588 if(HAS_MENU(pcontext
->hWnd
, pcontext
->wi
.dwStyle
))
589 ThemeDrawMenuBar(pcontext
, prcCurrent
);
591 if (pcontext
->wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
592 DrawEdge(pcontext
->hDC
, prcCurrent
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
594 if((pcontext
->wi
.dwStyle
& WS_HSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
))
595 ThemeDrawScrollBar(pcontext
, SB_HORZ
, NULL
);
597 if((pcontext
->wi
.dwStyle
& WS_VSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
598 ThemeDrawScrollBar(pcontext
, SB_VERT
, NULL
);
600 if((pcontext
->wi
.dwStyle
& (WS_HSCROLL
|WS_VSCROLL
)) == (WS_HSCROLL
|WS_VSCROLL
) &&
601 IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
) &&
602 IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
604 ThemeDrawScrollBarsGrip(pcontext
, prcCurrent
);
613 ThemeHandleNCPaint(HWND hWnd
, HRGN hRgn
)
615 DRAW_CONTEXT context
;
618 ThemeInitDrawContext(&context
, hWnd
, hRgn
);
620 rcCurrent
= context
.wi
.rcWindow
;
621 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
623 ThemePaintWindow(&context
, &rcCurrent
, TRUE
);
624 ThemeCleanupDrawContext(&context
);
630 ThemeHandleNcMouseMove(HWND hWnd
, DWORD ht
, POINT
* pt
)
632 DRAW_CONTEXT context
;
637 /* First of all check if we have something to do here */
638 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
639 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
642 /* Get theme data for this window */
643 pwndData
= ThemeGetWndData(hWnd
);
644 if (pwndData
== NULL
)
647 /* Begin tracking in the non client area if we are not tracking yet */
648 tme
.cbSize
= sizeof(TRACKMOUSEEVENT
);
649 tme
.dwFlags
= TME_QUERY
;
650 tme
.hwndTrack
= hWnd
;
651 TrackMouseEvent(&tme
);
652 if (tme
.dwFlags
!= (TME_LEAVE
| TME_NONCLIENT
))
654 tme
.hwndTrack
= hWnd
;
655 tme
.dwFlags
= TME_LEAVE
| TME_NONCLIENT
;
656 TrackMouseEvent(&tme
);
659 ThemeInitDrawContext(&context
, hWnd
, 0);
660 if (context
.wi
.dwStyle
& WS_SYSMENU
)
662 if (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
))
663 ThemeDrawCaptionButtons(&context
, ht
, 0);
666 if (context
.wi
.dwStyle
& WS_HSCROLL
)
668 if (ht
== HTHSCROLL
|| pwndData
->lastHitTest
== HTHSCROLL
)
669 ThemeDrawScrollBar(&context
, SB_HORZ
, ht
== HTHSCROLL
? pt
: NULL
);
672 if (context
.wi
.dwStyle
& WS_VSCROLL
)
674 if (ht
== HTVSCROLL
|| pwndData
->lastHitTest
== HTVSCROLL
)
675 ThemeDrawScrollBar(&context
, SB_VERT
, ht
== HTVSCROLL
? pt
: NULL
);
677 ThemeCleanupDrawContext(&context
);
679 pwndData
->lastHitTest
= ht
;
685 ThemeHandleNcMouseLeave(HWND hWnd
)
687 DRAW_CONTEXT context
;
691 /* First of all check if we have something to do here */
692 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
693 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
696 /* Get theme data for this window */
697 pwndData
= ThemeGetWndData(hWnd
);
698 if (pwndData
== NULL
)
701 ThemeInitDrawContext(&context
, hWnd
, 0);
702 if (context
.wi
.dwStyle
& WS_SYSMENU
&& HT_ISBUTTON(pwndData
->lastHitTest
))
703 ThemeDrawCaptionButtons(&context
, 0, 0);
705 if (context
.wi
.dwStyle
& WS_HSCROLL
&& pwndData
->lastHitTest
== HTHSCROLL
)
706 ThemeDrawScrollBar(&context
, SB_HORZ
, NULL
);
708 if (context
.wi
.dwStyle
& WS_VSCROLL
&& pwndData
->lastHitTest
== HTVSCROLL
)
709 ThemeDrawScrollBar(&context
, SB_VERT
, NULL
);
711 ThemeCleanupDrawContext(&context
);
713 pwndData
->lastHitTest
= HTNOWHERE
;
719 ThemeHandleButton(HWND hWnd
, WPARAM wParam
)
725 DRAW_CONTEXT context
;
728 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
729 if (!((Style
& WS_CAPTION
) && (Style
& WS_SYSMENU
)))
738 if (!(Style
& WS_MINIMIZEBOX
))
740 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
743 if (!(Style
& WS_MAXIMIZEBOX
))
745 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
751 /* Get theme data for this window */
752 pwndData
= ThemeGetWndData(hWnd
);
753 if (pwndData
== NULL
)
756 ThemeInitDrawContext(&context
, hWnd
, 0);
757 ThemeDrawCaptionButtons(&context
, 0, wParam
);
758 pwndData
->lastHitTest
= wParam
;
766 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
769 if (Msg
.message
== WM_LBUTTONUP
)
772 if (Msg
.message
!= WM_MOUSEMOVE
)
775 ht
= SendMessage(hWnd
, WM_NCHITTEST
, 0, MAKELPARAM(Msg
.pt
.x
, Msg
.pt
.y
));
776 Pressed
= (ht
== wParam
);
778 /* Only draw the buttons if the hit test changed */
779 if (ht
!= pwndData
->lastHitTest
&&
780 (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
)))
782 ThemeDrawCaptionButtons(&context
, 0, Pressed
? wParam
: 0);
783 pwndData
->lastHitTest
= ht
;
787 ThemeDrawCaptionButtons(&context
, ht
, 0);
788 ThemeCleanupDrawContext(&context
);
793 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
798 DefWndNCHitTest(HWND hWnd
, POINT Point
)
804 wi
.cbSize
= sizeof(wi
);
805 GetWindowInfo(hWnd
, &wi
);
807 if (!PtInRect(&wi
.rcWindow
, Point
))
811 WindowRect
= wi
.rcWindow
;
813 if (UserHasWindowEdge(wi
.dwStyle
, wi
.dwExStyle
))
817 InflateRect(&WindowRect
, -(int)wi
.cxWindowBorders
, -(int)wi
.cyWindowBorders
);
818 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
819 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
820 if (!PtInRect(&WindowRect
, Point
))
824 ThickFrame
= (wi
.dwStyle
& WS_THICKFRAME
);
825 if (Point
.y
< WindowRect
.top
)
827 if(wi
.dwStyle
& WS_MINIMIZE
)
831 if (Point
.x
< (WindowRect
.left
+ XSize
))
833 if (Point
.x
>= (WindowRect
.right
- XSize
))
837 if (Point
.y
>= WindowRect
.bottom
)
839 if(wi
.dwStyle
& WS_MINIMIZE
)
843 if (Point
.x
< (WindowRect
.left
+ XSize
))
845 if (Point
.x
>= (WindowRect
.right
- XSize
))
846 return HTBOTTOMRIGHT
;
849 if (Point
.x
< WindowRect
.left
)
851 if(wi
.dwStyle
& WS_MINIMIZE
)
855 if (Point
.y
< (WindowRect
.top
+ YSize
))
857 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
861 if (Point
.x
>= WindowRect
.right
)
863 if(wi
.dwStyle
& WS_MINIMIZE
)
867 if (Point
.y
< (WindowRect
.top
+ YSize
))
869 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
870 return HTBOTTOMRIGHT
;
877 if (wi
.dwExStyle
& WS_EX_STATICEDGE
)
878 InflateRect(&WindowRect
, -GetSystemMetrics(SM_CXBORDER
),
879 -GetSystemMetrics(SM_CYBORDER
));
880 if (!PtInRect(&WindowRect
, Point
))
884 if ((wi
.dwStyle
& WS_CAPTION
) == WS_CAPTION
)
886 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
887 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
889 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
891 if (!PtInRect(&WindowRect
, Point
))
893 if (wi
.dwStyle
& WS_SYSMENU
)
895 PWND_DATA pwndData
= ThemeGetWndData(hWnd
);
897 if (!(wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
899 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
900 // FIXME: The real test should check whether there is
901 // an icon for the system window, and if so, do the
902 // rect.left increase.
903 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
904 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
906 WindowRect
.left
+= GetSystemMetrics(SM_CXSMICON
);
911 POINT pt
= {Point
.x
- wi
.rcWindow
.left
, Point
.y
- wi
.rcWindow
.top
};
912 if (PtInRect(&pwndData
->rcCaptionButtons
[CLOSEBUTTON
], pt
))
914 if (PtInRect(&pwndData
->rcCaptionButtons
[MAXBUTTON
], pt
))
916 if (PtInRect(&pwndData
->rcCaptionButtons
[MINBUTTON
], pt
))
920 if (Point
.x
< WindowRect
.left
)
926 if(!(wi
.dwStyle
& WS_MINIMIZE
))
931 ScreenToClient(hWnd
, &ClientPoint
);
932 GetClientRect(hWnd
, &wi
.rcClient
);
934 if (PtInRect(&wi
.rcClient
, ClientPoint
))
939 if ((menu
= GetMenu(hWnd
)) && !(wi
.dwStyle
& WS_CHILD
))
941 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
945 if (wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
947 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
948 -2 * GetSystemMetrics(SM_CYBORDER
));
951 if ((wi
.dwStyle
& WS_VSCROLL
) && (wi
.dwStyle
& WS_HSCROLL
) &&
952 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
954 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
955 HWND Parent
= GetParent(hWnd
);
957 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
958 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
959 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
961 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
962 if (PtInRect(&TempRect
, Point
))
965 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
966 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
967 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
969 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
970 if (PtInRect(&TempRect2
, Point
))
973 TempRect
.top
= TempRect2
.top
;
974 TempRect
.bottom
= TempRect2
.bottom
;
976 GetClientRect(Parent
, &ParentRect
);
977 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(wi
.dwStyle
, wi
.dwExStyle
,
978 GetWindowLongW(Parent
, GWL_STYLE
), wi
.rcWindow
, ParentRect
))
980 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
983 return HTBOTTOMRIGHT
;
988 if (wi
.dwStyle
& WS_VSCROLL
)
990 RECT TempRect
= WindowRect
;
992 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
993 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
995 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
996 if (PtInRect(&TempRect
, Point
))
999 else if (wi
.dwStyle
& WS_HSCROLL
)
1001 RECT TempRect
= WindowRect
;
1002 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1003 if (PtInRect(&TempRect
, Point
))
1013 ThemeWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, WNDPROC DefWndProc
)
1018 return ThemeHandleNCPaint(hWnd
, (HRGN
)wParam
);
1020 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1022 case WM_NCUAHDRAWCAPTION
:
1024 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1026 case WM_NCUAHDRAWFRAME
:
1029 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) != WS_CAPTION
)
1032 ThemeHandleNCPaint(hWnd
, (HRGN
)1);
1034 case WM_NCMOUSEMOVE
:
1037 Point
.x
= GET_X_LPARAM(lParam
);
1038 Point
.y
= GET_Y_LPARAM(lParam
);
1039 return ThemeHandleNcMouseMove(hWnd
, wParam
, &Point
);
1041 case WM_NCMOUSELEAVE
:
1042 return ThemeHandleNcMouseLeave(hWnd
);
1043 case WM_NCLBUTTONDOWN
:
1050 ThemeHandleButton(hWnd
, wParam
);
1054 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1059 Point
.x
= GET_X_LPARAM(lParam
);
1060 Point
.y
= GET_Y_LPARAM(lParam
);
1061 return DefWndNCHitTest(hWnd
, Point
);
1065 if((wParam
& 0xfff0) == SC_VSCROLL
||
1066 (wParam
& 0xfff0) == SC_HSCROLL
)
1069 Pt
.x
= (short)LOWORD(lParam
);
1070 Pt
.y
= (short)HIWORD(lParam
);
1071 NC_TrackScrollBar(hWnd
, wParam
, Pt
);
1076 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1080 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1084 HRESULT WINAPI
DrawNCPreview(HDC hDC
,
1087 LPCWSTR pszThemeFileName
,
1088 LPCWSTR pszColorName
,
1089 LPCWSTR pszSizeName
,
1090 PNONCLIENTMETRICSW pncMetrics
,
1091 COLORREF
* lpaRgbValues
)
1093 WNDCLASSEXW DummyPreviewWindowClass
;
1096 HTHEMEFILE hThemeFile
;
1097 DRAW_CONTEXT context
;
1100 /* FIXME: We also need to implement drawing the rest of the preview windows
1101 * and make use of the ncmetrics and colors passed as parameters */
1103 /* Create a dummy window that will be used to trick the paint funtions */
1104 memset(&DummyPreviewWindowClass
, 0, sizeof(DummyPreviewWindowClass
));
1105 DummyPreviewWindowClass
.cbSize
= sizeof(DummyPreviewWindowClass
);
1106 DummyPreviewWindowClass
.lpszClassName
= L
"DummyPreviewWindowClass";
1107 DummyPreviewWindowClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
1108 DummyPreviewWindowClass
.hInstance
= hDllInst
;
1109 DummyPreviewWindowClass
.lpfnWndProc
= DefWindowProcW
;
1110 if (!RegisterClassExW(&DummyPreviewWindowClass
))
1113 hwndDummy
= CreateWindowExW(0, L
"DummyPreviewWindowClass", L
"Active window", WS_OVERLAPPEDWINDOW
,30,30,300,150,0,0,hDllInst
,NULL
);
1117 hres
= OpenThemeFile(pszThemeFileName
, pszColorName
, pszSizeName
, &hThemeFile
,0);
1121 /* Initialize the special draw context for the preview */
1123 context
.hWnd
= hwndDummy
;
1124 context
.theme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"WINDOW", 0);
1127 context
.scrolltheme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"SCROLLBAR", 0);
1128 if (!context
.scrolltheme
)
1130 context
.Active
= TRUE
;
1131 context
.wi
.cbSize
= sizeof(context
.wi
);
1132 if (!GetWindowInfo(hwndDummy
, &context
.wi
))
1134 context
.wi
.dwStyle
|= WS_VISIBLE
;
1135 context
.CaptionHeight
= context
.wi
.cyWindowBorders
;
1136 context
.CaptionHeight
+= GetSystemMetrics(context
.wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
1137 context
.hRgn
= CreateRectRgnIndirect(&context
.wi
.rcWindow
);
1139 /* Paint the window on the preview hDC */
1140 rcCurrent
= context
.wi
.rcWindow
;
1141 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
1142 SetViewportOrgEx(hDC
, context
.wi
.rcWindow
.left
, context
.wi
.rcWindow
.top
, NULL
);
1143 ThemeCalculateCaptionButtonsPos(hwndDummy
, context
.theme
);
1144 ThemePaintWindow(&context
, &rcCurrent
, FALSE
);
1145 SetViewportOrgEx(hDC
, 0, 0, NULL
);
1148 CloseThemeData (context
.theme
);
1149 CloseThemeData (context
.scrolltheme
);
1150 ThemeCleanupDrawContext(&context
);
1153 DestroyWindow(hwndDummy
);
1154 UnregisterClassW(L
"DummyPreviewWindowClass", hDllInst
);