2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "user_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient
);
36 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
38 /* Some useful macros */
39 #define HAS_DLGFRAME(style,exStyle) \
40 (((exStyle) & WS_EX_DLGMODALFRAME) || \
41 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
43 #define HAS_THICKFRAME(style,exStyle) \
44 (((style) & WS_THICKFRAME) && \
45 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47 #define HAS_THINFRAME(style) \
48 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
50 #define HAS_BIGFRAME(style,exStyle) \
51 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
52 ((exStyle) & WS_EX_DLGMODALFRAME))
54 #define HAS_STATICOUTERFRAME(style,exStyle) \
55 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
58 #define HAS_ANYFRAME(style,exStyle) \
59 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
60 ((exStyle) & WS_EX_DLGMODALFRAME) || \
61 !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_MENU(hwnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
66 /******************************************************************************
69 * Computes the size of the "outside" parts of the window based on the
70 * parameters of the client area.
79 * "Outer" parts of a window means the whole window frame, caption and
80 * menu bar. It does not include "inner" parts of the frame like client
81 * edge, static edge or scroll bars.
83 *****************************************************************************/
86 NC_AdjustRectOuter (LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
90 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) ==
93 adjust
= 1; /* for the outer frame always present */
98 if ((exStyle
& WS_EX_DLGMODALFRAME
) ||
99 (style
& (WS_THICKFRAME
|WS_DLGFRAME
))) adjust
= 2; /* outer */
101 if (style
& WS_THICKFRAME
)
102 adjust
+= ( GetSystemMetrics (SM_CXFRAME
)
103 - GetSystemMetrics (SM_CXDLGFRAME
)); /* The resize border */
104 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
105 (exStyle
& WS_EX_DLGMODALFRAME
))
106 adjust
++; /* The other border */
108 InflateRect (rect
, adjust
, adjust
);
110 if ((style
& WS_CAPTION
) == WS_CAPTION
)
112 if (exStyle
& WS_EX_TOOLWINDOW
)
113 rect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
115 rect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
117 if (menu
) rect
->top
-= GetSystemMetrics(SM_CYMENU
);
121 /******************************************************************************
124 * Computes the size of the "inside" part of the window based on the
125 * parameters of the client area.
133 * "Inner" part of a window means the window frame inside of the flat
134 * window frame. It includes the client edge, the static edge and the
137 *****************************************************************************/
140 NC_AdjustRectInner (LPRECT rect
, DWORD style
, DWORD exStyle
)
142 if (exStyle
& WS_EX_CLIENTEDGE
)
143 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
145 if (style
& WS_VSCROLL
)
147 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
148 rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
150 rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
152 if (style
& WS_HSCROLL
) rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
157 static HICON
NC_IconForWindow( HWND hwnd
)
160 WND
*wndPtr
= WIN_GetPtr( hwnd
);
162 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
&& wndPtr
!= WND_DESKTOP
)
164 hIcon
= wndPtr
->hIconSmall
;
165 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
166 WIN_ReleasePtr( wndPtr
);
168 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
169 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICON
);
171 /* If there is no icon specified and this is not a modal dialog,
172 * get the default one.
174 if (!hIcon
&& !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_DLGMODALFRAME
))
175 hIcon
= LoadImageW(0, (LPCWSTR
)IDI_WINLOGO
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
),
176 GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTCOLOR
| LR_SHARED
);
180 /* Draws the bar part(ie the big rectangle) of the caption */
181 static void NC_DrawCaptionBar (HDC hdc
, const RECT
*rect
, DWORD dwStyle
,
182 BOOL active
, BOOL gradient
)
186 TRIVERTEX vertices
[4];
188 GetSysColor (active
? COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
);
190 GetSysColor (active
? COLOR_GRADIENTACTIVECAPTION
191 : COLOR_GRADIENTINACTIVECAPTION
);
192 int buttonsAreaSize
= GetSystemMetrics(SM_CYCAPTION
) - 1;
193 static GRADIENT_RECT mesh
[] = {{0, 1}, {1, 2}, {2, 3}};
195 vertices
[0].Red
= vertices
[1].Red
= GetRValue (colLeft
) << 8;
196 vertices
[0].Green
= vertices
[1].Green
= GetGValue (colLeft
) << 8;
197 vertices
[0].Blue
= vertices
[1].Blue
= GetBValue (colLeft
) << 8;
198 vertices
[0].Alpha
= vertices
[1].Alpha
= 0xff00;
199 vertices
[2].Red
= vertices
[3].Red
= GetRValue (colRight
) << 8;
200 vertices
[2].Green
= vertices
[3].Green
= GetGValue (colRight
) << 8;
201 vertices
[2].Blue
= vertices
[3].Blue
= GetBValue (colRight
) << 8;
202 vertices
[2].Alpha
= vertices
[3].Alpha
= 0xff00;
204 if ((dwStyle
& WS_SYSMENU
)
205 && ((dwStyle
& WS_MAXIMIZEBOX
) || (dwStyle
& WS_MINIMIZEBOX
)))
206 buttonsAreaSize
+= 2 * (GetSystemMetrics(SM_CXSIZE
) + 1);
208 /* area behind icon; solid filled with left color */
209 vertices
[0].x
= rect
->left
;
210 vertices
[0].y
= rect
->top
;
211 if (dwStyle
& WS_SYSMENU
)
212 vertices
[1].x
= min (rect
->left
+ GetSystemMetrics(SM_CXSMICON
), rect
->right
);
214 vertices
[1].x
= vertices
[0].x
;
215 vertices
[1].y
= rect
->bottom
;
217 /* area behind text; gradient */
218 vertices
[2].x
= max (vertices
[1].x
, rect
->right
- buttonsAreaSize
);
219 vertices
[2].y
= rect
->top
;
221 /* area behind buttons; solid filled with right color */
222 vertices
[3].x
= rect
->right
;
223 vertices
[3].y
= rect
->bottom
;
225 GdiGradientFill (hdc
, vertices
, 4, mesh
, 3, GRADIENT_FILL_RECT_H
);
228 FillRect (hdc
, rect
, GetSysColorBrush (active
?
229 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
232 /***********************************************************************
233 * DrawCaption (USER32.@) Draws a caption bar
247 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
249 return DrawCaptionTempW (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x103F);
253 /***********************************************************************
254 * DrawCaptionTempA (USER32.@)
256 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
257 HICON hIcon
, LPCSTR str
, UINT uFlags
)
263 if (!(uFlags
& DC_TEXT
) || !str
)
264 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
266 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
267 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
269 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
270 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
271 HeapFree( GetProcessHeap (), 0, strW
);
277 /***********************************************************************
278 * DrawCaptionTempW (USER32.@)
280 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
281 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
285 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
286 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
288 /* drawing background */
289 if (uFlags
& DC_INBUTTON
) {
290 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
292 if (uFlags
& DC_ACTIVE
) {
293 HBRUSH hbr
= SelectObject (hdc
, SYSCOLOR_Get55AABrush());
294 PatBlt (hdc
, rc
.left
, rc
.top
,
295 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
296 SelectObject (hdc
, hbr
);
300 DWORD style
= GetWindowLongW (hwnd
, GWL_STYLE
);
301 NC_DrawCaptionBar (hdc
, &rc
, style
, uFlags
& DC_ACTIVE
, uFlags
& DC_GRADIENT
);
306 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
310 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
312 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
313 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
314 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
315 rc
.left
= pt
.x
+ GetSystemMetrics( SM_CXSMICON
);
319 if (uFlags
& DC_TEXT
) {
323 if (uFlags
& DC_INBUTTON
)
324 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
325 else if (uFlags
& DC_ACTIVE
)
326 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
328 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
330 SetBkMode (hdc
, TRANSPARENT
);
333 hOldFont
= SelectObject (hdc
, hFont
);
335 NONCLIENTMETRICSW nclm
;
337 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
338 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
339 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
340 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
341 hOldFont
= SelectObject (hdc
, hNewFont
);
346 if (!GetWindowTextW( hwnd
, text
, sizeof(text
)/sizeof(WCHAR
) )) text
[0] = 0;
350 DrawTextW( hdc
, str
, -1, &rc
, ((uFlags
& 0x4000) ? DT_CENTER
: DT_LEFT
) |
351 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_END_ELLIPSIS
);
354 SelectObject (hdc
, hOldFont
);
356 DeleteObject (SelectObject (hdc
, hOldFont
));
359 /* drawing focus ??? */
361 FIXME("undocumented flag (0x2000)!\n");
367 /***********************************************************************
368 * AdjustWindowRect (USER32.@)
370 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
372 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
376 /***********************************************************************
377 * AdjustWindowRectEx (USER32.@)
379 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
381 if (style
& WS_ICONIC
) return TRUE
;
382 style
&= ~(WS_HSCROLL
| WS_VSCROLL
);
384 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
);
386 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
387 NC_AdjustRectInner( rect
, style
, exStyle
);
393 /***********************************************************************
394 * NC_HandleNCCalcSize
396 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
398 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, WPARAM wparam
, RECT
*winRect
)
400 RECT tmpRect
= { 0, 0, 0, 0 };
402 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
403 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
404 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
409 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
410 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
412 if (!(style
& WS_ICONIC
))
414 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
416 winRect
->left
-= tmpRect
.left
;
417 winRect
->top
-= tmpRect
.top
;
418 winRect
->right
-= tmpRect
.right
;
419 winRect
->bottom
-= tmpRect
.bottom
;
421 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
423 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
424 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
427 MENU_GetMenuBarHeight( hwnd
,
428 winRect
->right
- winRect
->left
,
429 -tmpRect
.left
, -tmpRect
.top
);
432 if( exStyle
& WS_EX_CLIENTEDGE
)
433 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
434 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
435 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
436 - GetSystemMetrics(SM_CYEDGE
));
438 if (style
& WS_VSCROLL
)
439 if (winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
))
441 /* rectangle is in screen coords when wparam is false */
442 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
444 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
445 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
447 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
450 if (style
& WS_HSCROLL
)
451 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
452 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
454 if (winRect
->top
> winRect
->bottom
)
455 winRect
->bottom
= winRect
->top
;
457 if (winRect
->left
> winRect
->right
)
458 winRect
->right
= winRect
->left
;
464 /***********************************************************************
467 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
468 * but without the borders (if any).
470 static void NC_GetInsideRect( HWND hwnd
, enum coords_relative relative
, RECT
*rect
,
471 DWORD style
, DWORD ex_style
)
473 WIN_GetRectangles( hwnd
, relative
, rect
, NULL
);
475 if (style
& WS_ICONIC
) return;
477 /* Remove frame from rectangle */
478 if (HAS_THICKFRAME( style
, ex_style
))
480 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
482 else if (HAS_DLGFRAME( style
, ex_style
))
484 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
486 else if (HAS_THINFRAME( style
))
488 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
491 /* We have additional border information if the window
492 * is a child (but not an MDI child) */
493 if ((style
& WS_CHILD
) && !(ex_style
& WS_EX_MDICHILD
))
495 if (ex_style
& WS_EX_CLIENTEDGE
)
496 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
497 if (ex_style
& WS_EX_STATICEDGE
)
498 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
503 /***********************************************************************
506 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
508 LRESULT
NC_HandleNCHitTest( HWND hwnd
, POINT pt
)
511 DWORD style
, ex_style
;
513 TRACE("hwnd=%p pt=%d,%d\n", hwnd
, pt
.x
, pt
.y
);
515 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &rect
, &rcClient
);
516 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
518 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
519 ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
520 if (style
& WS_MINIMIZE
) return HTCAPTION
;
522 if (PtInRect( &rcClient
, pt
)) return HTCLIENT
;
525 if (HAS_THICKFRAME( style
, ex_style
))
527 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
528 if (!PtInRect( &rect
, pt
))
530 /* Check top sizing border */
533 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
534 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
537 /* Check bottom sizing border */
538 if (pt
.y
>= rect
.bottom
)
540 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
541 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
544 /* Check left sizing border */
545 if (pt
.x
< rect
.left
)
547 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
548 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
551 /* Check right sizing border */
552 if (pt
.x
>= rect
.right
)
554 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
555 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
560 else /* No thick frame */
562 if (HAS_DLGFRAME( style
, ex_style
))
563 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
564 else if (HAS_THINFRAME( style
))
565 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
566 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
571 if ((style
& WS_CAPTION
) == WS_CAPTION
)
573 if (ex_style
& WS_EX_TOOLWINDOW
)
574 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
576 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
577 if (!PtInRect( &rect
, pt
))
579 BOOL min_or_max_box
= (style
& WS_SYSMENU
) && (style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
580 if (ex_style
& WS_EX_LAYOUTRTL
)
582 /* Check system menu */
583 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
585 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
586 if (pt
.x
> rect
.right
) return HTSYSMENU
;
589 /* Check close button */
590 if (style
& WS_SYSMENU
)
592 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
593 if (pt
.x
< rect
.left
) return HTCLOSE
;
596 /* Check maximize box */
597 /* In win95 there is automatically a Maximize button when there is a minimize one*/
598 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
600 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
601 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
604 /* Check minimize box */
605 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
607 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
608 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
613 /* Check system menu */
614 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
616 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
617 if (pt
.x
< rect
.left
) return HTSYSMENU
;
620 /* Check close button */
621 if (style
& WS_SYSMENU
)
623 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
624 if (pt
.x
> rect
.right
) return HTCLOSE
;
627 /* Check maximize box */
628 /* In win95 there is automatically a Maximize button when there is a minimize one*/
629 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
631 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
632 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
635 /* Check minimize box */
636 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
638 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
639 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
648 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
649 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
652 /* Check vertical scroll bar */
654 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
655 if (style
& WS_VSCROLL
)
657 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
658 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
660 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
661 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
664 /* Check horizontal scroll bar */
666 if (style
& WS_HSCROLL
)
668 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
669 if (PtInRect( &rcClient
, pt
))
672 if ((style
& WS_VSCROLL
) &&
673 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
674 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
680 /* Has to return HTNOWHERE if nothing was found
681 Could happen when a window has a customized non client area */
686 /******************************************************************************
690 * Draws the system icon.
692 *****************************************************************************/
693 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
695 HICON hIcon
= NC_IconForWindow( hwnd
);
701 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
702 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
704 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
705 pt
.x
= rect
.left
+ 2;
706 pt
.y
= (rect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - GetSystemMetrics(SM_CYSMICON
)) / 2;
707 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
,
708 GetSystemMetrics(SM_CXSMICON
),
709 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
715 /******************************************************************************
719 * Draws the close button.
721 * If bGrayed is true, then draw a disabled Close button
723 *****************************************************************************/
725 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
728 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
729 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
731 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
733 /* A tool window has a smaller Close button */
734 if (ex_style
& WS_EX_TOOLWINDOW
)
736 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
737 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
738 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
740 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
741 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
742 rect
.bottom
= rect
.top
+ iBmpHeight
;
743 rect
.right
= rect
.left
+ iBmpWidth
;
747 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
748 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
752 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
754 (down
? DFCS_PUSHED
: 0) |
755 (bGrayed
? DFCS_INACTIVE
: 0)) );
758 /******************************************************************************
761 * Draws the maximize button for windows.
762 * If bGrayed is true, then draw a disabled Maximize button
764 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
768 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
769 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
771 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
772 if (ex_style
& WS_EX_TOOLWINDOW
) return;
774 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
776 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
777 if (style
& WS_SYSMENU
)
778 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
779 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
780 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
783 if (down
) flags
|= DFCS_PUSHED
;
784 if (bGrayed
) flags
|= DFCS_INACTIVE
;
785 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
788 /******************************************************************************
791 * Draws the minimize button for windows.
792 * If bGrayed is true, then draw a disabled Minimize button
794 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
797 UINT flags
= DFCS_CAPTIONMIN
;
798 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
799 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
801 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
802 if (ex_style
& WS_EX_TOOLWINDOW
) return;
804 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
805 if (style
& WS_SYSMENU
)
806 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
807 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
808 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
809 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
810 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
813 if (down
) flags
|= DFCS_PUSHED
;
814 if (bGrayed
) flags
|= DFCS_INACTIVE
;
815 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
818 /******************************************************************************
822 * Draw a window frame inside the given rectangle, and update the rectangle.
825 * Many. First, just what IS a frame in Win95? Note that the 3D look
826 * on the outer edge is handled by NC_DoNCPaint. As is the inner
827 * edge. The inner rectangle just inside the frame is handled by the
830 * In short, for most people, this function should be a nop (unless
831 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
832 * them lately, but just to get this code right). Even so, it doesn't
833 * appear to be so. It's being worked on...
835 *****************************************************************************/
837 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
841 /* Firstly the "thick" frame */
842 if (style
& WS_THICKFRAME
)
844 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
845 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
847 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
848 COLOR_INACTIVEBORDER
) );
850 PatBlt( hdc
, rect
->left
, rect
->top
,
851 rect
->right
- rect
->left
, height
, PATCOPY
);
852 PatBlt( hdc
, rect
->left
, rect
->top
,
853 width
, rect
->bottom
- rect
->top
, PATCOPY
);
854 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
855 rect
->right
- rect
->left
, -height
, PATCOPY
);
856 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
857 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
859 InflateRect( rect
, -width
, -height
);
862 /* Now the other bit of the frame */
863 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
864 (exStyle
& WS_EX_DLGMODALFRAME
))
866 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
867 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
868 /* This should give a value of 1 that should also work for a border */
870 SelectObject( hdc
, GetSysColorBrush(
871 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
873 (exStyle
& WS_EX_STATICEDGE
) ?
875 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
881 PatBlt( hdc
, rect
->left
, rect
->top
,
882 rect
->right
- rect
->left
, height
, PATCOPY
);
883 PatBlt( hdc
, rect
->left
, rect
->top
,
884 width
, rect
->bottom
- rect
->top
, PATCOPY
);
885 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
886 rect
->right
- rect
->left
, -height
, PATCOPY
);
887 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
888 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
890 InflateRect( rect
, -width
, -height
);
895 /******************************************************************************
899 * Draw the window caption for windows.
900 * The correct pen for the window frame must be selected in the DC.
902 *****************************************************************************/
904 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
905 DWORD exStyle
, BOOL active
)
911 BOOL gradient
= FALSE
;
913 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
914 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
915 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
916 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
917 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
918 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
919 SelectObject( hdc
, hPrevPen
);
922 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
923 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
925 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
926 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
927 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
930 if (style
& WS_SYSMENU
)
934 /* Go get the sysmenu */
935 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
936 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
938 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
939 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
940 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
941 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
943 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
945 /* In win95 the two buttons are always there */
946 /* But if the menu item is not in the menu they're disabled*/
948 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
949 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
951 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
952 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
956 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
958 NONCLIENTMETRICSW nclm
;
959 HFONT hFont
, hOldFont
;
960 nclm
.cbSize
= sizeof(nclm
);
961 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
962 if (exStyle
& WS_EX_TOOLWINDOW
)
963 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
965 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
966 hOldFont
= SelectObject (hdc
, hFont
);
967 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
968 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
969 SetBkMode( hdc
, TRANSPARENT
);
971 DrawTextW( hdc
, buffer
, -1, &r
,
972 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
973 DeleteObject (SelectObject (hdc
, hOldFont
));
978 /******************************************************************************
981 * Paint the non-client area for windows.
983 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
)
986 RECT rfuzz
, rect
, rectClip
;
989 DWORD dwStyle
, dwExStyle
;
994 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
995 dwStyle
= wndPtr
->dwStyle
;
996 dwExStyle
= wndPtr
->dwExStyle
;
997 flags
= wndPtr
->flags
;
998 WIN_ReleasePtr( wndPtr
);
1000 if ( dwStyle
& WS_MINIMIZE
||
1001 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1003 active
= flags
& WIN_NCACTIVATED
;
1005 TRACE("%p %d\n", hwnd
, active
);
1007 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1008 the call to GetDCEx implying that it is allowed not to use it either.
1009 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1010 will cause clipRgn to be deleted after ReleaseDC().
1011 Now, how is the "system" supposed to tell what happened?
1014 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1015 hrgn
= CreateRectRgnIndirect( &rectClient
);
1019 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1020 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1024 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1029 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1030 GetClipBox( hdc
, &rectClip
);
1032 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1034 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1035 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1037 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1038 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1041 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1043 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1046 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1047 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1048 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1051 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1052 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1054 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1055 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1058 if (HAS_MENU( hwnd
, dwStyle
))
1061 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1063 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1065 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
) + 1;
1068 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1070 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1071 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1073 /* Draw the scroll-bars */
1075 if (dwStyle
& WS_VSCROLL
)
1076 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1077 if (dwStyle
& WS_HSCROLL
)
1078 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1080 /* Draw the "size-box" */
1081 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1084 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1085 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1087 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1088 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1089 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1092 ReleaseDC( hwnd
, hdc
);
1098 /***********************************************************************
1101 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1103 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1105 HWND parent
= GetAncestor( hwnd
, GA_PARENT
);
1106 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1108 if( dwStyle
& WS_VISIBLE
)
1110 if( dwStyle
& WS_MINIMIZE
)
1111 WINPOS_RedrawIconTitle( hwnd
);
1113 NC_DoNCPaint( hwnd
, clip
);
1115 if (parent
== GetDesktopWindow())
1116 PostMessageW( parent
, WM_PARENTNOTIFY
, WM_NCPAINT
, (LPARAM
)hwnd
);
1122 /***********************************************************************
1123 * NC_HandleNCActivate
1125 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1127 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1129 /* Lotus Notes draws menu descriptions in the caption of its main
1130 * window. When it wants to restore original "system" view, it just
1131 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1132 * attempt to minimize redrawings lead to a not restored caption.
1134 if (wParam
) win_set_flags( hwnd
, WIN_NCACTIVATED
, 0 );
1135 else win_set_flags( hwnd
, 0, WIN_NCACTIVATED
);
1137 /* This isn't documented but is reproducible in at least XP SP2 and
1138 * Outlook 2007 depends on it
1143 WINPOS_RedrawIconTitle( hwnd
);
1145 NC_DoNCPaint( hwnd
, (HRGN
)1 );
1147 if (GetAncestor( hwnd
, GA_PARENT
) == GetDesktopWindow())
1148 PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY
, WM_NCACTIVATE
, (LPARAM
)hwnd
);
1155 /***********************************************************************
1156 * NC_HandleSetCursor
1158 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1160 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1162 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1164 switch((short)LOWORD(lParam
))
1168 WORD msg
= HIWORD( lParam
);
1169 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1170 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1177 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1187 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1191 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1195 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1199 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1202 /* Default cursor: arrow */
1203 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1206 /***********************************************************************
1209 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1211 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1214 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1215 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1217 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1218 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1219 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1220 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1224 /***********************************************************************
1227 * Track a mouse button press on the minimize or maximize box.
1229 * The big difference between 3.1 and 95 is the disabled button state.
1230 * In win95 the system button can be disabled, so it can ignore the mouse
1234 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1237 HDC hdc
= GetWindowDC( hwnd
);
1238 BOOL pressed
= TRUE
;
1240 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1241 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1243 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1245 if (wParam
== HTMINBUTTON
)
1247 /* If the style is not present, do nothing */
1248 if (!(wndStyle
& WS_MINIMIZEBOX
))
1251 /* Check if the sysmenu item for minimize is there */
1252 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1254 paintButton
= NC_DrawMinButton
;
1258 /* If the style is not present, do nothing */
1259 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1262 /* Check if the sysmenu item for maximize is there */
1263 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1265 paintButton
= NC_DrawMaxButton
;
1270 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1274 BOOL oldstate
= pressed
;
1276 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1277 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1279 if(msg
.message
== WM_LBUTTONUP
)
1282 if(msg
.message
!= WM_MOUSEMOVE
)
1285 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1286 if (pressed
!= oldstate
)
1287 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1291 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1294 ReleaseDC( hwnd
, hdc
);
1296 /* If the minimize or maximize items of the sysmenu are not there */
1297 /* or if the style is not present, do nothing */
1298 if ((!pressed
) || (state
== 0xFFFFFFFF))
1301 if (wParam
== HTMINBUTTON
)
1302 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1304 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1305 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1308 /***********************************************************************
1309 * NC_TrackCloseButton
1311 * Track a mouse button press on the Win95 close button.
1313 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1317 BOOL pressed
= TRUE
;
1318 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1324 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1326 /* If the close item of the sysmenu is disabled or not present do nothing */
1327 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1330 hdc
= GetWindowDC( hwnd
);
1334 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1338 BOOL oldstate
= pressed
;
1340 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1341 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1343 if(msg
.message
== WM_LBUTTONUP
)
1346 if(msg
.message
!= WM_MOUSEMOVE
)
1349 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1350 if (pressed
!= oldstate
)
1351 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1355 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1358 ReleaseDC( hwnd
, hdc
);
1359 if (!pressed
) return;
1361 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1365 /***********************************************************************
1368 * Track a mouse button press on the horizontal or vertical scroll-bar.
1370 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1374 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1376 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1377 scrollbar
= SB_HORZ
;
1379 else /* SC_VSCROLL */
1381 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1382 scrollbar
= SB_VERT
;
1384 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1388 /***********************************************************************
1389 * NC_HandleNCLButtonDown
1391 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1393 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1395 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1397 switch(wParam
) /* Hit test */
1401 HWND top
= hwnd
, parent
;
1404 if ((GetWindowLongW( top
, GWL_STYLE
) & (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1406 parent
= GetAncestor( top
, GA_PARENT
);
1407 if (!parent
|| parent
== GetDesktopWindow()) break;
1411 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1412 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1417 if( style
& WS_SYSMENU
)
1419 if( !(style
& WS_MINIMIZE
) )
1421 HDC hDC
= GetWindowDC(hwnd
);
1422 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1423 ReleaseDC( hwnd
, hDC
);
1425 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1430 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1434 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1438 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1443 NC_TrackMinMaxBox( hwnd
, wParam
);
1447 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1459 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1460 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1462 /* But that is not what WinNT does. Instead it sends this. This
1463 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1464 * SC_MOUSEMENU into wParam.
1466 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1476 /***********************************************************************
1477 * NC_HandleNCRButtonDown
1479 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1481 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1484 INT hittest
= wParam
;
1493 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1494 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1495 if (msg
.message
== WM_RBUTTONUP
)
1497 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1502 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1503 SendMessageW( hwnd
, WM_CONTEXTMENU
, (WPARAM
)hwnd
, MAKELPARAM(msg
.pt
.x
, msg
.pt
.y
));
1510 /***********************************************************************
1511 * NC_HandleNCLButtonDblClk
1513 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1515 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1518 * if this is an icon, send a restore since we are handling
1523 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1527 switch(wParam
) /* Hit test */
1530 /* stop processing if WS_MAXIMIZEBOX is missing */
1531 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1532 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1533 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1538 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1539 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1541 /* If the close item of the sysmenu is disabled or not present do nothing */
1542 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1545 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1550 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1554 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1561 /***********************************************************************
1562 * NC_HandleSysCommand
1564 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1566 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1568 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1570 if (!IsWindowEnabled( hwnd
)) return 0;
1572 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1575 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1578 switch (wParam
& 0xfff0)
1582 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1586 if (hwnd
== GetActiveWindow())
1587 ShowOwnedPopups(hwnd
,FALSE
);
1588 ShowWindow( hwnd
, SW_MINIMIZE
);
1592 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1593 ShowOwnedPopups(hwnd
,TRUE
);
1594 ShowWindow( hwnd
, SW_MAXIMIZE
);
1598 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1599 ShowOwnedPopups(hwnd
,TRUE
);
1600 ShowWindow( hwnd
, SW_RESTORE
);
1604 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1610 pt
.x
= (short)LOWORD(lParam
);
1611 pt
.y
= (short)HIWORD(lParam
);
1612 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1619 pt
.x
= (short)LOWORD(lParam
);
1620 pt
.y
= (short)HIWORD(lParam
);
1621 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1626 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1630 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1634 if (wParam
== SC_ABOUTWINE
)
1636 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1639 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1641 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1642 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1643 FreeLibrary( hmodule
);
1652 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1658 /***********************************************************************
1659 * GetTitleBarInfo (USER32.@)
1660 * TODO: Handle STATE_SYSTEM_PRESSED
1662 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1666 TRACE("(%p %p)\n", hwnd
, tbi
);
1669 SetLastError(ERROR_NOACCESS
);
1673 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1674 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1675 SetLastError(ERROR_INVALID_PARAMETER
);
1678 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1679 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1680 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1682 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1683 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1684 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1686 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1687 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1690 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1691 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1692 * Under XP it seems to
1694 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1695 if(dwStyle
& WS_CAPTION
) {
1696 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1697 if(dwStyle
& WS_SYSMENU
) {
1698 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1699 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1700 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1703 if(!(dwStyle
& WS_MINIMIZEBOX
))
1704 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1705 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1706 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1708 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1709 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1710 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1711 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1714 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1715 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1716 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1717 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1721 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;