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
498 return 0; // For WM_NCPAINT message, return 0.
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
, LPARAM lParam
)
657 PWND Wnd
= ValidateHwnd(hWnd
);
661 /* Lotus Notes draws menu descriptions in the caption of its main
662 * window. When it wants to restore original "system" view, it just
663 * sends WM_NCACTIVATE message to itself. Any optimizations here in
664 * attempt to minimize redrawings lead to a not restored caption.
667 NtUserxSetWindowState(Wnd
, WNDSACTIVEFRAME
);
669 NtUserxClearWindowState(Wnd
, WNDSACTIVEFRAME
);
671 if (Wnd
->state
& WNDS_NONCPAINT
)
674 /* This isn't documented but is reproducible in at least XP SP2 and
675 * Outlook 2007 depends on it
678 // If this parameter is set to -1, DefWindowProc does not repaint the
679 // nonclient area to reflect the state change.
682 DefWndNCPaint(hWnd
, HRGN_WINDOW
, wParam
);
689 * - Check the scrollbar handling
692 DefWndNCHitTest(HWND hWnd
, POINT Point
)
694 RECT WindowRect
, ClientRect
, OrigWndRect
;
697 DWORD Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
698 DWORD ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
700 GetWindowRect(hWnd
, &WindowRect
);
701 if (!PtInRect(&WindowRect
, Point
))
705 OrigWndRect
= WindowRect
;
707 if (UserHasWindowEdge(Style
, ExStyle
))
711 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
712 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
713 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
714 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
715 if (!PtInRect(&WindowRect
, Point
))
719 ThickFrame
= (Style
& WS_THICKFRAME
);
720 if (Point
.y
< WindowRect
.top
)
722 if(Style
& WS_MINIMIZE
)
726 if (Point
.x
< (WindowRect
.left
+ XSize
))
728 if (Point
.x
>= (WindowRect
.right
- XSize
))
732 if (Point
.y
>= WindowRect
.bottom
)
734 if(Style
& WS_MINIMIZE
)
738 if (Point
.x
< (WindowRect
.left
+ XSize
))
740 if (Point
.x
>= (WindowRect
.right
- XSize
))
741 return HTBOTTOMRIGHT
;
744 if (Point
.x
< WindowRect
.left
)
746 if(Style
& WS_MINIMIZE
)
750 if (Point
.y
< (WindowRect
.top
+ YSize
))
752 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
756 if (Point
.x
>= WindowRect
.right
)
758 if(Style
& WS_MINIMIZE
)
762 if (Point
.y
< (WindowRect
.top
+ YSize
))
764 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
765 return HTBOTTOMRIGHT
;
772 if (ExStyle
& WS_EX_STATICEDGE
)
773 InflateRect(&WindowRect
,
774 -GetSystemMetrics(SM_CXBORDER
),
775 -GetSystemMetrics(SM_CYBORDER
));
776 if (!PtInRect(&WindowRect
, Point
))
780 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
782 if (ExStyle
& WS_EX_TOOLWINDOW
)
783 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
785 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
786 if (!PtInRect(&WindowRect
, Point
))
788 if (Style
& WS_SYSMENU
)
790 if (ExStyle
& WS_EX_TOOLWINDOW
)
792 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
796 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
797 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
798 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
801 if (Point
.x
< WindowRect
.left
)
803 if (WindowRect
.right
<= Point
.x
)
805 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
806 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
807 if (Point
.x
>= WindowRect
.right
)
809 if (Style
& WS_MINIMIZEBOX
)
810 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
811 if (Point
.x
>= WindowRect
.right
)
817 if(!(Style
& WS_MINIMIZE
))
820 ScreenToClient(hWnd
, &ClientPoint
);
821 GetClientRect(hWnd
, &ClientRect
);
823 if (PtInRect(&ClientRect
, ClientPoint
))
828 if (GetMenu(hWnd
) && !(Style
& WS_CHILD
))
830 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
834 if (ExStyle
& WS_EX_CLIENTEDGE
)
836 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
837 -2 * GetSystemMetrics(SM_CYBORDER
));
840 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
841 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
843 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
844 HWND Parent
= GetParent(hWnd
);
846 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
847 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
848 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
850 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
851 if (PtInRect(&TempRect
, Point
))
854 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
855 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
856 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
858 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
859 if (PtInRect(&TempRect2
, Point
))
862 TempRect
.top
= TempRect2
.top
;
863 TempRect
.bottom
= TempRect2
.bottom
;
865 GetClientRect(Parent
, &ParentRect
);
866 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
867 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
869 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
872 return HTBOTTOMRIGHT
;
877 if (Style
& WS_VSCROLL
)
879 RECT TempRect
= WindowRect
;
881 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
882 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
884 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
885 if (PtInRect(&TempRect
, Point
))
888 if (Style
& WS_HSCROLL
)
890 RECT TempRect
= WindowRect
;
891 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
892 if (PtInRect(&TempRect
, Point
))
902 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
906 BOOL Pressed
= TRUE
, OldState
;
913 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
917 hSysMenu
= GetSystemMenu(hWnd
, FALSE
);
918 MenuState
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
919 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (GetClassLongPtrW(hWnd
, GCL_STYLE
) & CS_NOCLOSE
))
921 ButtonType
= DFCS_CAPTIONCLOSE
;
925 if (!(Style
& WS_MINIMIZEBOX
))
927 ButtonType
= DFCS_CAPTIONMIN
;
928 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
931 if (!(Style
& WS_MAXIMIZEBOX
))
933 ButtonType
= DFCS_CAPTIONMAX
;
934 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
943 * FIXME: Not sure where to do this, but we must flush the pending
944 * window updates when someone clicks on the close button and at
945 * the same time the window is overlapped with another one. This
946 * looks like a good place for now...
950 WindowDC
= GetWindowDC(hWnd
);
951 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
957 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
959 if (CallMsgFilterW( &Msg
, MSGF_MAX
)) continue;
961 if (Msg
.message
== WM_LBUTTONUP
)
964 if (Msg
.message
!= WM_MOUSEMOVE
)
968 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
969 if (Pressed
!= OldState
)
970 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
974 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
976 ReleaseDC(hWnd
, WindowDC
);
978 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, MAKELONG(Msg
.pt
.x
,Msg
.pt
.y
));
983 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
989 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
990 if ( NtUserCallHwndLock(hTopWnd
, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE
) ||
991 GetActiveWindow() == hTopWnd
)
993 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
999 LONG style
= GetWindowLongPtrW( hWnd
, GWL_STYLE
);
1000 if (style
& WS_SYSMENU
)
1002 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
1009 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
1014 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1019 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1026 DefWndDoButton(hWnd
, wParam
);
1038 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1049 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1053 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1058 /* Maximize/Restore the window */
1059 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1061 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1067 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1071 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1077 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1081 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1083 if ((wParam
& 0x0f) != HTHSCROLL
)
1085 //ScrollBar = SB_HORZ;
1089 if ((wParam
& 0x0f) != HTVSCROLL
)
1091 //ScrollBar = SB_VERT;
1097 /* PUBLIC FUNCTIONS ***********************************************************/
1100 RealAdjustWindowRectEx(LPRECT lpRect
,
1109 lpRect
->top
-= GetSystemMetrics(SM_CYMENU
);
1111 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1113 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1114 lpRect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
1116 lpRect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
1118 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1131 AdjustWindowRectEx(LPRECT lpRect
,
1136 BOOL Hook
, Ret
= FALSE
;
1140 Hook
= BeginIfHookedUserApiHook();
1142 /* Bypass SEH and go direct. */
1143 if (!Hook
) return RealAdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1147 Ret
= guah
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1149 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1164 AdjustWindowRect(LPRECT lpRect
,
1168 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1171 // Enabling this will cause captions to draw smoother, but slower:
1172 #define DOUBLE_BUFFER_CAPTION
1178 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1180 BOOL Hook
, Ret
= FALSE
;
1184 Hook
= BeginIfHookedUserApiHook();
1186 /* Bypass SEH and go direct. */
1187 if (!Hook
) return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1191 Ret
= guah
.DrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1193 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1218 UNICODE_STRING Text
= {0};
1219 RtlInitUnicodeString(&Text
, str
);
1220 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1242 if (!(uFlags
& DC_TEXT
) || !str
)
1243 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1245 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1246 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1248 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1249 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1250 HeapFree(GetProcessHeap(), 0, strW
);
1255 /***********************************************************************
1258 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1259 * but without the borders (if any).
1260 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1262 static void FASTCALL
1263 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1268 GetWindowRect(Wnd
, Rect
);
1269 Rect
->right
= Rect
->right
- Rect
->left
;
1271 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1274 Style
= GetWindowLongPtrW(Wnd
, GWL_STYLE
);
1275 if (0 != (Style
& WS_ICONIC
))
1280 /* Remove frame from rectangle */
1281 ExStyle
= GetWindowLongPtrW(Wnd
, GWL_EXSTYLE
);
1282 if (HAS_THICKFRAME(Style
, ExStyle
))
1284 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1286 else if (HAS_DLGFRAME(Style
, ExStyle
))
1288 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1290 else if (HAS_THINFRAME(Style
, ExStyle
))
1292 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1295 /* We have additional border information if the window
1296 * is a child (but not an MDI child) */
1297 if (0 != (Style
& WS_CHILD
)
1298 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1300 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1302 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1304 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1306 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1311 /***********************************************************************
1315 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1321 GetWindowRect(Wnd
, Rect
);
1325 NcGetInsideRect(Wnd
, Rect
);
1326 GetWindowRect(Wnd
, &WindowRect
);
1327 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1328 if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1330 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1332 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1333 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;