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
[4];
187 GetSysColor (active
? COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
);
189 GetSysColor (active
? COLOR_GRADIENTACTIVECAPTION
190 : COLOR_GRADIENTINACTIVECAPTION
);
191 int buttonsAreaSize
= GetSystemMetrics(SM_CYCAPTION
) - 1;
192 static GRADIENT_RECT mesh
[] = {{0, 1}, {1, 2}, {2, 3}};
194 vertices
[0].Red
= vertices
[1].Red
= GetRValue (colLeft
) << 8;
195 vertices
[0].Green
= vertices
[1].Green
= GetGValue (colLeft
) << 8;
196 vertices
[0].Blue
= vertices
[1].Blue
= GetBValue (colLeft
) << 8;
197 vertices
[0].Alpha
= vertices
[1].Alpha
= 0xff00;
198 vertices
[2].Red
= vertices
[3].Red
= GetRValue (colRight
) << 8;
199 vertices
[2].Green
= vertices
[3].Green
= GetGValue (colRight
) << 8;
200 vertices
[2].Blue
= vertices
[3].Blue
= GetBValue (colRight
) << 8;
201 vertices
[2].Alpha
= vertices
[3].Alpha
= 0xff00;
203 if ((dwStyle
& WS_SYSMENU
)
204 && ((dwStyle
& WS_MAXIMIZEBOX
) || (dwStyle
& WS_MINIMIZEBOX
)))
205 buttonsAreaSize
+= 2 * (GetSystemMetrics(SM_CXSIZE
) + 1);
207 /* area behind icon; solid filled with left color */
208 vertices
[0].x
= rect
->left
;
209 vertices
[0].y
= rect
->top
;
210 if (dwStyle
& WS_SYSMENU
)
211 vertices
[1].x
= min (rect
->left
+ GetSystemMetrics(SM_CXSMICON
), rect
->right
);
213 vertices
[1].x
= vertices
[0].x
;
214 vertices
[1].y
= rect
->bottom
;
216 /* area behind text; gradient */
217 vertices
[2].x
= max (vertices
[1].x
, rect
->right
- buttonsAreaSize
);
218 vertices
[2].y
= rect
->top
;
220 /* area behind buttons; solid filled with right color */
221 vertices
[3].x
= rect
->right
;
222 vertices
[3].y
= rect
->bottom
;
224 GdiGradientFill (hdc
, vertices
, 4, mesh
, 3, GRADIENT_FILL_RECT_H
);
227 FillRect (hdc
, rect
, GetSysColorBrush (active
?
228 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
231 /***********************************************************************
232 * DrawCaption (USER32.@) Draws a caption bar
246 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
248 return DrawCaptionTempW (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x103F);
252 /***********************************************************************
253 * DrawCaptionTempA (USER32.@)
255 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
256 HICON hIcon
, LPCSTR str
, UINT uFlags
)
262 if (!(uFlags
& DC_TEXT
) || !str
)
263 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
265 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
266 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
268 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
269 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
270 HeapFree( GetProcessHeap (), 0, strW
);
276 /***********************************************************************
277 * DrawCaptionTempW (USER32.@)
279 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
280 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
284 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
285 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
287 /* drawing background */
288 if (uFlags
& DC_INBUTTON
) {
289 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
291 if (uFlags
& DC_ACTIVE
) {
292 HBRUSH hbr
= SelectObject (hdc
, SYSCOLOR_Get55AABrush());
293 PatBlt (hdc
, rc
.left
, rc
.top
,
294 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
295 SelectObject (hdc
, hbr
);
299 DWORD style
= GetWindowLongW (hwnd
, GWL_STYLE
);
300 NC_DrawCaptionBar (hdc
, &rc
, style
, uFlags
& DC_ACTIVE
, uFlags
& DC_GRADIENT
);
305 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
309 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
311 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
312 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
313 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
314 rc
.left
+= (rc
.bottom
- rc
.top
);
318 if (uFlags
& DC_TEXT
) {
321 if (uFlags
& DC_INBUTTON
)
322 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
323 else if (uFlags
& DC_ACTIVE
)
324 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
326 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
328 SetBkMode (hdc
, TRANSPARENT
);
331 hOldFont
= SelectObject (hdc
, hFont
);
333 NONCLIENTMETRICSW nclm
;
335 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
336 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
337 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
338 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
339 hOldFont
= SelectObject (hdc
, hNewFont
);
343 DrawTextW (hdc
, str
, -1, &rc
,
344 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
348 nLen
= GetWindowTextW (hwnd
, szText
, 128);
349 DrawTextW (hdc
, szText
, nLen
, &rc
,
350 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
354 SelectObject (hdc
, hOldFont
);
356 DeleteObject (SelectObject (hdc
, hOldFont
));
359 /* drawing focus ??? */
361 FIXME("undocumented flag (0x2000)!\n");
367 /***********************************************************************
368 * AdjustWindowRect (USER32.@)
370 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
372 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
376 /***********************************************************************
377 * AdjustWindowRectEx (USER32.@)
379 BOOL WINAPI DECLSPEC_HOTPATCH
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
381 if (style
& WS_ICONIC
) return TRUE
;
382 style
&= ~(WS_HSCROLL
| WS_VSCROLL
);
384 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect
), style
, menu
, exStyle
);
386 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
387 NC_AdjustRectInner( rect
, style
, exStyle
);
393 /***********************************************************************
394 * NC_HandleNCCalcSize
396 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
398 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, WPARAM wparam
, RECT
*winRect
)
400 RECT tmpRect
= { 0, 0, 0, 0 };
402 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
403 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
404 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
409 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
410 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
412 if (!(style
& WS_ICONIC
))
414 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
416 winRect
->left
-= tmpRect
.left
;
417 winRect
->top
-= tmpRect
.top
;
418 winRect
->right
-= tmpRect
.right
;
419 winRect
->bottom
-= tmpRect
.bottom
;
421 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
423 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
424 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
427 MENU_GetMenuBarHeight( hwnd
,
428 winRect
->right
- winRect
->left
,
429 -tmpRect
.left
, -tmpRect
.top
);
432 if( exStyle
& WS_EX_CLIENTEDGE
)
433 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
434 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
435 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
436 - GetSystemMetrics(SM_CYEDGE
));
438 if (style
& WS_VSCROLL
)
439 if (winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
))
441 /* rectangle is in screen coords when wparam is false */
442 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
444 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
445 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
447 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
450 if (style
& WS_HSCROLL
)
451 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
452 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
454 if (winRect
->top
> winRect
->bottom
)
455 winRect
->bottom
= winRect
->top
;
457 if (winRect
->left
> winRect
->right
)
458 winRect
->right
= winRect
->left
;
464 /***********************************************************************
467 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
468 * but without the borders (if any).
470 static void NC_GetInsideRect( HWND hwnd
, enum coords_relative relative
, RECT
*rect
,
471 DWORD style
, DWORD ex_style
)
473 WIN_GetRectangles( hwnd
, relative
, rect
, NULL
);
475 if (style
& WS_ICONIC
) return;
477 /* Remove frame from rectangle */
478 if (HAS_THICKFRAME( style
, ex_style
))
480 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
482 else if (HAS_DLGFRAME( style
, ex_style
))
484 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
486 else if (HAS_THINFRAME( style
))
488 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
491 /* We have additional border information if the window
492 * is a child (but not an MDI child) */
493 if ((style
& WS_CHILD
) && !(ex_style
& WS_EX_MDICHILD
))
495 if (ex_style
& WS_EX_CLIENTEDGE
)
496 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
497 if (ex_style
& WS_EX_STATICEDGE
)
498 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
503 /***********************************************************************
506 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
508 LRESULT
NC_HandleNCHitTest( HWND hwnd
, POINT pt
)
511 DWORD style
, ex_style
;
513 TRACE("hwnd=%p pt=%d,%d\n", hwnd
, pt
.x
, pt
.y
);
515 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, &rect
, &rcClient
);
516 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
518 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
519 ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
520 if (style
& WS_MINIMIZE
) return HTCAPTION
;
522 if (PtInRect( &rcClient
, pt
)) return HTCLIENT
;
525 if (HAS_THICKFRAME( style
, ex_style
))
527 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
528 if (!PtInRect( &rect
, pt
))
530 /* Check top sizing border */
533 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
534 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
537 /* Check bottom sizing border */
538 if (pt
.y
>= rect
.bottom
)
540 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
541 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
544 /* Check left sizing border */
545 if (pt
.x
< rect
.left
)
547 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
548 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
551 /* Check right sizing border */
552 if (pt
.x
>= rect
.right
)
554 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
555 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
560 else /* No thick frame */
562 if (HAS_DLGFRAME( style
, ex_style
))
563 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
564 else if (HAS_THINFRAME( style
))
565 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
566 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
571 if ((style
& WS_CAPTION
) == WS_CAPTION
)
573 if (ex_style
& WS_EX_TOOLWINDOW
)
574 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
576 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
577 if (!PtInRect( &rect
, pt
))
579 BOOL min_or_max_box
= (style
& WS_SYSMENU
) && (style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
580 if (ex_style
& WS_EX_LAYOUTRTL
)
582 /* Check system menu */
583 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
585 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
586 if (pt
.x
> rect
.right
) return HTSYSMENU
;
589 /* Check close button */
590 if (style
& WS_SYSMENU
)
592 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
593 if (pt
.x
< rect
.left
) return HTCLOSE
;
596 /* Check maximize box */
597 /* In win95 there is automatically a Maximize button when there is a minimize one*/
598 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
600 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
601 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
604 /* Check minimize box */
605 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
607 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
608 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
613 /* Check system menu */
614 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
616 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
617 if (pt
.x
< rect
.left
) return HTSYSMENU
;
620 /* Check close button */
621 if (style
& WS_SYSMENU
)
623 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
624 if (pt
.x
> rect
.right
) return HTCLOSE
;
627 /* Check maximize box */
628 /* In win95 there is automatically a Maximize button when there is a minimize one*/
629 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
631 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
632 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
635 /* Check minimize box */
636 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
638 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
639 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
648 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
649 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
652 /* Check vertical scroll bar */
654 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
655 if (style
& WS_VSCROLL
)
657 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
658 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
660 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
661 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
664 /* Check horizontal scroll bar */
666 if (style
& WS_HSCROLL
)
668 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
669 if (PtInRect( &rcClient
, pt
))
672 if ((style
& WS_VSCROLL
) &&
673 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
674 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
680 /* Has to return HTNOWHERE if nothing was found
681 Could happen when a window has a customized non client area */
686 /******************************************************************************
690 * Draws the system icon.
692 *****************************************************************************/
693 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
695 HICON hIcon
= NC_IconForWindow( hwnd
);
701 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
702 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
704 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
705 pt
.x
= rect
.left
+ 2;
706 pt
.y
= (rect
.top
+ GetSystemMetrics(SM_CYCAPTION
) - GetSystemMetrics(SM_CYSMICON
)) / 2;
707 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
,
708 GetSystemMetrics(SM_CXSMICON
),
709 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
715 /******************************************************************************
719 * Draws the close button.
721 * If bGrayed is true, then draw a disabled Close button
723 *****************************************************************************/
725 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
728 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
729 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
731 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
733 /* A tool window has a smaller Close button */
734 if (ex_style
& WS_EX_TOOLWINDOW
)
736 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
737 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
738 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
740 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
741 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
742 rect
.bottom
= rect
.top
+ iBmpHeight
;
743 rect
.right
= rect
.left
+ iBmpWidth
;
747 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
748 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
752 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
754 (down
? DFCS_PUSHED
: 0) |
755 (bGrayed
? DFCS_INACTIVE
: 0)) );
758 /******************************************************************************
761 * Draws the maximize button for windows.
762 * If bGrayed is true, then draw a disabled Maximize button
764 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
768 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
769 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
771 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
772 if (ex_style
& WS_EX_TOOLWINDOW
) return;
774 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
776 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
777 if (style
& WS_SYSMENU
)
778 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
779 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
780 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
783 if (down
) flags
|= DFCS_PUSHED
;
784 if (bGrayed
) flags
|= DFCS_INACTIVE
;
785 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
788 /******************************************************************************
791 * Draws the minimize button for windows.
792 * If bGrayed is true, then draw a disabled Minimize button
794 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
797 UINT flags
= DFCS_CAPTIONMIN
;
798 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
799 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
801 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
802 if (ex_style
& WS_EX_TOOLWINDOW
) return;
804 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
805 if (style
& WS_SYSMENU
)
806 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
807 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
808 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
809 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
810 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
813 if (down
) flags
|= DFCS_PUSHED
;
814 if (bGrayed
) flags
|= DFCS_INACTIVE
;
815 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
818 /******************************************************************************
822 * Draw a window frame inside the given rectangle, and update the rectangle.
825 * Many. First, just what IS a frame in Win95? Note that the 3D look
826 * on the outer edge is handled by NC_DoNCPaint. As is the inner
827 * edge. The inner rectangle just inside the frame is handled by the
830 * In short, for most people, this function should be a nop (unless
831 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
832 * them lately, but just to get this code right). Even so, it doesn't
833 * appear to be so. It's being worked on...
835 *****************************************************************************/
837 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
841 /* Firstly the "thick" frame */
842 if (style
& WS_THICKFRAME
)
844 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
845 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
847 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
848 COLOR_INACTIVEBORDER
) );
850 PatBlt( hdc
, rect
->left
, rect
->top
,
851 rect
->right
- rect
->left
, height
, PATCOPY
);
852 PatBlt( hdc
, rect
->left
, rect
->top
,
853 width
, rect
->bottom
- rect
->top
, PATCOPY
);
854 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
855 rect
->right
- rect
->left
, -height
, PATCOPY
);
856 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
857 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
859 InflateRect( rect
, -width
, -height
);
862 /* Now the other bit of the frame */
863 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
864 (exStyle
& WS_EX_DLGMODALFRAME
))
866 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
867 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
868 /* This should give a value of 1 that should also work for a border */
870 SelectObject( hdc
, GetSysColorBrush(
871 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
873 (exStyle
& WS_EX_STATICEDGE
) ?
875 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
881 PatBlt( hdc
, rect
->left
, rect
->top
,
882 rect
->right
- rect
->left
, height
, PATCOPY
);
883 PatBlt( hdc
, rect
->left
, rect
->top
,
884 width
, rect
->bottom
- rect
->top
, PATCOPY
);
885 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
886 rect
->right
- rect
->left
, -height
, PATCOPY
);
887 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
888 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
890 InflateRect( rect
, -width
, -height
);
895 /******************************************************************************
899 * Draw the window caption for windows.
900 * The correct pen for the window frame must be selected in the DC.
902 *****************************************************************************/
904 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
905 DWORD exStyle
, BOOL active
)
911 BOOL gradient
= FALSE
;
913 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
914 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
915 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
916 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
917 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
918 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
919 SelectObject( hdc
, hPrevPen
);
922 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
923 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
925 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
926 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
927 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
930 if (style
& WS_SYSMENU
)
934 /* Go get the sysmenu */
935 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
936 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
938 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
939 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
940 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
941 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
943 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
945 /* In win95 the two buttons are always there */
946 /* But if the menu item is not in the menu they're disabled*/
948 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
949 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
951 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
952 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
956 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
958 NONCLIENTMETRICSW nclm
;
959 HFONT hFont
, hOldFont
;
960 nclm
.cbSize
= sizeof(nclm
);
961 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
962 if (exStyle
& WS_EX_TOOLWINDOW
)
963 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
965 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
966 hOldFont
= SelectObject (hdc
, hFont
);
967 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
968 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
969 SetBkMode( hdc
, TRANSPARENT
);
971 DrawTextW( hdc
, buffer
, -1, &r
,
972 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
973 DeleteObject (SelectObject (hdc
, hOldFont
));
978 /******************************************************************************
981 * Paint the non-client area for windows.
983 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
)
986 RECT rfuzz
, rect
, rectClip
;
989 DWORD dwStyle
, dwExStyle
;
994 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
995 dwStyle
= wndPtr
->dwStyle
;
996 dwExStyle
= wndPtr
->dwExStyle
;
997 flags
= wndPtr
->flags
;
998 WIN_ReleasePtr( wndPtr
);
1000 if ( dwStyle
& WS_MINIMIZE
||
1001 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1003 active
= flags
& WIN_NCACTIVATED
;
1005 TRACE("%p %d\n", hwnd
, active
);
1007 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1008 the call to GetDCEx implying that it is allowed not to use it either.
1009 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1010 will cause clipRgn to be deleted after ReleaseDC().
1011 Now, how is the "system" supposed to tell what happened?
1014 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1015 hrgn
= CreateRectRgnIndirect( &rectClient
);
1019 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1020 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1024 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1029 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1030 GetClipBox( hdc
, &rectClip
);
1032 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1034 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1035 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1037 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1038 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1041 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1043 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1046 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1047 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1048 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1051 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1052 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1054 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1055 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1058 if (HAS_MENU( hwnd
, dwStyle
))
1061 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1063 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1065 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
) + 1;
1068 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1070 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1071 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1073 /* Draw the scroll-bars */
1075 if (dwStyle
& WS_VSCROLL
)
1076 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1077 if (dwStyle
& WS_HSCROLL
)
1078 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1080 /* Draw the "size-box" */
1081 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1084 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1085 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1087 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1088 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1089 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1092 ReleaseDC( hwnd
, hdc
);
1098 /***********************************************************************
1101 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1103 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1105 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1107 if( dwStyle
& WS_VISIBLE
)
1109 if( dwStyle
& WS_MINIMIZE
)
1110 WINPOS_RedrawIconTitle( hwnd
);
1112 NC_DoNCPaint( hwnd
, clip
);
1118 /***********************************************************************
1119 * NC_HandleNCActivate
1121 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1123 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1125 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1127 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1129 /* Lotus Notes draws menu descriptions in the caption of its main
1130 * window. When it wants to restore original "system" view, it just
1131 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1132 * attempt to minimize redrawings lead to a not restored caption.
1134 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1135 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1136 WIN_ReleasePtr( wndPtr
);
1138 /* This isn't documented but is reproducible in at least XP SP2 and
1139 * Outlook 2007 depends on it
1144 WINPOS_RedrawIconTitle( hwnd
);
1146 NC_DoNCPaint( hwnd
, (HRGN
)1 );
1153 /***********************************************************************
1154 * NC_HandleSetCursor
1156 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1158 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1160 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1162 switch((short)LOWORD(lParam
))
1166 WORD msg
= HIWORD( lParam
);
1167 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1168 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1175 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1185 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1189 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1193 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1197 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1200 /* Default cursor: arrow */
1201 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1204 /***********************************************************************
1207 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1209 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1212 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1213 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1215 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1216 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1217 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1218 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1222 /***********************************************************************
1225 * Track a mouse button press on the minimize or maximize box.
1227 * The big difference between 3.1 and 95 is the disabled button state.
1228 * In win95 the system button can be disabled, so it can ignore the mouse
1232 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1235 HDC hdc
= GetWindowDC( hwnd
);
1236 BOOL pressed
= TRUE
;
1238 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1239 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1241 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1243 if (wParam
== HTMINBUTTON
)
1245 /* If the style is not present, do nothing */
1246 if (!(wndStyle
& WS_MINIMIZEBOX
))
1249 /* Check if the sysmenu item for minimize is there */
1250 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1252 paintButton
= NC_DrawMinButton
;
1256 /* If the style is not present, do nothing */
1257 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1260 /* Check if the sysmenu item for maximize is there */
1261 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1263 paintButton
= NC_DrawMaxButton
;
1268 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1272 BOOL oldstate
= pressed
;
1274 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1275 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1277 if(msg
.message
== WM_LBUTTONUP
)
1280 if(msg
.message
!= WM_MOUSEMOVE
)
1283 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1284 if (pressed
!= oldstate
)
1285 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1289 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1292 ReleaseDC( hwnd
, hdc
);
1294 /* If the minimize or maximize items of the sysmenu are not there */
1295 /* or if the style is not present, do nothing */
1296 if ((!pressed
) || (state
== 0xFFFFFFFF))
1299 if (wParam
== HTMINBUTTON
)
1300 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1302 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1303 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1306 /***********************************************************************
1307 * NC_TrackCloseButton
1309 * Track a mouse button press on the Win95 close button.
1311 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1315 BOOL pressed
= TRUE
;
1316 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1322 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1324 /* If the close item of the sysmenu is disabled or not present do nothing */
1325 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1328 hdc
= GetWindowDC( hwnd
);
1332 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1336 BOOL oldstate
= pressed
;
1338 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1339 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1341 if(msg
.message
== WM_LBUTTONUP
)
1344 if(msg
.message
!= WM_MOUSEMOVE
)
1347 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1348 if (pressed
!= oldstate
)
1349 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1353 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1356 ReleaseDC( hwnd
, hdc
);
1357 if (!pressed
) return;
1359 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1363 /***********************************************************************
1366 * Track a mouse button press on the horizontal or vertical scroll-bar.
1368 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1372 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1374 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1375 scrollbar
= SB_HORZ
;
1377 else /* SC_VSCROLL */
1379 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1380 scrollbar
= SB_VERT
;
1382 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1386 /***********************************************************************
1387 * NC_HandleNCLButtonDown
1389 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1391 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1393 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1395 switch(wParam
) /* Hit test */
1399 HWND top
= hwnd
, parent
;
1402 if ((GetWindowLongW( top
, GWL_STYLE
) & (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1404 parent
= GetAncestor( top
, GA_PARENT
);
1405 if (!parent
|| parent
== GetDesktopWindow()) break;
1409 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1410 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1415 if( style
& WS_SYSMENU
)
1417 if( !(style
& WS_MINIMIZE
) )
1419 HDC hDC
= GetWindowDC(hwnd
);
1420 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1421 ReleaseDC( hwnd
, hDC
);
1423 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1428 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1432 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1436 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1441 NC_TrackMinMaxBox( hwnd
, wParam
);
1445 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1457 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1458 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1460 /* But that is not what WinNT does. Instead it sends this. This
1461 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1462 * SC_MOUSEMENU into wParam.
1464 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1474 /***********************************************************************
1475 * NC_HandleNCRButtonDown
1477 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1479 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1482 INT hittest
= wParam
;
1488 if (!GetSystemMenu( hwnd
, FALSE
)) break;
1493 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1494 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1495 if (msg
.message
== WM_RBUTTONUP
)
1497 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1502 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1503 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, msg
.lParam
);
1510 /***********************************************************************
1511 * NC_HandleNCLButtonDblClk
1513 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1515 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1518 * if this is an icon, send a restore since we are handling
1523 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1527 switch(wParam
) /* Hit test */
1530 /* stop processing if WS_MAXIMIZEBOX is missing */
1531 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1532 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1533 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1538 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1539 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1541 /* If the close item of the sysmenu is disabled or not present do nothing */
1542 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1545 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1550 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1554 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1561 /***********************************************************************
1562 * NC_HandleSysCommand
1564 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1566 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1568 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1570 if (!IsWindowEnabled( hwnd
)) return 0;
1572 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1575 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1578 switch (wParam
& 0xfff0)
1582 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1586 if (hwnd
== GetActiveWindow())
1587 ShowOwnedPopups(hwnd
,FALSE
);
1588 ShowWindow( hwnd
, SW_MINIMIZE
);
1592 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1593 ShowOwnedPopups(hwnd
,TRUE
);
1594 ShowWindow( hwnd
, SW_MAXIMIZE
);
1598 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1599 ShowOwnedPopups(hwnd
,TRUE
);
1600 ShowWindow( hwnd
, SW_RESTORE
);
1604 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1610 pt
.x
= (short)LOWORD(lParam
);
1611 pt
.y
= (short)HIWORD(lParam
);
1612 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1619 pt
.x
= (short)LOWORD(lParam
);
1620 pt
.y
= (short)HIWORD(lParam
);
1621 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1626 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1630 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1634 if (wParam
== SC_ABOUTWINE
)
1636 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1639 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1641 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1642 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1643 FreeLibrary( hmodule
);
1652 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1658 /***********************************************************************
1659 * GetTitleBarInfo (USER32.@)
1660 * TODO: Handle STATE_SYSTEM_PRESSED
1662 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1666 TRACE("(%p %p)\n", hwnd
, tbi
);
1669 SetLastError(ERROR_NOACCESS
);
1673 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1674 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1675 SetLastError(ERROR_INVALID_PARAMETER
);
1678 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1679 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1680 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1682 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1683 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1684 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1686 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1687 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1690 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1691 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1692 * Under XP it seems to
1694 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1695 if(dwStyle
& WS_CAPTION
) {
1696 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1697 if(dwStyle
& WS_SYSMENU
) {
1698 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1699 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1700 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1703 if(!(dwStyle
& WS_MINIMIZEBOX
))
1704 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1705 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1706 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1708 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1709 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1710 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1711 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1714 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1715 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1716 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1717 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1721 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;