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
, 0, 0, LR_DEFAULTCOLOR
);
179 /* Draws the bar part(ie the big rectangle) of the caption */
180 static void NC_DrawCaptionBar (HDC hdc
, const RECT
*rect
, DWORD dwStyle
,
181 BOOL active
, BOOL gradient
)
185 TRIVERTEX vertices
[6];
187 GetSysColor (active
? COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
);
189 GetSysColor (active
? COLOR_GRADIENTACTIVECAPTION
190 : COLOR_GRADIENTINACTIVECAPTION
);
192 int buttonsAreaSize
= GetSystemMetrics(SM_CYCAPTION
) - 1;
193 static GRADIENT_RECT mesh
[] = {{0, 1}, {2, 3}, {4, 5}};
195 for (v
= 0; v
< 3; v
++)
197 vertices
[v
].Red
= GetRValue (colLeft
) << 8;
198 vertices
[v
].Green
= GetGValue (colLeft
) << 8;
199 vertices
[v
].Blue
= GetBValue (colLeft
) << 8;
200 vertices
[v
].Alpha
= 0x8000;
201 vertices
[v
+3].Red
= GetRValue (colRight
) << 8;
202 vertices
[v
+3].Green
= GetGValue (colRight
) << 8;
203 vertices
[v
+3].Blue
= GetBValue (colRight
) << 8;
204 vertices
[v
+3].Alpha
= 0x8000;
207 if ((dwStyle
& WS_SYSMENU
)
208 && ((dwStyle
& WS_MAXIMIZEBOX
) || (dwStyle
& WS_MINIMIZEBOX
)))
209 buttonsAreaSize
+= 2 * (GetSystemMetrics(SM_CXSIZE
) + 1);
211 /* area behind icon; solid filled with left color */
212 vertices
[0].x
= rect
->left
;
213 vertices
[0].y
= rect
->top
;
214 if (dwStyle
& WS_SYSMENU
)
216 min (rect
->left
+ GetSystemMetrics(SM_CXSMICON
), rect
->right
);
218 vertices
[1].x
= vertices
[0].x
;
219 vertices
[1].y
= rect
->bottom
;
221 /* area behind text; gradient */
222 vertices
[2].x
= vertices
[1].x
;
223 vertices
[2].y
= rect
->top
;
224 vertices
[3].x
= max (vertices
[2].x
, rect
->right
- buttonsAreaSize
);
225 vertices
[3].y
= rect
->bottom
;
227 /* area behind buttons; solid filled with right color */
228 vertices
[4].x
= vertices
[3].x
;
229 vertices
[4].y
= rect
->top
;
230 vertices
[5].x
= rect
->right
;
231 vertices
[5].y
= rect
->bottom
;
233 GdiGradientFill (hdc
, vertices
, 6, mesh
, 3, GRADIENT_FILL_RECT_H
);
236 FillRect (hdc
, rect
, GetSysColorBrush (active
?
237 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
240 /***********************************************************************
241 * DrawCaption (USER32.@) Draws a caption bar
255 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
257 return DrawCaptionTempW (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x103F);
261 /***********************************************************************
262 * DrawCaptionTempA (USER32.@)
264 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
265 HICON hIcon
, LPCSTR str
, UINT uFlags
)
271 if (!(uFlags
& DC_TEXT
) || !str
)
272 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
274 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
275 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
277 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
278 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
279 HeapFree( GetProcessHeap (), 0, strW
);
285 /***********************************************************************
286 * DrawCaptionTempW (USER32.@)
288 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
289 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
293 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
294 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
296 /* drawing background */
297 if (uFlags
& DC_INBUTTON
) {
298 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
300 if (uFlags
& DC_ACTIVE
) {
301 HBRUSH hbr
= SelectObject (hdc
, SYSCOLOR_55AABrush
);
302 PatBlt (hdc
, rc
.left
, rc
.top
,
303 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
304 SelectObject (hdc
, hbr
);
308 DWORD style
= GetWindowLongW (hwnd
, GWL_STYLE
);
309 NC_DrawCaptionBar (hdc
, &rc
, style
, uFlags
& DC_ACTIVE
, uFlags
& DC_GRADIENT
);
314 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
318 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
320 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
321 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
322 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
323 rc
.left
+= (rc
.bottom
- rc
.top
);
327 if (uFlags
& DC_TEXT
) {
330 if (uFlags
& DC_INBUTTON
)
331 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
332 else if (uFlags
& DC_ACTIVE
)
333 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
335 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
337 SetBkMode (hdc
, TRANSPARENT
);
340 hOldFont
= SelectObject (hdc
, hFont
);
342 NONCLIENTMETRICSW nclm
;
344 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
345 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
346 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
347 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
348 hOldFont
= SelectObject (hdc
, hNewFont
);
352 DrawTextW (hdc
, str
, -1, &rc
,
353 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
357 nLen
= GetWindowTextW (hwnd
, szText
, 128);
358 DrawTextW (hdc
, szText
, nLen
, &rc
,
359 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
363 SelectObject (hdc
, hOldFont
);
365 DeleteObject (SelectObject (hdc
, hOldFont
));
368 /* drawing focus ??? */
370 FIXME("undocumented flag (0x2000)!\n");
376 /***********************************************************************
377 * AdjustWindowRect (USER32.@)
379 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
381 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
385 /***********************************************************************
386 * AdjustWindowRectEx (USER32.@)
388 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
390 if (style
& WS_ICONIC
) return TRUE
;
391 style
&= ~(WS_HSCROLL
| WS_VSCROLL
);
393 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
);
395 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
396 NC_AdjustRectInner( rect
, style
, exStyle
);
402 /***********************************************************************
403 * NC_HandleNCCalcSize
405 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
407 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, WPARAM wparam
, RECT
*winRect
)
409 RECT tmpRect
= { 0, 0, 0, 0 };
411 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
412 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
413 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
418 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
419 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
421 if (!(style
& WS_ICONIC
))
423 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
425 winRect
->left
-= tmpRect
.left
;
426 winRect
->top
-= tmpRect
.top
;
427 winRect
->right
-= tmpRect
.right
;
428 winRect
->bottom
-= tmpRect
.bottom
;
430 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
432 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
433 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
436 MENU_GetMenuBarHeight( hwnd
,
437 winRect
->right
- winRect
->left
,
438 -tmpRect
.left
, -tmpRect
.top
);
441 if( exStyle
& WS_EX_CLIENTEDGE
)
442 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
443 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
444 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
445 - GetSystemMetrics(SM_CYEDGE
));
447 if (style
& WS_VSCROLL
)
448 if (winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
))
450 /* rectangle is in screen coords when wparam is false */
451 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
453 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
454 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
456 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
459 if (style
& WS_HSCROLL
)
460 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
461 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
463 if (winRect
->top
> winRect
->bottom
)
464 winRect
->bottom
= winRect
->top
;
466 if (winRect
->left
> winRect
->right
)
467 winRect
->right
= winRect
->left
;
473 /***********************************************************************
476 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
477 * but without the borders (if any).
479 static void NC_GetInsideRect( HWND hwnd
, enum coords_relative relative
, RECT
*rect
,
480 DWORD style
, DWORD ex_style
)
482 WIN_GetRectangles( hwnd
, relative
, rect
, NULL
);
484 if (style
& WS_ICONIC
) return;
486 /* Remove frame from rectangle */
487 if (HAS_THICKFRAME( style
, ex_style
))
489 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
491 else if (HAS_DLGFRAME( style
, ex_style
))
493 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
495 else if (HAS_THINFRAME( style
))
497 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
500 /* We have additional border information if the window
501 * is a child (but not an MDI child) */
502 if ((style
& WS_CHILD
) && !(ex_style
& WS_EX_MDICHILD
))
504 if (ex_style
& WS_EX_CLIENTEDGE
)
505 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
506 if (ex_style
& WS_EX_STATICEDGE
)
507 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
512 /***********************************************************************
515 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
517 LRESULT
NC_HandleNCHitTest( HWND hwnd
, POINT pt
)
520 DWORD style
, ex_style
;
522 TRACE("hwnd=%p pt=%d,%d\n", hwnd
, pt
.x
, pt
.y
);
524 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &rect
, &rcClient
);
525 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
527 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
528 ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
529 if (style
& WS_MINIMIZE
) return HTCAPTION
;
531 if (PtInRect( &rcClient
, pt
)) return HTCLIENT
;
534 if (HAS_THICKFRAME( style
, ex_style
))
536 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
537 if (!PtInRect( &rect
, pt
))
539 /* Check top sizing border */
542 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
543 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
546 /* Check bottom sizing border */
547 if (pt
.y
>= rect
.bottom
)
549 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
550 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
553 /* Check left sizing border */
554 if (pt
.x
< rect
.left
)
556 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
557 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
560 /* Check right sizing border */
561 if (pt
.x
>= rect
.right
)
563 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
564 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
569 else /* No thick frame */
571 if (HAS_DLGFRAME( style
, ex_style
))
572 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
573 else if (HAS_THINFRAME( style
))
574 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
575 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
580 if ((style
& WS_CAPTION
) == WS_CAPTION
)
582 if (ex_style
& WS_EX_TOOLWINDOW
)
583 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
585 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
586 if (!PtInRect( &rect
, pt
))
588 BOOL min_or_max_box
= (style
& WS_MAXIMIZEBOX
) ||
589 (style
& WS_MINIMIZEBOX
);
590 if (ex_style
& WS_EX_LAYOUTRTL
)
592 /* Check system menu */
593 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
595 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
596 if (pt
.x
> rect
.right
) return HTSYSMENU
;
599 /* Check close button */
600 if (style
& WS_SYSMENU
)
602 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
603 if (pt
.x
< rect
.left
) return HTCLOSE
;
606 /* Check maximize box */
607 /* In win95 there is automatically a Maximize button when there is a minimize one*/
608 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
610 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
611 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
614 /* Check minimize box */
615 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
617 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
618 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
623 /* Check system menu */
624 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
626 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
627 if (pt
.x
< rect
.left
) return HTSYSMENU
;
630 /* Check close button */
631 if (style
& WS_SYSMENU
)
633 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
634 if (pt
.x
> rect
.right
) return HTCLOSE
;
637 /* Check maximize box */
638 /* In win95 there is automatically a Maximize button when there is a minimize one*/
639 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
641 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
642 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
645 /* Check minimize box */
646 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
648 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
649 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
658 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
659 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
662 /* Check vertical scroll bar */
664 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
665 if (style
& WS_VSCROLL
)
667 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
668 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
670 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
671 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
674 /* Check horizontal scroll bar */
676 if (style
& WS_HSCROLL
)
678 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
679 if (PtInRect( &rcClient
, pt
))
682 if ((style
& WS_VSCROLL
) &&
683 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
684 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
690 /* Has to return HTNOWHERE if nothing was found
691 Could happen when a window has a customized non client area */
696 /******************************************************************************
700 * Draws the system icon.
702 *****************************************************************************/
703 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
705 HICON hIcon
= NC_IconForWindow( hwnd
);
710 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
711 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
713 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
714 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
715 GetSystemMetrics(SM_CXSMICON
),
716 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
722 /******************************************************************************
726 * Draws the close button.
728 * If bGrayed is true, then draw a disabled Close button
730 *****************************************************************************/
732 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
735 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
736 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
738 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
740 /* A tool window has a smaller Close button */
741 if (ex_style
& WS_EX_TOOLWINDOW
)
743 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
744 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
745 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
747 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
748 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
749 rect
.bottom
= rect
.top
+ iBmpHeight
;
750 rect
.right
= rect
.left
+ iBmpWidth
;
754 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
755 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
759 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
761 (down
? DFCS_PUSHED
: 0) |
762 (bGrayed
? DFCS_INACTIVE
: 0)) );
765 /******************************************************************************
768 * Draws the maximize button for windows.
769 * If bGrayed is true, then draw a disabled Maximize button
771 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
775 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
776 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
778 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
779 if (ex_style
& WS_EX_TOOLWINDOW
) return;
781 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
783 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
784 if (style
& WS_SYSMENU
)
785 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
786 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
787 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
790 if (down
) flags
|= DFCS_PUSHED
;
791 if (bGrayed
) flags
|= DFCS_INACTIVE
;
792 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
795 /******************************************************************************
798 * Draws the minimize button for windows.
799 * If bGrayed is true, then draw a disabled Minimize button
801 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
804 UINT flags
= DFCS_CAPTIONMIN
;
805 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
806 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
808 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
809 if (ex_style
& WS_EX_TOOLWINDOW
) return;
811 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
812 if (style
& WS_SYSMENU
)
813 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
814 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
815 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
816 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
817 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
820 if (down
) flags
|= DFCS_PUSHED
;
821 if (bGrayed
) flags
|= DFCS_INACTIVE
;
822 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
825 /******************************************************************************
829 * Draw a window frame inside the given rectangle, and update the rectangle.
832 * Many. First, just what IS a frame in Win95? Note that the 3D look
833 * on the outer edge is handled by NC_DoNCPaint. As is the inner
834 * edge. The inner rectangle just inside the frame is handled by the
837 * In short, for most people, this function should be a nop (unless
838 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
839 * them lately, but just to get this code right). Even so, it doesn't
840 * appear to be so. It's being worked on...
842 *****************************************************************************/
844 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
848 /* Firstly the "thick" frame */
849 if (style
& WS_THICKFRAME
)
851 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
852 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
854 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
855 COLOR_INACTIVEBORDER
) );
857 PatBlt( hdc
, rect
->left
, rect
->top
,
858 rect
->right
- rect
->left
, height
, PATCOPY
);
859 PatBlt( hdc
, rect
->left
, rect
->top
,
860 width
, rect
->bottom
- rect
->top
, PATCOPY
);
861 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
862 rect
->right
- rect
->left
, -height
, PATCOPY
);
863 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
864 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
866 InflateRect( rect
, -width
, -height
);
869 /* Now the other bit of the frame */
870 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
871 (exStyle
& WS_EX_DLGMODALFRAME
))
873 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
874 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
875 /* This should give a value of 1 that should also work for a border */
877 SelectObject( hdc
, GetSysColorBrush(
878 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
880 (exStyle
& WS_EX_STATICEDGE
) ?
882 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
888 PatBlt( hdc
, rect
->left
, rect
->top
,
889 rect
->right
- rect
->left
, height
, PATCOPY
);
890 PatBlt( hdc
, rect
->left
, rect
->top
,
891 width
, rect
->bottom
- rect
->top
, PATCOPY
);
892 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
893 rect
->right
- rect
->left
, -height
, PATCOPY
);
894 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
895 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
897 InflateRect( rect
, -width
, -height
);
902 /******************************************************************************
906 * Draw the window caption for windows.
907 * The correct pen for the window frame must be selected in the DC.
909 *****************************************************************************/
911 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
912 DWORD exStyle
, BOOL active
)
918 BOOL gradient
= FALSE
;
920 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
921 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
922 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
923 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
924 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
925 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
926 SelectObject( hdc
, hPrevPen
);
929 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
930 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
932 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
933 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
934 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
937 if (style
& WS_SYSMENU
)
941 /* Go get the sysmenu */
942 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
943 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
945 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
946 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
947 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
948 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
950 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
952 /* In win95 the two buttons are always there */
953 /* But if the menu item is not in the menu they're disabled*/
955 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
956 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
958 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
959 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
963 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
965 NONCLIENTMETRICSW nclm
;
966 HFONT hFont
, hOldFont
;
967 nclm
.cbSize
= sizeof(nclm
);
968 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
969 if (exStyle
& WS_EX_TOOLWINDOW
)
970 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
972 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
973 hOldFont
= SelectObject (hdc
, hFont
);
974 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
975 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
976 SetBkMode( hdc
, TRANSPARENT
);
978 DrawTextW( hdc
, buffer
, -1, &r
,
979 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
980 DeleteObject (SelectObject (hdc
, hOldFont
));
985 /******************************************************************************
988 * Paint the non-client area for windows.
990 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
993 RECT rfuzz
, rect
, rectClip
;
996 DWORD dwStyle
, dwExStyle
;
1001 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
1002 dwStyle
= wndPtr
->dwStyle
;
1003 dwExStyle
= wndPtr
->dwExStyle
;
1004 flags
= wndPtr
->flags
;
1005 WIN_ReleasePtr( wndPtr
);
1007 if ( dwStyle
& WS_MINIMIZE
||
1008 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1010 active
= flags
& WIN_NCACTIVATED
;
1012 TRACE("%p %d\n", hwnd
, active
);
1014 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1015 the call to GetDCEx implying that it is allowed not to use it either.
1016 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1017 will cause clipRgn to be deleted after ReleaseDC().
1018 Now, how is the "system" supposed to tell what happened?
1021 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1022 hrgn
= CreateRectRgnIndirect( &rectClient
);
1026 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1027 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1031 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1036 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1037 GetClipBox( hdc
, &rectClip
);
1039 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1041 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1042 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1044 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1045 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1048 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1050 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1053 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1054 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1055 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1058 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1059 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1061 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1062 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1065 if (HAS_MENU( hwnd
, dwStyle
))
1068 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1070 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1072 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1075 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1077 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1078 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1080 /* Draw the scroll-bars */
1082 if (dwStyle
& WS_VSCROLL
)
1083 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1084 if (dwStyle
& WS_HSCROLL
)
1085 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1087 /* Draw the "size-box" */
1088 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1091 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1092 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1094 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1095 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1096 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1099 ReleaseDC( hwnd
, hdc
);
1105 /***********************************************************************
1108 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1110 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1112 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1114 if( dwStyle
& WS_VISIBLE
)
1116 if( dwStyle
& WS_MINIMIZE
)
1117 WINPOS_RedrawIconTitle( hwnd
);
1119 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1125 /***********************************************************************
1126 * NC_HandleNCActivate
1128 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1130 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1132 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1134 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1136 /* Lotus Notes draws menu descriptions in the caption of its main
1137 * window. When it wants to restore original "system" view, it just
1138 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1139 * attempt to minimize redrawings lead to a not restored caption.
1141 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1142 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1143 WIN_ReleasePtr( wndPtr
);
1145 /* This isn't documented but is reproducible in at least XP SP2 and
1146 * Outlook 2007 depends on it
1151 WINPOS_RedrawIconTitle( hwnd
);
1153 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1160 /***********************************************************************
1161 * NC_HandleSetCursor
1163 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1165 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1167 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1169 switch((short)LOWORD(lParam
))
1173 WORD msg
= HIWORD( lParam
);
1174 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1175 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1182 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1192 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1196 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1200 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1204 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1207 /* Default cursor: arrow */
1208 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1211 /***********************************************************************
1214 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1216 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1219 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1220 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1222 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1223 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1224 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1225 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1229 /***********************************************************************
1232 * Track a mouse button press on the minimize or maximize box.
1234 * The big difference between 3.1 and 95 is the disabled button state.
1235 * In win95 the system button can be disabled, so it can ignore the mouse
1239 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1242 HDC hdc
= GetWindowDC( hwnd
);
1243 BOOL pressed
= TRUE
;
1245 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1246 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1248 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1250 if (wParam
== HTMINBUTTON
)
1252 /* If the style is not present, do nothing */
1253 if (!(wndStyle
& WS_MINIMIZEBOX
))
1256 /* Check if the sysmenu item for minimize is there */
1257 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1259 paintButton
= NC_DrawMinButton
;
1263 /* If the style is not present, do nothing */
1264 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1267 /* Check if the sysmenu item for maximize is there */
1268 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1270 paintButton
= NC_DrawMaxButton
;
1275 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1279 BOOL oldstate
= pressed
;
1281 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1282 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1284 if(msg
.message
== WM_LBUTTONUP
)
1287 if(msg
.message
!= WM_MOUSEMOVE
)
1290 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1291 if (pressed
!= oldstate
)
1292 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1296 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1299 ReleaseDC( hwnd
, hdc
);
1301 /* If the item minimize or maximize of the sysmenu are not there */
1302 /* or if the style is not present, do nothing */
1303 if ((!pressed
) || (state
== 0xFFFFFFFF))
1306 if (wParam
== HTMINBUTTON
)
1307 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1309 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1310 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1313 /***********************************************************************
1314 * NC_TrackCloseButton
1316 * Track a mouse button press on the Win95 close button.
1318 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1322 BOOL pressed
= TRUE
;
1323 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1329 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1331 /* If the item close of the sysmenu is disabled or not there do nothing */
1332 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1335 hdc
= GetWindowDC( hwnd
);
1339 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1343 BOOL oldstate
= pressed
;
1345 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1346 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1348 if(msg
.message
== WM_LBUTTONUP
)
1351 if(msg
.message
!= WM_MOUSEMOVE
)
1354 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1355 if (pressed
!= oldstate
)
1356 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1360 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1363 ReleaseDC( hwnd
, hdc
);
1364 if (!pressed
) return;
1366 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1370 /***********************************************************************
1373 * Track a mouse button press on the horizontal or vertical scroll-bar.
1375 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1379 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1381 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1382 scrollbar
= SB_HORZ
;
1384 else /* SC_VSCROLL */
1386 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1387 scrollbar
= SB_VERT
;
1389 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1393 /***********************************************************************
1394 * NC_HandleNCLButtonDown
1396 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1398 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1400 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1402 switch(wParam
) /* Hit test */
1406 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1408 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1409 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1414 if( style
& WS_SYSMENU
)
1416 if( !(style
& WS_MINIMIZE
) )
1418 HDC hDC
= GetWindowDC(hwnd
);
1419 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1420 ReleaseDC( hwnd
, hDC
);
1422 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1427 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1431 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1435 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1440 NC_TrackMinMaxBox( hwnd
, wParam
);
1444 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1456 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1457 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1459 /* But that is not what WinNT does. Instead it sends this. This
1460 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1461 * SC_MOUSEMENU into wParam.
1463 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1473 /***********************************************************************
1474 * NC_HandleNCLButtonDblClk
1476 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1478 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1481 * if this is an icon, send a restore since we are handling
1486 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1490 switch(wParam
) /* Hit test */
1493 /* stop processing if WS_MAXIMIZEBOX is missing */
1494 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1495 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1496 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1501 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1502 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1504 /* If the item close of the sysmenu is disabled or not there do nothing */
1505 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1508 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1513 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1517 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1524 /***********************************************************************
1525 * NC_HandleSysCommand
1527 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1529 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1531 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1533 if (!IsWindowEnabled( hwnd
)) return 0;
1535 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1538 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1541 switch (wParam
& 0xfff0)
1545 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1549 if (hwnd
== GetActiveWindow())
1550 ShowOwnedPopups(hwnd
,FALSE
);
1551 ShowWindow( hwnd
, SW_MINIMIZE
);
1555 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1556 ShowOwnedPopups(hwnd
,TRUE
);
1557 ShowWindow( hwnd
, SW_MAXIMIZE
);
1561 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1562 ShowOwnedPopups(hwnd
,TRUE
);
1563 ShowWindow( hwnd
, SW_RESTORE
);
1567 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1573 pt
.x
= (short)LOWORD(lParam
);
1574 pt
.y
= (short)HIWORD(lParam
);
1575 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1582 pt
.x
= (short)LOWORD(lParam
);
1583 pt
.y
= (short)HIWORD(lParam
);
1584 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1589 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1593 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1597 if (wParam
== SC_ABOUTWINE
)
1599 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1602 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1604 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1605 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1606 FreeLibrary( hmodule
);
1615 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1621 /***********************************************************************
1622 * GetTitleBarInfo (USER32.@)
1623 * TODO: Handle STATE_SYSTEM_PRESSED
1625 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1629 TRACE("(%p %p)\n", hwnd
, tbi
);
1632 SetLastError(ERROR_NOACCESS
);
1636 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1637 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1638 SetLastError(ERROR_INVALID_PARAMETER
);
1641 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1642 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1643 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1645 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1646 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1647 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1649 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1650 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1653 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1654 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1655 * Under XP it seems to
1657 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1658 if(dwStyle
& WS_CAPTION
) {
1659 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1660 if(dwStyle
& WS_SYSMENU
) {
1661 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1662 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1663 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1666 if(!(dwStyle
& WS_MINIMIZEBOX
))
1667 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1668 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1669 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1671 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1672 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1673 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1674 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1677 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1678 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1679 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1680 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1684 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;