2 * ReactOS User32 Library
3 * - Window non-client area management
5 * Copyright (C) 2003 ReactOS Team
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 /* INCLUDES *******************************************************************/
26 #include <wine/debug.h>
28 #define HAS_DLGFRAME(Style, ExStyle) \
29 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
30 (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))
32 #define HAS_THICKFRAME(Style, ExStyle) \
33 (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
34 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
36 #define HAS_THINFRAME(Style, ExStyle) \
37 (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))
39 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
40 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
41 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
42 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
43 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
45 #ifndef STATE_SYSTEM_OFFSCREEN
46 #define STATE_SYSTEM_OFFSCREEN 0x00010000
50 * FIXME: This should be moved to a header
53 IntDrawScrollBar(HWND hWnd
, HDC hDC
, INT nBar
);
55 IntScrollHitTest(HWND hWnd
, INT nBar
, POINT pt
, BOOL bDragging
);
57 BOOL WINAPI
GdiGradientFill(HDC
,PTRIVERTEX
,ULONG
,PVOID
,ULONG
,ULONG
);
59 extern ATOM AtomInternalPos
;
61 /* PRIVATE FUNCTIONS **********************************************************/
64 IntIsScrollBarVisible(HWND hWnd
, INT hBar
)
67 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
68 if(!NtUserGetScrollBarInfo(hWnd
, hBar
, &sbi
))
71 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
75 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
77 if (Style
& WS_MINIMIZE
)
79 if (ExStyle
& WS_EX_DLGMODALFRAME
)
81 if (ExStyle
& WS_EX_STATICEDGE
)
83 if (Style
& WS_THICKFRAME
)
86 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
92 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
96 if (UserHasWindowEdge(Style
, ExStyle
))
98 else if (ExStyle
& WS_EX_STATICEDGE
)
100 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
102 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
104 Size
->cx
= Size
->cy
= Border
;
105 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
107 Size
->cx
+= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
108 Size
->cy
+= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
110 Size
->cx
*= GetSystemMetrics(SM_CXBORDER
);
111 Size
->cy
*= GetSystemMetrics(SM_CYBORDER
);
115 UserHasMenu(HWND hWnd
, ULONG Style
)
117 return (!(Style
& WS_CHILD
) && GetMenu(hWnd
) != 0);
121 UserGetWindowIcon(HWND hwnd
)
125 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
128 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
131 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
134 hIcon
= (HICON
)GetClassLongPtr(hwnd
, GCL_HICONSM
);
137 hIcon
= (HICON
)GetClassLongPtr(hwnd
, GCL_HICON
);
143 UserDrawSysMenuButton(HWND hWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
147 if ((WindowIcon
= UserGetWindowIcon(hWnd
)))
149 return DrawIconEx(hDC
, Rect
->left
+ 2, Rect
->top
+ 2, WindowIcon
,
150 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
159 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
160 * wasting precious CPU cycles) every time
161 * - Center the buttons verticaly in the rect
164 UserDrawCaptionButton(HWND hWnd
, LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
168 if (!(Style
& WS_SYSMENU
))
177 case DFCS_CAPTIONMIN
:
179 if (ExStyle
& WS_EX_TOOLWINDOW
)
180 return; /* ToolWindows don't have min/max buttons */
182 if (Style
& WS_SYSMENU
)
183 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
184 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
185 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
186 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
187 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
191 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
192 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
193 (bDown
? DFCS_PUSHED
: 0) |
194 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
197 case DFCS_CAPTIONMAX
:
199 if (ExStyle
& WS_EX_TOOLWINDOW
)
200 return; /* ToolWindows don't have min/max buttons */
202 if (Style
& WS_SYSMENU
)
203 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
204 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
205 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
209 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
210 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
211 (bDown
? DFCS_PUSHED
: 0) |
212 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
215 case DFCS_CAPTIONCLOSE
:
217 HMENU hSysMenu
= GetSystemMenu(hWnd
, FALSE
);
218 UINT MenuState
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
220 /* FIXME: A tool window has a smaller Close button */
222 if (ExStyle
& WS_EX_TOOLWINDOW
)
224 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSMSIZE
);
225 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMSIZE
) - 2;
229 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
);
230 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
235 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
236 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
237 ((!(MenuState
& (MF_GRAYED
|MF_DISABLED
)) && !(GetClassLong(hWnd
, GCL_STYLE
) & CS_NOCLOSE
)) ? 0 : DFCS_INACTIVE
)));
244 UserDrawCaptionButtonWnd(HWND hWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
248 DWORD Style
, ExStyle
;
250 GetWindowRect(hWnd
, &WindowRect
);
251 WindowRect
.right
-= WindowRect
.left
;
252 WindowRect
.bottom
-= WindowRect
.top
;
253 WindowRect
.left
= WindowRect
.top
= 0;
254 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
255 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
256 UserGetWindowBorders(Style
, ExStyle
, &WindowBorder
, FALSE
);
257 InflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
258 UserDrawCaptionButton(hWnd
, &WindowRect
, Style
, ExStyle
, hDC
, bDown
, Type
);
262 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
263 the call to GetDCEx implying that it is allowed not to use it either.
264 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
265 will cause clipRgn to be deleted after ReleaseDC().
266 Now, how is the "system" supposed to tell what happened?
270 * - Drawing of WS_BORDER after scrollbars
271 * - Correct drawing of size-box
274 DefWndNCPaint(HWND hWnd
, HRGN hRgn
, BOOL Active
)
277 DWORD Style
, ExStyle
;
279 RECT ClientRect
, WindowRect
, CurrentRect
, TempRect
;
281 if (!IsWindowVisible(hWnd
))
284 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
286 hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
292 Parent
= GetParent(hWnd
);
293 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
296 if (ExStyle
& WS_EX_MDICHILD
)
298 Active
= IsChild(GetForegroundWindow(), hWnd
);
300 Active
= (hWnd
== (HWND
)SendMessageW(Parent
, WM_MDIGETACTIVE
, 0, 0));
304 Active
= (GetForegroundWindow() == hWnd
);
307 GetWindowRect(hWnd
, &WindowRect
);
308 GetClientRect(hWnd
, &ClientRect
);
310 CurrentRect
.top
= CurrentRect
.left
= 0;
311 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
312 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
314 /* Draw outer edge */
315 if (UserHasWindowEdge(Style
, ExStyle
))
317 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
319 if (ExStyle
& WS_EX_STATICEDGE
)
322 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
324 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNSHADOW
));
325 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
326 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
328 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNHIGHLIGHT
));
329 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
330 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
332 InflateRect(&CurrentRect
, -1, -1);
336 /* Firstly the "thick" frame */
337 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
340 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
341 GetSystemMetrics(SM_CXBORDER
);
343 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
344 GetSystemMetrics(SM_CYBORDER
);
346 SelectObject(hDC
, GetSysColorBrush(Active
? COLOR_ACTIVEBORDER
:
347 COLOR_INACTIVEBORDER
));
350 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
351 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
353 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
354 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
356 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
357 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
360 InflateRect(&CurrentRect
, -Width
, -Height
);
363 /* Now the other bit of the frame */
364 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
366 DWORD Width
= GetSystemMetrics(SM_CXBORDER
);
367 DWORD Height
= GetSystemMetrics(SM_CYBORDER
);
369 SelectObject(hDC
, GetSysColorBrush(
370 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
371 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
372 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
376 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
377 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
379 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
380 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
382 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
383 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
386 InflateRect(&CurrentRect
, -Width
, -Height
);
390 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
392 DWORD CaptionFlags
= DC_ICON
| DC_TEXT
| DC_BUTTONS
;
394 BOOL Gradient
= FALSE
;
396 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
398 CaptionFlags
|= DC_GRADIENT
;
401 TempRect
= CurrentRect
;
405 CaptionFlags
|= DC_ACTIVE
;
408 if (ExStyle
& WS_EX_TOOLWINDOW
)
410 CaptionFlags
|= DC_SMALLCAP
;
411 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
) - 1;
412 CurrentRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
416 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
417 CurrentRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
420 NtUserDrawCaption(hWnd
, hDC
, &TempRect
, CaptionFlags
);
423 if (Style
& WS_SYSMENU
)
425 UserDrawCaptionButton(hWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
426 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
428 UserDrawCaptionButton(hWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
429 UserDrawCaptionButton(hWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
432 if(!(Style
& WS_MINIMIZE
))
434 /* Line under caption */
435 PreviousPen
= SelectObject(hDC
, GetStockObject(DC_PEN
));
436 SetDCPenColor(hDC
, GetSysColor(
437 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
|
438 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
439 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
440 MoveToEx(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
441 LineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
442 SelectObject(hDC
, PreviousPen
);
446 if(!(Style
& WS_MINIMIZE
))
448 HMENU menu
= GetMenu(hWnd
);
450 if (menu
&& !(Style
& WS_CHILD
))
452 TempRect
= CurrentRect
;
453 TempRect
.bottom
= TempRect
.top
+ (UINT
)NtUserxSetMenuBarHeight(menu
, 0);
454 CurrentRect
.top
+= MenuDrawMenuBar(hDC
, &TempRect
, hWnd
, FALSE
);
457 if (ExStyle
& WS_EX_CLIENTEDGE
)
459 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
462 /* Draw the scrollbars */
463 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
464 IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
466 RECT ParentClientRect
;
468 TempRect
= CurrentRect
;
469 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
470 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
472 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
473 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
474 FillRect(hDC
, &TempRect
, GetSysColorBrush(COLOR_BTNFACE
));
475 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
477 GetClientRect(Parent
, &ParentClientRect
);
478 if (HASSIZEGRIP(Style
, ExStyle
, GetWindowLongPtrW(Parent
, GWL_STYLE
), WindowRect
, ParentClientRect
))
480 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
482 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
483 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
487 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
))
488 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
489 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
490 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
494 ReleaseDC(hWnd
, hDC
);
495 if (hRgn
!= HRGN_WINDOW
)
496 DeleteObject(hRgn
); // We use DCX_KEEPCLIPRGN
502 DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
)
505 DWORD Style
= GetClassLongPtrW(hWnd
, GCL_STYLE
);
518 if (Style
& CS_VREDRAW
)
520 Result
|= WVR_VREDRAW
;
522 if (Style
& CS_HREDRAW
)
524 Result
|= WVR_HREDRAW
;
526 Result
|= WVR_VALIDRECTS
;
529 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
530 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
532 if (!(Style
& WS_MINIMIZE
))
534 HMENU menu
= GetMenu(hWnd
);
536 if (UserHasWindowEdge(Style
, ExStyle
))
538 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
539 InflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
541 if ((ExStyle
& WS_EX_STATICEDGE
) || (Style
& WS_BORDER
))
543 InflateRect(Rect
, -1, -1);
546 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
548 if (ExStyle
& WS_EX_TOOLWINDOW
)
549 Rect
->top
+= GetSystemMetrics(SM_CYSMCAPTION
);
551 Rect
->top
+= GetSystemMetrics(SM_CYCAPTION
);
554 if (menu
&& !(Style
& WS_CHILD
))
556 HDC hDC
= GetWindowDC(hWnd
);
559 RECT CliRect
= *Rect
;
560 CliRect
.bottom
-= OrigRect
.top
;
561 CliRect
.right
-= OrigRect
.left
;
562 CliRect
.left
-= OrigRect
.left
;
563 CliRect
.top
-= OrigRect
.top
;
564 Rect
->top
+= MenuDrawMenuBar(hDC
, &CliRect
, hWnd
, TRUE
);
565 ReleaseDC(hWnd
, hDC
);
569 if (ExStyle
& WS_EX_CLIENTEDGE
)
571 InflateRect(Rect
, -2 * GetSystemMetrics(SM_CXBORDER
),
572 -2 * GetSystemMetrics(SM_CYBORDER
));
575 if(Style
& (WS_VSCROLL
| WS_HSCROLL
))
578 SETSCROLLBARINFO ssbi
;
580 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
581 if((Style
& WS_VSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &sbi
))
584 LONG sx
= Rect
->right
;
586 sx
-= GetSystemMetrics(SM_CXVSCROLL
);
587 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
588 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
590 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
592 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
593 NtUserSetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &ssbi
);
594 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
595 Style
&= ~WS_VSCROLL
;
598 Style
&= ~WS_VSCROLL
;
600 if((Style
& WS_HSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &sbi
))
603 LONG sy
= Rect
->bottom
;
605 sy
-= GetSystemMetrics(SM_CYHSCROLL
);
606 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
607 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
609 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
611 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
612 NtUserSetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &ssbi
);
613 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
614 Style
&= ~WS_HSCROLL
;
617 Style
&= ~WS_HSCROLL
;
620 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
622 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
623 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
625 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
626 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
630 if (Style
& WS_VSCROLL
)
632 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
633 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
635 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
637 else if (Style
& WS_HSCROLL
)
638 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
640 if (Rect
->top
> Rect
->bottom
)
641 Rect
->bottom
= Rect
->top
;
642 if (Rect
->left
> Rect
->right
)
643 Rect
->right
= Rect
->left
;
647 Rect
->right
= Rect
->left
;
648 Rect
->bottom
= Rect
->top
;
655 DefWndNCActivate(HWND hWnd
, WPARAM wParam
)
657 DefWndNCPaint(hWnd
, HRGN_WINDOW
, wParam
);
663 * - Check the scrollbar handling
666 DefWndNCHitTest(HWND hWnd
, POINT Point
)
668 RECT WindowRect
, ClientRect
, OrigWndRect
;
671 DWORD Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
672 DWORD ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
674 GetWindowRect(hWnd
, &WindowRect
);
675 if (!PtInRect(&WindowRect
, Point
))
679 OrigWndRect
= WindowRect
;
681 if (UserHasWindowEdge(Style
, ExStyle
))
685 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
686 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
687 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
688 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
689 if (!PtInRect(&WindowRect
, Point
))
693 ThickFrame
= (Style
& WS_THICKFRAME
);
694 if (Point
.y
< WindowRect
.top
)
696 if(Style
& WS_MINIMIZE
)
700 if (Point
.x
< (WindowRect
.left
+ XSize
))
702 if (Point
.x
>= (WindowRect
.right
- XSize
))
706 if (Point
.y
>= WindowRect
.bottom
)
708 if(Style
& WS_MINIMIZE
)
712 if (Point
.x
< (WindowRect
.left
+ XSize
))
714 if (Point
.x
>= (WindowRect
.right
- XSize
))
715 return HTBOTTOMRIGHT
;
718 if (Point
.x
< WindowRect
.left
)
720 if(Style
& WS_MINIMIZE
)
724 if (Point
.y
< (WindowRect
.top
+ YSize
))
726 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
730 if (Point
.x
>= WindowRect
.right
)
732 if(Style
& WS_MINIMIZE
)
736 if (Point
.y
< (WindowRect
.top
+ YSize
))
738 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
739 return HTBOTTOMRIGHT
;
746 if (ExStyle
& WS_EX_STATICEDGE
)
747 InflateRect(&WindowRect
,
748 -GetSystemMetrics(SM_CXBORDER
),
749 -GetSystemMetrics(SM_CYBORDER
));
750 if (!PtInRect(&WindowRect
, Point
))
754 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
756 if (ExStyle
& WS_EX_TOOLWINDOW
)
757 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
759 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
760 if (!PtInRect(&WindowRect
, Point
))
762 if (Style
& WS_SYSMENU
)
764 if (ExStyle
& WS_EX_TOOLWINDOW
)
766 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
770 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
771 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
772 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
775 if (Point
.x
< WindowRect
.left
)
777 if (WindowRect
.right
<= Point
.x
)
779 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
780 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
781 if (Point
.x
>= WindowRect
.right
)
783 if (Style
& WS_MINIMIZEBOX
)
784 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
785 if (Point
.x
>= WindowRect
.right
)
791 if(!(Style
& WS_MINIMIZE
))
794 ScreenToClient(hWnd
, &ClientPoint
);
795 GetClientRect(hWnd
, &ClientRect
);
797 if (PtInRect(&ClientRect
, ClientPoint
))
802 if (GetMenu(hWnd
) && !(Style
& WS_CHILD
))
804 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
808 if (ExStyle
& WS_EX_CLIENTEDGE
)
810 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
811 -2 * GetSystemMetrics(SM_CYBORDER
));
814 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
815 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
817 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
818 HWND Parent
= GetParent(hWnd
);
820 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
821 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
822 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
824 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
825 if (PtInRect(&TempRect
, Point
))
828 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
829 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
830 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
832 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
833 if (PtInRect(&TempRect2
, Point
))
836 TempRect
.top
= TempRect2
.top
;
837 TempRect
.bottom
= TempRect2
.bottom
;
839 GetClientRect(Parent
, &ParentRect
);
840 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
841 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
843 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
846 return HTBOTTOMRIGHT
;
851 if (Style
& WS_VSCROLL
)
853 RECT TempRect
= WindowRect
;
855 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
856 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
858 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
859 if (PtInRect(&TempRect
, Point
))
862 if (Style
& WS_HSCROLL
)
864 RECT TempRect
= WindowRect
;
865 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
866 if (PtInRect(&TempRect
, Point
))
876 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
880 BOOL Pressed
= TRUE
, OldState
;
887 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
891 hSysMenu
= GetSystemMenu(hWnd
, FALSE
);
892 MenuState
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
893 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (GetClassLongPtrW(hWnd
, GCL_STYLE
) & CS_NOCLOSE
))
895 ButtonType
= DFCS_CAPTIONCLOSE
;
899 if (!(Style
& WS_MINIMIZEBOX
))
901 ButtonType
= DFCS_CAPTIONMIN
;
902 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
905 if (!(Style
& WS_MAXIMIZEBOX
))
907 ButtonType
= DFCS_CAPTIONMAX
;
908 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
917 * FIXME: Not sure where to do this, but we must flush the pending
918 * window updates when someone clicks on the close button and at
919 * the same time the window is overlapped with another one. This
920 * looks like a good place for now...
924 WindowDC
= GetWindowDC(hWnd
);
925 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
931 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
934 if (Msg
.message
== WM_LBUTTONUP
)
937 if (Msg
.message
!= WM_MOUSEMOVE
)
941 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
942 if (Pressed
!= OldState
)
943 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
947 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
949 ReleaseDC(hWnd
, WindowDC
);
951 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
956 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
962 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
963 if (SetActiveWindow(hTopWnd
) || GetActiveWindow() == hTopWnd
)
965 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
971 if (GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_SYSMENU
)
973 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
980 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
985 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
990 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
997 DefWndDoButton(hWnd
, wParam
);
1009 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1018 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1022 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1027 /* Maximize/Restore the window */
1028 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1030 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1036 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1040 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1046 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1050 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1052 if ((wParam
& 0x0f) != HTHSCROLL
)
1054 ScrollBar
= SB_HORZ
;
1058 if ((wParam
& 0x0f) != HTVSCROLL
)
1060 ScrollBar
= SB_VERT
;
1066 /* PUBLIC FUNCTIONS ***********************************************************/
1069 RealAdjustWindowRectEx(LPRECT lpRect
,
1078 lpRect
->top
-= GetSystemMetrics(SM_CYMENU
);
1080 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1082 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1083 lpRect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
1085 lpRect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
1087 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1100 AdjustWindowRectEx(LPRECT lpRect
,
1105 BOOL Hook
, Ret
= FALSE
;
1109 Hook
= BeginIfHookedUserApiHook();
1111 /* Bypass SEH and go direct. */
1112 if (!Hook
) return RealAdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1116 Ret
= guah
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1133 AdjustWindowRect(LPRECT lpRect
,
1137 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1140 // Enabling this will cause captions to draw smoother, but slower:
1141 #define DOUBLE_BUFFER_CAPTION
1147 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1149 BOOL Hook
, Ret
= FALSE
;
1153 Hook
= BeginIfHookedUserApiHook();
1155 /* Bypass SEH and go direct. */
1156 if (!Hook
) return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1160 Ret
= guah
.DrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1162 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1187 UNICODE_STRING Text
= {0};
1188 RtlInitUnicodeString(&Text
, str
);
1189 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1211 if (!(uFlags
& DC_TEXT
) || !str
)
1212 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1214 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1215 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1217 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1218 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1219 HeapFree(GetProcessHeap(), 0, strW
);
1224 /***********************************************************************
1227 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1228 * but without the borders (if any).
1229 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1231 static void FASTCALL
1232 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1237 GetWindowRect(Wnd
, Rect
);
1238 Rect
->right
= Rect
->right
- Rect
->left
;
1240 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1243 Style
= GetWindowLongPtrW(Wnd
, GWL_STYLE
);
1244 if (0 != (Style
& WS_ICONIC
))
1249 /* Remove frame from rectangle */
1250 ExStyle
= GetWindowLongPtrW(Wnd
, GWL_EXSTYLE
);
1251 if (HAS_THICKFRAME(Style
, ExStyle
))
1253 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1255 else if (HAS_DLGFRAME(Style
, ExStyle
))
1257 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1259 else if (HAS_THINFRAME(Style
, ExStyle
))
1261 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1264 /* We have additional border information if the window
1265 * is a child (but not an MDI child) */
1266 if (0 != (Style
& WS_CHILD
)
1267 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1269 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1271 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1273 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1275 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1280 /***********************************************************************
1284 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1290 GetWindowRect(Wnd
, Rect
);
1294 NcGetInsideRect(Wnd
, Rect
);
1295 GetWindowRect(Wnd
, &WindowRect
);
1296 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1297 if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1299 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1301 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1302 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;