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"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
38 WINE_DECLARE_DEBUG_CHANNEL(shell);
40 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
42 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
53 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
54 #define SC_PUTMARK (SC_SCREENSAVE+2)
56 /* Some useful macros */
57 #define HAS_DLGFRAME(style,exStyle) \
58 (((exStyle) & WS_EX_DLGMODALFRAME) || \
59 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
61 #define HAS_THICKFRAME(style,exStyle) \
62 (((style) & WS_THICKFRAME) && \
63 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
65 #define HAS_THINFRAME(style) \
66 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
68 #define HAS_BIGFRAME(style,exStyle) \
69 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
70 ((exStyle) & WS_EX_DLGMODALFRAME))
72 #define HAS_STATICOUTERFRAME(style,exStyle) \
73 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
76 #define HAS_ANYFRAME(style,exStyle) \
77 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
78 ((exStyle) & WS_EX_DLGMODALFRAME) || \
79 !((style) & (WS_CHILD | WS_POPUP)))
81 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
84 /******************************************************************************
87 * Computes the size of the "outside" parts of the window based on the
88 * parameters of the client area.
97 * "Outer" parts of a window means the whole window frame, caption and
98 * menu bar. It does not include "inner" parts of the frame like client
99 * edge, static edge or scroll bars.
101 *****************************************************************************/
104 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
107 if(style & WS_ICONIC) return;
109 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
112 adjust = 1; /* for the outer frame always present */
117 if ((exStyle & WS_EX_DLGMODALFRAME) ||
118 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
120 if (style & WS_THICKFRAME)
121 adjust += ( GetSystemMetrics (SM_CXFRAME)
122 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
123 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
124 (exStyle & WS_EX_DLGMODALFRAME))
125 adjust++; /* The other border */
127 InflateRect (rect, adjust, adjust);
129 if ((style & WS_CAPTION) == WS_CAPTION)
131 if (exStyle & WS_EX_TOOLWINDOW)
132 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
134 rect->top -= GetSystemMetrics(SM_CYCAPTION);
136 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
140 /******************************************************************************
143 * Computes the size of the "inside" part of the window based on the
144 * parameters of the client area.
152 * "Inner" part of a window means the window frame inside of the flat
153 * window frame. It includes the client edge, the static edge and the
156 *****************************************************************************/
159 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
161 if(style & WS_ICONIC) return;
163 if (exStyle & WS_EX_CLIENTEDGE)
164 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
166 if (style & WS_VSCROLL)
168 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
169 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
171 rect->right += GetSystemMetrics(SM_CXVSCROLL);
173 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
178 static HICON NC_IconForWindow( HWND hwnd )
181 WND *wndPtr = WIN_GetPtr( hwnd );
183 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
185 hIcon = wndPtr->hIconSmall;
186 if (!hIcon) hIcon = wndPtr->hIcon;
187 WIN_ReleasePtr( wndPtr );
189 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
190 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
192 /* If there is no hIcon specified and this is a modal dialog,
193 * get the default one.
195 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
196 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
200 /* Draws the bar part(ie the big rectangle) of the caption */
201 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
202 BOOL active, BOOL gradient)
206 TRIVERTEX vertices[6];
208 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
210 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
211 : COLOR_GRADIENTINACTIVECAPTION);
213 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
214 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
216 for (v = 0; v < 3; v++)
218 vertices[v].Red = GetRValue (colLeft) << 8;
219 vertices[v].Green = GetGValue (colLeft) << 8;
220 vertices[v].Blue = GetBValue (colLeft) << 8;
221 vertices[v].Alpha = 0x8000;
222 vertices[v+3].Red = GetRValue (colRight) << 8;
223 vertices[v+3].Green = GetGValue (colRight) << 8;
224 vertices[v+3].Blue = GetBValue (colRight) << 8;
225 vertices[v+3].Alpha = 0x8000;
228 if ((dwStyle & WS_SYSMENU)
229 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
230 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
232 /* area behind icon; solid filled with left color */
233 vertices[0].x = rect->left;
234 vertices[0].y = rect->top;
235 if (dwStyle & WS_SYSMENU)
237 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
239 vertices[1].x = vertices[0].x;
240 vertices[1].y = rect->bottom;
242 /* area behind text; gradient */
243 vertices[2].x = vertices[1].x;
244 vertices[2].y = rect->top;
245 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
246 vertices[3].y = rect->bottom;
248 /* area behind buttons; solid filled with right color */
249 vertices[4].x = vertices[3].x;
250 vertices[4].y = rect->top;
251 vertices[5].x = rect->right;
252 vertices[5].y = rect->bottom;
254 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
257 FillRect (hdc, rect, GetSysColorBrush (active ?
258 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
261 /***********************************************************************
262 * DrawCaption (USER32.@) Draws a caption bar
276 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
278 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
282 /***********************************************************************
283 * DrawCaptionTempA (USER32.@)
285 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
286 HICON hIcon, LPCSTR str, UINT uFlags)
292 if (!(uFlags & DC_TEXT) || !str)
293 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
295 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
296 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
298 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
299 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
300 HeapFree( GetProcessHeap (), 0, strW );
306 /***********************************************************************
307 * DrawCaptionTempW (USER32.@)
309 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
310 HICON hIcon, LPCWSTR str, UINT uFlags)
314 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
315 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
317 /* drawing background */
318 if (uFlags & DC_INBUTTON) {
319 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
321 if (uFlags & DC_ACTIVE) {
322 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
323 PatBlt (hdc, rc.left, rc.top,
324 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
325 SelectObject (hdc, hbr);
329 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
330 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
335 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
339 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
341 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
342 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
343 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
344 rc.left += (rc.bottom - rc.top);
348 if (uFlags & DC_TEXT) {
351 if (uFlags & DC_INBUTTON)
352 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
353 else if (uFlags & DC_ACTIVE)
354 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
356 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
358 SetBkMode (hdc, TRANSPARENT);
361 hOldFont = SelectObject (hdc, hFont);
363 NONCLIENTMETRICSW nclm;
365 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
366 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
367 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
368 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
369 hOldFont = SelectObject (hdc, hNewFont);
373 DrawTextW (hdc, str, -1, &rc,
374 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
378 nLen = GetWindowTextW (hwnd, szText, 128);
379 DrawTextW (hdc, szText, nLen, &rc,
380 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
384 SelectObject (hdc, hOldFont);
386 DeleteObject (SelectObject (hdc, hOldFont));
389 /* drawing focus ??? */
391 FIXME("undocumented flag (0x2000)!\n");
397 /***********************************************************************
398 * AdjustWindowRect (USER32.@)
400 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
402 return AdjustWindowRectEx( rect, style, menu, 0 );
406 /***********************************************************************
407 * AdjustWindowRectEx (USER32.@)
409 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
411 /* Correct the window style */
412 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
413 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
414 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
415 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
417 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
418 rect->left, rect->top, rect->right, rect->bottom,
419 style, menu, exStyle );
421 NC_AdjustRectOuter( rect, style, menu, exStyle );
422 NC_AdjustRectInner( rect, style, exStyle );
428 /***********************************************************************
429 * NC_HandleNCCalcSize
431 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
433 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
435 RECT tmpRect = { 0, 0, 0, 0 };
437 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
438 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
439 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
441 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
442 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
446 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
448 winRect->left -= tmpRect.left;
449 winRect->top -= tmpRect.top;
450 winRect->right -= tmpRect.right;
451 winRect->bottom -= tmpRect.bottom;
453 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
455 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
456 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
459 MENU_GetMenuBarHeight( hwnd,
460 winRect->right - winRect->left,
461 -tmpRect.left, -tmpRect.top );
464 if( exStyle & WS_EX_CLIENTEDGE)
465 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
466 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
467 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
468 - GetSystemMetrics(SM_CYEDGE));
470 if (style & WS_VSCROLL)
471 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
472 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
473 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
475 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
478 if (style & WS_HSCROLL)
479 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
480 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
482 if (winRect->top > winRect->bottom)
483 winRect->bottom = winRect->top;
485 if (winRect->left > winRect->right)
486 winRect->right = winRect->left;
492 /***********************************************************************
495 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
496 * but without the borders (if any).
497 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
499 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
501 WND *wndPtr = WIN_GetPtr( hwnd );
503 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
505 rect->top = rect->left = 0;
506 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
507 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
509 if (wndPtr->dwStyle & WS_ICONIC) goto END;
511 /* Remove frame from rectangle */
512 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
514 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
516 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
518 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
520 else if (HAS_THINFRAME( wndPtr->dwStyle ))
522 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
525 /* We have additional border information if the window
526 * is a child (but not an MDI child) */
527 if ( (wndPtr->dwStyle & WS_CHILD) &&
528 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
530 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
531 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
532 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
533 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
537 WIN_ReleasePtr( wndPtr );
541 /***********************************************************************
544 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
546 * FIXME: Just a modified copy of the Win 3.1 version.
549 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
554 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
556 GetWindowRect(wndPtr->hwndSelf, &rect );
557 if (!PtInRect( &rect, pt )) return HTNOWHERE;
559 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
561 /* Check client area */
563 ScreenToClient( wndPtr->hwndSelf, &ptClient );
564 GetClientRect( wndPtr->hwndSelf, &rcClient );
565 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
568 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
570 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
571 if (!PtInRect( &rect, pt ))
573 /* Check top sizing border */
576 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
577 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
580 /* Check bottom sizing border */
581 if (pt.y >= rect.bottom)
583 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
584 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
587 /* Check left sizing border */
588 if (pt.x < rect.left)
590 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
591 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
594 /* Check right sizing border */
595 if (pt.x >= rect.right)
597 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
598 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
603 else /* No thick frame */
605 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
606 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
607 else if (HAS_THINFRAME( wndPtr->dwStyle ))
608 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
609 if (!PtInRect( &rect, pt )) return HTBORDER;
614 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
616 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
617 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
619 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
620 if (!PtInRect( &rect, pt ))
622 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
623 (wndPtr->dwStyle & WS_MINIMIZEBOX);
624 /* Check system menu */
625 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
627 if (NC_IconForWindow(wndPtr->hwndSelf))
628 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
630 if (pt.x < rect.left) return HTSYSMENU;
632 /* Check close button */
633 if (wndPtr->dwStyle & WS_SYSMENU)
634 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
635 if (pt.x > rect.right) return HTCLOSE;
637 /* Check maximize box */
638 /* In win95 there is automatically a Maximize button when there is a minimize one*/
639 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
640 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
641 if (pt.x > rect.right) return HTMAXBUTTON;
643 /* Check minimize box */
644 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
645 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
646 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
648 if (pt.x > rect.right) return HTMINBUTTON;
653 /* Check vertical scroll bar */
655 if (wndPtr->dwStyle & WS_VSCROLL)
657 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
658 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
660 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
661 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
664 /* Check horizontal scroll bar */
666 if (wndPtr->dwStyle & WS_HSCROLL)
668 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
669 if (PtInRect( &rcClient, ptClient ))
672 if ((wndPtr->dwStyle & WS_VSCROLL) &&
673 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
674 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
682 if (HAS_MENU(wndPtr))
684 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
688 /* Has to return HTNOWHERE if nothing was found
689 Could happen when a window has a customized non client area */
694 /***********************************************************************
697 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
699 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
702 WND *wndPtr = WIN_GetPtr( hwnd );
704 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
706 retvalue = NC_DoNCHitTest (wndPtr, pt);
707 WIN_ReleasePtr( wndPtr );
712 /******************************************************************************
716 * Draws the system icon.
718 *****************************************************************************/
719 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
721 HICON hIcon = NC_IconForWindow( hwnd );
726 NC_GetInsideRect( hwnd, &rect );
727 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
728 GetSystemMetrics(SM_CXSMICON),
729 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
735 /******************************************************************************
739 * Draws the close button.
741 * If bGrayed is true, then draw a disabled Close button
743 *****************************************************************************/
745 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
749 NC_GetInsideRect( hwnd, &rect );
751 /* A tool window has a smaller Close button */
752 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
754 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
755 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
756 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
758 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
759 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
760 rect.bottom = rect.top + iBmpHeight;
761 rect.right = rect.left + iBmpWidth;
765 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
766 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
770 DrawFrameControl( hdc, &rect, DFC_CAPTION,
772 (down ? DFCS_PUSHED : 0) |
773 (bGrayed ? DFCS_INACTIVE : 0)) );
776 /******************************************************************************
779 * Draws the maximize button for windows.
780 * If bGrayed is true, then draw a disabled Maximize button
782 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
787 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
788 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
791 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
793 NC_GetInsideRect( hwnd, &rect );
794 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
795 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
796 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
797 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
800 if (down) flags |= DFCS_PUSHED;
801 if (bGrayed) flags |= DFCS_INACTIVE;
802 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
805 /******************************************************************************
808 * Draws the minimize button for windows.
809 * If bGrayed is true, then draw a disabled Minimize button
811 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
814 UINT flags = DFCS_CAPTIONMIN;
815 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
817 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
818 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
821 NC_GetInsideRect( hwnd, &rect );
822 if (style & WS_SYSMENU)
823 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
824 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
825 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
826 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
827 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
830 if (down) flags |= DFCS_PUSHED;
831 if (bGrayed) flags |= DFCS_INACTIVE;
832 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
835 /******************************************************************************
839 * Draw a window frame inside the given rectangle, and update the rectangle.
842 * Many. First, just what IS a frame in Win95? Note that the 3D look
843 * on the outer edge is handled by NC_DoNCPaint. As is the inner
844 * edge. The inner rectangle just inside the frame is handled by the
847 * In short, for most people, this function should be a nop (unless
848 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
849 * them lately, but just to get this code right). Even so, it doesn't
850 * appear to be so. It's being worked on...
852 *****************************************************************************/
854 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
858 /* Firstly the "thick" frame */
859 if (style & WS_THICKFRAME)
861 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
862 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
864 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
865 COLOR_INACTIVEBORDER) );
867 PatBlt( hdc, rect->left, rect->top,
868 rect->right - rect->left, height, PATCOPY );
869 PatBlt( hdc, rect->left, rect->top,
870 width, rect->bottom - rect->top, PATCOPY );
871 PatBlt( hdc, rect->left, rect->bottom - 1,
872 rect->right - rect->left, -height, PATCOPY );
873 PatBlt( hdc, rect->right - 1, rect->top,
874 -width, rect->bottom - rect->top, PATCOPY );
876 InflateRect( rect, -width, -height );
879 /* Now the other bit of the frame */
880 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
881 (exStyle & WS_EX_DLGMODALFRAME))
883 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
884 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
885 /* This should give a value of 1 that should also work for a border */
887 SelectObject( hdc, GetSysColorBrush(
888 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
890 (exStyle & WS_EX_STATICEDGE) ?
892 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
898 PatBlt( hdc, rect->left, rect->top,
899 rect->right - rect->left, height, PATCOPY );
900 PatBlt( hdc, rect->left, rect->top,
901 width, rect->bottom - rect->top, PATCOPY );
902 PatBlt( hdc, rect->left, rect->bottom - 1,
903 rect->right - rect->left, -height, PATCOPY );
904 PatBlt( hdc, rect->right - 1, rect->top,
905 -width, rect->bottom - rect->top, PATCOPY );
907 InflateRect( rect, -width, -height );
912 /******************************************************************************
916 * Draw the window caption for windows.
917 * The correct pen for the window frame must be selected in the DC.
919 *****************************************************************************/
921 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
922 DWORD exStyle, BOOL active )
928 BOOL gradient = FALSE;
930 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
931 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
932 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
933 COLOR_WINDOWFRAME : COLOR_3DFACE) );
934 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
935 LineTo( hdc, r.right, r.bottom - 1 );
936 SelectObject( hdc, hPrevPen );
939 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
940 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
942 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
943 if (NC_DrawSysButton (hwnd, hdc, FALSE))
944 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
947 if (style & WS_SYSMENU)
951 /* Go get the sysmenu */
952 hSysMenu = GetSystemMenu(hwnd, FALSE);
953 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
955 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
956 NC_DrawCloseButton (hwnd, hdc, FALSE,
957 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
958 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
960 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
962 /* In win95 the two buttons are always there */
963 /* But if the menu item is not in the menu they're disabled*/
965 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
966 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
968 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
969 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
973 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
975 NONCLIENTMETRICSW nclm;
976 HFONT hFont, hOldFont;
977 nclm.cbSize = sizeof(nclm);
978 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
979 if (exStyle & WS_EX_TOOLWINDOW)
980 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
982 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
983 hOldFont = SelectObject (hdc, hFont);
984 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
985 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
986 SetBkMode( hdc, TRANSPARENT );
988 DrawTextW( hdc, buffer, -1, &r,
989 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
990 DeleteObject (SelectObject (hdc, hOldFont));
995 /******************************************************************************
998 * Paint the non-client area for windows.
1000 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1003 RECT rfuzz, rect, rectClip;
1006 DWORD dwStyle, dwExStyle;
1009 RECT rectClient, rectWindow;
1012 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1013 has_menu = HAS_MENU(wndPtr);
1014 dwStyle = wndPtr->dwStyle;
1015 dwExStyle = wndPtr->dwExStyle;
1016 flags = wndPtr->flags;
1017 rectWindow = wndPtr->rectWindow;
1018 WIN_ReleasePtr( wndPtr );
1020 if ( dwStyle & WS_MINIMIZE ||
1021 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1023 active = flags & WIN_NCACTIVATED;
1025 TRACE("%p %d\n", hwnd, active );
1027 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1028 the call to GetDCEx implying that it is allowed not to use it either.
1029 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1030 will cause clipRgn to be deleted after ReleaseDC().
1031 Now, how is the "system" supposed to tell what happened?
1034 GetClientRect( hwnd, &rectClient );
1035 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1036 hrgn = CreateRectRgnIndirect( &rectClient );
1040 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1041 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1045 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1050 rect.top = rect.left = 0;
1051 rect.right = rectWindow.right - rectWindow.left;
1052 rect.bottom = rectWindow.bottom - rectWindow.top;
1053 GetClipBox( hdc, &rectClip );
1055 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1057 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1058 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1060 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1061 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1064 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1066 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1069 if (dwExStyle & WS_EX_TOOLWINDOW) {
1070 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1071 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1074 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1075 rect.top += GetSystemMetrics(SM_CYCAPTION);
1077 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1078 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1084 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1086 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1087 r.left, r.top, r.right, r.bottom);
1089 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1092 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1093 rect.left, rect.top, rect.right, rect.bottom );
1095 if (dwExStyle & WS_EX_CLIENTEDGE)
1096 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1098 /* Draw the scroll-bars */
1100 if (dwStyle & WS_VSCROLL)
1101 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1102 if (dwStyle & WS_HSCROLL)
1103 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1105 /* Draw the "size-box" */
1106 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1109 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1110 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1112 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1113 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1114 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1117 ReleaseDC( hwnd, hdc );
1123 /***********************************************************************
1126 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1128 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1130 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1132 if( dwStyle & WS_VISIBLE )
1134 if( dwStyle & WS_MINIMIZE )
1135 WINPOS_RedrawIconTitle( hwnd );
1137 NC_DoNCPaint( hwnd, clip, FALSE );
1143 /***********************************************************************
1144 * NC_HandleNCActivate
1146 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1148 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1150 WND* wndPtr = WIN_GetPtr( hwnd );
1152 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1154 /* Lotus Notes draws menu descriptions in the caption of its main
1155 * window. When it wants to restore original "system" view, it just
1156 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1157 * attempt to minimize redrawings lead to a not restored caption.
1159 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1160 else wndPtr->flags &= ~WIN_NCACTIVATED;
1161 WIN_ReleasePtr( wndPtr );
1164 WINPOS_RedrawIconTitle( hwnd );
1166 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1172 /***********************************************************************
1173 * NC_HandleSetCursor
1175 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1177 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1179 hwnd = WIN_GetFullHandle( (HWND)wParam );
1181 switch((short)LOWORD(lParam))
1185 WORD msg = HIWORD( lParam );
1186 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1187 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1194 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1204 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1208 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1212 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1216 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1219 /* Default cursor: arrow */
1220 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1223 /***********************************************************************
1226 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1228 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1231 WND *wndPtr = WIN_GetPtr( hwnd );
1232 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1234 NC_GetInsideRect( hwnd, rect );
1235 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1236 if (wndPtr->dwStyle & WS_CHILD)
1237 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1238 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1239 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1240 WIN_ReleasePtr( wndPtr );
1244 /***********************************************************************
1247 * Track a mouse button press on the minimize or maximize box.
1249 * The big difference between 3.1 and 95 is the disabled button state.
1250 * In win95 the system button can be disabled, so it can ignore the mouse
1254 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1257 HDC hdc = GetWindowDC( hwnd );
1258 BOOL pressed = TRUE;
1260 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1261 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1263 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1265 if (wParam == HTMINBUTTON)
1267 /* If the style is not present, do nothing */
1268 if (!(wndStyle & WS_MINIMIZEBOX))
1271 /* Check if the sysmenu item for minimize is there */
1272 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1274 paintButton = &NC_DrawMinButton;
1278 /* If the style is not present, do nothing */
1279 if (!(wndStyle & WS_MAXIMIZEBOX))
1282 /* Check if the sysmenu item for maximize is there */
1283 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1285 paintButton = &NC_DrawMaxButton;
1290 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1294 BOOL oldstate = pressed;
1296 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1297 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1299 if(msg.message == WM_LBUTTONUP)
1302 if(msg.message != WM_MOUSEMOVE)
1305 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1306 if (pressed != oldstate)
1307 (*paintButton)( hwnd, hdc, pressed, FALSE);
1311 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1314 ReleaseDC( hwnd, hdc );
1316 /* If the item minimize or maximize of the sysmenu are not there */
1317 /* or if the style is not present, do nothing */
1318 if ((!pressed) || (state == 0xFFFFFFFF))
1321 if (wParam == HTMINBUTTON)
1322 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1324 SendMessageA( hwnd, WM_SYSCOMMAND,
1325 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1328 /***********************************************************************
1329 * NC_TrackCloseButton
1331 * Track a mouse button press on the Win95 close button.
1333 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1337 BOOL pressed = TRUE;
1338 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1344 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1346 /* If the item close of the sysmenu is disabled or not there do nothing */
1347 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1350 hdc = GetWindowDC( hwnd );
1354 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1358 BOOL oldstate = pressed;
1360 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1361 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1363 if(msg.message == WM_LBUTTONUP)
1366 if(msg.message != WM_MOUSEMOVE)
1369 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1370 if (pressed != oldstate)
1371 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1375 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1378 ReleaseDC( hwnd, hdc );
1379 if (!pressed) return;
1381 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1385 /***********************************************************************
1388 * Track a mouse button press on the horizontal or vertical scroll-bar.
1390 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1394 if ((wParam & 0xfff0) == SC_HSCROLL)
1396 if ((wParam & 0x0f) != HTHSCROLL) return;
1397 scrollbar = SB_HORZ;
1399 else /* SC_VSCROLL */
1401 if ((wParam & 0x0f) != HTVSCROLL) return;
1402 scrollbar = SB_VERT;
1404 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1408 /***********************************************************************
1409 * NC_HandleNCLButtonDown
1411 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1413 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1415 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1417 switch(wParam) /* Hit test */
1421 HWND top = GetAncestor( hwnd, GA_ROOT );
1423 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1424 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1429 if( style & WS_SYSMENU )
1431 if( !(style & WS_MINIMIZE) )
1433 HDC hDC = GetWindowDC(hwnd);
1434 NC_DrawSysButton( hwnd, hDC, TRUE );
1435 ReleaseDC( hwnd, hDC );
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1442 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1446 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1450 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1455 NC_TrackMinMaxBox( hwnd, wParam );
1459 NC_TrackCloseButton (hwnd, wParam);
1471 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1472 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1474 /* But that is not what WinNT does. Instead it sends this. This
1475 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1476 * SC_MOUSEMENU into wParam.
1478 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1488 /***********************************************************************
1489 * NC_HandleNCLButtonDblClk
1491 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1493 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1496 * if this is an icon, send a restore since we are handling
1501 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1505 switch(wParam) /* Hit test */
1508 /* stop processing if WS_MAXIMIZEBOX is missing */
1509 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1510 SendMessageW( hwnd, WM_SYSCOMMAND,
1511 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1516 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1517 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1519 /* If the item close of the sysmenu is disabled or not there do nothing */
1520 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1523 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1528 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1532 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1539 /***********************************************************************
1540 * NC_HandleSysCommand
1542 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1544 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1546 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1548 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1551 switch (wParam & 0xfff0)
1555 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1559 if (hwnd == GetForegroundWindow())
1560 ShowOwnedPopups(hwnd,FALSE);
1561 ShowWindow( hwnd, SW_MINIMIZE );
1565 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1566 ShowOwnedPopups(hwnd,TRUE);
1567 ShowWindow( hwnd, SW_MAXIMIZE );
1571 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1572 ShowOwnedPopups(hwnd,TRUE);
1573 ShowWindow( hwnd, SW_RESTORE );
1577 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1583 pt.x = (short)LOWORD(lParam);
1584 pt.y = (short)HIWORD(lParam);
1585 NC_TrackScrollBar( hwnd, wParam, pt );
1592 pt.x = (short)LOWORD(lParam);
1593 pt.y = (short)HIWORD(lParam);
1594 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1599 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1603 WinExec( "taskman.exe", SW_SHOWNORMAL );
1607 if (wParam == SC_ABOUTWINE)
1609 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1612 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1613 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1614 FreeLibrary( hmodule );
1618 if (wParam == SC_PUTMARK)
1619 DPRINTF("Debug mark requested by user\n");
1626 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1632 /*************************************************************
1635 * Stub for the grayed button of the caption
1637 *************************************************************/
1639 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1645 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1650 hdcMask = CreateCompatibleDC (0);
1651 SelectObject (hdcMask, hMaskBmp);
1653 /* Draw the grayed bitmap using the mask */
1654 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1655 BitBlt (hdc, x, y, 12, 10,
1656 hdcMask, 0, 0, 0xB8074A);
1659 SelectObject (hdc, hOldBrush);
1660 DeleteObject(hMaskBmp);
1666 /***********************************************************************
1667 * GetTitleBarInfo (USER32.@)
1668 * TODO: Handle STATE_SYSTEM_PRESSED
1670 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1675 TRACE("(%p %p)\n", hwnd, tbi);
1677 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1678 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1679 SetLastError(ERROR_INVALID_PARAMETER);
1682 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1683 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1684 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1686 GetWindowRect(hwnd, &wndRect);
1688 tbi->rcTitleBar.top += wndRect.top;
1689 tbi->rcTitleBar.left += wndRect.left;
1690 tbi->rcTitleBar.right += wndRect.left;
1692 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1693 if(dwExStyle & WS_EX_TOOLWINDOW)
1694 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1696 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1697 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1700 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1701 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1702 * Under XP it seems to
1704 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1705 if(dwStyle & WS_CAPTION) {
1706 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1707 if(dwStyle & WS_SYSMENU) {
1708 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1709 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1710 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1713 if(!(dwStyle & WS_MINIMIZEBOX))
1714 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1715 if(!(dwStyle & WS_MAXIMIZEBOX))
1716 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1718 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1719 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1720 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1721 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1724 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1726 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1727 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1731 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;