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
29 #include "user_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(nonclient
);
35 static const BYTE lpGrayMask
[] = { 0xAA, 0xA0,
46 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
47 #define SC_PUTMARK (SC_SCREENSAVE+2)
49 /* Some useful macros */
50 #define HAS_DLGFRAME(style,exStyle) \
51 (((exStyle) & WS_EX_DLGMODALFRAME) || \
52 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
54 #define HAS_THICKFRAME(style,exStyle) \
55 (((style) & WS_THICKFRAME) && \
56 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
58 #define HAS_THINFRAME(style) \
59 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
61 #define HAS_BIGFRAME(style,exStyle) \
62 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
63 ((exStyle) & WS_EX_DLGMODALFRAME))
65 #define HAS_STATICOUTERFRAME(style,exStyle) \
66 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
69 #define HAS_ANYFRAME(style,exStyle) \
70 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
71 ((exStyle) & WS_EX_DLGMODALFRAME) || \
72 !((style) & (WS_CHILD | WS_POPUP)))
74 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
77 /******************************************************************************
80 * Computes the size of the "outside" parts of the window based on the
81 * parameters of the client area.
90 * "Outer" parts of a window means the whole window frame, caption and
91 * menu bar. It does not include "inner" parts of the frame like client
92 * edge, static edge or scroll bars.
94 *****************************************************************************/
97 NC_AdjustRectOuter (LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
100 if(style
& WS_ICONIC
) return;
102 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) ==
105 adjust
= 1; /* for the outer frame always present */
110 if ((exStyle
& WS_EX_DLGMODALFRAME
) ||
111 (style
& (WS_THICKFRAME
|WS_DLGFRAME
))) adjust
= 2; /* outer */
113 if (style
& WS_THICKFRAME
)
114 adjust
+= ( GetSystemMetrics (SM_CXFRAME
)
115 - GetSystemMetrics (SM_CXDLGFRAME
)); /* The resize border */
116 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
117 (exStyle
& WS_EX_DLGMODALFRAME
))
118 adjust
++; /* The other border */
120 InflateRect (rect
, adjust
, adjust
);
122 if ((style
& WS_CAPTION
) == WS_CAPTION
)
124 if (exStyle
& WS_EX_TOOLWINDOW
)
125 rect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
127 rect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
129 if (menu
) rect
->top
-= GetSystemMetrics(SM_CYMENU
);
133 /******************************************************************************
136 * Computes the size of the "inside" part of the window based on the
137 * parameters of the client area.
145 * "Inner" part of a window means the window frame inside of the flat
146 * window frame. It includes the client edge, the static edge and the
149 *****************************************************************************/
152 NC_AdjustRectInner (LPRECT rect
, DWORD style
, DWORD exStyle
)
154 if(style
& WS_ICONIC
) return;
156 if (exStyle
& WS_EX_CLIENTEDGE
)
157 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
159 if (style
& WS_VSCROLL
)
161 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
162 rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
164 rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
166 if (style
& WS_HSCROLL
) rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
171 static HICON
NC_IconForWindow( HWND hwnd
)
174 WND
*wndPtr
= WIN_GetPtr( hwnd
);
176 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
&& wndPtr
!= WND_DESKTOP
)
178 hIcon
= wndPtr
->hIconSmall
;
179 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
180 WIN_ReleasePtr( wndPtr
);
182 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
183 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICON
);
185 /* If there is no hIcon specified and this is a modal dialog,
186 * get the default one.
188 if (!hIcon
&& (GetWindowLongW( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
189 hIcon
= LoadImageW(0, (LPCWSTR
)IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
193 /* Draws the bar part(ie the big rectangle) of the caption */
194 static void NC_DrawCaptionBar (HDC hdc
, const RECT
*rect
, DWORD dwStyle
,
195 BOOL active
, BOOL gradient
)
199 TRIVERTEX vertices
[6];
201 GetSysColor (active
? COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
);
203 GetSysColor (active
? COLOR_GRADIENTACTIVECAPTION
204 : COLOR_GRADIENTINACTIVECAPTION
);
206 int buttonsAreaSize
= GetSystemMetrics(SM_CYCAPTION
) - 1;
207 static GRADIENT_RECT mesh
[] = {{0, 1}, {2, 3}, {4, 5}};
209 for (v
= 0; v
< 3; v
++)
211 vertices
[v
].Red
= GetRValue (colLeft
) << 8;
212 vertices
[v
].Green
= GetGValue (colLeft
) << 8;
213 vertices
[v
].Blue
= GetBValue (colLeft
) << 8;
214 vertices
[v
].Alpha
= 0x8000;
215 vertices
[v
+3].Red
= GetRValue (colRight
) << 8;
216 vertices
[v
+3].Green
= GetGValue (colRight
) << 8;
217 vertices
[v
+3].Blue
= GetBValue (colRight
) << 8;
218 vertices
[v
+3].Alpha
= 0x8000;
221 if ((dwStyle
& WS_SYSMENU
)
222 && ((dwStyle
& WS_MAXIMIZEBOX
) || (dwStyle
& WS_MINIMIZEBOX
)))
223 buttonsAreaSize
+= 2 * (GetSystemMetrics(SM_CXSIZE
) + 1);
225 /* area behind icon; solid filled with left color */
226 vertices
[0].x
= rect
->left
;
227 vertices
[0].y
= rect
->top
;
228 if (dwStyle
& WS_SYSMENU
)
230 min (rect
->left
+ GetSystemMetrics(SM_CXSMICON
), rect
->right
);
232 vertices
[1].x
= vertices
[0].x
;
233 vertices
[1].y
= rect
->bottom
;
235 /* area behind text; gradient */
236 vertices
[2].x
= vertices
[1].x
;
237 vertices
[2].y
= rect
->top
;
238 vertices
[3].x
= max (vertices
[2].x
, rect
->right
- buttonsAreaSize
);
239 vertices
[3].y
= rect
->bottom
;
241 /* area behind buttons; solid filled with right color */
242 vertices
[4].x
= vertices
[3].x
;
243 vertices
[4].y
= rect
->top
;
244 vertices
[5].x
= rect
->right
;
245 vertices
[5].y
= rect
->bottom
;
247 GdiGradientFill (hdc
, vertices
, 6, mesh
, 3, GRADIENT_FILL_RECT_H
);
250 FillRect (hdc
, rect
, GetSysColorBrush (active
?
251 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
254 /***********************************************************************
255 * DrawCaption (USER32.@) Draws a caption bar
269 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
271 return DrawCaptionTempW (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x103F);
275 /***********************************************************************
276 * DrawCaptionTempA (USER32.@)
278 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
279 HICON hIcon
, LPCSTR str
, UINT uFlags
)
285 if (!(uFlags
& DC_TEXT
) || !str
)
286 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
288 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
289 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
291 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
292 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
293 HeapFree( GetProcessHeap (), 0, strW
);
299 /***********************************************************************
300 * DrawCaptionTempW (USER32.@)
302 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
303 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
307 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
308 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
310 /* drawing background */
311 if (uFlags
& DC_INBUTTON
) {
312 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
314 if (uFlags
& DC_ACTIVE
) {
315 HBRUSH hbr
= SelectObject (hdc
, SYSCOLOR_55AABrush
);
316 PatBlt (hdc
, rc
.left
, rc
.top
,
317 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
318 SelectObject (hdc
, hbr
);
322 DWORD style
= GetWindowLongW (hwnd
, GWL_STYLE
);
323 NC_DrawCaptionBar (hdc
, rect
, style
, uFlags
& DC_ACTIVE
, uFlags
& DC_GRADIENT
);
328 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
332 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
334 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
335 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
336 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
337 rc
.left
+= (rc
.bottom
- rc
.top
);
341 if (uFlags
& DC_TEXT
) {
344 if (uFlags
& DC_INBUTTON
)
345 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
346 else if (uFlags
& DC_ACTIVE
)
347 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
349 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
351 SetBkMode (hdc
, TRANSPARENT
);
354 hOldFont
= SelectObject (hdc
, hFont
);
356 NONCLIENTMETRICSW nclm
;
358 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
359 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
360 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
361 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
362 hOldFont
= SelectObject (hdc
, hNewFont
);
366 DrawTextW (hdc
, str
, -1, &rc
,
367 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
371 nLen
= GetWindowTextW (hwnd
, szText
, 128);
372 DrawTextW (hdc
, szText
, nLen
, &rc
,
373 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
377 SelectObject (hdc
, hOldFont
);
379 DeleteObject (SelectObject (hdc
, hOldFont
));
382 /* drawing focus ??? */
384 FIXME("undocumented flag (0x2000)!\n");
390 /***********************************************************************
391 * AdjustWindowRect (USER32.@)
393 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
395 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
399 /***********************************************************************
400 * AdjustWindowRectEx (USER32.@)
402 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
404 /* Correct the window style */
405 style
&= (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
| WS_CHILD
);
406 exStyle
&= (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
|
407 WS_EX_STATICEDGE
| WS_EX_TOOLWINDOW
);
408 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
410 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
411 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
412 style
, menu
, exStyle
);
414 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
415 NC_AdjustRectInner( rect
, style
, exStyle
);
421 /***********************************************************************
422 * NC_HandleNCCalcSize
424 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
426 LRESULT
NC_HandleNCCalcSize( HWND hwnd
, RECT
*winRect
)
428 RECT tmpRect
= { 0, 0, 0, 0 };
430 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
431 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
432 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
434 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
435 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
439 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
441 winRect
->left
-= tmpRect
.left
;
442 winRect
->top
-= tmpRect
.top
;
443 winRect
->right
-= tmpRect
.right
;
444 winRect
->bottom
-= tmpRect
.bottom
;
446 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
448 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
449 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
452 MENU_GetMenuBarHeight( hwnd
,
453 winRect
->right
- winRect
->left
,
454 -tmpRect
.left
, -tmpRect
.top
);
457 if( exStyle
& WS_EX_CLIENTEDGE
)
458 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
459 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
460 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
461 - GetSystemMetrics(SM_CYEDGE
));
463 if (style
& WS_VSCROLL
)
464 if( winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
)){
465 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
466 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
468 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
471 if (style
& WS_HSCROLL
)
472 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
473 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
475 if (winRect
->top
> winRect
->bottom
)
476 winRect
->bottom
= winRect
->top
;
478 if (winRect
->left
> winRect
->right
)
479 winRect
->right
= winRect
->left
;
485 /***********************************************************************
488 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
489 * but without the borders (if any).
490 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
492 static void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
494 WND
*wndPtr
= WIN_GetPtr( hwnd
);
496 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return;
498 rect
->top
= rect
->left
= 0;
499 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
500 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
502 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
504 /* Remove frame from rectangle */
505 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
507 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
509 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
511 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
513 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
515 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
518 /* We have additional border information if the window
519 * is a child (but not an MDI child) */
520 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
521 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
523 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
524 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
525 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
526 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
530 WIN_ReleasePtr( wndPtr
);
534 /***********************************************************************
537 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
539 * FIXME: Just a modified copy of the Win 3.1 version.
542 static LRESULT
NC_DoNCHitTest (WND
*wndPtr
, POINT pt
)
547 TRACE("hwnd=%p pt=%d,%d\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
549 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
550 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
552 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
554 /* Check client area */
556 ScreenToClient( wndPtr
->hwndSelf
, &ptClient
);
557 GetClientRect( wndPtr
->hwndSelf
, &rcClient
);
558 if (PtInRect( &rcClient
, ptClient
)) return HTCLIENT
;
561 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
563 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
564 if (!PtInRect( &rect
, pt
))
566 /* Check top sizing border */
569 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
570 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
573 /* Check bottom sizing border */
574 if (pt
.y
>= rect
.bottom
)
576 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
577 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
580 /* Check left sizing border */
581 if (pt
.x
< rect
.left
)
583 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
584 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
587 /* Check right sizing border */
588 if (pt
.x
>= rect
.right
)
590 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
591 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
596 else /* No thick frame */
598 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
599 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
600 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
601 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
602 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
607 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
609 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
610 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
612 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
613 if (!PtInRect( &rect
, pt
))
615 BOOL min_or_max_box
= (wndPtr
->dwStyle
& WS_MAXIMIZEBOX
) ||
616 (wndPtr
->dwStyle
& WS_MINIMIZEBOX
);
617 /* Check system menu */
618 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
620 if (NC_IconForWindow(wndPtr
->hwndSelf
))
621 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
623 if (pt
.x
< rect
.left
) return HTSYSMENU
;
625 /* Check close button */
626 if (wndPtr
->dwStyle
& WS_SYSMENU
)
627 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
628 if (pt
.x
> rect
.right
) return HTCLOSE
;
630 /* Check maximize box */
631 /* In win95 there is automatically a Maximize button when there is a minimize one*/
632 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
633 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
634 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
636 /* Check minimize box */
637 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
638 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
639 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
641 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
646 /* Check vertical scroll bar */
648 if (wndPtr
->dwStyle
& WS_VSCROLL
)
650 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
651 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
653 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
654 if (PtInRect( &rcClient
, ptClient
)) return HTVSCROLL
;
657 /* Check horizontal scroll bar */
659 if (wndPtr
->dwStyle
& WS_HSCROLL
)
661 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
662 if (PtInRect( &rcClient
, ptClient
))
665 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
666 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (ptClient
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
667 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (ptClient
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
675 if (HAS_MENU(wndPtr
))
677 if ((ptClient
.y
< 0) && (ptClient
.x
>= 0) && (ptClient
.x
< rcClient
.right
))
681 /* Has to return HTNOWHERE if nothing was found
682 Could happen when a window has a customized non client area */
687 /***********************************************************************
690 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
692 LRESULT
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
695 WND
*wndPtr
= WIN_GetPtr( hwnd
);
697 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return HTERROR
;
699 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
700 WIN_ReleasePtr( wndPtr
);
705 /******************************************************************************
709 * Draws the system icon.
711 *****************************************************************************/
712 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
714 HICON hIcon
= NC_IconForWindow( hwnd
);
719 NC_GetInsideRect( hwnd
, &rect
);
720 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
721 GetSystemMetrics(SM_CXSMICON
),
722 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
728 /******************************************************************************
732 * Draws the close button.
734 * If bGrayed is true, then draw a disabled Close button
736 *****************************************************************************/
738 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
742 NC_GetInsideRect( hwnd
, &rect
);
744 /* A tool window has a smaller Close button */
745 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
747 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
748 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
749 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
751 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
752 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
753 rect
.bottom
= rect
.top
+ iBmpHeight
;
754 rect
.right
= rect
.left
+ iBmpWidth
;
758 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
759 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
763 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
765 (down
? DFCS_PUSHED
: 0) |
766 (bGrayed
? DFCS_INACTIVE
: 0)) );
769 /******************************************************************************
772 * Draws the maximize button for windows.
773 * If bGrayed is true, then draw a disabled Maximize button
775 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
780 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
781 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
784 flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
786 NC_GetInsideRect( hwnd
, &rect
);
787 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
788 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
789 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
790 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
793 if (down
) flags
|= DFCS_PUSHED
;
794 if (bGrayed
) flags
|= DFCS_INACTIVE
;
795 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
798 /******************************************************************************
801 * Draws the minimize button for windows.
802 * If bGrayed is true, then draw a disabled Minimize button
804 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
807 UINT flags
= DFCS_CAPTIONMIN
;
808 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
810 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
811 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
814 NC_GetInsideRect( hwnd
, &rect
);
815 if (style
& WS_SYSMENU
)
816 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
817 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
818 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
819 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
820 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
823 if (down
) flags
|= DFCS_PUSHED
;
824 if (bGrayed
) flags
|= DFCS_INACTIVE
;
825 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
828 /******************************************************************************
832 * Draw a window frame inside the given rectangle, and update the rectangle.
835 * Many. First, just what IS a frame in Win95? Note that the 3D look
836 * on the outer edge is handled by NC_DoNCPaint. As is the inner
837 * edge. The inner rectangle just inside the frame is handled by the
840 * In short, for most people, this function should be a nop (unless
841 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
842 * them lately, but just to get this code right). Even so, it doesn't
843 * appear to be so. It's being worked on...
845 *****************************************************************************/
847 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
851 /* Firstly the "thick" frame */
852 if (style
& WS_THICKFRAME
)
854 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
855 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
857 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
858 COLOR_INACTIVEBORDER
) );
860 PatBlt( hdc
, rect
->left
, rect
->top
,
861 rect
->right
- rect
->left
, height
, PATCOPY
);
862 PatBlt( hdc
, rect
->left
, rect
->top
,
863 width
, rect
->bottom
- rect
->top
, PATCOPY
);
864 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
865 rect
->right
- rect
->left
, -height
, PATCOPY
);
866 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
867 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
869 InflateRect( rect
, -width
, -height
);
872 /* Now the other bit of the frame */
873 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
874 (exStyle
& WS_EX_DLGMODALFRAME
))
876 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
877 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
878 /* This should give a value of 1 that should also work for a border */
880 SelectObject( hdc
, GetSysColorBrush(
881 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
883 (exStyle
& WS_EX_STATICEDGE
) ?
885 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
891 PatBlt( hdc
, rect
->left
, rect
->top
,
892 rect
->right
- rect
->left
, height
, PATCOPY
);
893 PatBlt( hdc
, rect
->left
, rect
->top
,
894 width
, rect
->bottom
- rect
->top
, PATCOPY
);
895 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
896 rect
->right
- rect
->left
, -height
, PATCOPY
);
897 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
898 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
900 InflateRect( rect
, -width
, -height
);
905 /******************************************************************************
909 * Draw the window caption for windows.
910 * The correct pen for the window frame must be selected in the DC.
912 *****************************************************************************/
914 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
915 DWORD exStyle
, BOOL active
)
921 BOOL gradient
= FALSE
;
923 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
924 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
925 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
926 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
927 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
928 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
929 SelectObject( hdc
, hPrevPen
);
932 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS
, 0, &gradient
, 0);
933 NC_DrawCaptionBar (hdc
, rect
, style
, active
, gradient
);
935 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
936 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
937 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
940 if (style
& WS_SYSMENU
)
944 /* Go get the sysmenu */
945 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
946 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
948 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
949 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
950 (state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF));
951 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
953 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
955 /* In win95 the two buttons are always there */
956 /* But if the menu item is not in the menu they're disabled*/
958 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
959 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
961 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
962 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
966 if (GetWindowTextW( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
968 NONCLIENTMETRICSW nclm
;
969 HFONT hFont
, hOldFont
;
970 nclm
.cbSize
= sizeof(nclm
);
971 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
972 if (exStyle
& WS_EX_TOOLWINDOW
)
973 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
975 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
976 hOldFont
= SelectObject (hdc
, hFont
);
977 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
978 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
979 SetBkMode( hdc
, TRANSPARENT
);
981 DrawTextW( hdc
, buffer
, -1, &r
,
982 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
983 DeleteObject (SelectObject (hdc
, hOldFont
));
988 /******************************************************************************
991 * Paint the non-client area for windows.
993 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
996 RECT rfuzz
, rect
, rectClip
;
999 DWORD dwStyle
, dwExStyle
;
1002 RECT rectClient
, rectWindow
;
1005 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
1006 has_menu
= HAS_MENU(wndPtr
);
1007 dwStyle
= wndPtr
->dwStyle
;
1008 dwExStyle
= wndPtr
->dwExStyle
;
1009 flags
= wndPtr
->flags
;
1010 rectWindow
= wndPtr
->rectWindow
;
1011 WIN_ReleasePtr( wndPtr
);
1013 if ( dwStyle
& WS_MINIMIZE
||
1014 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
1016 active
= flags
& WIN_NCACTIVATED
;
1018 TRACE("%p %d\n", hwnd
, active
);
1020 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1021 the call to GetDCEx implying that it is allowed not to use it either.
1022 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1023 will cause clipRgn to be deleted after ReleaseDC().
1024 Now, how is the "system" supposed to tell what happened?
1027 GetClientRect( hwnd
, &rectClient
);
1028 MapWindowPoints( hwnd
, 0, (POINT
*)&rectClient
, 2 );
1029 hrgn
= CreateRectRgnIndirect( &rectClient
);
1033 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
1034 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
1038 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
1043 rect
.top
= rect
.left
= 0;
1044 rect
.right
= rectWindow
.right
- rectWindow
.left
;
1045 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
1046 GetClipBox( hdc
, &rectClip
);
1048 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1050 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1051 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1053 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1054 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1057 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1059 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1062 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1063 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1064 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1067 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1068 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1070 if( IntersectRect( &rfuzz
, &r
, &rectClip
) )
1071 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1077 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1079 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1080 r
.left
, r
.top
, r
.right
, r
.bottom
);
1082 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1085 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1086 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1088 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1089 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1091 /* Draw the scroll-bars */
1093 if (dwStyle
& WS_VSCROLL
)
1094 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1095 if (dwStyle
& WS_HSCROLL
)
1096 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1098 /* Draw the "size-box" */
1099 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1102 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1103 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1105 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1106 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1107 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1110 ReleaseDC( hwnd
, hdc
);
1116 /***********************************************************************
1119 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1121 LRESULT
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1123 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1125 if( dwStyle
& WS_VISIBLE
)
1127 if( dwStyle
& WS_MINIMIZE
)
1128 WINPOS_RedrawIconTitle( hwnd
);
1130 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1136 /***********************************************************************
1137 * NC_HandleNCActivate
1139 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1141 LRESULT
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1143 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1145 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1147 /* Lotus Notes draws menu descriptions in the caption of its main
1148 * window. When it wants to restore original "system" view, it just
1149 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1150 * attempt to minimize redrawings lead to a not restored caption.
1152 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1153 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1154 WIN_ReleasePtr( wndPtr
);
1157 WINPOS_RedrawIconTitle( hwnd
);
1159 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1165 /***********************************************************************
1166 * NC_HandleSetCursor
1168 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1170 LRESULT
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1172 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1174 switch((short)LOWORD(lParam
))
1178 WORD msg
= HIWORD( lParam
);
1179 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1180 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1187 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1197 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1201 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1205 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1209 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1212 /* Default cursor: arrow */
1213 return (LRESULT
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1216 /***********************************************************************
1219 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1221 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1224 WND
*wndPtr
= WIN_GetPtr( hwnd
);
1225 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return;
1227 NC_GetInsideRect( hwnd
, rect
);
1228 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1229 if (wndPtr
->dwStyle
& WS_CHILD
)
1230 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1231 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1232 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1233 WIN_ReleasePtr( wndPtr
);
1237 /***********************************************************************
1240 * Track a mouse button press on the minimize or maximize box.
1242 * The big difference between 3.1 and 95 is the disabled button state.
1243 * In win95 the system button can be disabled, so it can ignore the mouse
1247 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1250 HDC hdc
= GetWindowDC( hwnd
);
1251 BOOL pressed
= TRUE
;
1253 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1254 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1256 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1258 if (wParam
== HTMINBUTTON
)
1260 /* If the style is not present, do nothing */
1261 if (!(wndStyle
& WS_MINIMIZEBOX
))
1264 /* Check if the sysmenu item for minimize is there */
1265 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1267 paintButton
= &NC_DrawMinButton
;
1271 /* If the style is not present, do nothing */
1272 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1275 /* Check if the sysmenu item for maximize is there */
1276 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1278 paintButton
= &NC_DrawMaxButton
;
1283 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1287 BOOL oldstate
= pressed
;
1289 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1290 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1292 if(msg
.message
== WM_LBUTTONUP
)
1295 if(msg
.message
!= WM_MOUSEMOVE
)
1298 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1299 if (pressed
!= oldstate
)
1300 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1304 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1307 ReleaseDC( hwnd
, hdc
);
1309 /* If the item minimize or maximize of the sysmenu are not there */
1310 /* or if the style is not present, do nothing */
1311 if ((!pressed
) || (state
== 0xFFFFFFFF))
1314 if (wParam
== HTMINBUTTON
)
1315 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1317 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1318 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1321 /***********************************************************************
1322 * NC_TrackCloseButton
1324 * Track a mouse button press on the Win95 close button.
1326 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1330 BOOL pressed
= TRUE
;
1331 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1337 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1339 /* If the item close of the sysmenu is disabled or not there do nothing */
1340 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1343 hdc
= GetWindowDC( hwnd
);
1347 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1351 BOOL oldstate
= pressed
;
1353 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1354 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1356 if(msg
.message
== WM_LBUTTONUP
)
1359 if(msg
.message
!= WM_MOUSEMOVE
)
1362 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1363 if (pressed
!= oldstate
)
1364 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1368 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1371 ReleaseDC( hwnd
, hdc
);
1372 if (!pressed
) return;
1374 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1378 /***********************************************************************
1381 * Track a mouse button press on the horizontal or vertical scroll-bar.
1383 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1387 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1389 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1390 scrollbar
= SB_HORZ
;
1392 else /* SC_VSCROLL */
1394 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1395 scrollbar
= SB_VERT
;
1397 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1401 /***********************************************************************
1402 * NC_HandleNCLButtonDown
1404 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1406 LRESULT
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1408 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1410 switch(wParam
) /* Hit test */
1414 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1416 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1417 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1422 if( style
& WS_SYSMENU
)
1424 if( !(style
& WS_MINIMIZE
) )
1426 HDC hDC
= GetWindowDC(hwnd
);
1427 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1428 ReleaseDC( hwnd
, hDC
);
1430 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1435 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1439 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1443 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1448 NC_TrackMinMaxBox( hwnd
, wParam
);
1452 NC_TrackCloseButton (hwnd
, wParam
);
1464 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1465 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1467 /* But that is not what WinNT does. Instead it sends this. This
1468 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1469 * SC_MOUSEMENU into wParam.
1471 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1481 /***********************************************************************
1482 * NC_HandleNCLButtonDblClk
1484 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1486 LRESULT
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1489 * if this is an icon, send a restore since we are handling
1494 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1498 switch(wParam
) /* Hit test */
1501 /* stop processing if WS_MAXIMIZEBOX is missing */
1502 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1503 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1504 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1509 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1510 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1512 /* If the item close of the sysmenu is disabled or not there do nothing */
1513 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1516 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1521 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1525 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1532 /***********************************************************************
1533 * NC_HandleSysCommand
1535 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1537 LRESULT
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1539 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd
, wParam
, lParam
);
1541 if (!IsWindowEnabled( hwnd
)) return 0;
1543 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1546 switch (wParam
& 0xfff0)
1550 USER_Driver
->pSysCommandSizeMove( hwnd
, wParam
);
1554 if (hwnd
== GetForegroundWindow())
1555 ShowOwnedPopups(hwnd
,FALSE
);
1556 ShowWindow( hwnd
, SW_MINIMIZE
);
1560 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1561 ShowOwnedPopups(hwnd
,TRUE
);
1562 ShowWindow( hwnd
, SW_MAXIMIZE
);
1566 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1567 ShowOwnedPopups(hwnd
,TRUE
);
1568 ShowWindow( hwnd
, SW_RESTORE
);
1572 return SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
1578 pt
.x
= (short)LOWORD(lParam
);
1579 pt
.y
= (short)HIWORD(lParam
);
1580 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1587 pt
.x
= (short)LOWORD(lParam
);
1588 pt
.y
= (short)HIWORD(lParam
);
1589 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1594 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1598 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1602 if (wParam
== SC_ABOUTWINE
)
1604 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1607 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1608 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1609 FreeLibrary( hmodule
);
1613 if (wParam
== SC_PUTMARK
)
1614 DPRINTF("Debug mark requested by user\n");
1621 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam
);
1627 /***********************************************************************
1628 * GetTitleBarInfo (USER32.@)
1629 * TODO: Handle STATE_SYSTEM_PRESSED
1631 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1636 TRACE("(%p %p)\n", hwnd
, tbi
);
1638 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1639 TRACE("Invalid TITLEBARINFO size: %d\n", tbi
->cbSize
);
1640 SetLastError(ERROR_INVALID_PARAMETER
);
1643 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1644 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1645 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1647 GetWindowRect(hwnd
, &wndRect
);
1649 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1650 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1651 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1653 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1654 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1655 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1657 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1658 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1661 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1662 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1663 * Under XP it seems to
1665 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1666 if(dwStyle
& WS_CAPTION
) {
1667 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1668 if(dwStyle
& WS_SYSMENU
) {
1669 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1670 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1671 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1674 if(!(dwStyle
& WS_MINIMIZEBOX
))
1675 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1676 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1677 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1679 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1680 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1681 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1682 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1685 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1686 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1687 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1688 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1692 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;