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_55AABrush
);
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_MAXIMIZEBOX
) ||
580 (style
& WS_MINIMIZEBOX
);
581 if (ex_style
& WS_EX_LAYOUTRTL
)
583 /* Check system menu */
584 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
586 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
587 if (pt
.x
> rect
.right
) return HTSYSMENU
;
590 /* Check close button */
591 if (style
& WS_SYSMENU
)
593 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
);
594 if (pt
.x
< rect
.left
) return HTCLOSE
;
597 /* Check maximize box */
598 /* In win95 there is automatically a Maximize button when there is a minimize one*/
599 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
601 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
602 if (pt
.x
< rect
.left
) return HTMAXBUTTON
;
605 /* Check minimize box */
606 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
608 rect
.left
+= GetSystemMetrics(SM_CXSIZE
);
609 if (pt
.x
< rect
.left
) return HTMINBUTTON
;
614 /* Check system menu */
615 if ((style
& WS_SYSMENU
) && !(ex_style
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(hwnd
))
617 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
618 if (pt
.x
< rect
.left
) return HTSYSMENU
;
621 /* Check close button */
622 if (style
& WS_SYSMENU
)
624 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
);
625 if (pt
.x
> rect
.right
) return HTCLOSE
;
628 /* Check maximize box */
629 /* In win95 there is automatically a Maximize button when there is a minimize one*/
630 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
632 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
633 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
636 /* Check minimize box */
637 if (min_or_max_box
&& !(ex_style
& WS_EX_TOOLWINDOW
))
639 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
640 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
649 if (HAS_MENU( hwnd
, style
) && (pt
.y
< rcClient
.top
) &&
650 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
653 /* Check vertical scroll bar */
655 if (ex_style
& WS_EX_LAYOUTRTL
) ex_style
^= WS_EX_LEFTSCROLLBAR
;
656 if (style
& WS_VSCROLL
)
658 if((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0)
659 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
661 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
662 if (PtInRect( &rcClient
, pt
)) return HTVSCROLL
;
665 /* Check horizontal scroll bar */
667 if (style
& WS_HSCROLL
)
669 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
670 if (PtInRect( &rcClient
, pt
))
673 if ((style
& WS_VSCROLL
) &&
674 ((((ex_style
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
675 (((ex_style
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
681 /* Has to return HTNOWHERE if nothing was found
682 Could happen when a window has a customized non client area */
687 /******************************************************************************
691 * Draws the system icon.
693 *****************************************************************************/
694 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
696 HICON hIcon
= NC_IconForWindow( hwnd
);
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 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
706 GetSystemMetrics(SM_CXSMICON
),
707 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
713 /******************************************************************************
717 * Draws the close button.
719 * If bGrayed is true, then draw a disabled Close button
721 *****************************************************************************/
723 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
726 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
727 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
729 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
731 /* A tool window has a smaller Close button */
732 if (ex_style
& WS_EX_TOOLWINDOW
)
734 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
735 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
736 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
738 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
739 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
740 rect
.bottom
= rect
.top
+ iBmpHeight
;
741 rect
.right
= rect
.left
+ iBmpWidth
;
745 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
746 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
750 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
752 (down
? DFCS_PUSHED
: 0) |
753 (bGrayed
? DFCS_INACTIVE
: 0)) );
756 /******************************************************************************
759 * Draws the maximize button for windows.
760 * If bGrayed is true, then draw a disabled Maximize button
762 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
766 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
767 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
769 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
770 if (ex_style
& WS_EX_TOOLWINDOW
) return;
772 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
774 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
775 if (style
& WS_SYSMENU
)
776 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
777 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
778 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
781 if (down
) flags
|= DFCS_PUSHED
;
782 if (bGrayed
) flags
|= DFCS_INACTIVE
;
783 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
786 /******************************************************************************
789 * Draws the minimize button for windows.
790 * If bGrayed is true, then draw a disabled Minimize button
792 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
795 UINT flags
= DFCS_CAPTIONMIN
;
796 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
797 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
799 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
800 if (ex_style
& WS_EX_TOOLWINDOW
) return;
802 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
803 if (style
& WS_SYSMENU
)
804 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
805 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
806 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
807 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
808 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
811 if (down
) flags
|= DFCS_PUSHED
;
812 if (bGrayed
) flags
|= DFCS_INACTIVE
;
813 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
816 /******************************************************************************
820 * Draw a window frame inside the given rectangle, and update the rectangle.
823 * Many. First, just what IS a frame in Win95? Note that the 3D look
824 * on the outer edge is handled by NC_DoNCPaint. As is the inner
825 * edge. The inner rectangle just inside the frame is handled by the
828 * In short, for most people, this function should be a nop (unless
829 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
830 * them lately, but just to get this code right). Even so, it doesn't
831 * appear to be so. It's being worked on...
833 *****************************************************************************/
835 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
839 /* Firstly the "thick" frame */
840 if (style
& WS_THICKFRAME
)
842 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
843 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
845 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
846 COLOR_INACTIVEBORDER
) );
848 PatBlt( hdc
, rect
->left
, rect
->top
,
849 rect
->right
- rect
->left
, height
, PATCOPY
);
850 PatBlt( hdc
, rect
->left
, rect
->top
,
851 width
, rect
->bottom
- rect
->top
, PATCOPY
);
852 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
853 rect
->right
- rect
->left
, -height
, PATCOPY
);
854 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
855 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
857 InflateRect( rect
, -width
, -height
);
860 /* Now the other bit of the frame */
861 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
862 (exStyle
& WS_EX_DLGMODALFRAME
))
864 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
865 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
866 /* This should give a value of 1 that should also work for a border */
868 SelectObject( hdc
, GetSysColorBrush(
869 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
871 (exStyle
& WS_EX_STATICEDGE
) ?
873 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
879 PatBlt( hdc
, rect
->left
, rect
->top
,
880 rect
->right
- rect
->left
, height
, PATCOPY
);
881 PatBlt( hdc
, rect
->left
, rect
->top
,
882 width
, rect
->bottom
- rect
->top
, PATCOPY
);
883 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
884 rect
->right
- rect
->left
, -height
, PATCOPY
);
885 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
886 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
888 InflateRect( rect
, -width
, -height
);
893 /******************************************************************************
897 * Draw the window caption for windows.
898 * The correct pen for the window frame must be selected in the DC.
900 *****************************************************************************/
902 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
903 DWORD exStyle
, BOOL active
)
909 BOOL gradient
= FALSE
;
911 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
912 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
913 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
914 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
915 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
916 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
917 SelectObject( hdc
, hPrevPen
);
920 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
921 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
923 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
924 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
925 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
928 if (style
& WS_SYSMENU
)
932 /* Go get the sysmenu */
933 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
934 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
936 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
937 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
938 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
939 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
941 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
943 /* In win95 the two buttons are always there */
944 /* But if the menu item is not in the menu they're disabled*/
946 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
947 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
949 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
950 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
954 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
956 NONCLIENTMETRICSW nclm
;
957 HFONT hFont
, hOldFont
;
958 nclm
.cbSize
= sizeof(nclm
);
959 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
960 if (exStyle
& WS_EX_TOOLWINDOW
)
961 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
963 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
964 hOldFont
= SelectObject (hdc
, hFont
);
965 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
966 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
967 SetBkMode( hdc
, TRANSPARENT
);
969 DrawTextW( hdc
, buffer
, -1, &r
,
970 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
971 DeleteObject (SelectObject (hdc
, hOldFont
));
976 /******************************************************************************
979 * Paint the non-client area for windows.
981 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
984 RECT rfuzz
, rect
, rectClip
;
987 DWORD dwStyle
, dwExStyle
;
992 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
993 dwStyle
= wndPtr
->dwStyle
;
994 dwExStyle
= wndPtr
->dwExStyle
;
995 flags
= wndPtr
->flags
;
996 WIN_ReleasePtr( wndPtr
);
998 if ( dwStyle
& WS_MINIMIZE
||
999 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1001 active
= flags
& WIN_NCACTIVATED
;
1003 TRACE("%p %d\n", hwnd
, active
);
1005 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1006 the call to GetDCEx implying that it is allowed not to use it either.
1007 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1008 will cause clipRgn to be deleted after ReleaseDC().
1009 Now, how is the "system" supposed to tell what happened?
1012 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1013 hrgn
= CreateRectRgnIndirect( &rectClient
);
1017 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1018 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1022 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1027 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1028 GetClipBox( hdc
, &rectClip
);
1030 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1032 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1033 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1035 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1036 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1039 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1041 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1044 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1045 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1046 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1049 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1050 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1052 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1053 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1056 if (HAS_MENU( hwnd
, dwStyle
))
1059 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1061 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1063 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1066 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1068 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1069 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1071 /* Draw the scroll-bars */
1073 if (dwStyle
& WS_VSCROLL
)
1074 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1075 if (dwStyle
& WS_HSCROLL
)
1076 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1078 /* Draw the "size-box" */
1079 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1082 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1083 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1085 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1086 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1087 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1090 ReleaseDC( hwnd
, hdc
);
1096 /***********************************************************************
1099 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1101 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1103 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1105 if( dwStyle
& WS_VISIBLE
)
1107 if( dwStyle
& WS_MINIMIZE
)
1108 WINPOS_RedrawIconTitle( hwnd
);
1110 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1116 /***********************************************************************
1117 * NC_HandleNCActivate
1119 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1121 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1123 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1125 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1127 /* Lotus Notes draws menu descriptions in the caption of its main
1128 * window. When it wants to restore original "system" view, it just
1129 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1130 * attempt to minimize redrawings lead to a not restored caption.
1132 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1133 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1134 WIN_ReleasePtr( wndPtr
);
1136 /* This isn't documented but is reproducible in at least XP SP2 and
1137 * Outlook 2007 depends on it
1142 WINPOS_RedrawIconTitle( hwnd
);
1144 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1151 /***********************************************************************
1152 * NC_HandleSetCursor
1154 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1156 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1158 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1160 switch((short)LOWORD(lParam
))
1164 WORD msg
= HIWORD( lParam
);
1165 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1166 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1173 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1183 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1187 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1191 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1195 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1198 /* Default cursor: arrow */
1199 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1202 /***********************************************************************
1205 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1207 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1210 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1211 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1213 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1214 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1215 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1216 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1220 /***********************************************************************
1223 * Track a mouse button press on the minimize or maximize box.
1225 * The big difference between 3.1 and 95 is the disabled button state.
1226 * In win95 the system button can be disabled, so it can ignore the mouse
1230 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1233 HDC hdc
= GetWindowDC( hwnd
);
1234 BOOL pressed
= TRUE
;
1236 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1237 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1239 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1241 if (wParam
== HTMINBUTTON
)
1243 /* If the style is not present, do nothing */
1244 if (!(wndStyle
& WS_MINIMIZEBOX
))
1247 /* Check if the sysmenu item for minimize is there */
1248 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1250 paintButton
= NC_DrawMinButton
;
1254 /* If the style is not present, do nothing */
1255 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1258 /* Check if the sysmenu item for maximize is there */
1259 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1261 paintButton
= NC_DrawMaxButton
;
1266 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1270 BOOL oldstate
= pressed
;
1272 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1273 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1275 if(msg
.message
== WM_LBUTTONUP
)
1278 if(msg
.message
!= WM_MOUSEMOVE
)
1281 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1282 if (pressed
!= oldstate
)
1283 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1287 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1290 ReleaseDC( hwnd
, hdc
);
1292 /* If the item minimize or maximize of the sysmenu are not there */
1293 /* or if the style is not present, do nothing */
1294 if ((!pressed
) || (state
== 0xFFFFFFFF))
1297 if (wParam
== HTMINBUTTON
)
1298 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1300 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1301 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1304 /***********************************************************************
1305 * NC_TrackCloseButton
1307 * Track a mouse button press on the Win95 close button.
1309 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1313 BOOL pressed
= TRUE
;
1314 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1320 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1322 /* If the item close of the sysmenu is disabled or not there do nothing */
1323 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1326 hdc
= GetWindowDC( hwnd
);
1330 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1334 BOOL oldstate
= pressed
;
1336 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1337 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1339 if(msg
.message
== WM_LBUTTONUP
)
1342 if(msg
.message
!= WM_MOUSEMOVE
)
1345 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1346 if (pressed
!= oldstate
)
1347 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1351 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1354 ReleaseDC( hwnd
, hdc
);
1355 if (!pressed
) return;
1357 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1361 /***********************************************************************
1364 * Track a mouse button press on the horizontal or vertical scroll-bar.
1366 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1370 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1372 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1373 scrollbar
= SB_HORZ
;
1375 else /* SC_VSCROLL */
1377 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1378 scrollbar
= SB_VERT
;
1380 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1384 /***********************************************************************
1385 * NC_HandleNCLButtonDown
1387 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1389 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1391 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1393 switch(wParam
) /* Hit test */
1397 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1399 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1400 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1405 if( style
& WS_SYSMENU
)
1407 if( !(style
& WS_MINIMIZE
) )
1409 HDC hDC
= GetWindowDC(hwnd
);
1410 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1411 ReleaseDC( hwnd
, hDC
);
1413 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1418 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1422 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1426 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1431 NC_TrackMinMaxBox( hwnd
, wParam
);
1435 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1447 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1448 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1450 /* But that is not what WinNT does. Instead it sends this. This
1451 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1452 * SC_MOUSEMENU into wParam.
1454 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1464 /***********************************************************************
1465 * NC_HandleNCRButtonDown
1467 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1469 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1472 INT hittest
= wParam
;
1478 if (!GetSystemMenu( hwnd
, FALSE
)) break;
1483 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1484 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1485 if (msg
.message
== WM_RBUTTONUP
)
1487 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1492 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1493 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, msg
.lParam
);
1500 /***********************************************************************
1501 * NC_HandleNCLButtonDblClk
1503 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1505 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1508 * if this is an icon, send a restore since we are handling
1513 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1517 switch(wParam
) /* Hit test */
1520 /* stop processing if WS_MAXIMIZEBOX is missing */
1521 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1522 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1523 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1528 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1529 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1531 /* If the item close of the sysmenu is disabled or not there do nothing */
1532 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1535 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1540 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1544 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1551 /***********************************************************************
1552 * NC_HandleSysCommand
1554 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1556 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1558 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1560 if (!IsWindowEnabled( hwnd
)) return 0;
1562 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1565 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1568 switch (wParam
& 0xfff0)
1572 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1576 if (hwnd
== GetActiveWindow())
1577 ShowOwnedPopups(hwnd
,FALSE
);
1578 ShowWindow( hwnd
, SW_MINIMIZE
);
1582 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1583 ShowOwnedPopups(hwnd
,TRUE
);
1584 ShowWindow( hwnd
, SW_MAXIMIZE
);
1588 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1589 ShowOwnedPopups(hwnd
,TRUE
);
1590 ShowWindow( hwnd
, SW_RESTORE
);
1594 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1600 pt
.x
= (short)LOWORD(lParam
);
1601 pt
.y
= (short)HIWORD(lParam
);
1602 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1609 pt
.x
= (short)LOWORD(lParam
);
1610 pt
.y
= (short)HIWORD(lParam
);
1611 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1616 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1620 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1624 if (wParam
== SC_ABOUTWINE
)
1626 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1629 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1631 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1632 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1633 FreeLibrary( hmodule
);
1642 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1648 /***********************************************************************
1649 * GetTitleBarInfo (USER32.@)
1650 * TODO: Handle STATE_SYSTEM_PRESSED
1652 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1656 TRACE("(%p %p)\n", hwnd
, tbi
);
1659 SetLastError(ERROR_NOACCESS
);
1663 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1664 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1665 SetLastError(ERROR_INVALID_PARAMETER
);
1668 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1669 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1670 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1672 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1673 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1674 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1676 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1677 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1680 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1681 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1682 * Under XP it seems to
1684 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1685 if(dwStyle
& WS_CAPTION
) {
1686 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1687 if(dwStyle
& WS_SYSMENU
) {
1688 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1689 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1690 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1693 if(!(dwStyle
& WS_MINIMIZEBOX
))
1694 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1695 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1696 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1698 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1699 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1700 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1701 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1704 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1705 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1706 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1707 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1711 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;