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_MENU(hwnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
61 static void adjust_window_rect( RECT
*rect
, DWORD style
, BOOL menu
, DWORD exStyle
, NONCLIENTMETRICSW
*ncm
)
65 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
)
66 adjust
= 1; /* for the outer frame always present */
67 else if ((exStyle
& WS_EX_DLGMODALFRAME
) || (style
& (WS_THICKFRAME
|WS_DLGFRAME
)))
68 adjust
= 2; /* outer */
70 if (style
& WS_THICKFRAME
)
71 adjust
+= ncm
->iBorderWidth
+ ncm
->iPaddedBorderWidth
; /* The resize border */
73 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) || (exStyle
& WS_EX_DLGMODALFRAME
))
74 adjust
++; /* The other border */
76 InflateRect (rect
, adjust
, adjust
);
78 if ((style
& WS_CAPTION
) == WS_CAPTION
)
80 if (exStyle
& WS_EX_TOOLWINDOW
)
81 rect
->top
-= ncm
->iSmCaptionHeight
+ 1;
83 rect
->top
-= ncm
->iCaptionHeight
+ 1;
85 if (menu
) rect
->top
-= ncm
->iMenuHeight
+ 1;
87 if (exStyle
& WS_EX_CLIENTEDGE
)
88 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
92 static HICON
NC_IconForWindow( HWND hwnd
)
95 WND
*wndPtr
= WIN_GetPtr( hwnd
);
97 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
&& wndPtr
!= WND_DESKTOP
)
99 hIcon
= wndPtr
->hIconSmall
;
100 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
101 WIN_ReleasePtr( wndPtr
);
103 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
104 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICON
);
106 /* If there is no icon specified and this is not a modal dialog,
107 * get the default one.
109 if (!hIcon
&& !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_DLGMODALFRAME
))
110 hIcon
= LoadImageW(0, (LPCWSTR
)IDI_WINLOGO
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
),
111 GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTCOLOR
| LR_SHARED
);
115 /* Draws the bar part(ie the big rectangle) of the caption */
116 static void NC_DrawCaptionBar (HDC hdc
, const RECT
*rect
, DWORD dwStyle
,
117 BOOL active
, BOOL gradient
)
121 TRIVERTEX vertices
[4];
123 GetSysColor (active
? COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
);
125 GetSysColor (active
? COLOR_GRADIENTACTIVECAPTION
126 : COLOR_GRADIENTINACTIVECAPTION
);
127 int buttonsAreaSize
= GetSystemMetrics(SM_CYCAPTION
) - 1;
128 static GRADIENT_RECT mesh
[] = {{0, 1}, {1, 2}, {2, 3}};
130 vertices
[0].Red
= vertices
[1].Red
= GetRValue (colLeft
) << 8;
131 vertices
[0].Green
= vertices
[1].Green
= GetGValue (colLeft
) << 8;
132 vertices
[0].Blue
= vertices
[1].Blue
= GetBValue (colLeft
) << 8;
133 vertices
[0].Alpha
= vertices
[1].Alpha
= 0xff00;
134 vertices
[2].Red
= vertices
[3].Red
= GetRValue (colRight
) << 8;
135 vertices
[2].Green
= vertices
[3].Green
= GetGValue (colRight
) << 8;
136 vertices
[2].Blue
= vertices
[3].Blue
= GetBValue (colRight
) << 8;
137 vertices
[2].Alpha
= vertices
[3].Alpha
= 0xff00;
139 if ((dwStyle
& WS_SYSMENU
)
140 && ((dwStyle
& WS_MAXIMIZEBOX
) || (dwStyle
& WS_MINIMIZEBOX
)))
141 buttonsAreaSize
+= 2 * (GetSystemMetrics(SM_CXSIZE
) + 1);
143 /* area behind icon; solid filled with left color */
144 vertices
[0].x
= rect
->left
;
145 vertices
[0].y
= rect
->top
;
146 if (dwStyle
& WS_SYSMENU
)
147 vertices
[1].x
= min (rect
->left
+ GetSystemMetrics(SM_CXSMICON
), rect
->right
);
149 vertices
[1].x
= vertices
[0].x
;
150 vertices
[1].y
= rect
->bottom
;
152 /* area behind text; gradient */
153 vertices
[2].x
= max (vertices
[1].x
, rect
->right
- buttonsAreaSize
);
154 vertices
[2].y
= rect
->top
;
156 /* area behind buttons; solid filled with right color */
157 vertices
[3].x
= rect
->right
;
158 vertices
[3].y
= rect
->bottom
;
160 GdiGradientFill (hdc
, vertices
, 4, mesh
, 3, GRADIENT_FILL_RECT_H
);
163 FillRect (hdc
, rect
, GetSysColorBrush (active
?
164 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
167 /***********************************************************************
168 * DrawCaption (USER32.@) Draws a caption bar
182 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
184 return DrawCaptionTempW (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x103F);
188 /***********************************************************************
189 * DrawCaptionTempA (USER32.@)
191 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
192 HICON hIcon
, LPCSTR str
, UINT uFlags
)
198 if (!(uFlags
& DC_TEXT
) || !str
)
199 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
201 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
202 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
204 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
205 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
206 HeapFree( GetProcessHeap (), 0, strW
);
212 /***********************************************************************
213 * DrawCaptionTempW (USER32.@)
215 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
216 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
220 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
221 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
223 /* drawing background */
224 if (uFlags
& DC_INBUTTON
) {
225 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
227 if (uFlags
& DC_ACTIVE
) {
228 HBRUSH hbr
= SelectObject (hdc
, SYSCOLOR_Get55AABrush());
229 PatBlt (hdc
, rc
.left
, rc
.top
,
230 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
231 SelectObject (hdc
, hbr
);
235 DWORD style
= GetWindowLongW (hwnd
, GWL_STYLE
);
236 NC_DrawCaptionBar (hdc
, &rc
, style
, uFlags
& DC_ACTIVE
, uFlags
& DC_GRADIENT
);
241 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
245 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
247 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
248 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
249 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
250 rc
.left
= pt
.x
+ GetSystemMetrics( SM_CXSMICON
);
254 if (uFlags
& DC_TEXT
) {
258 if (uFlags
& DC_INBUTTON
)
259 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
260 else if (uFlags
& DC_ACTIVE
)
261 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
263 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
265 SetBkMode (hdc
, TRANSPARENT
);
268 hOldFont
= SelectObject (hdc
, hFont
);
270 NONCLIENTMETRICSW nclm
;
272 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
273 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
274 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
275 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
276 hOldFont
= SelectObject (hdc
, hNewFont
);
281 if (!GetWindowTextW( hwnd
, text
, ARRAY_SIZE( text
))) text
[0] = 0;
285 DrawTextW( hdc
, str
, -1, &rc
, ((uFlags
& 0x4000) ? DT_CENTER
: DT_LEFT
) |
286 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_END_ELLIPSIS
);
289 SelectObject (hdc
, hOldFont
);
291 DeleteObject (SelectObject (hdc
, hOldFont
));
294 /* drawing focus ??? */
296 FIXME("undocumented flag (0x2000)!\n");
302 /***********************************************************************
303 * AdjustWindowRect (USER32.@)
305 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
307 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
311 /***********************************************************************
312 * AdjustWindowRectEx (USER32.@)
314 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
316 NONCLIENTMETRICSW ncm
;
318 if (style
& WS_MINIMIZE
) return TRUE
;
320 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
);
322 ncm
.cbSize
= sizeof(ncm
);
323 SystemParametersInfoW( SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0 );
325 adjust_window_rect( rect
, style
, menu
, exStyle
, &ncm
);
330 /***********************************************************************
331 * AdjustWindowRectExForDpi (USER32.@)
333 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRectExForDpi( LPRECT rect
, DWORD style
, BOOL menu
,
334 DWORD exStyle
, UINT dpi
)
336 NONCLIENTMETRICSW ncm
;
338 if (style
& WS_MINIMIZE
) return TRUE
;
340 TRACE("(%s) %08x %d %08x %u\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
, dpi
);
342 ncm
.cbSize
= sizeof(ncm
);
343 SystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0, dpi
);
345 adjust_window_rect( rect
, style
, menu
, exStyle
, &ncm
);
350 /***********************************************************************
351 * NC_HandleNCCalcSize
353 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
355 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, WPARAM wparam
, RECT
*winRect
)
357 RECT tmpRect
= { 0, 0, 0, 0 };
359 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
360 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
361 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
366 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
367 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
369 if (!(style
& WS_MINIMIZE
))
371 AdjustWindowRectEx( &tmpRect
, style
, FALSE
, exStyle
& ~WS_EX_CLIENTEDGE
);
373 winRect
->left
-= tmpRect
.left
;
374 winRect
->top
-= tmpRect
.top
;
375 winRect
->right
-= tmpRect
.right
;
376 winRect
->bottom
-= tmpRect
.bottom
;
378 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
380 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
381 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
384 MENU_GetMenuBarHeight( hwnd
,
385 winRect
->right
- winRect
->left
,
386 -tmpRect
.left
, -tmpRect
.top
);
389 if( exStyle
& WS_EX_CLIENTEDGE
)
390 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
391 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
392 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
393 - GetSystemMetrics(SM_CYEDGE
));
395 if (style
& WS_VSCROLL
)
396 if (winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
))
398 /* rectangle is in screen coords when wparam is false */
399 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
401 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
402 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
404 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
407 if (style
& WS_HSCROLL
)
408 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
409 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
411 if (winRect
->top
> winRect
->bottom
)
412 winRect
->bottom
= winRect
->top
;
414 if (winRect
->left
> winRect
->right
)
415 winRect
->right
= winRect
->left
;
421 /***********************************************************************
424 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
425 * but without the borders (if any).
427 static void NC_GetInsideRect( HWND hwnd
, enum coords_relative relative
, RECT
*rect
,
428 DWORD style
, DWORD ex_style
)
430 WIN_GetRectangles( hwnd
, relative
, rect
, NULL
);
432 if (style
& WS_MINIMIZE
) return;
434 /* Remove frame from rectangle */
435 if (HAS_THICKFRAME( style
, ex_style
))
437 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
439 else if (HAS_DLGFRAME( style
, ex_style
))
441 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
443 else if (HAS_THINFRAME( style
))
445 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
448 /* We have additional border information if the window
449 * is a child (but not an MDI child) */
450 if ((style
& WS_CHILD
) && !(ex_style
& WS_EX_MDICHILD
))
452 if (ex_style
& WS_EX_CLIENTEDGE
)
453 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
454 if (ex_style
& WS_EX_STATICEDGE
)
455 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
460 /***********************************************************************
463 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
465 LRESULT
NC_HandleNCHitTest( HWND hwnd
, POINT pt
)
468 DWORD style
, ex_style
;
470 TRACE("hwnd=%p pt=%d,%d\n", hwnd
, pt
.x
, pt
.y
);
472 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &rect
, &rcClient
);
473 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
475 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
476 ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
477 if (style
& WS_MINIMIZE
) return HTCAPTION
;
479 if (PtInRect( &rcClient
, pt
)) return HTCLIENT
;
482 if (HAS_THICKFRAME( style
, ex_style
))
484 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
485 if (!PtInRect( &rect
, pt
))
487 /* Check top sizing border */
490 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
491 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
494 /* Check bottom sizing border */
495 if (pt
.y
>= rect
.bottom
)
497 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
498 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
501 /* Check left sizing border */
502 if (pt
.x
< rect
.left
)
504 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
505 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
508 /* Check right sizing border */
509 if (pt
.x
>= rect
.right
)
511 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
512 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
517 else /* No thick frame */
519 if (HAS_DLGFRAME( style
, ex_style
))
520 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
521 else if (HAS_THINFRAME( style
))
522 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
523 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
528 if ((style
& WS_CAPTION
) == WS_CAPTION
)
530 if (ex_style
& WS_EX_TOOLWINDOW
)
531 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
533 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
534 if (!PtInRect( &rect
, pt
))
536 BOOL min_or_max_box
= (style
& WS_SYSMENU
) && (style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
537 if (ex_style
& WS_EX_LAYOUTRTL
)
539 /* Check system menu */
540 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
542 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
543 if (pt
.x
> rect
.right
) return HTSYSMENU
;
546 /* Check close button */
547 if (style
& WS_SYSMENU
)
549 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
550 if (pt
.x
< rect
.left
) return HTCLOSE
;
553 /* Check maximize box */
554 /* In win95 there is automatically a Maximize button when there is a minimize one*/
555 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
557 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
558 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
561 /* Check minimize box */
562 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
564 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
565 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
570 /* Check system menu */
571 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
573 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
574 if (pt
.x
< rect
.left
) return HTSYSMENU
;
577 /* Check close button */
578 if (style
& WS_SYSMENU
)
580 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
581 if (pt
.x
> rect
.right
) return HTCLOSE
;
584 /* Check maximize box */
585 /* In win95 there is automatically a Maximize button when there is a minimize one*/
586 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
588 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
589 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
592 /* Check minimize box */
593 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
595 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
596 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
605 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
606 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
609 /* Check vertical scroll bar */
611 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
612 if (style
& WS_VSCROLL
)
614 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
615 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
617 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
618 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
621 /* Check horizontal scroll bar */
623 if (style
& WS_HSCROLL
)
625 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
626 if (PtInRect( &rcClient
, pt
))
629 if ((style
& WS_VSCROLL
) &&
630 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
631 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
637 /* Has to return HTNOWHERE if nothing was found
638 Could happen when a window has a customized non client area */
643 /******************************************************************************
647 * Draws the system icon.
649 *****************************************************************************/
650 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
652 HICON hIcon
= NC_IconForWindow( hwnd
);
658 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
659 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
661 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
662 pt
.x
= rect
.left
+ 2;
663 pt
.y
= rect
.top
+ (GetSystemMetrics(SM_CYCAPTION
) - GetSystemMetrics(SM_CYSMICON
)) / 2;
664 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
,
665 GetSystemMetrics(SM_CXSMICON
),
666 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
672 /******************************************************************************
676 * Draws the close button.
678 * If bGrayed is true, then draw a disabled Close button
680 *****************************************************************************/
682 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
685 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
686 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
688 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
690 /* A tool window has a smaller Close button */
691 if (ex_style
& WS_EX_TOOLWINDOW
)
693 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
694 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
695 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
697 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
698 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
699 rect
.bottom
= rect
.top
+ iBmpHeight
;
700 rect
.right
= rect
.left
+ iBmpWidth
;
704 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
705 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
709 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
711 (down
? DFCS_PUSHED
: 0) |
712 (bGrayed
? DFCS_INACTIVE
: 0)) );
715 /******************************************************************************
718 * Draws the maximize button for windows.
719 * If bGrayed is true, then draw a disabled Maximize button
721 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
725 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
726 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
728 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
729 if (ex_style
& WS_EX_TOOLWINDOW
) return;
731 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
733 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
734 if (style
& WS_SYSMENU
)
735 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
736 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
737 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
740 if (down
) flags
|= DFCS_PUSHED
;
741 if (bGrayed
) flags
|= DFCS_INACTIVE
;
742 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
745 /******************************************************************************
748 * Draws the minimize button for windows.
749 * If bGrayed is true, then draw a disabled Minimize button
751 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
754 UINT flags
= DFCS_CAPTIONMIN
;
755 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
756 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
758 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
759 if (ex_style
& WS_EX_TOOLWINDOW
) return;
761 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
762 if (style
& WS_SYSMENU
)
763 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
764 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
765 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
766 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
767 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
770 if (down
) flags
|= DFCS_PUSHED
;
771 if (bGrayed
) flags
|= DFCS_INACTIVE
;
772 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
775 /******************************************************************************
779 * Draw a window frame inside the given rectangle, and update the rectangle.
782 * Many. First, just what IS a frame in Win95? Note that the 3D look
783 * on the outer edge is handled by NC_DoNCPaint. As is the inner
784 * edge. The inner rectangle just inside the frame is handled by the
787 * In short, for most people, this function should be a nop (unless
788 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
789 * them lately, but just to get this code right). Even so, it doesn't
790 * appear to be so. It's being worked on...
792 *****************************************************************************/
794 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
798 /* Firstly the "thick" frame */
799 if (style
& WS_THICKFRAME
)
801 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
802 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
804 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
805 COLOR_INACTIVEBORDER
) );
807 PatBlt( hdc
, rect
->left
, rect
->top
,
808 rect
->right
- rect
->left
, height
, PATCOPY
);
809 PatBlt( hdc
, rect
->left
, rect
->top
,
810 width
, rect
->bottom
- rect
->top
, PATCOPY
);
811 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
812 rect
->right
- rect
->left
, -height
, PATCOPY
);
813 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
814 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
816 InflateRect( rect
, -width
, -height
);
819 /* Now the other bit of the frame */
820 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
821 (exStyle
& WS_EX_DLGMODALFRAME
))
823 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
824 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
825 /* This should give a value of 1 that should also work for a border */
827 SelectObject( hdc
, GetSysColorBrush(
828 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
830 (exStyle
& WS_EX_STATICEDGE
) ?
832 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
838 PatBlt( hdc
, rect
->left
, rect
->top
,
839 rect
->right
- rect
->left
, height
, PATCOPY
);
840 PatBlt( hdc
, rect
->left
, rect
->top
,
841 width
, rect
->bottom
- rect
->top
, PATCOPY
);
842 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
843 rect
->right
- rect
->left
, -height
, PATCOPY
);
844 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
845 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
847 InflateRect( rect
, -width
, -height
);
852 /******************************************************************************
856 * Draw the window caption for windows.
857 * The correct pen for the window frame must be selected in the DC.
859 *****************************************************************************/
861 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
862 DWORD exStyle
, BOOL active
)
868 BOOL gradient
= FALSE
;
870 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
871 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
872 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
873 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
874 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
875 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
876 SelectObject( hdc
, hPrevPen
);
879 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
880 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
882 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
883 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
884 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
887 if (style
& WS_SYSMENU
)
891 /* Go get the sysmenu */
892 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
893 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
895 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
896 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
897 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
898 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
900 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
902 /* In win95 the two buttons are always there */
903 /* But if the menu item is not in the menu they're disabled*/
905 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
906 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
908 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
909 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
913 if (GetWindowTextW( hwnd
, buffer
, ARRAY_SIZE( buffer
)))
915 NONCLIENTMETRICSW nclm
;
916 HFONT hFont
, hOldFont
;
917 nclm
.cbSize
= sizeof(nclm
);
918 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
919 if (exStyle
& WS_EX_TOOLWINDOW
)
920 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
922 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
923 hOldFont
= SelectObject (hdc
, hFont
);
924 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
925 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
926 SetBkMode( hdc
, TRANSPARENT
);
928 DrawTextW( hdc
, buffer
, -1, &r
,
929 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
930 DeleteObject (SelectObject (hdc
, hOldFont
));
935 /******************************************************************************
938 * Paint the non-client area for windows.
940 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
)
943 RECT rfuzz
, rect
, rectClip
;
946 DWORD dwStyle
, dwExStyle
;
951 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
952 dwStyle
= wndPtr
->dwStyle
;
953 dwExStyle
= wndPtr
->dwExStyle
;
954 flags
= wndPtr
->flags
;
955 WIN_ReleasePtr( wndPtr
);
957 if ( dwStyle
& WS_MINIMIZE
||
958 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
960 active
= flags
& WIN_NCACTIVATED
;
962 TRACE("%p %d\n", hwnd
, active
);
964 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
965 the call to GetDCEx implying that it is allowed not to use it either.
966 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
967 will cause clipRgn to be deleted after ReleaseDC().
968 Now, how is the "system" supposed to tell what happened?
971 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
972 hrgn
= CreateRectRgnIndirect( &rectClient
);
976 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
977 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
981 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
986 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
987 GetClipBox( hdc
, &rectClip
);
989 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
991 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
992 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
994 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
995 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
998 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1000 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1003 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1004 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1005 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1008 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1009 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1011 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1012 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1015 if (HAS_MENU( hwnd
, dwStyle
))
1018 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1020 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1022 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
) + 1;
1025 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1027 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1028 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1030 /* Draw the scroll-bars */
1032 if (dwStyle
& WS_VSCROLL
)
1033 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1034 if (dwStyle
& WS_HSCROLL
)
1035 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1037 /* Draw the "size-box" */
1038 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1041 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1042 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1044 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1045 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1046 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1049 ReleaseDC( hwnd
, hdc
);
1055 /***********************************************************************
1058 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1060 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1062 HWND parent
= GetAncestor( hwnd
, GA_PARENT
);
1063 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1065 if( dwStyle
& WS_VISIBLE
)
1067 if( dwStyle
& WS_MINIMIZE
)
1068 WINPOS_RedrawIconTitle( hwnd
);
1070 NC_DoNCPaint( hwnd
, clip
);
1072 if (parent
== GetDesktopWindow())
1073 PostMessageW( parent
, WM_PARENTNOTIFY
, WM_NCPAINT
, (LPARAM
)hwnd
);
1079 /***********************************************************************
1080 * NC_HandleNCActivate
1082 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1084 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1086 /* Lotus Notes draws menu descriptions in the caption of its main
1087 * window. When it wants to restore original "system" view, it just
1088 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1089 * attempt to minimize redrawings lead to a not restored caption.
1091 if (wParam
) win_set_flags( hwnd
, WIN_NCACTIVATED
, 0 );
1092 else win_set_flags( hwnd
, 0, WIN_NCACTIVATED
);
1094 /* This isn't documented but is reproducible in at least XP SP2 and
1095 * Outlook 2007 depends on it
1100 WINPOS_RedrawIconTitle( hwnd
);
1102 NC_DoNCPaint( hwnd
, (HRGN
)1 );
1104 if (GetAncestor( hwnd
, GA_PARENT
) == GetDesktopWindow())
1105 PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY
, WM_NCACTIVATE
, (LPARAM
)hwnd
);
1112 /***********************************************************************
1113 * NC_HandleSetCursor
1115 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1117 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1119 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1121 switch((short)LOWORD(lParam
))
1125 WORD msg
= HIWORD( lParam
);
1126 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1127 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1134 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1144 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1148 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1152 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1156 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1159 /* Default cursor: arrow */
1160 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1163 /***********************************************************************
1166 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1168 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1171 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1172 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1174 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1175 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1176 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1177 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1181 /***********************************************************************
1184 * Track a mouse button press on the minimize or maximize box.
1186 * The big difference between 3.1 and 95 is the disabled button state.
1187 * In win95 the system button can be disabled, so it can ignore the mouse
1191 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1194 HDC hdc
= GetWindowDC( hwnd
);
1195 BOOL pressed
= TRUE
;
1197 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1198 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1200 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1202 if (wParam
== HTMINBUTTON
)
1204 /* If the style is not present, do nothing */
1205 if (!(wndStyle
& WS_MINIMIZEBOX
))
1208 /* Check if the sysmenu item for minimize is there */
1209 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1211 paintButton
= NC_DrawMinButton
;
1215 /* If the style is not present, do nothing */
1216 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1219 /* Check if the sysmenu item for maximize is there */
1220 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1222 paintButton
= NC_DrawMaxButton
;
1227 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1231 BOOL oldstate
= pressed
;
1233 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1234 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1236 if(msg
.message
== WM_LBUTTONUP
)
1239 if(msg
.message
!= WM_MOUSEMOVE
)
1242 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1243 if (pressed
!= oldstate
)
1244 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1248 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1251 ReleaseDC( hwnd
, hdc
);
1253 /* If the minimize or maximize items of the sysmenu are not there */
1254 /* or if the style is not present, do nothing */
1255 if ((!pressed
) || (state
== 0xFFFFFFFF))
1258 if (wParam
== HTMINBUTTON
)
1259 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1261 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1262 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1265 /***********************************************************************
1266 * NC_TrackCloseButton
1268 * Track a mouse button press on the Win95 close button.
1270 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1274 BOOL pressed
= TRUE
;
1275 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1281 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1283 /* If the close item of the sysmenu is disabled or not present do nothing */
1284 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1287 hdc
= GetWindowDC( hwnd
);
1291 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1295 BOOL oldstate
= pressed
;
1297 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1298 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1300 if(msg
.message
== WM_LBUTTONUP
)
1303 if(msg
.message
!= WM_MOUSEMOVE
)
1306 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1307 if (pressed
!= oldstate
)
1308 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1312 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1315 ReleaseDC( hwnd
, hdc
);
1316 if (!pressed
) return;
1318 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1322 /***********************************************************************
1325 * Track a mouse button press on the horizontal or vertical scroll-bar.
1327 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1331 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1333 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1334 scrollbar
= SB_HORZ
;
1336 else /* SC_VSCROLL */
1338 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1339 scrollbar
= SB_VERT
;
1341 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1345 /***********************************************************************
1346 * NC_HandleNCLButtonDown
1348 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1350 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1352 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1354 switch(wParam
) /* Hit test */
1358 HWND top
= hwnd
, parent
;
1361 if ((GetWindowLongW( top
, GWL_STYLE
) & (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1363 parent
= GetAncestor( top
, GA_PARENT
);
1364 if (!parent
|| parent
== GetDesktopWindow()) break;
1368 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1369 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1374 if( style
& WS_SYSMENU
)
1376 if( !(style
& WS_MINIMIZE
) )
1378 HDC hDC
= GetWindowDC(hwnd
);
1379 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1380 ReleaseDC( hwnd
, hDC
);
1382 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1387 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1391 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1395 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1400 NC_TrackMinMaxBox( hwnd
, wParam
);
1404 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1416 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1417 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1419 /* But that is not what WinNT does. Instead it sends this. This
1420 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1421 * SC_MOUSEMENU into wParam.
1423 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1433 /***********************************************************************
1434 * NC_HandleNCRButtonDown
1436 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1438 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1441 INT hittest
= wParam
;
1450 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1451 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1452 if (msg
.message
== WM_RBUTTONUP
)
1454 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1459 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1460 SendMessageW( hwnd
, WM_CONTEXTMENU
, (WPARAM
)hwnd
, MAKELPARAM(msg
.pt
.x
, msg
.pt
.y
));
1467 /***********************************************************************
1468 * NC_HandleNCLButtonDblClk
1470 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1472 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1475 * if this is an icon, send a restore since we are handling
1480 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1484 switch(wParam
) /* Hit test */
1487 /* stop processing if WS_MAXIMIZEBOX is missing */
1488 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1489 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1490 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1495 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1496 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1498 /* If the close item of the sysmenu is disabled or not present do nothing */
1499 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1502 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1507 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1511 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1518 /***********************************************************************
1519 * NC_HandleSysCommand
1521 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1523 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1525 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1527 if (!IsWindowEnabled( hwnd
)) return 0;
1529 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1532 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1535 switch (wParam
& 0xfff0)
1539 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1543 if (hwnd
== GetActiveWindow())
1544 ShowOwnedPopups(hwnd
,FALSE
);
1545 ShowWindow( hwnd
, SW_MINIMIZE
);
1549 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1550 ShowOwnedPopups(hwnd
,TRUE
);
1551 ShowWindow( hwnd
, SW_MAXIMIZE
);
1555 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1556 ShowOwnedPopups(hwnd
,TRUE
);
1557 ShowWindow( hwnd
, SW_RESTORE
);
1561 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1567 pt
.x
= (short)LOWORD(lParam
);
1568 pt
.y
= (short)HIWORD(lParam
);
1569 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1576 pt
.x
= (short)LOWORD(lParam
);
1577 pt
.y
= (short)HIWORD(lParam
);
1578 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1583 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1587 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1591 if (wParam
== SC_ABOUTWINE
)
1593 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1596 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1598 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1599 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1600 FreeLibrary( hmodule
);
1609 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1615 /***********************************************************************
1616 * GetTitleBarInfo (USER32.@)
1617 * TODO: Handle STATE_SYSTEM_PRESSED
1619 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1623 TRACE("(%p %p)\n", hwnd
, tbi
);
1626 SetLastError(ERROR_NOACCESS
);
1630 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1631 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1632 SetLastError(ERROR_INVALID_PARAMETER
);
1635 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1636 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1637 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1639 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1640 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1641 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1643 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1644 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1647 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1648 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1649 * Under XP it seems to
1651 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1652 if(dwStyle
& WS_CAPTION
) {
1653 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1654 if(dwStyle
& WS_SYSMENU
) {
1655 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1656 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1657 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1660 if(!(dwStyle
& WS_MINIMIZEBOX
))
1661 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1662 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1663 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1665 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1666 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1667 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1668 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1671 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1672 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1673 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1674 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1678 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;