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_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
);
700 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
701 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
703 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
704 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
705 GetSystemMetrics(SM_CXSMICON
),
706 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
712 /******************************************************************************
716 * Draws the close button.
718 * If bGrayed is true, then draw a disabled Close button
720 *****************************************************************************/
722 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
725 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
726 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
728 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
730 /* A tool window has a smaller Close button */
731 if (ex_style
& WS_EX_TOOLWINDOW
)
733 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
734 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
735 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
737 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
738 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
739 rect
.bottom
= rect
.top
+ iBmpHeight
;
740 rect
.right
= rect
.left
+ iBmpWidth
;
744 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
745 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
749 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
751 (down
? DFCS_PUSHED
: 0) |
752 (bGrayed
? DFCS_INACTIVE
: 0)) );
755 /******************************************************************************
758 * Draws the maximize button for windows.
759 * If bGrayed is true, then draw a disabled Maximize button
761 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
765 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
766 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
768 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
769 if (ex_style
& WS_EX_TOOLWINDOW
) return;
771 flags
= (style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
773 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
774 if (style
& WS_SYSMENU
)
775 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
776 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
777 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
780 if (down
) flags
|= DFCS_PUSHED
;
781 if (bGrayed
) flags
|= DFCS_INACTIVE
;
782 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
785 /******************************************************************************
788 * Draws the minimize button for windows.
789 * If bGrayed is true, then draw a disabled Minimize button
791 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
794 UINT flags
= DFCS_CAPTIONMIN
;
795 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
796 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
798 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
799 if (ex_style
& WS_EX_TOOLWINDOW
) return;
801 NC_GetInsideRect( hwnd
, COORDS_WINDOW
, &rect
, style
, ex_style
);
802 if (style
& WS_SYSMENU
)
803 rect
.right
-= GetSystemMetrics(SM_CXSIZE
);
804 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
805 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
806 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
807 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 2;
810 if (down
) flags
|= DFCS_PUSHED
;
811 if (bGrayed
) flags
|= DFCS_INACTIVE
;
812 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
815 /******************************************************************************
819 * Draw a window frame inside the given rectangle, and update the rectangle.
822 * Many. First, just what IS a frame in Win95? Note that the 3D look
823 * on the outer edge is handled by NC_DoNCPaint. As is the inner
824 * edge. The inner rectangle just inside the frame is handled by the
827 * In short, for most people, this function should be a nop (unless
828 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
829 * them lately, but just to get this code right). Even so, it doesn't
830 * appear to be so. It's being worked on...
832 *****************************************************************************/
834 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
838 /* Firstly the "thick" frame */
839 if (style
& WS_THICKFRAME
)
841 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
842 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
844 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
845 COLOR_INACTIVEBORDER
) );
847 PatBlt( hdc
, rect
->left
, rect
->top
,
848 rect
->right
- rect
->left
, height
, PATCOPY
);
849 PatBlt( hdc
, rect
->left
, rect
->top
,
850 width
, rect
->bottom
- rect
->top
, PATCOPY
);
851 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
852 rect
->right
- rect
->left
, -height
, PATCOPY
);
853 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
854 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
856 InflateRect( rect
, -width
, -height
);
859 /* Now the other bit of the frame */
860 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
861 (exStyle
& WS_EX_DLGMODALFRAME
))
863 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
864 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
865 /* This should give a value of 1 that should also work for a border */
867 SelectObject( hdc
, GetSysColorBrush(
868 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
870 (exStyle
& WS_EX_STATICEDGE
) ?
872 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
878 PatBlt( hdc
, rect
->left
, rect
->top
,
879 rect
->right
- rect
->left
, height
, PATCOPY
);
880 PatBlt( hdc
, rect
->left
, rect
->top
,
881 width
, rect
->bottom
- rect
->top
, PATCOPY
);
882 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
883 rect
->right
- rect
->left
, -height
, PATCOPY
);
884 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
885 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
887 InflateRect( rect
, -width
, -height
);
892 /******************************************************************************
896 * Draw the window caption for windows.
897 * The correct pen for the window frame must be selected in the DC.
899 *****************************************************************************/
901 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
902 DWORD exStyle
, BOOL active
)
908 BOOL gradient
= FALSE
;
910 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
911 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
912 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
913 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
914 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
915 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
916 SelectObject( hdc
, hPrevPen
);
919 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
920 NC_DrawCaptionBar (hdc
, &r
, style
, active
, gradient
);
922 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
923 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
924 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
927 if (style
& WS_SYSMENU
)
931 /* Go get the sysmenu */
932 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
933 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
935 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
936 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
937 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
938 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
940 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
942 /* In win95 the two buttons are always there */
943 /* But if the menu item is not in the menu they're disabled*/
945 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
946 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
948 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
949 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
953 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
955 NONCLIENTMETRICSW nclm
;
956 HFONT hFont
, hOldFont
;
957 nclm
.cbSize
= sizeof(nclm
);
958 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
959 if (exStyle
& WS_EX_TOOLWINDOW
)
960 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
962 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
963 hOldFont
= SelectObject (hdc
, hFont
);
964 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
965 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
966 SetBkMode( hdc
, TRANSPARENT
);
968 DrawTextW( hdc
, buffer
, -1, &r
,
969 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
970 DeleteObject (SelectObject (hdc
, hOldFont
));
975 /******************************************************************************
978 * Paint the non-client area for windows.
980 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
983 RECT rfuzz
, rect
, rectClip
;
986 DWORD dwStyle
, dwExStyle
;
991 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
992 dwStyle
= wndPtr
->dwStyle
;
993 dwExStyle
= wndPtr
->dwExStyle
;
994 flags
= wndPtr
->flags
;
995 WIN_ReleasePtr( wndPtr
);
997 if ( dwStyle
& WS_MINIMIZE
||
998 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1000 active
= flags
& WIN_NCACTIVATED
;
1002 TRACE("%p %d\n", hwnd
, active
);
1004 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1005 the call to GetDCEx implying that it is allowed not to use it either.
1006 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1007 will cause clipRgn to be deleted after ReleaseDC().
1008 Now, how is the "system" supposed to tell what happened?
1011 WIN_GetRectangles( hwnd
, COORDS_SCREEN
, NULL
, &rectClient
);
1012 hrgn
= CreateRectRgnIndirect( &rectClient
);
1016 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1017 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1021 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1026 WIN_GetRectangles( hwnd
, COORDS_WINDOW
, &rect
, NULL
);
1027 GetClipBox( hdc
, &rectClip
);
1029 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1031 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1032 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1034 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1035 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1038 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1040 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1043 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1044 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1045 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1048 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1049 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1051 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1052 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1055 if (HAS_MENU( hwnd
, dwStyle
))
1058 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1060 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r
));
1062 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1065 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect
));
1067 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1068 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1070 /* Draw the scroll-bars */
1072 if (dwStyle
& WS_VSCROLL
)
1073 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1074 if (dwStyle
& WS_HSCROLL
)
1075 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1077 /* Draw the "size-box" */
1078 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1081 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1082 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1084 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1085 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1086 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1089 ReleaseDC( hwnd
, hdc
);
1095 /***********************************************************************
1098 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1100 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1102 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1104 if( dwStyle
& WS_VISIBLE
)
1106 if( dwStyle
& WS_MINIMIZE
)
1107 WINPOS_RedrawIconTitle( hwnd
);
1109 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1115 /***********************************************************************
1116 * NC_HandleNCActivate
1118 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1120 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1122 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1124 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1126 /* Lotus Notes draws menu descriptions in the caption of its main
1127 * window. When it wants to restore original "system" view, it just
1128 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1129 * attempt to minimize redrawings lead to a not restored caption.
1131 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1132 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1133 WIN_ReleasePtr( wndPtr
);
1135 /* This isn't documented but is reproducible in at least XP SP2 and
1136 * Outlook 2007 depends on it
1141 WINPOS_RedrawIconTitle( hwnd
);
1143 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1150 /***********************************************************************
1151 * NC_HandleSetCursor
1153 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1155 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1157 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1159 switch((short)LOWORD(lParam
))
1163 WORD msg
= HIWORD( lParam
);
1164 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1165 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1172 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1182 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1186 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1190 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1194 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1197 /* Default cursor: arrow */
1198 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1201 /***********************************************************************
1204 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1206 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1209 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1210 DWORD ex_style
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
1212 NC_GetInsideRect( hwnd
, COORDS_CLIENT
, rect
, style
, ex_style
);
1213 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1214 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1215 MapWindowPoints( hwnd
, 0, (POINT
*)rect
, 2 );
1219 /***********************************************************************
1222 * Track a mouse button press on the minimize or maximize box.
1224 * The big difference between 3.1 and 95 is the disabled button state.
1225 * In win95 the system button can be disabled, so it can ignore the mouse
1229 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1232 HDC hdc
= GetWindowDC( hwnd
);
1233 BOOL pressed
= TRUE
;
1235 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1236 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1238 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1240 if (wParam
== HTMINBUTTON
)
1242 /* If the style is not present, do nothing */
1243 if (!(wndStyle
& WS_MINIMIZEBOX
))
1246 /* Check if the sysmenu item for minimize is there */
1247 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1249 paintButton
= NC_DrawMinButton
;
1253 /* If the style is not present, do nothing */
1254 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1257 /* Check if the sysmenu item for maximize is there */
1258 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1260 paintButton
= NC_DrawMaxButton
;
1265 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1269 BOOL oldstate
= pressed
;
1271 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1272 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1274 if(msg
.message
== WM_LBUTTONUP
)
1277 if(msg
.message
!= WM_MOUSEMOVE
)
1280 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1281 if (pressed
!= oldstate
)
1282 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1286 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1289 ReleaseDC( hwnd
, hdc
);
1291 /* If the item minimize or maximize of the sysmenu are not there */
1292 /* or if the style is not present, do nothing */
1293 if ((!pressed
) || (state
== 0xFFFFFFFF))
1296 if (wParam
== HTMINBUTTON
)
1297 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1299 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1300 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1303 /***********************************************************************
1304 * NC_TrackCloseButton
1306 * Track a mouse button press on the Win95 close button.
1308 static void NC_TrackCloseButton (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1312 BOOL pressed
= TRUE
;
1313 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1319 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1321 /* If the item close of the sysmenu is disabled or not there do nothing */
1322 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1325 hdc
= GetWindowDC( hwnd
);
1329 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1333 BOOL oldstate
= pressed
;
1335 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1336 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1338 if(msg
.message
== WM_LBUTTONUP
)
1341 if(msg
.message
!= WM_MOUSEMOVE
)
1344 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1345 if (pressed
!= oldstate
)
1346 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1350 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1353 ReleaseDC( hwnd
, hdc
);
1354 if (!pressed
) return;
1356 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1360 /***********************************************************************
1363 * Track a mouse button press on the horizontal or vertical scroll-bar.
1365 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1369 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1371 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1372 scrollbar
= SB_HORZ
;
1374 else /* SC_VSCROLL */
1376 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1377 scrollbar
= SB_VERT
;
1379 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1383 /***********************************************************************
1384 * NC_HandleNCLButtonDown
1386 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1388 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1390 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1392 switch(wParam
) /* Hit test */
1396 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1398 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1399 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1404 if( style
& WS_SYSMENU
)
1406 if( !(style
& WS_MINIMIZE
) )
1408 HDC hDC
= GetWindowDC(hwnd
);
1409 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1410 ReleaseDC( hwnd
, hDC
);
1412 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1417 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1421 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1425 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1430 NC_TrackMinMaxBox( hwnd
, wParam
);
1434 NC_TrackCloseButton (hwnd
, wParam
, lParam
);
1446 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1447 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1449 /* But that is not what WinNT does. Instead it sends this. This
1450 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1451 * SC_MOUSEMENU into wParam.
1453 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1463 /***********************************************************************
1464 * NC_HandleNCRButtonDown
1466 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1468 LRESULT
NC_HandleNCRButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1471 INT hittest
= wParam
;
1477 if (!GetSystemMenu( hwnd
, FALSE
)) break;
1482 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1483 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1484 if (msg
.message
== WM_RBUTTONUP
)
1486 hittest
= NC_HandleNCHitTest( hwnd
, msg
.pt
);
1491 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
)
1492 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, msg
.lParam
);
1499 /***********************************************************************
1500 * NC_HandleNCLButtonDblClk
1502 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1504 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1507 * if this is an icon, send a restore since we are handling
1512 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1516 switch(wParam
) /* Hit test */
1519 /* stop processing if WS_MAXIMIZEBOX is missing */
1520 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1521 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1522 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1527 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1528 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1530 /* If the item close of the sysmenu is disabled or not there do nothing */
1531 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1534 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1539 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1543 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1550 /***********************************************************************
1551 * NC_HandleSysCommand
1553 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1555 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1557 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1559 if (!IsWindowEnabled( hwnd
)) return 0;
1561 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1564 if (!USER_Driver
->pSysCommand( hwnd
, wParam
, lParam
))
1567 switch (wParam
& 0xfff0)
1571 WINPOS_SysCommandSizeMove( hwnd
, wParam
);
1575 if (hwnd
== GetActiveWindow())
1576 ShowOwnedPopups(hwnd
,FALSE
);
1577 ShowWindow( hwnd
, SW_MINIMIZE
);
1581 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1582 ShowOwnedPopups(hwnd
,TRUE
);
1583 ShowWindow( hwnd
, SW_MAXIMIZE
);
1587 if (IsIconic(hwnd
) && hwnd
== GetActiveWindow())
1588 ShowOwnedPopups(hwnd
,TRUE
);
1589 ShowWindow( hwnd
, SW_RESTORE
);
1593 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1599 pt
.x
= (short)LOWORD(lParam
);
1600 pt
.y
= (short)HIWORD(lParam
);
1601 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1608 pt
.x
= (short)LOWORD(lParam
);
1609 pt
.y
= (short)HIWORD(lParam
);
1610 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1615 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1619 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1623 if (wParam
== SC_ABOUTWINE
)
1625 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1628 BOOL (WINAPI
*aboutproc
)(HWND
, LPCSTR
, LPCSTR
, HICON
);
1630 aboutproc
= (void *)GetProcAddress( hmodule
, "ShellAboutA" );
1631 if (aboutproc
) aboutproc( hwnd
, PACKAGE_STRING
, NULL
, 0 );
1632 FreeLibrary( hmodule
);
1641 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1647 /***********************************************************************
1648 * GetTitleBarInfo (USER32.@)
1649 * TODO: Handle STATE_SYSTEM_PRESSED
1651 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1655 TRACE("(%p %p)\n", hwnd
, tbi
);
1658 SetLastError(ERROR_NOACCESS
);
1662 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1663 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1664 SetLastError(ERROR_INVALID_PARAMETER
);
1667 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1668 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1669 NC_GetInsideRect(hwnd
, COORDS_SCREEN
, &tbi
->rcTitleBar
, dwStyle
, dwExStyle
);
1671 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1672 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1673 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1675 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1676 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1679 ZeroMemory(tbi
->rgstate
, sizeof(tbi
->rgstate
));
1680 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1681 * Under XP it seems to
1683 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1684 if(dwStyle
& WS_CAPTION
) {
1685 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1686 if(dwStyle
& WS_SYSMENU
) {
1687 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1688 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1689 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1692 if(!(dwStyle
& WS_MINIMIZEBOX
))
1693 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1694 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1695 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1697 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1698 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1699 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1700 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1703 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1704 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1705 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1706 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1710 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;