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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/winuser16.h"
30 #include "user_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
36 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
38 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
49 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
50 #define SC_PUTMARK (SC_SCREENSAVE+2)
52 /* Some useful macros */
53 #define HAS_DLGFRAME(style,exStyle) \
54 (((exStyle) & WS_EX_DLGMODALFRAME) || \
55 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
57 #define HAS_THICKFRAME(style,exStyle) \
58 (((style) & WS_THICKFRAME) && \
59 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
61 #define HAS_THINFRAME(style) \
62 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
64 #define HAS_BIGFRAME(style,exStyle) \
65 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
66 ((exStyle) & WS_EX_DLGMODALFRAME))
68 #define HAS_STATICOUTERFRAME(style,exStyle) \
69 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
72 #define HAS_ANYFRAME(style,exStyle) \
73 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
74 ((exStyle) & WS_EX_DLGMODALFRAME) || \
75 !((style) & (WS_CHILD | WS_POPUP)))
77 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
80 /******************************************************************************
83 * Computes the size of the "outside" parts of the window based on the
84 * parameters of the client area.
93 * "Outer" parts of a window means the whole window frame, caption and
94 * menu bar. It does not include "inner" parts of the frame like client
95 * edge, static edge or scroll bars.
97 *****************************************************************************/
100 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
103 if(style & WS_ICONIC) return;
105 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
108 adjust = 1; /* for the outer frame always present */
113 if ((exStyle & WS_EX_DLGMODALFRAME) ||
114 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
116 if (style & WS_THICKFRAME)
117 adjust += ( GetSystemMetrics (SM_CXFRAME)
118 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
119 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
120 (exStyle & WS_EX_DLGMODALFRAME))
121 adjust++; /* The other border */
123 InflateRect (rect, adjust, adjust);
125 if ((style & WS_CAPTION) == WS_CAPTION)
127 if (exStyle & WS_EX_TOOLWINDOW)
128 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
130 rect->top -= GetSystemMetrics(SM_CYCAPTION);
132 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
136 /******************************************************************************
139 * Computes the size of the "inside" part of the window based on the
140 * parameters of the client area.
148 * "Inner" part of a window means the window frame inside of the flat
149 * window frame. It includes the client edge, the static edge and the
152 *****************************************************************************/
155 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
157 if(style & WS_ICONIC) return;
159 if (exStyle & WS_EX_CLIENTEDGE)
160 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
162 if (style & WS_VSCROLL)
164 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
165 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
167 rect->right += GetSystemMetrics(SM_CXVSCROLL);
169 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
174 static HICON NC_IconForWindow( HWND hwnd )
177 WND *wndPtr = WIN_GetPtr( hwnd );
179 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
181 hIcon = wndPtr->hIconSmall;
182 if (!hIcon) hIcon = wndPtr->hIcon;
183 WIN_ReleasePtr( wndPtr );
185 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
186 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
188 /* If there is no hIcon specified and this is a modal dialog,
189 * get the default one.
191 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
192 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
196 /* Draws the bar part(ie the big rectangle) of the caption */
197 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
198 BOOL active, BOOL gradient)
202 TRIVERTEX vertices[6];
204 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
206 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
207 : COLOR_GRADIENTINACTIVECAPTION);
209 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
210 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
212 for (v = 0; v < 3; v++)
214 vertices[v].Red = GetRValue (colLeft) << 8;
215 vertices[v].Green = GetGValue (colLeft) << 8;
216 vertices[v].Blue = GetBValue (colLeft) << 8;
217 vertices[v].Alpha = 0x8000;
218 vertices[v+3].Red = GetRValue (colRight) << 8;
219 vertices[v+3].Green = GetGValue (colRight) << 8;
220 vertices[v+3].Blue = GetBValue (colRight) << 8;
221 vertices[v+3].Alpha = 0x8000;
224 if ((dwStyle & WS_SYSMENU)
225 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
226 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
228 /* area behind icon; solid filled with left color */
229 vertices[0].x = rect->left;
230 vertices[0].y = rect->top;
231 if (dwStyle & WS_SYSMENU)
233 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
235 vertices[1].x = vertices[0].x;
236 vertices[1].y = rect->bottom;
238 /* area behind text; gradient */
239 vertices[2].x = vertices[1].x;
240 vertices[2].y = rect->top;
241 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
242 vertices[3].y = rect->bottom;
244 /* area behind buttons; solid filled with right color */
245 vertices[4].x = vertices[3].x;
246 vertices[4].y = rect->top;
247 vertices[5].x = rect->right;
248 vertices[5].y = rect->bottom;
250 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
253 FillRect (hdc, rect, GetSysColorBrush (active ?
254 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
257 /***********************************************************************
258 * DrawCaption (USER32.@) Draws a caption bar
272 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
274 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
278 /***********************************************************************
279 * DrawCaptionTempA (USER32.@)
281 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
282 HICON hIcon, LPCSTR str, UINT uFlags)
288 if (!(uFlags & DC_TEXT) || !str)
289 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
291 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
292 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
294 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
295 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
296 HeapFree( GetProcessHeap (), 0, strW );
302 /***********************************************************************
303 * DrawCaptionTempW (USER32.@)
305 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
306 HICON hIcon, LPCWSTR str, UINT uFlags)
310 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
311 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
313 /* drawing background */
314 if (uFlags & DC_INBUTTON) {
315 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
317 if (uFlags & DC_ACTIVE) {
318 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
319 PatBlt (hdc, rc.left, rc.top,
320 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
321 SelectObject (hdc, hbr);
325 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
326 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
331 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
335 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
337 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
338 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
339 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
340 rc.left += (rc.bottom - rc.top);
344 if (uFlags & DC_TEXT) {
347 if (uFlags & DC_INBUTTON)
348 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
349 else if (uFlags & DC_ACTIVE)
350 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
352 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
354 SetBkMode (hdc, TRANSPARENT);
357 hOldFont = SelectObject (hdc, hFont);
359 NONCLIENTMETRICSW nclm;
361 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
362 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
363 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
364 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
365 hOldFont = SelectObject (hdc, hNewFont);
369 DrawTextW (hdc, str, -1, &rc,
370 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
374 nLen = GetWindowTextW (hwnd, szText, 128);
375 DrawTextW (hdc, szText, nLen, &rc,
376 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
380 SelectObject (hdc, hOldFont);
382 DeleteObject (SelectObject (hdc, hOldFont));
385 /* drawing focus ??? */
387 FIXME("undocumented flag (0x2000)!\n");
393 /***********************************************************************
394 * AdjustWindowRect (USER32.@)
396 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
398 return AdjustWindowRectEx( rect, style, menu, 0 );
402 /***********************************************************************
403 * AdjustWindowRectEx (USER32.@)
405 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
407 /* Correct the window style */
408 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
409 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
410 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
411 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
413 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
414 rect->left, rect->top, rect->right, rect->bottom,
415 style, menu, exStyle );
417 NC_AdjustRectOuter( rect, style, menu, exStyle );
418 NC_AdjustRectInner( rect, style, exStyle );
424 /***********************************************************************
425 * NC_HandleNCCalcSize
427 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
429 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
431 RECT tmpRect = { 0, 0, 0, 0 };
433 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
434 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
435 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
437 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
438 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
442 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
444 winRect->left -= tmpRect.left;
445 winRect->top -= tmpRect.top;
446 winRect->right -= tmpRect.right;
447 winRect->bottom -= tmpRect.bottom;
449 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
451 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
452 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
455 MENU_GetMenuBarHeight( hwnd,
456 winRect->right - winRect->left,
457 -tmpRect.left, -tmpRect.top );
460 if( exStyle & WS_EX_CLIENTEDGE)
461 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
462 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
463 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
464 - GetSystemMetrics(SM_CYEDGE));
466 if (style & WS_VSCROLL)
467 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
468 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
469 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
471 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
474 if (style & WS_HSCROLL)
475 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
476 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
478 if (winRect->top > winRect->bottom)
479 winRect->bottom = winRect->top;
481 if (winRect->left > winRect->right)
482 winRect->right = winRect->left;
488 /***********************************************************************
491 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
492 * but without the borders (if any).
493 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
495 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
497 WND *wndPtr = WIN_GetPtr( hwnd );
499 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
501 rect->top = rect->left = 0;
502 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
503 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
505 if (wndPtr->dwStyle & WS_ICONIC) goto END;
507 /* Remove frame from rectangle */
508 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
510 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
512 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
514 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
516 else if (HAS_THINFRAME( wndPtr->dwStyle ))
518 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
521 /* We have additional border information if the window
522 * is a child (but not an MDI child) */
523 if ( (wndPtr->dwStyle & WS_CHILD) &&
524 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
526 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
527 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
528 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
529 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
533 WIN_ReleasePtr( wndPtr );
537 /***********************************************************************
540 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
542 * FIXME: Just a modified copy of the Win 3.1 version.
545 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
550 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
552 GetWindowRect(wndPtr->hwndSelf, &rect );
553 if (!PtInRect( &rect, pt )) return HTNOWHERE;
555 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
557 /* Check client area */
559 ScreenToClient( wndPtr->hwndSelf, &ptClient );
560 GetClientRect( wndPtr->hwndSelf, &rcClient );
561 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
564 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
566 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
567 if (!PtInRect( &rect, pt ))
569 /* Check top sizing border */
572 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
573 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
576 /* Check bottom sizing border */
577 if (pt.y >= rect.bottom)
579 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
580 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
583 /* Check left sizing border */
584 if (pt.x < rect.left)
586 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
587 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
590 /* Check right sizing border */
591 if (pt.x >= rect.right)
593 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
594 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
599 else /* No thick frame */
601 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
602 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
603 else if (HAS_THINFRAME( wndPtr->dwStyle ))
604 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
605 if (!PtInRect( &rect, pt )) return HTBORDER;
610 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
612 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
613 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
615 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
616 if (!PtInRect( &rect, pt ))
618 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
619 (wndPtr->dwStyle & WS_MINIMIZEBOX);
620 /* Check system menu */
621 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
623 if (NC_IconForWindow(wndPtr->hwndSelf))
624 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
626 if (pt.x < rect.left) return HTSYSMENU;
628 /* Check close button */
629 if (wndPtr->dwStyle & WS_SYSMENU)
630 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
631 if (pt.x > rect.right) return HTCLOSE;
633 /* Check maximize box */
634 /* In win95 there is automatically a Maximize button when there is a minimize one*/
635 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
636 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
637 if (pt.x > rect.right) return HTMAXBUTTON;
639 /* Check minimize box */
640 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
641 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
642 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
644 if (pt.x > rect.right) return HTMINBUTTON;
649 /* Check vertical scroll bar */
651 if (wndPtr->dwStyle & WS_VSCROLL)
653 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
654 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
656 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
657 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
660 /* Check horizontal scroll bar */
662 if (wndPtr->dwStyle & WS_HSCROLL)
664 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
665 if (PtInRect( &rcClient, ptClient ))
668 if ((wndPtr->dwStyle & WS_VSCROLL) &&
669 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
670 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
678 if (HAS_MENU(wndPtr))
680 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
684 /* Has to return HTNOWHERE if nothing was found
685 Could happen when a window has a customized non client area */
690 /***********************************************************************
693 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
695 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
698 WND *wndPtr = WIN_GetPtr( hwnd );
700 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
702 retvalue = NC_DoNCHitTest (wndPtr, pt);
703 WIN_ReleasePtr( wndPtr );
708 /******************************************************************************
712 * Draws the system icon.
714 *****************************************************************************/
715 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
717 HICON hIcon = NC_IconForWindow( hwnd );
722 NC_GetInsideRect( hwnd, &rect );
723 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
724 GetSystemMetrics(SM_CXSMICON),
725 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
731 /******************************************************************************
735 * Draws the close button.
737 * If bGrayed is true, then draw a disabled Close button
739 *****************************************************************************/
741 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
745 NC_GetInsideRect( hwnd, &rect );
747 /* A tool window has a smaller Close button */
748 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
750 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
751 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
752 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
754 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
755 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
756 rect.bottom = rect.top + iBmpHeight;
757 rect.right = rect.left + iBmpWidth;
761 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
762 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
766 DrawFrameControl( hdc, &rect, DFC_CAPTION,
768 (down ? DFCS_PUSHED : 0) |
769 (bGrayed ? DFCS_INACTIVE : 0)) );
772 /******************************************************************************
775 * Draws the maximize button for windows.
776 * If bGrayed is true, then draw a disabled Maximize button
778 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
783 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
784 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
787 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
789 NC_GetInsideRect( hwnd, &rect );
790 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
791 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
792 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
793 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
796 if (down) flags |= DFCS_PUSHED;
797 if (bGrayed) flags |= DFCS_INACTIVE;
798 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
801 /******************************************************************************
804 * Draws the minimize button for windows.
805 * If bGrayed is true, then draw a disabled Minimize button
807 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
810 UINT flags = DFCS_CAPTIONMIN;
811 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
813 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
814 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
817 NC_GetInsideRect( hwnd, &rect );
818 if (style & WS_SYSMENU)
819 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
820 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
821 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
822 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
823 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
826 if (down) flags |= DFCS_PUSHED;
827 if (bGrayed) flags |= DFCS_INACTIVE;
828 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
831 /******************************************************************************
835 * Draw a window frame inside the given rectangle, and update the rectangle.
838 * Many. First, just what IS a frame in Win95? Note that the 3D look
839 * on the outer edge is handled by NC_DoNCPaint. As is the inner
840 * edge. The inner rectangle just inside the frame is handled by the
843 * In short, for most people, this function should be a nop (unless
844 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
845 * them lately, but just to get this code right). Even so, it doesn't
846 * appear to be so. It's being worked on...
848 *****************************************************************************/
850 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
854 /* Firstly the "thick" frame */
855 if (style & WS_THICKFRAME)
857 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
858 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
860 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
861 COLOR_INACTIVEBORDER) );
863 PatBlt( hdc, rect->left, rect->top,
864 rect->right - rect->left, height, PATCOPY );
865 PatBlt( hdc, rect->left, rect->top,
866 width, rect->bottom - rect->top, PATCOPY );
867 PatBlt( hdc, rect->left, rect->bottom - 1,
868 rect->right - rect->left, -height, PATCOPY );
869 PatBlt( hdc, rect->right - 1, rect->top,
870 -width, rect->bottom - rect->top, PATCOPY );
872 InflateRect( rect, -width, -height );
875 /* Now the other bit of the frame */
876 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
877 (exStyle & WS_EX_DLGMODALFRAME))
879 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
880 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
881 /* This should give a value of 1 that should also work for a border */
883 SelectObject( hdc, GetSysColorBrush(
884 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
886 (exStyle & WS_EX_STATICEDGE) ?
888 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
894 PatBlt( hdc, rect->left, rect->top,
895 rect->right - rect->left, height, PATCOPY );
896 PatBlt( hdc, rect->left, rect->top,
897 width, rect->bottom - rect->top, PATCOPY );
898 PatBlt( hdc, rect->left, rect->bottom - 1,
899 rect->right - rect->left, -height, PATCOPY );
900 PatBlt( hdc, rect->right - 1, rect->top,
901 -width, rect->bottom - rect->top, PATCOPY );
903 InflateRect( rect, -width, -height );
908 /******************************************************************************
912 * Draw the window caption for windows.
913 * The correct pen for the window frame must be selected in the DC.
915 *****************************************************************************/
917 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
918 DWORD exStyle, BOOL active )
924 BOOL gradient = FALSE;
926 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
927 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
928 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
929 COLOR_WINDOWFRAME : COLOR_3DFACE) );
930 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
931 LineTo( hdc, r.right, r.bottom - 1 );
932 SelectObject( hdc, hPrevPen );
935 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
936 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
938 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
939 if (NC_DrawSysButton (hwnd, hdc, FALSE))
940 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
943 if (style & WS_SYSMENU)
947 /* Go get the sysmenu */
948 hSysMenu = GetSystemMenu(hwnd, FALSE);
949 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
951 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
952 NC_DrawCloseButton (hwnd, hdc, FALSE,
953 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
954 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
956 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
958 /* In win95 the two buttons are always there */
959 /* But if the menu item is not in the menu they're disabled*/
961 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
962 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
964 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
965 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
969 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
971 NONCLIENTMETRICSW nclm;
972 HFONT hFont, hOldFont;
973 nclm.cbSize = sizeof(nclm);
974 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
975 if (exStyle & WS_EX_TOOLWINDOW)
976 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
978 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
979 hOldFont = SelectObject (hdc, hFont);
980 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
981 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
982 SetBkMode( hdc, TRANSPARENT );
984 DrawTextW( hdc, buffer, -1, &r,
985 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
986 DeleteObject (SelectObject (hdc, hOldFont));
991 /******************************************************************************
994 * Paint the non-client area for windows.
996 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
999 RECT rfuzz, rect, rectClip;
1002 DWORD dwStyle, dwExStyle;
1005 RECT rectClient, rectWindow;
1008 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1009 has_menu = HAS_MENU(wndPtr);
1010 dwStyle = wndPtr->dwStyle;
1011 dwExStyle = wndPtr->dwExStyle;
1012 flags = wndPtr->flags;
1013 rectWindow = wndPtr->rectWindow;
1014 WIN_ReleasePtr( wndPtr );
1016 if ( dwStyle & WS_MINIMIZE ||
1017 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1019 active = flags & WIN_NCACTIVATED;
1021 TRACE("%p %d\n", hwnd, active );
1023 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1024 the call to GetDCEx implying that it is allowed not to use it either.
1025 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1026 will cause clipRgn to be deleted after ReleaseDC().
1027 Now, how is the "system" supposed to tell what happened?
1030 GetClientRect( hwnd, &rectClient );
1031 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1032 hrgn = CreateRectRgnIndirect( &rectClient );
1036 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1037 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1041 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1046 rect.top = rect.left = 0;
1047 rect.right = rectWindow.right - rectWindow.left;
1048 rect.bottom = rectWindow.bottom - rectWindow.top;
1049 GetClipBox( hdc, &rectClip );
1051 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1053 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1054 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1056 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1057 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1060 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1062 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1065 if (dwExStyle & WS_EX_TOOLWINDOW) {
1066 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1067 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1070 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1071 rect.top += GetSystemMetrics(SM_CYCAPTION);
1073 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1074 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1080 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1082 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1083 r.left, r.top, r.right, r.bottom);
1085 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1088 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1089 rect.left, rect.top, rect.right, rect.bottom );
1091 if (dwExStyle & WS_EX_CLIENTEDGE)
1092 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1094 /* Draw the scroll-bars */
1096 if (dwStyle & WS_VSCROLL)
1097 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1098 if (dwStyle & WS_HSCROLL)
1099 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1101 /* Draw the "size-box" */
1102 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1105 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1106 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1108 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1109 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1110 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1113 ReleaseDC( hwnd, hdc );
1119 /***********************************************************************
1122 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1124 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1126 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1128 if( dwStyle & WS_VISIBLE )
1130 if( dwStyle & WS_MINIMIZE )
1131 WINPOS_RedrawIconTitle( hwnd );
1133 NC_DoNCPaint( hwnd, clip, FALSE );
1139 /***********************************************************************
1140 * NC_HandleNCActivate
1142 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1144 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1146 WND* wndPtr = WIN_GetPtr( hwnd );
1148 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1150 /* Lotus Notes draws menu descriptions in the caption of its main
1151 * window. When it wants to restore original "system" view, it just
1152 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1153 * attempt to minimize redrawings lead to a not restored caption.
1155 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1156 else wndPtr->flags &= ~WIN_NCACTIVATED;
1157 WIN_ReleasePtr( wndPtr );
1160 WINPOS_RedrawIconTitle( hwnd );
1162 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1168 /***********************************************************************
1169 * NC_HandleSetCursor
1171 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1173 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1175 hwnd = WIN_GetFullHandle( (HWND)wParam );
1177 switch((short)LOWORD(lParam))
1181 WORD msg = HIWORD( lParam );
1182 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1183 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1190 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1200 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1204 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1208 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1212 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1215 /* Default cursor: arrow */
1216 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1219 /***********************************************************************
1222 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1224 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1227 WND *wndPtr = WIN_GetPtr( hwnd );
1228 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1230 NC_GetInsideRect( hwnd, rect );
1231 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1232 if (wndPtr->dwStyle & WS_CHILD)
1233 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1234 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1235 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1236 WIN_ReleasePtr( wndPtr );
1240 /***********************************************************************
1243 * Track a mouse button press on the minimize or maximize box.
1245 * The big difference between 3.1 and 95 is the disabled button state.
1246 * In win95 the system button can be disabled, so it can ignore the mouse
1250 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1253 HDC hdc = GetWindowDC( hwnd );
1254 BOOL pressed = TRUE;
1256 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1257 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1259 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1261 if (wParam == HTMINBUTTON)
1263 /* If the style is not present, do nothing */
1264 if (!(wndStyle & WS_MINIMIZEBOX))
1267 /* Check if the sysmenu item for minimize is there */
1268 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1270 paintButton = &NC_DrawMinButton;
1274 /* If the style is not present, do nothing */
1275 if (!(wndStyle & WS_MAXIMIZEBOX))
1278 /* Check if the sysmenu item for maximize is there */
1279 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1281 paintButton = &NC_DrawMaxButton;
1286 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1290 BOOL oldstate = pressed;
1292 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1293 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1295 if(msg.message == WM_LBUTTONUP)
1298 if(msg.message != WM_MOUSEMOVE)
1301 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1302 if (pressed != oldstate)
1303 (*paintButton)( hwnd, hdc, pressed, FALSE);
1307 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1310 ReleaseDC( hwnd, hdc );
1312 /* If the item minimize or maximize of the sysmenu are not there */
1313 /* or if the style is not present, do nothing */
1314 if ((!pressed) || (state == 0xFFFFFFFF))
1317 if (wParam == HTMINBUTTON)
1318 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1320 SendMessageW( hwnd, WM_SYSCOMMAND,
1321 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1324 /***********************************************************************
1325 * NC_TrackCloseButton
1327 * Track a mouse button press on the Win95 close button.
1329 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1333 BOOL pressed = TRUE;
1334 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1340 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1342 /* If the item close of the sysmenu is disabled or not there do nothing */
1343 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1346 hdc = GetWindowDC( hwnd );
1350 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1354 BOOL oldstate = pressed;
1356 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1357 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1359 if(msg.message == WM_LBUTTONUP)
1362 if(msg.message != WM_MOUSEMOVE)
1365 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1366 if (pressed != oldstate)
1367 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1371 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1374 ReleaseDC( hwnd, hdc );
1375 if (!pressed) return;
1377 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1381 /***********************************************************************
1384 * Track a mouse button press on the horizontal or vertical scroll-bar.
1386 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1390 if ((wParam & 0xfff0) == SC_HSCROLL)
1392 if ((wParam & 0x0f) != HTHSCROLL) return;
1393 scrollbar = SB_HORZ;
1395 else /* SC_VSCROLL */
1397 if ((wParam & 0x0f) != HTVSCROLL) return;
1398 scrollbar = SB_VERT;
1400 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1404 /***********************************************************************
1405 * NC_HandleNCLButtonDown
1407 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1409 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1411 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1413 switch(wParam) /* Hit test */
1417 HWND top = GetAncestor( hwnd, GA_ROOT );
1419 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1420 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1425 if( style & WS_SYSMENU )
1427 if( !(style & WS_MINIMIZE) )
1429 HDC hDC = GetWindowDC(hwnd);
1430 NC_DrawSysButton( hwnd, hDC, TRUE );
1431 ReleaseDC( hwnd, hDC );
1433 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1438 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1442 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1446 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1451 NC_TrackMinMaxBox( hwnd, wParam );
1455 NC_TrackCloseButton (hwnd, wParam);
1467 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1468 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1470 /* But that is not what WinNT does. Instead it sends this. This
1471 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1472 * SC_MOUSEMENU into wParam.
1474 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1484 /***********************************************************************
1485 * NC_HandleNCLButtonDblClk
1487 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1489 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1492 * if this is an icon, send a restore since we are handling
1497 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1501 switch(wParam) /* Hit test */
1504 /* stop processing if WS_MAXIMIZEBOX is missing */
1505 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1506 SendMessageW( hwnd, WM_SYSCOMMAND,
1507 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1512 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1513 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1515 /* If the item close of the sysmenu is disabled or not there do nothing */
1516 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1519 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1524 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1528 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1535 /***********************************************************************
1536 * NC_HandleSysCommand
1538 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1540 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1542 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1544 if (!IsWindowEnabled( hwnd )) return 0;
1546 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1549 switch (wParam & 0xfff0)
1553 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1557 if (hwnd == GetForegroundWindow())
1558 ShowOwnedPopups(hwnd,FALSE);
1559 ShowWindow( hwnd, SW_MINIMIZE );
1563 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1564 ShowOwnedPopups(hwnd,TRUE);
1565 ShowWindow( hwnd, SW_MAXIMIZE );
1569 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1570 ShowOwnedPopups(hwnd,TRUE);
1571 ShowWindow( hwnd, SW_RESTORE );
1575 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1581 pt.x = (short)LOWORD(lParam);
1582 pt.y = (short)HIWORD(lParam);
1583 NC_TrackScrollBar( hwnd, wParam, pt );
1590 pt.x = (short)LOWORD(lParam);
1591 pt.y = (short)HIWORD(lParam);
1592 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1597 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1601 WinExec( "taskman.exe", SW_SHOWNORMAL );
1605 if (wParam == SC_ABOUTWINE)
1607 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1610 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1611 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1612 FreeLibrary( hmodule );
1616 if (wParam == SC_PUTMARK)
1617 DPRINTF("Debug mark requested by user\n");
1624 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1630 /*************************************************************
1633 * Stub for the grayed button of the caption
1635 *************************************************************/
1637 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1643 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1648 hdcMask = CreateCompatibleDC (0);
1649 SelectObject (hdcMask, hMaskBmp);
1651 /* Draw the grayed bitmap using the mask */
1652 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1653 BitBlt (hdc, x, y, 12, 10,
1654 hdcMask, 0, 0, 0xB8074A);
1657 SelectObject (hdc, hOldBrush);
1658 DeleteObject(hMaskBmp);
1664 /***********************************************************************
1665 * GetTitleBarInfo (USER32.@)
1666 * TODO: Handle STATE_SYSTEM_PRESSED
1668 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1673 TRACE("(%p %p)\n", hwnd, tbi);
1675 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1676 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1677 SetLastError(ERROR_INVALID_PARAMETER);
1680 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1681 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1682 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1684 GetWindowRect(hwnd, &wndRect);
1686 tbi->rcTitleBar.top += wndRect.top;
1687 tbi->rcTitleBar.left += wndRect.left;
1688 tbi->rcTitleBar.right += wndRect.left;
1690 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1691 if(dwExStyle & WS_EX_TOOLWINDOW)
1692 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1694 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1695 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1698 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1699 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1700 * Under XP it seems to
1702 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1703 if(dwStyle & WS_CAPTION) {
1704 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1705 if(dwStyle & WS_SYSMENU) {
1706 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1707 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1708 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1711 if(!(dwStyle & WS_MINIMIZEBOX))
1712 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1713 if(!(dwStyle & WS_MAXIMIZEBOX))
1714 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1716 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1717 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1718 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1719 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1722 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1723 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1729 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;