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 GetSysColorPen(int nIndex
);
60 BOOL WINAPI
GdiGradientFill(HDC
,PTRIVERTEX
,ULONG
,PVOID
,ULONG
,ULONG
);
62 extern ATOM AtomInternalPos
;
64 /* PRIVATE FUNCTIONS **********************************************************/
67 IntIsScrollBarVisible(HWND hWnd
, INT hBar
)
70 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
71 if(!NtUserGetScrollBarInfo(hWnd
, hBar
, &sbi
))
74 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
78 UserHasWindowEdge(DWORD Style
, DWORD ExStyle
)
80 if (Style
& WS_MINIMIZE
)
82 if (ExStyle
& WS_EX_DLGMODALFRAME
)
84 if (ExStyle
& WS_EX_STATICEDGE
)
86 if (Style
& WS_THICKFRAME
)
89 if (Style
== WS_DLGFRAME
|| Style
== WS_CAPTION
)
95 UserGetWindowBorders(DWORD Style
, DWORD ExStyle
, SIZE
*Size
, BOOL WithClient
)
99 if (UserHasWindowEdge(Style
, ExStyle
))
101 else if (ExStyle
& WS_EX_STATICEDGE
)
103 if ((ExStyle
& WS_EX_CLIENTEDGE
) && WithClient
)
105 if (Style
& WS_CAPTION
|| ExStyle
& WS_EX_DLGMODALFRAME
)
107 Size
->cx
= Size
->cy
= Border
;
108 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
110 Size
->cx
+= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
111 Size
->cy
+= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
113 Size
->cx
*= GetSystemMetrics(SM_CXBORDER
);
114 Size
->cy
*= GetSystemMetrics(SM_CYBORDER
);
118 UserHasMenu(HWND hWnd
, ULONG Style
)
120 return (!(Style
& WS_CHILD
) && GetMenu(hWnd
) != 0);
124 UserGetWindowIcon(HWND hwnd
)
128 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL2
, 0, SMTO_ABORTIFHUNG
, 1000, (LPDWORD
)&hIcon
);
131 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_SMALL
, 0, SMTO_ABORTIFHUNG
, 1000, (LPDWORD
)&hIcon
);
134 SendMessageTimeout(hwnd
, WM_GETICON
, ICON_BIG
, 0, SMTO_ABORTIFHUNG
, 1000, (LPDWORD
)&hIcon
);
137 hIcon
= (HICON
)GetClassLong(hwnd
, GCL_HICONSM
);
140 hIcon
= (HICON
)GetClassLong(hwnd
, GCL_HICON
);
146 UserDrawSysMenuButton(HWND hWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
150 if ((WindowIcon
= UserGetWindowIcon(hWnd
)))
152 return DrawIconEx(hDC
, Rect
->left
+ 2, Rect
->top
+ 2, WindowIcon
,
153 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
162 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
163 * wasting precious CPU cycles) every time
164 * - Center the buttons verticaly in the rect
167 UserDrawCaptionButton(LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
171 if (!(Style
& WS_SYSMENU
))
180 case DFCS_CAPTIONMIN
:
182 if (ExStyle
& WS_EX_TOOLWINDOW
)
183 return; /* ToolWindows don't have min/max buttons */
185 if (Style
& WS_SYSMENU
)
186 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
187 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
188 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
189 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
190 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
194 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
195 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
196 (bDown
? DFCS_PUSHED
: 0) |
197 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
200 case DFCS_CAPTIONMAX
:
202 if (ExStyle
& WS_EX_TOOLWINDOW
)
203 return; /* ToolWindows don't have min/max buttons */
205 if (Style
& WS_SYSMENU
)
206 TempRect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
207 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXSIZE
) + 1;
208 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
212 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
213 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
214 (bDown
? DFCS_PUSHED
: 0) |
215 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
218 case DFCS_CAPTIONCLOSE
:
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 ((Style
& WS_SYSMENU
) ? 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
= GetWindowLongW(hWnd
, GWL_STYLE
);
255 ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
256 UserGetWindowBorders(Style
, ExStyle
, &WindowBorder
, FALSE
);
257 InflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
258 UserDrawCaptionButton(&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
= GetWindowLongW(hWnd
, GWL_STYLE
);
286 hDC
= GetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
292 Parent
= GetParent(hWnd
);
293 ExStyle
= GetWindowLongW(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(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
426 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
428 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
429 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
432 if(!(Style
& WS_MINIMIZE
))
434 /* Line under caption */
435 PreviousPen
= SelectObject(hDC
, GetSysColorPen(
436 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
|
437 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
438 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
439 MoveToEx(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
440 LineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
441 SelectObject(hDC
, PreviousPen
);
445 if(!(Style
& WS_MINIMIZE
))
447 HMENU menu
= GetMenu(hWnd
);
449 if (menu
&& !(Style
& WS_CHILD
))
451 TempRect
= CurrentRect
;
452 TempRect
.bottom
= TempRect
.top
+ (UINT
)NtUserSetMenuBarHeight(menu
, 0);
453 CurrentRect
.top
+= MenuDrawMenuBar(hDC
, &TempRect
, hWnd
, FALSE
);
456 if (ExStyle
& WS_EX_CLIENTEDGE
)
458 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
461 /* Draw the scrollbars */
462 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
463 IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
465 RECT ParentClientRect
;
467 TempRect
= CurrentRect
;
468 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
469 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
471 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
472 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
473 FillRect(hDC
, &TempRect
, GetSysColorBrush(COLOR_BTNFACE
));
474 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
476 GetClientRect(Parent
, &ParentClientRect
);
477 if (HASSIZEGRIP(Style
, ExStyle
, GetWindowLongW(Parent
, GWL_STYLE
), WindowRect
, ParentClientRect
))
479 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
481 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
482 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
486 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
))
487 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
488 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
489 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
493 ReleaseDC(hWnd
, hDC
);
499 DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
)
502 DWORD Style
= GetClassLongW(hWnd
, GCL_STYLE
);
505 RECT OrigRect
= *Rect
;
509 if (Style
& CS_VREDRAW
)
511 Result
|= WVR_VREDRAW
;
513 if (Style
& CS_HREDRAW
)
515 Result
|= WVR_HREDRAW
;
517 Result
|= WVR_VALIDRECTS
;
520 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
521 ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
523 if (!(Style
& WS_MINIMIZE
))
525 HMENU menu
= GetMenu(hWnd
);
527 if (UserHasWindowEdge(Style
, ExStyle
))
529 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
530 InflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
532 if ((ExStyle
& WS_EX_STATICEDGE
) || (Style
& WS_BORDER
))
534 InflateRect(Rect
, -1, -1);
537 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
539 if (ExStyle
& WS_EX_TOOLWINDOW
)
540 Rect
->top
+= GetSystemMetrics(SM_CYSMCAPTION
);
542 Rect
->top
+= GetSystemMetrics(SM_CYCAPTION
);
545 if (menu
&& !(Style
& WS_CHILD
))
547 HDC hDC
= GetWindowDC(hWnd
);
550 RECT CliRect
= *Rect
;
551 CliRect
.bottom
-= OrigRect
.top
;
552 CliRect
.right
-= OrigRect
.left
;
553 CliRect
.left
-= OrigRect
.left
;
554 CliRect
.top
-= OrigRect
.top
;
555 Rect
->top
+= MenuDrawMenuBar(hDC
, &CliRect
, hWnd
, TRUE
);
556 ReleaseDC(hWnd
, hDC
);
560 if (ExStyle
& WS_EX_CLIENTEDGE
)
562 InflateRect(Rect
, -2 * GetSystemMetrics(SM_CXBORDER
),
563 -2 * GetSystemMetrics(SM_CYBORDER
));
566 if(Style
& (WS_VSCROLL
| WS_HSCROLL
))
569 SETSCROLLBARINFO ssbi
;
571 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
572 if((Style
& WS_VSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &sbi
))
575 LONG sx
= Rect
->right
;
577 sx
-= GetSystemMetrics(SM_CXVSCROLL
);
578 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
579 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
581 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
583 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
584 NtUserSetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &ssbi
);
585 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
586 Style
&= ~WS_VSCROLL
;
589 Style
&= ~WS_VSCROLL
;
591 if((Style
& WS_HSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &sbi
))
594 LONG sy
= Rect
->bottom
;
596 sy
-= GetSystemMetrics(SM_CYHSCROLL
);
597 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
598 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
600 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
602 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
603 NtUserSetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &ssbi
);
604 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
605 Style
&= ~WS_HSCROLL
;
608 Style
&= ~WS_HSCROLL
;
611 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
613 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
614 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
616 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
617 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
621 if (Style
& WS_VSCROLL
)
623 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
624 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
626 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
628 else if (Style
& WS_HSCROLL
)
629 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
631 if (Rect
->top
> Rect
->bottom
)
632 Rect
->bottom
= Rect
->top
;
633 if (Rect
->left
> Rect
->right
)
634 Rect
->right
= Rect
->left
;
638 Rect
->right
= Rect
->left
;
639 Rect
->bottom
= Rect
->top
;
646 DefWndNCActivate(HWND hWnd
, WPARAM wParam
)
648 DefWndNCPaint(hWnd
, (HRGN
)1, wParam
);
654 * - Check the scrollbar handling
657 DefWndNCHitTest(HWND hWnd
, POINT Point
)
659 RECT WindowRect
, ClientRect
, OrigWndRect
;
662 ULONG Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
663 ULONG ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
665 GetWindowRect(hWnd
, &WindowRect
);
666 if (!PtInRect(&WindowRect
, Point
))
670 OrigWndRect
= WindowRect
;
672 if (UserHasWindowEdge(Style
, ExStyle
))
676 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
677 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
678 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
679 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
680 if (!PtInRect(&WindowRect
, Point
))
684 ThickFrame
= (Style
& WS_THICKFRAME
);
685 if (Point
.y
< WindowRect
.top
)
687 if(Style
& WS_MINIMIZE
)
691 if (Point
.x
< (WindowRect
.left
+ XSize
))
693 if (Point
.x
>= (WindowRect
.right
- XSize
))
697 if (Point
.y
>= WindowRect
.bottom
)
699 if(Style
& WS_MINIMIZE
)
703 if (Point
.x
< (WindowRect
.left
+ XSize
))
705 if (Point
.x
>= (WindowRect
.right
- XSize
))
706 return HTBOTTOMRIGHT
;
709 if (Point
.x
< WindowRect
.left
)
711 if(Style
& WS_MINIMIZE
)
715 if (Point
.y
< (WindowRect
.top
+ YSize
))
717 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
721 if (Point
.x
>= WindowRect
.right
)
723 if(Style
& WS_MINIMIZE
)
727 if (Point
.y
< (WindowRect
.top
+ YSize
))
729 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
730 return HTBOTTOMRIGHT
;
737 if (ExStyle
& WS_EX_STATICEDGE
)
738 InflateRect(&WindowRect
,
739 -GetSystemMetrics(SM_CXBORDER
),
740 -GetSystemMetrics(SM_CYBORDER
));
741 if (!PtInRect(&WindowRect
, Point
))
745 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
747 if (ExStyle
& WS_EX_TOOLWINDOW
)
748 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
750 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
751 if (!PtInRect(&WindowRect
, Point
))
753 if (Style
& WS_SYSMENU
)
755 if (ExStyle
& WS_EX_TOOLWINDOW
)
757 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
761 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
762 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
763 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
766 if (Point
.x
< WindowRect
.left
)
768 if (WindowRect
.right
<= Point
.x
)
770 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
771 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
772 if (Point
.x
>= WindowRect
.right
)
774 if (Style
& WS_MINIMIZEBOX
)
775 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
776 if (Point
.x
>= WindowRect
.right
)
782 if(!(Style
& WS_MINIMIZE
))
787 ScreenToClient(hWnd
, &ClientPoint
);
788 GetClientRect(hWnd
, &ClientRect
);
790 if (PtInRect(&ClientRect
, ClientPoint
))
795 if ((menu
= GetMenu(hWnd
)) && !(Style
& WS_CHILD
))
797 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
801 if (ExStyle
& WS_EX_CLIENTEDGE
)
803 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
804 -2 * GetSystemMetrics(SM_CYBORDER
));
807 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
808 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
810 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
811 HWND Parent
= GetParent(hWnd
);
813 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
814 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
815 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
817 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
818 if (PtInRect(&TempRect
, Point
))
821 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
822 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
823 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
825 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
826 if (PtInRect(&TempRect2
, Point
))
829 TempRect
.top
= TempRect2
.top
;
830 TempRect
.bottom
= TempRect2
.bottom
;
832 GetClientRect(Parent
, &ParentRect
);
833 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
834 GetWindowLongW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
836 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
839 return HTBOTTOMRIGHT
;
844 if (Style
& WS_VSCROLL
)
846 RECT TempRect
= WindowRect
;
848 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
849 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
851 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
852 if (PtInRect(&TempRect
, Point
))
855 if (Style
& WS_HSCROLL
)
857 RECT TempRect
= WindowRect
;
858 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
859 if (PtInRect(&TempRect
, Point
))
869 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
873 BOOL Pressed
= TRUE
, OldState
;
875 ULONG ButtonType
, Style
;
877 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
881 if (!(Style
& WS_SYSMENU
))
883 ButtonType
= DFCS_CAPTIONCLOSE
;
887 if (!(Style
& WS_MINIMIZEBOX
))
889 ButtonType
= DFCS_CAPTIONMIN
;
890 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
893 if (!(Style
& WS_MAXIMIZEBOX
))
895 ButtonType
= DFCS_CAPTIONMAX
;
896 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
905 * FIXME: Not sure where to do this, but we must flush the pending
906 * window updates when someone clicks on the close button and at
907 * the same time the window is overlapped with another one. This
908 * looks like a good place for now...
912 WindowDC
= GetWindowDC(hWnd
);
913 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
919 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
922 if (Msg
.message
== WM_LBUTTONUP
)
925 if (Msg
.message
!= WM_MOUSEMOVE
)
929 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
930 if (Pressed
!= OldState
)
931 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
935 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
937 ReleaseDC(hWnd
, WindowDC
);
939 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
944 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
950 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
951 if (SetActiveWindow(hTopWnd
) || GetActiveWindow() == hTopWnd
)
953 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
959 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_SYSMENU
)
961 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
968 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
973 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
978 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
985 DefWndDoButton(hWnd
, wParam
);
997 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1006 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1010 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
1015 /* Maximize/Restore the window */
1016 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1018 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1024 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1028 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1034 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1038 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1040 if ((wParam
& 0x0f) != HTHSCROLL
)
1042 ScrollBar
= SB_HORZ
;
1046 if ((wParam
& 0x0f) != HTVSCROLL
)
1048 ScrollBar
= SB_VERT
;
1054 /* PUBLIC FUNCTIONS ***********************************************************/
1060 AdjustWindowRectEx(LPRECT lpRect
,
1069 lpRect
->top
-= GetSystemMetrics(SM_CYMENU
);
1071 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1073 if (dwExStyle
& WS_EX_TOOLWINDOW
)
1074 lpRect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
1076 lpRect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
1078 UserGetWindowBorders(dwStyle
, dwExStyle
, &BorderSize
, TRUE
);
1092 AdjustWindowRect(LPRECT lpRect
,
1096 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1099 // Enabling this will cause captions to draw smoother, but slower:
1100 #define DOUBLE_BUFFER_CAPTION
1106 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1108 return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1126 UNICODE_STRING Text
= {0};
1127 RtlInitUnicodeString(&Text
, str
);
1128 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1150 if (!(uFlags
& DC_TEXT
) || !str
)
1151 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1153 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1154 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1156 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1157 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1158 HeapFree(GetProcessHeap(), 0, strW
);
1163 /***********************************************************************
1166 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1167 * but without the borders (if any).
1168 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1170 static void FASTCALL
1171 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1176 GetWindowRect(Wnd
, Rect
);
1177 Rect
->right
= Rect
->right
- Rect
->left
;
1179 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1182 Style
= GetWindowLongW(Wnd
, GWL_STYLE
);
1183 if (0 != (Style
& WS_ICONIC
))
1188 /* Remove frame from rectangle */
1189 ExStyle
= GetWindowLongW(Wnd
, GWL_EXSTYLE
);
1190 if (HAS_THICKFRAME(Style
, ExStyle
))
1192 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1194 else if (HAS_DLGFRAME(Style
, ExStyle
))
1196 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1198 else if (HAS_THINFRAME(Style
, ExStyle
))
1200 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1203 /* We have additional border information if the window
1204 * is a child (but not an MDI child) */
1205 if (0 != (Style
& WS_CHILD
)
1206 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1208 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1210 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1212 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1214 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1219 /***********************************************************************
1223 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1229 GetWindowRect(Wnd
, Rect
);
1233 NcGetInsideRect(Wnd
, Rect
);
1234 GetWindowRect(Wnd
, &WindowRect
);
1235 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1236 if (0 != (GetWindowLongW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1238 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1240 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1241 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;