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"
33 #include "cursoricon.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
39 WINE_DECLARE_DEBUG_CHANNEL(shell);
41 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
43 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
54 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
55 #define SC_PUTMARK (SC_SCREENSAVE+2)
57 /* Some useful macros */
58 #define HAS_DLGFRAME(style,exStyle) \
59 (((exStyle) & WS_EX_DLGMODALFRAME) || \
60 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
62 #define HAS_THICKFRAME(style,exStyle) \
63 (((style) & WS_THICKFRAME) && \
64 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
66 #define HAS_THINFRAME(style) \
67 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
69 #define HAS_BIGFRAME(style,exStyle) \
70 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
71 ((exStyle) & WS_EX_DLGMODALFRAME))
73 #define HAS_STATICOUTERFRAME(style,exStyle) \
74 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
77 #define HAS_ANYFRAME(style,exStyle) \
78 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
79 ((exStyle) & WS_EX_DLGMODALFRAME) || \
80 !((style) & (WS_CHILD | WS_POPUP)))
82 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
85 /******************************************************************************
88 * Computes the size of the "outside" parts of the window based on the
89 * parameters of the client area.
98 * "Outer" parts of a window means the whole window frame, caption and
99 * menu bar. It does not include "inner" parts of the frame like client
100 * edge, static edge or scroll bars.
102 *****************************************************************************/
105 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
108 if(style & WS_ICONIC) return;
110 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
113 adjust = 1; /* for the outer frame always present */
118 if ((exStyle & WS_EX_DLGMODALFRAME) ||
119 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
121 if (style & WS_THICKFRAME)
122 adjust += ( GetSystemMetrics (SM_CXFRAME)
123 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
124 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
125 (exStyle & WS_EX_DLGMODALFRAME))
126 adjust++; /* The other border */
128 InflateRect (rect, adjust, adjust);
130 if ((style & WS_CAPTION) == WS_CAPTION)
132 if (exStyle & WS_EX_TOOLWINDOW)
133 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
135 rect->top -= GetSystemMetrics(SM_CYCAPTION);
137 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
141 /******************************************************************************
144 * Computes the size of the "inside" part of the window based on the
145 * parameters of the client area.
153 * "Inner" part of a window means the window frame inside of the flat
154 * window frame. It includes the client edge, the static edge and the
157 *****************************************************************************/
160 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
162 if(style & WS_ICONIC) return;
164 if (exStyle & WS_EX_CLIENTEDGE)
165 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
167 if (style & WS_VSCROLL)
169 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
170 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
172 rect->right += GetSystemMetrics(SM_CXVSCROLL);
174 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
179 static HICON NC_IconForWindow( HWND hwnd )
182 WND *wndPtr = WIN_GetPtr( hwnd );
184 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
186 hIcon = wndPtr->hIconSmall;
187 if (!hIcon) hIcon = wndPtr->hIcon;
188 WIN_ReleasePtr( wndPtr );
190 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
191 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
193 /* If there is no hIcon specified and this is a modal dialog,
194 * get the default one.
196 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
197 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
201 /***********************************************************************
202 * DrawCaption (USER32.@) Draws a caption bar
216 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
218 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
222 /***********************************************************************
223 * DrawCaptionTempA (USER32.@)
225 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
226 HICON hIcon, LPCSTR str, UINT uFlags)
232 if (!(uFlags & DC_TEXT) || !str)
233 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
235 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
236 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
238 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
239 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
240 HeapFree( GetProcessHeap (), 0, strW );
246 /***********************************************************************
247 * DrawCaptionTempW (USER32.@)
249 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
250 HICON hIcon, LPCWSTR str, UINT uFlags)
254 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
255 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
257 /* drawing background */
258 if (uFlags & DC_INBUTTON) {
259 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
261 if (uFlags & DC_ACTIVE) {
262 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
263 PatBlt (hdc, rc.left, rc.top,
264 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
265 SelectObject (hdc, hbr);
269 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
270 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
275 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
279 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
281 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
282 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
283 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
284 rc.left += (rc.bottom - rc.top);
288 if (uFlags & DC_TEXT) {
291 if (uFlags & DC_INBUTTON)
292 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
293 else if (uFlags & DC_ACTIVE)
294 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
296 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
298 SetBkMode (hdc, TRANSPARENT);
301 hOldFont = SelectObject (hdc, hFont);
303 NONCLIENTMETRICSW nclm;
305 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
306 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
307 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
308 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
309 hOldFont = SelectObject (hdc, hNewFont);
313 DrawTextW (hdc, str, -1, &rc,
314 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
318 nLen = GetWindowTextW (hwnd, szText, 128);
319 DrawTextW (hdc, szText, nLen, &rc,
320 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
324 SelectObject (hdc, hOldFont);
326 DeleteObject (SelectObject (hdc, hOldFont));
329 /* drawing focus ??? */
331 FIXME("undocumented flag (0x2000)!\n");
337 /***********************************************************************
338 * AdjustWindowRect (USER32.@)
340 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
342 return AdjustWindowRectEx( rect, style, menu, 0 );
346 /***********************************************************************
347 * AdjustWindowRectEx (USER32.@)
349 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
351 /* Correct the window style */
352 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
353 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
354 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
355 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
357 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
358 rect->left, rect->top, rect->right, rect->bottom,
359 style, menu, exStyle );
361 NC_AdjustRectOuter( rect, style, menu, exStyle );
362 NC_AdjustRectInner( rect, style, exStyle );
368 /***********************************************************************
369 * NC_HandleNCCalcSize
371 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
373 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
375 RECT tmpRect = { 0, 0, 0, 0 };
377 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
378 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
379 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
381 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
382 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
386 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
388 winRect->left -= tmpRect.left;
389 winRect->top -= tmpRect.top;
390 winRect->right -= tmpRect.right;
391 winRect->bottom -= tmpRect.bottom;
393 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
395 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
396 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
399 MENU_GetMenuBarHeight( hwnd,
400 winRect->right - winRect->left,
401 -tmpRect.left, -tmpRect.top ) + 1;
404 if( exStyle & WS_EX_CLIENTEDGE)
405 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
406 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
407 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
408 - GetSystemMetrics(SM_CYEDGE));
410 if (style & WS_VSCROLL)
411 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
412 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
413 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
415 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
418 if (style & WS_HSCROLL)
419 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
420 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
422 if (winRect->top > winRect->bottom)
423 winRect->bottom = winRect->top;
425 if (winRect->left > winRect->right)
426 winRect->right = winRect->left;
432 /***********************************************************************
435 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
436 * but without the borders (if any).
437 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
439 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
441 WND *wndPtr = WIN_GetPtr( hwnd );
443 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
445 rect->top = rect->left = 0;
446 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
447 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
449 if (wndPtr->dwStyle & WS_ICONIC) goto END;
451 /* Remove frame from rectangle */
452 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
454 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
456 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
458 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
460 else if (HAS_THINFRAME( wndPtr->dwStyle ))
462 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
465 /* We have additional border information if the window
466 * is a child (but not an MDI child) */
467 if ( (wndPtr->dwStyle & WS_CHILD) &&
468 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
470 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
471 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
472 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
473 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
477 WIN_ReleasePtr( wndPtr );
481 /***********************************************************************
484 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
486 * FIXME: Just a modified copy of the Win 3.1 version.
489 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
494 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
496 GetWindowRect(wndPtr->hwndSelf, &rect );
497 if (!PtInRect( &rect, pt )) return HTNOWHERE;
499 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
501 /* Check client area */
503 ScreenToClient( wndPtr->hwndSelf, &ptClient );
504 GetClientRect( wndPtr->hwndSelf, &rcClient );
505 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
508 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
510 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
511 if (!PtInRect( &rect, pt ))
513 /* Check top sizing border */
516 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
517 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
520 /* Check bottom sizing border */
521 if (pt.y >= rect.bottom)
523 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
524 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
527 /* Check left sizing border */
528 if (pt.x < rect.left)
530 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
531 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
534 /* Check right sizing border */
535 if (pt.x >= rect.right)
537 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
538 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
543 else /* No thick frame */
545 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
546 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
547 else if (HAS_THINFRAME( wndPtr->dwStyle ))
548 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
549 if (!PtInRect( &rect, pt )) return HTBORDER;
554 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
556 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
557 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
559 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
560 if (!PtInRect( &rect, pt ))
562 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
563 (wndPtr->dwStyle & WS_MINIMIZEBOX);
564 /* Check system menu */
565 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
567 if (NC_IconForWindow(wndPtr->hwndSelf))
568 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
570 if (pt.x < rect.left) return HTSYSMENU;
572 /* Check close button */
573 if (wndPtr->dwStyle & WS_SYSMENU)
574 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
575 if (pt.x > rect.right) return HTCLOSE;
577 /* Check maximize box */
578 /* In win95 there is automatically a Maximize button when there is a minimize one*/
579 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
580 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
581 if (pt.x > rect.right) return HTMAXBUTTON;
583 /* Check minimize box */
584 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
585 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
586 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
588 if (pt.x > rect.right) return HTMINBUTTON;
593 /* Check vertical scroll bar */
595 if (wndPtr->dwStyle & WS_VSCROLL)
597 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
598 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
600 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
601 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
604 /* Check horizontal scroll bar */
606 if (wndPtr->dwStyle & WS_HSCROLL)
608 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
609 if (PtInRect( &rcClient, ptClient ))
612 if ((wndPtr->dwStyle & WS_VSCROLL) &&
613 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
614 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
622 if (HAS_MENU(wndPtr))
624 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
628 /* Has to return HTNOWHERE if nothing was found
629 Could happen when a window has a customized non client area */
634 /***********************************************************************
637 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
639 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
642 WND *wndPtr = WIN_GetPtr( hwnd );
644 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
646 retvalue = NC_DoNCHitTest (wndPtr, pt);
647 WIN_ReleasePtr( wndPtr );
652 /******************************************************************************
656 * Draws the system icon.
658 *****************************************************************************/
659 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
661 HICON hIcon = NC_IconForWindow( hwnd );
666 NC_GetInsideRect( hwnd, &rect );
667 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
668 GetSystemMetrics(SM_CXSMICON),
669 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
675 /******************************************************************************
679 * Draws the close button.
681 * If bGrayed is true, then draw a disabled Close button
683 *****************************************************************************/
685 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
689 NC_GetInsideRect( hwnd, &rect );
691 /* A tool window has a smaller Close button */
692 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
694 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
695 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
696 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
698 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
699 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
700 rect.bottom = rect.top + iBmpHeight;
701 rect.right = rect.left + iBmpWidth;
705 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
706 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
710 DrawFrameControl( hdc, &rect, DFC_CAPTION,
712 (down ? DFCS_PUSHED : 0) |
713 (bGrayed ? DFCS_INACTIVE : 0)) );
716 /******************************************************************************
719 * Draws the maximize button for windows.
720 * If bGrayed is true, then draw a disabled Maximize button
722 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
727 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
728 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
731 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
733 NC_GetInsideRect( hwnd, &rect );
734 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
735 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
736 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
737 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
740 if (down) flags |= DFCS_PUSHED;
741 if (bGrayed) flags |= DFCS_INACTIVE;
742 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
745 /******************************************************************************
748 * Draws the minimize button for windows.
749 * If bGrayed is true, then draw a disabled Minimize button
751 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
754 UINT flags = DFCS_CAPTIONMIN;
755 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
757 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
758 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
761 NC_GetInsideRect( hwnd, &rect );
762 if (style & WS_SYSMENU)
763 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
764 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
765 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
766 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
767 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
770 if (down) flags |= DFCS_PUSHED;
771 if (bGrayed) flags |= DFCS_INACTIVE;
772 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
775 /******************************************************************************
779 * Draw a window frame inside the given rectangle, and update the rectangle.
782 * Many. First, just what IS a frame in Win95? Note that the 3D look
783 * on the outer edge is handled by NC_DoNCPaint. As is the inner
784 * edge. The inner rectangle just inside the frame is handled by the
787 * In short, for most people, this function should be a nop (unless
788 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
789 * them lately, but just to get this code right). Even so, it doesn't
790 * appear to be so. It's being worked on...
792 *****************************************************************************/
794 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
798 /* Firstly the "thick" frame */
799 if (style & WS_THICKFRAME)
801 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
802 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
804 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
805 COLOR_INACTIVEBORDER) );
807 PatBlt( hdc, rect->left, rect->top,
808 rect->right - rect->left, height, PATCOPY );
809 PatBlt( hdc, rect->left, rect->top,
810 width, rect->bottom - rect->top, PATCOPY );
811 PatBlt( hdc, rect->left, rect->bottom - 1,
812 rect->right - rect->left, -height, PATCOPY );
813 PatBlt( hdc, rect->right - 1, rect->top,
814 -width, rect->bottom - rect->top, PATCOPY );
816 InflateRect( rect, -width, -height );
819 /* Now the other bit of the frame */
820 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
821 (exStyle & WS_EX_DLGMODALFRAME))
823 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
824 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
825 /* This should give a value of 1 that should also work for a border */
827 SelectObject( hdc, GetSysColorBrush(
828 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
830 (exStyle & WS_EX_STATICEDGE) ?
832 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
838 PatBlt( hdc, rect->left, rect->top,
839 rect->right - rect->left, height, PATCOPY );
840 PatBlt( hdc, rect->left, rect->top,
841 width, rect->bottom - rect->top, PATCOPY );
842 PatBlt( hdc, rect->left, rect->bottom - 1,
843 rect->right - rect->left, -height, PATCOPY );
844 PatBlt( hdc, rect->right - 1, rect->top,
845 -width, rect->bottom - rect->top, PATCOPY );
847 InflateRect( rect, -width, -height );
852 /******************************************************************************
856 * Draw the window caption for windows.
857 * The correct pen for the window frame must be selected in the DC.
859 *****************************************************************************/
861 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
862 DWORD exStyle, BOOL active )
869 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
870 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
871 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
872 COLOR_WINDOWFRAME : COLOR_3DFACE) );
873 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
874 LineTo( hdc, r.right, r.bottom - 1 );
875 SelectObject( hdc, hPrevPen );
878 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
879 COLOR_INACTIVECAPTION) );
881 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
882 if (NC_DrawSysButton (hwnd, hdc, FALSE))
883 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
886 if (style & WS_SYSMENU)
890 /* Go get the sysmenu */
891 hSysMenu = GetSystemMenu(hwnd, FALSE);
892 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
894 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
895 NC_DrawCloseButton (hwnd, hdc, FALSE,
896 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
897 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
899 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
901 /* In win95 the two buttons are always there */
902 /* But if the menu item is not in the menu they're disabled*/
904 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
905 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
907 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
908 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
912 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
914 NONCLIENTMETRICSW nclm;
915 HFONT hFont, hOldFont;
916 nclm.cbSize = sizeof(nclm);
917 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
918 if (exStyle & WS_EX_TOOLWINDOW)
919 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
921 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
922 hOldFont = SelectObject (hdc, hFont);
923 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
924 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
925 SetBkMode( hdc, TRANSPARENT );
927 DrawTextW( hdc, buffer, -1, &r,
928 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
929 DeleteObject (SelectObject (hdc, hOldFont));
934 /******************************************************************************
937 * Paint the non-client area for windows.
939 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
942 RECT rfuzz, rect, rectClip;
945 DWORD dwStyle, dwExStyle;
948 RECT rectClient, rectWindow;
951 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
952 has_menu = HAS_MENU(wndPtr);
953 dwStyle = wndPtr->dwStyle;
954 dwExStyle = wndPtr->dwExStyle;
955 flags = wndPtr->flags;
956 rectWindow = wndPtr->rectWindow;
957 WIN_ReleasePtr( wndPtr );
959 if ( dwStyle & WS_MINIMIZE ||
960 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
962 active = flags & WIN_NCACTIVATED;
964 TRACE("%p %d\n", hwnd, active );
966 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
967 the call to GetDCEx implying that it is allowed not to use it either.
968 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
969 will cause clipRgn to be deleted after ReleaseDC().
970 Now, how is the "system" supposed to tell what happened?
973 GetClientRect( hwnd, &rectClient );
974 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
975 hrgn = CreateRectRgnIndirect( &rectClient );
979 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
980 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
984 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
989 rect.top = rect.left = 0;
990 rect.right = rectWindow.right - rectWindow.left;
991 rect.bottom = rectWindow.bottom - rectWindow.top;
992 GetClipBox( hdc, &rectClip );
994 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
996 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
997 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
999 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1000 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1003 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1005 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1008 if (dwExStyle & WS_EX_TOOLWINDOW) {
1009 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1010 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1013 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1014 rect.top += GetSystemMetrics(SM_CYCAPTION);
1016 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1017 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1023 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1025 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1026 r.left, r.top, r.right, r.bottom);
1028 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1031 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1032 rect.left, rect.top, rect.right, rect.bottom );
1034 if (dwExStyle & WS_EX_CLIENTEDGE)
1035 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1037 /* Draw the scroll-bars */
1039 if (dwStyle & WS_VSCROLL)
1040 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1041 if (dwStyle & WS_HSCROLL)
1042 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1044 /* Draw the "size-box" */
1045 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1048 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1049 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1051 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1052 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1053 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1056 ReleaseDC( hwnd, hdc );
1062 /***********************************************************************
1065 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1067 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1069 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1071 if( dwStyle & WS_VISIBLE )
1073 if( dwStyle & WS_MINIMIZE )
1074 WINPOS_RedrawIconTitle( hwnd );
1076 NC_DoNCPaint( hwnd, clip, FALSE );
1082 /***********************************************************************
1083 * NC_HandleNCActivate
1085 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1087 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1089 WND* wndPtr = WIN_GetPtr( hwnd );
1091 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1093 /* Lotus Notes draws menu descriptions in the caption of its main
1094 * window. When it wants to restore original "system" view, it just
1095 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1096 * attempt to minimize redrawings lead to a not restored caption.
1098 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1099 else wndPtr->flags &= ~WIN_NCACTIVATED;
1100 WIN_ReleasePtr( wndPtr );
1103 WINPOS_RedrawIconTitle( hwnd );
1105 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1111 /***********************************************************************
1112 * NC_HandleSetCursor
1114 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1116 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1118 hwnd = WIN_GetFullHandle( (HWND)wParam );
1120 switch((short)LOWORD(lParam))
1124 WORD msg = HIWORD( lParam );
1125 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1126 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1133 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1143 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1147 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1151 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1155 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1158 /* Default cursor: arrow */
1159 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1162 /***********************************************************************
1165 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1167 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1170 WND *wndPtr = WIN_GetPtr( hwnd );
1171 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1173 NC_GetInsideRect( hwnd, rect );
1174 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1175 if (wndPtr->dwStyle & WS_CHILD)
1176 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1177 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1178 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1179 WIN_ReleasePtr( wndPtr );
1183 /***********************************************************************
1186 * Track a mouse button press on the minimize or maximize box.
1188 * The big difference between 3.1 and 95 is the disabled button state.
1189 * In win95 the system button can be disabled, so it can ignore the mouse
1193 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1196 HDC hdc = GetWindowDC( hwnd );
1197 BOOL pressed = TRUE;
1199 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1200 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1202 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1204 if (wParam == HTMINBUTTON)
1206 /* If the style is not present, do nothing */
1207 if (!(wndStyle & WS_MINIMIZEBOX))
1210 /* Check if the sysmenu item for minimize is there */
1211 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1213 paintButton = &NC_DrawMinButton;
1217 /* If the style is not present, do nothing */
1218 if (!(wndStyle & WS_MAXIMIZEBOX))
1221 /* Check if the sysmenu item for maximize is there */
1222 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1224 paintButton = &NC_DrawMaxButton;
1229 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1233 BOOL oldstate = pressed;
1235 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1236 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1238 if(msg.message == WM_LBUTTONUP)
1241 if(msg.message != WM_MOUSEMOVE)
1244 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1245 if (pressed != oldstate)
1246 (*paintButton)( hwnd, hdc, pressed, FALSE);
1250 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1253 ReleaseDC( hwnd, hdc );
1255 /* If the item minimize or maximize of the sysmenu are not there */
1256 /* or if the style is not present, do nothing */
1257 if ((!pressed) || (state == 0xFFFFFFFF))
1260 if (wParam == HTMINBUTTON)
1261 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1263 SendMessageA( hwnd, WM_SYSCOMMAND,
1264 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1267 /***********************************************************************
1268 * NC_TrackCloseButton
1270 * Track a mouse button press on the Win95 close button.
1272 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1276 BOOL pressed = TRUE;
1277 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1283 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1285 /* If the item close of the sysmenu is disabled or not there do nothing */
1286 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1289 hdc = GetWindowDC( hwnd );
1293 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1297 BOOL oldstate = pressed;
1299 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1300 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1302 if(msg.message == WM_LBUTTONUP)
1305 if(msg.message != WM_MOUSEMOVE)
1308 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1309 if (pressed != oldstate)
1310 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1314 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1317 ReleaseDC( hwnd, hdc );
1318 if (!pressed) return;
1320 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1324 /***********************************************************************
1327 * Track a mouse button press on the horizontal or vertical scroll-bar.
1329 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1333 if ((wParam & 0xfff0) == SC_HSCROLL)
1335 if ((wParam & 0x0f) != HTHSCROLL) return;
1336 scrollbar = SB_HORZ;
1338 else /* SC_VSCROLL */
1340 if ((wParam & 0x0f) != HTVSCROLL) return;
1341 scrollbar = SB_VERT;
1343 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1347 /***********************************************************************
1348 * NC_HandleNCLButtonDown
1350 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1352 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1354 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1356 switch(wParam) /* Hit test */
1360 HWND top = GetAncestor( hwnd, GA_ROOT );
1362 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1363 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1368 if( style & WS_SYSMENU )
1370 if( !(style & WS_MINIMIZE) )
1372 HDC hDC = GetWindowDC(hwnd);
1373 NC_DrawSysButton( hwnd, hDC, TRUE );
1374 ReleaseDC( hwnd, hDC );
1376 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1381 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1385 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1389 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1394 NC_TrackMinMaxBox( hwnd, wParam );
1398 NC_TrackCloseButton (hwnd, wParam);
1410 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1411 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1413 /* But that is not what WinNT does. Instead it sends this. This
1414 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1415 * SC_MOUSEMENU into wParam.
1417 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1427 /***********************************************************************
1428 * NC_HandleNCLButtonDblClk
1430 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1432 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1435 * if this is an icon, send a restore since we are handling
1440 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1444 switch(wParam) /* Hit test */
1447 /* stop processing if WS_MAXIMIZEBOX is missing */
1448 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1449 SendMessageW( hwnd, WM_SYSCOMMAND,
1450 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1455 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1456 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1458 /* If the item close of the sysmenu is disabled or not there do nothing */
1459 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1462 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1467 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1471 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1478 /***********************************************************************
1479 * NC_HandleSysCommand
1481 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1483 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1485 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1487 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1490 switch (wParam & 0xfff0)
1494 if (USER_Driver.pSysCommandSizeMove)
1495 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
1499 if (hwnd == GetForegroundWindow())
1500 ShowOwnedPopups(hwnd,FALSE);
1501 ShowWindow( hwnd, SW_MINIMIZE );
1505 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1506 ShowOwnedPopups(hwnd,TRUE);
1507 ShowWindow( hwnd, SW_MAXIMIZE );
1511 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1512 ShowOwnedPopups(hwnd,TRUE);
1513 ShowWindow( hwnd, SW_RESTORE );
1517 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1523 pt.x = (short)LOWORD(lParam);
1524 pt.y = (short)HIWORD(lParam);
1525 NC_TrackScrollBar( hwnd, wParam, pt );
1532 pt.x = (short)LOWORD(lParam);
1533 pt.y = (short)HIWORD(lParam);
1534 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1539 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1543 WinExec( "taskman.exe", SW_SHOWNORMAL );
1547 if (wParam == SC_ABOUTWINE)
1549 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1552 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1553 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1554 FreeLibrary( hmodule );
1558 if (wParam == SC_PUTMARK)
1559 DPRINTF("Debug mark requested by user\n");
1566 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1572 /*************************************************************
1575 * Stub for the grayed button of the caption
1577 *************************************************************/
1579 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1585 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1590 hdcMask = CreateCompatibleDC (0);
1591 SelectObject (hdcMask, hMaskBmp);
1593 /* Draw the grayed bitmap using the mask */
1594 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1595 BitBlt (hdc, x, y, 12, 10,
1596 hdcMask, 0, 0, 0xB8074A);
1599 SelectObject (hdc, hOldBrush);
1600 DeleteObject(hMaskBmp);
1606 /***********************************************************************
1607 * GetTitleBarInfo (USER32.@)
1608 * TODO: Handle STATE_SYSTEM_PRESSED
1610 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1615 TRACE("(%p %p)\n", hwnd, tbi);
1617 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1618 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1619 SetLastError(ERROR_INVALID_PARAMETER);
1622 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1623 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1624 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1626 GetWindowRect(hwnd, &wndRect);
1628 tbi->rcTitleBar.top += wndRect.top;
1629 tbi->rcTitleBar.left += wndRect.left;
1630 tbi->rcTitleBar.right += wndRect.left;
1632 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1633 if(dwExStyle & WS_EX_TOOLWINDOW)
1634 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1636 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1637 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1640 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1641 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1642 * Under XP it seems to
1644 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1645 if(dwStyle & WS_CAPTION) {
1646 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1647 if(dwStyle & WS_SYSMENU) {
1648 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1649 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1650 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1653 if(!(dwStyle & WS_MINIMIZEBOX))
1654 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1655 if(!(dwStyle & WS_MAXIMIZEBOX))
1656 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1658 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1659 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1660 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1661 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1664 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1665 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1666 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1667 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1671 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;