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
30 #include "user_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
36 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
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 );
424 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
425 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
429 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
431 winRect->left -= tmpRect.left;
432 winRect->top -= tmpRect.top;
433 winRect->right -= tmpRect.right;
434 winRect->bottom -= tmpRect.bottom;
436 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
438 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
439 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
442 MENU_GetMenuBarHeight( hwnd,
443 winRect->right - winRect->left,
444 -tmpRect.left, -tmpRect.top );
447 if( exStyle & WS_EX_CLIENTEDGE)
448 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
449 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
450 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
451 - GetSystemMetrics(SM_CYEDGE));
453 if (style & WS_VSCROLL)
454 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
455 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
456 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
458 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
461 if (style & WS_HSCROLL)
462 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
463 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
465 if (winRect->top > winRect->bottom)
466 winRect->bottom = winRect->top;
468 if (winRect->left > winRect->right)
469 winRect->right = winRect->left;
475 /***********************************************************************
478 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
479 * but without the borders (if any).
480 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
482 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
484 WND *wndPtr = WIN_GetPtr( hwnd );
486 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
488 rect->top = rect->left = 0;
489 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
490 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
492 if (wndPtr->dwStyle & WS_ICONIC) goto END;
494 /* Remove frame from rectangle */
495 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
497 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
499 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
501 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
503 else if (HAS_THINFRAME( wndPtr->dwStyle ))
505 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
508 /* We have additional border information if the window
509 * is a child (but not an MDI child) */
510 if ( (wndPtr->dwStyle & WS_CHILD) &&
511 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
513 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
514 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
515 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
516 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
520 WIN_ReleasePtr( wndPtr );
524 /***********************************************************************
527 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
529 * FIXME: Just a modified copy of the Win 3.1 version.
532 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
537 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->obj.handle, pt.x, pt.y );
539 GetWindowRect(wndPtr->obj.handle, &rect );
540 if (!PtInRect( &rect, pt )) return HTNOWHERE;
542 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
544 /* Check client area */
546 ScreenToClient( wndPtr->obj.handle, &ptClient );
547 GetClientRect( wndPtr->obj.handle, &rcClient );
548 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
551 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
553 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
554 if (!PtInRect( &rect, pt ))
556 /* Check top sizing border */
559 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
560 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
563 /* Check bottom sizing border */
564 if (pt.y >= rect.bottom)
566 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
567 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
570 /* Check left sizing border */
571 if (pt.x < rect.left)
573 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
574 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
577 /* Check right sizing border */
578 if (pt.x >= rect.right)
580 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
581 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
586 else /* No thick frame */
588 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
589 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
590 else if (HAS_THINFRAME( wndPtr->dwStyle ))
591 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
592 if (!PtInRect( &rect, pt )) return HTBORDER;
597 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
599 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
600 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
602 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
603 if (!PtInRect( &rect, pt ))
605 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
606 (wndPtr->dwStyle & WS_MINIMIZEBOX);
607 /* Check system menu */
608 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
610 if (NC_IconForWindow(wndPtr->obj.handle))
611 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
613 if (pt.x < rect.left) return HTSYSMENU;
615 /* Check close button */
616 if (wndPtr->dwStyle & WS_SYSMENU)
617 rect.right -= GetSystemMetrics(SM_CYCAPTION);
618 if (pt.x > rect.right) return HTCLOSE;
620 /* Check maximize box */
621 /* In win95 there is automatically a Maximize button when there is a minimize one*/
622 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
623 rect.right -= GetSystemMetrics(SM_CXSIZE);
624 if (pt.x > rect.right) return HTMAXBUTTON;
626 /* Check minimize box */
627 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
628 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
629 rect.right -= GetSystemMetrics(SM_CXSIZE);
631 if (pt.x > rect.right) return HTMINBUTTON;
636 /* Check vertical scroll bar */
638 if (wndPtr->dwStyle & WS_VSCROLL)
640 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
641 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
643 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
644 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
647 /* Check horizontal scroll bar */
649 if (wndPtr->dwStyle & WS_HSCROLL)
651 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
652 if (PtInRect( &rcClient, ptClient ))
655 if ((wndPtr->dwStyle & WS_VSCROLL) &&
656 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
657 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
665 if (HAS_MENU(wndPtr))
667 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
671 /* Has to return HTNOWHERE if nothing was found
672 Could happen when a window has a customized non client area */
677 /***********************************************************************
680 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
682 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
685 WND *wndPtr = WIN_GetPtr( hwnd );
687 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
689 retvalue = NC_DoNCHitTest (wndPtr, pt);
690 WIN_ReleasePtr( wndPtr );
695 /******************************************************************************
699 * Draws the system icon.
701 *****************************************************************************/
702 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
704 HICON hIcon = NC_IconForWindow( hwnd );
709 NC_GetInsideRect( hwnd, &rect );
710 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
711 GetSystemMetrics(SM_CXSMICON),
712 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
718 /******************************************************************************
722 * Draws the close button.
724 * If bGrayed is true, then draw a disabled Close button
726 *****************************************************************************/
728 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
732 NC_GetInsideRect( hwnd, &rect );
734 /* A tool window has a smaller Close button */
735 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
737 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
738 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
739 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
741 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
742 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
743 rect.bottom = rect.top + iBmpHeight;
744 rect.right = rect.left + iBmpWidth;
748 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
749 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
753 DrawFrameControl( hdc, &rect, DFC_CAPTION,
755 (down ? DFCS_PUSHED : 0) |
756 (bGrayed ? DFCS_INACTIVE : 0)) );
759 /******************************************************************************
762 * Draws the maximize button for windows.
763 * If bGrayed is true, then draw a disabled Maximize button
765 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
770 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
771 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
774 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
776 NC_GetInsideRect( hwnd, &rect );
777 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
778 rect.right -= GetSystemMetrics(SM_CXSIZE);
779 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
780 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
783 if (down) flags |= DFCS_PUSHED;
784 if (bGrayed) flags |= DFCS_INACTIVE;
785 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
788 /******************************************************************************
791 * Draws the minimize button for windows.
792 * If bGrayed is true, then draw a disabled Minimize button
794 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
797 UINT flags = DFCS_CAPTIONMIN;
798 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
800 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
801 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
804 NC_GetInsideRect( hwnd, &rect );
805 if (style & WS_SYSMENU)
806 rect.right -= GetSystemMetrics(SM_CXSIZE);
807 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
808 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
809 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
810 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
813 if (down) flags |= DFCS_PUSHED;
814 if (bGrayed) flags |= DFCS_INACTIVE;
815 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
818 /******************************************************************************
822 * Draw a window frame inside the given rectangle, and update the rectangle.
825 * Many. First, just what IS a frame in Win95? Note that the 3D look
826 * on the outer edge is handled by NC_DoNCPaint. As is the inner
827 * edge. The inner rectangle just inside the frame is handled by the
830 * In short, for most people, this function should be a nop (unless
831 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
832 * them lately, but just to get this code right). Even so, it doesn't
833 * appear to be so. It's being worked on...
835 *****************************************************************************/
837 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
841 /* Firstly the "thick" frame */
842 if (style & WS_THICKFRAME)
844 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
845 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
847 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
848 COLOR_INACTIVEBORDER) );
850 PatBlt( hdc, rect->left, rect->top,
851 rect->right - rect->left, height, PATCOPY );
852 PatBlt( hdc, rect->left, rect->top,
853 width, rect->bottom - rect->top, PATCOPY );
854 PatBlt( hdc, rect->left, rect->bottom - 1,
855 rect->right - rect->left, -height, PATCOPY );
856 PatBlt( hdc, rect->right - 1, rect->top,
857 -width, rect->bottom - rect->top, PATCOPY );
859 InflateRect( rect, -width, -height );
862 /* Now the other bit of the frame */
863 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
864 (exStyle & WS_EX_DLGMODALFRAME))
866 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
867 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
868 /* This should give a value of 1 that should also work for a border */
870 SelectObject( hdc, GetSysColorBrush(
871 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
873 (exStyle & WS_EX_STATICEDGE) ?
875 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
881 PatBlt( hdc, rect->left, rect->top,
882 rect->right - rect->left, height, PATCOPY );
883 PatBlt( hdc, rect->left, rect->top,
884 width, rect->bottom - rect->top, PATCOPY );
885 PatBlt( hdc, rect->left, rect->bottom - 1,
886 rect->right - rect->left, -height, PATCOPY );
887 PatBlt( hdc, rect->right - 1, rect->top,
888 -width, rect->bottom - rect->top, PATCOPY );
890 InflateRect( rect, -width, -height );
895 /******************************************************************************
899 * Draw the window caption for windows.
900 * The correct pen for the window frame must be selected in the DC.
902 *****************************************************************************/
904 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
905 DWORD exStyle, BOOL active )
911 BOOL gradient = FALSE;
913 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
914 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
915 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
916 COLOR_WINDOWFRAME : COLOR_3DFACE) );
917 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
918 LineTo( hdc, r.right, r.bottom - 1 );
919 SelectObject( hdc, hPrevPen );
922 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
923 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
925 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
926 if (NC_DrawSysButton (hwnd, hdc, FALSE))
927 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
930 if (style & WS_SYSMENU)
934 /* Go get the sysmenu */
935 hSysMenu = GetSystemMenu(hwnd, FALSE);
936 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
938 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
939 NC_DrawCloseButton (hwnd, hdc, FALSE,
940 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
941 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
943 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
945 /* In win95 the two buttons are always there */
946 /* But if the menu item is not in the menu they're disabled*/
948 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
949 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
951 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
952 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
956 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
958 NONCLIENTMETRICSW nclm;
959 HFONT hFont, hOldFont;
960 nclm.cbSize = sizeof(nclm);
961 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
962 if (exStyle & WS_EX_TOOLWINDOW)
963 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
965 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
966 hOldFont = SelectObject (hdc, hFont);
967 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
968 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
969 SetBkMode( hdc, TRANSPARENT );
971 DrawTextW( hdc, buffer, -1, &r,
972 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
973 DeleteObject (SelectObject (hdc, hOldFont));
978 /******************************************************************************
981 * Paint the non-client area for windows.
983 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
986 RECT rfuzz, rect, rectClip;
989 DWORD dwStyle, dwExStyle;
992 RECT rectClient, rectWindow;
995 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
996 has_menu = HAS_MENU(wndPtr);
997 dwStyle = wndPtr->dwStyle;
998 dwExStyle = wndPtr->dwExStyle;
999 flags = wndPtr->flags;
1000 rectWindow = wndPtr->rectWindow;
1001 WIN_ReleasePtr( wndPtr );
1003 if ( dwStyle & WS_MINIMIZE ||
1004 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1006 active = flags & WIN_NCACTIVATED;
1008 TRACE("%p %d\n", hwnd, active );
1010 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1011 the call to GetDCEx implying that it is allowed not to use it either.
1012 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1013 will cause clipRgn to be deleted after ReleaseDC().
1014 Now, how is the "system" supposed to tell what happened?
1017 GetClientRect( hwnd, &rectClient );
1018 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1019 hrgn = CreateRectRgnIndirect( &rectClient );
1023 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1024 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1028 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1033 rect.top = rect.left = 0;
1034 rect.right = rectWindow.right - rectWindow.left;
1035 rect.bottom = rectWindow.bottom - rectWindow.top;
1036 GetClipBox( hdc, &rectClip );
1038 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1040 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1041 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1043 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1044 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1047 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1049 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1052 if (dwExStyle & WS_EX_TOOLWINDOW) {
1053 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1054 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1057 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1058 rect.top += GetSystemMetrics(SM_CYCAPTION);
1060 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1061 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1067 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1069 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1071 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1074 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1076 if (dwExStyle & WS_EX_CLIENTEDGE)
1077 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1079 /* Draw the scroll-bars */
1081 if (dwStyle & WS_VSCROLL)
1082 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1083 if (dwStyle & WS_HSCROLL)
1084 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1086 /* Draw the "size-box" */
1087 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1090 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1091 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1093 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1094 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1095 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1098 ReleaseDC( hwnd, hdc );
1104 /***********************************************************************
1107 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1109 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1111 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1113 if( dwStyle & WS_VISIBLE )
1115 if( dwStyle & WS_MINIMIZE )
1116 WINPOS_RedrawIconTitle( hwnd );
1118 NC_DoNCPaint( hwnd, clip, FALSE );
1124 /***********************************************************************
1125 * NC_HandleNCActivate
1127 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1129 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1131 WND* wndPtr = WIN_GetPtr( hwnd );
1133 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1135 /* Lotus Notes draws menu descriptions in the caption of its main
1136 * window. When it wants to restore original "system" view, it just
1137 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1138 * attempt to minimize redrawings lead to a not restored caption.
1140 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1141 else wndPtr->flags &= ~WIN_NCACTIVATED;
1142 WIN_ReleasePtr( wndPtr );
1144 /* This isn't documented but is reproducible in at least XP SP2 and
1145 * Outlook 2007 depends on it
1150 WINPOS_RedrawIconTitle( hwnd );
1152 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1159 /***********************************************************************
1160 * NC_HandleSetCursor
1162 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1164 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1166 hwnd = WIN_GetFullHandle( (HWND)wParam );
1168 switch((short)LOWORD(lParam))
1172 WORD msg = HIWORD( lParam );
1173 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1174 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1181 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1191 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1195 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1199 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1203 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1206 /* Default cursor: arrow */
1207 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1210 /***********************************************************************
1213 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1215 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1218 WND *wndPtr = WIN_GetPtr( hwnd );
1219 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1221 NC_GetInsideRect( hwnd, rect );
1222 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1223 if (wndPtr->dwStyle & WS_CHILD)
1224 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1225 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1226 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1227 WIN_ReleasePtr( wndPtr );
1231 /***********************************************************************
1234 * Track a mouse button press on the minimize or maximize box.
1236 * The big difference between 3.1 and 95 is the disabled button state.
1237 * In win95 the system button can be disabled, so it can ignore the mouse
1241 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1244 HDC hdc = GetWindowDC( hwnd );
1245 BOOL pressed = TRUE;
1247 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1248 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1250 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1252 if (wParam == HTMINBUTTON)
1254 /* If the style is not present, do nothing */
1255 if (!(wndStyle & WS_MINIMIZEBOX))
1258 /* Check if the sysmenu item for minimize is there */
1259 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1261 paintButton = NC_DrawMinButton;
1265 /* If the style is not present, do nothing */
1266 if (!(wndStyle & WS_MAXIMIZEBOX))
1269 /* Check if the sysmenu item for maximize is there */
1270 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1272 paintButton = NC_DrawMaxButton;
1277 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1281 BOOL oldstate = pressed;
1283 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1284 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1286 if(msg.message == WM_LBUTTONUP)
1289 if(msg.message != WM_MOUSEMOVE)
1292 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1293 if (pressed != oldstate)
1294 (*paintButton)( hwnd, hdc, pressed, FALSE);
1298 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1301 ReleaseDC( hwnd, hdc );
1303 /* If the item minimize or maximize of the sysmenu are not there */
1304 /* or if the style is not present, do nothing */
1305 if ((!pressed) || (state == 0xFFFFFFFF))
1308 if (wParam == HTMINBUTTON)
1309 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1311 SendMessageW( hwnd, WM_SYSCOMMAND,
1312 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1315 /***********************************************************************
1316 * NC_TrackCloseButton
1318 * Track a mouse button press on the Win95 close button.
1320 static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1324 BOOL pressed = TRUE;
1325 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1331 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1333 /* If the item close of the sysmenu is disabled or not there do nothing */
1334 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1337 hdc = GetWindowDC( hwnd );
1341 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1345 BOOL oldstate = pressed;
1347 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1348 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1350 if(msg.message == WM_LBUTTONUP)
1353 if(msg.message != WM_MOUSEMOVE)
1356 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1357 if (pressed != oldstate)
1358 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1362 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1365 ReleaseDC( hwnd, hdc );
1366 if (!pressed) return;
1368 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1372 /***********************************************************************
1375 * Track a mouse button press on the horizontal or vertical scroll-bar.
1377 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1381 if ((wParam & 0xfff0) == SC_HSCROLL)
1383 if ((wParam & 0x0f) != HTHSCROLL) return;
1384 scrollbar = SB_HORZ;
1386 else /* SC_VSCROLL */
1388 if ((wParam & 0x0f) != HTVSCROLL) return;
1389 scrollbar = SB_VERT;
1391 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1395 /***********************************************************************
1396 * NC_HandleNCLButtonDown
1398 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1400 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1402 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1404 switch(wParam) /* Hit test */
1408 HWND top = GetAncestor( hwnd, GA_ROOT );
1410 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1411 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1416 if( style & WS_SYSMENU )
1418 if( !(style & WS_MINIMIZE) )
1420 HDC hDC = GetWindowDC(hwnd);
1421 NC_DrawSysButton( hwnd, hDC, TRUE );
1422 ReleaseDC( hwnd, hDC );
1424 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1429 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1433 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1442 NC_TrackMinMaxBox( hwnd, wParam );
1446 NC_TrackCloseButton (hwnd, wParam, lParam);
1458 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1459 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1461 /* But that is not what WinNT does. Instead it sends this. This
1462 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1463 * SC_MOUSEMENU into wParam.
1465 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1475 /***********************************************************************
1476 * NC_HandleNCLButtonDblClk
1478 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1480 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1483 * if this is an icon, send a restore since we are handling
1488 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1492 switch(wParam) /* Hit test */
1495 /* stop processing if WS_MAXIMIZEBOX is missing */
1496 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1497 SendMessageW( hwnd, WM_SYSCOMMAND,
1498 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1503 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1504 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1506 /* If the item close of the sysmenu is disabled or not there do nothing */
1507 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1510 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1515 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1519 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1526 /***********************************************************************
1527 * NC_HandleSysCommand
1529 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1531 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1533 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1535 if (!IsWindowEnabled( hwnd )) return 0;
1537 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1540 if (!USER_Driver->pSysCommand( hwnd, wParam, lParam ))
1543 switch (wParam & 0xfff0)
1547 WINPOS_SysCommandSizeMove( hwnd, wParam );
1551 if (hwnd == GetActiveWindow())
1552 ShowOwnedPopups(hwnd,FALSE);
1553 ShowWindow( hwnd, SW_MINIMIZE );
1557 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1558 ShowOwnedPopups(hwnd,TRUE);
1559 ShowWindow( hwnd, SW_MAXIMIZE );
1563 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1564 ShowOwnedPopups(hwnd,TRUE);
1565 ShowWindow( hwnd, SW_RESTORE );
1569 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1575 pt.x = (short)LOWORD(lParam);
1576 pt.y = (short)HIWORD(lParam);
1577 NC_TrackScrollBar( hwnd, wParam, pt );
1584 pt.x = (short)LOWORD(lParam);
1585 pt.y = (short)HIWORD(lParam);
1586 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1591 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1595 WinExec( "taskman.exe", SW_SHOWNORMAL );
1599 if (wParam == SC_ABOUTWINE)
1601 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1604 BOOL (WINAPI *aboutproc)(HWND, LPCSTR, LPCSTR, HICON);
1606 aboutproc = (void *)GetProcAddress( hmodule, "ShellAboutA" );
1607 if (aboutproc) aboutproc( hwnd, PACKAGE_STRING, NULL, 0 );
1608 FreeLibrary( hmodule );
1617 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1623 /***********************************************************************
1624 * GetTitleBarInfo (USER32.@)
1625 * TODO: Handle STATE_SYSTEM_PRESSED
1627 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1632 TRACE("(%p %p)\n", hwnd, tbi);
1635 SetLastError(ERROR_NOACCESS);
1639 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1640 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1641 SetLastError(ERROR_INVALID_PARAMETER);
1644 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1645 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1646 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1648 GetWindowRect(hwnd, &wndRect);
1650 tbi->rcTitleBar.top += wndRect.top;
1651 tbi->rcTitleBar.left += wndRect.left;
1652 tbi->rcTitleBar.right += wndRect.left;
1654 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1655 if(dwExStyle & WS_EX_TOOLWINDOW)
1656 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1658 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1659 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1662 ZeroMemory(tbi->rgstate, sizeof(tbi->rgstate));
1663 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1664 * Under XP it seems to
1666 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1667 if(dwStyle & WS_CAPTION) {
1668 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1669 if(dwStyle & WS_SYSMENU) {
1670 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1671 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1672 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1675 if(!(dwStyle & WS_MINIMIZEBOX))
1676 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1677 if(!(dwStyle & WS_MAXIMIZEBOX))
1678 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1680 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1681 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1682 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1683 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1686 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1687 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1688 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1689 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1693 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;