2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "user_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
35 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
37 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
48 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
49 #define SC_PUTMARK (SC_SCREENSAVE+2)
51 /* Some useful macros */
52 #define HAS_DLGFRAME(style,exStyle) \
53 (((exStyle) & WS_EX_DLGMODALFRAME) || \
54 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
56 #define HAS_THICKFRAME(style,exStyle) \
57 (((style) & WS_THICKFRAME) && \
58 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
60 #define HAS_THINFRAME(style) \
61 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_BIGFRAME(style,exStyle) \
64 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
65 ((exStyle) & WS_EX_DLGMODALFRAME))
67 #define HAS_STATICOUTERFRAME(style,exStyle) \
68 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
71 #define HAS_ANYFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME) || \
74 !((style) & (WS_CHILD | WS_POPUP)))
76 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
79 /******************************************************************************
82 * Computes the size of the "outside" parts of the window based on the
83 * parameters of the client area.
92 * "Outer" parts of a window means the whole window frame, caption and
93 * menu bar. It does not include "inner" parts of the frame like client
94 * edge, static edge or scroll bars.
96 *****************************************************************************/
99 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
102 if(style & WS_ICONIC) return;
104 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
107 adjust = 1; /* for the outer frame always present */
112 if ((exStyle & WS_EX_DLGMODALFRAME) ||
113 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
115 if (style & WS_THICKFRAME)
116 adjust += ( GetSystemMetrics (SM_CXFRAME)
117 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
118 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
119 (exStyle & WS_EX_DLGMODALFRAME))
120 adjust++; /* The other border */
122 InflateRect (rect, adjust, adjust);
124 if ((style & WS_CAPTION) == WS_CAPTION)
126 if (exStyle & WS_EX_TOOLWINDOW)
127 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
129 rect->top -= GetSystemMetrics(SM_CYCAPTION);
131 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
135 /******************************************************************************
138 * Computes the size of the "inside" part of the window based on the
139 * parameters of the client area.
147 * "Inner" part of a window means the window frame inside of the flat
148 * window frame. It includes the client edge, the static edge and the
151 *****************************************************************************/
154 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
156 if(style & WS_ICONIC) return;
158 if (exStyle & WS_EX_CLIENTEDGE)
159 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
161 if (style & WS_VSCROLL)
163 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
164 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
166 rect->right += GetSystemMetrics(SM_CXVSCROLL);
168 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
173 static HICON NC_IconForWindow( HWND hwnd )
176 WND *wndPtr = WIN_GetPtr( hwnd );
178 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
180 hIcon = wndPtr->hIconSmall;
181 if (!hIcon) hIcon = wndPtr->hIcon;
182 WIN_ReleasePtr( wndPtr );
184 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
185 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
187 /* If there is no hIcon specified and this is a modal dialog,
188 * get the default one.
190 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
191 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
195 /* Draws the bar part(ie the big rectangle) of the caption */
196 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
197 BOOL active, BOOL gradient)
201 TRIVERTEX vertices[6];
203 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
205 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
206 : COLOR_GRADIENTINACTIVECAPTION);
208 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
209 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
211 for (v = 0; v < 3; v++)
213 vertices[v].Red = GetRValue (colLeft) << 8;
214 vertices[v].Green = GetGValue (colLeft) << 8;
215 vertices[v].Blue = GetBValue (colLeft) << 8;
216 vertices[v].Alpha = 0x8000;
217 vertices[v+3].Red = GetRValue (colRight) << 8;
218 vertices[v+3].Green = GetGValue (colRight) << 8;
219 vertices[v+3].Blue = GetBValue (colRight) << 8;
220 vertices[v+3].Alpha = 0x8000;
223 if ((dwStyle & WS_SYSMENU)
224 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
225 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
227 /* area behind icon; solid filled with left color */
228 vertices[0].x = rect->left;
229 vertices[0].y = rect->top;
230 if (dwStyle & WS_SYSMENU)
232 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
234 vertices[1].x = vertices[0].x;
235 vertices[1].y = rect->bottom;
237 /* area behind text; gradient */
238 vertices[2].x = vertices[1].x;
239 vertices[2].y = rect->top;
240 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
241 vertices[3].y = rect->bottom;
243 /* area behind buttons; solid filled with right color */
244 vertices[4].x = vertices[3].x;
245 vertices[4].y = rect->top;
246 vertices[5].x = rect->right;
247 vertices[5].y = rect->bottom;
249 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
252 FillRect (hdc, rect, GetSysColorBrush (active ?
253 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
256 /***********************************************************************
257 * DrawCaption (USER32.@) Draws a caption bar
271 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
273 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
277 /***********************************************************************
278 * DrawCaptionTempA (USER32.@)
280 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
281 HICON hIcon, LPCSTR str, UINT uFlags)
287 if (!(uFlags & DC_TEXT) || !str)
288 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
290 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
291 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
293 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
294 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
295 HeapFree( GetProcessHeap (), 0, strW );
301 /***********************************************************************
302 * DrawCaptionTempW (USER32.@)
304 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
305 HICON hIcon, LPCWSTR str, UINT uFlags)
309 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
310 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
312 /* drawing background */
313 if (uFlags & DC_INBUTTON) {
314 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
316 if (uFlags & DC_ACTIVE) {
317 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
318 PatBlt (hdc, rc.left, rc.top,
319 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
320 SelectObject (hdc, hbr);
324 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
325 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
330 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
334 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
336 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
337 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
338 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
339 rc.left += (rc.bottom - rc.top);
343 if (uFlags & DC_TEXT) {
346 if (uFlags & DC_INBUTTON)
347 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
348 else if (uFlags & DC_ACTIVE)
349 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
351 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
353 SetBkMode (hdc, TRANSPARENT);
356 hOldFont = SelectObject (hdc, hFont);
358 NONCLIENTMETRICSW nclm;
360 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
361 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
362 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
363 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
364 hOldFont = SelectObject (hdc, hNewFont);
368 DrawTextW (hdc, str, -1, &rc,
369 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
373 nLen = GetWindowTextW (hwnd, szText, 128);
374 DrawTextW (hdc, szText, nLen, &rc,
375 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
379 SelectObject (hdc, hOldFont);
381 DeleteObject (SelectObject (hdc, hOldFont));
384 /* drawing focus ??? */
386 FIXME("undocumented flag (0x2000)!\n");
392 /***********************************************************************
393 * AdjustWindowRect (USER32.@)
395 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
397 return AdjustWindowRectEx( rect, style, menu, 0 );
401 /***********************************************************************
402 * AdjustWindowRectEx (USER32.@)
404 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
406 /* Correct the window style */
407 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
408 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
409 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
410 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
412 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
413 rect->left, rect->top, rect->right, rect->bottom,
414 style, menu, exStyle );
416 NC_AdjustRectOuter( rect, style, menu, exStyle );
417 NC_AdjustRectInner( rect, style, exStyle );
423 /***********************************************************************
424 * NC_HandleNCCalcSize
426 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
428 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
430 RECT tmpRect = { 0, 0, 0, 0 };
432 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
433 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
434 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
436 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
437 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
441 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
443 winRect->left -= tmpRect.left;
444 winRect->top -= tmpRect.top;
445 winRect->right -= tmpRect.right;
446 winRect->bottom -= tmpRect.bottom;
448 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
450 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
451 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
454 MENU_GetMenuBarHeight( hwnd,
455 winRect->right - winRect->left,
456 -tmpRect.left, -tmpRect.top );
459 if( exStyle & WS_EX_CLIENTEDGE)
460 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
461 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
462 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
463 - GetSystemMetrics(SM_CYEDGE));
465 if (style & WS_VSCROLL)
466 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
467 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
468 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
470 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
473 if (style & WS_HSCROLL)
474 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
475 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
477 if (winRect->top > winRect->bottom)
478 winRect->bottom = winRect->top;
480 if (winRect->left > winRect->right)
481 winRect->right = winRect->left;
487 /***********************************************************************
490 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
491 * but without the borders (if any).
492 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
494 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
496 WND *wndPtr = WIN_GetPtr( hwnd );
498 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
500 rect->top = rect->left = 0;
501 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
502 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
504 if (wndPtr->dwStyle & WS_ICONIC) goto END;
506 /* Remove frame from rectangle */
507 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
509 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
511 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
515 else if (HAS_THINFRAME( wndPtr->dwStyle ))
517 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
520 /* We have additional border information if the window
521 * is a child (but not an MDI child) */
522 if ( (wndPtr->dwStyle & WS_CHILD) &&
523 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
525 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
526 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
527 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
528 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
532 WIN_ReleasePtr( wndPtr );
536 /***********************************************************************
539 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
541 * FIXME: Just a modified copy of the Win 3.1 version.
544 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
549 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
551 GetWindowRect(wndPtr->hwndSelf, &rect );
552 if (!PtInRect( &rect, pt )) return HTNOWHERE;
554 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
556 /* Check client area */
558 ScreenToClient( wndPtr->hwndSelf, &ptClient );
559 GetClientRect( wndPtr->hwndSelf, &rcClient );
560 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
563 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
565 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
566 if (!PtInRect( &rect, pt ))
568 /* Check top sizing border */
571 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
572 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
575 /* Check bottom sizing border */
576 if (pt.y >= rect.bottom)
578 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
579 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
582 /* Check left sizing border */
583 if (pt.x < rect.left)
585 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
586 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
589 /* Check right sizing border */
590 if (pt.x >= rect.right)
592 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
593 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
598 else /* No thick frame */
600 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
601 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
602 else if (HAS_THINFRAME( wndPtr->dwStyle ))
603 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
604 if (!PtInRect( &rect, pt )) return HTBORDER;
609 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
611 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
612 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
614 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
615 if (!PtInRect( &rect, pt ))
617 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
618 (wndPtr->dwStyle & WS_MINIMIZEBOX);
619 /* Check system menu */
620 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
622 if (NC_IconForWindow(wndPtr->hwndSelf))
623 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
625 if (pt.x < rect.left) return HTSYSMENU;
627 /* Check close button */
628 if (wndPtr->dwStyle & WS_SYSMENU)
629 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
630 if (pt.x > rect.right) return HTCLOSE;
632 /* Check maximize box */
633 /* In win95 there is automatically a Maximize button when there is a minimize one*/
634 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
635 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
636 if (pt.x > rect.right) return HTMAXBUTTON;
638 /* Check minimize box */
639 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
640 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
641 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
643 if (pt.x > rect.right) return HTMINBUTTON;
648 /* Check vertical scroll bar */
650 if (wndPtr->dwStyle & WS_VSCROLL)
652 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
653 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
655 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
656 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
659 /* Check horizontal scroll bar */
661 if (wndPtr->dwStyle & WS_HSCROLL)
663 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
664 if (PtInRect( &rcClient, ptClient ))
667 if ((wndPtr->dwStyle & WS_VSCROLL) &&
668 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
669 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
677 if (HAS_MENU(wndPtr))
679 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
683 /* Has to return HTNOWHERE if nothing was found
684 Could happen when a window has a customized non client area */
689 /***********************************************************************
692 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
694 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
697 WND *wndPtr = WIN_GetPtr( hwnd );
699 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
701 retvalue = NC_DoNCHitTest (wndPtr, pt);
702 WIN_ReleasePtr( wndPtr );
707 /******************************************************************************
711 * Draws the system icon.
713 *****************************************************************************/
714 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
716 HICON hIcon = NC_IconForWindow( hwnd );
721 NC_GetInsideRect( hwnd, &rect );
722 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
723 GetSystemMetrics(SM_CXSMICON),
724 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
730 /******************************************************************************
734 * Draws the close button.
736 * If bGrayed is true, then draw a disabled Close button
738 *****************************************************************************/
740 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
744 NC_GetInsideRect( hwnd, &rect );
746 /* A tool window has a smaller Close button */
747 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & 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) - 1;
761 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
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)
782 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
783 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
786 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
788 NC_GetInsideRect( hwnd, &rect );
789 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
790 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
791 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
792 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
795 if (down) flags |= DFCS_PUSHED;
796 if (bGrayed) flags |= DFCS_INACTIVE;
797 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
800 /******************************************************************************
803 * Draws the minimize button for windows.
804 * If bGrayed is true, then draw a disabled Minimize button
806 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
809 UINT flags = DFCS_CAPTIONMIN;
810 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
812 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
813 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
816 NC_GetInsideRect( hwnd, &rect );
817 if (style & WS_SYSMENU)
818 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
819 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
820 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
821 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
822 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
825 if (down) flags |= DFCS_PUSHED;
826 if (bGrayed) flags |= DFCS_INACTIVE;
827 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
830 /******************************************************************************
834 * Draw a window frame inside the given rectangle, and update the rectangle.
837 * Many. First, just what IS a frame in Win95? Note that the 3D look
838 * on the outer edge is handled by NC_DoNCPaint. As is the inner
839 * edge. The inner rectangle just inside the frame is handled by the
842 * In short, for most people, this function should be a nop (unless
843 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
844 * them lately, but just to get this code right). Even so, it doesn't
845 * appear to be so. It's being worked on...
847 *****************************************************************************/
849 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
853 /* Firstly the "thick" frame */
854 if (style & WS_THICKFRAME)
856 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
857 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
859 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
860 COLOR_INACTIVEBORDER) );
862 PatBlt( hdc, rect->left, rect->top,
863 rect->right - rect->left, height, PATCOPY );
864 PatBlt( hdc, rect->left, rect->top,
865 width, rect->bottom - rect->top, PATCOPY );
866 PatBlt( hdc, rect->left, rect->bottom - 1,
867 rect->right - rect->left, -height, PATCOPY );
868 PatBlt( hdc, rect->right - 1, rect->top,
869 -width, rect->bottom - rect->top, PATCOPY );
871 InflateRect( rect, -width, -height );
874 /* Now the other bit of the frame */
875 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
876 (exStyle & WS_EX_DLGMODALFRAME))
878 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
879 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
880 /* This should give a value of 1 that should also work for a border */
882 SelectObject( hdc, GetSysColorBrush(
883 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
885 (exStyle & WS_EX_STATICEDGE) ?
887 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
893 PatBlt( hdc, rect->left, rect->top,
894 rect->right - rect->left, height, PATCOPY );
895 PatBlt( hdc, rect->left, rect->top,
896 width, rect->bottom - rect->top, PATCOPY );
897 PatBlt( hdc, rect->left, rect->bottom - 1,
898 rect->right - rect->left, -height, PATCOPY );
899 PatBlt( hdc, rect->right - 1, rect->top,
900 -width, rect->bottom - rect->top, PATCOPY );
902 InflateRect( rect, -width, -height );
907 /******************************************************************************
911 * Draw the window caption for windows.
912 * The correct pen for the window frame must be selected in the DC.
914 *****************************************************************************/
916 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
917 DWORD exStyle, BOOL active )
923 BOOL gradient = FALSE;
925 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
926 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
927 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
928 COLOR_WINDOWFRAME : COLOR_3DFACE) );
929 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
930 LineTo( hdc, r.right, r.bottom - 1 );
931 SelectObject( hdc, hPrevPen );
934 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
935 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
937 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
938 if (NC_DrawSysButton (hwnd, hdc, FALSE))
939 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
942 if (style & WS_SYSMENU)
946 /* Go get the sysmenu */
947 hSysMenu = GetSystemMenu(hwnd, FALSE);
948 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
950 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
951 NC_DrawCloseButton (hwnd, hdc, FALSE,
952 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
953 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
955 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
957 /* In win95 the two buttons are always there */
958 /* But if the menu item is not in the menu they're disabled*/
960 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
961 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
963 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
964 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
968 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
970 NONCLIENTMETRICSW nclm;
971 HFONT hFont, hOldFont;
972 nclm.cbSize = sizeof(nclm);
973 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
974 if (exStyle & WS_EX_TOOLWINDOW)
975 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
977 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
978 hOldFont = SelectObject (hdc, hFont);
979 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
980 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
981 SetBkMode( hdc, TRANSPARENT );
983 DrawTextW( hdc, buffer, -1, &r,
984 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
985 DeleteObject (SelectObject (hdc, hOldFont));
990 /******************************************************************************
993 * Paint the non-client area for windows.
995 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
998 RECT rfuzz, rect, rectClip;
1001 DWORD dwStyle, dwExStyle;
1004 RECT rectClient, rectWindow;
1007 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1008 has_menu = HAS_MENU(wndPtr);
1009 dwStyle = wndPtr->dwStyle;
1010 dwExStyle = wndPtr->dwExStyle;
1011 flags = wndPtr->flags;
1012 rectWindow = wndPtr->rectWindow;
1013 WIN_ReleasePtr( wndPtr );
1015 if ( dwStyle & WS_MINIMIZE ||
1016 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1018 active = flags & WIN_NCACTIVATED;
1020 TRACE("%p %d\n", hwnd, active );
1022 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1023 the call to GetDCEx implying that it is allowed not to use it either.
1024 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1025 will cause clipRgn to be deleted after ReleaseDC().
1026 Now, how is the "system" supposed to tell what happened?
1029 GetClientRect( hwnd, &rectClient );
1030 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1031 hrgn = CreateRectRgnIndirect( &rectClient );
1035 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1036 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1040 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1045 rect.top = rect.left = 0;
1046 rect.right = rectWindow.right - rectWindow.left;
1047 rect.bottom = rectWindow.bottom - rectWindow.top;
1048 GetClipBox( hdc, &rectClip );
1050 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1052 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1053 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1055 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1056 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1059 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1061 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1064 if (dwExStyle & WS_EX_TOOLWINDOW) {
1065 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1066 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1069 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1070 rect.top += GetSystemMetrics(SM_CYCAPTION);
1072 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1073 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1079 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1081 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1082 r.left, r.top, r.right, r.bottom);
1084 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1087 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1088 rect.left, rect.top, rect.right, rect.bottom );
1090 if (dwExStyle & WS_EX_CLIENTEDGE)
1091 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1093 /* Draw the scroll-bars */
1095 if (dwStyle & WS_VSCROLL)
1096 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1097 if (dwStyle & WS_HSCROLL)
1098 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1100 /* Draw the "size-box" */
1101 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1104 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1105 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1107 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1108 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1109 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1112 ReleaseDC( hwnd, hdc );
1118 /***********************************************************************
1121 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1123 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1125 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1127 if( dwStyle & WS_VISIBLE )
1129 if( dwStyle & WS_MINIMIZE )
1130 WINPOS_RedrawIconTitle( hwnd );
1132 NC_DoNCPaint( hwnd, clip, FALSE );
1138 /***********************************************************************
1139 * NC_HandleNCActivate
1141 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1143 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1145 WND* wndPtr = WIN_GetPtr( hwnd );
1147 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1149 /* Lotus Notes draws menu descriptions in the caption of its main
1150 * window. When it wants to restore original "system" view, it just
1151 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1152 * attempt to minimize redrawings lead to a not restored caption.
1154 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1155 else wndPtr->flags &= ~WIN_NCACTIVATED;
1156 WIN_ReleasePtr( wndPtr );
1159 WINPOS_RedrawIconTitle( hwnd );
1161 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1167 /***********************************************************************
1168 * NC_HandleSetCursor
1170 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1172 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1174 hwnd = WIN_GetFullHandle( (HWND)wParam );
1176 switch((short)LOWORD(lParam))
1180 WORD msg = HIWORD( lParam );
1181 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1182 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1189 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1199 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1203 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1207 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1211 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1214 /* Default cursor: arrow */
1215 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1218 /***********************************************************************
1221 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1223 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1226 WND *wndPtr = WIN_GetPtr( hwnd );
1227 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1229 NC_GetInsideRect( hwnd, rect );
1230 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1231 if (wndPtr->dwStyle & WS_CHILD)
1232 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1233 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1234 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1235 WIN_ReleasePtr( wndPtr );
1239 /***********************************************************************
1242 * Track a mouse button press on the minimize or maximize box.
1244 * The big difference between 3.1 and 95 is the disabled button state.
1245 * In win95 the system button can be disabled, so it can ignore the mouse
1249 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1252 HDC hdc = GetWindowDC( hwnd );
1253 BOOL pressed = TRUE;
1255 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1256 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1258 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1260 if (wParam == HTMINBUTTON)
1262 /* If the style is not present, do nothing */
1263 if (!(wndStyle & WS_MINIMIZEBOX))
1266 /* Check if the sysmenu item for minimize is there */
1267 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1269 paintButton = &NC_DrawMinButton;
1273 /* If the style is not present, do nothing */
1274 if (!(wndStyle & WS_MAXIMIZEBOX))
1277 /* Check if the sysmenu item for maximize is there */
1278 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1280 paintButton = &NC_DrawMaxButton;
1285 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1289 BOOL oldstate = pressed;
1291 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1292 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1294 if(msg.message == WM_LBUTTONUP)
1297 if(msg.message != WM_MOUSEMOVE)
1300 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1301 if (pressed != oldstate)
1302 (*paintButton)( hwnd, hdc, pressed, FALSE);
1306 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1309 ReleaseDC( hwnd, hdc );
1311 /* If the item minimize or maximize of the sysmenu are not there */
1312 /* or if the style is not present, do nothing */
1313 if ((!pressed) || (state == 0xFFFFFFFF))
1316 if (wParam == HTMINBUTTON)
1317 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1319 SendMessageW( hwnd, WM_SYSCOMMAND,
1320 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1323 /***********************************************************************
1324 * NC_TrackCloseButton
1326 * Track a mouse button press on the Win95 close button.
1328 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1332 BOOL pressed = TRUE;
1333 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1339 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1341 /* If the item close of the sysmenu is disabled or not there do nothing */
1342 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1345 hdc = GetWindowDC( hwnd );
1349 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1353 BOOL oldstate = pressed;
1355 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1356 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1358 if(msg.message == WM_LBUTTONUP)
1361 if(msg.message != WM_MOUSEMOVE)
1364 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1365 if (pressed != oldstate)
1366 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1370 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1373 ReleaseDC( hwnd, hdc );
1374 if (!pressed) return;
1376 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1380 /***********************************************************************
1383 * Track a mouse button press on the horizontal or vertical scroll-bar.
1385 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1389 if ((wParam & 0xfff0) == SC_HSCROLL)
1391 if ((wParam & 0x0f) != HTHSCROLL) return;
1392 scrollbar = SB_HORZ;
1394 else /* SC_VSCROLL */
1396 if ((wParam & 0x0f) != HTVSCROLL) return;
1397 scrollbar = SB_VERT;
1399 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1403 /***********************************************************************
1404 * NC_HandleNCLButtonDown
1406 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1408 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1410 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1412 switch(wParam) /* Hit test */
1416 HWND top = GetAncestor( hwnd, GA_ROOT );
1418 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1419 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1424 if( style & WS_SYSMENU )
1426 if( !(style & WS_MINIMIZE) )
1428 HDC hDC = GetWindowDC(hwnd);
1429 NC_DrawSysButton( hwnd, hDC, TRUE );
1430 ReleaseDC( hwnd, hDC );
1432 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1441 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1445 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1450 NC_TrackMinMaxBox( hwnd, wParam );
1454 NC_TrackCloseButton (hwnd, wParam);
1466 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1467 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1469 /* But that is not what WinNT does. Instead it sends this. This
1470 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1471 * SC_MOUSEMENU into wParam.
1473 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1483 /***********************************************************************
1484 * NC_HandleNCLButtonDblClk
1486 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1488 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1491 * if this is an icon, send a restore since we are handling
1496 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1500 switch(wParam) /* Hit test */
1503 /* stop processing if WS_MAXIMIZEBOX is missing */
1504 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1505 SendMessageW( hwnd, WM_SYSCOMMAND,
1506 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1511 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1512 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1514 /* If the item close of the sysmenu is disabled or not there do nothing */
1515 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1518 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1523 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1527 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1534 /***********************************************************************
1535 * NC_HandleSysCommand
1537 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1539 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1541 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1543 if (!IsWindowEnabled( hwnd )) return 0;
1545 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1548 switch (wParam & 0xfff0)
1552 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1556 if (hwnd == GetForegroundWindow())
1557 ShowOwnedPopups(hwnd,FALSE);
1558 ShowWindow( hwnd, SW_MINIMIZE );
1562 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1563 ShowOwnedPopups(hwnd,TRUE);
1564 ShowWindow( hwnd, SW_MAXIMIZE );
1568 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1569 ShowOwnedPopups(hwnd,TRUE);
1570 ShowWindow( hwnd, SW_RESTORE );
1574 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1580 pt.x = (short)LOWORD(lParam);
1581 pt.y = (short)HIWORD(lParam);
1582 NC_TrackScrollBar( hwnd, wParam, pt );
1589 pt.x = (short)LOWORD(lParam);
1590 pt.y = (short)HIWORD(lParam);
1591 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1596 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1600 WinExec( "taskman.exe", SW_SHOWNORMAL );
1604 if (wParam == SC_ABOUTWINE)
1606 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1609 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1610 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1611 FreeLibrary( hmodule );
1615 if (wParam == SC_PUTMARK)
1616 DPRINTF("Debug mark requested by user\n");
1623 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1629 /*************************************************************
1632 * Stub for the grayed button of the caption
1634 *************************************************************/
1636 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1642 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1647 hdcMask = CreateCompatibleDC (0);
1648 SelectObject (hdcMask, hMaskBmp);
1650 /* Draw the grayed bitmap using the mask */
1651 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1652 BitBlt (hdc, x, y, 12, 10,
1653 hdcMask, 0, 0, 0xB8074A);
1656 SelectObject (hdc, hOldBrush);
1657 DeleteObject(hMaskBmp);
1663 /***********************************************************************
1664 * GetTitleBarInfo (USER32.@)
1665 * TODO: Handle STATE_SYSTEM_PRESSED
1667 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1672 TRACE("(%p %p)\n", hwnd, tbi);
1674 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1675 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1676 SetLastError(ERROR_INVALID_PARAMETER);
1679 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1680 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1681 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1683 GetWindowRect(hwnd, &wndRect);
1685 tbi->rcTitleBar.top += wndRect.top;
1686 tbi->rcTitleBar.left += wndRect.left;
1687 tbi->rcTitleBar.right += wndRect.left;
1689 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1690 if(dwExStyle & WS_EX_TOOLWINDOW)
1691 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1693 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1694 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1697 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1698 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1699 * Under XP it seems to
1701 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1702 if(dwStyle & WS_CAPTION) {
1703 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1704 if(dwStyle & WS_SYSMENU) {
1705 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1706 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1707 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1710 if(!(dwStyle & WS_MINIMIZEBOX))
1711 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1712 if(!(dwStyle & WS_MAXIMIZEBOX))
1713 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1715 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1716 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1717 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1718 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1721 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1722 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1723 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1728 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;