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);
39 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
41 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
52 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
53 #define SC_PUTMARK (SC_SCREENSAVE+2)
55 /* Some useful macros */
56 #define HAS_DLGFRAME(style,exStyle) \
57 (((exStyle) & WS_EX_DLGMODALFRAME) || \
58 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
60 #define HAS_THICKFRAME(style,exStyle) \
61 (((style) & WS_THICKFRAME) && \
62 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
64 #define HAS_THINFRAME(style) \
65 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
67 #define HAS_BIGFRAME(style,exStyle) \
68 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
69 ((exStyle) & WS_EX_DLGMODALFRAME))
71 #define HAS_STATICOUTERFRAME(style,exStyle) \
72 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
75 #define HAS_ANYFRAME(style,exStyle) \
76 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
77 ((exStyle) & WS_EX_DLGMODALFRAME) || \
78 !((style) & (WS_CHILD | WS_POPUP)))
80 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
83 /******************************************************************************
86 * Computes the size of the "outside" parts of the window based on the
87 * parameters of the client area.
96 * "Outer" parts of a window means the whole window frame, caption and
97 * menu bar. It does not include "inner" parts of the frame like client
98 * edge, static edge or scroll bars.
100 *****************************************************************************/
103 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
106 if(style & WS_ICONIC) return;
108 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
111 adjust = 1; /* for the outer frame always present */
116 if ((exStyle & WS_EX_DLGMODALFRAME) ||
117 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
119 if (style & WS_THICKFRAME)
120 adjust += ( GetSystemMetrics (SM_CXFRAME)
121 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
122 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
123 (exStyle & WS_EX_DLGMODALFRAME))
124 adjust++; /* The other border */
126 InflateRect (rect, adjust, adjust);
128 if ((style & WS_CAPTION) == WS_CAPTION)
130 if (exStyle & WS_EX_TOOLWINDOW)
131 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
133 rect->top -= GetSystemMetrics(SM_CYCAPTION);
135 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
139 /******************************************************************************
142 * Computes the size of the "inside" part of the window based on the
143 * parameters of the client area.
151 * "Inner" part of a window means the window frame inside of the flat
152 * window frame. It includes the client edge, the static edge and the
155 *****************************************************************************/
158 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
160 if(style & WS_ICONIC) return;
162 if (exStyle & WS_EX_CLIENTEDGE)
163 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
165 if (style & WS_VSCROLL)
167 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
168 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
170 rect->right += GetSystemMetrics(SM_CXVSCROLL);
172 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
177 static HICON NC_IconForWindow( HWND hwnd )
180 WND *wndPtr = WIN_GetPtr( hwnd );
182 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
184 hIcon = wndPtr->hIconSmall;
185 if (!hIcon) hIcon = wndPtr->hIcon;
186 WIN_ReleasePtr( wndPtr );
188 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
189 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
191 /* If there is no hIcon specified and this is a modal dialog,
192 * get the default one.
194 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
195 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
199 /* Draws the bar part(ie the big rectangle) of the caption */
200 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
201 BOOL active, BOOL gradient)
205 TRIVERTEX vertices[6];
207 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
209 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
210 : COLOR_GRADIENTINACTIVECAPTION);
212 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
213 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
215 for (v = 0; v < 3; v++)
217 vertices[v].Red = GetRValue (colLeft) << 8;
218 vertices[v].Green = GetGValue (colLeft) << 8;
219 vertices[v].Blue = GetBValue (colLeft) << 8;
220 vertices[v].Alpha = 0x8000;
221 vertices[v+3].Red = GetRValue (colRight) << 8;
222 vertices[v+3].Green = GetGValue (colRight) << 8;
223 vertices[v+3].Blue = GetBValue (colRight) << 8;
224 vertices[v+3].Alpha = 0x8000;
227 if ((dwStyle & WS_SYSMENU)
228 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
229 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
231 /* area behind icon; solid filled with left color */
232 vertices[0].x = rect->left;
233 vertices[0].y = rect->top;
234 if (dwStyle & WS_SYSMENU)
236 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
238 vertices[1].x = vertices[0].x;
239 vertices[1].y = rect->bottom;
241 /* area behind text; gradient */
242 vertices[2].x = vertices[1].x;
243 vertices[2].y = rect->top;
244 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
245 vertices[3].y = rect->bottom;
247 /* area behind buttons; solid filled with right color */
248 vertices[4].x = vertices[3].x;
249 vertices[4].y = rect->top;
250 vertices[5].x = rect->right;
251 vertices[5].y = rect->bottom;
253 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
256 FillRect (hdc, rect, GetSysColorBrush (active ?
257 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
260 /***********************************************************************
261 * DrawCaption (USER32.@) Draws a caption bar
275 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
277 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
281 /***********************************************************************
282 * DrawCaptionTempA (USER32.@)
284 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
285 HICON hIcon, LPCSTR str, UINT uFlags)
291 if (!(uFlags & DC_TEXT) || !str)
292 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
294 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
295 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
297 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
298 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
299 HeapFree( GetProcessHeap (), 0, strW );
305 /***********************************************************************
306 * DrawCaptionTempW (USER32.@)
308 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
309 HICON hIcon, LPCWSTR str, UINT uFlags)
313 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
314 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
316 /* drawing background */
317 if (uFlags & DC_INBUTTON) {
318 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
320 if (uFlags & DC_ACTIVE) {
321 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
322 PatBlt (hdc, rc.left, rc.top,
323 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
324 SelectObject (hdc, hbr);
328 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
329 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
334 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
338 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
340 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
341 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
342 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
343 rc.left += (rc.bottom - rc.top);
347 if (uFlags & DC_TEXT) {
350 if (uFlags & DC_INBUTTON)
351 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
352 else if (uFlags & DC_ACTIVE)
353 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
355 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
357 SetBkMode (hdc, TRANSPARENT);
360 hOldFont = SelectObject (hdc, hFont);
362 NONCLIENTMETRICSW nclm;
364 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
365 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
366 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
367 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
368 hOldFont = SelectObject (hdc, hNewFont);
372 DrawTextW (hdc, str, -1, &rc,
373 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
377 nLen = GetWindowTextW (hwnd, szText, 128);
378 DrawTextW (hdc, szText, nLen, &rc,
379 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
383 SelectObject (hdc, hOldFont);
385 DeleteObject (SelectObject (hdc, hOldFont));
388 /* drawing focus ??? */
390 FIXME("undocumented flag (0x2000)!\n");
396 /***********************************************************************
397 * AdjustWindowRect (USER32.@)
399 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
401 return AdjustWindowRectEx( rect, style, menu, 0 );
405 /***********************************************************************
406 * AdjustWindowRectEx (USER32.@)
408 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
410 /* Correct the window style */
411 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
412 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
413 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
414 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
416 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
417 rect->left, rect->top, rect->right, rect->bottom,
418 style, menu, exStyle );
420 NC_AdjustRectOuter( rect, style, menu, exStyle );
421 NC_AdjustRectInner( rect, style, exStyle );
427 /***********************************************************************
428 * NC_HandleNCCalcSize
430 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
432 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
434 RECT tmpRect = { 0, 0, 0, 0 };
436 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
437 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
438 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
440 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
441 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
445 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
447 winRect->left -= tmpRect.left;
448 winRect->top -= tmpRect.top;
449 winRect->right -= tmpRect.right;
450 winRect->bottom -= tmpRect.bottom;
452 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
454 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
455 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
458 MENU_GetMenuBarHeight( hwnd,
459 winRect->right - winRect->left,
460 -tmpRect.left, -tmpRect.top );
463 if( exStyle & WS_EX_CLIENTEDGE)
464 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
465 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
466 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
467 - GetSystemMetrics(SM_CYEDGE));
469 if (style & WS_VSCROLL)
470 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
471 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
472 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
474 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
477 if (style & WS_HSCROLL)
478 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
479 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
481 if (winRect->top > winRect->bottom)
482 winRect->bottom = winRect->top;
484 if (winRect->left > winRect->right)
485 winRect->right = winRect->left;
491 /***********************************************************************
494 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
495 * but without the borders (if any).
496 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
498 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
500 WND *wndPtr = WIN_GetPtr( hwnd );
502 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
504 rect->top = rect->left = 0;
505 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
506 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
508 if (wndPtr->dwStyle & WS_ICONIC) goto END;
510 /* Remove frame from rectangle */
511 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
515 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
517 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
519 else if (HAS_THINFRAME( wndPtr->dwStyle ))
521 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
524 /* We have additional border information if the window
525 * is a child (but not an MDI child) */
526 if ( (wndPtr->dwStyle & WS_CHILD) &&
527 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
529 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
530 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
531 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
532 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
536 WIN_ReleasePtr( wndPtr );
540 /***********************************************************************
543 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
545 * FIXME: Just a modified copy of the Win 3.1 version.
548 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
553 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
555 GetWindowRect(wndPtr->hwndSelf, &rect );
556 if (!PtInRect( &rect, pt )) return HTNOWHERE;
558 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
560 /* Check client area */
562 ScreenToClient( wndPtr->hwndSelf, &ptClient );
563 GetClientRect( wndPtr->hwndSelf, &rcClient );
564 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
567 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
569 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
570 if (!PtInRect( &rect, pt ))
572 /* Check top sizing border */
575 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
576 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
579 /* Check bottom sizing border */
580 if (pt.y >= rect.bottom)
582 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
583 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
586 /* Check left sizing border */
587 if (pt.x < rect.left)
589 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
590 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
593 /* Check right sizing border */
594 if (pt.x >= rect.right)
596 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
597 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
602 else /* No thick frame */
604 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
605 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
606 else if (HAS_THINFRAME( wndPtr->dwStyle ))
607 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
608 if (!PtInRect( &rect, pt )) return HTBORDER;
613 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
615 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
616 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
618 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
619 if (!PtInRect( &rect, pt ))
621 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
622 (wndPtr->dwStyle & WS_MINIMIZEBOX);
623 /* Check system menu */
624 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
626 if (NC_IconForWindow(wndPtr->hwndSelf))
627 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
629 if (pt.x < rect.left) return HTSYSMENU;
631 /* Check close button */
632 if (wndPtr->dwStyle & WS_SYSMENU)
633 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
634 if (pt.x > rect.right) return HTCLOSE;
636 /* Check maximize box */
637 /* In win95 there is automatically a Maximize button when there is a minimize one*/
638 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
639 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
640 if (pt.x > rect.right) return HTMAXBUTTON;
642 /* Check minimize box */
643 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
644 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
645 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
647 if (pt.x > rect.right) return HTMINBUTTON;
652 /* Check vertical scroll bar */
654 if (wndPtr->dwStyle & WS_VSCROLL)
656 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
657 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
659 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
660 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
663 /* Check horizontal scroll bar */
665 if (wndPtr->dwStyle & WS_HSCROLL)
667 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
668 if (PtInRect( &rcClient, ptClient ))
671 if ((wndPtr->dwStyle & WS_VSCROLL) &&
672 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
673 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
681 if (HAS_MENU(wndPtr))
683 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
687 /* Has to return HTNOWHERE if nothing was found
688 Could happen when a window has a customized non client area */
693 /***********************************************************************
696 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
698 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
701 WND *wndPtr = WIN_GetPtr( hwnd );
703 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
705 retvalue = NC_DoNCHitTest (wndPtr, pt);
706 WIN_ReleasePtr( wndPtr );
711 /******************************************************************************
715 * Draws the system icon.
717 *****************************************************************************/
718 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
720 HICON hIcon = NC_IconForWindow( hwnd );
725 NC_GetInsideRect( hwnd, &rect );
726 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
727 GetSystemMetrics(SM_CXSMICON),
728 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
734 /******************************************************************************
738 * Draws the close button.
740 * If bGrayed is true, then draw a disabled Close button
742 *****************************************************************************/
744 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
748 NC_GetInsideRect( hwnd, &rect );
750 /* A tool window has a smaller Close button */
751 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
753 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
754 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
755 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
757 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
758 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
759 rect.bottom = rect.top + iBmpHeight;
760 rect.right = rect.left + iBmpWidth;
764 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
765 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
769 DrawFrameControl( hdc, &rect, DFC_CAPTION,
771 (down ? DFCS_PUSHED : 0) |
772 (bGrayed ? DFCS_INACTIVE : 0)) );
775 /******************************************************************************
778 * Draws the maximize button for windows.
779 * If bGrayed is true, then draw a disabled Maximize button
781 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
786 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
787 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
790 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
792 NC_GetInsideRect( hwnd, &rect );
793 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
794 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
795 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
796 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
799 if (down) flags |= DFCS_PUSHED;
800 if (bGrayed) flags |= DFCS_INACTIVE;
801 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
804 /******************************************************************************
807 * Draws the minimize button for windows.
808 * If bGrayed is true, then draw a disabled Minimize button
810 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
813 UINT flags = DFCS_CAPTIONMIN;
814 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
816 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
817 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
820 NC_GetInsideRect( hwnd, &rect );
821 if (style & WS_SYSMENU)
822 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
823 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
824 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
825 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
826 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
829 if (down) flags |= DFCS_PUSHED;
830 if (bGrayed) flags |= DFCS_INACTIVE;
831 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
834 /******************************************************************************
838 * Draw a window frame inside the given rectangle, and update the rectangle.
841 * Many. First, just what IS a frame in Win95? Note that the 3D look
842 * on the outer edge is handled by NC_DoNCPaint. As is the inner
843 * edge. The inner rectangle just inside the frame is handled by the
846 * In short, for most people, this function should be a nop (unless
847 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
848 * them lately, but just to get this code right). Even so, it doesn't
849 * appear to be so. It's being worked on...
851 *****************************************************************************/
853 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
857 /* Firstly the "thick" frame */
858 if (style & WS_THICKFRAME)
860 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
861 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
863 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
864 COLOR_INACTIVEBORDER) );
866 PatBlt( hdc, rect->left, rect->top,
867 rect->right - rect->left, height, PATCOPY );
868 PatBlt( hdc, rect->left, rect->top,
869 width, rect->bottom - rect->top, PATCOPY );
870 PatBlt( hdc, rect->left, rect->bottom - 1,
871 rect->right - rect->left, -height, PATCOPY );
872 PatBlt( hdc, rect->right - 1, rect->top,
873 -width, rect->bottom - rect->top, PATCOPY );
875 InflateRect( rect, -width, -height );
878 /* Now the other bit of the frame */
879 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
880 (exStyle & WS_EX_DLGMODALFRAME))
882 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
883 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
884 /* This should give a value of 1 that should also work for a border */
886 SelectObject( hdc, GetSysColorBrush(
887 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
889 (exStyle & WS_EX_STATICEDGE) ?
891 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
897 PatBlt( hdc, rect->left, rect->top,
898 rect->right - rect->left, height, PATCOPY );
899 PatBlt( hdc, rect->left, rect->top,
900 width, rect->bottom - rect->top, PATCOPY );
901 PatBlt( hdc, rect->left, rect->bottom - 1,
902 rect->right - rect->left, -height, PATCOPY );
903 PatBlt( hdc, rect->right - 1, rect->top,
904 -width, rect->bottom - rect->top, PATCOPY );
906 InflateRect( rect, -width, -height );
911 /******************************************************************************
915 * Draw the window caption for windows.
916 * The correct pen for the window frame must be selected in the DC.
918 *****************************************************************************/
920 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
921 DWORD exStyle, BOOL active )
927 BOOL gradient = FALSE;
929 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
930 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
931 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
932 COLOR_WINDOWFRAME : COLOR_3DFACE) );
933 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
934 LineTo( hdc, r.right, r.bottom - 1 );
935 SelectObject( hdc, hPrevPen );
938 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
939 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
941 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
942 if (NC_DrawSysButton (hwnd, hdc, FALSE))
943 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
946 if (style & WS_SYSMENU)
950 /* Go get the sysmenu */
951 hSysMenu = GetSystemMenu(hwnd, FALSE);
952 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
954 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
955 NC_DrawCloseButton (hwnd, hdc, FALSE,
956 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
957 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
959 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
961 /* In win95 the two buttons are always there */
962 /* But if the menu item is not in the menu they're disabled*/
964 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
965 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
967 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
968 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
972 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
974 NONCLIENTMETRICSW nclm;
975 HFONT hFont, hOldFont;
976 nclm.cbSize = sizeof(nclm);
977 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
978 if (exStyle & WS_EX_TOOLWINDOW)
979 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
981 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
982 hOldFont = SelectObject (hdc, hFont);
983 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
984 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
985 SetBkMode( hdc, TRANSPARENT );
987 DrawTextW( hdc, buffer, -1, &r,
988 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
989 DeleteObject (SelectObject (hdc, hOldFont));
994 /******************************************************************************
997 * Paint the non-client area for windows.
999 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1002 RECT rfuzz, rect, rectClip;
1005 DWORD dwStyle, dwExStyle;
1008 RECT rectClient, rectWindow;
1011 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1012 has_menu = HAS_MENU(wndPtr);
1013 dwStyle = wndPtr->dwStyle;
1014 dwExStyle = wndPtr->dwExStyle;
1015 flags = wndPtr->flags;
1016 rectWindow = wndPtr->rectWindow;
1017 WIN_ReleasePtr( wndPtr );
1019 if ( dwStyle & WS_MINIMIZE ||
1020 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1022 active = flags & WIN_NCACTIVATED;
1024 TRACE("%p %d\n", hwnd, active );
1026 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1027 the call to GetDCEx implying that it is allowed not to use it either.
1028 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1029 will cause clipRgn to be deleted after ReleaseDC().
1030 Now, how is the "system" supposed to tell what happened?
1033 GetClientRect( hwnd, &rectClient );
1034 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1035 hrgn = CreateRectRgnIndirect( &rectClient );
1039 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1040 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1044 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1049 rect.top = rect.left = 0;
1050 rect.right = rectWindow.right - rectWindow.left;
1051 rect.bottom = rectWindow.bottom - rectWindow.top;
1052 GetClipBox( hdc, &rectClip );
1054 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1056 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1057 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1059 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1060 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1063 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1065 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1068 if (dwExStyle & WS_EX_TOOLWINDOW) {
1069 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1070 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1073 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1074 rect.top += GetSystemMetrics(SM_CYCAPTION);
1076 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1077 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1083 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1085 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1086 r.left, r.top, r.right, r.bottom);
1088 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1091 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1092 rect.left, rect.top, rect.right, rect.bottom );
1094 if (dwExStyle & WS_EX_CLIENTEDGE)
1095 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1097 /* Draw the scroll-bars */
1099 if (dwStyle & WS_VSCROLL)
1100 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1101 if (dwStyle & WS_HSCROLL)
1102 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1104 /* Draw the "size-box" */
1105 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1108 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1109 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1111 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1112 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1113 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1116 ReleaseDC( hwnd, hdc );
1122 /***********************************************************************
1125 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1127 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1129 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1131 if( dwStyle & WS_VISIBLE )
1133 if( dwStyle & WS_MINIMIZE )
1134 WINPOS_RedrawIconTitle( hwnd );
1136 NC_DoNCPaint( hwnd, clip, FALSE );
1142 /***********************************************************************
1143 * NC_HandleNCActivate
1145 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1147 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1149 WND* wndPtr = WIN_GetPtr( hwnd );
1151 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1153 /* Lotus Notes draws menu descriptions in the caption of its main
1154 * window. When it wants to restore original "system" view, it just
1155 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1156 * attempt to minimize redrawings lead to a not restored caption.
1158 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1159 else wndPtr->flags &= ~WIN_NCACTIVATED;
1160 WIN_ReleasePtr( wndPtr );
1163 WINPOS_RedrawIconTitle( hwnd );
1165 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1171 /***********************************************************************
1172 * NC_HandleSetCursor
1174 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1176 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1178 hwnd = WIN_GetFullHandle( (HWND)wParam );
1180 switch((short)LOWORD(lParam))
1184 WORD msg = HIWORD( lParam );
1185 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1186 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1193 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1203 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1207 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1211 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1215 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1218 /* Default cursor: arrow */
1219 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1222 /***********************************************************************
1225 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1227 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1230 WND *wndPtr = WIN_GetPtr( hwnd );
1231 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1233 NC_GetInsideRect( hwnd, rect );
1234 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1235 if (wndPtr->dwStyle & WS_CHILD)
1236 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1237 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1238 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1239 WIN_ReleasePtr( wndPtr );
1243 /***********************************************************************
1246 * Track a mouse button press on the minimize or maximize box.
1248 * The big difference between 3.1 and 95 is the disabled button state.
1249 * In win95 the system button can be disabled, so it can ignore the mouse
1253 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1256 HDC hdc = GetWindowDC( hwnd );
1257 BOOL pressed = TRUE;
1259 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1260 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1262 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1264 if (wParam == HTMINBUTTON)
1266 /* If the style is not present, do nothing */
1267 if (!(wndStyle & WS_MINIMIZEBOX))
1270 /* Check if the sysmenu item for minimize is there */
1271 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1273 paintButton = &NC_DrawMinButton;
1277 /* If the style is not present, do nothing */
1278 if (!(wndStyle & WS_MAXIMIZEBOX))
1281 /* Check if the sysmenu item for maximize is there */
1282 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1284 paintButton = &NC_DrawMaxButton;
1289 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1293 BOOL oldstate = pressed;
1295 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1296 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1298 if(msg.message == WM_LBUTTONUP)
1301 if(msg.message != WM_MOUSEMOVE)
1304 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1305 if (pressed != oldstate)
1306 (*paintButton)( hwnd, hdc, pressed, FALSE);
1310 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1313 ReleaseDC( hwnd, hdc );
1315 /* If the item minimize or maximize of the sysmenu are not there */
1316 /* or if the style is not present, do nothing */
1317 if ((!pressed) || (state == 0xFFFFFFFF))
1320 if (wParam == HTMINBUTTON)
1321 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1323 SendMessageA( hwnd, WM_SYSCOMMAND,
1324 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1327 /***********************************************************************
1328 * NC_TrackCloseButton
1330 * Track a mouse button press on the Win95 close button.
1332 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1336 BOOL pressed = TRUE;
1337 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1343 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1345 /* If the item close of the sysmenu is disabled or not there do nothing */
1346 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1349 hdc = GetWindowDC( hwnd );
1353 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1357 BOOL oldstate = pressed;
1359 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1360 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1362 if(msg.message == WM_LBUTTONUP)
1365 if(msg.message != WM_MOUSEMOVE)
1368 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1369 if (pressed != oldstate)
1370 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1374 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1377 ReleaseDC( hwnd, hdc );
1378 if (!pressed) return;
1380 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1384 /***********************************************************************
1387 * Track a mouse button press on the horizontal or vertical scroll-bar.
1389 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1393 if ((wParam & 0xfff0) == SC_HSCROLL)
1395 if ((wParam & 0x0f) != HTHSCROLL) return;
1396 scrollbar = SB_HORZ;
1398 else /* SC_VSCROLL */
1400 if ((wParam & 0x0f) != HTVSCROLL) return;
1401 scrollbar = SB_VERT;
1403 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1407 /***********************************************************************
1408 * NC_HandleNCLButtonDown
1410 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1412 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1414 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1416 switch(wParam) /* Hit test */
1420 HWND top = GetAncestor( hwnd, GA_ROOT );
1422 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1423 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1428 if( style & WS_SYSMENU )
1430 if( !(style & WS_MINIMIZE) )
1432 HDC hDC = GetWindowDC(hwnd);
1433 NC_DrawSysButton( hwnd, hDC, TRUE );
1434 ReleaseDC( hwnd, hDC );
1436 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1441 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1445 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1449 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1454 NC_TrackMinMaxBox( hwnd, wParam );
1458 NC_TrackCloseButton (hwnd, wParam);
1470 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1471 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1473 /* But that is not what WinNT does. Instead it sends this. This
1474 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1475 * SC_MOUSEMENU into wParam.
1477 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1487 /***********************************************************************
1488 * NC_HandleNCLButtonDblClk
1490 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1492 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1495 * if this is an icon, send a restore since we are handling
1500 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1504 switch(wParam) /* Hit test */
1507 /* stop processing if WS_MAXIMIZEBOX is missing */
1508 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1509 SendMessageW( hwnd, WM_SYSCOMMAND,
1510 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1515 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1516 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1518 /* If the item close of the sysmenu is disabled or not there do nothing */
1519 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1522 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1527 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1531 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1538 /***********************************************************************
1539 * NC_HandleSysCommand
1541 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1543 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1545 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1547 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1550 switch (wParam & 0xfff0)
1554 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1558 if (hwnd == GetForegroundWindow())
1559 ShowOwnedPopups(hwnd,FALSE);
1560 ShowWindow( hwnd, SW_MINIMIZE );
1564 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1565 ShowOwnedPopups(hwnd,TRUE);
1566 ShowWindow( hwnd, SW_MAXIMIZE );
1570 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1571 ShowOwnedPopups(hwnd,TRUE);
1572 ShowWindow( hwnd, SW_RESTORE );
1576 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1582 pt.x = (short)LOWORD(lParam);
1583 pt.y = (short)HIWORD(lParam);
1584 NC_TrackScrollBar( hwnd, wParam, pt );
1591 pt.x = (short)LOWORD(lParam);
1592 pt.y = (short)HIWORD(lParam);
1593 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1598 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1602 WinExec( "taskman.exe", SW_SHOWNORMAL );
1606 if (wParam == SC_ABOUTWINE)
1608 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1611 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1612 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1613 FreeLibrary( hmodule );
1617 if (wParam == SC_PUTMARK)
1618 DPRINTF("Debug mark requested by user\n");
1625 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1631 /*************************************************************
1634 * Stub for the grayed button of the caption
1636 *************************************************************/
1638 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1644 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1649 hdcMask = CreateCompatibleDC (0);
1650 SelectObject (hdcMask, hMaskBmp);
1652 /* Draw the grayed bitmap using the mask */
1653 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1654 BitBlt (hdc, x, y, 12, 10,
1655 hdcMask, 0, 0, 0xB8074A);
1658 SelectObject (hdc, hOldBrush);
1659 DeleteObject(hMaskBmp);
1665 /***********************************************************************
1666 * GetTitleBarInfo (USER32.@)
1667 * TODO: Handle STATE_SYSTEM_PRESSED
1669 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1674 TRACE("(%p %p)\n", hwnd, tbi);
1676 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1677 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1678 SetLastError(ERROR_INVALID_PARAMETER);
1681 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1682 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1683 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1685 GetWindowRect(hwnd, &wndRect);
1687 tbi->rcTitleBar.top += wndRect.top;
1688 tbi->rcTitleBar.left += wndRect.left;
1689 tbi->rcTitleBar.right += wndRect.left;
1691 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1692 if(dwExStyle & WS_EX_TOOLWINDOW)
1693 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1695 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1696 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1699 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1700 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1701 * Under XP it seems to
1703 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1704 if(dwStyle & WS_CAPTION) {
1705 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1706 if(dwStyle & WS_SYSMENU) {
1707 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1708 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1709 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1712 if(!(dwStyle & WS_MINIMIZEBOX))
1713 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1714 if(!(dwStyle & WS_MAXIMIZEBOX))
1715 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1717 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1718 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1719 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1720 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1723 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1726 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1730 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;