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"
33 #include "cursoricon.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(nonclient
);
39 WINE_DECLARE_DEBUG_CHANNEL(shell
);
41 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
);
43 static const BYTE lpGrayMask
[] = { 0xAA, 0xA0,
54 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
55 #define SC_PUTMARK (SC_SCREENSAVE+2)
57 /* Some useful macros */
58 #define HAS_DLGFRAME(style,exStyle) \
59 (((exStyle) & WS_EX_DLGMODALFRAME) || \
60 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
62 #define HAS_THICKFRAME(style,exStyle) \
63 (((style) & WS_THICKFRAME) && \
64 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
66 #define HAS_THINFRAME(style) \
67 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
69 #define HAS_BIGFRAME(style,exStyle) \
70 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
71 ((exStyle) & WS_EX_DLGMODALFRAME))
73 #define HAS_STATICOUTERFRAME(style,exStyle) \
74 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
77 #define HAS_ANYFRAME(style,exStyle) \
78 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
79 ((exStyle) & WS_EX_DLGMODALFRAME) || \
80 !((style) & (WS_CHILD | WS_POPUP)))
82 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
85 /******************************************************************************
88 * Computes the size of the "outside" parts of the window based on the
89 * parameters of the client area.
98 * "Outer" parts of a window means the whole window frame, caption and
99 * menu bar. It does not include "inner" parts of the frame like client
100 * edge, static edge or scroll bars.
102 *****************************************************************************/
105 NC_AdjustRectOuter (LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
108 if(style
& WS_ICONIC
) return;
110 if ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_DLGMODALFRAME
)) ==
113 adjust
= 1; /* for the outer frame always present */
118 if ((exStyle
& WS_EX_DLGMODALFRAME
) ||
119 (style
& (WS_THICKFRAME
|WS_DLGFRAME
))) adjust
= 2; /* outer */
121 if (style
& WS_THICKFRAME
)
122 adjust
+= ( GetSystemMetrics (SM_CXFRAME
)
123 - GetSystemMetrics (SM_CXDLGFRAME
)); /* The resize border */
124 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
125 (exStyle
& WS_EX_DLGMODALFRAME
))
126 adjust
++; /* The other border */
128 InflateRect (rect
, adjust
, adjust
);
130 if ((style
& WS_CAPTION
) == WS_CAPTION
)
132 if (exStyle
& WS_EX_TOOLWINDOW
)
133 rect
->top
-= GetSystemMetrics(SM_CYSMCAPTION
);
135 rect
->top
-= GetSystemMetrics(SM_CYCAPTION
);
137 if (menu
) rect
->top
-= GetSystemMetrics(SM_CYMENU
);
141 /******************************************************************************
144 * Computes the size of the "inside" part of the window based on the
145 * parameters of the client area.
153 * "Inner" part of a window means the window frame inside of the flat
154 * window frame. It includes the client edge, the static edge and the
157 *****************************************************************************/
160 NC_AdjustRectInner (LPRECT rect
, DWORD style
, DWORD exStyle
)
162 if(style
& WS_ICONIC
) return;
164 if (exStyle
& WS_EX_CLIENTEDGE
)
165 InflateRect(rect
, GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
167 if (style
& WS_VSCROLL
)
169 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
170 rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
172 rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
174 if (style
& WS_HSCROLL
) rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
179 static HICON
NC_IconForWindow( HWND hwnd
)
182 WND
*wndPtr
= WIN_GetPtr( hwnd
);
184 if (wndPtr
&& wndPtr
!= WND_OTHER_PROCESS
&& wndPtr
!= WND_DESKTOP
)
186 hIcon
= wndPtr
->hIconSmall
;
187 if (!hIcon
) hIcon
= wndPtr
->hIcon
;
188 WIN_ReleasePtr( wndPtr
);
190 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICONSM
);
191 if (!hIcon
) hIcon
= (HICON
) GetClassLongPtrW( hwnd
, GCLP_HICON
);
193 /* If there is no hIcon specified and this is a modal dialog,
194 * get the default one.
196 if (!hIcon
&& (GetWindowLongW( hwnd
, GWL_STYLE
) & DS_MODALFRAME
))
197 hIcon
= LoadImageW(0, (LPCWSTR
)IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
201 /***********************************************************************
202 * DrawCaption (USER32.@) Draws a caption bar
216 DrawCaption (HWND hwnd
, HDC hdc
, const RECT
*lpRect
, UINT uFlags
)
218 return DrawCaptionTempA (hwnd
, hdc
, lpRect
, 0, 0, NULL
, uFlags
& 0x1F);
222 /***********************************************************************
223 * DrawCaptionTempA (USER32.@)
225 BOOL WINAPI
DrawCaptionTempA (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
226 HICON hIcon
, LPCSTR str
, UINT uFlags
)
232 if (!(uFlags
& DC_TEXT
) || !str
)
233 return DrawCaptionTempW( hwnd
, hdc
, rect
, hFont
, hIcon
, NULL
, uFlags
);
235 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
236 if ((strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
238 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
239 ret
= DrawCaptionTempW (hwnd
, hdc
, rect
, hFont
, hIcon
, strW
, uFlags
);
240 HeapFree( GetProcessHeap (), 0, strW
);
246 /***********************************************************************
247 * DrawCaptionTempW (USER32.@)
249 BOOL WINAPI
DrawCaptionTempW (HWND hwnd
, HDC hdc
, const RECT
*rect
, HFONT hFont
,
250 HICON hIcon
, LPCWSTR str
, UINT uFlags
)
254 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
255 hwnd
, hdc
, rect
, hFont
, hIcon
, debugstr_w(str
), uFlags
);
257 /* drawing background */
258 if (uFlags
& DC_INBUTTON
) {
259 FillRect (hdc
, &rc
, GetSysColorBrush (COLOR_3DFACE
));
261 if (uFlags
& DC_ACTIVE
) {
262 HBRUSH hbr
= SelectObject (hdc
, UITOOLS_GetPattern55AABrush ());
263 PatBlt (hdc
, rc
.left
, rc
.top
,
264 rc
.right
-rc
.left
, rc
.bottom
-rc
.top
, 0xFA0089);
265 SelectObject (hdc
, hbr
);
269 FillRect (hdc
, &rc
, GetSysColorBrush ((uFlags
& DC_ACTIVE
) ?
270 COLOR_ACTIVECAPTION
: COLOR_INACTIVECAPTION
));
275 if ((uFlags
& DC_ICON
) && !(uFlags
& DC_SMALLCAP
)) {
279 pt
.y
= (rc
.bottom
+ rc
.top
- GetSystemMetrics(SM_CYSMICON
)) / 2;
281 if (!hIcon
) hIcon
= NC_IconForWindow(hwnd
);
282 DrawIconEx (hdc
, pt
.x
, pt
.y
, hIcon
, GetSystemMetrics(SM_CXSMICON
),
283 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
284 rc
.left
+= (rc
.bottom
- rc
.top
);
288 if (uFlags
& DC_TEXT
) {
291 if (uFlags
& DC_INBUTTON
)
292 SetTextColor (hdc
, GetSysColor (COLOR_BTNTEXT
));
293 else if (uFlags
& DC_ACTIVE
)
294 SetTextColor (hdc
, GetSysColor (COLOR_CAPTIONTEXT
));
296 SetTextColor (hdc
, GetSysColor (COLOR_INACTIVECAPTIONTEXT
));
298 SetBkMode (hdc
, TRANSPARENT
);
301 hOldFont
= SelectObject (hdc
, hFont
);
303 NONCLIENTMETRICSW nclm
;
305 nclm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
306 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
307 hNewFont
= CreateFontIndirectW ((uFlags
& DC_SMALLCAP
) ?
308 &nclm
.lfSmCaptionFont
: &nclm
.lfCaptionFont
);
309 hOldFont
= SelectObject (hdc
, hNewFont
);
313 DrawTextW (hdc
, str
, -1, &rc
,
314 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
318 nLen
= GetWindowTextW (hwnd
, szText
, 128);
319 DrawTextW (hdc
, szText
, nLen
, &rc
,
320 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
324 SelectObject (hdc
, hOldFont
);
326 DeleteObject (SelectObject (hdc
, hOldFont
));
329 /* drawing focus ??? */
331 FIXME("undocumented flag (0x2000)!\n");
337 /***********************************************************************
338 * AdjustWindowRect (USER32.@)
340 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
342 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
346 /***********************************************************************
347 * AdjustWindowRectEx (USER32.@)
349 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
351 /* Correct the window style */
352 style
&= (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
| WS_CHILD
);
353 exStyle
&= (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
|
354 WS_EX_STATICEDGE
| WS_EX_TOOLWINDOW
);
355 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
357 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
358 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
359 style
, menu
, exStyle
);
361 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
362 NC_AdjustRectInner( rect
, style
, exStyle
);
368 /***********************************************************************
369 * NC_HandleNCCalcSize
371 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
373 LONG
NC_HandleNCCalcSize( HWND hwnd
, RECT
*winRect
)
375 RECT tmpRect
= { 0, 0, 0, 0 };
377 LONG cls_style
= GetClassLongW(hwnd
, GCL_STYLE
);
378 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
379 LONG exStyle
= GetWindowLongW( hwnd
, GWL_EXSTYLE
);
381 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
382 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
386 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
388 winRect
->left
-= tmpRect
.left
;
389 winRect
->top
-= tmpRect
.top
;
390 winRect
->right
-= tmpRect
.right
;
391 winRect
->bottom
-= tmpRect
.bottom
;
393 if (((style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
) && GetMenu(hwnd
))
395 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
396 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
399 MENU_GetMenuBarHeight( hwnd
,
400 winRect
->right
- winRect
->left
,
401 -tmpRect
.left
, -tmpRect
.top
) + 1;
404 if( exStyle
& WS_EX_CLIENTEDGE
)
405 if( winRect
->right
- winRect
->left
> 2 * GetSystemMetrics(SM_CXEDGE
) &&
406 winRect
->bottom
- winRect
->top
> 2 * GetSystemMetrics(SM_CYEDGE
))
407 InflateRect( winRect
, - GetSystemMetrics(SM_CXEDGE
),
408 - GetSystemMetrics(SM_CYEDGE
));
410 if (style
& WS_VSCROLL
)
411 if( winRect
->right
- winRect
->left
>= GetSystemMetrics(SM_CXVSCROLL
)){
412 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
413 winRect
->left
+= GetSystemMetrics(SM_CXVSCROLL
);
415 winRect
->right
-= GetSystemMetrics(SM_CXVSCROLL
);
418 if (style
& WS_HSCROLL
)
419 if( winRect
->bottom
- winRect
->top
> GetSystemMetrics(SM_CYHSCROLL
))
420 winRect
->bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
422 if (winRect
->top
> winRect
->bottom
)
423 winRect
->bottom
= winRect
->top
;
425 if (winRect
->left
> winRect
->right
)
426 winRect
->right
= winRect
->left
;
432 /***********************************************************************
435 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
436 * but without the borders (if any).
437 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
439 static void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
441 WND
*wndPtr
= WIN_GetPtr( hwnd
);
443 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return;
445 rect
->top
= rect
->left
= 0;
446 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
447 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
449 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
451 /* Remove frame from rectangle */
452 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
454 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
456 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
458 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
460 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
462 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
465 /* We have additional border information if the window
466 * is a child (but not an MDI child) */
467 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
468 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
470 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
471 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
472 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
473 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
477 WIN_ReleasePtr( wndPtr
);
481 /***********************************************************************
484 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
486 * FIXME: Just a modified copy of the Win 3.1 version.
489 static LONG
NC_DoNCHitTest (WND
*wndPtr
, POINT pt
)
494 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
496 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
497 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
499 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
501 /* Check client area */
503 ScreenToClient( wndPtr
->hwndSelf
, &ptClient
);
504 GetClientRect( wndPtr
->hwndSelf
, &rcClient
);
505 if (PtInRect( &rcClient
, ptClient
)) return HTCLIENT
;
508 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
510 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
511 if (!PtInRect( &rect
, pt
))
513 /* Check top sizing border */
516 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
517 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
520 /* Check bottom sizing border */
521 if (pt
.y
>= rect
.bottom
)
523 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
524 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
527 /* Check left sizing border */
528 if (pt
.x
< rect
.left
)
530 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
531 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
534 /* Check right sizing border */
535 if (pt
.x
>= rect
.right
)
537 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
538 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
543 else /* No thick frame */
545 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
546 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
547 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
548 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
549 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
554 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
556 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
557 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
559 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
560 if (!PtInRect( &rect
, pt
))
562 BOOL min_or_max_box
= (wndPtr
->dwStyle
& WS_MAXIMIZEBOX
) ||
563 (wndPtr
->dwStyle
& WS_MINIMIZEBOX
);
564 /* Check system menu */
565 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
567 if (NC_IconForWindow(wndPtr
->hwndSelf
))
568 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
570 if (pt
.x
< rect
.left
) return HTSYSMENU
;
572 /* Check close button */
573 if (wndPtr
->dwStyle
& WS_SYSMENU
)
574 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
575 if (pt
.x
> rect
.right
) return HTCLOSE
;
577 /* Check maximize box */
578 /* In win95 there is automatically a Maximize button when there is a minimize one*/
579 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
580 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
581 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
583 /* Check minimize box */
584 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
585 if (min_or_max_box
&& !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
586 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
588 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
593 /* Check vertical scroll bar */
595 if (wndPtr
->dwStyle
& WS_VSCROLL
)
597 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
598 rcClient
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
600 rcClient
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
601 if (PtInRect( &rcClient
, ptClient
)) return HTVSCROLL
;
604 /* Check horizontal scroll bar */
606 if (wndPtr
->dwStyle
& WS_HSCROLL
)
608 rcClient
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
609 if (PtInRect( &rcClient
, ptClient
))
612 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
613 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (ptClient
.x
<= rcClient
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
614 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (ptClient
.x
>= rcClient
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
622 if (HAS_MENU(wndPtr
))
624 if ((ptClient
.y
< 0) && (ptClient
.x
>= 0) && (ptClient
.x
< rcClient
.right
))
628 /* Has to return HTNOWHERE if nothing was found
629 Could happen when a window has a customized non client area */
634 /***********************************************************************
637 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
639 LONG
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
642 WND
*wndPtr
= WIN_GetPtr( hwnd
);
644 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return HTERROR
;
646 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
647 WIN_ReleasePtr( wndPtr
);
652 /******************************************************************************
656 * Draws the system icon.
658 *****************************************************************************/
659 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
661 HICON hIcon
= NC_IconForWindow( hwnd
);
666 NC_GetInsideRect( hwnd
, &rect
);
667 DrawIconEx (hdc
, rect
.left
+ 2, rect
.top
+ 1, hIcon
,
668 GetSystemMetrics(SM_CXSMICON
),
669 GetSystemMetrics(SM_CYSMICON
), 0, 0, DI_NORMAL
);
675 /******************************************************************************
679 * Draws the close button.
681 * If bGrayed is true, then draw a disabled Close button
683 *****************************************************************************/
685 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
689 NC_GetInsideRect( hwnd
, &rect
);
691 /* A tool window has a smaller Close button */
692 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
694 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
695 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
696 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
698 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
699 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
700 rect
.bottom
= rect
.top
+ iBmpHeight
;
701 rect
.right
= rect
.left
+ iBmpWidth
;
705 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
706 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
710 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
712 (down
? DFCS_PUSHED
: 0) |
713 (bGrayed
? DFCS_INACTIVE
: 0)) );
716 /******************************************************************************
719 * Draws the maximize button for windows.
720 * If bGrayed is true, then draw a disabled Maximize button
722 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
727 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
728 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
731 flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
733 NC_GetInsideRect( hwnd
, &rect
);
734 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
735 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
736 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
737 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
740 if (down
) flags
|= DFCS_PUSHED
;
741 if (bGrayed
) flags
|= DFCS_INACTIVE
;
742 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
745 /******************************************************************************
748 * Draws the minimize button for windows.
749 * If bGrayed is true, then draw a disabled Minimize button
751 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
754 UINT flags
= DFCS_CAPTIONMIN
;
755 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
757 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
758 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
761 NC_GetInsideRect( hwnd
, &rect
);
762 if (style
& WS_SYSMENU
)
763 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
764 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
765 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
766 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
767 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
770 if (down
) flags
|= DFCS_PUSHED
;
771 if (bGrayed
) flags
|= DFCS_INACTIVE
;
772 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
775 /******************************************************************************
779 * Draw a window frame inside the given rectangle, and update the rectangle.
782 * Many. First, just what IS a frame in Win95? Note that the 3D look
783 * on the outer edge is handled by NC_DoNCPaint. As is the inner
784 * edge. The inner rectangle just inside the frame is handled by the
787 * In short, for most people, this function should be a nop (unless
788 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
789 * them lately, but just to get this code right). Even so, it doesn't
790 * appear to be so. It's being worked on...
792 *****************************************************************************/
794 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
798 /* Firstly the "thick" frame */
799 if (style
& WS_THICKFRAME
)
801 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
802 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
804 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
805 COLOR_INACTIVEBORDER
) );
807 PatBlt( hdc
, rect
->left
, rect
->top
,
808 rect
->right
- rect
->left
, height
, PATCOPY
);
809 PatBlt( hdc
, rect
->left
, rect
->top
,
810 width
, rect
->bottom
- rect
->top
, PATCOPY
);
811 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
812 rect
->right
- rect
->left
, -height
, PATCOPY
);
813 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
814 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
816 InflateRect( rect
, -width
, -height
);
819 /* Now the other bit of the frame */
820 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
821 (exStyle
& WS_EX_DLGMODALFRAME
))
823 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
824 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
825 /* This should give a value of 1 that should also work for a border */
827 SelectObject( hdc
, GetSysColorBrush(
828 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
830 (exStyle
& WS_EX_STATICEDGE
) ?
832 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
838 PatBlt( hdc
, rect
->left
, rect
->top
,
839 rect
->right
- rect
->left
, height
, PATCOPY
);
840 PatBlt( hdc
, rect
->left
, rect
->top
,
841 width
, rect
->bottom
- rect
->top
, PATCOPY
);
842 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
843 rect
->right
- rect
->left
, -height
, PATCOPY
);
844 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
845 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
847 InflateRect( rect
, -width
, -height
);
852 /******************************************************************************
856 * Draw the window caption for windows.
857 * The correct pen for the window frame must be selected in the DC.
859 *****************************************************************************/
861 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
862 DWORD exStyle
, BOOL active
)
869 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
870 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
871 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
872 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
873 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
874 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
875 SelectObject( hdc
, hPrevPen
);
878 FillRect( hdc
, &r
, GetSysColorBrush(active
? COLOR_ACTIVECAPTION
:
879 COLOR_INACTIVECAPTION
) );
881 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
882 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
883 r
.left
+= GetSystemMetrics(SM_CXSMICON
) + 2;
886 if (style
& WS_SYSMENU
)
890 /* Go get the sysmenu */
891 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
892 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
894 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
895 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
896 ((((state
& MF_DISABLED
) || (state
& MF_GRAYED
))) && (state
!= 0xFFFFFFFF)));
897 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
899 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
901 /* In win95 the two buttons are always there */
902 /* But if the menu item is not in the menu they're disabled*/
904 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
905 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
907 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
908 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
912 if (InternalGetWindowText( hwnd
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
914 NONCLIENTMETRICSW nclm
;
915 HFONT hFont
, hOldFont
;
916 nclm
.cbSize
= sizeof(nclm
);
917 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
918 if (exStyle
& WS_EX_TOOLWINDOW
)
919 hFont
= CreateFontIndirectW (&nclm
.lfSmCaptionFont
);
921 hFont
= CreateFontIndirectW (&nclm
.lfCaptionFont
);
922 hOldFont
= SelectObject (hdc
, hFont
);
923 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
924 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
925 SetBkMode( hdc
, TRANSPARENT
);
927 DrawTextW( hdc
, buffer
, -1, &r
,
928 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
929 DeleteObject (SelectObject (hdc
, hOldFont
));
934 /******************************************************************************
937 * Paint the non-client area for windows.
939 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
942 RECT rfuzz
, rect
, rectClip
;
945 DWORD dwStyle
, dwExStyle
;
948 RECT rectClient
, rectWindow
;
951 if (!(wndPtr
= WIN_GetPtr( hwnd
)) || wndPtr
== WND_OTHER_PROCESS
) return;
952 has_menu
= HAS_MENU(wndPtr
);
953 dwStyle
= wndPtr
->dwStyle
;
954 dwExStyle
= wndPtr
->dwExStyle
;
955 flags
= wndPtr
->flags
;
956 rectClient
= wndPtr
->rectClient
;
957 rectWindow
= wndPtr
->rectWindow
;
958 WIN_ReleasePtr( wndPtr
);
960 if ( dwStyle
& WS_MINIMIZE
||
961 !WIN_IsWindowDrawable( hwnd
, 0 )) return; /* Nothing to do */
963 active
= flags
& WIN_NCACTIVATED
;
965 TRACE("%p %d\n", hwnd
, active
);
967 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
968 the call to GetDCEx implying that it is allowed not to use it either.
969 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
970 will cause clipRgn to be deleted after ReleaseDC().
971 Now, how is the "system" supposed to tell what happened?
974 hrgn
= CreateRectRgn( rectClient
.left
- rectWindow
.left
,
975 rectClient
.top
- rectWindow
.top
,
976 rectClient
.right
- rectWindow
.left
,
977 rectClient
.bottom
- rectWindow
.top
);
980 CombineRgn( hrgn
, clip
, hrgn
, RGN_DIFF
);
981 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_INTERSECTRGN
);
985 hdc
= GetDCEx( hwnd
, hrgn
, DCX_USESTYLE
| DCX_WINDOW
| DCX_EXCLUDERGN
);
990 rect
.top
= rect
.left
= 0;
991 rect
.right
= rectWindow
.right
- rectWindow
.left
;
992 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
995 GetRgnBox( clip
, &rectClip
);
1002 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1004 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1005 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1007 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1008 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1011 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1013 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1016 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1017 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1018 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1021 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1022 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1024 if( !clip
|| IntersectRect( &rfuzz
, &r
, &rectClip
) )
1025 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1031 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1033 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1034 r
.left
, r
.top
, r
.right
, r
.bottom
);
1036 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1039 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1040 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1042 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1043 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1045 /* Draw the scroll-bars */
1047 if (dwStyle
& WS_VSCROLL
)
1048 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1049 if (dwStyle
& WS_HSCROLL
)
1050 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1052 /* Draw the "size-box" */
1053 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1056 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1057 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1059 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1060 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1061 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1064 ReleaseDC( hwnd
, hdc
);
1070 /***********************************************************************
1073 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1075 LONG
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1077 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1079 if( dwStyle
& WS_VISIBLE
)
1081 if( dwStyle
& WS_MINIMIZE
)
1082 WINPOS_RedrawIconTitle( hwnd
);
1084 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1090 /***********************************************************************
1091 * NC_HandleNCActivate
1093 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1095 LONG
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1097 WND
* wndPtr
= WIN_GetPtr( hwnd
);
1099 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
) return FALSE
;
1101 /* Lotus Notes draws menu descriptions in the caption of its main
1102 * window. When it wants to restore original "system" view, it just
1103 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1104 * attempt to minimize redrawings lead to a not restored caption.
1106 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1107 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1108 WIN_ReleasePtr( wndPtr
);
1111 WINPOS_RedrawIconTitle( hwnd
);
1113 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1119 /***********************************************************************
1120 * NC_HandleSetCursor
1122 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1124 LONG
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1126 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1128 switch((short)LOWORD(lParam
))
1132 WORD msg
= HIWORD( lParam
);
1133 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1134 (msg
== WM_RBUTTONDOWN
) || (msg
== WM_XBUTTONDOWN
))
1141 HCURSOR hCursor
= (HCURSOR
)GetClassLongPtrW(hwnd
, GCLP_HCURSOR
);
1151 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1155 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1159 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1163 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1166 /* Default cursor: arrow */
1167 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1170 /***********************************************************************
1173 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1175 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1178 WND
*wndPtr
= WIN_GetPtr( hwnd
);
1179 if (!wndPtr
|| wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return;
1181 NC_GetInsideRect( hwnd
, rect
);
1182 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1183 if (wndPtr
->dwStyle
& WS_CHILD
)
1184 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1185 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1186 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1187 WIN_ReleasePtr( wndPtr
);
1191 /***********************************************************************
1194 * Track a mouse button press on the minimize or maximize box.
1196 * The big difference between 3.1 and 95 is the disabled button state.
1197 * In win95 the system button can be disabled, so it can ignore the mouse
1201 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1204 HDC hdc
= GetWindowDC( hwnd
);
1205 BOOL pressed
= TRUE
;
1207 DWORD wndStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1208 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1210 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1212 if (wParam
== HTMINBUTTON
)
1214 /* If the style is not present, do nothing */
1215 if (!(wndStyle
& WS_MINIMIZEBOX
))
1218 /* Check if the sysmenu item for minimize is there */
1219 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1221 paintButton
= &NC_DrawMinButton
;
1225 /* If the style is not present, do nothing */
1226 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1229 /* Check if the sysmenu item for maximize is there */
1230 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1232 paintButton
= &NC_DrawMaxButton
;
1237 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1241 BOOL oldstate
= pressed
;
1243 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1244 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1246 if(msg
.message
== WM_LBUTTONUP
)
1249 if(msg
.message
!= WM_MOUSEMOVE
)
1252 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1253 if (pressed
!= oldstate
)
1254 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1258 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1261 ReleaseDC( hwnd
, hdc
);
1263 /* If the item minimize or maximize of the sysmenu are not there */
1264 /* or if the style is not present, do nothing */
1265 if ((!pressed
) || (state
== 0xFFFFFFFF))
1268 if (wParam
== HTMINBUTTON
)
1269 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1271 SendMessageA( hwnd
, WM_SYSCOMMAND
,
1272 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1275 /***********************************************************************
1276 * NC_TrackCloseButton
1278 * Track a mouse button press on the Win95 close button.
1280 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1284 BOOL pressed
= TRUE
;
1285 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1291 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1293 /* If the item close of the sysmenu is disabled or not there do nothing */
1294 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1297 hdc
= GetWindowDC( hwnd
);
1301 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1305 BOOL oldstate
= pressed
;
1307 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1308 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1310 if(msg
.message
== WM_LBUTTONUP
)
1313 if(msg
.message
!= WM_MOUSEMOVE
)
1316 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1317 if (pressed
!= oldstate
)
1318 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1322 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1325 ReleaseDC( hwnd
, hdc
);
1326 if (!pressed
) return;
1328 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1332 /***********************************************************************
1335 * Track a mouse button press on the horizontal or vertical scroll-bar.
1337 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1341 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1343 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1344 scrollbar
= SB_HORZ
;
1346 else /* SC_VSCROLL */
1348 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1349 scrollbar
= SB_VERT
;
1351 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1355 /***********************************************************************
1356 * NC_HandleNCLButtonDown
1358 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1360 LONG
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1362 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1364 switch(wParam
) /* Hit test */
1368 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1370 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1371 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1376 if( style
& WS_SYSMENU
)
1378 if( !(style
& WS_MINIMIZE
) )
1380 HDC hDC
= GetWindowDC(hwnd
);
1381 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1382 ReleaseDC( hwnd
, hDC
);
1384 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1389 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1393 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1397 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1402 NC_TrackMinMaxBox( hwnd
, wParam
);
1406 NC_TrackCloseButton (hwnd
, wParam
);
1418 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1419 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1421 /* But that is not what WinNT does. Instead it sends this. This
1422 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1423 * SC_MOUSEMENU into wParam.
1425 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1435 /***********************************************************************
1436 * NC_HandleNCLButtonDblClk
1438 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1440 LONG
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1443 * if this is an icon, send a restore since we are handling
1448 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1452 switch(wParam
) /* Hit test */
1455 /* stop processing if WS_MAXIMIZEBOX is missing */
1456 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1457 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1458 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1462 if (!(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
))
1463 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1467 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1471 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1478 /***********************************************************************
1479 * NC_HandleSysCommand
1481 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1483 LONG
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1485 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam
, lParam
);
1487 if (HOOK_CallHooks( WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
, TRUE
))
1490 switch (wParam
& 0xfff0)
1494 if (USER_Driver
.pSysCommandSizeMove
)
1495 USER_Driver
.pSysCommandSizeMove( hwnd
, wParam
);
1499 if (hwnd
== GetForegroundWindow())
1500 ShowOwnedPopups(hwnd
,FALSE
);
1501 ShowWindow( hwnd
, SW_MINIMIZE
);
1505 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1506 ShowOwnedPopups(hwnd
,TRUE
);
1507 ShowWindow( hwnd
, SW_MAXIMIZE
);
1511 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1512 ShowOwnedPopups(hwnd
,TRUE
);
1513 ShowWindow( hwnd
, SW_RESTORE
);
1517 return SendMessageA( hwnd
, WM_CLOSE
, 0, 0 );
1523 pt
.x
= (short)LOWORD(lParam
);
1524 pt
.y
= (short)HIWORD(lParam
);
1525 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1532 pt
.x
= (short)LOWORD(lParam
);
1533 pt
.y
= (short)HIWORD(lParam
);
1534 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1539 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1543 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1547 if (wParam
== SC_ABOUTWINE
)
1549 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1552 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1553 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1554 FreeLibrary( hmodule
);
1558 if (wParam
== SC_PUTMARK
)
1559 DPRINTF("Debug mark requested by user\n");
1566 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam
);
1572 /*************************************************************
1575 * Stub for the grayed button of the caption
1577 *************************************************************/
1579 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
)
1585 hMaskBmp
= CreateBitmap (12, 10, 1, 1, lpGrayMask
);
1590 hdcMask
= CreateCompatibleDC (0);
1591 SelectObject (hdcMask
, hMaskBmp
);
1593 /* Draw the grayed bitmap using the mask */
1594 hOldBrush
= SelectObject (hdc
, (HGDIOBJ
)RGB(128, 128, 128));
1595 BitBlt (hdc
, x
, y
, 12, 10,
1596 hdcMask
, 0, 0, 0xB8074A);
1599 SelectObject (hdc
, hOldBrush
);
1600 DeleteObject(hMaskBmp
);
1606 /***********************************************************************
1607 * GetTitleBarInfo (USER32.@)
1608 * TODO: Handle STATE_SYSTEM_PRESSED
1610 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1615 TRACE("(%p %p)\n", hwnd
, tbi
);
1617 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1618 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi
->cbSize
);
1619 SetLastError(ERROR_INVALID_PARAMETER
);
1622 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1623 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1624 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1626 GetWindowRect(hwnd
, &wndRect
);
1628 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1629 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1630 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1632 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1633 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1634 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1636 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1637 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1640 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1641 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1642 * Under XP it seems to
1644 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1645 if(dwStyle
& WS_CAPTION
) {
1646 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1647 if(dwStyle
& WS_SYSMENU
) {
1648 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1649 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1650 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1653 if(!(dwStyle
& WS_MINIMIZEBOX
))
1654 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1655 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1656 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1658 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1659 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1660 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1661 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1664 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1665 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1666 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1667 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1671 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;