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, (LPDWORD
)&hIcon
);
128 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (LPDWORD
)&hIcon
);
131 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (LPDWORD
)&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(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 /* FIXME: A tool window has a smaller Close button */
219 if (ExStyle
& WS_EX_TOOLWINDOW
)
221 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSMSIZE
);
222 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMSIZE
) - 2;
226 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
);
227 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
232 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
233 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
234 ((Style
& WS_SYSMENU
) ? 0 : DFCS_INACTIVE
)));
241 UserDrawCaptionButtonWnd(HWND hWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
245 DWORD Style
, ExStyle
;
247 GetWindowRect(hWnd
, &WindowRect
);
248 WindowRect
.right
-= WindowRect
.left
;
249 WindowRect
.bottom
-= WindowRect
.top
;
250 WindowRect
.left
= WindowRect
.top
= 0;
251 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
252 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
253 UserGetWindowBorders(Style
, ExStyle
, &WindowBorder
, FALSE
);
254 InflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
255 UserDrawCaptionButton(&WindowRect
, Style
, ExStyle
, hDC
, bDown
, Type
);
259 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
260 the call to GetDCEx implying that it is allowed not to use it either.
261 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
262 will cause clipRgn to be deleted after ReleaseDC().
263 Now, how is the "system" supposed to tell what happened?
267 * - Drawing of WS_BORDER after scrollbars
268 * - Correct drawing of size-box
271 DefWndNCPaint(HWND hWnd
, HRGN hRgn
, BOOL Active
)
274 DWORD Style
, ExStyle
;
276 RECT ClientRect
, WindowRect
, CurrentRect
, TempRect
;
278 if (!IsWindowVisible(hWnd
))
281 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
283 hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
289 Parent
= GetParent(hWnd
);
290 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
293 if (ExStyle
& WS_EX_MDICHILD
)
295 Active
= IsChild(GetForegroundWindow(), hWnd
);
297 Active
= (hWnd
== (HWND
)SendMessageW(Parent
, WM_MDIGETACTIVE
, 0, 0));
301 Active
= (GetForegroundWindow() == hWnd
);
304 GetWindowRect(hWnd
, &WindowRect
);
305 GetClientRect(hWnd
, &ClientRect
);
307 CurrentRect
.top
= CurrentRect
.left
= 0;
308 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
309 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
311 /* Draw outer edge */
312 if (UserHasWindowEdge(Style
, ExStyle
))
314 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
316 if (ExStyle
& WS_EX_STATICEDGE
)
319 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
321 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNSHADOW
));
322 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
323 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
325 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNHIGHLIGHT
));
326 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
327 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
329 InflateRect(&CurrentRect
, -1, -1);
333 /* Firstly the "thick" frame */
334 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
337 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
338 GetSystemMetrics(SM_CXBORDER
);
340 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
341 GetSystemMetrics(SM_CYBORDER
);
343 SelectObject(hDC
, GetSysColorBrush(Active
? COLOR_ACTIVEBORDER
:
344 COLOR_INACTIVEBORDER
));
347 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
348 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
350 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
351 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
353 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
354 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
357 InflateRect(&CurrentRect
, -Width
, -Height
);
360 /* Now the other bit of the frame */
361 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
363 DWORD Width
= GetSystemMetrics(SM_CXBORDER
);
364 DWORD Height
= GetSystemMetrics(SM_CYBORDER
);
366 SelectObject(hDC
, GetSysColorBrush(
367 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
368 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
369 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
373 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
374 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
376 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
377 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
379 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
380 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
383 InflateRect(&CurrentRect
, -Width
, -Height
);
387 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
389 DWORD CaptionFlags
= DC_ICON
| DC_TEXT
| DC_BUTTONS
;
391 BOOL Gradient
= FALSE
;
393 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
395 CaptionFlags
|= DC_GRADIENT
;
398 TempRect
= CurrentRect
;
402 CaptionFlags
|= DC_ACTIVE
;
405 if (ExStyle
& WS_EX_TOOLWINDOW
)
407 CaptionFlags
|= DC_SMALLCAP
;
408 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
) - 1;
409 CurrentRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
413 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
414 CurrentRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
417 NtUserDrawCaption(hWnd
, hDC
, &TempRect
, CaptionFlags
);
420 if (Style
& WS_SYSMENU
)
422 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
423 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
425 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
426 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
429 if(!(Style
& WS_MINIMIZE
))
431 /* Line under caption */
432 PreviousPen
= SelectObject(hDC
, GetStockObject(DC_PEN
));
433 SetDCPenColor(hDC
, GetSysColor(
434 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
|
435 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
436 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
437 MoveToEx(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
438 LineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
439 SelectObject(hDC
, PreviousPen
);
443 if(!(Style
& WS_MINIMIZE
))
445 HMENU menu
= GetMenu(hWnd
);
447 if (menu
&& !(Style
& WS_CHILD
))
449 TempRect
= CurrentRect
;
450 TempRect
.bottom
= TempRect
.top
+ (UINT
)NtUserSetMenuBarHeight(menu
, 0);
451 CurrentRect
.top
+= MenuDrawMenuBar(hDC
, &TempRect
, hWnd
, FALSE
);
454 if (ExStyle
& WS_EX_CLIENTEDGE
)
456 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
459 /* Draw the scrollbars */
460 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
461 IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
463 RECT ParentClientRect
;
465 TempRect
= CurrentRect
;
466 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
467 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
469 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
470 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
471 FillRect(hDC
, &TempRect
, GetSysColorBrush(COLOR_BTNFACE
));
472 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
474 GetClientRect(Parent
, &ParentClientRect
);
475 if (HASSIZEGRIP(Style
, ExStyle
, GetWindowLongPtrW(Parent
, GWL_STYLE
), WindowRect
, ParentClientRect
))
477 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
479 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
480 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
484 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
))
485 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
486 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
487 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
491 ReleaseDC(hWnd
, hDC
);
497 DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
)
500 DWORD Style
= GetClassLongPtrW(hWnd
, GCL_STYLE
);
513 if (Style
& CS_VREDRAW
)
515 Result
|= WVR_VREDRAW
;
517 if (Style
& CS_HREDRAW
)
519 Result
|= WVR_HREDRAW
;
521 Result
|= WVR_VALIDRECTS
;
524 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
525 ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
527 if (!(Style
& WS_MINIMIZE
))
529 HMENU menu
= GetMenu(hWnd
);
531 if (UserHasWindowEdge(Style
, ExStyle
))
533 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
534 InflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
536 if ((ExStyle
& WS_EX_STATICEDGE
) || (Style
& WS_BORDER
))
538 InflateRect(Rect
, -1, -1);
541 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
543 if (ExStyle
& WS_EX_TOOLWINDOW
)
544 Rect
->top
+= GetSystemMetrics(SM_CYSMCAPTION
);
546 Rect
->top
+= GetSystemMetrics(SM_CYCAPTION
);
549 if (menu
&& !(Style
& WS_CHILD
))
551 HDC hDC
= GetWindowDC(hWnd
);
554 RECT CliRect
= *Rect
;
555 CliRect
.bottom
-= OrigRect
.top
;
556 CliRect
.right
-= OrigRect
.left
;
557 CliRect
.left
-= OrigRect
.left
;
558 CliRect
.top
-= OrigRect
.top
;
559 Rect
->top
+= MenuDrawMenuBar(hDC
, &CliRect
, hWnd
, TRUE
);
560 ReleaseDC(hWnd
, hDC
);
564 if (ExStyle
& WS_EX_CLIENTEDGE
)
566 InflateRect(Rect
, -2 * GetSystemMetrics(SM_CXBORDER
),
567 -2 * GetSystemMetrics(SM_CYBORDER
));
570 if(Style
& (WS_VSCROLL
| WS_HSCROLL
))
573 SETSCROLLBARINFO ssbi
;
575 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
576 if((Style
& WS_VSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &sbi
))
579 LONG sx
= Rect
->right
;
581 sx
-= GetSystemMetrics(SM_CXVSCROLL
);
582 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
583 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
585 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
587 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
588 NtUserSetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &ssbi
);
589 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
590 Style
&= ~WS_VSCROLL
;
593 Style
&= ~WS_VSCROLL
;
595 if((Style
& WS_HSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &sbi
))
598 LONG sy
= Rect
->bottom
;
600 sy
-= GetSystemMetrics(SM_CYHSCROLL
);
601 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
602 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
604 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
606 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
607 NtUserSetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &ssbi
);
608 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
609 Style
&= ~WS_HSCROLL
;
612 Style
&= ~WS_HSCROLL
;
615 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
617 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
618 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
620 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
621 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
625 if (Style
& WS_VSCROLL
)
627 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
628 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
630 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
632 else if (Style
& WS_HSCROLL
)
633 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
635 if (Rect
->top
> Rect
->bottom
)
636 Rect
->bottom
= Rect
->top
;
637 if (Rect
->left
> Rect
->right
)
638 Rect
->right
= Rect
->left
;
642 Rect
->right
= Rect
->left
;
643 Rect
->bottom
= Rect
->top
;
650 DefWndNCActivate(HWND hWnd
, WPARAM wParam
)
652 DefWndNCPaint(hWnd
, (HRGN
)1, wParam
);
658 * - Check the scrollbar handling
661 DefWndNCHitTest(HWND hWnd
, POINT Point
)
663 RECT WindowRect
, ClientRect
, OrigWndRect
;
666 ULONG Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
667 ULONG ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
669 GetWindowRect(hWnd
, &WindowRect
);
670 if (!PtInRect(&WindowRect
, Point
))
674 OrigWndRect
= WindowRect
;
676 if (UserHasWindowEdge(Style
, ExStyle
))
680 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
681 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
682 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
683 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
684 if (!PtInRect(&WindowRect
, Point
))
688 ThickFrame
= (Style
& WS_THICKFRAME
);
689 if (Point
.y
< WindowRect
.top
)
691 if(Style
& WS_MINIMIZE
)
695 if (Point
.x
< (WindowRect
.left
+ XSize
))
697 if (Point
.x
>= (WindowRect
.right
- XSize
))
701 if (Point
.y
>= WindowRect
.bottom
)
703 if(Style
& WS_MINIMIZE
)
707 if (Point
.x
< (WindowRect
.left
+ XSize
))
709 if (Point
.x
>= (WindowRect
.right
- XSize
))
710 return HTBOTTOMRIGHT
;
713 if (Point
.x
< WindowRect
.left
)
715 if(Style
& WS_MINIMIZE
)
719 if (Point
.y
< (WindowRect
.top
+ YSize
))
721 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
725 if (Point
.x
>= WindowRect
.right
)
727 if(Style
& WS_MINIMIZE
)
731 if (Point
.y
< (WindowRect
.top
+ YSize
))
733 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
734 return HTBOTTOMRIGHT
;
741 if (ExStyle
& WS_EX_STATICEDGE
)
742 InflateRect(&WindowRect
,
743 -GetSystemMetrics(SM_CXBORDER
),
744 -GetSystemMetrics(SM_CYBORDER
));
745 if (!PtInRect(&WindowRect
, Point
))
749 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
751 if (ExStyle
& WS_EX_TOOLWINDOW
)
752 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
754 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
755 if (!PtInRect(&WindowRect
, Point
))
757 if (Style
& WS_SYSMENU
)
759 if (ExStyle
& WS_EX_TOOLWINDOW
)
761 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
765 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
766 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
767 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
770 if (Point
.x
< WindowRect
.left
)
772 if (WindowRect
.right
<= Point
.x
)
774 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
775 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
776 if (Point
.x
>= WindowRect
.right
)
778 if (Style
& WS_MINIMIZEBOX
)
779 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
780 if (Point
.x
>= WindowRect
.right
)
786 if(!(Style
& WS_MINIMIZE
))
791 ScreenToClient(hWnd
, &ClientPoint
);
792 GetClientRect(hWnd
, &ClientRect
);
794 if (PtInRect(&ClientRect
, ClientPoint
))
799 if ((menu
= GetMenu(hWnd
)) && !(Style
& WS_CHILD
))
801 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
805 if (ExStyle
& WS_EX_CLIENTEDGE
)
807 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
808 -2 * GetSystemMetrics(SM_CYBORDER
));
811 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
812 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
814 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
815 HWND Parent
= GetParent(hWnd
);
817 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
818 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
819 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
821 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
822 if (PtInRect(&TempRect
, Point
))
825 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
826 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
827 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
829 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
830 if (PtInRect(&TempRect2
, Point
))
833 TempRect
.top
= TempRect2
.top
;
834 TempRect
.bottom
= TempRect2
.bottom
;
836 GetClientRect(Parent
, &ParentRect
);
837 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
838 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
840 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
843 return HTBOTTOMRIGHT
;
848 if (Style
& WS_VSCROLL
)
850 RECT TempRect
= WindowRect
;
852 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
853 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
855 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
856 if (PtInRect(&TempRect
, Point
))
859 if (Style
& WS_HSCROLL
)
861 RECT TempRect
= WindowRect
;
862 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
863 if (PtInRect(&TempRect
, Point
))
873 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
877 BOOL Pressed
= TRUE
, OldState
;
879 ULONG ButtonType
, Style
;
881 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
885 if (!(Style
& WS_SYSMENU
))
887 ButtonType
= DFCS_CAPTIONCLOSE
;
891 if (!(Style
& WS_MINIMIZEBOX
))
893 ButtonType
= DFCS_CAPTIONMIN
;
894 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
897 if (!(Style
& WS_MAXIMIZEBOX
))
899 ButtonType
= DFCS_CAPTIONMAX
;
900 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
909 * FIXME: Not sure where to do this, but we must flush the pending
910 * window updates when someone clicks on the close button and at
911 * the same time the window is overlapped with another one. This
912 * looks like a good place for now...
916 WindowDC
= GetWindowDC(hWnd
);
917 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
923 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
926 if (Msg
.message
== WM_LBUTTONUP
)
929 if (Msg
.message
!= WM_MOUSEMOVE
)
933 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
934 if (Pressed
!= OldState
)
935 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
939 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
941 ReleaseDC(hWnd
, WindowDC
);
943 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
948 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
954 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
955 if (SetActiveWindow(hTopWnd
) || GetActiveWindow() == hTopWnd
)
957 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
963 if (GetWindowLongPtrW(hWnd
, GWL_STYLE
) & WS_SYSMENU
)
965 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
972 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
977 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
982 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
989 DefWndDoButton(hWnd
, wParam
);
1001 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1010 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1014 Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1019 /* Maximize/Restore the window */
1020 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1022 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1028 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1032 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1038 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1042 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1044 if ((wParam
& 0x0f) != HTHSCROLL
)
1046 ScrollBar
= SB_HORZ
;
1050 if ((wParam
& 0x0f) != HTVSCROLL
)
1052 ScrollBar
= SB_VERT
;
1058 /* PUBLIC FUNCTIONS ***********************************************************/
1061 RealAdjustWindowRectEx(LPRECT lpRect
,
1070 lpRect
->top
-= GetSystemMetrics(SM_CYMENU
);
1072 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1074 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1075 lpRect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
1077 lpRect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
1079 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1092 AdjustWindowRectEx(LPRECT lpRect
,
1097 BOOL Hook
, Ret
= FALSE
;
1101 Hook
= BeginIfHookedUserApiHook();
1103 /* Bypass SEH and go direct. */
1104 if (!Hook
) return RealAdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1108 Ret
= guah
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
1110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1125 AdjustWindowRect(LPRECT lpRect
,
1129 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1132 // Enabling this will cause captions to draw smoother, but slower:
1133 #define DOUBLE_BUFFER_CAPTION
1139 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1141 BOOL Hook
, Ret
= FALSE
;
1145 Hook
= BeginIfHookedUserApiHook();
1147 /* Bypass SEH and go direct. */
1148 if (!Hook
) return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1152 Ret
= guah
.DrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1179 UNICODE_STRING Text
= {0};
1180 RtlInitUnicodeString(&Text
, str
);
1181 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1203 if (!(uFlags
& DC_TEXT
) || !str
)
1204 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1206 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1207 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1209 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1210 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1211 HeapFree(GetProcessHeap(), 0, strW
);
1216 /***********************************************************************
1219 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1220 * but without the borders (if any).
1221 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1223 static void FASTCALL
1224 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1229 GetWindowRect(Wnd
, Rect
);
1230 Rect
->right
= Rect
->right
- Rect
->left
;
1232 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1235 Style
= GetWindowLongPtrW(Wnd
, GWL_STYLE
);
1236 if (0 != (Style
& WS_ICONIC
))
1241 /* Remove frame from rectangle */
1242 ExStyle
= GetWindowLongPtrW(Wnd
, GWL_EXSTYLE
);
1243 if (HAS_THICKFRAME(Style
, ExStyle
))
1245 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1247 else if (HAS_DLGFRAME(Style
, ExStyle
))
1249 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1251 else if (HAS_THINFRAME(Style
, ExStyle
))
1253 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1256 /* We have additional border information if the window
1257 * is a child (but not an MDI child) */
1258 if (0 != (Style
& WS_CHILD
)
1259 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1261 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1263 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1265 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1267 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1272 /***********************************************************************
1276 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1282 GetWindowRect(Wnd
, Rect
);
1286 NcGetInsideRect(Wnd
, Rect
);
1287 GetWindowRect(Wnd
, &WindowRect
);
1288 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1289 if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1291 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1293 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1294 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;