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"
34 #include "cursoricon.h"
36 #include "nonclient.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(nonclient
);
41 WINE_DECLARE_DEBUG_CHANNEL(shell
);
43 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
);
45 static const BYTE lpGrayMask
[] = { 0xAA, 0xA0,
56 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
57 #define SC_PUTMARK (SC_SCREENSAVE+2)
59 /* Some useful macros */
60 #define HAS_DLGFRAME(style,exStyle) \
61 (((exStyle) & WS_EX_DLGMODALFRAME) || \
62 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
64 #define HAS_THICKFRAME(style,exStyle) \
65 (((style) & WS_THICKFRAME) && \
66 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
68 #define HAS_THINFRAME(style) \
69 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
71 #define HAS_BIGFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME))
75 #define HAS_STATICOUTERFRAME(style,exStyle) \
76 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
79 #define HAS_ANYFRAME(style,exStyle) \
80 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
81 ((exStyle) & WS_EX_DLGMODALFRAME) || \
82 !((style) & (WS_CHILD | WS_POPUP)))
84 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
87 /******************************************************************************
90 * Computes the size of the "outside" parts of the window based on the
91 * parameters of the client area.
100 * "Outer" parts of a window means the whole window frame, caption and
101 * menu bar. It does not include "inner" parts of the frame like client
102 * edge, static edge or scroll bars.
104 *****************************************************************************/
107 NC_AdjustRectOuter (LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
110 if(style
& WS_ICONIC
) return;
112 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) ==
115 adjust
= 1; /* for the outer frame always present */
120 if ((exStyle
& WS_EX_DLGMODALFRAME
) ||
121 (style
& (WS_THICKFRAME
|WS_DLGFRAME
))) adjust
= 2; /* outer */
123 if (style
& WS_THICKFRAME
)
124 adjust
+= ( GetSystemMetrics (SM_CXFRAME
)
125 - GetSystemMetrics (SM_CXDLGFRAME
)); /* The resize border */
126 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
127 (exStyle
& WS_EX_DLGMODALFRAME
))
128 adjust
++; /* The other border */
130 InflateRect (rect
, adjust
, adjust
);
132 if ((style
& WS_CAPTION
) == WS_CAPTION
)
134 if (exStyle
& WS_EX_TOOLWINDOW
)
135 rect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
137 rect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
139 if (menu
) rect
->top
-= GetSystemMetrics(SM_CYMENU
);
143 /******************************************************************************
146 * Computes the size of the "inside" part of the window based on the
147 * parameters of the client area.
155 * "Inner" part of a window means the window frame inside of the flat
156 * window frame. It includes the client edge, the static edge and the
159 *****************************************************************************/
162 NC_AdjustRectInner (LPRECT rect
, DWORD style
, DWORD exStyle
)
164 if(style
& WS_ICONIC
) return;
166 if (exStyle
& WS_EX_CLIENTEDGE
)
167 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
169 if (style
& WS_VSCROLL
)
171 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
172 rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
174 rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
176 if (style
& WS_HSCROLL
) rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
181 static HICON
NC_IconForWindow( HWND hwnd
)
184 WND
*wndPtr
= WIN_GetPtr( hwnd
);
186 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
)
188 hIcon
= wndPtr
->hIconSmall
;
189 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
190 WIN_ReleasePtr( wndPtr
);
192 if (!hIcon
) hIcon
= (HICON
) GetClassLongA( hwnd
, GCL_HICONSM
);
193 if (!hIcon
) hIcon
= (HICON
) GetClassLongA( hwnd
, GCL_HICON
);
195 /* If there is no hIcon specified and this is a modal dialog,
196 * get the default one.
198 if (!hIcon
&& (GetWindowLongA( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
199 hIcon
= LoadImageA(0, (LPSTR
)IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
203 /***********************************************************************
204 * DrawCaption (USER32.@) Draws a caption bar
218 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
220 return DrawCaptionTempA (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x1F);
224 /***********************************************************************
225 * DrawCaptionTempA (USER32.@)
227 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
228 HICON hIcon
, LPCSTR str
, UINT uFlags
)
234 if (!(uFlags
& DC_TEXT
) || !str
)
235 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
237 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
238 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
240 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
241 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
242 HeapFree( GetProcessHeap (), 0, strW
);
248 /***********************************************************************
249 * DrawCaptionTempW (USER32.@)
251 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
252 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
256 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
257 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
259 /* drawing background */
260 if (uFlags
& DC_INBUTTON
) {
261 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
263 if (uFlags
& DC_ACTIVE
) {
264 HBRUSH hbr
= SelectObject (hdc
, UITOOLS_GetPattern55AABrush ());
265 PatBlt (hdc
, rc
.left
, rc
.top
,
266 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
267 SelectObject (hdc
, hbr
);
271 FillRect (hdc
, &rc
, GetSysColorBrush ((uFlags
& DC_ACTIVE
) ?
272 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
277 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
281 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
283 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
284 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
285 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
286 rc
.left
+= (rc
.bottom
- rc
.top
);
290 if (uFlags
& DC_TEXT
) {
293 if (uFlags
& DC_INBUTTON
)
294 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
295 else if (uFlags
& DC_ACTIVE
)
296 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
298 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
300 SetBkMode (hdc
, TRANSPARENT
);
303 hOldFont
= SelectObject (hdc
, hFont
);
305 NONCLIENTMETRICSW nclm
;
307 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
308 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
309 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
310 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
311 hOldFont
= SelectObject (hdc
, hNewFont
);
315 DrawTextW (hdc
, str
, -1, &rc
,
316 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
320 nLen
= GetWindowTextW (hwnd
, szText
, 128);
321 DrawTextW (hdc
, szText
, nLen
, &rc
,
322 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
326 SelectObject (hdc
, hOldFont
);
328 DeleteObject (SelectObject (hdc
, hOldFont
));
331 /* drawing focus ??? */
333 FIXME("undocumented flag (0x2000)!\n");
339 /***********************************************************************
340 * AdjustWindowRect (USER32.@)
342 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
344 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
348 /***********************************************************************
349 * AdjustWindowRectEx (USER32.@)
351 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
353 /* Correct the window style */
354 style
&= (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
| WS_CHILD
);
355 exStyle
&= (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
|
356 WS_EX_STATICEDGE
| WS_EX_TOOLWINDOW
);
357 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
359 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
360 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
361 style
, menu
, exStyle
);
363 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
364 NC_AdjustRectInner( rect
, style
, exStyle
);
370 /***********************************************************************
371 * NC_HandleNCCalcSize
373 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
375 LONG
NC_HandleNCCalcSize( HWND hwnd
, RECT
*winRect
)
377 RECT tmpRect
= { 0, 0, 0, 0 };
379 LONG cls_style
= GetClassLongA(hwnd
, GCL_STYLE
);
380 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
381 LONG exStyle
= GetWindowLongA( hwnd
, GWL_EXSTYLE
);
383 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
384 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
388 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
390 winRect
->left
-= tmpRect
.left
;
391 winRect
->top
-= tmpRect
.top
;
392 winRect
->right
-= tmpRect
.right
;
393 winRect
->bottom
-= tmpRect
.bottom
;
395 if (!(style
& WS_CHILD
) && GetMenu(hwnd
))
397 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
398 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
401 MENU_GetMenuBarHeight( hwnd
,
402 winRect
->right
- winRect
->left
,
403 -tmpRect
.left
, -tmpRect
.top
) + 1;
406 SetRect(&tmpRect
, 0, 0, 0, 0);
407 NC_AdjustRectInner (&tmpRect
, style
, exStyle
);
408 winRect
->left
-= tmpRect
.left
;
409 winRect
->top
-= tmpRect
.top
;
410 winRect
->right
-= tmpRect
.right
;
411 winRect
->bottom
-= tmpRect
.bottom
;
413 if (winRect
->top
> winRect
->bottom
)
414 winRect
->bottom
= winRect
->top
;
416 if (winRect
->left
> winRect
->right
)
417 winRect
->right
= winRect
->left
;
423 /***********************************************************************
426 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
427 * but without the borders (if any).
428 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
430 void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
432 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
434 rect
->top
= rect
->left
= 0;
435 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
436 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
438 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
440 /* Remove frame from rectangle */
441 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
443 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
445 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
447 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
449 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
451 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
454 /* We have additional border information if the window
455 * is a child (but not an MDI child) */
456 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
457 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
459 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
460 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
461 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
462 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
466 WIN_ReleaseWndPtr(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
)
483 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
485 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
486 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
488 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
491 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
493 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
494 if (!PtInRect( &rect
, pt
))
496 /* Check top sizing border */
499 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
500 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
503 /* Check bottom sizing border */
504 if (pt
.y
>= rect
.bottom
)
506 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
507 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
510 /* Check left sizing border */
511 if (pt
.x
< rect
.left
)
513 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
514 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
517 /* Check right sizing border */
518 if (pt
.x
>= rect
.right
)
520 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
521 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
526 else /* No thick frame */
528 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
529 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
530 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
531 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
532 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
537 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
539 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
540 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
542 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
543 if (!PtInRect( &rect
, pt
))
545 /* Check system menu */
546 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
548 if (NC_IconForWindow(wndPtr
->hwndSelf
))
549 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
551 if (pt
.x
< rect
.left
) return HTSYSMENU
;
553 /* Check close button */
554 if (wndPtr
->dwStyle
& WS_SYSMENU
)
555 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
556 if (pt
.x
> rect
.right
) return HTCLOSE
;
558 /* Check maximize box */
559 /* In win95 there is automatically a Maximize button when there is a minimize one*/
560 if ((wndPtr
->dwStyle
& WS_MAXIMIZEBOX
)|| (wndPtr
->dwStyle
& WS_MINIMIZEBOX
))
561 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
562 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
564 /* Check minimize box */
565 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
566 if ((wndPtr
->dwStyle
& WS_MINIMIZEBOX
)||(wndPtr
->dwStyle
& WS_MAXIMIZEBOX
))
567 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
569 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
574 /* Check client area */
576 ScreenToClient( wndPtr
->hwndSelf
, &pt
);
577 GetClientRect( wndPtr
->hwndSelf
, &rect
);
578 if (PtInRect( &rect
, pt
)) return HTCLIENT
;
580 /* Check vertical scroll bar */
582 if (wndPtr
->dwStyle
& WS_VSCROLL
)
584 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
585 rect
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
587 rect
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
588 if (PtInRect( &rect
, pt
)) return HTVSCROLL
;
591 /* Check horizontal scroll bar */
593 if (wndPtr
->dwStyle
& WS_HSCROLL
)
595 rect
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
596 if (PtInRect( &rect
, pt
))
599 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
600 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rect
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
601 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rect
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
609 if (HAS_MENU(wndPtr
))
611 if ((pt
.y
< 0) && (pt
.x
>= 0) && (pt
.x
< rect
.right
))
615 /* Has to return HTNOWHERE if nothing was found
616 Could happen when a window has a customized non client area */
621 /***********************************************************************
624 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
626 LONG
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
629 WND
*wndPtr
= WIN_FindWndPtr (hwnd
);
634 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
635 WIN_ReleaseWndPtr(wndPtr
);
640 /******************************************************************************
644 * Draws the system icon.
646 *****************************************************************************/
647 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
649 HICON hIcon
= NC_IconForWindow( hwnd
);
654 NC_GetInsideRect( hwnd
, &rect
);
655 DrawIconEx (hdc
, rect
.left
+ 1, rect
.top
+ 1, hIcon
,
656 GetSystemMetrics(SM_CXSIZE
) - 1,
657 GetSystemMetrics(SM_CYSIZE
) - 1, 0, 0, DI_NORMAL
);
663 /******************************************************************************
667 * Draws the close button.
669 * If bGrayed is true, then draw a disabled Close button
671 *****************************************************************************/
673 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
677 NC_GetInsideRect( hwnd
, &rect
);
679 /* A tool window has a smaller Close button */
680 if (GetWindowLongA( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
682 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
683 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
684 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
686 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
687 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
688 rect
.bottom
= rect
.top
+ iBmpHeight
;
689 rect
.right
= rect
.left
+ iBmpWidth
;
693 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
694 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
698 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
700 (down
? DFCS_PUSHED
: 0) |
701 (bGrayed
? DFCS_INACTIVE
: 0)) );
704 /******************************************************************************
707 * Draws the maximize button for windows.
708 * If bGrayed is true, then draw a disabled Maximize button
710 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
713 UINT flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
715 NC_GetInsideRect( hwnd
, &rect
);
716 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
717 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
718 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
719 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
722 if (down
) flags
|= DFCS_PUSHED
;
723 if (bGrayed
) flags
|= DFCS_INACTIVE
;
724 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
727 /******************************************************************************
730 * Draws the minimize button for windows.
731 * If bGrayed is true, then draw a disabled Minimize button
733 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
736 UINT flags
= DFCS_CAPTIONMIN
;
737 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
739 NC_GetInsideRect( hwnd
, &rect
);
740 if (style
& WS_SYSMENU
)
741 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
742 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
743 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
744 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
745 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
748 if (down
) flags
|= DFCS_PUSHED
;
749 if (bGrayed
) flags
|= DFCS_INACTIVE
;
750 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
753 /******************************************************************************
757 * Draw a window frame inside the given rectangle, and update the rectangle.
760 * Many. First, just what IS a frame in Win95? Note that the 3D look
761 * on the outer edge is handled by NC_DoNCPaint. As is the inner
762 * edge. The inner rectangle just inside the frame is handled by the
765 * In short, for most people, this function should be a nop (unless
766 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
767 * them lately, but just to get this code right). Even so, it doesn't
768 * appear to be so. It's being worked on...
770 *****************************************************************************/
772 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
776 /* Firstly the "thick" frame */
777 if (style
& WS_THICKFRAME
)
779 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
780 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
782 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
783 COLOR_INACTIVEBORDER
) );
785 PatBlt( hdc
, rect
->left
, rect
->top
,
786 rect
->right
- rect
->left
, height
, PATCOPY
);
787 PatBlt( hdc
, rect
->left
, rect
->top
,
788 width
, rect
->bottom
- rect
->top
, PATCOPY
);
789 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
790 rect
->right
- rect
->left
, -height
, PATCOPY
);
791 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
792 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
794 InflateRect( rect
, -width
, -height
);
797 /* Now the other bit of the frame */
798 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
799 (exStyle
& WS_EX_DLGMODALFRAME
))
801 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
802 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
803 /* This should give a value of 1 that should also work for a border */
805 SelectObject( hdc
, GetSysColorBrush(
806 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
808 (exStyle
& WS_EX_STATICEDGE
) ?
810 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
816 PatBlt( hdc
, rect
->left
, rect
->top
,
817 rect
->right
- rect
->left
, height
, PATCOPY
);
818 PatBlt( hdc
, rect
->left
, rect
->top
,
819 width
, rect
->bottom
- rect
->top
, PATCOPY
);
820 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
821 rect
->right
- rect
->left
, -height
, PATCOPY
);
822 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
823 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
825 InflateRect( rect
, -width
, -height
);
830 /******************************************************************************
834 * Draw the window caption for windows.
835 * The correct pen for the window frame must be selected in the DC.
837 *****************************************************************************/
839 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
840 DWORD exStyle
, BOOL active
)
847 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
848 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
849 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
850 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
851 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
852 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
853 SelectObject( hdc
, hPrevPen
);
856 FillRect( hdc
, &r
, GetSysColorBrush(active
? COLOR_ACTIVECAPTION
:
857 COLOR_INACTIVECAPTION
) );
859 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
860 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
861 r
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
864 if (style
& WS_SYSMENU
)
868 /* Go get the sysmenu */
869 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
870 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
872 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
873 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
874 ((((state
& MF_DISABLED
) || (state
& MF_GRAYED
))) && (state
!= 0xFFFFFFFF)));
875 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
877 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
879 /* In win95 the two buttons are always there */
880 /* But if the menu item is not in the menu they're disabled*/
882 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
883 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
885 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
886 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
890 if (InternalGetWindowText( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
892 NONCLIENTMETRICSW nclm
;
893 HFONT hFont
, hOldFont
;
894 nclm
.cbSize
= sizeof(nclm
);
895 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
896 if (exStyle
& WS_EX_TOOLWINDOW
)
897 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
899 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
900 hOldFont
= SelectObject (hdc
, hFont
);
901 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
902 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
903 SetBkMode( hdc
, TRANSPARENT
);
905 DrawTextW( hdc
, buffer
, -1, &r
,
906 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
907 DeleteObject (SelectObject (hdc
, hOldFont
));
912 /******************************************************************************
916 * Paint the non-client area for windows. The clip region is
920 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
921 * misc/tweak.c controls/menu.c # :-)
923 *****************************************************************************/
925 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
928 RECT rfuzz
, rect
, rectClip
;
931 DWORD dwStyle
, dwExStyle
;
933 RECT rectClient
, rectWindow
;
936 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
937 has_menu
= HAS_MENU(wndPtr
);
938 dwStyle
= wndPtr
->dwStyle
;
939 dwExStyle
= wndPtr
->dwExStyle
;
940 flags
= wndPtr
->flags
;
941 rectClient
= wndPtr
->rectClient
;
942 rectWindow
= wndPtr
->rectWindow
;
943 WIN_ReleasePtr( wndPtr
);
945 if ( dwStyle
& WS_MINIMIZE
||
946 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
948 active
= flags
& WIN_NCACTIVATED
;
950 TRACE("%p %d\n", hwnd
, active
);
952 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
953 the call to GetDCEx implying that it is allowed not to use it either.
954 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
955 will cause clipRgn to be deleted after ReleaseDC().
956 Now, how is the "system" supposed to tell what happened?
959 if (!(hdc
= GetDCEx( hwnd
, (clip
> (HRGN
)1) ? clip
: 0, DCX_USESTYLE
| DCX_WINDOW
|
960 ((clip
> (HRGN
)1) ?(DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
) : 0) ))) return;
963 if (ExcludeVisRect16( HDC_16(hdc
), rectClient
.left
-rectWindow
.left
,
964 rectClient
.top
-rectWindow
.top
,
965 rectClient
.right
-rectWindow
.left
,
966 rectClient
.bottom
-rectWindow
.top
)
969 ReleaseDC( hwnd
, hdc
);
973 rect
.top
= rect
.left
= 0;
974 rect
.right
= rectWindow
.right
- rectWindow
.left
;
975 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
978 GetRgnBox( clip
, &rectClip
);
985 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
987 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
988 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
990 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
991 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
994 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
996 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
999 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1000 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1001 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1004 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1005 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1007 if( !clip
|| IntersectRect( &rfuzz
, &r
, &rectClip
) )
1008 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1014 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1016 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1017 r
.left
, r
.top
, r
.right
, r
.bottom
);
1019 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1022 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1023 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1025 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1026 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1028 /* Draw the scroll-bars */
1030 if (dwStyle
& WS_VSCROLL
)
1031 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1032 if (dwStyle
& WS_HSCROLL
)
1033 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1035 /* Draw the "size-box" */
1036 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1039 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1040 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1042 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1043 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1044 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1047 ReleaseDC( hwnd
, hdc
);
1053 /***********************************************************************
1056 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1058 LONG
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1060 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1062 if( dwStyle
& WS_VISIBLE
)
1064 if( dwStyle
& WS_MINIMIZE
)
1065 WINPOS_RedrawIconTitle( hwnd
);
1067 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1073 /***********************************************************************
1074 * NC_HandleNCActivate
1076 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1078 LONG
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1080 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1082 /* Lotus Notes draws menu descriptions in the caption of its main
1083 * window. When it wants to restore original "system" view, it just
1084 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1085 * attempt to minimize redrawings lead to a not restored caption.
1089 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1090 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1091 WIN_ReleaseWndPtr(wndPtr
);
1094 WINPOS_RedrawIconTitle( hwnd
);
1096 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1102 /***********************************************************************
1103 * NC_HandleSetCursor
1105 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1107 LONG
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1109 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1111 switch((short)LOWORD(lParam
))
1115 WORD msg
= HIWORD( lParam
);
1116 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1117 (msg
== WM_RBUTTONDOWN
))
1124 HCURSOR hCursor
= (HCURSOR
)GetClassLongA(hwnd
, GCL_HCURSOR
);
1134 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1138 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1142 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1146 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1149 /* Default cursor: arrow */
1150 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1153 /***********************************************************************
1156 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1158 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1161 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1162 if (!wndPtr
) return;
1164 NC_GetInsideRect( hwnd
, rect
);
1165 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1166 if (wndPtr
->dwStyle
& WS_CHILD
)
1167 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1168 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1169 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1170 WIN_ReleaseWndPtr( wndPtr
);
1174 /***********************************************************************
1177 * Track a mouse button press on the minimize or maximize box.
1179 * The big difference between 3.1 and 95 is the disabled button state.
1180 * In win95 the system button can be disabled, so it can ignore the mouse
1184 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1187 HDC hdc
= GetWindowDC( hwnd
);
1188 BOOL pressed
= TRUE
;
1190 DWORD wndStyle
= GetWindowLongA( hwnd
, GWL_STYLE
);
1191 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1193 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1195 if (wParam
== HTMINBUTTON
)
1197 /* If the style is not present, do nothing */
1198 if (!(wndStyle
& WS_MINIMIZEBOX
))
1201 /* Check if the sysmenu item for minimize is there */
1202 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1204 paintButton
= &NC_DrawMinButton
;
1208 /* If the style is not present, do nothing */
1209 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1212 /* Check if the sysmenu item for maximize is there */
1213 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1215 paintButton
= &NC_DrawMaxButton
;
1220 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1224 BOOL oldstate
= pressed
;
1226 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1227 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1229 if(msg
.message
== WM_LBUTTONUP
)
1232 if(msg
.message
!= WM_MOUSEMOVE
)
1235 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1236 if (pressed
!= oldstate
)
1237 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1241 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1244 ReleaseDC( hwnd
, hdc
);
1246 /* If the item minimize or maximize of the sysmenu are not there */
1247 /* or if the style is not present, do nothing */
1248 if ((!pressed
) || (state
== 0xFFFFFFFF))
1251 if (wParam
== HTMINBUTTON
)
1252 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1254 SendMessageA( hwnd
, WM_SYSCOMMAND
,
1255 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1258 /***********************************************************************
1259 * NC_TrackCloseButton
1261 * Track a mouse button press on the Win95 close button.
1263 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1267 BOOL pressed
= TRUE
;
1268 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1274 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1276 /* If the item close of the sysmenu is disabled or not there do nothing */
1277 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1280 hdc
= GetWindowDC( hwnd
);
1284 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1288 BOOL oldstate
= pressed
;
1290 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1291 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1293 if(msg
.message
== WM_LBUTTONUP
)
1296 if(msg
.message
!= WM_MOUSEMOVE
)
1299 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1300 if (pressed
!= oldstate
)
1301 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1305 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1308 ReleaseDC( hwnd
, hdc
);
1309 if (!pressed
) return;
1311 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1315 /***********************************************************************
1318 * Track a mouse button press on the horizontal or vertical scroll-bar.
1320 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1324 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1326 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1327 scrollbar
= SB_HORZ
;
1329 else /* SC_VSCROLL */
1331 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1332 scrollbar
= SB_VERT
;
1334 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1338 /***********************************************************************
1339 * NC_HandleNCLButtonDown
1341 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1343 LONG
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1345 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1347 switch(wParam
) /* Hit test */
1351 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1353 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1354 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1359 if( style
& WS_SYSMENU
)
1361 if( !(style
& WS_MINIMIZE
) )
1363 HDC hDC
= GetWindowDC(hwnd
);
1364 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1365 ReleaseDC( hwnd
, hDC
);
1367 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1372 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1376 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1380 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1385 NC_TrackMinMaxBox( hwnd
, wParam
);
1389 NC_TrackCloseButton (hwnd
, wParam
);
1401 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1402 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1404 /* But that is not what WinNT does. Instead it sends this. This
1405 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1406 * SC_MOUSEMENU into wParam.
1408 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1418 /***********************************************************************
1419 * NC_HandleNCLButtonDblClk
1421 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1423 LONG
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1426 * if this is an icon, send a restore since we are handling
1431 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1435 switch(wParam
) /* Hit test */
1438 /* stop processing if WS_MAXIMIZEBOX is missing */
1439 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1440 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1441 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1445 if (!(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
))
1446 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1450 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1454 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1461 /***********************************************************************
1462 * NC_HandleSysCommand
1464 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1466 LONG
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1468 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam
, lParam
);
1470 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1473 switch (wParam
& 0xfff0)
1477 if (USER_Driver
.pSysCommandSizeMove
)
1478 USER_Driver
.pSysCommandSizeMove( hwnd
, wParam
);
1482 if (hwnd
== GetForegroundWindow())
1483 ShowOwnedPopups(hwnd
,FALSE
);
1484 ShowWindow( hwnd
, SW_MINIMIZE
);
1488 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1489 ShowOwnedPopups(hwnd
,TRUE
);
1490 ShowWindow( hwnd
, SW_MAXIMIZE
);
1494 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1495 ShowOwnedPopups(hwnd
,TRUE
);
1496 ShowWindow( hwnd
, SW_RESTORE
);
1500 return SendMessageA( hwnd
, WM_CLOSE
, 0, 0 );
1506 pt
.x
= (short)LOWORD(lParam
);
1507 pt
.y
= (short)HIWORD(lParam
);
1508 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1515 pt
.x
= (short)LOWORD(lParam
);
1516 pt
.y
= (short)HIWORD(lParam
);
1517 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1522 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1526 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1530 if (wParam
== SC_ABOUTWINE
)
1532 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1535 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1536 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1537 FreeLibrary( hmodule
);
1541 if (wParam
== SC_PUTMARK
)
1542 DPRINTF("Debug mark requested by user\n");
1549 FIXME("unimplemented!\n");
1555 /*************************************************************
1558 * Stub for the grayed button of the caption
1560 *************************************************************/
1562 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
)
1568 hMaskBmp
= CreateBitmap (12, 10, 1, 1, lpGrayMask
);
1573 hdcMask
= CreateCompatibleDC (0);
1574 SelectObject (hdcMask
, hMaskBmp
);
1576 /* Draw the grayed bitmap using the mask */
1577 hOldBrush
= SelectObject (hdc
, (HGDIOBJ
)RGB(128, 128, 128));
1578 BitBlt (hdc
, x
, y
, 12, 10,
1579 hdcMask
, 0, 0, 0xB8074A);
1582 SelectObject (hdc
, hOldBrush
);
1583 DeleteObject(hMaskBmp
);
1589 /***********************************************************************
1590 * GetTitleBarInfo (USER32.@)
1591 * TODO: Handle STATE_SYSTEM_PRESSED
1593 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1598 TRACE("(%p %p)\n", hwnd
, tbi
);
1600 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1601 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi
->cbSize
);
1602 SetLastError(ERROR_INVALID_PARAMETER
);
1605 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1606 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1607 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1609 GetWindowRect(hwnd
, &wndRect
);
1611 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1612 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1613 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1615 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1616 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1617 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1619 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1620 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1623 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1624 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1625 * Under XP it seems to
1627 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1628 if(dwStyle
& WS_CAPTION
) {
1629 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1630 if(dwStyle
& WS_SYSMENU
) {
1631 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1632 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1633 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1636 if(!(dwStyle
& WS_MINIMIZEBOX
))
1637 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1638 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1639 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1641 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1642 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1643 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1644 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1647 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1648 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1649 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1650 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1654 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;