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(hwnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
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).
481 static void NC_GetInsideRect( HWND hwnd, enum coords_relative relative, RECT *rect,
482 DWORD style, DWORD ex_style )
484 WIN_GetRectangles( hwnd, relative, rect, NULL );
486 if (style & WS_ICONIC) return;
488 /* Remove frame from rectangle */
489 if (HAS_THICKFRAME( style, ex_style ))
491 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
493 else if (HAS_DLGFRAME( style, ex_style ))
495 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
497 else if (HAS_THINFRAME( style ))
499 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
502 /* We have additional border information if the window
503 * is a child (but not an MDI child) */
504 if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD))
506 if (ex_style & WS_EX_CLIENTEDGE)
507 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
508 if (ex_style & WS_EX_STATICEDGE)
509 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
514 /***********************************************************************
517 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
519 LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt )
522 DWORD style, ex_style;
524 TRACE("hwnd=%p pt=%d,%d\n", hwnd, pt.x, pt.y );
526 ScreenToClient( hwnd, &pt );
527 WIN_GetRectangles( hwnd, COORDS_CLIENT, &rect, &rcClient );
528 if (!PtInRect( &rect, pt )) return HTNOWHERE;
530 style = GetWindowLongW( hwnd, GWL_STYLE );
531 ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
532 if (style & WS_MINIMIZE) return HTCAPTION;
534 if (PtInRect( &rcClient, pt )) return HTCLIENT;
537 if (HAS_THICKFRAME( style, ex_style ))
539 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
540 if (!PtInRect( &rect, pt ))
542 /* Check top sizing border */
545 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
546 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
549 /* Check bottom sizing border */
550 if (pt.y >= rect.bottom)
552 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
553 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
556 /* Check left sizing border */
557 if (pt.x < rect.left)
559 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
560 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
563 /* Check right sizing border */
564 if (pt.x >= rect.right)
566 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
567 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
572 else /* No thick frame */
574 if (HAS_DLGFRAME( style, ex_style ))
575 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
576 else if (HAS_THINFRAME( style ))
577 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
578 if (!PtInRect( &rect, pt )) return HTBORDER;
583 if ((style & WS_CAPTION) == WS_CAPTION)
585 if (ex_style & WS_EX_TOOLWINDOW)
586 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
588 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
589 if (!PtInRect( &rect, pt ))
591 BOOL min_or_max_box = (style & WS_MAXIMIZEBOX) ||
592 (style & WS_MINIMIZEBOX);
593 /* Check system menu */
594 if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW))
596 if (NC_IconForWindow(hwnd)) rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
598 if (pt.x < rect.left) return HTSYSMENU;
600 /* Check close button */
601 if (style & WS_SYSMENU)
602 rect.right -= GetSystemMetrics(SM_CYCAPTION);
603 if (pt.x > rect.right) return HTCLOSE;
605 /* Check maximize box */
606 /* In win95 there is automatically a Maximize button when there is a minimize one*/
607 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
608 rect.right -= GetSystemMetrics(SM_CXSIZE);
609 if (pt.x > rect.right) return HTMAXBUTTON;
611 /* Check minimize box */
612 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
613 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
614 rect.right -= GetSystemMetrics(SM_CXSIZE);
616 if (pt.x > rect.right) return HTMINBUTTON;
621 /* Check vertical scroll bar */
623 if (style & WS_VSCROLL)
625 if((ex_style & WS_EX_LEFTSCROLLBAR) != 0)
626 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
628 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
629 if (PtInRect( &rcClient, pt )) return HTVSCROLL;
632 /* Check horizontal scroll bar */
634 if (style & WS_HSCROLL)
636 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
637 if (PtInRect( &rcClient, pt ))
640 if ((style & WS_VSCROLL) &&
641 ((((ex_style & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
642 (((ex_style & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
650 if (HAS_MENU( hwnd, style ))
652 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rcClient.right))
656 /* Has to return HTNOWHERE if nothing was found
657 Could happen when a window has a customized non client area */
662 /******************************************************************************
666 * Draws the system icon.
668 *****************************************************************************/
669 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
671 HICON hIcon = NC_IconForWindow( hwnd );
676 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
677 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
679 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
680 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
681 GetSystemMetrics(SM_CXSMICON),
682 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
688 /******************************************************************************
692 * Draws the close button.
694 * If bGrayed is true, then draw a disabled Close button
696 *****************************************************************************/
698 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
701 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
702 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
704 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
706 /* A tool window has a smaller Close button */
707 if (ex_style & WS_EX_TOOLWINDOW)
709 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
710 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
711 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
713 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
714 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
715 rect.bottom = rect.top + iBmpHeight;
716 rect.right = rect.left + iBmpWidth;
720 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
721 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
725 DrawFrameControl( hdc, &rect, DFC_CAPTION,
727 (down ? DFCS_PUSHED : 0) |
728 (bGrayed ? DFCS_INACTIVE : 0)) );
731 /******************************************************************************
734 * Draws the maximize button for windows.
735 * If bGrayed is true, then draw a disabled Maximize button
737 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
741 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
742 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
744 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
745 if (ex_style & WS_EX_TOOLWINDOW) return;
747 flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
749 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
750 if (style & WS_SYSMENU)
751 rect.right -= GetSystemMetrics(SM_CXSIZE);
752 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
753 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
756 if (down) flags |= DFCS_PUSHED;
757 if (bGrayed) flags |= DFCS_INACTIVE;
758 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
761 /******************************************************************************
764 * Draws the minimize button for windows.
765 * If bGrayed is true, then draw a disabled Minimize button
767 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
770 UINT flags = DFCS_CAPTIONMIN;
771 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
772 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
774 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
775 if (ex_style & WS_EX_TOOLWINDOW) return;
777 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
778 if (style & WS_SYSMENU)
779 rect.right -= GetSystemMetrics(SM_CXSIZE);
780 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
781 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
782 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
783 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
786 if (down) flags |= DFCS_PUSHED;
787 if (bGrayed) flags |= DFCS_INACTIVE;
788 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
791 /******************************************************************************
795 * Draw a window frame inside the given rectangle, and update the rectangle.
798 * Many. First, just what IS a frame in Win95? Note that the 3D look
799 * on the outer edge is handled by NC_DoNCPaint. As is the inner
800 * edge. The inner rectangle just inside the frame is handled by the
803 * In short, for most people, this function should be a nop (unless
804 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
805 * them lately, but just to get this code right). Even so, it doesn't
806 * appear to be so. It's being worked on...
808 *****************************************************************************/
810 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
814 /* Firstly the "thick" frame */
815 if (style & WS_THICKFRAME)
817 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
818 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
820 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
821 COLOR_INACTIVEBORDER) );
823 PatBlt( hdc, rect->left, rect->top,
824 rect->right - rect->left, height, PATCOPY );
825 PatBlt( hdc, rect->left, rect->top,
826 width, rect->bottom - rect->top, PATCOPY );
827 PatBlt( hdc, rect->left, rect->bottom - 1,
828 rect->right - rect->left, -height, PATCOPY );
829 PatBlt( hdc, rect->right - 1, rect->top,
830 -width, rect->bottom - rect->top, PATCOPY );
832 InflateRect( rect, -width, -height );
835 /* Now the other bit of the frame */
836 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
837 (exStyle & WS_EX_DLGMODALFRAME))
839 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
840 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
841 /* This should give a value of 1 that should also work for a border */
843 SelectObject( hdc, GetSysColorBrush(
844 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
846 (exStyle & WS_EX_STATICEDGE) ?
848 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
854 PatBlt( hdc, rect->left, rect->top,
855 rect->right - rect->left, height, PATCOPY );
856 PatBlt( hdc, rect->left, rect->top,
857 width, rect->bottom - rect->top, PATCOPY );
858 PatBlt( hdc, rect->left, rect->bottom - 1,
859 rect->right - rect->left, -height, PATCOPY );
860 PatBlt( hdc, rect->right - 1, rect->top,
861 -width, rect->bottom - rect->top, PATCOPY );
863 InflateRect( rect, -width, -height );
868 /******************************************************************************
872 * Draw the window caption for windows.
873 * The correct pen for the window frame must be selected in the DC.
875 *****************************************************************************/
877 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
878 DWORD exStyle, BOOL active )
884 BOOL gradient = FALSE;
886 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
887 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
888 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
889 COLOR_WINDOWFRAME : COLOR_3DFACE) );
890 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
891 LineTo( hdc, r.right, r.bottom - 1 );
892 SelectObject( hdc, hPrevPen );
895 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
896 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
898 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
899 if (NC_DrawSysButton (hwnd, hdc, FALSE))
900 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
903 if (style & WS_SYSMENU)
907 /* Go get the sysmenu */
908 hSysMenu = GetSystemMenu(hwnd, FALSE);
909 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
911 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
912 NC_DrawCloseButton (hwnd, hdc, FALSE,
913 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
914 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
916 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
918 /* In win95 the two buttons are always there */
919 /* But if the menu item is not in the menu they're disabled*/
921 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
922 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
924 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
925 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
929 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
931 NONCLIENTMETRICSW nclm;
932 HFONT hFont, hOldFont;
933 nclm.cbSize = sizeof(nclm);
934 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
935 if (exStyle & WS_EX_TOOLWINDOW)
936 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
938 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
939 hOldFont = SelectObject (hdc, hFont);
940 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
941 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
942 SetBkMode( hdc, TRANSPARENT );
944 DrawTextW( hdc, buffer, -1, &r,
945 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
946 DeleteObject (SelectObject (hdc, hOldFont));
951 /******************************************************************************
954 * Paint the non-client area for windows.
956 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
959 RECT rfuzz, rect, rectClip;
962 DWORD dwStyle, dwExStyle;
967 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
968 dwStyle = wndPtr->dwStyle;
969 dwExStyle = wndPtr->dwExStyle;
970 flags = wndPtr->flags;
971 WIN_ReleasePtr( wndPtr );
973 if ( dwStyle & WS_MINIMIZE ||
974 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
976 active = flags & WIN_NCACTIVATED;
978 TRACE("%p %d\n", hwnd, active );
980 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
981 the call to GetDCEx implying that it is allowed not to use it either.
982 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
983 will cause clipRgn to be deleted after ReleaseDC().
984 Now, how is the "system" supposed to tell what happened?
987 WIN_GetRectangles( hwnd, COORDS_SCREEN, NULL, &rectClient );
988 hrgn = CreateRectRgnIndirect( &rectClient );
992 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
993 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
997 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1002 WIN_GetRectangles( hwnd, COORDS_WINDOW, &rect, NULL );
1003 GetClipBox( hdc, &rectClip );
1005 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1007 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1008 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1010 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1011 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1014 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1016 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1019 if (dwExStyle & WS_EX_TOOLWINDOW) {
1020 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1021 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1024 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1025 rect.top += GetSystemMetrics(SM_CYCAPTION);
1027 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1028 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1031 if (HAS_MENU( hwnd, dwStyle ))
1034 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1036 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1038 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1041 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1043 if (dwExStyle & WS_EX_CLIENTEDGE)
1044 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1046 /* Draw the scroll-bars */
1048 if (dwStyle & WS_VSCROLL)
1049 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1050 if (dwStyle & WS_HSCROLL)
1051 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1053 /* Draw the "size-box" */
1054 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1057 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1058 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1060 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1061 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1062 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1065 ReleaseDC( hwnd, hdc );
1071 /***********************************************************************
1074 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1076 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1078 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1080 if( dwStyle & WS_VISIBLE )
1082 if( dwStyle & WS_MINIMIZE )
1083 WINPOS_RedrawIconTitle( hwnd );
1085 NC_DoNCPaint( hwnd, clip, FALSE );
1091 /***********************************************************************
1092 * NC_HandleNCActivate
1094 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1096 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1098 WND* wndPtr = WIN_GetPtr( hwnd );
1100 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1102 /* Lotus Notes draws menu descriptions in the caption of its main
1103 * window. When it wants to restore original "system" view, it just
1104 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1105 * attempt to minimize redrawings lead to a not restored caption.
1107 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1108 else wndPtr->flags &= ~WIN_NCACTIVATED;
1109 WIN_ReleasePtr( wndPtr );
1111 /* This isn't documented but is reproducible in at least XP SP2 and
1112 * Outlook 2007 depends on it
1117 WINPOS_RedrawIconTitle( hwnd );
1119 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1126 /***********************************************************************
1127 * NC_HandleSetCursor
1129 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1131 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1133 hwnd = WIN_GetFullHandle( (HWND)wParam );
1135 switch((short)LOWORD(lParam))
1139 WORD msg = HIWORD( lParam );
1140 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1141 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1148 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1158 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1162 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1166 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1170 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1173 /* Default cursor: arrow */
1174 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1177 /***********************************************************************
1180 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1182 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1185 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
1186 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
1188 NC_GetInsideRect( hwnd, COORDS_SCREEN, rect, style, ex_style );
1189 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1190 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1194 /***********************************************************************
1197 * Track a mouse button press on the minimize or maximize box.
1199 * The big difference between 3.1 and 95 is the disabled button state.
1200 * In win95 the system button can be disabled, so it can ignore the mouse
1204 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1207 HDC hdc = GetWindowDC( hwnd );
1208 BOOL pressed = TRUE;
1210 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1211 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1213 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1215 if (wParam == HTMINBUTTON)
1217 /* If the style is not present, do nothing */
1218 if (!(wndStyle & WS_MINIMIZEBOX))
1221 /* Check if the sysmenu item for minimize is there */
1222 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1224 paintButton = NC_DrawMinButton;
1228 /* If the style is not present, do nothing */
1229 if (!(wndStyle & WS_MAXIMIZEBOX))
1232 /* Check if the sysmenu item for maximize is there */
1233 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1235 paintButton = NC_DrawMaxButton;
1240 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1244 BOOL oldstate = pressed;
1246 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1247 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1249 if(msg.message == WM_LBUTTONUP)
1252 if(msg.message != WM_MOUSEMOVE)
1255 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1256 if (pressed != oldstate)
1257 (*paintButton)( hwnd, hdc, pressed, FALSE);
1261 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1264 ReleaseDC( hwnd, hdc );
1266 /* If the item minimize or maximize of the sysmenu are not there */
1267 /* or if the style is not present, do nothing */
1268 if ((!pressed) || (state == 0xFFFFFFFF))
1271 if (wParam == HTMINBUTTON)
1272 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1274 SendMessageW( hwnd, WM_SYSCOMMAND,
1275 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1278 /***********************************************************************
1279 * NC_TrackCloseButton
1281 * Track a mouse button press on the Win95 close button.
1283 static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1287 BOOL pressed = TRUE;
1288 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1294 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1296 /* If the item close of the sysmenu is disabled or not there do nothing */
1297 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1300 hdc = GetWindowDC( hwnd );
1304 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1308 BOOL oldstate = pressed;
1310 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1311 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1313 if(msg.message == WM_LBUTTONUP)
1316 if(msg.message != WM_MOUSEMOVE)
1319 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1320 if (pressed != oldstate)
1321 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1325 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1328 ReleaseDC( hwnd, hdc );
1329 if (!pressed) return;
1331 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1335 /***********************************************************************
1338 * Track a mouse button press on the horizontal or vertical scroll-bar.
1340 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1344 if ((wParam & 0xfff0) == SC_HSCROLL)
1346 if ((wParam & 0x0f) != HTHSCROLL) return;
1347 scrollbar = SB_HORZ;
1349 else /* SC_VSCROLL */
1351 if ((wParam & 0x0f) != HTVSCROLL) return;
1352 scrollbar = SB_VERT;
1354 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1358 /***********************************************************************
1359 * NC_HandleNCLButtonDown
1361 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1363 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1365 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1367 switch(wParam) /* Hit test */
1371 HWND top = GetAncestor( hwnd, GA_ROOT );
1373 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1374 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1379 if( style & WS_SYSMENU )
1381 if( !(style & WS_MINIMIZE) )
1383 HDC hDC = GetWindowDC(hwnd);
1384 NC_DrawSysButton( hwnd, hDC, TRUE );
1385 ReleaseDC( hwnd, hDC );
1387 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1392 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1396 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1400 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1405 NC_TrackMinMaxBox( hwnd, wParam );
1409 NC_TrackCloseButton (hwnd, wParam, lParam);
1421 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1422 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1424 /* But that is not what WinNT does. Instead it sends this. This
1425 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1426 * SC_MOUSEMENU into wParam.
1428 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1438 /***********************************************************************
1439 * NC_HandleNCLButtonDblClk
1441 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1443 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1446 * if this is an icon, send a restore since we are handling
1451 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1455 switch(wParam) /* Hit test */
1458 /* stop processing if WS_MAXIMIZEBOX is missing */
1459 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1460 SendMessageW( hwnd, WM_SYSCOMMAND,
1461 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1466 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1467 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1469 /* If the item close of the sysmenu is disabled or not there do nothing */
1470 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1473 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1478 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1482 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1489 /***********************************************************************
1490 * NC_HandleSysCommand
1492 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1494 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1496 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1498 if (!IsWindowEnabled( hwnd )) return 0;
1500 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1503 if (!USER_Driver->pSysCommand( hwnd, wParam, lParam ))
1506 switch (wParam & 0xfff0)
1510 WINPOS_SysCommandSizeMove( hwnd, wParam );
1514 if (hwnd == GetActiveWindow())
1515 ShowOwnedPopups(hwnd,FALSE);
1516 ShowWindow( hwnd, SW_MINIMIZE );
1520 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1521 ShowOwnedPopups(hwnd,TRUE);
1522 ShowWindow( hwnd, SW_MAXIMIZE );
1526 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1527 ShowOwnedPopups(hwnd,TRUE);
1528 ShowWindow( hwnd, SW_RESTORE );
1532 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1538 pt.x = (short)LOWORD(lParam);
1539 pt.y = (short)HIWORD(lParam);
1540 NC_TrackScrollBar( hwnd, wParam, pt );
1547 pt.x = (short)LOWORD(lParam);
1548 pt.y = (short)HIWORD(lParam);
1549 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1554 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1558 WinExec( "taskman.exe", SW_SHOWNORMAL );
1562 if (wParam == SC_ABOUTWINE)
1564 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1567 BOOL (WINAPI *aboutproc)(HWND, LPCSTR, LPCSTR, HICON);
1569 aboutproc = (void *)GetProcAddress( hmodule, "ShellAboutA" );
1570 if (aboutproc) aboutproc( hwnd, PACKAGE_STRING, NULL, 0 );
1571 FreeLibrary( hmodule );
1580 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1586 /***********************************************************************
1587 * GetTitleBarInfo (USER32.@)
1588 * TODO: Handle STATE_SYSTEM_PRESSED
1590 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1594 TRACE("(%p %p)\n", hwnd, tbi);
1597 SetLastError(ERROR_NOACCESS);
1601 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1602 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1603 SetLastError(ERROR_INVALID_PARAMETER);
1606 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1607 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1608 NC_GetInsideRect(hwnd, COORDS_SCREEN, &tbi->rcTitleBar, dwStyle, dwExStyle);
1610 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1611 if(dwExStyle & WS_EX_TOOLWINDOW)
1612 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1614 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1615 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1618 ZeroMemory(tbi->rgstate, sizeof(tbi->rgstate));
1619 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1620 * Under XP it seems to
1622 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1623 if(dwStyle & WS_CAPTION) {
1624 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1625 if(dwStyle & WS_SYSMENU) {
1626 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1627 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1628 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1631 if(!(dwStyle & WS_MINIMIZEBOX))
1632 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1633 if(!(dwStyle & WS_MAXIMIZEBOX))
1634 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1636 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1637 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1638 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1639 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1642 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1643 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1644 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1645 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1649 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;