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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/winuser16.h"
31 #include "user_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
38 WINE_DECLARE_DEBUG_CHANNEL(shell);
40 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
42 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
53 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
54 #define SC_PUTMARK (SC_SCREENSAVE+2)
56 /* Some useful macros */
57 #define HAS_DLGFRAME(style,exStyle) \
58 (((exStyle) & WS_EX_DLGMODALFRAME) || \
59 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
61 #define HAS_THICKFRAME(style,exStyle) \
62 (((style) & WS_THICKFRAME) && \
63 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
65 #define HAS_THINFRAME(style) \
66 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
68 #define HAS_BIGFRAME(style,exStyle) \
69 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
70 ((exStyle) & WS_EX_DLGMODALFRAME))
72 #define HAS_STATICOUTERFRAME(style,exStyle) \
73 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
76 #define HAS_ANYFRAME(style,exStyle) \
77 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
78 ((exStyle) & WS_EX_DLGMODALFRAME) || \
79 !((style) & (WS_CHILD | WS_POPUP)))
81 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
84 /******************************************************************************
87 * Computes the size of the "outside" parts of the window based on the
88 * parameters of the client area.
97 * "Outer" parts of a window means the whole window frame, caption and
98 * menu bar. It does not include "inner" parts of the frame like client
99 * edge, static edge or scroll bars.
101 *****************************************************************************/
104 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
107 if(style & WS_ICONIC) return;
109 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
112 adjust = 1; /* for the outer frame always present */
117 if ((exStyle & WS_EX_DLGMODALFRAME) ||
118 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
120 if (style & WS_THICKFRAME)
121 adjust += ( GetSystemMetrics (SM_CXFRAME)
122 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
123 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
124 (exStyle & WS_EX_DLGMODALFRAME))
125 adjust++; /* The other border */
127 InflateRect (rect, adjust, adjust);
129 if ((style & WS_CAPTION) == WS_CAPTION)
131 if (exStyle & WS_EX_TOOLWINDOW)
132 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
134 rect->top -= GetSystemMetrics(SM_CYCAPTION);
136 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
140 /******************************************************************************
143 * Computes the size of the "inside" part of the window based on the
144 * parameters of the client area.
152 * "Inner" part of a window means the window frame inside of the flat
153 * window frame. It includes the client edge, the static edge and the
156 *****************************************************************************/
159 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
161 if(style & WS_ICONIC) return;
163 if (exStyle & WS_EX_CLIENTEDGE)
164 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
166 if (style & WS_VSCROLL)
168 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
169 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
171 rect->right += GetSystemMetrics(SM_CXVSCROLL);
173 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
178 static HICON NC_IconForWindow( HWND hwnd )
181 WND *wndPtr = WIN_GetPtr( hwnd );
183 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
185 hIcon = wndPtr->hIconSmall;
186 if (!hIcon) hIcon = wndPtr->hIcon;
187 WIN_ReleasePtr( wndPtr );
189 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
190 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
192 /* If there is no hIcon specified and this is a modal dialog,
193 * get the default one.
195 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
196 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
200 /***********************************************************************
201 * DrawCaption (USER32.@) Draws a caption bar
215 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
217 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
221 /***********************************************************************
222 * DrawCaptionTempA (USER32.@)
224 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
225 HICON hIcon, LPCSTR str, UINT uFlags)
231 if (!(uFlags & DC_TEXT) || !str)
232 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
234 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
235 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
237 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
238 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
239 HeapFree( GetProcessHeap (), 0, strW );
245 /***********************************************************************
246 * DrawCaptionTempW (USER32.@)
248 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
249 HICON hIcon, LPCWSTR str, UINT uFlags)
253 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
254 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
256 /* drawing background */
257 if (uFlags & DC_INBUTTON) {
258 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
260 if (uFlags & DC_ACTIVE) {
261 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
262 PatBlt (hdc, rc.left, rc.top,
263 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
264 SelectObject (hdc, hbr);
268 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
269 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
274 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
278 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
280 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
281 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
282 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
283 rc.left += (rc.bottom - rc.top);
287 if (uFlags & DC_TEXT) {
290 if (uFlags & DC_INBUTTON)
291 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
292 else if (uFlags & DC_ACTIVE)
293 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
295 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
297 SetBkMode (hdc, TRANSPARENT);
300 hOldFont = SelectObject (hdc, hFont);
302 NONCLIENTMETRICSW nclm;
304 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
305 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
306 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
307 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
308 hOldFont = SelectObject (hdc, hNewFont);
312 DrawTextW (hdc, str, -1, &rc,
313 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
317 nLen = GetWindowTextW (hwnd, szText, 128);
318 DrawTextW (hdc, szText, nLen, &rc,
319 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
323 SelectObject (hdc, hOldFont);
325 DeleteObject (SelectObject (hdc, hOldFont));
328 /* drawing focus ??? */
330 FIXME("undocumented flag (0x2000)!\n");
336 /***********************************************************************
337 * AdjustWindowRect (USER32.@)
339 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
341 return AdjustWindowRectEx( rect, style, menu, 0 );
345 /***********************************************************************
346 * AdjustWindowRectEx (USER32.@)
348 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
350 /* Correct the window style */
351 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
352 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
353 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
354 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
356 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
357 rect->left, rect->top, rect->right, rect->bottom,
358 style, menu, exStyle );
360 NC_AdjustRectOuter( rect, style, menu, exStyle );
361 NC_AdjustRectInner( rect, style, exStyle );
367 /***********************************************************************
368 * NC_HandleNCCalcSize
370 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
372 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
374 RECT tmpRect = { 0, 0, 0, 0 };
376 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
377 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
378 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
380 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
381 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
385 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
387 winRect->left -= tmpRect.left;
388 winRect->top -= tmpRect.top;
389 winRect->right -= tmpRect.right;
390 winRect->bottom -= tmpRect.bottom;
392 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
394 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
395 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
398 MENU_GetMenuBarHeight( hwnd,
399 winRect->right - winRect->left,
400 -tmpRect.left, -tmpRect.top );
403 if( exStyle & WS_EX_CLIENTEDGE)
404 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
405 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
406 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
407 - GetSystemMetrics(SM_CYEDGE));
409 if (style & WS_VSCROLL)
410 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
411 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
412 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
414 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
417 if (style & WS_HSCROLL)
418 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
419 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
421 if (winRect->top > winRect->bottom)
422 winRect->bottom = winRect->top;
424 if (winRect->left > winRect->right)
425 winRect->right = winRect->left;
431 /***********************************************************************
434 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
435 * but without the borders (if any).
436 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
438 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
440 WND *wndPtr = WIN_GetPtr( hwnd );
442 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
444 rect->top = rect->left = 0;
445 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
446 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
448 if (wndPtr->dwStyle & WS_ICONIC) goto END;
450 /* Remove frame from rectangle */
451 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
453 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
455 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
457 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
459 else if (HAS_THINFRAME( wndPtr->dwStyle ))
461 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
464 /* We have additional border information if the window
465 * is a child (but not an MDI child) */
466 if ( (wndPtr->dwStyle & WS_CHILD) &&
467 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
469 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
470 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
471 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
472 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
476 WIN_ReleasePtr( wndPtr );
480 /***********************************************************************
483 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
485 * FIXME: Just a modified copy of the Win 3.1 version.
488 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
493 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
495 GetWindowRect(wndPtr->hwndSelf, &rect );
496 if (!PtInRect( &rect, pt )) return HTNOWHERE;
498 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
500 /* Check client area */
502 ScreenToClient( wndPtr->hwndSelf, &ptClient );
503 GetClientRect( wndPtr->hwndSelf, &rcClient );
504 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
507 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
509 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
510 if (!PtInRect( &rect, pt ))
512 /* Check top sizing border */
515 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
516 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
519 /* Check bottom sizing border */
520 if (pt.y >= rect.bottom)
522 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
523 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
526 /* Check left sizing border */
527 if (pt.x < rect.left)
529 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
530 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
533 /* Check right sizing border */
534 if (pt.x >= rect.right)
536 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
537 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
542 else /* No thick frame */
544 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
545 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
546 else if (HAS_THINFRAME( wndPtr->dwStyle ))
547 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
548 if (!PtInRect( &rect, pt )) return HTBORDER;
553 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
555 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
556 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
558 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
559 if (!PtInRect( &rect, pt ))
561 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
562 (wndPtr->dwStyle & WS_MINIMIZEBOX);
563 /* Check system menu */
564 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
566 if (NC_IconForWindow(wndPtr->hwndSelf))
567 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
569 if (pt.x < rect.left) return HTSYSMENU;
571 /* Check close button */
572 if (wndPtr->dwStyle & WS_SYSMENU)
573 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
574 if (pt.x > rect.right) return HTCLOSE;
576 /* Check maximize box */
577 /* In win95 there is automatically a Maximize button when there is a minimize one*/
578 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
579 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
580 if (pt.x > rect.right) return HTMAXBUTTON;
582 /* Check minimize box */
583 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
584 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
585 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
587 if (pt.x > rect.right) return HTMINBUTTON;
592 /* Check vertical scroll bar */
594 if (wndPtr->dwStyle & WS_VSCROLL)
596 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
597 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
599 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
600 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
603 /* Check horizontal scroll bar */
605 if (wndPtr->dwStyle & WS_HSCROLL)
607 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
608 if (PtInRect( &rcClient, ptClient ))
611 if ((wndPtr->dwStyle & WS_VSCROLL) &&
612 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
613 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
621 if (HAS_MENU(wndPtr))
623 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
627 /* Has to return HTNOWHERE if nothing was found
628 Could happen when a window has a customized non client area */
633 /***********************************************************************
636 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
638 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
641 WND *wndPtr = WIN_GetPtr( hwnd );
643 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
645 retvalue = NC_DoNCHitTest (wndPtr, pt);
646 WIN_ReleasePtr( wndPtr );
651 /******************************************************************************
655 * Draws the system icon.
657 *****************************************************************************/
658 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
660 HICON hIcon = NC_IconForWindow( hwnd );
665 NC_GetInsideRect( hwnd, &rect );
666 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
667 GetSystemMetrics(SM_CXSMICON),
668 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
674 /******************************************************************************
678 * Draws the close button.
680 * If bGrayed is true, then draw a disabled Close button
682 *****************************************************************************/
684 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
688 NC_GetInsideRect( hwnd, &rect );
690 /* A tool window has a smaller Close button */
691 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
693 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
694 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
695 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
697 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
698 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
699 rect.bottom = rect.top + iBmpHeight;
700 rect.right = rect.left + iBmpWidth;
704 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
705 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
709 DrawFrameControl( hdc, &rect, DFC_CAPTION,
711 (down ? DFCS_PUSHED : 0) |
712 (bGrayed ? DFCS_INACTIVE : 0)) );
715 /******************************************************************************
718 * Draws the maximize button for windows.
719 * If bGrayed is true, then draw a disabled Maximize button
721 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
726 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
727 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
730 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
732 NC_GetInsideRect( hwnd, &rect );
733 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
734 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
735 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
736 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
739 if (down) flags |= DFCS_PUSHED;
740 if (bGrayed) flags |= DFCS_INACTIVE;
741 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
744 /******************************************************************************
747 * Draws the minimize button for windows.
748 * If bGrayed is true, then draw a disabled Minimize button
750 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
753 UINT flags = DFCS_CAPTIONMIN;
754 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
756 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
757 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
760 NC_GetInsideRect( hwnd, &rect );
761 if (style & WS_SYSMENU)
762 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
763 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
764 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
765 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
766 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
769 if (down) flags |= DFCS_PUSHED;
770 if (bGrayed) flags |= DFCS_INACTIVE;
771 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
774 /******************************************************************************
778 * Draw a window frame inside the given rectangle, and update the rectangle.
781 * Many. First, just what IS a frame in Win95? Note that the 3D look
782 * on the outer edge is handled by NC_DoNCPaint. As is the inner
783 * edge. The inner rectangle just inside the frame is handled by the
786 * In short, for most people, this function should be a nop (unless
787 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
788 * them lately, but just to get this code right). Even so, it doesn't
789 * appear to be so. It's being worked on...
791 *****************************************************************************/
793 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
797 /* Firstly the "thick" frame */
798 if (style & WS_THICKFRAME)
800 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
801 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
803 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
804 COLOR_INACTIVEBORDER) );
806 PatBlt( hdc, rect->left, rect->top,
807 rect->right - rect->left, height, PATCOPY );
808 PatBlt( hdc, rect->left, rect->top,
809 width, rect->bottom - rect->top, PATCOPY );
810 PatBlt( hdc, rect->left, rect->bottom - 1,
811 rect->right - rect->left, -height, PATCOPY );
812 PatBlt( hdc, rect->right - 1, rect->top,
813 -width, rect->bottom - rect->top, PATCOPY );
815 InflateRect( rect, -width, -height );
818 /* Now the other bit of the frame */
819 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
820 (exStyle & WS_EX_DLGMODALFRAME))
822 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
823 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
824 /* This should give a value of 1 that should also work for a border */
826 SelectObject( hdc, GetSysColorBrush(
827 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
829 (exStyle & WS_EX_STATICEDGE) ?
831 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
837 PatBlt( hdc, rect->left, rect->top,
838 rect->right - rect->left, height, PATCOPY );
839 PatBlt( hdc, rect->left, rect->top,
840 width, rect->bottom - rect->top, PATCOPY );
841 PatBlt( hdc, rect->left, rect->bottom - 1,
842 rect->right - rect->left, -height, PATCOPY );
843 PatBlt( hdc, rect->right - 1, rect->top,
844 -width, rect->bottom - rect->top, PATCOPY );
846 InflateRect( rect, -width, -height );
851 /******************************************************************************
855 * Draw the window caption for windows.
856 * The correct pen for the window frame must be selected in the DC.
858 *****************************************************************************/
860 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
861 DWORD exStyle, BOOL active )
868 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
869 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
870 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
871 COLOR_WINDOWFRAME : COLOR_3DFACE) );
872 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
873 LineTo( hdc, r.right, r.bottom - 1 );
874 SelectObject( hdc, hPrevPen );
877 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
878 COLOR_INACTIVECAPTION) );
880 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
881 if (NC_DrawSysButton (hwnd, hdc, FALSE))
882 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
885 if (style & WS_SYSMENU)
889 /* Go get the sysmenu */
890 hSysMenu = GetSystemMenu(hwnd, FALSE);
891 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
893 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
894 NC_DrawCloseButton (hwnd, hdc, FALSE,
895 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
896 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
898 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
900 /* In win95 the two buttons are always there */
901 /* But if the menu item is not in the menu they're disabled*/
903 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
904 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
906 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
907 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
911 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
913 NONCLIENTMETRICSW nclm;
914 HFONT hFont, hOldFont;
915 nclm.cbSize = sizeof(nclm);
916 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
917 if (exStyle & WS_EX_TOOLWINDOW)
918 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
920 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
921 hOldFont = SelectObject (hdc, hFont);
922 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
923 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
924 SetBkMode( hdc, TRANSPARENT );
926 DrawTextW( hdc, buffer, -1, &r,
927 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
928 DeleteObject (SelectObject (hdc, hOldFont));
933 /******************************************************************************
936 * Paint the non-client area for windows.
938 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
941 RECT rfuzz, rect, rectClip;
944 DWORD dwStyle, dwExStyle;
947 RECT rectClient, rectWindow;
950 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
951 has_menu = HAS_MENU(wndPtr);
952 dwStyle = wndPtr->dwStyle;
953 dwExStyle = wndPtr->dwExStyle;
954 flags = wndPtr->flags;
955 rectWindow = wndPtr->rectWindow;
956 WIN_ReleasePtr( wndPtr );
958 if ( dwStyle & WS_MINIMIZE ||
959 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
961 active = flags & WIN_NCACTIVATED;
963 TRACE("%p %d\n", hwnd, active );
965 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
966 the call to GetDCEx implying that it is allowed not to use it either.
967 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
968 will cause clipRgn to be deleted after ReleaseDC().
969 Now, how is the "system" supposed to tell what happened?
972 GetClientRect( hwnd, &rectClient );
973 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
974 hrgn = CreateRectRgnIndirect( &rectClient );
978 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
979 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
983 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
988 rect.top = rect.left = 0;
989 rect.right = rectWindow.right - rectWindow.left;
990 rect.bottom = rectWindow.bottom - rectWindow.top;
991 GetClipBox( hdc, &rectClip );
993 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
995 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
996 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
998 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
999 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1002 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1004 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1007 if (dwExStyle & WS_EX_TOOLWINDOW) {
1008 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1009 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1012 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1013 rect.top += GetSystemMetrics(SM_CYCAPTION);
1015 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1016 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1022 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1024 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1025 r.left, r.top, r.right, r.bottom);
1027 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1030 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1031 rect.left, rect.top, rect.right, rect.bottom );
1033 if (dwExStyle & WS_EX_CLIENTEDGE)
1034 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1036 /* Draw the scroll-bars */
1038 if (dwStyle & WS_VSCROLL)
1039 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1040 if (dwStyle & WS_HSCROLL)
1041 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1043 /* Draw the "size-box" */
1044 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1047 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1048 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1050 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1051 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1052 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1055 ReleaseDC( hwnd, hdc );
1061 /***********************************************************************
1064 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1066 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1068 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1070 if( dwStyle & WS_VISIBLE )
1072 if( dwStyle & WS_MINIMIZE )
1073 WINPOS_RedrawIconTitle( hwnd );
1075 NC_DoNCPaint( hwnd, clip, FALSE );
1081 /***********************************************************************
1082 * NC_HandleNCActivate
1084 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1086 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1088 WND* wndPtr = WIN_GetPtr( hwnd );
1090 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1092 /* Lotus Notes draws menu descriptions in the caption of its main
1093 * window. When it wants to restore original "system" view, it just
1094 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1095 * attempt to minimize redrawings lead to a not restored caption.
1097 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1098 else wndPtr->flags &= ~WIN_NCACTIVATED;
1099 WIN_ReleasePtr( wndPtr );
1102 WINPOS_RedrawIconTitle( hwnd );
1104 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1110 /***********************************************************************
1111 * NC_HandleSetCursor
1113 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1115 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1117 hwnd = WIN_GetFullHandle( (HWND)wParam );
1119 switch((short)LOWORD(lParam))
1123 WORD msg = HIWORD( lParam );
1124 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1125 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1132 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1142 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1146 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1150 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1154 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1157 /* Default cursor: arrow */
1158 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1161 /***********************************************************************
1164 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1166 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1169 WND *wndPtr = WIN_GetPtr( hwnd );
1170 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1172 NC_GetInsideRect( hwnd, rect );
1173 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1174 if (wndPtr->dwStyle & WS_CHILD)
1175 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1176 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1177 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1178 WIN_ReleasePtr( wndPtr );
1182 /***********************************************************************
1185 * Track a mouse button press on the minimize or maximize box.
1187 * The big difference between 3.1 and 95 is the disabled button state.
1188 * In win95 the system button can be disabled, so it can ignore the mouse
1192 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1195 HDC hdc = GetWindowDC( hwnd );
1196 BOOL pressed = TRUE;
1198 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1199 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1201 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1203 if (wParam == HTMINBUTTON)
1205 /* If the style is not present, do nothing */
1206 if (!(wndStyle & WS_MINIMIZEBOX))
1209 /* Check if the sysmenu item for minimize is there */
1210 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1212 paintButton = &NC_DrawMinButton;
1216 /* If the style is not present, do nothing */
1217 if (!(wndStyle & WS_MAXIMIZEBOX))
1220 /* Check if the sysmenu item for maximize is there */
1221 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1223 paintButton = &NC_DrawMaxButton;
1228 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1232 BOOL oldstate = pressed;
1234 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1235 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1237 if(msg.message == WM_LBUTTONUP)
1240 if(msg.message != WM_MOUSEMOVE)
1243 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1244 if (pressed != oldstate)
1245 (*paintButton)( hwnd, hdc, pressed, FALSE);
1249 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1252 ReleaseDC( hwnd, hdc );
1254 /* If the item minimize or maximize of the sysmenu are not there */
1255 /* or if the style is not present, do nothing */
1256 if ((!pressed) || (state == 0xFFFFFFFF))
1259 if (wParam == HTMINBUTTON)
1260 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1262 SendMessageA( hwnd, WM_SYSCOMMAND,
1263 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1266 /***********************************************************************
1267 * NC_TrackCloseButton
1269 * Track a mouse button press on the Win95 close button.
1271 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1275 BOOL pressed = TRUE;
1276 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1282 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1284 /* If the item close of the sysmenu is disabled or not there do nothing */
1285 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1288 hdc = GetWindowDC( hwnd );
1292 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1296 BOOL oldstate = pressed;
1298 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1299 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1301 if(msg.message == WM_LBUTTONUP)
1304 if(msg.message != WM_MOUSEMOVE)
1307 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1308 if (pressed != oldstate)
1309 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1313 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1316 ReleaseDC( hwnd, hdc );
1317 if (!pressed) return;
1319 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1323 /***********************************************************************
1326 * Track a mouse button press on the horizontal or vertical scroll-bar.
1328 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1332 if ((wParam & 0xfff0) == SC_HSCROLL)
1334 if ((wParam & 0x0f) != HTHSCROLL) return;
1335 scrollbar = SB_HORZ;
1337 else /* SC_VSCROLL */
1339 if ((wParam & 0x0f) != HTVSCROLL) return;
1340 scrollbar = SB_VERT;
1342 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1346 /***********************************************************************
1347 * NC_HandleNCLButtonDown
1349 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1351 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1353 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1355 switch(wParam) /* Hit test */
1359 HWND top = GetAncestor( hwnd, GA_ROOT );
1361 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1362 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1367 if( style & WS_SYSMENU )
1369 if( !(style & WS_MINIMIZE) )
1371 HDC hDC = GetWindowDC(hwnd);
1372 NC_DrawSysButton( hwnd, hDC, TRUE );
1373 ReleaseDC( hwnd, hDC );
1375 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1380 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1384 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1388 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1393 NC_TrackMinMaxBox( hwnd, wParam );
1397 NC_TrackCloseButton (hwnd, wParam);
1409 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1410 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1412 /* But that is not what WinNT does. Instead it sends this. This
1413 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1414 * SC_MOUSEMENU into wParam.
1416 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1426 /***********************************************************************
1427 * NC_HandleNCLButtonDblClk
1429 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1431 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1434 * if this is an icon, send a restore since we are handling
1439 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1443 switch(wParam) /* Hit test */
1446 /* stop processing if WS_MAXIMIZEBOX is missing */
1447 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1448 SendMessageW( hwnd, WM_SYSCOMMAND,
1449 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1454 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1455 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1457 /* If the item close of the sysmenu is disabled or not there do nothing */
1458 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1461 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1466 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1470 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1477 /***********************************************************************
1478 * NC_HandleSysCommand
1480 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1482 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1484 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1486 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1489 switch (wParam & 0xfff0)
1493 if (USER_Driver.pSysCommandSizeMove)
1494 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
1498 if (hwnd == GetForegroundWindow())
1499 ShowOwnedPopups(hwnd,FALSE);
1500 ShowWindow( hwnd, SW_MINIMIZE );
1504 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1505 ShowOwnedPopups(hwnd,TRUE);
1506 ShowWindow( hwnd, SW_MAXIMIZE );
1510 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1511 ShowOwnedPopups(hwnd,TRUE);
1512 ShowWindow( hwnd, SW_RESTORE );
1516 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1522 pt.x = (short)LOWORD(lParam);
1523 pt.y = (short)HIWORD(lParam);
1524 NC_TrackScrollBar( hwnd, wParam, pt );
1531 pt.x = (short)LOWORD(lParam);
1532 pt.y = (short)HIWORD(lParam);
1533 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1538 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1542 WinExec( "taskman.exe", SW_SHOWNORMAL );
1546 if (wParam == SC_ABOUTWINE)
1548 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1551 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1552 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1553 FreeLibrary( hmodule );
1557 if (wParam == SC_PUTMARK)
1558 DPRINTF("Debug mark requested by user\n");
1565 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1571 /*************************************************************
1574 * Stub for the grayed button of the caption
1576 *************************************************************/
1578 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1584 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1589 hdcMask = CreateCompatibleDC (0);
1590 SelectObject (hdcMask, hMaskBmp);
1592 /* Draw the grayed bitmap using the mask */
1593 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1594 BitBlt (hdc, x, y, 12, 10,
1595 hdcMask, 0, 0, 0xB8074A);
1598 SelectObject (hdc, hOldBrush);
1599 DeleteObject(hMaskBmp);
1605 /***********************************************************************
1606 * GetTitleBarInfo (USER32.@)
1607 * TODO: Handle STATE_SYSTEM_PRESSED
1609 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1614 TRACE("(%p %p)\n", hwnd, tbi);
1616 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1617 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1618 SetLastError(ERROR_INVALID_PARAMETER);
1621 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1622 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1623 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1625 GetWindowRect(hwnd, &wndRect);
1627 tbi->rcTitleBar.top += wndRect.top;
1628 tbi->rcTitleBar.left += wndRect.left;
1629 tbi->rcTitleBar.right += wndRect.left;
1631 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1632 if(dwExStyle & WS_EX_TOOLWINDOW)
1633 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1635 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1636 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1639 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1640 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1641 * Under XP it seems to
1643 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1644 if(dwStyle & WS_CAPTION) {
1645 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1646 if(dwStyle & WS_SYSMENU) {
1647 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1648 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1649 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1652 if(!(dwStyle & WS_MINIMIZEBOX))
1653 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1654 if(!(dwStyle & WS_MAXIMIZEBOX))
1655 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1657 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1658 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1659 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1660 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1663 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1664 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1665 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1666 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1670 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;