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
)};
222 /* First of all check if we have something to do here */
223 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
224 if((style
& (WS_CAPTION
| WS_SYSMENU
)) != (WS_CAPTION
| WS_SYSMENU
))
227 /* Get theme data for this window */
228 pwndData
= ThemeGetWndData(hWnd
);
229 if (pwndData
== NULL
)
233 htheme
= pwndData
->hthemeWindow
;
235 if(!GetWindowInfo(hWnd
, &wi
))
238 /* Calculate the area of the caption */
239 rcCurrent
.top
= rcCurrent
.left
= 0;
240 rcCurrent
.right
= wi
.rcWindow
.right
- wi
.rcWindow
.left
;
241 rcCurrent
.bottom
= wi
.rcWindow
.bottom
- wi
.rcWindow
.top
;
243 /* Add a padding around the objects of the caption */
244 InflateRect(&rcCurrent
, -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
245 -(int)wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
247 iPartId
= wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
249 GetThemePartSize(htheme
, NULL
, iPartId
, 0, NULL
, TS_MIN
, &ButtonSize
);
251 ButtonHeight
= GetSystemMetrics( wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMSIZE
: SM_CYSIZE
);
252 ButtonWidth
= MulDiv(ButtonSize
.cx
, ButtonHeight
, ButtonSize
.cy
);
257 for (i
= CLOSEBUTTON
; i
<= HELPBUTTON
; i
++)
259 SetRect(&pwndData
->rcCaptionButtons
[i
],
260 rcCurrent
.right
- ButtonWidth
,
263 rcCurrent
.top
+ ButtonHeight
);
265 rcCurrent
.right
-= ButtonWidth
+ BUTTON_GAP_SIZE
;
270 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext
,
272 CAPTIONBUTTON buttonId
,
276 PWND_DATA pwndData
= ThemeGetWndData(pcontext
->hWnd
);
283 iPartId
= pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
? WP_SMALLCLOSEBUTTON
: WP_CLOSEBUTTON
;
287 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
289 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
292 iStateId
= BUTTON_DISABLED
;
295 iPartId
= pcontext
->wi
.dwStyle
& WS_MAXIMIZE
? WP_RESTOREBUTTON
: WP_MAXBUTTON
;
299 if (!(pcontext
->wi
.dwStyle
& WS_MINIMIZEBOX
))
301 if (!(pcontext
->wi
.dwStyle
& WS_MAXIMIZEBOX
))
304 iStateId
= BUTTON_DISABLED
;
307 iPartId
= pcontext
->wi
.dwStyle
& WS_MINIMIZE
? WP_RESTOREBUTTON
: WP_MINBUTTON
;
311 //FIXME: Implement Help Button
316 prcCurrent
->right
= pwndData
->rcCaptionButtons
[buttonId
].left
;
318 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, iPartId
, iStateId
, &pwndData
->rcCaptionButtons
[buttonId
], NULL
);
322 ThemeGetButtonState(DWORD htCurrect
, DWORD htHot
, DWORD htDown
, BOOL Active
)
324 if (htHot
== htCurrect
)
327 return BUTTON_INACTIVE
;
328 if (htDown
== htCurrect
)
329 return BUTTON_PRESSED
;
331 return BUTTON_NORMAL
;
334 /* Used only from mouse event handlers */
336 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext
, DWORD htHot
, DWORD htDown
)
338 /* Draw the buttons */
339 ThemeDrawCaptionButton(pcontext
, NULL
, CLOSEBUTTON
,
340 ThemeGetButtonState(HTCLOSE
, htHot
, htDown
, pcontext
->Active
));
341 ThemeDrawCaptionButton(pcontext
, NULL
, MAXBUTTON
,
342 ThemeGetButtonState(HTMAXBUTTON
, htHot
, htDown
, pcontext
->Active
));
343 ThemeDrawCaptionButton(pcontext
, NULL
, MINBUTTON
,
344 ThemeGetButtonState(HTMINBUTTON
, htHot
, htDown
, pcontext
->Active
));
345 ThemeDrawCaptionButton(pcontext
, NULL
, HELPBUTTON
,
346 ThemeGetButtonState(HTHELP
, htHot
, htDown
, pcontext
->Active
));
349 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */
351 ThemeDrawCaption(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
357 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar
358 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption
359 if ((pcontext
->wi
.dwStyle
& WS_SYSMENU
) && !(pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
360 hIcon
= UserGetWindowIcon(pcontext
);
364 /* Get the caption part and state id */
365 if (pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
366 iPart
= WP_MINCAPTION
;
367 else if (pcontext
->wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
368 iPart
= WP_SMALLCAPTION
;
369 else if (pcontext
->wi
.dwStyle
& WS_MAXIMIZE
)
370 iPart
= WP_MAXCAPTION
;
374 iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
376 /* Draw the caption background */
377 rcPart
= *prcCurrent
;
378 rcPart
.bottom
= rcPart
.top
+ pcontext
->CaptionHeight
;
379 prcCurrent
->top
= rcPart
.bottom
;
380 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,iPart
,iState
,&rcPart
,NULL
);
382 /* Add a padding around the objects of the caption */
383 InflateRect(&rcPart
, -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
,
384 -(int)pcontext
->wi
.cyWindowBorders
-BUTTON_GAP_SIZE
);
386 /* Draw the caption buttons */
387 if (pcontext
->wi
.dwStyle
& WS_SYSMENU
)
389 iState
= pcontext
->Active
? BUTTON_NORMAL
: BUTTON_INACTIVE
;
391 ThemeDrawCaptionButton(pcontext
, &rcPart
, CLOSEBUTTON
, iState
);
392 ThemeDrawCaptionButton(pcontext
, &rcPart
, MAXBUTTON
, iState
);
393 ThemeDrawCaptionButton(pcontext
, &rcPart
, MINBUTTON
, iState
);
394 ThemeDrawCaptionButton(pcontext
, &rcPart
, HELPBUTTON
, iState
);
402 int IconHeight
= GetSystemMetrics(SM_CYSMICON
);
403 int IconWidth
= GetSystemMetrics(SM_CXSMICON
);
404 DrawIconEx(pcontext
->hDC
, rcPart
.left
, rcPart
.top
, hIcon
, IconWidth
, IconHeight
, 0, NULL
, DI_NORMAL
);
405 rcPart
.left
+= IconWidth
+ 4;
410 /* Draw the caption */
411 ThemeDrawCaptionText(pcontext
, &rcPart
, iPart
, iState
);
415 ThemeDrawBorders(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
418 int iState
= pcontext
->Active
? FS_ACTIVE
: FS_INACTIVE
;
420 /* Draw the bottom border */
421 rcPart
= *prcCurrent
;
422 rcPart
.top
= rcPart
.bottom
- pcontext
->wi
.cyWindowBorders
;
423 prcCurrent
->bottom
= rcPart
.top
;
424 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
, WP_FRAMEBOTTOM
, iState
, &rcPart
, NULL
);
426 /* Draw the left border */
427 rcPart
= *prcCurrent
;
428 rcPart
.right
= rcPart
.left
+ pcontext
->wi
.cxWindowBorders
;
429 prcCurrent
->left
= rcPart
.right
;
430 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMELEFT
, iState
, &rcPart
, NULL
);
432 /* Draw the right border */
433 rcPart
= *prcCurrent
;
434 rcPart
.left
= rcPart
.right
- pcontext
->wi
.cxWindowBorders
;
435 prcCurrent
->right
= rcPart
.left
;
436 DrawThemeBackground(pcontext
->theme
, pcontext
->hDC
,WP_FRAMERIGHT
, iState
, &rcPart
, NULL
);
440 DrawClassicFrame(PDRAW_CONTEXT context
, RECT
* prcCurrent
)
442 /* Draw outer edge */
443 if (UserHasWindowEdge(context
->wi
.dwStyle
, context
->wi
.dwExStyle
))
445 DrawEdge(context
->hDC
, prcCurrent
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
447 else if (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
)
449 DrawEdge(context
->hDC
, prcCurrent
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
452 /* Firstly the "thick" frame */
453 if ((context
->wi
.dwStyle
& WS_THICKFRAME
) && !(context
->wi
.dwStyle
& WS_MINIMIZE
))
456 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
457 GetSystemMetrics(SM_CXBORDER
);
459 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
460 GetSystemMetrics(SM_CYBORDER
);
462 SelectObject(context
->hDC
, GetSysColorBrush(
463 context
->Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
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 /* Now the other bit of the frame */
479 if (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_BORDER
) || (context
->wi
.dwExStyle
& WS_EX_DLGMODALFRAME
))
481 INT Width
= GetSystemMetrics(SM_CXBORDER
);
482 INT Height
= GetSystemMetrics(SM_CYBORDER
);
484 SelectObject(context
->hDC
, GetSysColorBrush(
485 (context
->wi
.dwExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
486 (context
->wi
.dwExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
487 (context
->wi
.dwStyle
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
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
);
504 static void ThemeDrawMenuBar(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
506 /* Let the window manager paint the menu */
507 prcCurrent
->top
+= PaintMenuBar(pcontext
->hWnd
,
509 pcontext
->wi
.cxWindowBorders
,
510 pcontext
->wi
.cxWindowBorders
,
515 static void ThemeDrawScrollBarsGrip(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
)
519 RECT ParentClientRect
;
522 rcPart
= *prcCurrent
;
524 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
525 rcPart
.right
= rcPart
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
527 rcPart
.left
= rcPart
.right
- GetSystemMetrics(SM_CXVSCROLL
);
529 rcPart
.top
= rcPart
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
531 FillRect(pcontext
->hDC
, &rcPart
, GetSysColorBrush(COLOR_BTNFACE
));
533 hwndParent
= GetParent(pcontext
->hWnd
);
534 GetClientRect(hwndParent
, &ParentClientRect
);
535 ParentStyle
= GetWindowLongW(hwndParent
, GWL_STYLE
);
537 if (HASSIZEGRIP(pcontext
->wi
.dwStyle
, pcontext
->wi
.dwExStyle
, ParentStyle
, pcontext
->wi
.rcWindow
, ParentClientRect
))
540 if (pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
)
541 iState
= pcontext
->wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
;
543 iState
= SZB_RIGHTALIGN
;
544 DrawThemeBackground(pcontext
->scrolltheme
, pcontext
->hDC
, SBP_SIZEBOX
, iState
, &rcPart
, NULL
);
549 ThemePaintWindow(PDRAW_CONTEXT pcontext
, RECT
* prcCurrent
, BOOL bDoDoubleBuffering
)
551 if(!(pcontext
->wi
.dwStyle
& WS_VISIBLE
))
554 if((pcontext
->wi
.dwStyle
& WS_CAPTION
)==WS_CAPTION
)
556 if (bDoDoubleBuffering
)
557 ThemeStartBufferedPaint(pcontext
, prcCurrent
->right
, pcontext
->CaptionHeight
);
558 ThemeDrawCaption(pcontext
, prcCurrent
);
559 if (bDoDoubleBuffering
)
560 ThemeEndBufferedPaint(pcontext
, 0, 0, prcCurrent
->right
, pcontext
->CaptionHeight
);
561 ThemeDrawBorders(pcontext
, prcCurrent
);
565 DrawClassicFrame(pcontext
, prcCurrent
);
568 if(pcontext
->wi
.dwStyle
& WS_MINIMIZE
)
571 if(HAS_MENU(pcontext
->hWnd
, pcontext
->wi
.dwStyle
))
572 ThemeDrawMenuBar(pcontext
, prcCurrent
);
574 if (pcontext
->wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
575 DrawEdge(pcontext
->hDC
, prcCurrent
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
577 if((pcontext
->wi
.dwStyle
& WS_HSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
))
578 ThemeDrawScrollBar(pcontext
, SB_HORZ
, NULL
);
580 if((pcontext
->wi
.dwStyle
& WS_VSCROLL
) && IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
581 ThemeDrawScrollBar(pcontext
, SB_VERT
, NULL
);
583 if((pcontext
->wi
.dwStyle
& (WS_HSCROLL
|WS_VSCROLL
)) == (WS_HSCROLL
|WS_VSCROLL
) &&
584 IsScrollBarVisible(pcontext
->hWnd
, OBJID_HSCROLL
) &&
585 IsScrollBarVisible(pcontext
->hWnd
, OBJID_VSCROLL
))
587 ThemeDrawScrollBarsGrip(pcontext
, prcCurrent
);
596 ThemeHandleNCPaint(HWND hWnd
, HRGN hRgn
)
598 DRAW_CONTEXT context
;
601 ThemeInitDrawContext(&context
, hWnd
, hRgn
);
603 rcCurrent
= context
.wi
.rcWindow
;
604 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
606 ThemePaintWindow(&context
, &rcCurrent
, TRUE
);
607 ThemeCleanupDrawContext(&context
);
613 ThemeHandleNcMouseMove(HWND hWnd
, DWORD ht
, POINT
* pt
)
615 DRAW_CONTEXT context
;
620 /* First of all check if we have something to do here */
621 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
622 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
625 /* Get theme data for this window */
626 pwndData
= ThemeGetWndData(hWnd
);
627 if (pwndData
== NULL
)
630 /* Begin tracking in the non client area if we are not tracking yet */
631 tme
.cbSize
= sizeof(TRACKMOUSEEVENT
);
632 tme
.dwFlags
= TME_QUERY
;
633 tme
.hwndTrack
= hWnd
;
634 TrackMouseEvent(&tme
);
635 if (tme
.dwFlags
!= (TME_LEAVE
| TME_NONCLIENT
))
637 tme
.hwndTrack
= hWnd
;
638 tme
.dwFlags
= TME_LEAVE
| TME_NONCLIENT
;
639 TrackMouseEvent(&tme
);
642 ThemeInitDrawContext(&context
, hWnd
, 0);
643 if (context
.wi
.dwStyle
& WS_SYSMENU
)
645 if (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
))
646 ThemeDrawCaptionButtons(&context
, ht
, 0);
649 if (context
.wi
.dwStyle
& WS_HSCROLL
)
651 if (ht
== HTHSCROLL
|| pwndData
->lastHitTest
== HTHSCROLL
)
652 ThemeDrawScrollBar(&context
, SB_HORZ
, ht
== HTHSCROLL
? pt
: NULL
);
655 if (context
.wi
.dwStyle
& WS_VSCROLL
)
657 if (ht
== HTVSCROLL
|| pwndData
->lastHitTest
== HTVSCROLL
)
658 ThemeDrawScrollBar(&context
, SB_VERT
, ht
== HTVSCROLL
? pt
: NULL
);
660 ThemeCleanupDrawContext(&context
);
662 pwndData
->lastHitTest
= ht
;
668 ThemeHandleNcMouseLeave(HWND hWnd
)
670 DRAW_CONTEXT context
;
674 /* First of all check if we have something to do here */
675 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
676 if((style
& (WS_CAPTION
|WS_HSCROLL
|WS_VSCROLL
))==0)
679 /* Get theme data for this window */
680 pwndData
= ThemeGetWndData(hWnd
);
681 if (pwndData
== NULL
)
684 ThemeInitDrawContext(&context
, hWnd
, 0);
685 if (context
.wi
.dwStyle
& WS_SYSMENU
&& HT_ISBUTTON(pwndData
->lastHitTest
))
686 ThemeDrawCaptionButtons(&context
, 0, 0);
688 if (context
.wi
.dwStyle
& WS_HSCROLL
&& pwndData
->lastHitTest
== HTHSCROLL
)
689 ThemeDrawScrollBar(&context
, SB_HORZ
, NULL
);
691 if (context
.wi
.dwStyle
& WS_VSCROLL
&& pwndData
->lastHitTest
== HTVSCROLL
)
692 ThemeDrawScrollBar(&context
, SB_VERT
, NULL
);
694 ThemeCleanupDrawContext(&context
);
696 pwndData
->lastHitTest
= HTNOWHERE
;
702 ThemeHandleButton(HWND hWnd
, WPARAM wParam
)
708 DRAW_CONTEXT context
;
711 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
712 if (!((Style
& WS_CAPTION
) && (Style
& WS_SYSMENU
)))
721 if (!(Style
& WS_MINIMIZEBOX
))
723 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
726 if (!(Style
& WS_MAXIMIZEBOX
))
728 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
734 /* Get theme data for this window */
735 pwndData
= ThemeGetWndData(hWnd
);
736 if (pwndData
== NULL
)
739 ThemeInitDrawContext(&context
, hWnd
, 0);
740 ThemeDrawCaptionButtons(&context
, 0, wParam
);
741 pwndData
->lastHitTest
= wParam
;
749 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
752 if (Msg
.message
== WM_LBUTTONUP
)
755 if (Msg
.message
!= WM_MOUSEMOVE
)
758 ht
= SendMessage(hWnd
, WM_NCHITTEST
, 0, MAKELPARAM(Msg
.pt
.x
, Msg
.pt
.y
));
759 Pressed
= (ht
== wParam
);
761 /* Only draw the buttons if the hit test changed */
762 if (ht
!= pwndData
->lastHitTest
&&
763 (HT_ISBUTTON(ht
) || HT_ISBUTTON(pwndData
->lastHitTest
)))
765 ThemeDrawCaptionButtons(&context
, 0, Pressed
? wParam
: 0);
766 pwndData
->lastHitTest
= ht
;
770 ThemeDrawCaptionButtons(&context
, ht
, 0);
771 ThemeCleanupDrawContext(&context
);
776 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
781 DefWndNCHitTest(HWND hWnd
, POINT Point
)
787 wi
.cbSize
= sizeof(wi
);
788 GetWindowInfo(hWnd
, &wi
);
790 if (!PtInRect(&wi
.rcWindow
, Point
))
794 WindowRect
= wi
.rcWindow
;
796 if (UserHasWindowEdge(wi
.dwStyle
, wi
.dwExStyle
))
800 InflateRect(&WindowRect
, -(int)wi
.cxWindowBorders
, -(int)wi
.cyWindowBorders
);
801 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
802 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
803 if (!PtInRect(&WindowRect
, Point
))
807 ThickFrame
= (wi
.dwStyle
& WS_THICKFRAME
);
808 if (Point
.y
< WindowRect
.top
)
810 if(wi
.dwStyle
& WS_MINIMIZE
)
814 if (Point
.x
< (WindowRect
.left
+ XSize
))
816 if (Point
.x
>= (WindowRect
.right
- XSize
))
820 if (Point
.y
>= WindowRect
.bottom
)
822 if(wi
.dwStyle
& WS_MINIMIZE
)
826 if (Point
.x
< (WindowRect
.left
+ XSize
))
828 if (Point
.x
>= (WindowRect
.right
- XSize
))
829 return HTBOTTOMRIGHT
;
832 if (Point
.x
< WindowRect
.left
)
834 if(wi
.dwStyle
& WS_MINIMIZE
)
838 if (Point
.y
< (WindowRect
.top
+ YSize
))
840 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
844 if (Point
.x
>= WindowRect
.right
)
846 if(wi
.dwStyle
& WS_MINIMIZE
)
850 if (Point
.y
< (WindowRect
.top
+ YSize
))
852 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
853 return HTBOTTOMRIGHT
;
860 if (wi
.dwExStyle
& WS_EX_STATICEDGE
)
861 InflateRect(&WindowRect
, -GetSystemMetrics(SM_CXBORDER
),
862 -GetSystemMetrics(SM_CYBORDER
));
863 if (!PtInRect(&WindowRect
, Point
))
867 if ((wi
.dwStyle
& WS_CAPTION
) == WS_CAPTION
)
869 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
870 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
872 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
874 if (!PtInRect(&WindowRect
, Point
))
876 if (wi
.dwStyle
& WS_SYSMENU
)
878 PWND_DATA pwndData
= ThemeGetWndData(hWnd
);
880 if (!(wi
.dwExStyle
& WS_EX_TOOLWINDOW
))
882 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME))
883 // FIXME: The real test should check whether there is
884 // an icon for the system window, and if so, do the
885 // rect.left increase.
886 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest
887 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
889 WindowRect
.left
+= GetSystemMetrics(SM_CXSMICON
);
894 POINT pt
= {Point
.x
- wi
.rcWindow
.left
, Point
.y
- wi
.rcWindow
.top
};
895 if (PtInRect(&pwndData
->rcCaptionButtons
[CLOSEBUTTON
], pt
))
897 if (PtInRect(&pwndData
->rcCaptionButtons
[MAXBUTTON
], pt
))
899 if (PtInRect(&pwndData
->rcCaptionButtons
[MINBUTTON
], pt
))
903 if (Point
.x
< WindowRect
.left
)
909 if(!(wi
.dwStyle
& WS_MINIMIZE
))
914 ScreenToClient(hWnd
, &ClientPoint
);
915 GetClientRect(hWnd
, &wi
.rcClient
);
917 if (PtInRect(&wi
.rcClient
, ClientPoint
))
922 if ((menu
= GetMenu(hWnd
)) && !(wi
.dwStyle
& WS_CHILD
))
924 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
928 if (wi
.dwExStyle
& WS_EX_CLIENTEDGE
)
930 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
931 -2 * GetSystemMetrics(SM_CYBORDER
));
934 if ((wi
.dwStyle
& WS_VSCROLL
) && (wi
.dwStyle
& WS_HSCROLL
) &&
935 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
937 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
938 HWND Parent
= GetParent(hWnd
);
940 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
941 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
942 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
944 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
945 if (PtInRect(&TempRect
, Point
))
948 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
949 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
950 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
952 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
953 if (PtInRect(&TempRect2
, Point
))
956 TempRect
.top
= TempRect2
.top
;
957 TempRect
.bottom
= TempRect2
.bottom
;
959 GetClientRect(Parent
, &ParentRect
);
960 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(wi
.dwStyle
, wi
.dwExStyle
,
961 GetWindowLongW(Parent
, GWL_STYLE
), wi
.rcWindow
, ParentRect
))
963 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
966 return HTBOTTOMRIGHT
;
971 if (wi
.dwStyle
& WS_VSCROLL
)
973 RECT TempRect
= WindowRect
;
975 if ((wi
.dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
976 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
978 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
979 if (PtInRect(&TempRect
, Point
))
982 else if (wi
.dwStyle
& WS_HSCROLL
)
984 RECT TempRect
= WindowRect
;
985 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
986 if (PtInRect(&TempRect
, Point
))
996 ThemeWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, WNDPROC DefWndProc
)
1001 return ThemeHandleNCPaint(hWnd
, (HRGN
)wParam
);
1003 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
1005 case WM_NCUAHDRAWCAPTION
:
1007 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
1009 case WM_NCUAHDRAWFRAME
:
1012 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) != WS_CAPTION
)
1015 ThemeHandleNCPaint(hWnd
, (HRGN
)1);
1017 case WM_NCMOUSEMOVE
:
1020 Point
.x
= GET_X_LPARAM(lParam
);
1021 Point
.y
= GET_Y_LPARAM(lParam
);
1022 return ThemeHandleNcMouseMove(hWnd
, wParam
, &Point
);
1024 case WM_NCMOUSELEAVE
:
1025 return ThemeHandleNcMouseLeave(hWnd
);
1026 case WM_NCLBUTTONDOWN
:
1033 ThemeHandleButton(hWnd
, wParam
);
1037 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1042 Point
.x
= GET_X_LPARAM(lParam
);
1043 Point
.y
= GET_Y_LPARAM(lParam
);
1044 return DefWndNCHitTest(hWnd
, Point
);
1048 if((wParam
& 0xfff0) == SC_VSCROLL
||
1049 (wParam
& 0xfff0) == SC_HSCROLL
)
1052 Pt
.x
= (short)LOWORD(lParam
);
1053 Pt
.y
= (short)HIWORD(lParam
);
1054 NC_TrackScrollBar(hWnd
, wParam
, Pt
);
1059 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1063 return DefWndProc(hWnd
, Msg
, wParam
, lParam
);
1067 HRESULT WINAPI
DrawNCPreview(HDC hDC
,
1070 LPCWSTR pszThemeFileName
,
1071 LPCWSTR pszColorName
,
1072 LPCWSTR pszSizeName
,
1073 PNONCLIENTMETRICSW pncMetrics
,
1074 COLORREF
* lpaRgbValues
)
1076 WNDCLASSEXW DummyPreviewWindowClass
;
1079 HTHEMEFILE hThemeFile
;
1080 DRAW_CONTEXT context
;
1083 /* FIXME: We also need to implement drawing the rest of the preview windows
1084 * and make use of the ncmetrics and colors passed as parameters */
1086 /* Create a dummy window that will be used to trick the paint funtions */
1087 memset(&DummyPreviewWindowClass
, 0, sizeof(DummyPreviewWindowClass
));
1088 DummyPreviewWindowClass
.cbSize
= sizeof(DummyPreviewWindowClass
);
1089 DummyPreviewWindowClass
.lpszClassName
= L
"DummyPreviewWindowClass";
1090 DummyPreviewWindowClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
1091 DummyPreviewWindowClass
.hInstance
= hDllInst
;
1092 DummyPreviewWindowClass
.lpfnWndProc
= DefWindowProcW
;
1093 if (!RegisterClassExW(&DummyPreviewWindowClass
))
1096 hwndDummy
= CreateWindowExW(0, L
"DummyPreviewWindowClass", L
"Active window", WS_OVERLAPPEDWINDOW
,30,30,300,150,0,0,hDllInst
,NULL
);
1100 hres
= OpenThemeFile(pszThemeFileName
, pszColorName
, pszSizeName
, &hThemeFile
,0);
1104 /* Initialize the special draw context for the preview */
1106 context
.hWnd
= hwndDummy
;
1107 context
.theme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"WINDOW", 0);
1110 context
.scrolltheme
= OpenThemeDataFromFile(hThemeFile
, hwndDummy
, L
"SCROLLBAR", 0);
1111 if (!context
.scrolltheme
)
1113 context
.Active
= TRUE
;
1114 context
.wi
.cbSize
= sizeof(context
.wi
);
1115 if (!GetWindowInfo(hwndDummy
, &context
.wi
))
1117 context
.wi
.dwStyle
|= WS_VISIBLE
;
1118 context
.CaptionHeight
= context
.wi
.cyWindowBorders
;
1119 context
.CaptionHeight
+= GetSystemMetrics(context
.wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
1120 context
.hRgn
= CreateRectRgnIndirect(&context
.wi
.rcWindow
);
1122 /* Paint the window on the preview hDC */
1123 rcCurrent
= context
.wi
.rcWindow
;
1124 OffsetRect( &rcCurrent
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
1125 SetViewportOrgEx(hDC
, context
.wi
.rcWindow
.left
, context
.wi
.rcWindow
.top
, NULL
);
1126 ThemeCalculateCaptionButtonsPos(hwndDummy
, context
.theme
);
1127 ThemePaintWindow(&context
, &rcCurrent
, FALSE
);
1128 SetViewportOrgEx(hDC
, 0, 0, NULL
);
1131 CloseThemeData (context
.theme
);
1132 CloseThemeData (context
.scrolltheme
);
1133 ThemeCleanupDrawContext(&context
);
1136 DestroyWindow(hwndDummy
);
1137 UnregisterClassW(L
"DummyPreviewWindowClass", hDllInst
);