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).
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 NC_HandleNCHitTest().
519 * FIXME: Just a modified copy of the Win 3.1 version.
522 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
527 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->obj.handle, pt.x, pt.y );
529 GetWindowRect(wndPtr->obj.handle, &rect );
530 if (!PtInRect( &rect, pt )) return HTNOWHERE;
532 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
534 /* Check client area */
536 ScreenToClient( wndPtr->obj.handle, &ptClient );
537 GetClientRect( wndPtr->obj.handle, &rcClient );
538 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
541 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
543 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
544 if (!PtInRect( &rect, pt ))
546 /* Check top sizing border */
549 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
550 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
553 /* Check bottom sizing border */
554 if (pt.y >= rect.bottom)
556 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
557 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
560 /* Check left sizing border */
561 if (pt.x < rect.left)
563 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
564 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
567 /* Check right sizing border */
568 if (pt.x >= rect.right)
570 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
571 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
576 else /* No thick frame */
578 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
579 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
580 else if (HAS_THINFRAME( wndPtr->dwStyle ))
581 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
582 if (!PtInRect( &rect, pt )) return HTBORDER;
587 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
589 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
590 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
592 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
593 if (!PtInRect( &rect, pt ))
595 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
596 (wndPtr->dwStyle & WS_MINIMIZEBOX);
597 /* Check system menu */
598 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
600 if (NC_IconForWindow(wndPtr->obj.handle))
601 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
603 if (pt.x < rect.left) return HTSYSMENU;
605 /* Check close button */
606 if (wndPtr->dwStyle & WS_SYSMENU)
607 rect.right -= GetSystemMetrics(SM_CYCAPTION);
608 if (pt.x > rect.right) return HTCLOSE;
610 /* Check maximize box */
611 /* In win95 there is automatically a Maximize button when there is a minimize one*/
612 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
613 rect.right -= GetSystemMetrics(SM_CXSIZE);
614 if (pt.x > rect.right) return HTMAXBUTTON;
616 /* Check minimize box */
617 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
618 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
619 rect.right -= GetSystemMetrics(SM_CXSIZE);
621 if (pt.x > rect.right) return HTMINBUTTON;
626 /* Check vertical scroll bar */
628 if (wndPtr->dwStyle & WS_VSCROLL)
630 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
631 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
633 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
634 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
637 /* Check horizontal scroll bar */
639 if (wndPtr->dwStyle & WS_HSCROLL)
641 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
642 if (PtInRect( &rcClient, ptClient ))
645 if ((wndPtr->dwStyle & WS_VSCROLL) &&
646 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
647 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
655 if (HAS_MENU(wndPtr))
657 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
661 /* Has to return HTNOWHERE if nothing was found
662 Could happen when a window has a customized non client area */
667 /***********************************************************************
670 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
672 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
675 WND *wndPtr = WIN_GetPtr( hwnd );
677 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
679 retvalue = NC_DoNCHitTest (wndPtr, pt);
680 WIN_ReleasePtr( wndPtr );
685 /******************************************************************************
689 * Draws the system icon.
691 *****************************************************************************/
692 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
694 HICON hIcon = NC_IconForWindow( hwnd );
699 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
700 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
702 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
703 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
704 GetSystemMetrics(SM_CXSMICON),
705 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
711 /******************************************************************************
715 * Draws the close button.
717 * If bGrayed is true, then draw a disabled Close button
719 *****************************************************************************/
721 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
724 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
725 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
727 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
729 /* A tool window has a smaller Close button */
730 if (ex_style & WS_EX_TOOLWINDOW)
732 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
733 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
734 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
736 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
737 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
738 rect.bottom = rect.top + iBmpHeight;
739 rect.right = rect.left + iBmpWidth;
743 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
744 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
748 DrawFrameControl( hdc, &rect, DFC_CAPTION,
750 (down ? DFCS_PUSHED : 0) |
751 (bGrayed ? DFCS_INACTIVE : 0)) );
754 /******************************************************************************
757 * Draws the maximize button for windows.
758 * If bGrayed is true, then draw a disabled Maximize button
760 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
764 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
765 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
767 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
768 if (ex_style & WS_EX_TOOLWINDOW) return;
770 flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
772 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
773 if (style & WS_SYSMENU)
774 rect.right -= GetSystemMetrics(SM_CXSIZE);
775 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
776 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
779 if (down) flags |= DFCS_PUSHED;
780 if (bGrayed) flags |= DFCS_INACTIVE;
781 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
784 /******************************************************************************
787 * Draws the minimize button for windows.
788 * If bGrayed is true, then draw a disabled Minimize button
790 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
793 UINT flags = DFCS_CAPTIONMIN;
794 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
795 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
797 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
798 if (ex_style & WS_EX_TOOLWINDOW) return;
800 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
801 if (style & WS_SYSMENU)
802 rect.right -= GetSystemMetrics(SM_CXSIZE);
803 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
804 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
805 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
806 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
809 if (down) flags |= DFCS_PUSHED;
810 if (bGrayed) flags |= DFCS_INACTIVE;
811 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
814 /******************************************************************************
818 * Draw a window frame inside the given rectangle, and update the rectangle.
821 * Many. First, just what IS a frame in Win95? Note that the 3D look
822 * on the outer edge is handled by NC_DoNCPaint. As is the inner
823 * edge. The inner rectangle just inside the frame is handled by the
826 * In short, for most people, this function should be a nop (unless
827 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
828 * them lately, but just to get this code right). Even so, it doesn't
829 * appear to be so. It's being worked on...
831 *****************************************************************************/
833 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
837 /* Firstly the "thick" frame */
838 if (style & WS_THICKFRAME)
840 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
841 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
843 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
844 COLOR_INACTIVEBORDER) );
846 PatBlt( hdc, rect->left, rect->top,
847 rect->right - rect->left, height, PATCOPY );
848 PatBlt( hdc, rect->left, rect->top,
849 width, rect->bottom - rect->top, PATCOPY );
850 PatBlt( hdc, rect->left, rect->bottom - 1,
851 rect->right - rect->left, -height, PATCOPY );
852 PatBlt( hdc, rect->right - 1, rect->top,
853 -width, rect->bottom - rect->top, PATCOPY );
855 InflateRect( rect, -width, -height );
858 /* Now the other bit of the frame */
859 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
860 (exStyle & WS_EX_DLGMODALFRAME))
862 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
863 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
864 /* This should give a value of 1 that should also work for a border */
866 SelectObject( hdc, GetSysColorBrush(
867 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
869 (exStyle & WS_EX_STATICEDGE) ?
871 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
877 PatBlt( hdc, rect->left, rect->top,
878 rect->right - rect->left, height, PATCOPY );
879 PatBlt( hdc, rect->left, rect->top,
880 width, rect->bottom - rect->top, PATCOPY );
881 PatBlt( hdc, rect->left, rect->bottom - 1,
882 rect->right - rect->left, -height, PATCOPY );
883 PatBlt( hdc, rect->right - 1, rect->top,
884 -width, rect->bottom - rect->top, PATCOPY );
886 InflateRect( rect, -width, -height );
891 /******************************************************************************
895 * Draw the window caption for windows.
896 * The correct pen for the window frame must be selected in the DC.
898 *****************************************************************************/
900 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
901 DWORD exStyle, BOOL active )
907 BOOL gradient = FALSE;
909 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
910 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
911 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
912 COLOR_WINDOWFRAME : COLOR_3DFACE) );
913 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
914 LineTo( hdc, r.right, r.bottom - 1 );
915 SelectObject( hdc, hPrevPen );
918 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
919 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
921 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
922 if (NC_DrawSysButton (hwnd, hdc, FALSE))
923 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
926 if (style & WS_SYSMENU)
930 /* Go get the sysmenu */
931 hSysMenu = GetSystemMenu(hwnd, FALSE);
932 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
934 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
935 NC_DrawCloseButton (hwnd, hdc, FALSE,
936 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
937 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
939 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
941 /* In win95 the two buttons are always there */
942 /* But if the menu item is not in the menu they're disabled*/
944 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
945 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
947 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
948 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
952 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
954 NONCLIENTMETRICSW nclm;
955 HFONT hFont, hOldFont;
956 nclm.cbSize = sizeof(nclm);
957 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
958 if (exStyle & WS_EX_TOOLWINDOW)
959 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
961 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
962 hOldFont = SelectObject (hdc, hFont);
963 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
964 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
965 SetBkMode( hdc, TRANSPARENT );
967 DrawTextW( hdc, buffer, -1, &r,
968 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
969 DeleteObject (SelectObject (hdc, hOldFont));
974 /******************************************************************************
977 * Paint the non-client area for windows.
979 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
982 RECT rfuzz, rect, rectClip;
985 DWORD dwStyle, dwExStyle;
991 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
992 has_menu = HAS_MENU(wndPtr);
993 dwStyle = wndPtr->dwStyle;
994 dwExStyle = wndPtr->dwExStyle;
995 flags = wndPtr->flags;
996 WIN_ReleasePtr( wndPtr );
998 if ( dwStyle & WS_MINIMIZE ||
999 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1001 active = flags & WIN_NCACTIVATED;
1003 TRACE("%p %d\n", hwnd, active );
1005 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1006 the call to GetDCEx implying that it is allowed not to use it either.
1007 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1008 will cause clipRgn to be deleted after ReleaseDC().
1009 Now, how is the "system" supposed to tell what happened?
1012 WIN_GetRectangles( hwnd, COORDS_SCREEN, NULL, &rectClient );
1013 hrgn = CreateRectRgnIndirect( &rectClient );
1017 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1018 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1022 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1027 WIN_GetRectangles( hwnd, COORDS_WINDOW, &rect, NULL );
1028 GetClipBox( hdc, &rectClip );
1030 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1032 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1033 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1035 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1036 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1039 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1041 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1044 if (dwExStyle & WS_EX_TOOLWINDOW) {
1045 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1046 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1049 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1050 rect.top += GetSystemMetrics(SM_CYCAPTION);
1052 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1053 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1059 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1061 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1063 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1066 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1068 if (dwExStyle & WS_EX_CLIENTEDGE)
1069 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1071 /* Draw the scroll-bars */
1073 if (dwStyle & WS_VSCROLL)
1074 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1075 if (dwStyle & WS_HSCROLL)
1076 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1078 /* Draw the "size-box" */
1079 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1082 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1083 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1085 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1086 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1087 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1090 ReleaseDC( hwnd, hdc );
1096 /***********************************************************************
1099 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1101 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1103 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1105 if( dwStyle & WS_VISIBLE )
1107 if( dwStyle & WS_MINIMIZE )
1108 WINPOS_RedrawIconTitle( hwnd );
1110 NC_DoNCPaint( hwnd, clip, FALSE );
1116 /***********************************************************************
1117 * NC_HandleNCActivate
1119 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1121 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1123 WND* wndPtr = WIN_GetPtr( hwnd );
1125 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1127 /* Lotus Notes draws menu descriptions in the caption of its main
1128 * window. When it wants to restore original "system" view, it just
1129 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1130 * attempt to minimize redrawings lead to a not restored caption.
1132 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1133 else wndPtr->flags &= ~WIN_NCACTIVATED;
1134 WIN_ReleasePtr( wndPtr );
1136 /* This isn't documented but is reproducible in at least XP SP2 and
1137 * Outlook 2007 depends on it
1142 WINPOS_RedrawIconTitle( hwnd );
1144 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1151 /***********************************************************************
1152 * NC_HandleSetCursor
1154 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1156 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1158 hwnd = WIN_GetFullHandle( (HWND)wParam );
1160 switch((short)LOWORD(lParam))
1164 WORD msg = HIWORD( lParam );
1165 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1166 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1173 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1183 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1187 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1191 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1195 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1198 /* Default cursor: arrow */
1199 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1202 /***********************************************************************
1205 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1207 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1210 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
1211 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
1213 NC_GetInsideRect( hwnd, COORDS_SCREEN, rect, style, ex_style );
1214 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1215 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1219 /***********************************************************************
1222 * Track a mouse button press on the minimize or maximize box.
1224 * The big difference between 3.1 and 95 is the disabled button state.
1225 * In win95 the system button can be disabled, so it can ignore the mouse
1229 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1232 HDC hdc = GetWindowDC( hwnd );
1233 BOOL pressed = TRUE;
1235 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1236 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1238 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1240 if (wParam == HTMINBUTTON)
1242 /* If the style is not present, do nothing */
1243 if (!(wndStyle & WS_MINIMIZEBOX))
1246 /* Check if the sysmenu item for minimize is there */
1247 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1249 paintButton = NC_DrawMinButton;
1253 /* If the style is not present, do nothing */
1254 if (!(wndStyle & WS_MAXIMIZEBOX))
1257 /* Check if the sysmenu item for maximize is there */
1258 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1260 paintButton = NC_DrawMaxButton;
1265 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1269 BOOL oldstate = pressed;
1271 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1272 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1274 if(msg.message == WM_LBUTTONUP)
1277 if(msg.message != WM_MOUSEMOVE)
1280 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1281 if (pressed != oldstate)
1282 (*paintButton)( hwnd, hdc, pressed, FALSE);
1286 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1289 ReleaseDC( hwnd, hdc );
1291 /* If the item minimize or maximize of the sysmenu are not there */
1292 /* or if the style is not present, do nothing */
1293 if ((!pressed) || (state == 0xFFFFFFFF))
1296 if (wParam == HTMINBUTTON)
1297 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1299 SendMessageW( hwnd, WM_SYSCOMMAND,
1300 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1303 /***********************************************************************
1304 * NC_TrackCloseButton
1306 * Track a mouse button press on the Win95 close button.
1308 static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1312 BOOL pressed = TRUE;
1313 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1319 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1321 /* If the item close of the sysmenu is disabled or not there do nothing */
1322 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1325 hdc = GetWindowDC( hwnd );
1329 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1333 BOOL oldstate = pressed;
1335 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1336 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1338 if(msg.message == WM_LBUTTONUP)
1341 if(msg.message != WM_MOUSEMOVE)
1344 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1345 if (pressed != oldstate)
1346 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1350 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1353 ReleaseDC( hwnd, hdc );
1354 if (!pressed) return;
1356 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1360 /***********************************************************************
1363 * Track a mouse button press on the horizontal or vertical scroll-bar.
1365 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1369 if ((wParam & 0xfff0) == SC_HSCROLL)
1371 if ((wParam & 0x0f) != HTHSCROLL) return;
1372 scrollbar = SB_HORZ;
1374 else /* SC_VSCROLL */
1376 if ((wParam & 0x0f) != HTVSCROLL) return;
1377 scrollbar = SB_VERT;
1379 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1383 /***********************************************************************
1384 * NC_HandleNCLButtonDown
1386 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1388 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1390 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1392 switch(wParam) /* Hit test */
1396 HWND top = GetAncestor( hwnd, GA_ROOT );
1398 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1399 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1404 if( style & WS_SYSMENU )
1406 if( !(style & WS_MINIMIZE) )
1408 HDC hDC = GetWindowDC(hwnd);
1409 NC_DrawSysButton( hwnd, hDC, TRUE );
1410 ReleaseDC( hwnd, hDC );
1412 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1417 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1421 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1425 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1430 NC_TrackMinMaxBox( hwnd, wParam );
1434 NC_TrackCloseButton (hwnd, wParam, lParam);
1446 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1447 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1449 /* But that is not what WinNT does. Instead it sends this. This
1450 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1451 * SC_MOUSEMENU into wParam.
1453 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1463 /***********************************************************************
1464 * NC_HandleNCLButtonDblClk
1466 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1468 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1471 * if this is an icon, send a restore since we are handling
1476 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1480 switch(wParam) /* Hit test */
1483 /* stop processing if WS_MAXIMIZEBOX is missing */
1484 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1485 SendMessageW( hwnd, WM_SYSCOMMAND,
1486 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1491 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1492 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1494 /* If the item close of the sysmenu is disabled or not there do nothing */
1495 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1498 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1503 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1507 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1514 /***********************************************************************
1515 * NC_HandleSysCommand
1517 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1519 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1521 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1523 if (!IsWindowEnabled( hwnd )) return 0;
1525 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1528 if (!USER_Driver->pSysCommand( hwnd, wParam, lParam ))
1531 switch (wParam & 0xfff0)
1535 WINPOS_SysCommandSizeMove( hwnd, wParam );
1539 if (hwnd == GetActiveWindow())
1540 ShowOwnedPopups(hwnd,FALSE);
1541 ShowWindow( hwnd, SW_MINIMIZE );
1545 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1546 ShowOwnedPopups(hwnd,TRUE);
1547 ShowWindow( hwnd, SW_MAXIMIZE );
1551 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1552 ShowOwnedPopups(hwnd,TRUE);
1553 ShowWindow( hwnd, SW_RESTORE );
1557 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1563 pt.x = (short)LOWORD(lParam);
1564 pt.y = (short)HIWORD(lParam);
1565 NC_TrackScrollBar( hwnd, wParam, pt );
1572 pt.x = (short)LOWORD(lParam);
1573 pt.y = (short)HIWORD(lParam);
1574 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1579 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1583 WinExec( "taskman.exe", SW_SHOWNORMAL );
1587 if (wParam == SC_ABOUTWINE)
1589 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1592 BOOL (WINAPI *aboutproc)(HWND, LPCSTR, LPCSTR, HICON);
1594 aboutproc = (void *)GetProcAddress( hmodule, "ShellAboutA" );
1595 if (aboutproc) aboutproc( hwnd, PACKAGE_STRING, NULL, 0 );
1596 FreeLibrary( hmodule );
1605 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1611 /***********************************************************************
1612 * GetTitleBarInfo (USER32.@)
1613 * TODO: Handle STATE_SYSTEM_PRESSED
1615 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1619 TRACE("(%p %p)\n", hwnd, tbi);
1622 SetLastError(ERROR_NOACCESS);
1626 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1627 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1628 SetLastError(ERROR_INVALID_PARAMETER);
1631 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1632 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1633 NC_GetInsideRect(hwnd, COORDS_SCREEN, &tbi->rcTitleBar, dwStyle, dwExStyle);
1635 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1636 if(dwExStyle & WS_EX_TOOLWINDOW)
1637 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1639 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1640 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1643 ZeroMemory(tbi->rgstate, sizeof(tbi->rgstate));
1644 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1645 * Under XP it seems to
1647 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1648 if(dwStyle & WS_CAPTION) {
1649 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1650 if(dwStyle & WS_SYSMENU) {
1651 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1652 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1653 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1656 if(!(dwStyle & WS_MINIMIZEBOX))
1657 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1658 if(!(dwStyle & WS_MAXIMIZEBOX))
1659 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1661 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1662 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1663 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1664 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1667 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1668 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1669 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1670 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1674 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;