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 IsScrollBarVisible(HWND hWnd
, INT hBar
)
53 SCROLLBARINFO sbi
= {sizeof(SCROLLBARINFO
)};
54 if(!GetScrollBarInfo(hWnd
, hBar
, &sbi
))
57 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
61 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
63 if (Style
& WS_MINIMIZE
)
65 if (ExStyle
& WS_EX_DLGMODALFRAME
)
67 if (ExStyle
& WS_EX_STATICEDGE
)
69 if (Style
& WS_THICKFRAME
)
72 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
78 UserGetWindowIcon(PDRAW_CONTEXT pcontext
)
82 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
85 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
88 SendMessageTimeout(pcontext
->hWnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
91 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICONSM
);
94 hIcon
= (HICON
)GetClassLong(pcontext
->hWnd
, GCL_HICON
);
96 // See also win32ss/user/ntuser/nonclient.c!NC_IconForWindow
97 if (!hIcon
&& !(pcontext
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
98 hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_WINLOGO
);
103 HRESULT WINAPI
ThemeDrawCaptionText(PDRAW_CONTEXT pcontext
, RECT
* pRect
, int iPartId
, int iStateId
)
107 HGDIOBJ oldFont
= NULL
;
110 COLORREF oldTextColor
;
113 WCHAR
*pszText
= buffer
;
116 len
= InternalGetWindowText(pcontext
->hWnd
, NULL
, 0);
120 len
++; /* From now on this is the size of the buffer so include the null */
122 if (len
> ARRAYSIZE(buffer
))
124 pszText
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
126 return E_OUTOFMEMORY
;
129 InternalGetWindowText(pcontext
->hWnd
, pszText
, len
);
131 hr
= GetThemeSysFont(0,TMT_CAPTIONFONT
,&logfont
);
133 hFont
= CreateFontIndirectW(&logfont
);
136 oldFont
= SelectObject(pcontext
->hDC
, hFont
);
138 if (!pcontext
->Active
)
139 textColor
= GetSysColor(COLOR_INACTIVECAPTIONTEXT
);
141 textColor
= GetSysColor(COLOR_CAPTIONTEXT
);
143 oldTextColor
= SetTextColor(pcontext
->hDC
, textColor
);
144 DrawThemeText(pcontext
->theme
,
150 DT_VCENTER
| DT_SINGLELINE
| DT_END_ELLIPSIS
,
153 SetTextColor(pcontext
->hDC
, oldTextColor
);
157 SelectObject(pcontext
->hDC
, oldFont
);
160 if (pszText
!= buffer
)
162 HeapFree(GetProcessHeap(), 0, pszText
);
168 ThemeInitDrawContext(PDRAW_CONTEXT pcontext
,
172 pcontext
->wi
.cbSize
= sizeof(pcontext
->wi
);
173 GetWindowInfo(hWnd
, &pcontext
->wi
);
174 pcontext
->hWnd
= hWnd
;
175 pcontext
->Active
= IsWindowActive(hWnd
, pcontext
->wi
.dwExStyle
);
176 pcontext
->theme
= GetNCCaptionTheme(hWnd
, pcontext
->wi
.dwStyle
);
177 pcontext
->scrolltheme
= GetNCScrollbarTheme(hWnd
, pcontext
->wi
.dwStyle
);
179 pcontext
->CaptionHeight
= pcontext
->wi
.cyWindowBorders
;
180 pcontext
->CaptionHeight
+= GetSystemMetrics(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
184 hRgn
= CreateRectRgnIndirect(&pcontext
->wi
.rcWindow
);
186 pcontext
->hRgn
= hRgn
;
188 pcontext
->hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
192 ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext
)
194 ReleaseDC(pcontext
->hWnd
,pcontext
->hDC
);
196 if(pcontext
->hRgn
!= NULL
)
198 DeleteObject(pcontext
->hRgn
);
203 ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext
, int cx
, int cy
)
207 pcontext
->hDCScreen
= pcontext
->hDC
;
208 pcontext
->hDC
= CreateCompatibleDC(pcontext
->hDCScreen
);
209 hbmp
= CreateCompatibleBitmap(pcontext
->hDCScreen
, cx
, cy
);
210 pcontext
->hbmpOld
= (HBITMAP
)SelectObject(pcontext
->hDC
, hbmp
);
214 ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext
, int x
, int y
, int cx
, int cy
)
217 BitBlt(pcontext
->hDCScreen
, 0, 0, cx
, cy
, pcontext
->hDC
, x
, y
, SRCCOPY
);
218 hbmp
= (HBITMAP
) SelectObject(pcontext
->hDC
, pcontext
->hbmpOld
);
219 DeleteObject(pcontext
->hDC
);
222 pcontext
->hDC
= pcontext
->hDCScreen
;
225 void ThemeCalculateCaptionButtonsPos(HWND hWnd
, HTHEME htheme
)
229 INT ButtonWidth
, ButtonHeight
, iPartId
, i
;
230 WINDOWINFO wi
= {sizeof(wi
)};
233 /* First of all check if we have something to do here */
234 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
235 if((style
& (WS_CAPTION
| WS_SYSMENU
)) != (WS_CAPTION
| WS_SYSMENU
))
238 /* Get theme data for this window */
239 pwndData
= ThemeGetWndData(hWnd
);
240 if (pwndData
== NULL
)
244 htheme
= pwndData
->hthemeWindow
;
246 if(!GetWindowInfo(hWnd
, &wi
))
249 /* Calculate the area of the caption */
250 rcCurrent
.top
= rcCurrent
.left
= 0;
251 rcCurrent
.right
= wi
.rcWindow
.right
- wi
.rcWindow
.left
;
252 rcCurrent
.bottom
= wi
.rcWindow
.bottom
- wi
.rcWindow
.top
;
254 /* Add a padding around the objects of the caption */
255 InflateRect(&rcCurrent
, -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
256 -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
258 for (i
= CLOSEBUTTON
; i
<= HELPBUTTON
; i
++)
265 iPartId
= wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
269 iPartId
= wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
273 iPartId
= wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
277 iPartId
= WP_HELPBUTTON
;
280 GetThemePartSize(htheme
, NULL
, iPartId
, 0, NULL
, TS_MIN
, &ButtonSize
);
282 ButtonHeight
= GetSystemMetrics( wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMSIZE
: SM_CYSIZE
);
283 ButtonWidth
= MulDiv(ButtonSize
.cx
, ButtonHeight
, ButtonSize
.cy
);
288 SetRect(&pwndData
->rcCaptionButtons
[i
],
289 rcCurrent
.right
- ButtonWidth
,
292 rcCurrent
.top
+ ButtonHeight
);
294 rcCurrent
.right
-= ButtonWidth
+ BUTTON_GAP_SIZE
;
299 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext
,
300 CAPTIONBUTTON buttonId
,
304 PWND_DATA pwndData
= ThemeGetWndData(pcontext
->hWnd
);
311 iPartId
= pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
315 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
317 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
320 iStateId
= BUTTON_DISABLED
;
323 iPartId
= pcontext
->wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
327 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
329 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
332 iStateId
= BUTTON_DISABLED
;
335 iPartId
= pcontext
->wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
339 //FIXME: Implement Help Button
343 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, iPartId
, iStateId
, &pwndData
->rcCaptionButtons
[buttonId
], NULL
);
347 ThemeGetButtonState(DWORD htCurrect
, DWORD htHot
, DWORD htDown
, BOOL Active
)
349 if (htHot
== htCurrect
)
352 return BUTTON_INACTIVE
;
353 if (htDown
== htCurrect
)
354 return BUTTON_PRESSED
;
356 return BUTTON_NORMAL
;
359 /* Used only from mouse event handlers */
361 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext
, DWORD htHot
, DWORD htDown
)
363 /* Draw the buttons */
364 ThemeDrawCaptionButton(pcontext
, CLOSEBUTTON
,
365 ThemeGetButtonState(HTCLOSE
, htHot
, htDown
, pcontext
->Active
));
366 ThemeDrawCaptionButton(pcontext
, MAXBUTTON
,
367 ThemeGetButtonState(HTMAXBUTTON
, htHot
, htDown
, pcontext
->Active
));
368 ThemeDrawCaptionButton(pcontext
, MINBUTTON
,
369 ThemeGetButtonState(HTMINBUTTON
, htHot
, htDown
, pcontext
->Active
));
370 ThemeDrawCaptionButton(pcontext
, HELPBUTTON
,
371 ThemeGetButtonState(HTHELP
, htHot
, htDown
, pcontext
->Active
));
374 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
376 ThemeDrawCaption(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
382 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
383 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
384 if ((pcontext
->wi
.dwStyle
& WS_SYSMENU
) && !(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
385 hIcon
= UserGetWindowIcon(pcontext
);
389 /* Get the caption part and state id */
390 if (pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
391 iPart
= WP_MINCAPTION
;
392 else if (pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
393 iPart
= WP_SMALLCAPTION
;
394 else if (pcontext
->wi
.dwStyle
& WS_MAXIMIZE
)
395 iPart
= WP_MAXCAPTION
;
399 iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
401 /* Draw the caption background */
402 rcPart
= *prcCurrent
;
403 rcPart
.bottom
= rcPart
.top
+ pcontext
->CaptionHeight
;
404 prcCurrent
->top
= rcPart
.bottom
;
405 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,iPart
,iState
,&rcPart
,NULL
);
407 /* Add a padding around the objects of the caption */
408 InflateRect(&rcPart
, -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
409 -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
411 /* Draw the caption buttons */
412 if (pcontext
->wi
.dwStyle
& WS_SYSMENU
)
414 iState
= pcontext
->Active
? BUTTON_NORMAL
: BUTTON_INACTIVE
;
416 ThemeDrawCaptionButton(pcontext
, CLOSEBUTTON
, iState
);
417 ThemeDrawCaptionButton(pcontext
, MAXBUTTON
, iState
);
418 ThemeDrawCaptionButton(pcontext
, MINBUTTON
, iState
);
419 ThemeDrawCaptionButton(pcontext
, HELPBUTTON
, iState
);
427 int IconHeight
= GetSystemMetrics(SM_CYSMICON
);
428 int IconWidth
= GetSystemMetrics(SM_CXSMICON
);
429 DrawIconEx(pcontext
->hDC
, rcPart
.left
, rcPart
.top
, hIcon
, IconWidth
, IconHeight
, 0, NULL
, DI_NORMAL
);
430 rcPart
.left
+= IconWidth
+ 4;
435 /* Draw the caption */
436 ThemeDrawCaptionText(pcontext
, &rcPart
, iPart
, iState
);
440 ThemeDrawBorders(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
443 int iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
445 /* Draw the bottom border */
446 rcPart
= *prcCurrent
;
447 rcPart
.top
= rcPart
.bottom
- pcontext
->wi
.cyWindowBorders
;
448 prcCurrent
->bottom
= rcPart
.top
;
449 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, WP_FRAMEBOTTOM
, iState
, &rcPart
, NULL
);
451 /* Draw the left border */
452 rcPart
= *prcCurrent
;
453 rcPart
.right
= rcPart
.left
+ pcontext
->wi
.cxWindowBorders
;
454 prcCurrent
->left
= rcPart
.right
;
455 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMELEFT
, iState
, &rcPart
, NULL
);
457 /* Draw the right border */
458 rcPart
= *prcCurrent
;
459 rcPart
.left
= rcPart
.right
- pcontext
->wi
.cxWindowBorders
;
460 prcCurrent
->right
= rcPart
.left
;
461 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMERIGHT
, iState
, &rcPart
, NULL
);
465 DrawClassicFrame(PDRAW_CONTEXT context
, RECT
* prcCurrent
)
467 /* Draw outer edge */
468 if (UserHasWindowEdge(context
->wi
.dwStyle
, context
->wi
.dwExStyle
))
470 DrawEdge(context
->hDC
, prcCurrent
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
472 else if (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
)
474 DrawEdge(context
->hDC
, prcCurrent
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
477 /* Firstly the "thick" frame */
478 if ((context
->wi
.dwStyle
& WS_THICKFRAME
) && !(context
->wi
.dwStyle
& WS_MINIMIZE
))
481 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
482 GetSystemMetrics(SM_CXBORDER
);
484 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
485 GetSystemMetrics(SM_CYBORDER
);
487 SelectObject(context
->hDC
, GetSysColorBrush(
488 context
->Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
491 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
492 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
493 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
494 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
495 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
496 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
497 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
498 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
500 InflateRect(prcCurrent
, -Width
, -Height
);
503 /* Now the other bit of the frame */
504 if (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_BORDER
) || (context
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
506 INT Width
= GetSystemMetrics(SM_CXBORDER
);
507 INT Height
= GetSystemMetrics(SM_CYBORDER
);
509 SelectObject(context
->hDC
, GetSysColorBrush(
510 (context
->wi
.dwExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
511 (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
512 (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
516 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
517 prcCurrent
->right
- prcCurrent
->left
, Height
, PATCOPY
);
518 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->top
,
519 Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
520 PatBlt(context
->hDC
, prcCurrent
->left
, prcCurrent
->bottom
- 1,
521 prcCurrent
->right
- prcCurrent
->left
, -Height
, PATCOPY
);
522 PatBlt(context
->hDC
, prcCurrent
->right
- 1, prcCurrent
->top
,
523 -Width
, prcCurrent
->bottom
- prcCurrent
->top
, PATCOPY
);
525 InflateRect(prcCurrent
, -Width
, -Height
);
529 static void ThemeDrawMenuBar(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
531 /* Let the window manager paint the menu */
532 prcCurrent
->top
+= PaintMenuBar(pcontext
->hWnd
,
534 pcontext
->wi
.cxWindowBorders
,
535 pcontext
->wi
.cxWindowBorders
,
540 static void ThemeDrawScrollBarsGrip(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
544 RECT ParentClientRect
;
547 rcPart
= *prcCurrent
;
549 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
550 rcPart
.right
= rcPart
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
552 rcPart
.left
= rcPart
.right
- GetSystemMetrics(SM_CXVSCROLL
);
554 rcPart
.top
= rcPart
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
556 FillRect(pcontext
->hDC
, &rcPart
, GetSysColorBrush(COLOR_BTNFACE
));
558 hwndParent
= GetParent(pcontext
->hWnd
);
559 GetClientRect(hwndParent
, &ParentClientRect
);
560 ParentStyle
= GetWindowLongW(hwndParent
, GWL_STYLE
);
562 if (HASSIZEGRIP(pcontext
->wi
.dwStyle
, pcontext
->wi
.dwExStyle
, ParentStyle
, pcontext
->wi
.rcWindow
, ParentClientRect
))
565 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
566 iState
= pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
;
568 iState
= SZB_RIGHTALIGN
;
569 DrawThemeBackground(pcontext
->scrolltheme
, pcontext
->hDC
, SBP_SIZEBOX
, iState
, &rcPart
, NULL
);
574 ThemePaintWindow(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
, BOOL bDoDoubleBuffering
)
576 if(!(pcontext
->wi
.dwStyle
& WS_VISIBLE
))
579 if((pcontext
->wi
.dwStyle
& WS_CAPTION
)==WS_CAPTION
)
581 if (bDoDoubleBuffering
)
582 ThemeStartBufferedPaint(pcontext
, prcCurrent
->right
, pcontext
->CaptionHeight
);
583 ThemeDrawCaption(pcontext
, prcCurrent
);
584 if (bDoDoubleBuffering
)
585 ThemeEndBufferedPaint(pcontext
, 0, 0, prcCurrent
->right
, pcontext
->CaptionHeight
);
586 ThemeDrawBorders(pcontext
, prcCurrent
);
590 DrawClassicFrame(pcontext
, prcCurrent
);
593 if(pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
596 if(HAS_MENU(pcontext
->hWnd
, pcontext
->wi
.dwStyle
))
597 ThemeDrawMenuBar(pcontext
, prcCurrent
);
599 if (pcontext
->wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
600 DrawEdge(pcontext
->hDC
, prcCurrent
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
602 if((pcontext
->wi
.dwStyle
& WS_HSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
))
603 ThemeDrawScrollBar(pcontext
, SB_HORZ
, NULL
);
605 if((pcontext
->wi
.dwStyle
& WS_VSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
606 ThemeDrawScrollBar(pcontext
, SB_VERT
, NULL
);
608 if((pcontext
->wi
.dwStyle
& (WS_HSCROLL
|WS_VSCROLL
)) == (WS_HSCROLL
|WS_VSCROLL
) &&
609 IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
) &&
610 IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
612 ThemeDrawScrollBarsGrip(pcontext
, prcCurrent
);
621 ThemeHandleNCPaint(HWND hWnd
, HRGN hRgn
)
623 DRAW_CONTEXT context
;
626 ThemeInitDrawContext(&context
, hWnd
, hRgn
);
628 rcCurrent
= context
.wi
.rcWindow
;
629 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
631 ThemePaintWindow(&context
, &rcCurrent
, TRUE
);
632 ThemeCleanupDrawContext(&context
);
638 ThemeHandleNcMouseMove(HWND hWnd
, DWORD ht
, POINT
* pt
)
640 DRAW_CONTEXT context
;
645 /* First of all check if we have something to do here */
646 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
647 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
650 /* Get theme data for this window */
651 pwndData
= ThemeGetWndData(hWnd
);
652 if (pwndData
== NULL
)
655 /* Begin tracking in the non client area if we are not tracking yet */
656 tme
.cbSize
= sizeof(TRACKMOUSEEVENT
);
657 tme
.dwFlags
= TME_QUERY
;
658 tme
.hwndTrack
= hWnd
;
659 TrackMouseEvent(&tme
);
660 if (tme
.dwFlags
!= (TME_LEAVE
| TME_NONCLIENT
))
662 tme
.hwndTrack
= hWnd
;
663 tme
.dwFlags
= TME_LEAVE
| TME_NONCLIENT
;
664 TrackMouseEvent(&tme
);
667 ThemeInitDrawContext(&context
, hWnd
, 0);
668 if (context
.wi
.dwStyle
& WS_SYSMENU
)
670 if (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
))
671 ThemeDrawCaptionButtons(&context
, ht
, 0);
674 if (context
.wi
.dwStyle
& WS_HSCROLL
)
676 if (ht
== HTHSCROLL
|| pwndData
->lastHitTest
== HTHSCROLL
)
677 ThemeDrawScrollBar(&context
, SB_HORZ
, ht
== HTHSCROLL
? pt
: NULL
);
680 if (context
.wi
.dwStyle
& WS_VSCROLL
)
682 if (ht
== HTVSCROLL
|| pwndData
->lastHitTest
== HTVSCROLL
)
683 ThemeDrawScrollBar(&context
, SB_VERT
, ht
== HTVSCROLL
? pt
: NULL
);
685 ThemeCleanupDrawContext(&context
);
687 pwndData
->lastHitTest
= ht
;
693 ThemeHandleNcMouseLeave(HWND hWnd
)
695 DRAW_CONTEXT context
;
699 /* First of all check if we have something to do here */
700 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
701 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
704 /* Get theme data for this window */
705 pwndData
= ThemeGetWndData(hWnd
);
706 if (pwndData
== NULL
)
709 ThemeInitDrawContext(&context
, hWnd
, 0);
710 if (context
.wi
.dwStyle
& WS_SYSMENU
&& HT_ISBUTTON(pwndData
->lastHitTest
))
711 ThemeDrawCaptionButtons(&context
, 0, 0);
713 if (context
.wi
.dwStyle
& WS_HSCROLL
&& pwndData
->lastHitTest
== HTHSCROLL
)
714 ThemeDrawScrollBar(&context
, SB_HORZ
, NULL
);
716 if (context
.wi
.dwStyle
& WS_VSCROLL
&& pwndData
->lastHitTest
== HTVSCROLL
)
717 ThemeDrawScrollBar(&context
, SB_VERT
, NULL
);
719 ThemeCleanupDrawContext(&context
);
721 pwndData
->lastHitTest
= HTNOWHERE
;
727 ThemeHandleButton(HWND hWnd
, WPARAM wParam
)
733 DRAW_CONTEXT context
;
736 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
737 if (!((Style
& WS_CAPTION
) && (Style
& WS_SYSMENU
)))
746 if (!(Style
& WS_MINIMIZEBOX
))
748 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
751 if (!(Style
& WS_MAXIMIZEBOX
))
753 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
759 /* Get theme data for this window */
760 pwndData
= ThemeGetWndData(hWnd
);
761 if (pwndData
== NULL
)
764 ThemeInitDrawContext(&context
, hWnd
, 0);
765 ThemeDrawCaptionButtons(&context
, 0, wParam
);
766 pwndData
->lastHitTest
= wParam
;
774 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
777 if (Msg
.message
== WM_LBUTTONUP
)
780 if (Msg
.message
!= WM_MOUSEMOVE
)
783 ht
= SendMessage(hWnd
, WM_NCHITTEST
, 0, MAKELPARAM(Msg
.pt
.x
, Msg
.pt
.y
));
784 Pressed
= (ht
== wParam
);
786 /* Only draw the buttons if the hit test changed */
787 if (ht
!= pwndData
->lastHitTest
&&
788 (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
)))
790 ThemeDrawCaptionButtons(&context
, 0, Pressed
? wParam
: 0);
791 pwndData
->lastHitTest
= ht
;
795 ThemeDrawCaptionButtons(&context
, ht
, 0);
796 ThemeCleanupDrawContext(&context
);
801 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
806 DefWndNCHitTest(HWND hWnd
, POINT Point
)
812 wi
.cbSize
= sizeof(wi
);
813 GetWindowInfo(hWnd
, &wi
);
815 if (!PtInRect(&wi
.rcWindow
, Point
))
819 WindowRect
= wi
.rcWindow
;
821 if (UserHasWindowEdge(wi
.dwStyle
, wi
.dwExStyle
))
825 InflateRect(&WindowRect
, -(int)wi
.cxWindowBorders
, -(int)wi
.cyWindowBorders
);
826 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
827 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
828 if (!PtInRect(&WindowRect
, Point
))
832 ThickFrame
= (wi
.dwStyle
& WS_THICKFRAME
);
833 if (Point
.y
< WindowRect
.top
)
835 if(wi
.dwStyle
& WS_MINIMIZE
)
839 if (Point
.x
< (WindowRect
.left
+ XSize
))
841 if (Point
.x
>= (WindowRect
.right
- XSize
))
845 if (Point
.y
>= WindowRect
.bottom
)
847 if(wi
.dwStyle
& WS_MINIMIZE
)
851 if (Point
.x
< (WindowRect
.left
+ XSize
))
853 if (Point
.x
>= (WindowRect
.right
- XSize
))
854 return HTBOTTOMRIGHT
;
857 if (Point
.x
< WindowRect
.left
)
859 if(wi
.dwStyle
& WS_MINIMIZE
)
863 if (Point
.y
< (WindowRect
.top
+ YSize
))
865 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
869 if (Point
.x
>= WindowRect
.right
)
871 if(wi
.dwStyle
& WS_MINIMIZE
)
875 if (Point
.y
< (WindowRect
.top
+ YSize
))
877 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
878 return HTBOTTOMRIGHT
;
885 if (wi
.dwExStyle
& WS_EX_STATICEDGE
)
886 InflateRect(&WindowRect
, -GetSystemMetrics(SM_CXBORDER
),
887 -GetSystemMetrics(SM_CYBORDER
));
888 if (!PtInRect(&WindowRect
, Point
))
892 if ((wi
.dwStyle
& WS_CAPTION
) == WS_CAPTION
)
894 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
895 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
897 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
899 if (!PtInRect(&WindowRect
, Point
))
901 if (wi
.dwStyle
& WS_SYSMENU
)
903 PWND_DATA pwndData
= ThemeGetWndData(hWnd
);
905 if (!(wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
907 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
908 // FIXME: The real test should check whether there is
909 // an icon for the system window, and if so, do the
910 // rect.left increase.
911 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
912 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
914 WindowRect
.left
+= GetSystemMetrics(SM_CXSMICON
);
919 POINT pt
= {Point
.x
- wi
.rcWindow
.left
, Point
.y
- wi
.rcWindow
.top
};
920 if (PtInRect(&pwndData
->rcCaptionButtons
[CLOSEBUTTON
], pt
))
922 if (PtInRect(&pwndData
->rcCaptionButtons
[MAXBUTTON
], pt
))
924 if (PtInRect(&pwndData
->rcCaptionButtons
[MINBUTTON
], pt
))
928 if (Point
.x
< WindowRect
.left
)
934 if(!(wi
.dwStyle
& WS_MINIMIZE
))
939 ScreenToClient(hWnd
, &ClientPoint
);
940 GetClientRect(hWnd
, &wi
.rcClient
);
942 if (PtInRect(&wi
.rcClient
, ClientPoint
))
947 if ((menu
= GetMenu(hWnd
)) && !(wi
.dwStyle
& WS_CHILD
))
949 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
953 if (wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
955 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
956 -2 * GetSystemMetrics(SM_CYBORDER
));
959 if ((wi
.dwStyle
& WS_VSCROLL
) && (wi
.dwStyle
& WS_HSCROLL
) &&
960 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
962 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
963 HWND Parent
= GetParent(hWnd
);
965 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
966 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
967 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
969 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
970 if (PtInRect(&TempRect
, Point
))
973 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
974 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
975 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
977 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
978 if (PtInRect(&TempRect2
, Point
))
981 TempRect
.top
= TempRect2
.top
;
982 TempRect
.bottom
= TempRect2
.bottom
;
984 GetClientRect(Parent
, &ParentRect
);
985 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(wi
.dwStyle
, wi
.dwExStyle
,
986 GetWindowLongW(Parent
, GWL_STYLE
), wi
.rcWindow
, ParentRect
))
988 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
991 return HTBOTTOMRIGHT
;
996 if (wi
.dwStyle
& WS_VSCROLL
)
998 RECT TempRect
= WindowRect
;
1000 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1001 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1003 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1004 if (PtInRect(&TempRect
, Point
))
1007 else if (wi
.dwStyle
& WS_HSCROLL
)
1009 RECT TempRect
= WindowRect
;
1010 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1011 if (PtInRect(&TempRect
, Point
))
1021 ThemeWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, WNDPROC DefWndProc
)
1026 return ThemeHandleNCPaint(hWnd
, (HRGN
)wParam
);
1028 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1030 case WM_NCUAHDRAWCAPTION
:
1032 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1034 case WM_NCUAHDRAWFRAME
:
1037 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) != WS_CAPTION
)
1040 ThemeHandleNCPaint(hWnd
, (HRGN
)1);
1042 case WM_NCMOUSEMOVE
:
1045 Point
.x
= GET_X_LPARAM(lParam
);
1046 Point
.y
= GET_Y_LPARAM(lParam
);
1047 return ThemeHandleNcMouseMove(hWnd
, wParam
, &Point
);
1049 case WM_NCMOUSELEAVE
:
1050 return ThemeHandleNcMouseLeave(hWnd
);
1051 case WM_NCLBUTTONDOWN
:
1058 ThemeHandleButton(hWnd
, wParam
);
1062 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1067 Point
.x
= GET_X_LPARAM(lParam
);
1068 Point
.y
= GET_Y_LPARAM(lParam
);
1069 return DefWndNCHitTest(hWnd
, Point
);
1073 if((wParam
& 0xfff0) == SC_VSCROLL
||
1074 (wParam
& 0xfff0) == SC_HSCROLL
)
1077 Pt
.x
= (short)LOWORD(lParam
);
1078 Pt
.y
= (short)HIWORD(lParam
);
1079 NC_TrackScrollBar(hWnd
, wParam
, Pt
);
1084 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1088 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1092 HRESULT WINAPI
DrawNCPreview(HDC hDC
,
1095 LPCWSTR pszThemeFileName
,
1096 LPCWSTR pszColorName
,
1097 LPCWSTR pszSizeName
,
1098 PNONCLIENTMETRICSW pncMetrics
,
1099 COLORREF
* lpaRgbValues
)
1101 WNDCLASSEXW DummyPreviewWindowClass
;
1104 HTHEMEFILE hThemeFile
;
1105 DRAW_CONTEXT context
;
1108 /* FIXME: We also need to implement drawing the rest of the preview windows
1109 * and make use of the ncmetrics and colors passed as parameters */
1111 /* Create a dummy window that will be used to trick the paint funtions */
1112 memset(&DummyPreviewWindowClass
, 0, sizeof(DummyPreviewWindowClass
));
1113 DummyPreviewWindowClass
.cbSize
= sizeof(DummyPreviewWindowClass
);
1114 DummyPreviewWindowClass
.lpszClassName
= L
"DummyPreviewWindowClass";
1115 DummyPreviewWindowClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
1116 DummyPreviewWindowClass
.hInstance
= hDllInst
;
1117 DummyPreviewWindowClass
.lpfnWndProc
= DefWindowProcW
;
1118 if (!RegisterClassExW(&DummyPreviewWindowClass
))
1121 hwndDummy
= CreateWindowExW(0, L
"DummyPreviewWindowClass", L
"Active window", WS_OVERLAPPEDWINDOW
,30,30,300,150,0,0,hDllInst
,NULL
);
1125 hres
= OpenThemeFile(pszThemeFileName
, pszColorName
, pszSizeName
, &hThemeFile
,0);
1129 /* Initialize the special draw context for the preview */
1131 context
.hWnd
= hwndDummy
;
1132 context
.theme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"WINDOW", 0);
1135 context
.scrolltheme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"SCROLLBAR", 0);
1136 if (!context
.scrolltheme
)
1138 context
.Active
= TRUE
;
1139 context
.wi
.cbSize
= sizeof(context
.wi
);
1140 if (!GetWindowInfo(hwndDummy
, &context
.wi
))
1142 context
.wi
.dwStyle
|= WS_VISIBLE
;
1143 context
.CaptionHeight
= context
.wi
.cyWindowBorders
;
1144 context
.CaptionHeight
+= GetSystemMetrics(context
.wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
1145 context
.hRgn
= CreateRectRgnIndirect(&context
.wi
.rcWindow
);
1147 /* Paint the window on the preview hDC */
1148 rcCurrent
= context
.wi
.rcWindow
;
1149 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
1150 SetViewportOrgEx(hDC
, context
.wi
.rcWindow
.left
, context
.wi
.rcWindow
.top
, NULL
);
1151 ThemeCalculateCaptionButtonsPos(hwndDummy
, context
.theme
);
1152 ThemePaintWindow(&context
, &rcCurrent
, FALSE
);
1153 SetViewportOrgEx(hDC
, 0, 0, NULL
);
1156 CloseThemeData (context
.theme
);
1157 CloseThemeData (context
.scrolltheme
);
1158 ThemeCleanupDrawContext(&context
);
1161 DestroyWindow(hwndDummy
);
1162 UnregisterClassW(L
"DummyPreviewWindowClass", hDllInst
);