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
, CACHE_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 (USER.102)
342 BOOL16 WINAPI
AdjustWindowRect16( LPRECT16 rect
, DWORD style
, BOOL16 menu
)
344 return AdjustWindowRectEx16( rect
, style
, menu
, 0 );
348 /***********************************************************************
349 * AdjustWindowRect (USER32.@)
351 BOOL WINAPI
AdjustWindowRect( LPRECT rect
, DWORD style
, BOOL menu
)
353 return AdjustWindowRectEx( rect
, style
, menu
, 0 );
357 /***********************************************************************
358 * AdjustWindowRectEx (USER.454)
360 BOOL16 WINAPI
AdjustWindowRectEx16( LPRECT16 rect
, DWORD style
,
361 BOOL16 menu
, DWORD exStyle
)
366 CONV_RECT16TO32( rect
, &rect32
);
367 ret
= AdjustWindowRectEx( &rect32
, style
, menu
, exStyle
);
368 CONV_RECT32TO16( &rect32
, rect
);
373 /***********************************************************************
374 * AdjustWindowRectEx (USER32.@)
376 BOOL WINAPI
AdjustWindowRectEx( LPRECT rect
, DWORD style
, BOOL menu
, DWORD exStyle
)
378 /* Correct the window style */
379 style
&= (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
| WS_CHILD
);
380 exStyle
&= (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
|
381 WS_EX_STATICEDGE
| WS_EX_TOOLWINDOW
);
382 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
384 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
385 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
386 style
, menu
, exStyle
);
388 NC_AdjustRectOuter( rect
, style
, menu
, exStyle
);
389 NC_AdjustRectInner( rect
, style
, exStyle
);
395 /***********************************************************************
396 * NC_HandleNCCalcSize
398 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
400 LONG
NC_HandleNCCalcSize( HWND hwnd
, RECT
*winRect
)
402 RECT tmpRect
= { 0, 0, 0, 0 };
404 LONG cls_style
= GetClassLongA(hwnd
, GCL_STYLE
);
405 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
406 LONG exStyle
= GetWindowLongA( hwnd
, GWL_EXSTYLE
);
408 if (cls_style
& CS_VREDRAW
) result
|= WVR_VREDRAW
;
409 if (cls_style
& CS_HREDRAW
) result
|= WVR_HREDRAW
;
413 NC_AdjustRectOuter( &tmpRect
, style
, FALSE
, exStyle
);
415 winRect
->left
-= tmpRect
.left
;
416 winRect
->top
-= tmpRect
.top
;
417 winRect
->right
-= tmpRect
.right
;
418 winRect
->bottom
-= tmpRect
.bottom
;
420 if (!(style
& WS_CHILD
) && GetMenu(hwnd
))
422 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
423 hwnd
, winRect
->right
- winRect
->left
, -tmpRect
.left
, -tmpRect
.top
);
426 MENU_GetMenuBarHeight( hwnd
,
427 winRect
->right
- winRect
->left
,
428 -tmpRect
.left
, -tmpRect
.top
) + 1;
431 SetRect(&tmpRect
, 0, 0, 0, 0);
432 NC_AdjustRectInner (&tmpRect
, style
, exStyle
);
433 winRect
->left
-= tmpRect
.left
;
434 winRect
->top
-= tmpRect
.top
;
435 winRect
->right
-= tmpRect
.right
;
436 winRect
->bottom
-= tmpRect
.bottom
;
438 if (winRect
->top
> winRect
->bottom
)
439 winRect
->bottom
= winRect
->top
;
441 if (winRect
->left
> winRect
->right
)
442 winRect
->right
= winRect
->left
;
448 /***********************************************************************
451 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
452 * but without the borders (if any).
453 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
455 void NC_GetInsideRect( HWND hwnd
, RECT
*rect
)
457 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
459 rect
->top
= rect
->left
= 0;
460 rect
->right
= wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
;
461 rect
->bottom
= wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
;
463 if (wndPtr
->dwStyle
& WS_ICONIC
) goto END
;
465 /* Remove frame from rectangle */
466 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
468 InflateRect( rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
470 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
472 InflateRect( rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
474 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
476 InflateRect( rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
) );
479 /* We have additional border information if the window
480 * is a child (but not an MDI child) */
481 if ( (wndPtr
->dwStyle
& WS_CHILD
) &&
482 ( (wndPtr
->dwExStyle
& WS_EX_MDICHILD
) == 0 ) )
484 if (wndPtr
->dwExStyle
& WS_EX_CLIENTEDGE
)
485 InflateRect (rect
, -GetSystemMetrics(SM_CXEDGE
), -GetSystemMetrics(SM_CYEDGE
));
486 if (wndPtr
->dwExStyle
& WS_EX_STATICEDGE
)
487 InflateRect (rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
491 WIN_ReleaseWndPtr(wndPtr
);
496 /***********************************************************************
499 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
501 * FIXME: Just a modified copy of the Win 3.1 version.
504 static LONG
NC_DoNCHitTest (WND
*wndPtr
, POINT pt
)
508 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr
->hwndSelf
, pt
.x
, pt
.y
);
510 GetWindowRect(wndPtr
->hwndSelf
, &rect
);
511 if (!PtInRect( &rect
, pt
)) return HTNOWHERE
;
513 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
516 if (HAS_THICKFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
518 InflateRect( &rect
, -GetSystemMetrics(SM_CXFRAME
), -GetSystemMetrics(SM_CYFRAME
) );
519 if (!PtInRect( &rect
, pt
))
521 /* Check top sizing border */
524 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
525 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
528 /* Check bottom sizing border */
529 if (pt
.y
>= rect
.bottom
)
531 if (pt
.x
< rect
.left
+GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
532 if (pt
.x
>= rect
.right
-GetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
535 /* Check left sizing border */
536 if (pt
.x
< rect
.left
)
538 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
539 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
542 /* Check right sizing border */
543 if (pt
.x
>= rect
.right
)
545 if (pt
.y
< rect
.top
+GetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
546 if (pt
.y
>= rect
.bottom
-GetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
551 else /* No thick frame */
553 if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
554 InflateRect(&rect
, -GetSystemMetrics(SM_CXDLGFRAME
), -GetSystemMetrics(SM_CYDLGFRAME
));
555 else if (HAS_THINFRAME( wndPtr
->dwStyle
))
556 InflateRect(&rect
, -GetSystemMetrics(SM_CXBORDER
), -GetSystemMetrics(SM_CYBORDER
));
557 if (!PtInRect( &rect
, pt
)) return HTBORDER
;
562 if ((wndPtr
->dwStyle
& WS_CAPTION
) == WS_CAPTION
)
564 if (wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
)
565 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
) - 1;
567 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
568 if (!PtInRect( &rect
, pt
))
570 /* Check system menu */
571 if ((wndPtr
->dwStyle
& WS_SYSMENU
) && !(wndPtr
->dwExStyle
& WS_EX_TOOLWINDOW
))
573 if (NC_IconForWindow(wndPtr
->hwndSelf
))
574 rect
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
576 if (pt
.x
< rect
.left
) return HTSYSMENU
;
578 /* Check close button */
579 if (wndPtr
->dwStyle
& WS_SYSMENU
)
580 rect
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
581 if (pt
.x
> rect
.right
) return HTCLOSE
;
583 /* Check maximize box */
584 /* In win95 there is automatically a Maximize button when there is a minimize one*/
585 if ((wndPtr
->dwStyle
& WS_MAXIMIZEBOX
)|| (wndPtr
->dwStyle
& WS_MINIMIZEBOX
))
586 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
587 if (pt
.x
> rect
.right
) return HTMAXBUTTON
;
589 /* Check minimize box */
590 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
591 if ((wndPtr
->dwStyle
& WS_MINIMIZEBOX
)||(wndPtr
->dwStyle
& WS_MAXIMIZEBOX
))
592 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
594 if (pt
.x
> rect
.right
) return HTMINBUTTON
;
599 /* Check client area */
601 ScreenToClient( wndPtr
->hwndSelf
, &pt
);
602 GetClientRect( wndPtr
->hwndSelf
, &rect
);
603 if (PtInRect( &rect
, pt
)) return HTCLIENT
;
605 /* Check vertical scroll bar */
607 if (wndPtr
->dwStyle
& WS_VSCROLL
)
609 if((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
610 rect
.left
-= GetSystemMetrics(SM_CXVSCROLL
);
612 rect
.right
+= GetSystemMetrics(SM_CXVSCROLL
);
613 if (PtInRect( &rect
, pt
)) return HTVSCROLL
;
616 /* Check horizontal scroll bar */
618 if (wndPtr
->dwStyle
& WS_HSCROLL
)
620 rect
.bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
621 if (PtInRect( &rect
, pt
))
624 if ((wndPtr
->dwStyle
& WS_VSCROLL
) &&
625 ((((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rect
.left
+ GetSystemMetrics(SM_CXVSCROLL
))) ||
626 (((wndPtr
->dwExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rect
.right
- GetSystemMetrics(SM_CXVSCROLL
)))))
634 if (HAS_MENU(wndPtr
))
636 if ((pt
.y
< 0) && (pt
.x
>= 0) && (pt
.x
< rect
.right
))
640 /* Has to return HTNOWHERE if nothing was found
641 Could happen when a window has a customized non client area */
646 /***********************************************************************
649 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
651 LONG
NC_HandleNCHitTest (HWND hwnd
, POINT pt
)
654 WND
*wndPtr
= WIN_FindWndPtr (hwnd
);
659 retvalue
= NC_DoNCHitTest (wndPtr
, pt
);
660 WIN_ReleaseWndPtr(wndPtr
);
665 /******************************************************************************
669 * Draws the system icon.
671 *****************************************************************************/
672 BOOL
NC_DrawSysButton (HWND hwnd
, HDC hdc
, BOOL down
)
674 HICON hIcon
= NC_IconForWindow( hwnd
);
679 NC_GetInsideRect( hwnd
, &rect
);
680 DrawIconEx (hdc
, rect
.left
+ 1, rect
.top
+ 1, hIcon
,
681 GetSystemMetrics(SM_CXSIZE
) - 1,
682 GetSystemMetrics(SM_CYSIZE
) - 1, 0, 0, DI_NORMAL
);
688 /******************************************************************************
692 * Draws the close button.
694 * If bGrayed is true, then draw a disabled Close button
696 *****************************************************************************/
698 static void NC_DrawCloseButton (HWND hwnd
, HDC hdc
, BOOL down
, BOOL bGrayed
)
702 NC_GetInsideRect( hwnd
, &rect
);
704 /* A tool window has a smaller Close button */
705 if (GetWindowLongA( hwnd
, GWL_EXSTYLE
) & WS_EX_TOOLWINDOW
)
707 INT iBmpHeight
= 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
708 INT iBmpWidth
= 11; /* it uses 11x11 for the close button in tool window */
709 INT iCaptionHeight
= GetSystemMetrics(SM_CYSMCAPTION
);
711 rect
.top
= rect
.top
+ (iCaptionHeight
- 1 - iBmpHeight
) / 2;
712 rect
.left
= rect
.right
- (iCaptionHeight
+ 1 + iBmpWidth
) / 2;
713 rect
.bottom
= rect
.top
+ iBmpHeight
;
714 rect
.right
= rect
.left
+ iBmpWidth
;
718 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
) - 1;
719 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
723 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
,
725 (down
? DFCS_PUSHED
: 0) |
726 (bGrayed
? DFCS_INACTIVE
: 0)) );
729 /******************************************************************************
732 * Draws the maximize button for windows.
733 * If bGrayed is true, then draw a disabled Maximize button
735 static void NC_DrawMaxButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
738 UINT flags
= IsZoomed(hwnd
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
;
740 NC_GetInsideRect( hwnd
, &rect
);
741 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_SYSMENU
)
742 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
743 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
744 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
747 if (down
) flags
|= DFCS_PUSHED
;
748 if (bGrayed
) flags
|= DFCS_INACTIVE
;
749 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
752 /******************************************************************************
755 * Draws the minimize button for windows.
756 * If bGrayed is true, then draw a disabled Minimize button
758 static void NC_DrawMinButton(HWND hwnd
,HDC hdc
,BOOL down
, BOOL bGrayed
)
761 UINT flags
= DFCS_CAPTIONMIN
;
762 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
764 NC_GetInsideRect( hwnd
, &rect
);
765 if (style
& WS_SYSMENU
)
766 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
767 if (style
& (WS_MAXIMIZEBOX
|WS_MINIMIZEBOX
))
768 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) - 2;
769 rect
.left
= rect
.right
- GetSystemMetrics(SM_CXSIZE
);
770 rect
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
) - 1;
773 if (down
) flags
|= DFCS_PUSHED
;
774 if (bGrayed
) flags
|= DFCS_INACTIVE
;
775 DrawFrameControl( hdc
, &rect
, DFC_CAPTION
, flags
);
778 /******************************************************************************
782 * Draw a window frame inside the given rectangle, and update the rectangle.
785 * Many. First, just what IS a frame in Win95? Note that the 3D look
786 * on the outer edge is handled by NC_DoNCPaint. As is the inner
787 * edge. The inner rectangle just inside the frame is handled by the
790 * In short, for most people, this function should be a nop (unless
791 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
792 * them lately, but just to get this code right). Even so, it doesn't
793 * appear to be so. It's being worked on...
795 *****************************************************************************/
797 static void NC_DrawFrame( HDC hdc
, RECT
*rect
, BOOL active
, DWORD style
, DWORD exStyle
)
801 /* Firstly the "thick" frame */
802 if (style
& WS_THICKFRAME
)
804 width
= GetSystemMetrics(SM_CXFRAME
) - GetSystemMetrics(SM_CXDLGFRAME
);
805 height
= GetSystemMetrics(SM_CYFRAME
) - GetSystemMetrics(SM_CYDLGFRAME
);
807 SelectObject( hdc
, GetSysColorBrush(active
? COLOR_ACTIVEBORDER
:
808 COLOR_INACTIVEBORDER
) );
810 PatBlt( hdc
, rect
->left
, rect
->top
,
811 rect
->right
- rect
->left
, height
, PATCOPY
);
812 PatBlt( hdc
, rect
->left
, rect
->top
,
813 width
, rect
->bottom
- rect
->top
, PATCOPY
);
814 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
815 rect
->right
- rect
->left
, -height
, PATCOPY
);
816 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
817 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
819 InflateRect( rect
, -width
, -height
);
822 /* Now the other bit of the frame */
823 if ((style
& (WS_BORDER
|WS_DLGFRAME
)) ||
824 (exStyle
& WS_EX_DLGMODALFRAME
))
826 width
= GetSystemMetrics(SM_CXDLGFRAME
) - GetSystemMetrics(SM_CXEDGE
);
827 height
= GetSystemMetrics(SM_CYDLGFRAME
) - GetSystemMetrics(SM_CYEDGE
);
828 /* This should give a value of 1 that should also work for a border */
830 SelectObject( hdc
, GetSysColorBrush(
831 (exStyle
& (WS_EX_DLGMODALFRAME
|WS_EX_CLIENTEDGE
)) ?
833 (exStyle
& WS_EX_STATICEDGE
) ?
835 (style
& (WS_DLGFRAME
|WS_THICKFRAME
)) ?
841 PatBlt( hdc
, rect
->left
, rect
->top
,
842 rect
->right
- rect
->left
, height
, PATCOPY
);
843 PatBlt( hdc
, rect
->left
, rect
->top
,
844 width
, rect
->bottom
- rect
->top
, PATCOPY
);
845 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
846 rect
->right
- rect
->left
, -height
, PATCOPY
);
847 PatBlt( hdc
, rect
->right
- 1, rect
->top
,
848 -width
, rect
->bottom
- rect
->top
, PATCOPY
);
850 InflateRect( rect
, -width
, -height
);
855 /******************************************************************************
859 * Draw the window caption for windows.
860 * The correct pen for the window frame must be selected in the DC.
862 *****************************************************************************/
864 static void NC_DrawCaption( HDC hdc
, RECT
*rect
, HWND hwnd
, DWORD style
,
865 DWORD exStyle
, BOOL active
)
872 hPrevPen
= SelectObject( hdc
, SYSCOLOR_GetPen(
873 ((exStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|
874 WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
875 COLOR_WINDOWFRAME
: COLOR_3DFACE
) );
876 MoveToEx( hdc
, r
.left
, r
.bottom
- 1, NULL
);
877 LineTo( hdc
, r
.right
, r
.bottom
- 1 );
878 SelectObject( hdc
, hPrevPen
);
881 FillRect( hdc
, &r
, GetSysColorBrush(active
? COLOR_ACTIVECAPTION
:
882 COLOR_INACTIVECAPTION
) );
884 if ((style
& WS_SYSMENU
) && !(exStyle
& WS_EX_TOOLWINDOW
)) {
885 if (NC_DrawSysButton (hwnd
, hdc
, FALSE
))
886 r
.left
+= GetSystemMetrics(SM_CYCAPTION
) - 1;
889 if (style
& WS_SYSMENU
)
893 /* Go get the sysmenu */
894 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
895 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
897 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
898 NC_DrawCloseButton (hwnd
, hdc
, FALSE
,
899 ((((state
& MF_DISABLED
) || (state
& MF_GRAYED
))) && (state
!= 0xFFFFFFFF)));
900 r
.right
-= GetSystemMetrics(SM_CYCAPTION
) - 1;
902 if ((style
& WS_MAXIMIZEBOX
) || (style
& WS_MINIMIZEBOX
))
904 /* In win95 the two buttons are always there */
905 /* But if the menu item is not in the menu they're disabled*/
907 NC_DrawMaxButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MAXIMIZEBOX
)));
908 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
910 NC_DrawMinButton( hwnd
, hdc
, FALSE
, (!(style
& WS_MINIMIZEBOX
)));
911 r
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
915 if (GetWindowTextA( hwnd
, buffer
, sizeof(buffer
) )) {
916 NONCLIENTMETRICSA nclm
;
917 HFONT hFont
, hOldFont
;
918 nclm
.cbSize
= sizeof(NONCLIENTMETRICSA
);
919 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS
, 0, &nclm
, 0);
920 if (exStyle
& WS_EX_TOOLWINDOW
)
921 hFont
= CreateFontIndirectA (&nclm
.lfSmCaptionFont
);
923 hFont
= CreateFontIndirectA (&nclm
.lfCaptionFont
);
924 hOldFont
= SelectObject (hdc
, hFont
);
925 if (active
) SetTextColor( hdc
, GetSysColor( COLOR_CAPTIONTEXT
) );
926 else SetTextColor( hdc
, GetSysColor( COLOR_INACTIVECAPTIONTEXT
) );
927 SetBkMode( hdc
, TRANSPARENT
);
929 DrawTextA( hdc
, buffer
, -1, &r
,
930 DT_SINGLELINE
| DT_VCENTER
| DT_NOPREFIX
| DT_LEFT
);
931 DeleteObject (SelectObject (hdc
, hOldFont
));
936 /******************************************************************************
940 * Paint the non-client area for windows. The clip region is
944 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
945 * misc/tweak.c controls/menu.c # :-)
947 *****************************************************************************/
949 static void NC_DoNCPaint( HWND hwnd
, HRGN clip
, BOOL suppress_menupaint
)
952 RECT rfuzz
, rect
, rectClip
;
955 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 if (!(hdc
= GetDCEx( hwnd
, (clip
> (HRGN
)1) ? clip
: 0, DCX_USESTYLE
| DCX_WINDOW
|
984 ((clip
> (HRGN
)1) ?(DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
) : 0) ))) return;
987 if (ExcludeVisRect16( HDC_16(hdc
), rectClient
.left
-rectWindow
.left
,
988 rectClient
.top
-rectWindow
.top
,
989 rectClient
.right
-rectWindow
.left
,
990 rectClient
.bottom
-rectWindow
.top
)
993 ReleaseDC( hwnd
, hdc
);
997 rect
.top
= rect
.left
= 0;
998 rect
.right
= rectWindow
.right
- rectWindow
.left
;
999 rect
.bottom
= rectWindow
.bottom
- rectWindow
.top
;
1001 if( clip
> (HRGN
)1 )
1002 GetRgnBox( clip
, &rectClip
);
1009 SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
1011 if (HAS_STATICOUTERFRAME(dwStyle
, dwExStyle
)) {
1012 DrawEdge (hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
| BF_ADJUST
);
1014 else if (HAS_BIGFRAME( dwStyle
, dwExStyle
)) {
1015 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1018 NC_DrawFrame(hdc
, &rect
, active
, dwStyle
, dwExStyle
);
1020 if ((dwStyle
& WS_CAPTION
) == WS_CAPTION
)
1023 if (dwExStyle
& WS_EX_TOOLWINDOW
) {
1024 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYSMCAPTION
);
1025 rect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1028 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYCAPTION
);
1029 rect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1031 if( !clip
|| IntersectRect( &rfuzz
, &r
, &rectClip
) )
1032 NC_DrawCaption(hdc
, &r
, hwnd
, dwStyle
, dwExStyle
, active
);
1038 r
.bottom
= rect
.top
+ GetSystemMetrics(SM_CYMENU
);
1040 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1041 r
.left
, r
.top
, r
.right
, r
.bottom
);
1043 rect
.top
+= MENU_DrawMenuBar( hdc
, &r
, hwnd
, suppress_menupaint
) + 1;
1046 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1047 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1049 if (dwExStyle
& WS_EX_CLIENTEDGE
)
1050 DrawEdge (hdc
, &rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1052 /* Draw the scroll-bars */
1054 if (dwStyle
& WS_VSCROLL
)
1055 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_VERT
, TRUE
, TRUE
);
1056 if (dwStyle
& WS_HSCROLL
)
1057 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_HORZ
, TRUE
, TRUE
);
1059 /* Draw the "size-box" */
1060 if ((dwStyle
& WS_VSCROLL
) && (dwStyle
& WS_HSCROLL
))
1063 if((dwExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1064 r
.right
= r
.left
+ GetSystemMetrics(SM_CXVSCROLL
) + 1;
1066 r
.left
= r
.right
- GetSystemMetrics(SM_CXVSCROLL
) + 1;
1067 r
.top
= r
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) + 1;
1068 FillRect( hdc
, &r
, GetSysColorBrush(COLOR_SCROLLBAR
) );
1071 ReleaseDC( hwnd
, hdc
);
1077 /***********************************************************************
1080 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1082 LONG
NC_HandleNCPaint( HWND hwnd
, HRGN clip
)
1084 DWORD dwStyle
= GetWindowLongW( hwnd
, GWL_STYLE
);
1086 if( dwStyle
& WS_VISIBLE
)
1088 if( dwStyle
& WS_MINIMIZE
)
1089 WINPOS_RedrawIconTitle( hwnd
);
1091 NC_DoNCPaint( hwnd
, clip
, FALSE
);
1097 /***********************************************************************
1098 * NC_HandleNCActivate
1100 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1102 LONG
NC_HandleNCActivate( HWND hwnd
, WPARAM wParam
)
1104 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1106 /* Lotus Notes draws menu descriptions in the caption of its main
1107 * window. When it wants to restore original "system" view, it just
1108 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1109 * attempt to minimize redrawings lead to a not restored caption.
1113 if (wParam
) wndPtr
->flags
|= WIN_NCACTIVATED
;
1114 else wndPtr
->flags
&= ~WIN_NCACTIVATED
;
1115 WIN_ReleaseWndPtr(wndPtr
);
1118 WINPOS_RedrawIconTitle( hwnd
);
1120 NC_DoNCPaint( hwnd
, (HRGN
)1, FALSE
);
1126 /***********************************************************************
1127 * NC_HandleSetCursor
1129 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1131 LONG
NC_HandleSetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1133 hwnd
= WIN_GetFullHandle( (HWND
)wParam
);
1135 switch((short)LOWORD(lParam
))
1139 WORD msg
= HIWORD( lParam
);
1140 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_MBUTTONDOWN
) ||
1141 (msg
== WM_RBUTTONDOWN
))
1148 HCURSOR hCursor
= (HCURSOR
)GetClassLongA(hwnd
, GCL_HCURSOR
);
1158 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZEWE
) );
1162 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENS
) );
1166 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENWSE
) );
1170 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_SIZENESW
) );
1173 /* Default cursor: arrow */
1174 return (LONG
)SetCursor( LoadCursorA( 0, (LPSTR
)IDC_ARROW
) );
1177 /***********************************************************************
1180 void NC_GetSysPopupPos( HWND hwnd
, RECT
* rect
)
1182 if (IsIconic(hwnd
)) GetWindowRect( hwnd
, rect
);
1185 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
1186 if (!wndPtr
) return;
1188 NC_GetInsideRect( hwnd
, rect
);
1189 OffsetRect( rect
, wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
);
1190 if (wndPtr
->dwStyle
& WS_CHILD
)
1191 ClientToScreen( GetParent(hwnd
), (POINT
*)rect
);
1192 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1193 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYCAPTION
) - 1;
1194 WIN_ReleaseWndPtr( wndPtr
);
1198 /***********************************************************************
1201 * Track a mouse button press on the minimize or maximize box.
1203 * The big difference between 3.1 and 95 is the disabled button state.
1204 * In win95 the system button can be disabled, so it can ignore the mouse
1208 static void NC_TrackMinMaxBox( HWND hwnd
, WORD wParam
)
1211 HDC hdc
= GetWindowDC( hwnd
);
1212 BOOL pressed
= TRUE
;
1214 DWORD wndStyle
= GetWindowLongA( hwnd
, GWL_STYLE
);
1215 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1217 void (*paintButton
)(HWND
, HDC
, BOOL
, BOOL
);
1219 if (wParam
== HTMINBUTTON
)
1221 /* If the style is not present, do nothing */
1222 if (!(wndStyle
& WS_MINIMIZEBOX
))
1225 /* Check if the sysmenu item for minimize is there */
1226 state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1228 paintButton
= &NC_DrawMinButton
;
1232 /* If the style is not present, do nothing */
1233 if (!(wndStyle
& WS_MAXIMIZEBOX
))
1236 /* Check if the sysmenu item for maximize is there */
1237 state
= GetMenuState(hSysMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
1239 paintButton
= &NC_DrawMaxButton
;
1244 (*paintButton
)( hwnd
, hdc
, TRUE
, FALSE
);
1248 BOOL oldstate
= pressed
;
1250 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1251 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1253 if(msg
.message
== WM_LBUTTONUP
)
1256 if(msg
.message
!= WM_MOUSEMOVE
)
1259 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1260 if (pressed
!= oldstate
)
1261 (*paintButton
)( hwnd
, hdc
, pressed
, FALSE
);
1265 (*paintButton
)(hwnd
, hdc
, FALSE
, FALSE
);
1268 ReleaseDC( hwnd
, hdc
);
1270 /* If the item minimize or maximize of the sysmenu are not there */
1271 /* or if the style is not present, do nothing */
1272 if ((!pressed
) || (state
== 0xFFFFFFFF))
1275 if (wParam
== HTMINBUTTON
)
1276 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1278 SendMessageA( hwnd
, WM_SYSCOMMAND
,
1279 IsZoomed(hwnd
) ? SC_RESTORE
:SC_MAXIMIZE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1282 /***********************************************************************
1283 * NC_TrackCloseButton
1285 * Track a mouse button press on the Win95 close button.
1287 static void NC_TrackCloseButton (HWND hwnd
, WORD wParam
)
1291 BOOL pressed
= TRUE
;
1292 HMENU hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1298 state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1300 /* If the item close of the sysmenu is disabled or not there do nothing */
1301 if((state
& MF_DISABLED
) || (state
& MF_GRAYED
) || (state
== 0xFFFFFFFF))
1304 hdc
= GetWindowDC( hwnd
);
1308 NC_DrawCloseButton (hwnd
, hdc
, TRUE
, FALSE
);
1312 BOOL oldstate
= pressed
;
1314 if (!GetMessageW( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
)) break;
1315 if (CallMsgFilterW( &msg
, MSGF_MAX
)) continue;
1317 if(msg
.message
== WM_LBUTTONUP
)
1320 if(msg
.message
!= WM_MOUSEMOVE
)
1323 pressed
= (NC_HandleNCHitTest( hwnd
, msg
.pt
) == wParam
);
1324 if (pressed
!= oldstate
)
1325 NC_DrawCloseButton (hwnd
, hdc
, pressed
, FALSE
);
1329 NC_DrawCloseButton (hwnd
, hdc
, FALSE
, FALSE
);
1332 ReleaseDC( hwnd
, hdc
);
1333 if (!pressed
) return;
1335 SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, MAKELONG(msg
.pt
.x
,msg
.pt
.y
) );
1339 /***********************************************************************
1342 * Track a mouse button press on the horizontal or vertical scroll-bar.
1344 static void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
1348 if ((wParam
& 0xfff0) == SC_HSCROLL
)
1350 if ((wParam
& 0x0f) != HTHSCROLL
) return;
1351 scrollbar
= SB_HORZ
;
1353 else /* SC_VSCROLL */
1355 if ((wParam
& 0x0f) != HTVSCROLL
) return;
1356 scrollbar
= SB_VERT
;
1358 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);
1362 /***********************************************************************
1363 * NC_HandleNCLButtonDown
1365 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1367 LONG
NC_HandleNCLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1369 LONG style
= GetWindowLongA( hwnd
, GWL_STYLE
);
1371 switch(wParam
) /* Hit test */
1375 HWND top
= GetAncestor( hwnd
, GA_ROOT
);
1377 if (FOCUS_MouseActivate( top
) || (GetActiveWindow() == top
))
1378 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1383 if( style
& WS_SYSMENU
)
1385 if( !(style
& WS_MINIMIZE
) )
1387 HDC hDC
= GetWindowDC(hwnd
);
1388 NC_DrawSysButton( hwnd
, hDC
, TRUE
);
1389 ReleaseDC( hwnd
, hDC
);
1391 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1396 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_MOUSEMENU
, lParam
);
1400 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1404 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1409 NC_TrackMinMaxBox( hwnd
, wParam
);
1413 NC_TrackCloseButton (hwnd
, wParam
);
1425 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1426 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1428 /* But that is not what WinNT does. Instead it sends this. This
1429 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1430 * SC_MOUSEMENU into wParam.
1432 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
-WMSZ_LEFT
), lParam
);
1442 /***********************************************************************
1443 * NC_HandleNCLButtonDblClk
1445 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1447 LONG
NC_HandleNCLButtonDblClk( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1450 * if this is an icon, send a restore since we are handling
1455 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
);
1459 switch(wParam
) /* Hit test */
1462 /* stop processing if WS_MAXIMIZEBOX is missing */
1463 if (GetWindowLongA( hwnd
, GWL_STYLE
) & WS_MAXIMIZEBOX
)
1464 SendMessageW( hwnd
, WM_SYSCOMMAND
,
1465 IsZoomed(hwnd
) ? SC_RESTORE
: SC_MAXIMIZE
, lParam
);
1469 if (!(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
))
1470 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1474 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1478 SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1485 /***********************************************************************
1486 * NC_HandleSysCommand
1488 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1490 LONG
NC_HandleSysCommand( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1492 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam
, lParam
);
1494 switch (wParam
& 0xfff0)
1498 if (USER_Driver
.pSysCommandSizeMove
)
1499 USER_Driver
.pSysCommandSizeMove( hwnd
, wParam
);
1503 if (hwnd
== GetForegroundWindow())
1504 ShowOwnedPopups(hwnd
,FALSE
);
1505 ShowWindow( hwnd
, SW_MINIMIZE
);
1509 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1510 ShowOwnedPopups(hwnd
,TRUE
);
1511 ShowWindow( hwnd
, SW_MAXIMIZE
);
1515 if (IsIconic(hwnd
) && hwnd
== GetForegroundWindow())
1516 ShowOwnedPopups(hwnd
,TRUE
);
1517 ShowWindow( hwnd
, SW_RESTORE
);
1521 return SendMessageA( hwnd
, WM_CLOSE
, 0, 0 );
1527 pt
.x
= (short)LOWORD(lParam
);
1528 pt
.y
= (short)HIWORD(lParam
);
1529 NC_TrackScrollBar( hwnd
, wParam
, pt
);
1536 pt
.x
= (short)LOWORD(lParam
);
1537 pt
.y
= (short)HIWORD(lParam
);
1538 MENU_TrackMouseMenuBar( hwnd
, wParam
& 0x000F, pt
);
1543 MENU_TrackKbdMenuBar( hwnd
, wParam
, (WCHAR
)lParam
);
1547 WinExec( "taskman.exe", SW_SHOWNORMAL
);
1551 if (wParam
== SC_ABOUTWINE
)
1553 HMODULE hmodule
= LoadLibraryA( "shell32.dll" );
1556 FARPROC aboutproc
= GetProcAddress( hmodule
, "ShellAboutA" );
1557 if (aboutproc
) aboutproc( hwnd
, PACKAGE_NAME
, PACKAGE_STRING
, 0 );
1558 FreeLibrary( hmodule
);
1562 if (wParam
== SC_PUTMARK
)
1563 DPRINTF("Debug mark requested by user\n");
1570 FIXME("unimplemented!\n");
1576 /*************************************************************
1579 * Stub for the grayed button of the caption
1581 *************************************************************/
1583 BOOL
NC_DrawGrayButton(HDC hdc
, int x
, int y
)
1589 hMaskBmp
= CreateBitmap (12, 10, 1, 1, lpGrayMask
);
1594 hdcMask
= CreateCompatibleDC (0);
1595 SelectObject (hdcMask
, hMaskBmp
);
1597 /* Draw the grayed bitmap using the mask */
1598 hOldBrush
= SelectObject (hdc
, (HGDIOBJ
)RGB(128, 128, 128));
1599 BitBlt (hdc
, x
, y
, 12, 10,
1600 hdcMask
, 0, 0, 0xB8074A);
1603 SelectObject (hdc
, hOldBrush
);
1604 DeleteObject(hMaskBmp
);
1610 /***********************************************************************
1611 * GetTitleBarInfo (USER32.@)
1612 * TODO: Handle STATE_SYSTEM_PRESSED
1614 BOOL WINAPI
GetTitleBarInfo(HWND hwnd
, PTITLEBARINFO tbi
) {
1619 TRACE("(%p %p)\n", hwnd
, tbi
);
1621 if(tbi
->cbSize
!= sizeof(TITLEBARINFO
)) {
1622 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi
->cbSize
);
1623 SetLastError(ERROR_INVALID_PARAMETER
);
1626 dwStyle
= GetWindowLongW(hwnd
, GWL_STYLE
);
1627 dwExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
1628 NC_GetInsideRect(hwnd
, &tbi
->rcTitleBar
);
1630 GetWindowRect(hwnd
, &wndRect
);
1632 tbi
->rcTitleBar
.top
+= wndRect
.top
;
1633 tbi
->rcTitleBar
.left
+= wndRect
.left
;
1634 tbi
->rcTitleBar
.right
+= wndRect
.left
;
1636 tbi
->rcTitleBar
.bottom
= tbi
->rcTitleBar
.top
;
1637 if(dwExStyle
& WS_EX_TOOLWINDOW
)
1638 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYSMCAPTION
);
1640 tbi
->rcTitleBar
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
1641 tbi
->rcTitleBar
.left
+= GetSystemMetrics(SM_CXSIZE
);
1644 ZeroMemory(&tbi
->rgstate
, sizeof(tbi
->rgstate
));
1645 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1646 * Under XP it seems to
1648 tbi
->rgstate
[0] = STATE_SYSTEM_FOCUSABLE
;
1649 if(dwStyle
& WS_CAPTION
) {
1650 tbi
->rgstate
[1] = STATE_SYSTEM_INVISIBLE
;
1651 if(dwStyle
& WS_SYSMENU
) {
1652 if(!(dwStyle
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
))) {
1653 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1654 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1657 if(!(dwStyle
& WS_MINIMIZEBOX
))
1658 tbi
->rgstate
[2] = STATE_SYSTEM_UNAVAILABLE
;
1659 if(!(dwStyle
& WS_MAXIMIZEBOX
))
1660 tbi
->rgstate
[3] = STATE_SYSTEM_UNAVAILABLE
;
1662 if(!(dwExStyle
& WS_EX_CONTEXTHELP
))
1663 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1664 if(GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
1665 tbi
->rgstate
[5] = STATE_SYSTEM_UNAVAILABLE
;
1668 tbi
->rgstate
[2] = STATE_SYSTEM_INVISIBLE
;
1669 tbi
->rgstate
[3] = STATE_SYSTEM_INVISIBLE
;
1670 tbi
->rgstate
[4] = STATE_SYSTEM_INVISIBLE
;
1671 tbi
->rgstate
[5] = STATE_SYSTEM_INVISIBLE
;
1675 tbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;