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?
268 #define DCX_USESTYLE 0x00010000
269 #define DCX_KEEPCLIPRGN 0x00040000 // <-- You do this!
272 * - Drawing of WS_BORDER after scrollbars
273 * - Correct drawing of size-box
276 DefWndNCPaint(HWND hWnd
, HRGN hRgn
, BOOL Active
)
279 DWORD Style
, ExStyle
;
281 RECT ClientRect
, WindowRect
, CurrentRect
, TempRect
;
283 if (!IsWindowVisible(hWnd
))
286 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
288 hDC
= NtUserGetDCEx(hWnd
, hRgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_KEEPCLIPRGN
);
294 Parent
= GetParent(hWnd
);
295 ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
298 if (ExStyle
& WS_EX_MDICHILD
)
300 Active
= IsChild(NtUserGetForegroundWindow(), hWnd
);
302 Active
= (hWnd
== (HWND
)SendMessageW(Parent
, WM_MDIGETACTIVE
, 0, 0));
306 Active
= (NtUserGetForegroundWindow() == hWnd
);
309 GetWindowRect(hWnd
, &WindowRect
);
310 GetClientRect(hWnd
, &ClientRect
);
312 CurrentRect
.top
= CurrentRect
.left
= 0;
313 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
314 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
316 /* Draw outer edge */
317 if (UserHasWindowEdge(Style
, ExStyle
))
319 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
321 if (ExStyle
& WS_EX_STATICEDGE
)
324 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
326 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNSHADOW
));
327 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
328 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
330 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNHIGHLIGHT
));
331 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
332 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
334 InflateRect(&CurrentRect
, -1, -1);
338 /* Firstly the "thick" frame */
339 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
342 (GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
)) *
343 GetSystemMetrics(SM_CXBORDER
);
345 (GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
)) *
346 GetSystemMetrics(SM_CYBORDER
);
348 SelectObject(hDC
, GetSysColorBrush(Active
? COLOR_ACTIVEBORDER
:
349 COLOR_INACTIVEBORDER
));
352 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
353 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
355 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
356 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
358 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
359 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
362 InflateRect(&CurrentRect
, -Width
, -Height
);
365 /* Now the other bit of the frame */
366 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
368 DWORD Width
= GetSystemMetrics(SM_CXBORDER
);
369 DWORD Height
= GetSystemMetrics(SM_CYBORDER
);
371 SelectObject(hDC
, GetSysColorBrush(
372 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
373 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
374 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
378 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, Height
, PATCOPY
);
379 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
381 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
382 PatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
384 PatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
, CurrentRect
.right
- CurrentRect
.left
, -Height
, PATCOPY
);
385 PatBlt(hDC
, CurrentRect
.right
, CurrentRect
.top
, -Width
, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
388 InflateRect(&CurrentRect
, -Width
, -Height
);
392 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
394 DWORD CaptionFlags
= DC_ICON
| DC_TEXT
| DC_BUTTONS
;
396 BOOL Gradient
= FALSE
;
398 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
400 CaptionFlags
|= DC_GRADIENT
;
403 TempRect
= CurrentRect
;
407 CaptionFlags
|= DC_ACTIVE
;
410 if (ExStyle
& WS_EX_TOOLWINDOW
)
412 CaptionFlags
|= DC_SMALLCAP
;
413 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
) - 1;
414 CurrentRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
418 TempRect
.bottom
= TempRect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
419 CurrentRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
422 NtUserDrawCaption(hWnd
, hDC
, &TempRect
, CaptionFlags
);
425 if (Style
& WS_SYSMENU
)
427 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
428 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
430 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
431 UserDrawCaptionButton(&TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
434 if(!(Style
& WS_MINIMIZE
))
436 /* Line under caption */
437 PreviousPen
= SelectObject(hDC
, GetSysColorPen(
438 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
|
439 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
440 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
441 MoveToEx(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
442 LineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
443 SelectObject(hDC
, PreviousPen
);
447 if(!(Style
& WS_MINIMIZE
))
449 HMENU menu
= GetMenu(hWnd
);
451 if (menu
&& !(Style
& WS_CHILD
))
453 TempRect
= CurrentRect
;
454 TempRect
.bottom
= TempRect
.top
+ (UINT
)NtUserSetMenuBarHeight(menu
, 0);
455 CurrentRect
.top
+= MenuDrawMenuBar(hDC
, &TempRect
, hWnd
, FALSE
);
458 if (ExStyle
& WS_EX_CLIENTEDGE
)
460 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
463 /* Draw the scrollbars */
464 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
465 IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
467 RECT ParentClientRect
;
469 TempRect
= CurrentRect
;
470 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
471 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
473 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
474 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
475 FillRect(hDC
, &TempRect
, GetSysColorBrush(COLOR_BTNFACE
));
476 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
478 GetClientRect(Parent
, &ParentClientRect
);
479 if (HASSIZEGRIP(Style
, ExStyle
, GetWindowLongW(Parent
, GWL_STYLE
), WindowRect
, ParentClientRect
))
481 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
483 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
484 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
488 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_VSCROLL
))
489 IntDrawScrollBar(hWnd
, hDC
, SB_VERT
);
490 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(hWnd
, OBJID_HSCROLL
))
491 IntDrawScrollBar(hWnd
, hDC
, SB_HORZ
);
495 ReleaseDC(hWnd
, hDC
);
501 DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
)
504 DWORD Style
= GetClassLongW(hWnd
, GCL_STYLE
);
507 RECT OrigRect
= *Rect
;
511 if (Style
& CS_VREDRAW
)
513 Result
|= WVR_VREDRAW
;
515 if (Style
& CS_HREDRAW
)
517 Result
|= WVR_HREDRAW
;
519 Result
|= WVR_VALIDRECTS
;
522 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
523 ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
525 if (!(Style
& WS_MINIMIZE
))
527 HMENU menu
= GetMenu(hWnd
);
529 if (UserHasWindowEdge(Style
, ExStyle
))
531 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
532 InflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
534 if ((ExStyle
& WS_EX_STATICEDGE
) || (Style
& WS_BORDER
))
536 InflateRect(Rect
, -1, -1);
539 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
541 if (ExStyle
& WS_EX_TOOLWINDOW
)
542 Rect
->top
+= GetSystemMetrics(SM_CYSMCAPTION
);
544 Rect
->top
+= GetSystemMetrics(SM_CYCAPTION
);
547 if (menu
&& !(Style
& WS_CHILD
))
549 HDC hDC
= NtUserGetWindowDC(hWnd
);
552 RECT CliRect
= *Rect
;
553 CliRect
.bottom
-= OrigRect
.top
;
554 CliRect
.right
-= OrigRect
.left
;
555 CliRect
.left
-= OrigRect
.left
;
556 CliRect
.top
-= OrigRect
.top
;
557 Rect
->top
+= MenuDrawMenuBar(hDC
, &CliRect
, hWnd
, TRUE
);
558 ReleaseDC(hWnd
, hDC
);
562 if (ExStyle
& WS_EX_CLIENTEDGE
)
564 InflateRect(Rect
, -2 * GetSystemMetrics(SM_CXBORDER
),
565 -2 * GetSystemMetrics(SM_CYBORDER
));
568 if(Style
& (WS_VSCROLL
| WS_HSCROLL
))
571 SETSCROLLBARINFO ssbi
;
573 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
574 if((Style
& WS_VSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &sbi
))
577 LONG sx
= Rect
->right
;
579 sx
-= GetSystemMetrics(SM_CXVSCROLL
);
580 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
581 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
583 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
585 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
586 NtUserSetScrollBarInfo(hWnd
, OBJID_VSCROLL
, &ssbi
);
587 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
588 Style
&= ~WS_VSCROLL
;
591 Style
&= ~WS_VSCROLL
;
593 if((Style
& WS_HSCROLL
) && NtUserGetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &sbi
))
596 LONG sy
= Rect
->bottom
;
598 sy
-= GetSystemMetrics(SM_CYHSCROLL
);
599 for(i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
600 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
602 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
604 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
605 NtUserSetScrollBarInfo(hWnd
, OBJID_HSCROLL
, &ssbi
);
606 if(ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
607 Style
&= ~WS_HSCROLL
;
610 Style
&= ~WS_HSCROLL
;
613 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
615 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
616 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
618 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
619 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
623 if (Style
& WS_VSCROLL
)
625 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
626 Rect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
628 Rect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
630 else if (Style
& WS_HSCROLL
)
631 Rect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
633 if (Rect
->top
> Rect
->bottom
)
634 Rect
->bottom
= Rect
->top
;
635 if (Rect
->left
> Rect
->right
)
636 Rect
->right
= Rect
->left
;
640 Rect
->right
= Rect
->left
;
641 Rect
->bottom
= Rect
->top
;
648 DefWndNCActivate(HWND hWnd
, WPARAM wParam
)
650 DefWndNCPaint(hWnd
, (HRGN
)1, wParam
);
656 * - Check the scrollbar handling
659 DefWndNCHitTest(HWND hWnd
, POINT Point
)
661 RECT WindowRect
, ClientRect
, OrigWndRect
;
664 ULONG Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
665 ULONG ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
667 GetWindowRect(hWnd
, &WindowRect
);
668 if (!PtInRect(&WindowRect
, Point
))
672 OrigWndRect
= WindowRect
;
674 if (UserHasWindowEdge(Style
, ExStyle
))
678 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
679 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
680 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
681 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
682 if (!PtInRect(&WindowRect
, Point
))
686 ThickFrame
= (Style
& WS_THICKFRAME
);
687 if (Point
.y
< WindowRect
.top
)
689 if(Style
& WS_MINIMIZE
)
693 if (Point
.x
< (WindowRect
.left
+ XSize
))
695 if (Point
.x
>= (WindowRect
.right
- XSize
))
699 if (Point
.y
>= WindowRect
.bottom
)
701 if(Style
& WS_MINIMIZE
)
705 if (Point
.x
< (WindowRect
.left
+ XSize
))
707 if (Point
.x
>= (WindowRect
.right
- XSize
))
708 return HTBOTTOMRIGHT
;
711 if (Point
.x
< WindowRect
.left
)
713 if(Style
& WS_MINIMIZE
)
717 if (Point
.y
< (WindowRect
.top
+ YSize
))
719 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
723 if (Point
.x
>= WindowRect
.right
)
725 if(Style
& WS_MINIMIZE
)
729 if (Point
.y
< (WindowRect
.top
+ YSize
))
731 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
732 return HTBOTTOMRIGHT
;
739 if (ExStyle
& WS_EX_STATICEDGE
)
740 InflateRect(&WindowRect
,
741 -GetSystemMetrics(SM_CXBORDER
),
742 -GetSystemMetrics(SM_CYBORDER
));
743 if (!PtInRect(&WindowRect
, Point
))
747 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
749 if (ExStyle
& WS_EX_TOOLWINDOW
)
750 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
752 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
753 if (!PtInRect(&WindowRect
, Point
))
755 if (Style
& WS_SYSMENU
)
757 if (ExStyle
& WS_EX_TOOLWINDOW
)
759 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
763 if(!(ExStyle
& WS_EX_DLGMODALFRAME
))
764 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
765 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
768 if (Point
.x
< WindowRect
.left
)
770 if (WindowRect
.right
<= Point
.x
)
772 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
773 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
774 if (Point
.x
>= WindowRect
.right
)
776 if (Style
& WS_MINIMIZEBOX
)
777 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
778 if (Point
.x
>= WindowRect
.right
)
784 if(!(Style
& WS_MINIMIZE
))
789 ScreenToClient(hWnd
, &ClientPoint
);
790 GetClientRect(hWnd
, &ClientRect
);
792 if (PtInRect(&ClientRect
, ClientPoint
))
797 if ((menu
= GetMenu(hWnd
)) && !(Style
& WS_CHILD
))
799 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
803 if (ExStyle
& WS_EX_CLIENTEDGE
)
805 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
806 -2 * GetSystemMetrics(SM_CYBORDER
));
809 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
810 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
812 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
813 HWND Parent
= GetParent(hWnd
);
815 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
816 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
817 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
819 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
820 if (PtInRect(&TempRect
, Point
))
823 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
824 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
825 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
827 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
828 if (PtInRect(&TempRect2
, Point
))
831 TempRect
.top
= TempRect2
.top
;
832 TempRect
.bottom
= TempRect2
.bottom
;
834 GetClientRect(Parent
, &ParentRect
);
835 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
836 GetWindowLongW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
838 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
841 return HTBOTTOMRIGHT
;
846 if (Style
& WS_VSCROLL
)
848 RECT TempRect
= WindowRect
;
850 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
851 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
853 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
854 if (PtInRect(&TempRect
, Point
))
857 if (Style
& WS_HSCROLL
)
859 RECT TempRect
= WindowRect
;
860 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
861 if (PtInRect(&TempRect
, Point
))
871 DefWndDoButton(HWND hWnd
, WPARAM wParam
)
875 BOOL Pressed
= TRUE
, OldState
;
877 ULONG ButtonType
, Style
;
879 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
883 if (!(Style
& WS_SYSMENU
))
885 ButtonType
= DFCS_CAPTIONCLOSE
;
889 if (!(Style
& WS_MINIMIZEBOX
))
891 ButtonType
= DFCS_CAPTIONMIN
;
892 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
895 if (!(Style
& WS_MAXIMIZEBOX
))
897 ButtonType
= DFCS_CAPTIONMAX
;
898 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
907 * FIXME: Not sure where to do this, but we must flush the pending
908 * window updates when someone clicks on the close button and at
909 * the same time the window is overlapped with another one. This
910 * looks like a good place for now...
914 WindowDC
= NtUserGetWindowDC(hWnd
);
915 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, TRUE
, ButtonType
);
917 NtUserSetCapture(hWnd
);
921 if (GetMessageW(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
) <= 0)
924 if (Msg
.message
== WM_LBUTTONUP
)
927 if (Msg
.message
!= WM_MOUSEMOVE
)
931 Pressed
= (DefWndNCHitTest(hWnd
, Msg
.pt
) == wParam
);
932 if (Pressed
!= OldState
)
933 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, Pressed
, ButtonType
);
937 UserDrawCaptionButtonWnd(hWnd
, WindowDC
, FALSE
, ButtonType
);
939 ReleaseDC(hWnd
, WindowDC
);
941 SendMessageW(hWnd
, WM_SYSCOMMAND
, SCMsg
, 0);
946 DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
952 HWND hTopWnd
= GetAncestor(hWnd
, GA_ROOT
);
953 if (NtUserSetActiveWindow(hTopWnd
) || GetActiveWindow() == hTopWnd
)
955 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
961 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_SYSMENU
)
963 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
,
970 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
975 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
980 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
987 DefWndDoButton(hWnd
, wParam
);
999 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1008 DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1012 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
1017 /* Maximize/Restore the window */
1018 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1020 SendMessageW(hWnd
, WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1026 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1030 return DefWndNCLButtonDown(hWnd
, wParam
, lParam
);
1036 DefWndTrackScrollBar(HWND hWnd
, WPARAM wParam
, POINT Point
)
1040 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1042 if ((wParam
& 0x0f) != HTHSCROLL
)
1044 ScrollBar
= SB_HORZ
;
1048 if ((wParam
& 0x0f) != HTVSCROLL
)
1050 ScrollBar
= SB_VERT
;
1056 /* PUBLIC FUNCTIONS ***********************************************************/
1062 AdjustWindowRectEx(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
);
1094 AdjustWindowRect(LPRECT lpRect
,
1098 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, 0);
1101 // Enabling this will cause captions to draw smoother, but slower:
1102 #define DOUBLE_BUFFER_CAPTION
1108 DrawCaption(HWND hWnd
, HDC hDC
, LPCRECT lprc
, UINT uFlags
)
1110 return NtUserDrawCaption(hWnd
, hDC
, lprc
, uFlags
);
1128 UNICODE_STRING Text
= {0};
1129 RtlInitUnicodeString(&Text
, str
);
1130 return NtUserDrawCaptionTemp(hWnd
, hDC
, rect
, hFont
, hIcon
, &Text
, uFlags
);
1152 if (!(uFlags
& DC_TEXT
) || !str
)
1153 return DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
1155 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
1156 if ((strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
1158 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
1159 ret
= DrawCaptionTempW(hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
1160 HeapFree(GetProcessHeap(), 0, strW
);
1165 /***********************************************************************
1168 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1169 * but without the borders (if any).
1170 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1172 static void FASTCALL
1173 NcGetInsideRect(HWND Wnd
, RECT
*Rect
)
1178 GetWindowRect(Wnd
, Rect
);
1179 Rect
->right
= Rect
->right
- Rect
->left
;
1181 Rect
->bottom
= Rect
->bottom
- Rect
->top
;
1184 Style
= GetWindowLongW(Wnd
, GWL_STYLE
);
1185 if (0 != (Style
& WS_ICONIC
))
1190 /* Remove frame from rectangle */
1191 ExStyle
= GetWindowLongW(Wnd
, GWL_EXSTYLE
);
1192 if (HAS_THICKFRAME(Style
, ExStyle
))
1194 InflateRect(Rect
, - GetSystemMetrics(SM_CXFRAME
), - GetSystemMetrics(SM_CYFRAME
));
1196 else if (HAS_DLGFRAME(Style
, ExStyle
))
1198 InflateRect(Rect
, - GetSystemMetrics(SM_CXDLGFRAME
), - GetSystemMetrics(SM_CYDLGFRAME
));
1200 else if (HAS_THINFRAME(Style
, ExStyle
))
1202 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1205 /* We have additional border information if the window
1206 * is a child (but not an MDI child) */
1207 if (0 != (Style
& WS_CHILD
)
1208 && 0 == (ExStyle
& WS_EX_MDICHILD
))
1210 if (0 != (ExStyle
& WS_EX_CLIENTEDGE
))
1212 InflateRect(Rect
, - GetSystemMetrics(SM_CXEDGE
), - GetSystemMetrics(SM_CYEDGE
));
1214 if (0 != (ExStyle
& WS_EX_STATICEDGE
))
1216 InflateRect(Rect
, - GetSystemMetrics(SM_CXBORDER
), - GetSystemMetrics(SM_CYBORDER
));
1221 /***********************************************************************
1225 NcGetSysPopupPos(HWND Wnd
, RECT
*Rect
)
1231 GetWindowRect(Wnd
, Rect
);
1235 NcGetInsideRect(Wnd
, Rect
);
1236 GetWindowRect(Wnd
, &WindowRect
);
1237 OffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
1238 if (0 != (GetWindowLongW(Wnd
, GWL_STYLE
) & WS_CHILD
))
1240 ClientToScreen(GetParent(Wnd
), (POINT
*) Rect
);
1242 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1243 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;