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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/winuser16.h"
31 #include "user_private.h"
34 #include "cursoricon.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(nonclient
);
40 WINE_DECLARE_DEBUG_CHANNEL(shell
);
42 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
);
44 static const BYTE lpGrayMask
[] = { 0xAA, 0xA0,
55 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
56 #define SC_PUTMARK (SC_SCREENSAVE+2)
58 /* Some useful macros */
59 #define HAS_DLGFRAME(style,exStyle) \
60 (((exStyle) & WS_EX_DLGMODALFRAME) || \
61 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
63 #define HAS_THICKFRAME(style,exStyle) \
64 (((style) & WS_THICKFRAME) && \
65 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
67 #define HAS_THINFRAME(style) \
68 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
70 #define HAS_BIGFRAME(style,exStyle) \
71 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
72 ((exStyle) & WS_EX_DLGMODALFRAME))
74 #define HAS_STATICOUTERFRAME(style,exStyle) \
75 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
78 #define HAS_ANYFRAME(style,exStyle) \
79 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
80 ((exStyle) & WS_EX_DLGMODALFRAME) || \
81 !((style) & (WS_CHILD | WS_POPUP)))
83 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
86 /******************************************************************************
89 * Computes the size of the "outside" parts of the window based on the
90 * parameters of the client area.
99 * "Outer" parts of a window means the whole window frame, caption and
100 * menu bar. It does not include "inner" parts of the frame like client
101 * edge, static edge or scroll bars.
103 *****************************************************************************/
106 NC_AdjustRectOuter (LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
109 if(style
& WS_ICONIC
) return;
111 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) ==
114 adjust
= 1; /* for the outer frame always present */
119 if ((exStyle
& WS_EX_DLGMODALFRAME
) ||
120 (style
& (WS_THICKFRAME
|WS_DLGFRAME
))) adjust
= 2; /* outer */
122 if (style
& WS_THICKFRAME
)
123 adjust
+= ( GetSystemMetrics (SM_CXFRAME
)
124 - GetSystemMetrics (SM_CXDLGFRAME
)); /* The resize border */
125 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
126 (exStyle
& WS_EX_DLGMODALFRAME
))
127 adjust
++; /* The other border */
129 InflateRect (rect
, adjust
, adjust
);
131 if ((style
& WS_CAPTION
) == WS_CAPTION
)
133 if (exStyle
& WS_EX_TOOLWINDOW
)
134 rect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
136 rect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
138 if (menu
) rect
->top
-= GetSystemMetrics(SM_CYMENU
);
142 /******************************************************************************
145 * Computes the size of the "inside" part of the window based on the
146 * parameters of the client area.
154 * "Inner" part of a window means the window frame inside of the flat
155 * window frame. It includes the client edge, the static edge and the
158 *****************************************************************************/
161 NC_AdjustRectInner (LPRECT rect
, DWORD style
, DWORD exStyle
)
163 if(style
& WS_ICONIC
) return;
165 if (exStyle
& WS_EX_CLIENTEDGE
)
166 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
168 if (style
& WS_VSCROLL
)
170 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
171 rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
173 rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
175 if (style
& WS_HSCROLL
) rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
180 static HICON
NC_IconForWindow( HWND hwnd
)
183 WND
*wndPtr
= WIN_GetPtr( hwnd
);
185 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
)
187 hIcon
= wndPtr
->hIconSmall
;
188 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
189 WIN_ReleasePtr( wndPtr
);
191 if (!hIcon
) hIcon
= (HICON
) GetClassLongA( hwnd
, GCL_HICONSM
);
192 if (!hIcon
) hIcon
= (HICON
) GetClassLongA( hwnd
, GCL_HICON
);
194 /* If there is no hIcon specified and this is a modal dialog,
195 * get the default one.
197 if (!hIcon
&& (GetWindowLongA( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
198 hIcon
= LoadImageA(0, (LPSTR
)IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
202 /***********************************************************************
203 * DrawCaption (USER32.@) Draws a caption bar
217 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
219 return DrawCaptionTempA (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x1F);
223 /***********************************************************************
224 * DrawCaptionTempA (USER32.@)
226 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
227 HICON hIcon
, LPCSTR str
, UINT uFlags
)
233 if (!(uFlags
& DC_TEXT
) || !str
)
234 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
236 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
237 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
239 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
240 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
241 HeapFree( GetProcessHeap (), 0, strW
);
247 /***********************************************************************
248 * DrawCaptionTempW (USER32.@)
250 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
251 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
255 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
256 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
258 /* drawing background */
259 if (uFlags
& DC_INBUTTON
) {
260 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
262 if (uFlags
& DC_ACTIVE
) {
263 HBRUSH hbr
= SelectObject (hdc
, UITOOLS_GetPattern55AABrush ());
264 PatBlt (hdc
, rc
.left
, rc
.top
,
265 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
266 SelectObject (hdc
, hbr
);
270 FillRect (hdc
, &rc
, GetSysColorBrush ((uFlags
& DC_ACTIVE
) ?
271 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
276 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
280 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
282 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
283 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
284 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
285 rc
.left
+= (rc
.bottom
- rc
.top
);
289 if (uFlags
& DC_TEXT
) {
292 if (uFlags
& DC_INBUTTON
)
293 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
294 else if (uFlags
& DC_ACTIVE
)
295 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
297 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
299 SetBkMode (hdc
, TRANSPARENT
);
302 hOldFont
= SelectObject (hdc
, hFont
);
304 NONCLIENTMETRICSW nclm
;
306 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
307 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
308 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
309 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
310 hOldFont
= SelectObject (hdc
, hNewFont
);
314 DrawTextW (hdc
, str
, -1, &rc
,
315 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
319 nLen
= GetWindowTextW (hwnd
, szText
, 128);
320 DrawTextW (hdc
, szText
, nLen
, &rc
,
321 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
325 SelectObject (hdc
, hOldFont
);
327 DeleteObject (SelectObject (hdc
, hOldFont
));
330 /* drawing focus ??? */
332 FIXME("undocumented flag (0x2000)!\n");
338 /***********************************************************************
339 * AdjustWindowRect (USER32.@)
341 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
343 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
347 /***********************************************************************
348 * AdjustWindowRectEx (USER32.@)
350 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
352 /* Correct the window style */
353 style
&= (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
| WS_CHILD
);
354 exStyle
&= (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
|
355 WS_EX_STATICEDGE
| WS_EX_TOOLWINDOW
);
356 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
358 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
359 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
360 style
, menu
, exStyle
);
362 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
363 NC_AdjustRectInner( rect
, style
, exStyle
);
369 /***********************************************************************
370 * NC_HandleNCCalcSize
372 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
374 LONG
NC_HandleNCCalcSize( HWND hwnd
, RECT
*winRect
)
376 RECT tmpRect
= { 0, 0, 0, 0 };
378 LONG cls_style
= GetClassLongA(hwnd
, GCL_STYLE
);
379 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
380 LONG exStyle
= GetWindowLongA( hwnd
, GWL_EXSTYLE
);
382 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
383 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
387 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
389 winRect
->left
-= tmpRect
.left
;
390 winRect
->top
-= tmpRect
.top
;
391 winRect
->right
-= tmpRect
.right
;
392 winRect
->bottom
-= tmpRect
.bottom
;
394 if (!(style
& WS_CHILD
) && GetMenu(hwnd
))
396 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
397 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
400 MENU_GetMenuBarHeight( hwnd
,
401 winRect
->right
- winRect
->left
,
402 -tmpRect
.left
, -tmpRect
.top
) + 1;
405 SetRect(&tmpRect
, 0, 0, 0, 0);
406 NC_AdjustRectInner (&tmpRect
, style
, exStyle
);
407 winRect
->left
-= tmpRect
.left
;
408 winRect
->top
-= tmpRect
.top
;
409 winRect
->right
-= tmpRect
.right
;
410 winRect
->bottom
-= tmpRect
.bottom
;
412 if (winRect
->top
> winRect
->bottom
)
413 winRect
->bottom
= winRect
->top
;
415 if (winRect
->left
> winRect
->right
)
416 winRect
->right
= winRect
->left
;
422 /***********************************************************************
425 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
426 * but without the borders (if any).
427 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
429 static void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
431 WND
*wndPtr
= WIN_GetPtr( hwnd
);
433 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
435 rect
->top
= rect
->left
= 0;
436 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
437 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
439 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
441 /* Remove frame from rectangle */
442 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
444 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
446 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
448 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
450 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
452 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
455 /* We have additional border information if the window
456 * is a child (but not an MDI child) */
457 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
458 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
460 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
461 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
462 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
463 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
467 WIN_ReleasePtr( wndPtr
);
471 /***********************************************************************
474 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
476 * FIXME: Just a modified copy of the Win 3.1 version.
479 static LONG
NC_DoNCHitTest (WND
*wndPtr
, POINT pt
)
484 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
486 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
487 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
489 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
491 /* Check client area */
493 ScreenToClient( wndPtr
->hwndSelf
, &ptClient
);
494 GetClientRect( wndPtr
->hwndSelf
, &rcClient
);
495 if (PtInRect( &rcClient
, ptClient
)) return HTCLIENT
;
498 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
500 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
501 if (!PtInRect( &rect
, pt
))
503 /* Check top sizing border */
506 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
507 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
510 /* Check bottom sizing border */
511 if (pt
.y
>= rect
.bottom
)
513 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
514 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
517 /* Check left sizing border */
518 if (pt
.x
< rect
.left
)
520 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
521 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
524 /* Check right sizing border */
525 if (pt
.x
>= rect
.right
)
527 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
528 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
533 else /* No thick frame */
535 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
536 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
537 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
538 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
539 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
544 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
546 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
547 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
549 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
550 if (!PtInRect( &rect
, pt
))
552 BOOL min_or_max_box
= (wndPtr
->dwStyle
& WS_MAXIMIZEBOX
) ||
553 (wndPtr
->dwStyle
& WS_MINIMIZEBOX
);
554 /* Check system menu */
555 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
557 if (NC_IconForWindow(wndPtr
->hwndSelf
))
558 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
560 if (pt
.x
< rect
.left
) return HTSYSMENU
;
562 /* Check close button */
563 if (wndPtr
->dwStyle
& WS_SYSMENU
)
564 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
565 if (pt
.x
> rect
.right
) return HTCLOSE
;
567 /* Check maximize box */
568 /* In win95 there is automatically a Maximize button when there is a minimize one*/
569 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
570 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
571 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
573 /* Check minimize box */
574 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
575 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
576 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
578 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
583 /* Check vertical scroll bar */
585 if (wndPtr
->dwStyle
& WS_VSCROLL
)
587 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
588 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
590 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
591 if (PtInRect( &rcClient
, ptClient
)) return HTVSCROLL
;
594 /* Check horizontal scroll bar */
596 if (wndPtr
->dwStyle
& WS_HSCROLL
)
598 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
599 if (PtInRect( &rcClient
, ptClient
))
602 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
603 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (ptClient
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
604 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (ptClient
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
612 if (HAS_MENU(wndPtr
))
614 if ((ptClient
.y
< 0) && (ptClient
.x
>= 0) && (ptClient
.x
< rcClient
.right
))
618 /* Has to return HTNOWHERE if nothing was found
619 Could happen when a window has a customized non client area */
624 /***********************************************************************
627 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
629 LONG
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
632 WND
*wndPtr
= WIN_GetPtr( hwnd
);
634 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return HTERROR
;
636 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
637 WIN_ReleasePtr( wndPtr
);
642 /******************************************************************************
646 * Draws the system icon.
648 *****************************************************************************/
649 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
651 HICON hIcon
= NC_IconForWindow( hwnd
);
656 NC_GetInsideRect( hwnd
, &rect
);
657 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
658 GetSystemMetrics(SM_CXSMICON
),
659 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
665 /******************************************************************************
669 * Draws the close button.
671 * If bGrayed is true, then draw a disabled Close button
673 *****************************************************************************/
675 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
679 NC_GetInsideRect( hwnd
, &rect
);
681 /* A tool window has a smaller Close button */
682 if (GetWindowLongA( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
684 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
685 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
686 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
688 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
689 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
690 rect
.bottom
= rect
.top
+ iBmpHeight
;
691 rect
.right
= rect
.left
+ iBmpWidth
;
695 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
696 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
700 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
702 (down
? DFCS_PUSHED
: 0) |
703 (bGrayed
? DFCS_INACTIVE
: 0)) );
706 /******************************************************************************
709 * Draws the maximize button for windows.
710 * If bGrayed is true, then draw a disabled Maximize button
712 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
717 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
718 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
721 flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
723 NC_GetInsideRect( hwnd
, &rect
);
724 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
725 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
726 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
727 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
730 if (down
) flags
|= DFCS_PUSHED
;
731 if (bGrayed
) flags
|= DFCS_INACTIVE
;
732 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
735 /******************************************************************************
738 * Draws the minimize button for windows.
739 * If bGrayed is true, then draw a disabled Minimize button
741 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
744 UINT flags
= DFCS_CAPTIONMIN
;
745 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
747 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
748 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
751 NC_GetInsideRect( hwnd
, &rect
);
752 if (style
& WS_SYSMENU
)
753 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
754 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
755 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
756 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
757 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
760 if (down
) flags
|= DFCS_PUSHED
;
761 if (bGrayed
) flags
|= DFCS_INACTIVE
;
762 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
765 /******************************************************************************
769 * Draw a window frame inside the given rectangle, and update the rectangle.
772 * Many. First, just what IS a frame in Win95? Note that the 3D look
773 * on the outer edge is handled by NC_DoNCPaint. As is the inner
774 * edge. The inner rectangle just inside the frame is handled by the
777 * In short, for most people, this function should be a nop (unless
778 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
779 * them lately, but just to get this code right). Even so, it doesn't
780 * appear to be so. It's being worked on...
782 *****************************************************************************/
784 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
788 /* Firstly the "thick" frame */
789 if (style
& WS_THICKFRAME
)
791 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
792 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
794 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
795 COLOR_INACTIVEBORDER
) );
797 PatBlt( hdc
, rect
->left
, rect
->top
,
798 rect
->right
- rect
->left
, height
, PATCOPY
);
799 PatBlt( hdc
, rect
->left
, rect
->top
,
800 width
, rect
->bottom
- rect
->top
, PATCOPY
);
801 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
802 rect
->right
- rect
->left
, -height
, PATCOPY
);
803 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
804 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
806 InflateRect( rect
, -width
, -height
);
809 /* Now the other bit of the frame */
810 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
811 (exStyle
& WS_EX_DLGMODALFRAME
))
813 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
814 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
815 /* This should give a value of 1 that should also work for a border */
817 SelectObject( hdc
, GetSysColorBrush(
818 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
820 (exStyle
& WS_EX_STATICEDGE
) ?
822 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
828 PatBlt( hdc
, rect
->left
, rect
->top
,
829 rect
->right
- rect
->left
, height
, PATCOPY
);
830 PatBlt( hdc
, rect
->left
, rect
->top
,
831 width
, rect
->bottom
- rect
->top
, PATCOPY
);
832 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
833 rect
->right
- rect
->left
, -height
, PATCOPY
);
834 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
835 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
837 InflateRect( rect
, -width
, -height
);
842 /******************************************************************************
846 * Draw the window caption for windows.
847 * The correct pen for the window frame must be selected in the DC.
849 *****************************************************************************/
851 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
852 DWORD exStyle
, BOOL active
)
859 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
860 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
861 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
862 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
863 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
864 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
865 SelectObject( hdc
, hPrevPen
);
868 FillRect( hdc
, &r
, GetSysColorBrush(active
? COLOR_ACTIVECAPTION
:
869 COLOR_INACTIVECAPTION
) );
871 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
872 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
873 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
876 if (style
& WS_SYSMENU
)
880 /* Go get the sysmenu */
881 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
882 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
884 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
885 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
886 ((((state
& MF_DISABLED
) || (state
& MF_GRAYED
))) && (state
!= 0xFFFFFFFF)));
887 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
889 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
891 /* In win95 the two buttons are always there */
892 /* But if the menu item is not in the menu they're disabled*/
894 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
895 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
897 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
898 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
902 if (InternalGetWindowText( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
904 NONCLIENTMETRICSW nclm
;
905 HFONT hFont
, hOldFont
;
906 nclm
.cbSize
= sizeof(nclm
);
907 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
908 if (exStyle
& WS_EX_TOOLWINDOW
)
909 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
911 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
912 hOldFont
= SelectObject (hdc
, hFont
);
913 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
914 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
915 SetBkMode( hdc
, TRANSPARENT
);
917 DrawTextW( hdc
, buffer
, -1, &r
,
918 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
919 DeleteObject (SelectObject (hdc
, hOldFont
));
924 /******************************************************************************
928 * Paint the non-client area for windows. The clip region is
932 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
933 * misc/tweak.c controls/menu.c # :-)
935 *****************************************************************************/
937 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
940 RECT rfuzz
, rect
, rectClip
;
943 DWORD dwStyle
, dwExStyle
;
946 RECT rectClient
, rectWindow
;
949 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
950 has_menu
= HAS_MENU(wndPtr
);
951 dwStyle
= wndPtr
->dwStyle
;
952 dwExStyle
= wndPtr
->dwExStyle
;
953 flags
= wndPtr
->flags
;
954 rectClient
= wndPtr
->rectClient
;
955 rectWindow
= wndPtr
->rectWindow
;
956 WIN_ReleasePtr( wndPtr
);
958 if ( dwStyle
& WS_MINIMIZE
||
959 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
961 active
= flags
& WIN_NCACTIVATED
;
963 TRACE("%p %d\n", hwnd
, active
);
965 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
966 the call to GetDCEx implying that it is allowed not to use it either.
967 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
968 will cause clipRgn to be deleted after ReleaseDC().
969 Now, how is the "system" supposed to tell what happened?
972 hrgn
= CreateRectRgn( rectClient
.left
- rectWindow
.left
,
973 rectClient
.top
- rectWindow
.top
,
974 rectClient
.right
- rectWindow
.left
,
975 rectClient
.bottom
- rectWindow
.top
);
978 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
979 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
983 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
988 rect
.top
= rect
.left
= 0;
989 rect
.right
= rectWindow
.right
- rectWindow
.left
;
990 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
993 GetRgnBox( clip
, &rectClip
);
1000 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1002 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1003 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1005 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1006 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1009 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1011 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1014 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1015 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1016 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1019 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1020 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1022 if( !clip
|| IntersectRect( &rfuzz
, &r
, &rectClip
) )
1023 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1029 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1031 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1032 r
.left
, r
.top
, r
.right
, r
.bottom
);
1034 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1037 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1038 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1040 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1041 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1043 /* Draw the scroll-bars */
1045 if (dwStyle
& WS_VSCROLL
)
1046 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1047 if (dwStyle
& WS_HSCROLL
)
1048 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1050 /* Draw the "size-box" */
1051 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1054 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1055 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1057 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1058 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1059 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1062 ReleaseDC( hwnd
, hdc
);
1068 /***********************************************************************
1071 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1073 LONG
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1075 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1077 if( dwStyle
& WS_VISIBLE
)
1079 if( dwStyle
& WS_MINIMIZE
)
1080 WINPOS_RedrawIconTitle( hwnd
);
1082 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1088 /***********************************************************************
1089 * NC_HandleNCActivate
1091 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1093 LONG
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1095 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1097 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1099 /* Lotus Notes draws menu descriptions in the caption of its main
1100 * window. When it wants to restore original "system" view, it just
1101 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1102 * attempt to minimize redrawings lead to a not restored caption.
1104 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1105 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1106 WIN_ReleasePtr( wndPtr
);
1109 WINPOS_RedrawIconTitle( hwnd
);
1111 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1117 /***********************************************************************
1118 * NC_HandleSetCursor
1120 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1122 LONG
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1124 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1126 switch((short)LOWORD(lParam
))
1130 WORD msg
= HIWORD( lParam
);
1131 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1132 (msg
== WM_RBUTTONDOWN
))
1139 HCURSOR hCursor
= (HCURSOR
)GetClassLongA(hwnd
, GCL_HCURSOR
);
1149 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1153 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1157 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1161 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1164 /* Default cursor: arrow */
1165 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1168 /***********************************************************************
1171 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1173 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1176 WND
*wndPtr
= WIN_GetPtr( hwnd
);
1177 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
1179 NC_GetInsideRect( hwnd
, rect
);
1180 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1181 if (wndPtr
->dwStyle
& WS_CHILD
)
1182 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1183 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1184 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1185 WIN_ReleasePtr( wndPtr
);
1189 /***********************************************************************
1192 * Track a mouse button press on the minimize or maximize box.
1194 * The big difference between 3.1 and 95 is the disabled button state.
1195 * In win95 the system button can be disabled, so it can ignore the mouse
1199 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1202 HDC hdc
= GetWindowDC( hwnd
);
1203 BOOL pressed
= TRUE
;
1205 DWORD wndStyle
= GetWindowLongA( hwnd
, GWL_STYLE
);
1206 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1208 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1210 if (wParam
== HTMINBUTTON
)
1212 /* If the style is not present, do nothing */
1213 if (!(wndStyle
& WS_MINIMIZEBOX
))
1216 /* Check if the sysmenu item for minimize is there */
1217 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1219 paintButton
= &NC_DrawMinButton
;
1223 /* If the style is not present, do nothing */
1224 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1227 /* Check if the sysmenu item for maximize is there */
1228 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1230 paintButton
= &NC_DrawMaxButton
;
1235 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1239 BOOL oldstate
= pressed
;
1241 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1242 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1244 if(msg
.message
== WM_LBUTTONUP
)
1247 if(msg
.message
!= WM_MOUSEMOVE
)
1250 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1251 if (pressed
!= oldstate
)
1252 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1256 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1259 ReleaseDC( hwnd
, hdc
);
1261 /* If the item minimize or maximize of the sysmenu are not there */
1262 /* or if the style is not present, do nothing */
1263 if ((!pressed
) || (state
== 0xFFFFFFFF))
1266 if (wParam
== HTMINBUTTON
)
1267 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1269 SendMessageA( hwnd
, WM_SYSCOMMAND
,
1270 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1273 /***********************************************************************
1274 * NC_TrackCloseButton
1276 * Track a mouse button press on the Win95 close button.
1278 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1282 BOOL pressed
= TRUE
;
1283 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1289 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1291 /* If the item close of the sysmenu is disabled or not there do nothing */
1292 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1295 hdc
= GetWindowDC( hwnd
);
1299 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1303 BOOL oldstate
= pressed
;
1305 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1306 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1308 if(msg
.message
== WM_LBUTTONUP
)
1311 if(msg
.message
!= WM_MOUSEMOVE
)
1314 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1315 if (pressed
!= oldstate
)
1316 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1320 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1323 ReleaseDC( hwnd
, hdc
);
1324 if (!pressed
) return;
1326 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1330 /***********************************************************************
1333 * Track a mouse button press on the horizontal or vertical scroll-bar.
1335 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1339 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1341 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1342 scrollbar
= SB_HORZ
;
1344 else /* SC_VSCROLL */
1346 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1347 scrollbar
= SB_VERT
;
1349 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1353 /***********************************************************************
1354 * NC_HandleNCLButtonDown
1356 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1358 LONG
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1360 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1362 switch(wParam
) /* Hit test */
1366 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1368 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1369 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1374 if( style
& WS_SYSMENU
)
1376 if( !(style
& WS_MINIMIZE
) )
1378 HDC hDC
= GetWindowDC(hwnd
);
1379 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1380 ReleaseDC( hwnd
, hDC
);
1382 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1387 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1391 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1395 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1400 NC_TrackMinMaxBox( hwnd
, wParam
);
1404 NC_TrackCloseButton (hwnd
, wParam
);
1416 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1417 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1419 /* But that is not what WinNT does. Instead it sends this. This
1420 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1421 * SC_MOUSEMENU into wParam.
1423 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1433 /***********************************************************************
1434 * NC_HandleNCLButtonDblClk
1436 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1438 LONG
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1441 * if this is an icon, send a restore since we are handling
1446 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1450 switch(wParam
) /* Hit test */
1453 /* stop processing if WS_MAXIMIZEBOX is missing */
1454 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1455 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1456 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1460 if (!(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
))
1461 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1465 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1469 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1476 /***********************************************************************
1477 * NC_HandleSysCommand
1479 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1481 LONG
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1483 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam
, lParam
);
1485 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1488 switch (wParam
& 0xfff0)
1492 if (USER_Driver
.pSysCommandSizeMove
)
1493 USER_Driver
.pSysCommandSizeMove( hwnd
, wParam
);
1497 if (hwnd
== GetForegroundWindow())
1498 ShowOwnedPopups(hwnd
,FALSE
);
1499 ShowWindow( hwnd
, SW_MINIMIZE
);
1503 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1504 ShowOwnedPopups(hwnd
,TRUE
);
1505 ShowWindow( hwnd
, SW_MAXIMIZE
);
1509 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1510 ShowOwnedPopups(hwnd
,TRUE
);
1511 ShowWindow( hwnd
, SW_RESTORE
);
1515 return SendMessageA( hwnd
, WM_CLOSE
, 0, 0 );
1521 pt
.x
= (short)LOWORD(lParam
);
1522 pt
.y
= (short)HIWORD(lParam
);
1523 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1530 pt
.x
= (short)LOWORD(lParam
);
1531 pt
.y
= (short)HIWORD(lParam
);
1532 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1537 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1541 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1545 if (wParam
== SC_ABOUTWINE
)
1547 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1550 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1551 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1552 FreeLibrary( hmodule
);
1556 if (wParam
== SC_PUTMARK
)
1557 DPRINTF("Debug mark requested by user\n");
1564 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam
);
1570 /*************************************************************
1573 * Stub for the grayed button of the caption
1575 *************************************************************/
1577 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
)
1583 hMaskBmp
= CreateBitmap (12, 10, 1, 1, lpGrayMask
);
1588 hdcMask
= CreateCompatibleDC (0);
1589 SelectObject (hdcMask
, hMaskBmp
);
1591 /* Draw the grayed bitmap using the mask */
1592 hOldBrush
= SelectObject (hdc
, (HGDIOBJ
)RGB(128, 128, 128));
1593 BitBlt (hdc
, x
, y
, 12, 10,
1594 hdcMask
, 0, 0, 0xB8074A);
1597 SelectObject (hdc
, hOldBrush
);
1598 DeleteObject(hMaskBmp
);
1604 /***********************************************************************
1605 * GetTitleBarInfo (USER32.@)
1606 * TODO: Handle STATE_SYSTEM_PRESSED
1608 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1613 TRACE("(%p %p)\n", hwnd
, tbi
);
1615 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1616 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi
->cbSize
);
1617 SetLastError(ERROR_INVALID_PARAMETER
);
1620 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1621 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1622 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1624 GetWindowRect(hwnd
, &wndRect
);
1626 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1627 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1628 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1630 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1631 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1632 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1634 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1635 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1638 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1639 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1640 * Under XP it seems to
1642 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1643 if(dwStyle
& WS_CAPTION
) {
1644 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1645 if(dwStyle
& WS_SYSMENU
) {
1646 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1647 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1648 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1651 if(!(dwStyle
& WS_MINIMIZEBOX
))
1652 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1653 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1654 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1656 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1657 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1658 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1659 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1662 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1663 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1664 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1665 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1669 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;