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
) GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
192 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICON
);
194 /* If there is no hIcon specified and this is a modal dialog,
195 * get the default one.
197 if (!hIcon
&& (GetWindowLongW( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
198 hIcon
= LoadImageW(0, (LPCWSTR
)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
= GetClassLongW(hwnd
, GCL_STYLE
);
379 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
380 LONG exStyle
= GetWindowLongW( 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 if( exStyle
& WS_EX_CLIENTEDGE
)
406 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
407 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
408 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
409 - GetSystemMetrics(SM_CYEDGE
));
411 if (style
& WS_VSCROLL
)
412 if( winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
)){
413 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
414 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
416 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
419 if (style
& WS_HSCROLL
)
420 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
421 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
423 if (winRect
->top
> winRect
->bottom
)
424 winRect
->bottom
= winRect
->top
;
426 if (winRect
->left
> winRect
->right
)
427 winRect
->right
= winRect
->left
;
433 /***********************************************************************
436 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
437 * but without the borders (if any).
438 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
440 static void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
442 WND
*wndPtr
= WIN_GetPtr( hwnd
);
444 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
446 rect
->top
= rect
->left
= 0;
447 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
448 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
450 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
452 /* Remove frame from rectangle */
453 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
455 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
457 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
459 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
461 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
463 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
466 /* We have additional border information if the window
467 * is a child (but not an MDI child) */
468 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
469 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
471 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
472 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
473 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
474 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
478 WIN_ReleasePtr( wndPtr
);
482 /***********************************************************************
485 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
487 * FIXME: Just a modified copy of the Win 3.1 version.
490 static LONG
NC_DoNCHitTest (WND
*wndPtr
, POINT pt
)
495 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
497 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
498 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
500 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
502 /* Check client area */
504 ScreenToClient( wndPtr
->hwndSelf
, &ptClient
);
505 GetClientRect( wndPtr
->hwndSelf
, &rcClient
);
506 if (PtInRect( &rcClient
, ptClient
)) return HTCLIENT
;
509 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
511 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
512 if (!PtInRect( &rect
, pt
))
514 /* Check top sizing border */
517 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
518 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
521 /* Check bottom sizing border */
522 if (pt
.y
>= rect
.bottom
)
524 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
525 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
528 /* Check left sizing border */
529 if (pt
.x
< rect
.left
)
531 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
532 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
535 /* Check right sizing border */
536 if (pt
.x
>= rect
.right
)
538 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
539 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
544 else /* No thick frame */
546 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
547 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
548 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
549 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
550 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
555 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
557 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
558 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
560 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
561 if (!PtInRect( &rect
, pt
))
563 BOOL min_or_max_box
= (wndPtr
->dwStyle
& WS_MAXIMIZEBOX
) ||
564 (wndPtr
->dwStyle
& WS_MINIMIZEBOX
);
565 /* Check system menu */
566 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
568 if (NC_IconForWindow(wndPtr
->hwndSelf
))
569 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
571 if (pt
.x
< rect
.left
) return HTSYSMENU
;
573 /* Check close button */
574 if (wndPtr
->dwStyle
& WS_SYSMENU
)
575 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
576 if (pt
.x
> rect
.right
) return HTCLOSE
;
578 /* Check maximize box */
579 /* In win95 there is automatically a Maximize button when there is a minimize one*/
580 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
581 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
582 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
584 /* Check minimize box */
585 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
586 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
587 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
589 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
594 /* Check vertical scroll bar */
596 if (wndPtr
->dwStyle
& WS_VSCROLL
)
598 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
599 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
601 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
602 if (PtInRect( &rcClient
, ptClient
)) return HTVSCROLL
;
605 /* Check horizontal scroll bar */
607 if (wndPtr
->dwStyle
& WS_HSCROLL
)
609 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
610 if (PtInRect( &rcClient
, ptClient
))
613 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
614 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (ptClient
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
615 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (ptClient
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
623 if (HAS_MENU(wndPtr
))
625 if ((ptClient
.y
< 0) && (ptClient
.x
>= 0) && (ptClient
.x
< rcClient
.right
))
629 /* Has to return HTNOWHERE if nothing was found
630 Could happen when a window has a customized non client area */
635 /***********************************************************************
638 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
640 LONG
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
643 WND
*wndPtr
= WIN_GetPtr( hwnd
);
645 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return HTERROR
;
647 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
648 WIN_ReleasePtr( wndPtr
);
653 /******************************************************************************
657 * Draws the system icon.
659 *****************************************************************************/
660 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
662 HICON hIcon
= NC_IconForWindow( hwnd
);
667 NC_GetInsideRect( hwnd
, &rect
);
668 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
669 GetSystemMetrics(SM_CXSMICON
),
670 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
676 /******************************************************************************
680 * Draws the close button.
682 * If bGrayed is true, then draw a disabled Close button
684 *****************************************************************************/
686 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
690 NC_GetInsideRect( hwnd
, &rect
);
692 /* A tool window has a smaller Close button */
693 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
695 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
696 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
697 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
699 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
700 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
701 rect
.bottom
= rect
.top
+ iBmpHeight
;
702 rect
.right
= rect
.left
+ iBmpWidth
;
706 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
707 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
711 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
713 (down
? DFCS_PUSHED
: 0) |
714 (bGrayed
? DFCS_INACTIVE
: 0)) );
717 /******************************************************************************
720 * Draws the maximize button for windows.
721 * If bGrayed is true, then draw a disabled Maximize button
723 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
728 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
729 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
732 flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
734 NC_GetInsideRect( hwnd
, &rect
);
735 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
736 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
737 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
738 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
741 if (down
) flags
|= DFCS_PUSHED
;
742 if (bGrayed
) flags
|= DFCS_INACTIVE
;
743 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
746 /******************************************************************************
749 * Draws the minimize button for windows.
750 * If bGrayed is true, then draw a disabled Minimize button
752 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
755 UINT flags
= DFCS_CAPTIONMIN
;
756 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
758 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
759 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
762 NC_GetInsideRect( hwnd
, &rect
);
763 if (style
& WS_SYSMENU
)
764 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
765 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
766 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
767 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
768 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
771 if (down
) flags
|= DFCS_PUSHED
;
772 if (bGrayed
) flags
|= DFCS_INACTIVE
;
773 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
776 /******************************************************************************
780 * Draw a window frame inside the given rectangle, and update the rectangle.
783 * Many. First, just what IS a frame in Win95? Note that the 3D look
784 * on the outer edge is handled by NC_DoNCPaint. As is the inner
785 * edge. The inner rectangle just inside the frame is handled by the
788 * In short, for most people, this function should be a nop (unless
789 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
790 * them lately, but just to get this code right). Even so, it doesn't
791 * appear to be so. It's being worked on...
793 *****************************************************************************/
795 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
799 /* Firstly the "thick" frame */
800 if (style
& WS_THICKFRAME
)
802 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
803 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
805 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
806 COLOR_INACTIVEBORDER
) );
808 PatBlt( hdc
, rect
->left
, rect
->top
,
809 rect
->right
- rect
->left
, height
, PATCOPY
);
810 PatBlt( hdc
, rect
->left
, rect
->top
,
811 width
, rect
->bottom
- rect
->top
, PATCOPY
);
812 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
813 rect
->right
- rect
->left
, -height
, PATCOPY
);
814 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
815 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
817 InflateRect( rect
, -width
, -height
);
820 /* Now the other bit of the frame */
821 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
822 (exStyle
& WS_EX_DLGMODALFRAME
))
824 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
825 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
826 /* This should give a value of 1 that should also work for a border */
828 SelectObject( hdc
, GetSysColorBrush(
829 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
831 (exStyle
& WS_EX_STATICEDGE
) ?
833 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
839 PatBlt( hdc
, rect
->left
, rect
->top
,
840 rect
->right
- rect
->left
, height
, PATCOPY
);
841 PatBlt( hdc
, rect
->left
, rect
->top
,
842 width
, rect
->bottom
- rect
->top
, PATCOPY
);
843 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
844 rect
->right
- rect
->left
, -height
, PATCOPY
);
845 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
846 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
848 InflateRect( rect
, -width
, -height
);
853 /******************************************************************************
857 * Draw the window caption for windows.
858 * The correct pen for the window frame must be selected in the DC.
860 *****************************************************************************/
862 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
863 DWORD exStyle
, BOOL active
)
870 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
871 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
872 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
873 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
874 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
875 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
876 SelectObject( hdc
, hPrevPen
);
879 FillRect( hdc
, &r
, GetSysColorBrush(active
? COLOR_ACTIVECAPTION
:
880 COLOR_INACTIVECAPTION
) );
882 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
883 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
884 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
887 if (style
& WS_SYSMENU
)
891 /* Go get the sysmenu */
892 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
893 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
895 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
896 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
897 ((((state
& MF_DISABLED
) || (state
& MF_GRAYED
))) && (state
!= 0xFFFFFFFF)));
898 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
900 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
902 /* In win95 the two buttons are always there */
903 /* But if the menu item is not in the menu they're disabled*/
905 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
906 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
908 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
909 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
913 if (InternalGetWindowText( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
915 NONCLIENTMETRICSW nclm
;
916 HFONT hFont
, hOldFont
;
917 nclm
.cbSize
= sizeof(nclm
);
918 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
919 if (exStyle
& WS_EX_TOOLWINDOW
)
920 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
922 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
923 hOldFont
= SelectObject (hdc
, hFont
);
924 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
925 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
926 SetBkMode( hdc
, TRANSPARENT
);
928 DrawTextW( hdc
, buffer
, -1, &r
,
929 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
930 DeleteObject (SelectObject (hdc
, hOldFont
));
935 /******************************************************************************
939 * Paint the non-client area for windows. The clip region is
943 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
944 * misc/tweak.c controls/menu.c # :-)
946 *****************************************************************************/
948 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
951 RECT rfuzz
, rect
, rectClip
;
954 DWORD dwStyle
, dwExStyle
;
957 RECT rectClient
, rectWindow
;
960 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
961 has_menu
= HAS_MENU(wndPtr
);
962 dwStyle
= wndPtr
->dwStyle
;
963 dwExStyle
= wndPtr
->dwExStyle
;
964 flags
= wndPtr
->flags
;
965 rectClient
= wndPtr
->rectClient
;
966 rectWindow
= wndPtr
->rectWindow
;
967 WIN_ReleasePtr( wndPtr
);
969 if ( dwStyle
& WS_MINIMIZE
||
970 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
972 active
= flags
& WIN_NCACTIVATED
;
974 TRACE("%p %d\n", hwnd
, active
);
976 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
977 the call to GetDCEx implying that it is allowed not to use it either.
978 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
979 will cause clipRgn to be deleted after ReleaseDC().
980 Now, how is the "system" supposed to tell what happened?
983 hrgn
= CreateRectRgn( rectClient
.left
- rectWindow
.left
,
984 rectClient
.top
- rectWindow
.top
,
985 rectClient
.right
- rectWindow
.left
,
986 rectClient
.bottom
- rectWindow
.top
);
989 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
990 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
994 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
999 rect
.top
= rect
.left
= 0;
1000 rect
.right
= rectWindow
.right
- rectWindow
.left
;
1001 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
1003 if( clip
> (HRGN
)1 )
1004 GetRgnBox( clip
, &rectClip
);
1011 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1013 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1014 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1016 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1017 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1020 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1022 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1025 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1026 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1027 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1030 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1031 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1033 if( !clip
|| IntersectRect( &rfuzz
, &r
, &rectClip
) )
1034 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1040 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1042 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1043 r
.left
, r
.top
, r
.right
, r
.bottom
);
1045 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1048 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1049 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1051 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1052 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1054 /* Draw the scroll-bars */
1056 if (dwStyle
& WS_VSCROLL
)
1057 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1058 if (dwStyle
& WS_HSCROLL
)
1059 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1061 /* Draw the "size-box" */
1062 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1065 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1066 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1068 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1069 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1070 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1073 ReleaseDC( hwnd
, hdc
);
1079 /***********************************************************************
1082 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1084 LONG
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1086 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1088 if( dwStyle
& WS_VISIBLE
)
1090 if( dwStyle
& WS_MINIMIZE
)
1091 WINPOS_RedrawIconTitle( hwnd
);
1093 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1099 /***********************************************************************
1100 * NC_HandleNCActivate
1102 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1104 LONG
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1106 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1108 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1110 /* Lotus Notes draws menu descriptions in the caption of its main
1111 * window. When it wants to restore original "system" view, it just
1112 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1113 * attempt to minimize redrawings lead to a not restored caption.
1115 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1116 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1117 WIN_ReleasePtr( wndPtr
);
1120 WINPOS_RedrawIconTitle( hwnd
);
1122 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1128 /***********************************************************************
1129 * NC_HandleSetCursor
1131 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1133 LONG
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1135 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1137 switch((short)LOWORD(lParam
))
1141 WORD msg
= HIWORD( lParam
);
1142 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1143 (msg
== WM_RBUTTONDOWN
))
1150 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1160 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1164 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1168 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1172 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1175 /* Default cursor: arrow */
1176 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1179 /***********************************************************************
1182 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1184 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1187 WND
*wndPtr
= WIN_GetPtr( hwnd
);
1188 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return;
1190 NC_GetInsideRect( hwnd
, rect
);
1191 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1192 if (wndPtr
->dwStyle
& WS_CHILD
)
1193 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1194 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1195 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1196 WIN_ReleasePtr( wndPtr
);
1200 /***********************************************************************
1203 * Track a mouse button press on the minimize or maximize box.
1205 * The big difference between 3.1 and 95 is the disabled button state.
1206 * In win95 the system button can be disabled, so it can ignore the mouse
1210 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1213 HDC hdc
= GetWindowDC( hwnd
);
1214 BOOL pressed
= TRUE
;
1216 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1217 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1219 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1221 if (wParam
== HTMINBUTTON
)
1223 /* If the style is not present, do nothing */
1224 if (!(wndStyle
& WS_MINIMIZEBOX
))
1227 /* Check if the sysmenu item for minimize is there */
1228 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1230 paintButton
= &NC_DrawMinButton
;
1234 /* If the style is not present, do nothing */
1235 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1238 /* Check if the sysmenu item for maximize is there */
1239 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1241 paintButton
= &NC_DrawMaxButton
;
1246 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1250 BOOL oldstate
= pressed
;
1252 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1253 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1255 if(msg
.message
== WM_LBUTTONUP
)
1258 if(msg
.message
!= WM_MOUSEMOVE
)
1261 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1262 if (pressed
!= oldstate
)
1263 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1267 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1270 ReleaseDC( hwnd
, hdc
);
1272 /* If the item minimize or maximize of the sysmenu are not there */
1273 /* or if the style is not present, do nothing */
1274 if ((!pressed
) || (state
== 0xFFFFFFFF))
1277 if (wParam
== HTMINBUTTON
)
1278 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1280 SendMessageA( hwnd
, WM_SYSCOMMAND
,
1281 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1284 /***********************************************************************
1285 * NC_TrackCloseButton
1287 * Track a mouse button press on the Win95 close button.
1289 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1293 BOOL pressed
= TRUE
;
1294 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1300 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1302 /* If the item close of the sysmenu is disabled or not there do nothing */
1303 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1306 hdc
= GetWindowDC( hwnd
);
1310 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1314 BOOL oldstate
= pressed
;
1316 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1317 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1319 if(msg
.message
== WM_LBUTTONUP
)
1322 if(msg
.message
!= WM_MOUSEMOVE
)
1325 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1326 if (pressed
!= oldstate
)
1327 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1331 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1334 ReleaseDC( hwnd
, hdc
);
1335 if (!pressed
) return;
1337 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1341 /***********************************************************************
1344 * Track a mouse button press on the horizontal or vertical scroll-bar.
1346 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1350 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1352 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1353 scrollbar
= SB_HORZ
;
1355 else /* SC_VSCROLL */
1357 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1358 scrollbar
= SB_VERT
;
1360 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1364 /***********************************************************************
1365 * NC_HandleNCLButtonDown
1367 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1369 LONG
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1371 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1373 switch(wParam
) /* Hit test */
1377 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1379 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1380 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1385 if( style
& WS_SYSMENU
)
1387 if( !(style
& WS_MINIMIZE
) )
1389 HDC hDC
= GetWindowDC(hwnd
);
1390 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1391 ReleaseDC( hwnd
, hDC
);
1393 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1398 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1402 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1406 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1411 NC_TrackMinMaxBox( hwnd
, wParam
);
1415 NC_TrackCloseButton (hwnd
, wParam
);
1427 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1428 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1430 /* But that is not what WinNT does. Instead it sends this. This
1431 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1432 * SC_MOUSEMENU into wParam.
1434 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1444 /***********************************************************************
1445 * NC_HandleNCLButtonDblClk
1447 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1449 LONG
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1452 * if this is an icon, send a restore since we are handling
1457 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1461 switch(wParam
) /* Hit test */
1464 /* stop processing if WS_MAXIMIZEBOX is missing */
1465 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1466 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1467 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1471 if (!(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
))
1472 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1476 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1480 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1487 /***********************************************************************
1488 * NC_HandleSysCommand
1490 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1492 LONG
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1494 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam
, lParam
);
1496 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1499 switch (wParam
& 0xfff0)
1503 if (USER_Driver
.pSysCommandSizeMove
)
1504 USER_Driver
.pSysCommandSizeMove( hwnd
, wParam
);
1508 if (hwnd
== GetForegroundWindow())
1509 ShowOwnedPopups(hwnd
,FALSE
);
1510 ShowWindow( hwnd
, SW_MINIMIZE
);
1514 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1515 ShowOwnedPopups(hwnd
,TRUE
);
1516 ShowWindow( hwnd
, SW_MAXIMIZE
);
1520 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1521 ShowOwnedPopups(hwnd
,TRUE
);
1522 ShowWindow( hwnd
, SW_RESTORE
);
1526 return SendMessageA( hwnd
, WM_CLOSE
, 0, 0 );
1532 pt
.x
= (short)LOWORD(lParam
);
1533 pt
.y
= (short)HIWORD(lParam
);
1534 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1541 pt
.x
= (short)LOWORD(lParam
);
1542 pt
.y
= (short)HIWORD(lParam
);
1543 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1548 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1552 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1556 if (wParam
== SC_ABOUTWINE
)
1558 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1561 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1562 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1563 FreeLibrary( hmodule
);
1567 if (wParam
== SC_PUTMARK
)
1568 DPRINTF("Debug mark requested by user\n");
1575 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam
);
1581 /*************************************************************
1584 * Stub for the grayed button of the caption
1586 *************************************************************/
1588 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
)
1594 hMaskBmp
= CreateBitmap (12, 10, 1, 1, lpGrayMask
);
1599 hdcMask
= CreateCompatibleDC (0);
1600 SelectObject (hdcMask
, hMaskBmp
);
1602 /* Draw the grayed bitmap using the mask */
1603 hOldBrush
= SelectObject (hdc
, (HGDIOBJ
)RGB(128, 128, 128));
1604 BitBlt (hdc
, x
, y
, 12, 10,
1605 hdcMask
, 0, 0, 0xB8074A);
1608 SelectObject (hdc
, hOldBrush
);
1609 DeleteObject(hMaskBmp
);
1615 /***********************************************************************
1616 * GetTitleBarInfo (USER32.@)
1617 * TODO: Handle STATE_SYSTEM_PRESSED
1619 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1624 TRACE("(%p %p)\n", hwnd
, tbi
);
1626 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1627 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi
->cbSize
);
1628 SetLastError(ERROR_INVALID_PARAMETER
);
1631 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1632 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1633 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1635 GetWindowRect(hwnd
, &wndRect
);
1637 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1638 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1639 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1641 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1642 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1643 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1645 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1646 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1649 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1650 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1651 * Under XP it seems to
1653 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1654 if(dwStyle
& WS_CAPTION
) {
1655 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1656 if(dwStyle
& WS_SYSMENU
) {
1657 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1658 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1659 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1662 if(!(dwStyle
& WS_MINIMIZEBOX
))
1663 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1664 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1665 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1667 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1668 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1669 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1670 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1673 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1674 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1675 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1676 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1680 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;