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
29 #include "user_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
35 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
36 #define SC_PUTMARK (SC_SCREENSAVE+2)
38 /* Some useful macros */
39 #define HAS_DLGFRAME(style,exStyle) \
40 (((exStyle) & WS_EX_DLGMODALFRAME) || \
41 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
43 #define HAS_THICKFRAME(style,exStyle) \
44 (((style) & WS_THICKFRAME) && \
45 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47 #define HAS_THINFRAME(style) \
48 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
50 #define HAS_BIGFRAME(style,exStyle) \
51 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
52 ((exStyle) & WS_EX_DLGMODALFRAME))
54 #define HAS_STATICOUTERFRAME(style,exStyle) \
55 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
58 #define HAS_ANYFRAME(style,exStyle) \
59 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
60 ((exStyle) & WS_EX_DLGMODALFRAME) || \
61 !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
66 /******************************************************************************
69 * Computes the size of the "outside" parts of the window based on the
70 * parameters of the client area.
79 * "Outer" parts of a window means the whole window frame, caption and
80 * menu bar. It does not include "inner" parts of the frame like client
81 * edge, static edge or scroll bars.
83 *****************************************************************************/
86 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
89 if(style & WS_ICONIC) return;
91 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
94 adjust = 1; /* for the outer frame always present */
99 if ((exStyle & WS_EX_DLGMODALFRAME) ||
100 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
102 if (style & WS_THICKFRAME)
103 adjust += ( GetSystemMetrics (SM_CXFRAME)
104 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
105 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
106 (exStyle & WS_EX_DLGMODALFRAME))
107 adjust++; /* The other border */
109 InflateRect (rect, adjust, adjust);
111 if ((style & WS_CAPTION) == WS_CAPTION)
113 if (exStyle & WS_EX_TOOLWINDOW)
114 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
116 rect->top -= GetSystemMetrics(SM_CYCAPTION);
118 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
122 /******************************************************************************
125 * Computes the size of the "inside" part of the window based on the
126 * parameters of the client area.
134 * "Inner" part of a window means the window frame inside of the flat
135 * window frame. It includes the client edge, the static edge and the
138 *****************************************************************************/
141 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
143 if(style & WS_ICONIC) return;
145 if (exStyle & WS_EX_CLIENTEDGE)
146 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
148 if (style & WS_VSCROLL)
150 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
151 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
153 rect->right += GetSystemMetrics(SM_CXVSCROLL);
155 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
160 static HICON NC_IconForWindow( HWND hwnd )
163 WND *wndPtr = WIN_GetPtr( hwnd );
165 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
167 hIcon = wndPtr->hIconSmall;
168 if (!hIcon) hIcon = wndPtr->hIcon;
169 WIN_ReleasePtr( wndPtr );
171 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
172 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
174 /* If there is no hIcon specified and this is a modal dialog,
175 * get the default one.
177 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
178 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
182 /* Draws the bar part(ie the big rectangle) of the caption */
183 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
184 BOOL active, BOOL gradient)
188 TRIVERTEX vertices[6];
190 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
192 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
193 : COLOR_GRADIENTINACTIVECAPTION);
195 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
196 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
198 for (v = 0; v < 3; v++)
200 vertices[v].Red = GetRValue (colLeft) << 8;
201 vertices[v].Green = GetGValue (colLeft) << 8;
202 vertices[v].Blue = GetBValue (colLeft) << 8;
203 vertices[v].Alpha = 0x8000;
204 vertices[v+3].Red = GetRValue (colRight) << 8;
205 vertices[v+3].Green = GetGValue (colRight) << 8;
206 vertices[v+3].Blue = GetBValue (colRight) << 8;
207 vertices[v+3].Alpha = 0x8000;
210 if ((dwStyle & WS_SYSMENU)
211 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
212 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
214 /* area behind icon; solid filled with left color */
215 vertices[0].x = rect->left;
216 vertices[0].y = rect->top;
217 if (dwStyle & WS_SYSMENU)
219 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
221 vertices[1].x = vertices[0].x;
222 vertices[1].y = rect->bottom;
224 /* area behind text; gradient */
225 vertices[2].x = vertices[1].x;
226 vertices[2].y = rect->top;
227 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
228 vertices[3].y = rect->bottom;
230 /* area behind buttons; solid filled with right color */
231 vertices[4].x = vertices[3].x;
232 vertices[4].y = rect->top;
233 vertices[5].x = rect->right;
234 vertices[5].y = rect->bottom;
236 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
239 FillRect (hdc, rect, GetSysColorBrush (active ?
240 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
243 /***********************************************************************
244 * DrawCaption (USER32.@) Draws a caption bar
258 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
260 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
264 /***********************************************************************
265 * DrawCaptionTempA (USER32.@)
267 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
268 HICON hIcon, LPCSTR str, UINT uFlags)
274 if (!(uFlags & DC_TEXT) || !str)
275 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
277 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
278 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
280 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
281 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
282 HeapFree( GetProcessHeap (), 0, strW );
288 /***********************************************************************
289 * DrawCaptionTempW (USER32.@)
291 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
292 HICON hIcon, LPCWSTR str, UINT uFlags)
296 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
297 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
299 /* drawing background */
300 if (uFlags & DC_INBUTTON) {
301 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
303 if (uFlags & DC_ACTIVE) {
304 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
305 PatBlt (hdc, rc.left, rc.top,
306 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
307 SelectObject (hdc, hbr);
311 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
312 NC_DrawCaptionBar (hdc, &rc, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
317 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
321 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
323 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
324 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
325 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
326 rc.left += (rc.bottom - rc.top);
330 if (uFlags & DC_TEXT) {
333 if (uFlags & DC_INBUTTON)
334 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
335 else if (uFlags & DC_ACTIVE)
336 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
338 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
340 SetBkMode (hdc, TRANSPARENT);
343 hOldFont = SelectObject (hdc, hFont);
345 NONCLIENTMETRICSW nclm;
347 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
348 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
349 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
350 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
351 hOldFont = SelectObject (hdc, hNewFont);
355 DrawTextW (hdc, str, -1, &rc,
356 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
360 nLen = GetWindowTextW (hwnd, szText, 128);
361 DrawTextW (hdc, szText, nLen, &rc,
362 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
366 SelectObject (hdc, hOldFont);
368 DeleteObject (SelectObject (hdc, hOldFont));
371 /* drawing focus ??? */
373 FIXME("undocumented flag (0x2000)!\n");
379 /***********************************************************************
380 * AdjustWindowRect (USER32.@)
382 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
384 return AdjustWindowRectEx( rect, style, menu, 0 );
388 /***********************************************************************
389 * AdjustWindowRectEx (USER32.@)
391 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
393 /* Correct the window style */
394 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
395 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
396 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
397 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
399 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect), style, menu, exStyle );
401 NC_AdjustRectOuter( rect, style, menu, exStyle );
402 NC_AdjustRectInner( rect, style, exStyle );
408 /***********************************************************************
409 * NC_HandleNCCalcSize
411 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
413 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
415 RECT tmpRect = { 0, 0, 0, 0 };
417 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
418 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
419 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
421 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
422 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
426 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
428 winRect->left -= tmpRect.left;
429 winRect->top -= tmpRect.top;
430 winRect->right -= tmpRect.right;
431 winRect->bottom -= tmpRect.bottom;
433 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
435 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
436 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
439 MENU_GetMenuBarHeight( hwnd,
440 winRect->right - winRect->left,
441 -tmpRect.left, -tmpRect.top );
444 if( exStyle & WS_EX_CLIENTEDGE)
445 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
446 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
447 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
448 - GetSystemMetrics(SM_CYEDGE));
450 if (style & WS_VSCROLL)
451 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
452 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
453 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
455 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
458 if (style & WS_HSCROLL)
459 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
460 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
462 if (winRect->top > winRect->bottom)
463 winRect->bottom = winRect->top;
465 if (winRect->left > winRect->right)
466 winRect->right = winRect->left;
472 /***********************************************************************
475 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
476 * but without the borders (if any).
477 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
479 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
481 WND *wndPtr = WIN_GetPtr( hwnd );
483 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
485 rect->top = rect->left = 0;
486 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
487 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
489 if (wndPtr->dwStyle & WS_ICONIC) goto END;
491 /* Remove frame from rectangle */
492 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
494 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
496 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
498 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
500 else if (HAS_THINFRAME( wndPtr->dwStyle ))
502 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
505 /* We have additional border information if the window
506 * is a child (but not an MDI child) */
507 if ( (wndPtr->dwStyle & WS_CHILD) &&
508 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
510 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
511 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
512 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
513 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
517 WIN_ReleasePtr( wndPtr );
521 /***********************************************************************
524 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
526 * FIXME: Just a modified copy of the Win 3.1 version.
529 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
534 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
536 GetWindowRect(wndPtr->hwndSelf, &rect );
537 if (!PtInRect( &rect, pt )) return HTNOWHERE;
539 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
541 /* Check client area */
543 ScreenToClient( wndPtr->hwndSelf, &ptClient );
544 GetClientRect( wndPtr->hwndSelf, &rcClient );
545 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
548 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
550 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
551 if (!PtInRect( &rect, pt ))
553 /* Check top sizing border */
556 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
557 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
560 /* Check bottom sizing border */
561 if (pt.y >= rect.bottom)
563 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
564 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
567 /* Check left sizing border */
568 if (pt.x < rect.left)
570 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
571 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
574 /* Check right sizing border */
575 if (pt.x >= rect.right)
577 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
578 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
583 else /* No thick frame */
585 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
586 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
587 else if (HAS_THINFRAME( wndPtr->dwStyle ))
588 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
589 if (!PtInRect( &rect, pt )) return HTBORDER;
594 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
596 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
597 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
599 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
600 if (!PtInRect( &rect, pt ))
602 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
603 (wndPtr->dwStyle & WS_MINIMIZEBOX);
604 /* Check system menu */
605 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
607 if (NC_IconForWindow(wndPtr->hwndSelf))
608 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
610 if (pt.x < rect.left) return HTSYSMENU;
612 /* Check close button */
613 if (wndPtr->dwStyle & WS_SYSMENU)
614 rect.right -= GetSystemMetrics(SM_CYCAPTION);
615 if (pt.x > rect.right) return HTCLOSE;
617 /* Check maximize box */
618 /* In win95 there is automatically a Maximize button when there is a minimize one*/
619 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
620 rect.right -= GetSystemMetrics(SM_CXSIZE);
621 if (pt.x > rect.right) return HTMAXBUTTON;
623 /* Check minimize box */
624 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
625 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
626 rect.right -= GetSystemMetrics(SM_CXSIZE);
628 if (pt.x > rect.right) return HTMINBUTTON;
633 /* Check vertical scroll bar */
635 if (wndPtr->dwStyle & WS_VSCROLL)
637 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
638 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
640 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
641 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
644 /* Check horizontal scroll bar */
646 if (wndPtr->dwStyle & WS_HSCROLL)
648 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
649 if (PtInRect( &rcClient, ptClient ))
652 if ((wndPtr->dwStyle & WS_VSCROLL) &&
653 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
654 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
662 if (HAS_MENU(wndPtr))
664 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
668 /* Has to return HTNOWHERE if nothing was found
669 Could happen when a window has a customized non client area */
674 /***********************************************************************
677 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
679 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
682 WND *wndPtr = WIN_GetPtr( hwnd );
684 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
686 retvalue = NC_DoNCHitTest (wndPtr, pt);
687 WIN_ReleasePtr( wndPtr );
692 /******************************************************************************
696 * Draws the system icon.
698 *****************************************************************************/
699 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
701 HICON hIcon = NC_IconForWindow( hwnd );
706 NC_GetInsideRect( hwnd, &rect );
707 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
708 GetSystemMetrics(SM_CXSMICON),
709 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
715 /******************************************************************************
719 * Draws the close button.
721 * If bGrayed is true, then draw a disabled Close button
723 *****************************************************************************/
725 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
729 NC_GetInsideRect( hwnd, &rect );
731 /* A tool window has a smaller Close button */
732 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
734 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
735 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
736 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
738 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
739 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
740 rect.bottom = rect.top + iBmpHeight;
741 rect.right = rect.left + iBmpWidth;
745 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
746 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
750 DrawFrameControl( hdc, &rect, DFC_CAPTION,
752 (down ? DFCS_PUSHED : 0) |
753 (bGrayed ? DFCS_INACTIVE : 0)) );
756 /******************************************************************************
759 * Draws the maximize button for windows.
760 * If bGrayed is true, then draw a disabled Maximize button
762 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
767 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
768 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
771 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
773 NC_GetInsideRect( hwnd, &rect );
774 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
775 rect.right -= GetSystemMetrics(SM_CXSIZE);
776 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
777 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
780 if (down) flags |= DFCS_PUSHED;
781 if (bGrayed) flags |= DFCS_INACTIVE;
782 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
785 /******************************************************************************
788 * Draws the minimize button for windows.
789 * If bGrayed is true, then draw a disabled Minimize button
791 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
794 UINT flags = DFCS_CAPTIONMIN;
795 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
797 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
798 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
801 NC_GetInsideRect( hwnd, &rect );
802 if (style & WS_SYSMENU)
803 rect.right -= GetSystemMetrics(SM_CXSIZE);
804 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
805 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
806 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
807 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
810 if (down) flags |= DFCS_PUSHED;
811 if (bGrayed) flags |= DFCS_INACTIVE;
812 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
815 /******************************************************************************
819 * Draw a window frame inside the given rectangle, and update the rectangle.
822 * Many. First, just what IS a frame in Win95? Note that the 3D look
823 * on the outer edge is handled by NC_DoNCPaint. As is the inner
824 * edge. The inner rectangle just inside the frame is handled by the
827 * In short, for most people, this function should be a nop (unless
828 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
829 * them lately, but just to get this code right). Even so, it doesn't
830 * appear to be so. It's being worked on...
832 *****************************************************************************/
834 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
838 /* Firstly the "thick" frame */
839 if (style & WS_THICKFRAME)
841 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
842 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
844 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
845 COLOR_INACTIVEBORDER) );
847 PatBlt( hdc, rect->left, rect->top,
848 rect->right - rect->left, height, PATCOPY );
849 PatBlt( hdc, rect->left, rect->top,
850 width, rect->bottom - rect->top, PATCOPY );
851 PatBlt( hdc, rect->left, rect->bottom - 1,
852 rect->right - rect->left, -height, PATCOPY );
853 PatBlt( hdc, rect->right - 1, rect->top,
854 -width, rect->bottom - rect->top, PATCOPY );
856 InflateRect( rect, -width, -height );
859 /* Now the other bit of the frame */
860 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
861 (exStyle & WS_EX_DLGMODALFRAME))
863 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
864 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
865 /* This should give a value of 1 that should also work for a border */
867 SelectObject( hdc, GetSysColorBrush(
868 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
870 (exStyle & WS_EX_STATICEDGE) ?
872 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
878 PatBlt( hdc, rect->left, rect->top,
879 rect->right - rect->left, height, PATCOPY );
880 PatBlt( hdc, rect->left, rect->top,
881 width, rect->bottom - rect->top, PATCOPY );
882 PatBlt( hdc, rect->left, rect->bottom - 1,
883 rect->right - rect->left, -height, PATCOPY );
884 PatBlt( hdc, rect->right - 1, rect->top,
885 -width, rect->bottom - rect->top, PATCOPY );
887 InflateRect( rect, -width, -height );
892 /******************************************************************************
896 * Draw the window caption for windows.
897 * The correct pen for the window frame must be selected in the DC.
899 *****************************************************************************/
901 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
902 DWORD exStyle, BOOL active )
908 BOOL gradient = FALSE;
910 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
911 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
912 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
913 COLOR_WINDOWFRAME : COLOR_3DFACE) );
914 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
915 LineTo( hdc, r.right, r.bottom - 1 );
916 SelectObject( hdc, hPrevPen );
919 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
920 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
922 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
923 if (NC_DrawSysButton (hwnd, hdc, FALSE))
924 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
927 if (style & WS_SYSMENU)
931 /* Go get the sysmenu */
932 hSysMenu = GetSystemMenu(hwnd, FALSE);
933 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
935 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
936 NC_DrawCloseButton (hwnd, hdc, FALSE,
937 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
938 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
940 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
942 /* In win95 the two buttons are always there */
943 /* But if the menu item is not in the menu they're disabled*/
945 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
946 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
948 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
949 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
953 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
955 NONCLIENTMETRICSW nclm;
956 HFONT hFont, hOldFont;
957 nclm.cbSize = sizeof(nclm);
958 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
959 if (exStyle & WS_EX_TOOLWINDOW)
960 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
962 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
963 hOldFont = SelectObject (hdc, hFont);
964 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
965 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
966 SetBkMode( hdc, TRANSPARENT );
968 DrawTextW( hdc, buffer, -1, &r,
969 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
970 DeleteObject (SelectObject (hdc, hOldFont));
975 /******************************************************************************
978 * Paint the non-client area for windows.
980 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
983 RECT rfuzz, rect, rectClip;
986 DWORD dwStyle, dwExStyle;
989 RECT rectClient, rectWindow;
992 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
993 has_menu = HAS_MENU(wndPtr);
994 dwStyle = wndPtr->dwStyle;
995 dwExStyle = wndPtr->dwExStyle;
996 flags = wndPtr->flags;
997 rectWindow = wndPtr->rectWindow;
998 WIN_ReleasePtr( wndPtr );
1000 if ( dwStyle & WS_MINIMIZE ||
1001 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1003 active = flags & WIN_NCACTIVATED;
1005 TRACE("%p %d\n", hwnd, active );
1007 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1008 the call to GetDCEx implying that it is allowed not to use it either.
1009 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1010 will cause clipRgn to be deleted after ReleaseDC().
1011 Now, how is the "system" supposed to tell what happened?
1014 GetClientRect( hwnd, &rectClient );
1015 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1016 hrgn = CreateRectRgnIndirect( &rectClient );
1020 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1021 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1025 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1030 rect.top = rect.left = 0;
1031 rect.right = rectWindow.right - rectWindow.left;
1032 rect.bottom = rectWindow.bottom - rectWindow.top;
1033 GetClipBox( hdc, &rectClip );
1035 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1037 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1038 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1040 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1041 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1044 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1046 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1049 if (dwExStyle & WS_EX_TOOLWINDOW) {
1050 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1051 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1054 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1055 rect.top += GetSystemMetrics(SM_CYCAPTION);
1057 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1058 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1064 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1066 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1068 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1071 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1073 if (dwExStyle & WS_EX_CLIENTEDGE)
1074 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1076 /* Draw the scroll-bars */
1078 if (dwStyle & WS_VSCROLL)
1079 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1080 if (dwStyle & WS_HSCROLL)
1081 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1083 /* Draw the "size-box" */
1084 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1087 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1088 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1090 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1091 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1092 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1095 ReleaseDC( hwnd, hdc );
1101 /***********************************************************************
1104 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1106 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1108 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1110 if( dwStyle & WS_VISIBLE )
1112 if( dwStyle & WS_MINIMIZE )
1113 WINPOS_RedrawIconTitle( hwnd );
1115 NC_DoNCPaint( hwnd, clip, FALSE );
1121 /***********************************************************************
1122 * NC_HandleNCActivate
1124 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1126 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1128 WND* wndPtr = WIN_GetPtr( hwnd );
1130 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1132 /* Lotus Notes draws menu descriptions in the caption of its main
1133 * window. When it wants to restore original "system" view, it just
1134 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1135 * attempt to minimize redrawings lead to a not restored caption.
1137 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1138 else wndPtr->flags &= ~WIN_NCACTIVATED;
1139 WIN_ReleasePtr( wndPtr );
1141 /* This isn't documented but is reproducible in at least XP SP2 and
1142 * Outlook 2007 depends on it
1147 WINPOS_RedrawIconTitle( hwnd );
1149 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1156 /***********************************************************************
1157 * NC_HandleSetCursor
1159 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1161 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1163 hwnd = WIN_GetFullHandle( (HWND)wParam );
1165 switch((short)LOWORD(lParam))
1169 WORD msg = HIWORD( lParam );
1170 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1171 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1178 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1188 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1192 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1196 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1200 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1203 /* Default cursor: arrow */
1204 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1207 /***********************************************************************
1210 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1212 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1215 WND *wndPtr = WIN_GetPtr( hwnd );
1216 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1218 NC_GetInsideRect( hwnd, rect );
1219 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1220 if (wndPtr->dwStyle & WS_CHILD)
1221 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1222 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1223 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1224 WIN_ReleasePtr( wndPtr );
1228 /***********************************************************************
1231 * Track a mouse button press on the minimize or maximize box.
1233 * The big difference between 3.1 and 95 is the disabled button state.
1234 * In win95 the system button can be disabled, so it can ignore the mouse
1238 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1241 HDC hdc = GetWindowDC( hwnd );
1242 BOOL pressed = TRUE;
1244 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1245 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1247 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1249 if (wParam == HTMINBUTTON)
1251 /* If the style is not present, do nothing */
1252 if (!(wndStyle & WS_MINIMIZEBOX))
1255 /* Check if the sysmenu item for minimize is there */
1256 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1258 paintButton = &NC_DrawMinButton;
1262 /* If the style is not present, do nothing */
1263 if (!(wndStyle & WS_MAXIMIZEBOX))
1266 /* Check if the sysmenu item for maximize is there */
1267 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1269 paintButton = &NC_DrawMaxButton;
1274 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1278 BOOL oldstate = pressed;
1280 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1281 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1283 if(msg.message == WM_LBUTTONUP)
1286 if(msg.message != WM_MOUSEMOVE)
1289 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1290 if (pressed != oldstate)
1291 (*paintButton)( hwnd, hdc, pressed, FALSE);
1295 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1298 ReleaseDC( hwnd, hdc );
1300 /* If the item minimize or maximize of the sysmenu are not there */
1301 /* or if the style is not present, do nothing */
1302 if ((!pressed) || (state == 0xFFFFFFFF))
1305 if (wParam == HTMINBUTTON)
1306 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1308 SendMessageW( hwnd, WM_SYSCOMMAND,
1309 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1312 /***********************************************************************
1313 * NC_TrackCloseButton
1315 * Track a mouse button press on the Win95 close button.
1317 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1321 BOOL pressed = TRUE;
1322 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1328 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1330 /* If the item close of the sysmenu is disabled or not there do nothing */
1331 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1334 hdc = GetWindowDC( hwnd );
1338 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1342 BOOL oldstate = pressed;
1344 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1345 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1347 if(msg.message == WM_LBUTTONUP)
1350 if(msg.message != WM_MOUSEMOVE)
1353 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1354 if (pressed != oldstate)
1355 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1359 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1362 ReleaseDC( hwnd, hdc );
1363 if (!pressed) return;
1365 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1369 /***********************************************************************
1372 * Track a mouse button press on the horizontal or vertical scroll-bar.
1374 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1378 if ((wParam & 0xfff0) == SC_HSCROLL)
1380 if ((wParam & 0x0f) != HTHSCROLL) return;
1381 scrollbar = SB_HORZ;
1383 else /* SC_VSCROLL */
1385 if ((wParam & 0x0f) != HTVSCROLL) return;
1386 scrollbar = SB_VERT;
1388 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1392 /***********************************************************************
1393 * NC_HandleNCLButtonDown
1395 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1397 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1399 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1401 switch(wParam) /* Hit test */
1405 HWND top = GetAncestor( hwnd, GA_ROOT );
1407 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1408 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1413 if( style & WS_SYSMENU )
1415 if( !(style & WS_MINIMIZE) )
1417 HDC hDC = GetWindowDC(hwnd);
1418 NC_DrawSysButton( hwnd, hDC, TRUE );
1419 ReleaseDC( hwnd, hDC );
1421 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1426 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1430 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1434 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1439 NC_TrackMinMaxBox( hwnd, wParam );
1443 NC_TrackCloseButton (hwnd, wParam);
1455 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1456 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1458 /* But that is not what WinNT does. Instead it sends this. This
1459 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1460 * SC_MOUSEMENU into wParam.
1462 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1472 /***********************************************************************
1473 * NC_HandleNCLButtonDblClk
1475 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1477 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1480 * if this is an icon, send a restore since we are handling
1485 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1489 switch(wParam) /* Hit test */
1492 /* stop processing if WS_MAXIMIZEBOX is missing */
1493 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1494 SendMessageW( hwnd, WM_SYSCOMMAND,
1495 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1500 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1501 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1503 /* If the item close of the sysmenu is disabled or not there do nothing */
1504 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1507 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1512 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1516 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1523 /***********************************************************************
1524 * NC_HandleSysCommand
1526 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1528 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1530 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1532 if (!IsWindowEnabled( hwnd )) return 0;
1534 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1537 switch (wParam & 0xfff0)
1541 WINPOS_SysCommandSizeMove( hwnd, wParam );
1545 if (hwnd == GetForegroundWindow())
1546 ShowOwnedPopups(hwnd,FALSE);
1547 ShowWindow( hwnd, SW_MINIMIZE );
1551 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1552 ShowOwnedPopups(hwnd,TRUE);
1553 ShowWindow( hwnd, SW_MAXIMIZE );
1557 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1558 ShowOwnedPopups(hwnd,TRUE);
1559 ShowWindow( hwnd, SW_RESTORE );
1563 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1569 pt.x = (short)LOWORD(lParam);
1570 pt.y = (short)HIWORD(lParam);
1571 NC_TrackScrollBar( hwnd, wParam, pt );
1578 pt.x = (short)LOWORD(lParam);
1579 pt.y = (short)HIWORD(lParam);
1580 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1585 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1589 WinExec( "taskman.exe", SW_SHOWNORMAL );
1593 if (wParam == SC_ABOUTWINE)
1595 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1598 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1599 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1600 FreeLibrary( hmodule );
1604 if (wParam == SC_PUTMARK)
1605 DPRINTF("Debug mark requested by user\n");
1612 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1618 /***********************************************************************
1619 * GetTitleBarInfo (USER32.@)
1620 * TODO: Handle STATE_SYSTEM_PRESSED
1622 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1627 TRACE("(%p %p)\n", hwnd, tbi);
1629 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1630 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1631 SetLastError(ERROR_INVALID_PARAMETER);
1634 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1635 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1636 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1638 GetWindowRect(hwnd, &wndRect);
1640 tbi->rcTitleBar.top += wndRect.top;
1641 tbi->rcTitleBar.left += wndRect.left;
1642 tbi->rcTitleBar.right += wndRect.left;
1644 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1645 if(dwExStyle & WS_EX_TOOLWINDOW)
1646 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1648 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1649 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1652 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1653 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1654 * Under XP it seems to
1656 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1657 if(dwStyle & WS_CAPTION) {
1658 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1659 if(dwStyle & WS_SYSMENU) {
1660 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1661 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1662 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1665 if(!(dwStyle & WS_MINIMIZEBOX))
1666 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1667 if(!(dwStyle & WS_MAXIMIZEBOX))
1668 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1670 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1671 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1672 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1673 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1676 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1677 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1678 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1679 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1683 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;