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
) && !(exStyle
& WS_EX_DLGMODALFRAME
))
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 hIcon specified and this is a modal dialog,
172 * get the default one.
174 if (!hIcon
&& (GetWindowLongW( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
175 hIcon
= LoadImageW(0, (LPCWSTR
)IDI_WINLOGO
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
),
176 GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTCOLOR
);
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
+= (rc
.bottom
- rc
.top
);
319 if (uFlags
& DC_TEXT
) {
322 if (uFlags
& DC_INBUTTON
)
323 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
324 else if (uFlags
& DC_ACTIVE
)
325 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
327 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
329 SetBkMode (hdc
, TRANSPARENT
);
332 hOldFont
= SelectObject (hdc
, hFont
);
334 NONCLIENTMETRICSW nclm
;
336 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
337 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
338 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
339 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
340 hOldFont
= SelectObject (hdc
, hNewFont
);
344 DrawTextW (hdc
, str
, -1, &rc
,
345 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
349 nLen
= GetWindowTextW (hwnd
, szText
, 128);
350 DrawTextW (hdc
, szText
, nLen
, &rc
,
351 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
355 SelectObject (hdc
, hOldFont
);
357 DeleteObject (SelectObject (hdc
, hOldFont
));
360 /* drawing focus ??? */
362 FIXME("undocumented flag (0x2000)!\n");
368 /***********************************************************************
369 * AdjustWindowRect (USER32.@)
371 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
373 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
377 /***********************************************************************
378 * AdjustWindowRectEx (USER32.@)
380 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
382 if (style
& WS_ICONIC
) return TRUE
;
383 style
&= ~(WS_HSCROLL
| WS_VSCROLL
);
385 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
);
387 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
388 NC_AdjustRectInner( rect
, style
, exStyle
);
394 /***********************************************************************
395 * NC_HandleNCCalcSize
397 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
399 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, WPARAM wparam
, RECT
*winRect
)
401 RECT tmpRect
= { 0, 0, 0, 0 };
403 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
404 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
405 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
410 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
411 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
413 if (!(style
& WS_ICONIC
))
415 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
417 winRect
->left
-= tmpRect
.left
;
418 winRect
->top
-= tmpRect
.top
;
419 winRect
->right
-= tmpRect
.right
;
420 winRect
->bottom
-= tmpRect
.bottom
;
422 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
424 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
425 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
428 MENU_GetMenuBarHeight( hwnd
,
429 winRect
->right
- winRect
->left
,
430 -tmpRect
.left
, -tmpRect
.top
);
433 if( exStyle
& WS_EX_CLIENTEDGE
)
434 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
435 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
436 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
437 - GetSystemMetrics(SM_CYEDGE
));
439 if (style
& WS_VSCROLL
)
440 if (winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
))
442 /* rectangle is in screen coords when wparam is false */
443 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
445 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
446 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
448 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
451 if (style
& WS_HSCROLL
)
452 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
453 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
455 if (winRect
->top
> winRect
->bottom
)
456 winRect
->bottom
= winRect
->top
;
458 if (winRect
->left
> winRect
->right
)
459 winRect
->right
= winRect
->left
;
465 /***********************************************************************
468 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
469 * but without the borders (if any).
471 static void NC_GetInsideRect( HWND hwnd
, enum coords_relative relative
, RECT
*rect
,
472 DWORD style
, DWORD ex_style
)
474 WIN_GetRectangles( hwnd
, relative
, rect
, NULL
);
476 if (style
& WS_ICONIC
) return;
478 /* Remove frame from rectangle */
479 if (HAS_THICKFRAME( style
, ex_style
))
481 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
483 else if (HAS_DLGFRAME( style
, ex_style
))
485 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
487 else if (HAS_THINFRAME( style
))
489 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
492 /* We have additional border information if the window
493 * is a child (but not an MDI child) */
494 if ((style
& WS_CHILD
) && !(ex_style
& WS_EX_MDICHILD
))
496 if (ex_style
& WS_EX_CLIENTEDGE
)
497 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
498 if (ex_style
& WS_EX_STATICEDGE
)
499 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
504 /***********************************************************************
507 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
509 LRESULT
NC_HandleNCHitTest( HWND hwnd
, POINT pt
)
512 DWORD style
, ex_style
;
514 TRACE("hwnd=%p pt=%d,%d\n", hwnd
, pt
.x
, pt
.y
);
516 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &rect
, &rcClient
);
517 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
519 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
520 ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
521 if (style
& WS_MINIMIZE
) return HTCAPTION
;
523 if (PtInRect( &rcClient
, pt
)) return HTCLIENT
;
526 if (HAS_THICKFRAME( style
, ex_style
))
528 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
529 if (!PtInRect( &rect
, pt
))
531 /* Check top sizing border */
534 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
535 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
538 /* Check bottom sizing border */
539 if (pt
.y
>= rect
.bottom
)
541 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
542 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
545 /* Check left sizing border */
546 if (pt
.x
< rect
.left
)
548 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
549 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
552 /* Check right sizing border */
553 if (pt
.x
>= rect
.right
)
555 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
556 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
561 else /* No thick frame */
563 if (HAS_DLGFRAME( style
, ex_style
))
564 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
565 else if (HAS_THINFRAME( style
))
566 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
567 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
572 if ((style
& WS_CAPTION
) == WS_CAPTION
)
574 if (ex_style
& WS_EX_TOOLWINDOW
)
575 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
577 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
578 if (!PtInRect( &rect
, pt
))
580 BOOL min_or_max_box
= (style
& WS_SYSMENU
) && (style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
581 if (ex_style
& WS_EX_LAYOUTRTL
)
583 /* Check system menu */
584 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
586 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
587 if (pt
.x
> rect
.right
) return HTSYSMENU
;
590 /* Check close button */
591 if (style
& WS_SYSMENU
)
593 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
594 if (pt
.x
< rect
.left
) return HTCLOSE
;
597 /* Check maximize box */
598 /* In win95 there is automatically a Maximize button when there is a minimize one*/
599 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
601 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
602 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
605 /* Check minimize box */
606 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
608 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
609 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
614 /* Check system menu */
615 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
617 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
618 if (pt
.x
< rect
.left
) return HTSYSMENU
;
621 /* Check close button */
622 if (style
& WS_SYSMENU
)
624 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
625 if (pt
.x
> rect
.right
) return HTCLOSE
;
628 /* Check maximize box */
629 /* In win95 there is automatically a Maximize button when there is a minimize one*/
630 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
632 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
633 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
636 /* Check minimize box */
637 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
639 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
640 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
649 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
650 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
653 /* Check vertical scroll bar */
655 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
656 if (style
& WS_VSCROLL
)
658 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
659 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
661 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
662 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
665 /* Check horizontal scroll bar */
667 if (style
& WS_HSCROLL
)
669 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
670 if (PtInRect( &rcClient
, pt
))
673 if ((style
& WS_VSCROLL
) &&
674 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
675 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
681 /* Has to return HTNOWHERE if nothing was found
682 Could happen when a window has a customized non client area */
687 /******************************************************************************
691 * Draws the system icon.
693 *****************************************************************************/
694 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
696 HICON hIcon
= NC_IconForWindow( hwnd
);
702 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
703 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
705 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
706 pt
.x
= rect
.left
+ 2;
707 pt
.y
= (rect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - GetSystemMetrics(SM_CYSMICON
)) / 2;
708 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
,
709 GetSystemMetrics(SM_CXSMICON
),
710 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
716 /******************************************************************************
720 * Draws the close button.
722 * If bGrayed is true, then draw a disabled Close button
724 *****************************************************************************/
726 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
729 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
730 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
732 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
734 /* A tool window has a smaller Close button */
735 if (ex_style
& WS_EX_TOOLWINDOW
)
737 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
738 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
739 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
741 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
742 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
743 rect
.bottom
= rect
.top
+ iBmpHeight
;
744 rect
.right
= rect
.left
+ iBmpWidth
;
748 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
749 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
753 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
755 (down
? DFCS_PUSHED
: 0) |
756 (bGrayed
? DFCS_INACTIVE
: 0)) );
759 /******************************************************************************
762 * Draws the maximize button for windows.
763 * If bGrayed is true, then draw a disabled Maximize button
765 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
769 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
770 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
772 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
773 if (ex_style
& WS_EX_TOOLWINDOW
) return;
775 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
777 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
778 if (style
& WS_SYSMENU
)
779 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
780 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
781 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
784 if (down
) flags
|= DFCS_PUSHED
;
785 if (bGrayed
) flags
|= DFCS_INACTIVE
;
786 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
789 /******************************************************************************
792 * Draws the minimize button for windows.
793 * If bGrayed is true, then draw a disabled Minimize button
795 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
798 UINT flags
= DFCS_CAPTIONMIN
;
799 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
800 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
802 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
803 if (ex_style
& WS_EX_TOOLWINDOW
) return;
805 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
806 if (style
& WS_SYSMENU
)
807 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
808 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
809 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
810 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
811 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
814 if (down
) flags
|= DFCS_PUSHED
;
815 if (bGrayed
) flags
|= DFCS_INACTIVE
;
816 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
819 /******************************************************************************
823 * Draw a window frame inside the given rectangle, and update the rectangle.
826 * Many. First, just what IS a frame in Win95? Note that the 3D look
827 * on the outer edge is handled by NC_DoNCPaint. As is the inner
828 * edge. The inner rectangle just inside the frame is handled by the
831 * In short, for most people, this function should be a nop (unless
832 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
833 * them lately, but just to get this code right). Even so, it doesn't
834 * appear to be so. It's being worked on...
836 *****************************************************************************/
838 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
842 /* Firstly the "thick" frame */
843 if (style
& WS_THICKFRAME
)
845 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
846 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
848 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
849 COLOR_INACTIVEBORDER
) );
851 PatBlt( hdc
, rect
->left
, rect
->top
,
852 rect
->right
- rect
->left
, height
, PATCOPY
);
853 PatBlt( hdc
, rect
->left
, rect
->top
,
854 width
, rect
->bottom
- rect
->top
, PATCOPY
);
855 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
856 rect
->right
- rect
->left
, -height
, PATCOPY
);
857 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
858 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
860 InflateRect( rect
, -width
, -height
);
863 /* Now the other bit of the frame */
864 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
865 (exStyle
& WS_EX_DLGMODALFRAME
))
867 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
868 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
869 /* This should give a value of 1 that should also work for a border */
871 SelectObject( hdc
, GetSysColorBrush(
872 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
874 (exStyle
& WS_EX_STATICEDGE
) ?
876 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
882 PatBlt( hdc
, rect
->left
, rect
->top
,
883 rect
->right
- rect
->left
, height
, PATCOPY
);
884 PatBlt( hdc
, rect
->left
, rect
->top
,
885 width
, rect
->bottom
- rect
->top
, PATCOPY
);
886 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
887 rect
->right
- rect
->left
, -height
, PATCOPY
);
888 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
889 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
891 InflateRect( rect
, -width
, -height
);
896 /******************************************************************************
900 * Draw the window caption for windows.
901 * The correct pen for the window frame must be selected in the DC.
903 *****************************************************************************/
905 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
906 DWORD exStyle
, BOOL active
)
912 BOOL gradient
= FALSE
;
914 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
915 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
916 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
917 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
918 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
919 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
920 SelectObject( hdc
, hPrevPen
);
923 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
924 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
926 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
927 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
928 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
931 if (style
& WS_SYSMENU
)
935 /* Go get the sysmenu */
936 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
937 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
939 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
940 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
941 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
942 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
944 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
946 /* In win95 the two buttons are always there */
947 /* But if the menu item is not in the menu they're disabled*/
949 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
950 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
952 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
953 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
957 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
959 NONCLIENTMETRICSW nclm
;
960 HFONT hFont
, hOldFont
;
961 nclm
.cbSize
= sizeof(nclm
);
962 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
963 if (exStyle
& WS_EX_TOOLWINDOW
)
964 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
966 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
967 hOldFont
= SelectObject (hdc
, hFont
);
968 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
969 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
970 SetBkMode( hdc
, TRANSPARENT
);
972 DrawTextW( hdc
, buffer
, -1, &r
,
973 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
974 DeleteObject (SelectObject (hdc
, hOldFont
));
979 /******************************************************************************
982 * Paint the non-client area for windows.
984 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
)
987 RECT rfuzz
, rect
, rectClip
;
990 DWORD dwStyle
, dwExStyle
;
995 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
996 dwStyle
= wndPtr
->dwStyle
;
997 dwExStyle
= wndPtr
->dwExStyle
;
998 flags
= wndPtr
->flags
;
999 WIN_ReleasePtr( wndPtr
);
1001 if ( dwStyle
& WS_MINIMIZE
||
1002 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1004 active
= flags
& WIN_NCACTIVATED
;
1006 TRACE("%p %d\n", hwnd
, active
);
1008 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1009 the call to GetDCEx implying that it is allowed not to use it either.
1010 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1011 will cause clipRgn to be deleted after ReleaseDC().
1012 Now, how is the "system" supposed to tell what happened?
1015 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1016 hrgn
= CreateRectRgnIndirect( &rectClient
);
1020 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1021 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1025 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1030 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1031 GetClipBox( hdc
, &rectClip
);
1033 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1035 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1036 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1038 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1039 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1042 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1044 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1047 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1048 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1049 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1052 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1053 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1055 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1056 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1059 if (HAS_MENU( hwnd
, dwStyle
))
1062 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1064 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1066 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
) + 1;
1069 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1071 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1072 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1074 /* Draw the scroll-bars */
1076 if (dwStyle
& WS_VSCROLL
)
1077 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1078 if (dwStyle
& WS_HSCROLL
)
1079 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1081 /* Draw the "size-box" */
1082 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1085 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1086 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1088 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1089 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1090 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1093 ReleaseDC( hwnd
, hdc
);
1099 /***********************************************************************
1102 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1104 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
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
);
1119 /***********************************************************************
1120 * NC_HandleNCActivate
1122 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1124 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1126 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1128 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1130 /* Lotus Notes draws menu descriptions in the caption of its main
1131 * window. When it wants to restore original "system" view, it just
1132 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1133 * attempt to minimize redrawings lead to a not restored caption.
1135 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1136 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1137 WIN_ReleasePtr( wndPtr
);
1139 /* This isn't documented but is reproducible in at least XP SP2 and
1140 * Outlook 2007 depends on it
1145 WINPOS_RedrawIconTitle( hwnd
);
1147 NC_DoNCPaint( hwnd
, (HRGN
)1 );
1154 /***********************************************************************
1155 * NC_HandleSetCursor
1157 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1159 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1161 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1163 switch((short)LOWORD(lParam
))
1167 WORD msg
= HIWORD( lParam
);
1168 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1169 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1176 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1186 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1190 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1194 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1198 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1201 /* Default cursor: arrow */
1202 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1205 /***********************************************************************
1208 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1210 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1213 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1214 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1216 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1217 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1218 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1219 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1223 /***********************************************************************
1226 * Track a mouse button press on the minimize or maximize box.
1228 * The big difference between 3.1 and 95 is the disabled button state.
1229 * In win95 the system button can be disabled, so it can ignore the mouse
1233 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1236 HDC hdc
= GetWindowDC( hwnd
);
1237 BOOL pressed
= TRUE
;
1239 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1240 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1242 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1244 if (wParam
== HTMINBUTTON
)
1246 /* If the style is not present, do nothing */
1247 if (!(wndStyle
& WS_MINIMIZEBOX
))
1250 /* Check if the sysmenu item for minimize is there */
1251 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1253 paintButton
= NC_DrawMinButton
;
1257 /* If the style is not present, do nothing */
1258 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1261 /* Check if the sysmenu item for maximize is there */
1262 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1264 paintButton
= NC_DrawMaxButton
;
1269 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1273 BOOL oldstate
= pressed
;
1275 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1276 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1278 if(msg
.message
== WM_LBUTTONUP
)
1281 if(msg
.message
!= WM_MOUSEMOVE
)
1284 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1285 if (pressed
!= oldstate
)
1286 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1290 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1293 ReleaseDC( hwnd
, hdc
);
1295 /* If the minimize or maximize items of the sysmenu are not there */
1296 /* or if the style is not present, do nothing */
1297 if ((!pressed
) || (state
== 0xFFFFFFFF))
1300 if (wParam
== HTMINBUTTON
)
1301 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1303 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1304 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1307 /***********************************************************************
1308 * NC_TrackCloseButton
1310 * Track a mouse button press on the Win95 close button.
1312 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1316 BOOL pressed
= TRUE
;
1317 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1323 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1325 /* If the close item of the sysmenu is disabled or not present do nothing */
1326 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1329 hdc
= GetWindowDC( hwnd
);
1333 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1337 BOOL oldstate
= pressed
;
1339 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1340 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1342 if(msg
.message
== WM_LBUTTONUP
)
1345 if(msg
.message
!= WM_MOUSEMOVE
)
1348 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1349 if (pressed
!= oldstate
)
1350 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1354 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1357 ReleaseDC( hwnd
, hdc
);
1358 if (!pressed
) return;
1360 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1364 /***********************************************************************
1367 * Track a mouse button press on the horizontal or vertical scroll-bar.
1369 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1373 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1375 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1376 scrollbar
= SB_HORZ
;
1378 else /* SC_VSCROLL */
1380 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1381 scrollbar
= SB_VERT
;
1383 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1387 /***********************************************************************
1388 * NC_HandleNCLButtonDown
1390 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1392 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1394 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1396 switch(wParam
) /* Hit test */
1400 HWND top
= hwnd
, parent
;
1403 if ((GetWindowLongW( top
, GWL_STYLE
) & (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1405 parent
= GetAncestor( top
, GA_PARENT
);
1406 if (!parent
|| parent
== GetDesktopWindow()) break;
1410 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1411 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1416 if( style
& WS_SYSMENU
)
1418 if( !(style
& WS_MINIMIZE
) )
1420 HDC hDC
= GetWindowDC(hwnd
);
1421 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1422 ReleaseDC( hwnd
, hDC
);
1424 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1429 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1433 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1437 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1442 NC_TrackMinMaxBox( hwnd
, wParam
);
1446 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1458 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1459 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1461 /* But that is not what WinNT does. Instead it sends this. This
1462 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1463 * SC_MOUSEMENU into wParam.
1465 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1475 /***********************************************************************
1476 * NC_HandleNCRButtonDown
1478 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1480 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1483 INT hittest
= wParam
;
1489 if (!GetSystemMenu( hwnd
, FALSE
)) break;
1494 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1495 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1496 if (msg
.message
== WM_RBUTTONUP
)
1498 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1503 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1504 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, msg
.lParam
);
1511 /***********************************************************************
1512 * NC_HandleNCLButtonDblClk
1514 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1516 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1519 * if this is an icon, send a restore since we are handling
1524 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1528 switch(wParam
) /* Hit test */
1531 /* stop processing if WS_MAXIMIZEBOX is missing */
1532 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1533 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1534 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1539 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1540 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1542 /* If the close item of the sysmenu is disabled or not present do nothing */
1543 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1546 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1551 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1555 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1562 /***********************************************************************
1563 * NC_HandleSysCommand
1565 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1567 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1569 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1571 if (!IsWindowEnabled( hwnd
)) return 0;
1573 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1576 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1579 switch (wParam
& 0xfff0)
1583 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1587 if (hwnd
== GetActiveWindow())
1588 ShowOwnedPopups(hwnd
,FALSE
);
1589 ShowWindow( hwnd
, SW_MINIMIZE
);
1593 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1594 ShowOwnedPopups(hwnd
,TRUE
);
1595 ShowWindow( hwnd
, SW_MAXIMIZE
);
1599 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1600 ShowOwnedPopups(hwnd
,TRUE
);
1601 ShowWindow( hwnd
, SW_RESTORE
);
1605 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1611 pt
.x
= (short)LOWORD(lParam
);
1612 pt
.y
= (short)HIWORD(lParam
);
1613 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1620 pt
.x
= (short)LOWORD(lParam
);
1621 pt
.y
= (short)HIWORD(lParam
);
1622 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1627 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1631 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1635 if (wParam
== SC_ABOUTWINE
)
1637 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1640 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1642 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1643 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1644 FreeLibrary( hmodule
);
1653 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1659 /***********************************************************************
1660 * GetTitleBarInfo (USER32.@)
1661 * TODO: Handle STATE_SYSTEM_PRESSED
1663 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1667 TRACE("(%p %p)\n", hwnd
, tbi
);
1670 SetLastError(ERROR_NOACCESS
);
1674 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1675 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1676 SetLastError(ERROR_INVALID_PARAMETER
);
1679 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1680 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1681 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1683 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1684 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1685 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1687 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1688 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1691 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1692 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1693 * Under XP it seems to
1695 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1696 if(dwStyle
& WS_CAPTION
) {
1697 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1698 if(dwStyle
& WS_SYSMENU
) {
1699 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1700 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1701 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1704 if(!(dwStyle
& WS_MINIMIZEBOX
))
1705 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1706 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1707 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1709 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1710 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1711 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1712 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1715 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1716 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1717 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1718 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1722 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;