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, WPARAM wparam, 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))
456 /* rectangle is in screen coords when wparam is false */
457 if (!wparam && (exStyle & WS_EX_LAYOUTRTL)) exStyle ^= WS_EX_LEFTSCROLLBAR;
459 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
460 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
462 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
465 if (style & WS_HSCROLL)
466 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
467 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
469 if (winRect->top > winRect->bottom)
470 winRect->bottom = winRect->top;
472 if (winRect->left > winRect->right)
473 winRect->right = winRect->left;
479 /***********************************************************************
482 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
483 * but without the borders (if any).
485 static void NC_GetInsideRect( HWND hwnd, enum coords_relative relative, RECT *rect,
486 DWORD style, DWORD ex_style )
488 WIN_GetRectangles( hwnd, relative, rect, NULL );
490 if (style & WS_ICONIC) return;
492 /* Remove frame from rectangle */
493 if (HAS_THICKFRAME( style, ex_style ))
495 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
497 else if (HAS_DLGFRAME( style, ex_style ))
499 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
501 else if (HAS_THINFRAME( style ))
503 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
506 /* We have additional border information if the window
507 * is a child (but not an MDI child) */
508 if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD))
510 if (ex_style & WS_EX_CLIENTEDGE)
511 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
512 if (ex_style & WS_EX_STATICEDGE)
513 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
518 /***********************************************************************
521 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
523 LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt )
526 DWORD style, ex_style;
528 TRACE("hwnd=%p pt=%d,%d\n", hwnd, pt.x, pt.y );
530 WIN_GetRectangles( hwnd, COORDS_SCREEN, &rect, &rcClient );
531 if (!PtInRect( &rect, pt )) return HTNOWHERE;
533 style = GetWindowLongW( hwnd, GWL_STYLE );
534 ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
535 if (style & WS_MINIMIZE) return HTCAPTION;
537 if (PtInRect( &rcClient, pt )) return HTCLIENT;
540 if (HAS_THICKFRAME( style, ex_style ))
542 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
543 if (!PtInRect( &rect, pt ))
545 /* Check top sizing border */
548 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
549 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
552 /* Check bottom sizing border */
553 if (pt.y >= rect.bottom)
555 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
556 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
559 /* Check left sizing border */
560 if (pt.x < rect.left)
562 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
563 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
566 /* Check right sizing border */
567 if (pt.x >= rect.right)
569 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
570 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
575 else /* No thick frame */
577 if (HAS_DLGFRAME( style, ex_style ))
578 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
579 else if (HAS_THINFRAME( style ))
580 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
581 if (!PtInRect( &rect, pt )) return HTBORDER;
586 if ((style & WS_CAPTION) == WS_CAPTION)
588 if (ex_style & WS_EX_TOOLWINDOW)
589 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
591 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
592 if (!PtInRect( &rect, pt ))
594 BOOL min_or_max_box = (style & WS_MAXIMIZEBOX) ||
595 (style & WS_MINIMIZEBOX);
596 if (ex_style & WS_EX_LAYOUTRTL)
598 /* Check system menu */
599 if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW) && NC_IconForWindow(hwnd))
601 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
602 if (pt.x > rect.right) return HTSYSMENU;
605 /* Check close button */
606 if (style & WS_SYSMENU)
608 rect.left += GetSystemMetrics(SM_CYCAPTION);
609 if (pt.x < rect.left) return HTCLOSE;
612 /* Check maximize box */
613 /* In win95 there is automatically a Maximize button when there is a minimize one*/
614 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
616 rect.left += GetSystemMetrics(SM_CXSIZE);
617 if (pt.x < rect.left) return HTMAXBUTTON;
620 /* Check minimize box */
621 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
623 rect.left += GetSystemMetrics(SM_CXSIZE);
624 if (pt.x < rect.left) return HTMINBUTTON;
629 /* Check system menu */
630 if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW) && NC_IconForWindow(hwnd))
632 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
633 if (pt.x < rect.left) return HTSYSMENU;
636 /* Check close button */
637 if (style & WS_SYSMENU)
639 rect.right -= GetSystemMetrics(SM_CYCAPTION);
640 if (pt.x > rect.right) return HTCLOSE;
643 /* Check maximize box */
644 /* In win95 there is automatically a Maximize button when there is a minimize one*/
645 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
647 rect.right -= GetSystemMetrics(SM_CXSIZE);
648 if (pt.x > rect.right) return HTMAXBUTTON;
651 /* Check minimize box */
652 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
654 rect.right -= GetSystemMetrics(SM_CXSIZE);
655 if (pt.x > rect.right) return HTMINBUTTON;
664 if (HAS_MENU( hwnd, style ) && (pt.y < rcClient.top) &&
665 (pt.x >= rcClient.left) && (pt.x < rcClient.right))
668 /* Check vertical scroll bar */
670 if (ex_style & WS_EX_LAYOUTRTL) ex_style ^= WS_EX_LEFTSCROLLBAR;
671 if (style & WS_VSCROLL)
673 if((ex_style & WS_EX_LEFTSCROLLBAR) != 0)
674 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
676 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
677 if (PtInRect( &rcClient, pt )) return HTVSCROLL;
680 /* Check horizontal scroll bar */
682 if (style & WS_HSCROLL)
684 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
685 if (PtInRect( &rcClient, pt ))
688 if ((style & WS_VSCROLL) &&
689 ((((ex_style & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
690 (((ex_style & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
696 /* Has to return HTNOWHERE if nothing was found
697 Could happen when a window has a customized non client area */
702 /******************************************************************************
706 * Draws the system icon.
708 *****************************************************************************/
709 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
711 HICON hIcon = NC_IconForWindow( hwnd );
716 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
717 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
719 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
720 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
721 GetSystemMetrics(SM_CXSMICON),
722 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
728 /******************************************************************************
732 * Draws the close button.
734 * If bGrayed is true, then draw a disabled Close button
736 *****************************************************************************/
738 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
741 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
742 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
744 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
746 /* A tool window has a smaller Close button */
747 if (ex_style & WS_EX_TOOLWINDOW)
749 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
750 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
751 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
753 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
754 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
755 rect.bottom = rect.top + iBmpHeight;
756 rect.right = rect.left + iBmpWidth;
760 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
761 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
765 DrawFrameControl( hdc, &rect, DFC_CAPTION,
767 (down ? DFCS_PUSHED : 0) |
768 (bGrayed ? DFCS_INACTIVE : 0)) );
771 /******************************************************************************
774 * Draws the maximize button for windows.
775 * If bGrayed is true, then draw a disabled Maximize button
777 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
781 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
782 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
784 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
785 if (ex_style & WS_EX_TOOLWINDOW) return;
787 flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
789 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
790 if (style & WS_SYSMENU)
791 rect.right -= GetSystemMetrics(SM_CXSIZE);
792 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
793 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
796 if (down) flags |= DFCS_PUSHED;
797 if (bGrayed) flags |= DFCS_INACTIVE;
798 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
801 /******************************************************************************
804 * Draws the minimize button for windows.
805 * If bGrayed is true, then draw a disabled Minimize button
807 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
810 UINT flags = DFCS_CAPTIONMIN;
811 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
812 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
814 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
815 if (ex_style & WS_EX_TOOLWINDOW) return;
817 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
818 if (style & WS_SYSMENU)
819 rect.right -= GetSystemMetrics(SM_CXSIZE);
820 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
821 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
822 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
823 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
826 if (down) flags |= DFCS_PUSHED;
827 if (bGrayed) flags |= DFCS_INACTIVE;
828 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
831 /******************************************************************************
835 * Draw a window frame inside the given rectangle, and update the rectangle.
838 * Many. First, just what IS a frame in Win95? Note that the 3D look
839 * on the outer edge is handled by NC_DoNCPaint. As is the inner
840 * edge. The inner rectangle just inside the frame is handled by the
843 * In short, for most people, this function should be a nop (unless
844 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
845 * them lately, but just to get this code right). Even so, it doesn't
846 * appear to be so. It's being worked on...
848 *****************************************************************************/
850 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
854 /* Firstly the "thick" frame */
855 if (style & WS_THICKFRAME)
857 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
858 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
860 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
861 COLOR_INACTIVEBORDER) );
863 PatBlt( hdc, rect->left, rect->top,
864 rect->right - rect->left, height, PATCOPY );
865 PatBlt( hdc, rect->left, rect->top,
866 width, rect->bottom - rect->top, PATCOPY );
867 PatBlt( hdc, rect->left, rect->bottom - 1,
868 rect->right - rect->left, -height, PATCOPY );
869 PatBlt( hdc, rect->right - 1, rect->top,
870 -width, rect->bottom - rect->top, PATCOPY );
872 InflateRect( rect, -width, -height );
875 /* Now the other bit of the frame */
876 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
877 (exStyle & WS_EX_DLGMODALFRAME))
879 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
880 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
881 /* This should give a value of 1 that should also work for a border */
883 SelectObject( hdc, GetSysColorBrush(
884 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
886 (exStyle & WS_EX_STATICEDGE) ?
888 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
894 PatBlt( hdc, rect->left, rect->top,
895 rect->right - rect->left, height, PATCOPY );
896 PatBlt( hdc, rect->left, rect->top,
897 width, rect->bottom - rect->top, PATCOPY );
898 PatBlt( hdc, rect->left, rect->bottom - 1,
899 rect->right - rect->left, -height, PATCOPY );
900 PatBlt( hdc, rect->right - 1, rect->top,
901 -width, rect->bottom - rect->top, PATCOPY );
903 InflateRect( rect, -width, -height );
908 /******************************************************************************
912 * Draw the window caption for windows.
913 * The correct pen for the window frame must be selected in the DC.
915 *****************************************************************************/
917 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
918 DWORD exStyle, BOOL active )
924 BOOL gradient = FALSE;
926 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
927 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
928 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
929 COLOR_WINDOWFRAME : COLOR_3DFACE) );
930 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
931 LineTo( hdc, r.right, r.bottom - 1 );
932 SelectObject( hdc, hPrevPen );
935 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
936 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
938 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
939 if (NC_DrawSysButton (hwnd, hdc, FALSE))
940 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
943 if (style & WS_SYSMENU)
947 /* Go get the sysmenu */
948 hSysMenu = GetSystemMenu(hwnd, FALSE);
949 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
951 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
952 NC_DrawCloseButton (hwnd, hdc, FALSE,
953 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
954 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
956 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
958 /* In win95 the two buttons are always there */
959 /* But if the menu item is not in the menu they're disabled*/
961 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
962 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
964 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
965 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
969 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
971 NONCLIENTMETRICSW nclm;
972 HFONT hFont, hOldFont;
973 nclm.cbSize = sizeof(nclm);
974 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
975 if (exStyle & WS_EX_TOOLWINDOW)
976 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
978 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
979 hOldFont = SelectObject (hdc, hFont);
980 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
981 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
982 SetBkMode( hdc, TRANSPARENT );
984 DrawTextW( hdc, buffer, -1, &r,
985 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
986 DeleteObject (SelectObject (hdc, hOldFont));
991 /******************************************************************************
994 * Paint the non-client area for windows.
996 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
999 RECT rfuzz, rect, rectClip;
1002 DWORD dwStyle, dwExStyle;
1007 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1008 dwStyle = wndPtr->dwStyle;
1009 dwExStyle = wndPtr->dwExStyle;
1010 flags = wndPtr->flags;
1011 WIN_ReleasePtr( wndPtr );
1013 if ( dwStyle & WS_MINIMIZE ||
1014 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1016 active = flags & WIN_NCACTIVATED;
1018 TRACE("%p %d\n", hwnd, active );
1020 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1021 the call to GetDCEx implying that it is allowed not to use it either.
1022 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1023 will cause clipRgn to be deleted after ReleaseDC().
1024 Now, how is the "system" supposed to tell what happened?
1027 WIN_GetRectangles( hwnd, COORDS_SCREEN, NULL, &rectClient );
1028 hrgn = CreateRectRgnIndirect( &rectClient );
1032 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1033 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1037 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1042 WIN_GetRectangles( hwnd, COORDS_WINDOW, &rect, NULL );
1043 GetClipBox( hdc, &rectClip );
1045 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1047 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1048 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1050 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1051 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1054 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1056 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1059 if (dwExStyle & WS_EX_TOOLWINDOW) {
1060 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1061 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1064 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1065 rect.top += GetSystemMetrics(SM_CYCAPTION);
1067 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1068 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1071 if (HAS_MENU( hwnd, dwStyle ))
1074 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1076 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1078 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1081 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1083 if (dwExStyle & WS_EX_CLIENTEDGE)
1084 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1086 /* Draw the scroll-bars */
1088 if (dwStyle & WS_VSCROLL)
1089 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1090 if (dwStyle & WS_HSCROLL)
1091 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1093 /* Draw the "size-box" */
1094 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1097 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1098 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1100 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1101 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1102 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1105 ReleaseDC( hwnd, hdc );
1111 /***********************************************************************
1114 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1116 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1118 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1120 if( dwStyle & WS_VISIBLE )
1122 if( dwStyle & WS_MINIMIZE )
1123 WINPOS_RedrawIconTitle( hwnd );
1125 NC_DoNCPaint( hwnd, clip, FALSE );
1131 /***********************************************************************
1132 * NC_HandleNCActivate
1134 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1136 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1138 WND* wndPtr = WIN_GetPtr( hwnd );
1140 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1142 /* Lotus Notes draws menu descriptions in the caption of its main
1143 * window. When it wants to restore original "system" view, it just
1144 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1145 * attempt to minimize redrawings lead to a not restored caption.
1147 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1148 else wndPtr->flags &= ~WIN_NCACTIVATED;
1149 WIN_ReleasePtr( wndPtr );
1151 /* This isn't documented but is reproducible in at least XP SP2 and
1152 * Outlook 2007 depends on it
1157 WINPOS_RedrawIconTitle( hwnd );
1159 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1166 /***********************************************************************
1167 * NC_HandleSetCursor
1169 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1171 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1173 hwnd = WIN_GetFullHandle( (HWND)wParam );
1175 switch((short)LOWORD(lParam))
1179 WORD msg = HIWORD( lParam );
1180 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1181 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1188 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1198 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1202 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1206 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1210 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1213 /* Default cursor: arrow */
1214 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1217 /***********************************************************************
1220 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1222 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1225 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
1226 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
1228 NC_GetInsideRect( hwnd, COORDS_CLIENT, rect, style, ex_style );
1229 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1230 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1231 MapWindowPoints( hwnd, 0, (POINT *)rect, 2 );
1235 /***********************************************************************
1238 * Track a mouse button press on the minimize or maximize box.
1240 * The big difference between 3.1 and 95 is the disabled button state.
1241 * In win95 the system button can be disabled, so it can ignore the mouse
1245 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1248 HDC hdc = GetWindowDC( hwnd );
1249 BOOL pressed = TRUE;
1251 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1252 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1254 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1256 if (wParam == HTMINBUTTON)
1258 /* If the style is not present, do nothing */
1259 if (!(wndStyle & WS_MINIMIZEBOX))
1262 /* Check if the sysmenu item for minimize is there */
1263 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1265 paintButton = NC_DrawMinButton;
1269 /* If the style is not present, do nothing */
1270 if (!(wndStyle & WS_MAXIMIZEBOX))
1273 /* Check if the sysmenu item for maximize is there */
1274 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1276 paintButton = NC_DrawMaxButton;
1281 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1285 BOOL oldstate = pressed;
1287 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1288 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1290 if(msg.message == WM_LBUTTONUP)
1293 if(msg.message != WM_MOUSEMOVE)
1296 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1297 if (pressed != oldstate)
1298 (*paintButton)( hwnd, hdc, pressed, FALSE);
1302 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1305 ReleaseDC( hwnd, hdc );
1307 /* If the item minimize or maximize of the sysmenu are not there */
1308 /* or if the style is not present, do nothing */
1309 if ((!pressed) || (state == 0xFFFFFFFF))
1312 if (wParam == HTMINBUTTON)
1313 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1315 SendMessageW( hwnd, WM_SYSCOMMAND,
1316 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1319 /***********************************************************************
1320 * NC_TrackCloseButton
1322 * Track a mouse button press on the Win95 close button.
1324 static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1328 BOOL pressed = TRUE;
1329 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1335 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1337 /* If the item close of the sysmenu is disabled or not there do nothing */
1338 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1341 hdc = GetWindowDC( hwnd );
1345 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1349 BOOL oldstate = pressed;
1351 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1352 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1354 if(msg.message == WM_LBUTTONUP)
1357 if(msg.message != WM_MOUSEMOVE)
1360 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1361 if (pressed != oldstate)
1362 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1366 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1369 ReleaseDC( hwnd, hdc );
1370 if (!pressed) return;
1372 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1376 /***********************************************************************
1379 * Track a mouse button press on the horizontal or vertical scroll-bar.
1381 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1385 if ((wParam & 0xfff0) == SC_HSCROLL)
1387 if ((wParam & 0x0f) != HTHSCROLL) return;
1388 scrollbar = SB_HORZ;
1390 else /* SC_VSCROLL */
1392 if ((wParam & 0x0f) != HTVSCROLL) return;
1393 scrollbar = SB_VERT;
1395 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1399 /***********************************************************************
1400 * NC_HandleNCLButtonDown
1402 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1404 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1406 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1408 switch(wParam) /* Hit test */
1412 HWND top = GetAncestor( hwnd, GA_ROOT );
1414 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1415 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1420 if( style & WS_SYSMENU )
1422 if( !(style & WS_MINIMIZE) )
1424 HDC hDC = GetWindowDC(hwnd);
1425 NC_DrawSysButton( hwnd, hDC, TRUE );
1426 ReleaseDC( hwnd, hDC );
1428 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1433 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1441 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1446 NC_TrackMinMaxBox( hwnd, wParam );
1450 NC_TrackCloseButton (hwnd, wParam, lParam);
1462 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1463 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1465 /* But that is not what WinNT does. Instead it sends this. This
1466 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1467 * SC_MOUSEMENU into wParam.
1469 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1479 /***********************************************************************
1480 * NC_HandleNCLButtonDblClk
1482 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1484 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1487 * if this is an icon, send a restore since we are handling
1492 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1496 switch(wParam) /* Hit test */
1499 /* stop processing if WS_MAXIMIZEBOX is missing */
1500 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1501 SendMessageW( hwnd, WM_SYSCOMMAND,
1502 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1507 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1508 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1510 /* If the item close of the sysmenu is disabled or not there do nothing */
1511 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1514 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1519 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1523 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1530 /***********************************************************************
1531 * NC_HandleSysCommand
1533 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1535 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1537 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1539 if (!IsWindowEnabled( hwnd )) return 0;
1541 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1544 if (!USER_Driver->pSysCommand( hwnd, wParam, lParam ))
1547 switch (wParam & 0xfff0)
1551 WINPOS_SysCommandSizeMove( hwnd, wParam );
1555 if (hwnd == GetActiveWindow())
1556 ShowOwnedPopups(hwnd,FALSE);
1557 ShowWindow( hwnd, SW_MINIMIZE );
1561 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1562 ShowOwnedPopups(hwnd,TRUE);
1563 ShowWindow( hwnd, SW_MAXIMIZE );
1567 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1568 ShowOwnedPopups(hwnd,TRUE);
1569 ShowWindow( hwnd, SW_RESTORE );
1573 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1579 pt.x = (short)LOWORD(lParam);
1580 pt.y = (short)HIWORD(lParam);
1581 NC_TrackScrollBar( hwnd, wParam, pt );
1588 pt.x = (short)LOWORD(lParam);
1589 pt.y = (short)HIWORD(lParam);
1590 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1595 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1599 WinExec( "taskman.exe", SW_SHOWNORMAL );
1603 if (wParam == SC_ABOUTWINE)
1605 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1608 BOOL (WINAPI *aboutproc)(HWND, LPCSTR, LPCSTR, HICON);
1610 aboutproc = (void *)GetProcAddress( hmodule, "ShellAboutA" );
1611 if (aboutproc) aboutproc( hwnd, PACKAGE_STRING, NULL, 0 );
1612 FreeLibrary( hmodule );
1621 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1627 /***********************************************************************
1628 * GetTitleBarInfo (USER32.@)
1629 * TODO: Handle STATE_SYSTEM_PRESSED
1631 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1635 TRACE("(%p %p)\n", hwnd, tbi);
1638 SetLastError(ERROR_NOACCESS);
1642 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1643 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1644 SetLastError(ERROR_INVALID_PARAMETER);
1647 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1648 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1649 NC_GetInsideRect(hwnd, COORDS_SCREEN, &tbi->rcTitleBar, dwStyle, dwExStyle);
1651 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1652 if(dwExStyle & WS_EX_TOOLWINDOW)
1653 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1655 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1656 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1659 ZeroMemory(tbi->rgstate, sizeof(tbi->rgstate));
1660 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1661 * Under XP it seems to
1663 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1664 if(dwStyle & WS_CAPTION) {
1665 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1666 if(dwStyle & WS_SYSMENU) {
1667 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1668 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1669 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1672 if(!(dwStyle & WS_MINIMIZEBOX))
1673 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1674 if(!(dwStyle & WS_MAXIMIZEBOX))
1675 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1677 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1678 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1679 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1680 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1683 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1684 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1685 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1686 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1690 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;