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 Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 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 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; see the file COPYING.LIB.
19 * If not, write to the Free Software Foundation,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* INCLUDES *******************************************************************/
27 #include <wine/debug.h>
29 #define HAS_DLGFRAME(Style, ExStyle) \
30 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
31 (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))
33 #define HAS_THICKFRAME(Style, ExStyle) \
34 (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
35 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
37 #define HAS_THINFRAME(Style, ExStyle) \
38 (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))
40 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
41 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
42 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
43 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
44 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
46 #ifndef STATE_SYSTEM_OFFSCREEN
47 #define STATE_SYSTEM_OFFSCREEN 0x00010000
51 * FIXME: This should be moved to a header
54 IntDrawScrollBar(HWND hWnd
, HDC hDC
, INT nBar
);
56 IntScrollHitTest(HWND hWnd
, INT nBar
, POINT pt
, BOOL bDragging
);
58 BOOL WINAPI
GdiGradientFill(HDC
,PTRIVERTEX
,ULONG
,PVOID
,ULONG
,ULONG
);
60 extern ATOM AtomInternalPos
;
62 /* PRIVATE FUNCTIONS **********************************************************/
65 IntIsScrollBarVisible(HWND hWnd
, INT hBar
)
68 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
69 if(!NtUserGetScrollBarInfo(hWnd
, hBar
, &sbi
))
72 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
76 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
78 if (Style
& WS_MINIMIZE
)
80 if (ExStyle
& WS_EX_DLGMODALFRAME
)
82 if (ExStyle
& WS_EX_STATICEDGE
)
84 if (Style
& WS_THICKFRAME
)
87 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
93 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
97 if (UserHasWindowEdge(Style
, ExStyle
))
99 else if (ExStyle
& WS_EX_STATICEDGE
)
101 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
103 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
105 Size
->cx
= Size
->cy
= Border
;
106 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
108 Size
->cx
+= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
109 Size
->cy
+= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
111 Size
->cx
*= GetSystemMetrics(SM_CXBORDER
);
112 Size
->cy
*= GetSystemMetrics(SM_CYBORDER
);
116 UserHasMenu(HWND hWnd
, ULONG Style
)
118 return (!(Style
& WS_CHILD
) && GetMenu(hWnd
) != 0);
122 UserGetWindowIcon(HWND hwnd
)
126 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
129 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
132 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (PDWORD_PTR
)&hIcon
);
135 hIcon
= (HICON
)GetClassLongPtr(hwnd
, GCL_HICONSM
);
138 hIcon
= (HICON
)GetClassLongPtr(hwnd
, GCL_HICON
);
144 UserDrawSysMenuButton(HWND hWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
148 if ((WindowIcon
= UserGetWindowIcon(hWnd
)))
150 return DrawIconEx(hDC
, Rect
->left
+ 2, Rect
->top
+ 2, WindowIcon
,
151 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
160 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
161 * wasting precious CPU cycles) every time
162 * - Center the buttons verticaly in the rect
165 UserDrawCaptionButton(LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
169 if (!(Style
& WS_SYSMENU
))
178 case DFCS_CAPTIONMIN
:
180 if (ExStyle
& WS_EX_TOOLWINDOW
)
181 return; /* ToolWindows don't have min/max buttons */
183 if (Style
& WS_SYSMENU
)
184 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
185 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
186 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
187 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
188 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
192 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
193 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
194 (bDown
? DFCS_PUSHED
: 0) |
195 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
198 case DFCS_CAPTIONMAX
:
200 if (ExStyle
& WS_EX_TOOLWINDOW
)
201 return; /* ToolWindows don't have min/max buttons */
203 if (Style
& WS_SYSMENU
)
204 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
205 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
206 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
210 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
211 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
212 (bDown
? DFCS_PUSHED
: 0) |
213 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
216 case DFCS_CAPTIONCLOSE
:
218 /* FIXME: A tool window has a smaller Close button */
220 if (ExStyle
& WS_EX_TOOLWINDOW
)
222 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSMSIZE
);
223 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMSIZE
) - 2;
227 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
);
228 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
233 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
234 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
235 ((Style
& WS_SYSMENU
) ? 0 : DFCS_INACTIVE
)));
242 UserDrawCaptionButtonWnd(HWND hWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
246 DWORD Style
, ExStyle
;
248 GetWindowRect(hWnd
, &WindowRect
);
249 WindowRect
.right
-= WindowRect
.left
;
250 WindowRect
.bottom
-= WindowRect
.top
;
251 WindowRect
.left
= WindowRect
.top
= 0;
252 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
253 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
254 UserGetWindowBorders(Style
, ExStyle
, &WindowBorder
, FALSE
);
255 InflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
256 UserDrawCaptionButton(&WindowRect
, Style
, ExStyle
, hDC
, bDown
, Type
);
260 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
261 the call to GetDCEx implying that it is allowed not to use it either.
262 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
263 will cause clipRgn to be deleted after ReleaseDC().
264 Now, how is the "system" supposed to tell what happened?
268 * - Drawing of WS_BORDER after scrollbars
269 * - Correct drawing of size-box
272 DefWndNCPaint(HWND hWnd
, HRGN hRgn
, BOOL Active
)
275 DWORD Style
, ExStyle
;
277 RECT ClientRect
, WindowRect
, CurrentRect
, TempRect
;
279 if (!IsWindowVisible(hWnd
))
282 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
284 hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
290 Parent
= GetParent(hWnd
);
291 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
294 if (ExStyle
& WS_EX_MDICHILD
)
296 Active
= IsChild(GetForegroundWindow(), hWnd
);
298 Active
= (hWnd
== (HWND
)SendMessageW(Parent
, WM_MDIGETACTIVE
, 0, 0));
302 Active
= (GetForegroundWindow() == hWnd
);
305 GetWindowRect(hWnd
, &WindowRect
);
306 GetClientRect(hWnd
, &ClientRect
);
308 CurrentRect
.top
= CurrentRect
.left
= 0;
309 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
310 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
312 /* Draw outer edge */
313 if (UserHasWindowEdge(Style
, ExStyle
))
315 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
317 if (ExStyle
& WS_EX_STATICEDGE
)
320 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
322 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNSHADOW
));
323 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
324 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
326 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNHIGHLIGHT
));
327 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
328 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
330 InflateRect(&CurrentRect
, -1, -1);
334 /* Firstly the "thick" frame */
335 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
338 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
339 GetSystemMetrics(SM_CXBORDER
);
341 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
342 GetSystemMetrics(SM_CYBORDER
);
344 SelectObject(hDC
, GetSysColorBrush(Active
? COLOR_ACTIVEBORDER
:
345 COLOR_INACTIVEBORDER
));
348 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
349 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
351 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
352 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
354 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
355 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
358 InflateRect(&CurrentRect
, -Width
, -Height
);
361 /* Now the other bit of the frame */
362 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
364 DWORD Width
= GetSystemMetrics(SM_CXBORDER
);
365 DWORD Height
= GetSystemMetrics(SM_CYBORDER
);
367 SelectObject(hDC
, GetSysColorBrush(
368 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
369 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
370 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
374 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
375 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
377 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
378 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
380 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
381 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
384 InflateRect(&CurrentRect
, -Width
, -Height
);
388 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
390 DWORD CaptionFlags
= DC_ICON
| DC_TEXT
| DC_BUTTONS
;
392 BOOL Gradient
= FALSE
;
394 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
396 CaptionFlags
|= DC_GRADIENT
;
399 TempRect
= CurrentRect
;
403 CaptionFlags
|= DC_ACTIVE
;
406 if (ExStyle
& WS_EX_TOOLWINDOW
)
408 CaptionFlags
|= DC_SMALLCAP
;
409 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
) - 1;
410 CurrentRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
414 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
415 CurrentRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
418 NtUserDrawCaption(hWnd
, hDC
, &TempRect
, CaptionFlags
);
421 if (Style
& WS_SYSMENU
)
423 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
424 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
426 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
427 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
430 if(!(Style
& WS_MINIMIZE
))
432 /* Line under caption */
433 PreviousPen
= SelectObject(hDC
, GetStockObject(DC_PEN
));
434 SetDCPenColor(hDC
, GetSysColor(
435 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
|
436 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
437 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
438 MoveToEx(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
439 LineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
440 SelectObject(hDC
, PreviousPen
);
444 if(!(Style
& WS_MINIMIZE
))
446 HMENU menu
= GetMenu(hWnd
);
448 if (menu
&& !(Style
& WS_CHILD
))
450 TempRect
= CurrentRect
;
451 TempRect
.bottom
= TempRect
.top
+ (UINT
)NtUserSetMenuBarHeight(menu
, 0);
452 CurrentRect
.top
+= MenuDrawMenuBar(hDC
, &TempRect
, hWnd
, FALSE
);
455 if (ExStyle
& WS_EX_CLIENTEDGE
)
457 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
460 /* Draw the scrollbars */
461 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
462 IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
464 RECT ParentClientRect
;
466 TempRect
= CurrentRect
;
467 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
468 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
470 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
471 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
472 FillRect(hDC
, &TempRect
, GetSysColorBrush(COLOR_BTNFACE
));
473 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
475 GetClientRect(Parent
, &ParentClientRect
);
476 if (HASSIZEGRIP(Style
, ExStyle
, GetWindowLongPtrW(Parent
, GWL_STYLE
), WindowRect
, ParentClientRect
))
478 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
480 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
481 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
485 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
))
486 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
487 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
488 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
492 ReleaseDC(hWnd
, hDC
);
498 DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
)
501 DWORD Style
= GetClassLongPtrW(hWnd
, GCL_STYLE
);
514 if (Style
& CS_VREDRAW
)
516 Result
|= WVR_VREDRAW
;
518 if (Style
& CS_HREDRAW
)
520 Result
|= WVR_HREDRAW
;
522 Result
|= WVR_VALIDRECTS
;
525 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
526 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
528 if (!(Style
& WS_MINIMIZE
))
530 HMENU menu
= GetMenu(hWnd
);
532 if (UserHasWindowEdge(Style
, ExStyle
))
534 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
535 InflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
537 if ((ExStyle
& WS_EX_STATICEDGE
) || (Style
& WS_BORDER
))
539 InflateRect(Rect
, -1, -1);
542 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
544 if (ExStyle
& WS_EX_TOOLWINDOW
)
545 Rect
->top
+= GetSystemMetrics(SM_CYSMCAPTION
);
547 Rect
->top
+= GetSystemMetrics(SM_CYCAPTION
);
550 if (menu
&& !(Style
& WS_CHILD
))
552 HDC hDC
= GetWindowDC(hWnd
);
555 RECT CliRect
= *Rect
;
556 CliRect
.bottom
-= OrigRect
.top
;
557 CliRect
.right
-= OrigRect
.left
;
558 CliRect
.left
-= OrigRect
.left
;
559 CliRect
.top
-= OrigRect
.top
;
560 Rect
->top
+= MenuDrawMenuBar(hDC
, &CliRect
, hWnd
, TRUE
);
561 ReleaseDC(hWnd
, hDC
);
565 if (ExStyle
& WS_EX_CLIENTEDGE
)
567 InflateRect(Rect
, -2 * GetSystemMetrics(SM_CXBORDER
),
568 -2 * GetSystemMetrics(SM_CYBORDER
));
571 if(Style
& (WS_VSCROLL
| WS_HSCROLL
))
574 SETSCROLLBARINFO ssbi
;
576 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
577 if((Style
& WS_VSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &sbi
))
580 LONG sx
= Rect
->right
;
582 sx
-= GetSystemMetrics(SM_CXVSCROLL
);
583 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
584 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
586 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
588 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
589 NtUserSetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &ssbi
);
590 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
591 Style
&= ~WS_VSCROLL
;
594 Style
&= ~WS_VSCROLL
;
596 if((Style
& WS_HSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &sbi
))
599 LONG sy
= Rect
->bottom
;
601 sy
-= GetSystemMetrics(SM_CYHSCROLL
);
602 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
603 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
605 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
607 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
608 NtUserSetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &ssbi
);
609 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
610 Style
&= ~WS_HSCROLL
;
613 Style
&= ~WS_HSCROLL
;
616 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
618 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
619 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
621 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
622 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
626 if (Style
& WS_VSCROLL
)
628 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
629 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
631 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
633 else if (Style
& WS_HSCROLL
)
634 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
636 if (Rect
->top
> Rect
->bottom
)
637 Rect
->bottom
= Rect
->top
;
638 if (Rect
->left
> Rect
->right
)
639 Rect
->right
= Rect
->left
;
643 Rect
->right
= Rect
->left
;
644 Rect
->bottom
= Rect
->top
;
651 DefWndNCActivate(HWND hWnd
, WPARAM wParam
)
653 DefWndNCPaint(hWnd
, (HRGN
)1, wParam
);
659 * - Check the scrollbar handling
662 DefWndNCHitTest(HWND hWnd
, POINT Point
)
664 RECT WindowRect
, ClientRect
, OrigWndRect
;
667 ULONG Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
668 ULONG ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
670 GetWindowRect(hWnd
, &WindowRect
);
671 if (!PtInRect(&WindowRect
, Point
))
675 OrigWndRect
= WindowRect
;
677 if (UserHasWindowEdge(Style
, ExStyle
))
681 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
682 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
683 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
684 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
685 if (!PtInRect(&WindowRect
, Point
))
689 ThickFrame
= (Style
& WS_THICKFRAME
);
690 if (Point
.y
< WindowRect
.top
)
692 if(Style
& WS_MINIMIZE
)
696 if (Point
.x
< (WindowRect
.left
+ XSize
))
698 if (Point
.x
>= (WindowRect
.right
- XSize
))
702 if (Point
.y
>= WindowRect
.bottom
)
704 if(Style
& WS_MINIMIZE
)
708 if (Point
.x
< (WindowRect
.left
+ XSize
))
710 if (Point
.x
>= (WindowRect
.right
- XSize
))
711 return HTBOTTOMRIGHT
;
714 if (Point
.x
< WindowRect
.left
)
716 if(Style
& WS_MINIMIZE
)
720 if (Point
.y
< (WindowRect
.top
+ YSize
))
722 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
726 if (Point
.x
>= WindowRect
.right
)
728 if(Style
& WS_MINIMIZE
)
732 if (Point
.y
< (WindowRect
.top
+ YSize
))
734 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
735 return HTBOTTOMRIGHT
;
742 if (ExStyle
& WS_EX_STATICEDGE
)
743 InflateRect(&WindowRect
,
744 -GetSystemMetrics(SM_CXBORDER
),
745 -GetSystemMetrics(SM_CYBORDER
));
746 if (!PtInRect(&WindowRect
, Point
))
750 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
752 if (ExStyle
& WS_EX_TOOLWINDOW
)
753 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
755 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
756 if (!PtInRect(&WindowRect
, Point
))
758 if (Style
& WS_SYSMENU
)
760 if (ExStyle
& WS_EX_TOOLWINDOW
)
762 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
766 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
767 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
768 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
771 if (Point
.x
< WindowRect
.left
)
773 if (WindowRect
.right
<= Point
.x
)
775 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
776 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
777 if (Point
.x
>= WindowRect
.right
)
779 if (Style
& WS_MINIMIZEBOX
)
780 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
781 if (Point
.x
>= WindowRect
.right
)
787 if(!(Style
& WS_MINIMIZE
))
792 ScreenToClient(hWnd
, &ClientPoint
);
793 GetClientRect(hWnd
, &ClientRect
);
795 if (PtInRect(&ClientRect
, ClientPoint
))
800 if ((menu
= GetMenu(hWnd
)) && !(Style
& WS_CHILD
))
802 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
806 if (ExStyle
& WS_EX_CLIENTEDGE
)
808 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
809 -2 * GetSystemMetrics(SM_CYBORDER
));
812 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
813 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
815 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
816 HWND Parent
= GetParent(hWnd
);
818 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
819 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
820 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
822 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
823 if (PtInRect(&TempRect
, Point
))
826 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
827 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
828 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
830 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
831 if (PtInRect(&TempRect2
, Point
))
834 TempRect
.top
= TempRect2
.top
;
835 TempRect
.bottom
= TempRect2
.bottom
;
837 GetClientRect(Parent
, &ParentRect
);
838 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
839 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
841 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
844 return HTBOTTOMRIGHT
;
849 if (Style
& WS_VSCROLL
)
851 RECT TempRect
= WindowRect
;
853 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
854 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
856 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
857 if (PtInRect(&TempRect
, Point
))
860 if (Style
& WS_HSCROLL
)
862 RECT TempRect
= WindowRect
;
863 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
864 if (PtInRect(&TempRect
, Point
))
874 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
878 BOOL Pressed
= TRUE
, OldState
;
880 ULONG ButtonType
, Style
;
882 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
886 if (!(Style
& WS_SYSMENU
))
888 ButtonType
= DFCS_CAPTIONCLOSE
;
892 if (!(Style
& WS_MINIMIZEBOX
))
894 ButtonType
= DFCS_CAPTIONMIN
;
895 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
898 if (!(Style
& WS_MAXIMIZEBOX
))
900 ButtonType
= DFCS_CAPTIONMAX
;
901 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
910 * FIXME: Not sure where to do this, but we must flush the pending
911 * window updates when someone clicks on the close button and at
912 * the same time the window is overlapped with another one. This
913 * looks like a good place for now...
917 WindowDC
= GetWindowDC(hWnd
);
918 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
924 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
927 if (Msg
.message
== WM_LBUTTONUP
)
930 if (Msg
.message
!= WM_MOUSEMOVE
)
934 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
935 if (Pressed
!= OldState
)
936 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
940 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
942 ReleaseDC(hWnd
, WindowDC
);
944 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
949 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
955 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
956 if (SetActiveWindow(hTopWnd
) || GetActiveWindow() == hTopWnd
)
958 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
964 if (GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_SYSMENU
)
966 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
973 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
978 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
983 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
990 DefWndDoButton(hWnd
, wParam
);
1002 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1011 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1015 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1020 /* Maximize/Restore the window */
1021 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1023 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1029 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1033 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1039 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1043 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1045 if ((wParam
& 0x0f) != HTHSCROLL
)
1047 ScrollBar
= SB_HORZ
;
1051 if ((wParam
& 0x0f) != HTVSCROLL
)
1053 ScrollBar
= SB_VERT
;
1059 /* PUBLIC FUNCTIONS ***********************************************************/
1062 RealAdjustWindowRectEx(LPRECT lpRect
,
1071 lpRect
->top
-= GetSystemMetrics(SM_CYMENU
);
1073 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1075 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1076 lpRect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
1078 lpRect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
1080 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1093 AdjustWindowRectEx(LPRECT lpRect
,
1098 BOOL Hook
, Ret
= FALSE
;
1102 Hook
= BeginIfHookedUserApiHook();
1104 /* Bypass SEH and go direct. */
1105 if (!Hook
) return RealAdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1109 Ret
= guah
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1111 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1126 AdjustWindowRect(LPRECT lpRect
,
1130 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1133 // Enabling this will cause captions to draw smoother, but slower:
1134 #define DOUBLE_BUFFER_CAPTION
1140 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1142 BOOL Hook
, Ret
= FALSE
;
1146 Hook
= BeginIfHookedUserApiHook();
1148 /* Bypass SEH and go direct. */
1149 if (!Hook
) return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1153 Ret
= guah
.DrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1180 UNICODE_STRING Text
= {0};
1181 RtlInitUnicodeString(&Text
, str
);
1182 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1204 if (!(uFlags
& DC_TEXT
) || !str
)
1205 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1207 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1208 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1210 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1211 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1212 HeapFree(GetProcessHeap(), 0, strW
);
1217 /***********************************************************************
1220 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1221 * but without the borders (if any).
1222 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1224 static void FASTCALL
1225 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1230 GetWindowRect(Wnd
, Rect
);
1231 Rect
->right
= Rect
->right
- Rect
->left
;
1233 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1236 Style
= GetWindowLongPtrW(Wnd
, GWL_STYLE
);
1237 if (0 != (Style
& WS_ICONIC
))
1242 /* Remove frame from rectangle */
1243 ExStyle
= GetWindowLongPtrW(Wnd
, GWL_EXSTYLE
);
1244 if (HAS_THICKFRAME(Style
, ExStyle
))
1246 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1248 else if (HAS_DLGFRAME(Style
, ExStyle
))
1250 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1252 else if (HAS_THINFRAME(Style
, ExStyle
))
1254 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1257 /* We have additional border information if the window
1258 * is a child (but not an MDI child) */
1259 if (0 != (Style
& WS_CHILD
)
1260 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1262 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1264 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1266 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1268 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1273 /***********************************************************************
1277 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1283 GetWindowRect(Wnd
, Rect
);
1287 NcGetInsideRect(Wnd
, Rect
);
1288 GetWindowRect(Wnd
, &WindowRect
);
1289 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1290 if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1292 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1294 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1295 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;