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"
34 #include "cursoricon.h"
36 #include "nonclient.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
41 WINE_DECLARE_DEBUG_CHANNEL(shell);
43 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
45 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
56 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
57 #define SC_PUTMARK (SC_SCREENSAVE+2)
59 /* Some useful macros */
60 #define HAS_DLGFRAME(style,exStyle) \
61 (((exStyle) & WS_EX_DLGMODALFRAME) || \
62 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
64 #define HAS_THICKFRAME(style,exStyle) \
65 (((style) & WS_THICKFRAME) && \
66 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
68 #define HAS_THINFRAME(style) \
69 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
71 #define HAS_BIGFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME))
75 #define HAS_STATICOUTERFRAME(style,exStyle) \
76 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
79 #define HAS_ANYFRAME(style,exStyle) \
80 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
81 ((exStyle) & WS_EX_DLGMODALFRAME) || \
82 !((style) & (WS_CHILD | WS_POPUP)))
84 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
87 /******************************************************************************
90 * Computes the size of the "outside" parts of the window based on the
91 * parameters of the client area.
100 * "Outer" parts of a window means the whole window frame, caption and
101 * menu bar. It does not include "inner" parts of the frame like client
102 * edge, static edge or scroll bars.
104 *****************************************************************************/
107 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
110 if(style & WS_ICONIC) return;
112 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
115 adjust = 1; /* for the outer frame always present */
120 if ((exStyle & WS_EX_DLGMODALFRAME) ||
121 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
123 if (style & WS_THICKFRAME)
124 adjust += ( GetSystemMetrics (SM_CXFRAME)
125 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
126 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
127 (exStyle & WS_EX_DLGMODALFRAME))
128 adjust++; /* The other border */
130 InflateRect (rect, adjust, adjust);
132 if ((style & WS_CAPTION) == WS_CAPTION)
134 if (exStyle & WS_EX_TOOLWINDOW)
135 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
137 rect->top -= GetSystemMetrics(SM_CYCAPTION);
139 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
143 /******************************************************************************
146 * Computes the size of the "inside" part of the window based on the
147 * parameters of the client area.
155 * "Inner" part of a window means the window frame inside of the flat
156 * window frame. It includes the client edge, the static edge and the
159 *****************************************************************************/
162 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
164 if(style & WS_ICONIC) return;
166 if (exStyle & WS_EX_CLIENTEDGE)
167 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
169 if (style & WS_VSCROLL)
171 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
172 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
174 rect->right += GetSystemMetrics(SM_CXVSCROLL);
176 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
181 static HICON NC_IconForWindow( HWND hwnd )
184 WND *wndPtr = WIN_GetPtr( hwnd );
186 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
188 hIcon = wndPtr->hIconSmall;
189 if (!hIcon) hIcon = wndPtr->hIcon;
190 WIN_ReleasePtr( wndPtr );
192 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
193 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
195 /* If there is no hIcon specified and this is a modal dialog,
196 * get the default one.
198 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
199 hIcon = LoadImageA(0, (LPSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
203 /***********************************************************************
204 * DrawCaption (USER32.@) Draws a caption bar
218 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
220 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
224 /***********************************************************************
225 * DrawCaptionTempA (USER32.@)
227 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
228 HICON hIcon, LPCSTR str, UINT uFlags)
234 if (!(uFlags & DC_TEXT) || !str)
235 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
237 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
238 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
240 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
241 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
242 HeapFree( GetProcessHeap (), 0, strW );
248 /***********************************************************************
249 * DrawCaptionTempW (USER32.@)
251 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
252 HICON hIcon, LPCWSTR str, UINT uFlags)
256 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
257 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
259 /* drawing background */
260 if (uFlags & DC_INBUTTON) {
261 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
263 if (uFlags & DC_ACTIVE) {
264 HBRUSH hbr = SelectObject (hdc, UITOOLS_GetPattern55AABrush ());
265 PatBlt (hdc, rc.left, rc.top,
266 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
267 SelectObject (hdc, hbr);
271 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
272 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
277 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
281 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
283 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
284 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
285 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
286 rc.left += (rc.bottom - rc.top);
290 if (uFlags & DC_TEXT) {
293 if (uFlags & DC_INBUTTON)
294 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
295 else if (uFlags & DC_ACTIVE)
296 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
298 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
300 SetBkMode (hdc, TRANSPARENT);
303 hOldFont = SelectObject (hdc, hFont);
305 NONCLIENTMETRICSW nclm;
307 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
308 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
309 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
310 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
311 hOldFont = SelectObject (hdc, hNewFont);
315 DrawTextW (hdc, str, -1, &rc,
316 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
320 nLen = GetWindowTextW (hwnd, szText, 128);
321 DrawTextW (hdc, szText, nLen, &rc,
322 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
326 SelectObject (hdc, hOldFont);
328 DeleteObject (SelectObject (hdc, hOldFont));
331 /* drawing focus ??? */
333 FIXME("undocumented flag (0x2000)!\n");
339 /***********************************************************************
340 * AdjustWindowRect (USER32.@)
342 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
344 return AdjustWindowRectEx( rect, style, menu, 0 );
348 /***********************************************************************
349 * AdjustWindowRectEx (USER32.@)
351 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
353 /* Correct the window style */
354 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
355 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
356 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
357 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
359 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
360 rect->left, rect->top, rect->right, rect->bottom,
361 style, menu, exStyle );
363 NC_AdjustRectOuter( rect, style, menu, exStyle );
364 NC_AdjustRectInner( rect, style, exStyle );
370 /***********************************************************************
371 * NC_HandleNCCalcSize
373 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
375 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
377 RECT tmpRect = { 0, 0, 0, 0 };
379 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
380 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
381 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
383 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
384 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
388 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
390 winRect->left -= tmpRect.left;
391 winRect->top -= tmpRect.top;
392 winRect->right -= tmpRect.right;
393 winRect->bottom -= tmpRect.bottom;
395 if (!(style & WS_CHILD) && GetMenu(hwnd))
397 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
398 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
401 MENU_GetMenuBarHeight( hwnd,
402 winRect->right - winRect->left,
403 -tmpRect.left, -tmpRect.top ) + 1;
406 SetRect(&tmpRect, 0, 0, 0, 0);
407 NC_AdjustRectInner (&tmpRect, style, exStyle);
408 winRect->left -= tmpRect.left;
409 winRect->top -= tmpRect.top;
410 winRect->right -= tmpRect.right;
411 winRect->bottom -= tmpRect.bottom;
413 if (winRect->top > winRect->bottom)
414 winRect->bottom = winRect->top;
416 if (winRect->left > winRect->right)
417 winRect->right = winRect->left;
423 /***********************************************************************
426 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
427 * but without the borders (if any).
428 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
430 void NC_GetInsideRect( HWND hwnd, RECT *rect )
432 WND * wndPtr = WIN_FindWndPtr( hwnd );
434 rect->top = rect->left = 0;
435 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
436 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
438 if (wndPtr->dwStyle & WS_ICONIC) goto END;
440 /* Remove frame from rectangle */
441 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
443 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
445 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
447 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
449 else if (HAS_THINFRAME( wndPtr->dwStyle ))
451 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
454 /* We have additional border information if the window
455 * is a child (but not an MDI child) */
456 if ( (wndPtr->dwStyle & WS_CHILD) &&
457 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
459 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
460 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
461 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
462 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
466 WIN_ReleaseWndPtr(wndPtr);
471 /***********************************************************************
474 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
476 * FIXME: Just a modified copy of the Win 3.1 version.
479 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
484 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
486 GetWindowRect(wndPtr->hwndSelf, &rect );
487 if (!PtInRect( &rect, pt )) return HTNOWHERE;
489 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
491 /* Check client area */
493 ScreenToClient( wndPtr->hwndSelf, &ptClient );
494 GetClientRect( wndPtr->hwndSelf, &rcClient );
495 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
498 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
500 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
501 if (!PtInRect( &rect, pt ))
503 /* Check top sizing border */
506 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
507 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
510 /* Check bottom sizing border */
511 if (pt.y >= rect.bottom)
513 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
514 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
517 /* Check left sizing border */
518 if (pt.x < rect.left)
520 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
521 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
524 /* Check right sizing border */
525 if (pt.x >= rect.right)
527 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
528 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
533 else /* No thick frame */
535 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
536 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
537 else if (HAS_THINFRAME( wndPtr->dwStyle ))
538 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
539 if (!PtInRect( &rect, pt )) return HTBORDER;
544 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
546 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
547 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
549 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
550 if (!PtInRect( &rect, pt ))
552 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
553 (wndPtr->dwStyle & WS_MINIMIZEBOX);
554 /* Check system menu */
555 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
557 if (NC_IconForWindow(wndPtr->hwndSelf))
558 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
560 if (pt.x < rect.left) return HTSYSMENU;
562 /* Check close button */
563 if (wndPtr->dwStyle & WS_SYSMENU)
564 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
565 if (pt.x > rect.right) return HTCLOSE;
567 /* Check maximize box */
568 /* In win95 there is automatically a Maximize button when there is a minimize one*/
569 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
570 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
571 if (pt.x > rect.right) return HTMAXBUTTON;
573 /* Check minimize box */
574 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
575 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
576 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
578 if (pt.x > rect.right) return HTMINBUTTON;
583 /* Check vertical scroll bar */
585 if (wndPtr->dwStyle & WS_VSCROLL)
587 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
588 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
590 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
591 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
594 /* Check horizontal scroll bar */
596 if (wndPtr->dwStyle & WS_HSCROLL)
598 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
599 if (PtInRect( &rcClient, ptClient ))
602 if ((wndPtr->dwStyle & WS_VSCROLL) &&
603 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
604 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
612 if (HAS_MENU(wndPtr))
614 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
618 /* Has to return HTNOWHERE if nothing was found
619 Could happen when a window has a customized non client area */
624 /***********************************************************************
627 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
629 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
632 WND *wndPtr = WIN_FindWndPtr (hwnd);
637 retvalue = NC_DoNCHitTest (wndPtr, pt);
638 WIN_ReleaseWndPtr(wndPtr);
643 /******************************************************************************
647 * Draws the system icon.
649 *****************************************************************************/
650 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
652 HICON hIcon = NC_IconForWindow( hwnd );
657 NC_GetInsideRect( hwnd, &rect );
658 DrawIconEx (hdc, rect.left + 1, rect.top + 1, hIcon,
659 GetSystemMetrics(SM_CXSIZE) - 1,
660 GetSystemMetrics(SM_CYSIZE) - 1, 0, 0, DI_NORMAL);
666 /******************************************************************************
670 * Draws the close button.
672 * If bGrayed is true, then draw a disabled Close button
674 *****************************************************************************/
676 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
680 NC_GetInsideRect( hwnd, &rect );
682 /* A tool window has a smaller Close button */
683 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
685 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
686 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
687 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
689 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
690 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
691 rect.bottom = rect.top + iBmpHeight;
692 rect.right = rect.left + iBmpWidth;
696 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
697 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
701 DrawFrameControl( hdc, &rect, DFC_CAPTION,
703 (down ? DFCS_PUSHED : 0) |
704 (bGrayed ? DFCS_INACTIVE : 0)) );
707 /******************************************************************************
710 * Draws the maximize button for windows.
711 * If bGrayed is true, then draw a disabled Maximize button
713 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
718 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
719 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
722 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
724 NC_GetInsideRect( hwnd, &rect );
725 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
726 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
727 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
728 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
731 if (down) flags |= DFCS_PUSHED;
732 if (bGrayed) flags |= DFCS_INACTIVE;
733 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
736 /******************************************************************************
739 * Draws the minimize button for windows.
740 * If bGrayed is true, then draw a disabled Minimize button
742 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
745 UINT flags = DFCS_CAPTIONMIN;
746 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
748 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
749 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
752 NC_GetInsideRect( hwnd, &rect );
753 if (style & WS_SYSMENU)
754 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
755 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
756 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
757 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
758 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
761 if (down) flags |= DFCS_PUSHED;
762 if (bGrayed) flags |= DFCS_INACTIVE;
763 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
766 /******************************************************************************
770 * Draw a window frame inside the given rectangle, and update the rectangle.
773 * Many. First, just what IS a frame in Win95? Note that the 3D look
774 * on the outer edge is handled by NC_DoNCPaint. As is the inner
775 * edge. The inner rectangle just inside the frame is handled by the
778 * In short, for most people, this function should be a nop (unless
779 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
780 * them lately, but just to get this code right). Even so, it doesn't
781 * appear to be so. It's being worked on...
783 *****************************************************************************/
785 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
789 /* Firstly the "thick" frame */
790 if (style & WS_THICKFRAME)
792 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
793 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
795 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
796 COLOR_INACTIVEBORDER) );
798 PatBlt( hdc, rect->left, rect->top,
799 rect->right - rect->left, height, PATCOPY );
800 PatBlt( hdc, rect->left, rect->top,
801 width, rect->bottom - rect->top, PATCOPY );
802 PatBlt( hdc, rect->left, rect->bottom - 1,
803 rect->right - rect->left, -height, PATCOPY );
804 PatBlt( hdc, rect->right - 1, rect->top,
805 -width, rect->bottom - rect->top, PATCOPY );
807 InflateRect( rect, -width, -height );
810 /* Now the other bit of the frame */
811 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
812 (exStyle & WS_EX_DLGMODALFRAME))
814 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
815 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
816 /* This should give a value of 1 that should also work for a border */
818 SelectObject( hdc, GetSysColorBrush(
819 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
821 (exStyle & WS_EX_STATICEDGE) ?
823 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
829 PatBlt( hdc, rect->left, rect->top,
830 rect->right - rect->left, height, PATCOPY );
831 PatBlt( hdc, rect->left, rect->top,
832 width, rect->bottom - rect->top, PATCOPY );
833 PatBlt( hdc, rect->left, rect->bottom - 1,
834 rect->right - rect->left, -height, PATCOPY );
835 PatBlt( hdc, rect->right - 1, rect->top,
836 -width, rect->bottom - rect->top, PATCOPY );
838 InflateRect( rect, -width, -height );
843 /******************************************************************************
847 * Draw the window caption for windows.
848 * The correct pen for the window frame must be selected in the DC.
850 *****************************************************************************/
852 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
853 DWORD exStyle, BOOL active )
860 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
861 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
862 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
863 COLOR_WINDOWFRAME : COLOR_3DFACE) );
864 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
865 LineTo( hdc, r.right, r.bottom - 1 );
866 SelectObject( hdc, hPrevPen );
869 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
870 COLOR_INACTIVECAPTION) );
872 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
873 if (NC_DrawSysButton (hwnd, hdc, FALSE))
874 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
877 if (style & WS_SYSMENU)
881 /* Go get the sysmenu */
882 hSysMenu = GetSystemMenu(hwnd, FALSE);
883 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
885 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
886 NC_DrawCloseButton (hwnd, hdc, FALSE,
887 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
888 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
890 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
892 /* In win95 the two buttons are always there */
893 /* But if the menu item is not in the menu they're disabled*/
895 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
896 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
898 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
899 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
903 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
905 NONCLIENTMETRICSW nclm;
906 HFONT hFont, hOldFont;
907 nclm.cbSize = sizeof(nclm);
908 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
909 if (exStyle & WS_EX_TOOLWINDOW)
910 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
912 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
913 hOldFont = SelectObject (hdc, hFont);
914 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
915 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
916 SetBkMode( hdc, TRANSPARENT );
918 DrawTextW( hdc, buffer, -1, &r,
919 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
920 DeleteObject (SelectObject (hdc, hOldFont));
925 /******************************************************************************
929 * Paint the non-client area for windows. The clip region is
933 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
934 * misc/tweak.c controls/menu.c # :-)
936 *****************************************************************************/
938 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
941 RECT rfuzz, rect, rectClip;
944 DWORD dwStyle, dwExStyle;
946 RECT rectClient, rectWindow;
949 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
950 has_menu = HAS_MENU(wndPtr);
951 dwStyle = wndPtr->dwStyle;
952 dwExStyle = wndPtr->dwExStyle;
953 flags = wndPtr->flags;
954 rectClient = wndPtr->rectClient;
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 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
973 ((clip > (HRGN)1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
976 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
977 rectClient.top-rectWindow.top,
978 rectClient.right-rectWindow.left,
979 rectClient.bottom-rectWindow.top )
982 ReleaseDC( hwnd, hdc );
986 rect.top = rect.left = 0;
987 rect.right = rectWindow.right - rectWindow.left;
988 rect.bottom = rectWindow.bottom - rectWindow.top;
991 GetRgnBox( clip, &rectClip );
998 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1000 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1001 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1003 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1004 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1007 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1009 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1012 if (dwExStyle & WS_EX_TOOLWINDOW) {
1013 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1014 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1017 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1018 rect.top += GetSystemMetrics(SM_CYCAPTION);
1020 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1021 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1027 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1029 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1030 r.left, r.top, r.right, r.bottom);
1032 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1035 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1036 rect.left, rect.top, rect.right, rect.bottom );
1038 if (dwExStyle & WS_EX_CLIENTEDGE)
1039 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1041 /* Draw the scroll-bars */
1043 if (dwStyle & WS_VSCROLL)
1044 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1045 if (dwStyle & WS_HSCROLL)
1046 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1048 /* Draw the "size-box" */
1049 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1052 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1053 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1055 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1056 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1057 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1060 ReleaseDC( hwnd, hdc );
1066 /***********************************************************************
1069 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1071 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1073 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1075 if( dwStyle & WS_VISIBLE )
1077 if( dwStyle & WS_MINIMIZE )
1078 WINPOS_RedrawIconTitle( hwnd );
1080 NC_DoNCPaint( hwnd, clip, FALSE );
1086 /***********************************************************************
1087 * NC_HandleNCActivate
1089 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1091 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1093 WND* wndPtr = WIN_FindWndPtr( hwnd );
1095 /* Lotus Notes draws menu descriptions in the caption of its main
1096 * window. When it wants to restore original "system" view, it just
1097 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1098 * attempt to minimize redrawings lead to a not restored caption.
1102 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1103 else wndPtr->flags &= ~WIN_NCACTIVATED;
1104 WIN_ReleaseWndPtr(wndPtr);
1107 WINPOS_RedrawIconTitle( hwnd );
1109 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1115 /***********************************************************************
1116 * NC_HandleSetCursor
1118 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1120 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1122 hwnd = WIN_GetFullHandle( (HWND)wParam );
1124 switch((short)LOWORD(lParam))
1128 WORD msg = HIWORD( lParam );
1129 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1130 (msg == WM_RBUTTONDOWN))
1137 HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
1147 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1151 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1155 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1159 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1162 /* Default cursor: arrow */
1163 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1166 /***********************************************************************
1169 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1171 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1174 WND *wndPtr = WIN_FindWndPtr( hwnd );
1175 if (!wndPtr) return;
1177 NC_GetInsideRect( hwnd, rect );
1178 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1179 if (wndPtr->dwStyle & WS_CHILD)
1180 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1181 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1182 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1183 WIN_ReleaseWndPtr( wndPtr );
1187 /***********************************************************************
1190 * Track a mouse button press on the minimize or maximize box.
1192 * The big difference between 3.1 and 95 is the disabled button state.
1193 * In win95 the system button can be disabled, so it can ignore the mouse
1197 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1200 HDC hdc = GetWindowDC( hwnd );
1201 BOOL pressed = TRUE;
1203 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1204 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1206 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1208 if (wParam == HTMINBUTTON)
1210 /* If the style is not present, do nothing */
1211 if (!(wndStyle & WS_MINIMIZEBOX))
1214 /* Check if the sysmenu item for minimize is there */
1215 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1217 paintButton = &NC_DrawMinButton;
1221 /* If the style is not present, do nothing */
1222 if (!(wndStyle & WS_MAXIMIZEBOX))
1225 /* Check if the sysmenu item for maximize is there */
1226 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1228 paintButton = &NC_DrawMaxButton;
1233 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1237 BOOL oldstate = pressed;
1239 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1240 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1242 if(msg.message == WM_LBUTTONUP)
1245 if(msg.message != WM_MOUSEMOVE)
1248 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1249 if (pressed != oldstate)
1250 (*paintButton)( hwnd, hdc, pressed, FALSE);
1254 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1257 ReleaseDC( hwnd, hdc );
1259 /* If the item minimize or maximize of the sysmenu are not there */
1260 /* or if the style is not present, do nothing */
1261 if ((!pressed) || (state == 0xFFFFFFFF))
1264 if (wParam == HTMINBUTTON)
1265 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1267 SendMessageA( hwnd, WM_SYSCOMMAND,
1268 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1271 /***********************************************************************
1272 * NC_TrackCloseButton
1274 * Track a mouse button press on the Win95 close button.
1276 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1280 BOOL pressed = TRUE;
1281 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1287 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1289 /* If the item close of the sysmenu is disabled or not there do nothing */
1290 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1293 hdc = GetWindowDC( hwnd );
1297 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1301 BOOL oldstate = pressed;
1303 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1304 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1306 if(msg.message == WM_LBUTTONUP)
1309 if(msg.message != WM_MOUSEMOVE)
1312 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1313 if (pressed != oldstate)
1314 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1318 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1321 ReleaseDC( hwnd, hdc );
1322 if (!pressed) return;
1324 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1328 /***********************************************************************
1331 * Track a mouse button press on the horizontal or vertical scroll-bar.
1333 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1337 if ((wParam & 0xfff0) == SC_HSCROLL)
1339 if ((wParam & 0x0f) != HTHSCROLL) return;
1340 scrollbar = SB_HORZ;
1342 else /* SC_VSCROLL */
1344 if ((wParam & 0x0f) != HTVSCROLL) return;
1345 scrollbar = SB_VERT;
1347 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1351 /***********************************************************************
1352 * NC_HandleNCLButtonDown
1354 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1356 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1358 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1360 switch(wParam) /* Hit test */
1364 HWND top = GetAncestor( hwnd, GA_ROOT );
1366 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1367 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1372 if( style & WS_SYSMENU )
1374 if( !(style & WS_MINIMIZE) )
1376 HDC hDC = GetWindowDC(hwnd);
1377 NC_DrawSysButton( hwnd, hDC, TRUE );
1378 ReleaseDC( hwnd, hDC );
1380 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1385 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1389 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1393 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1398 NC_TrackMinMaxBox( hwnd, wParam );
1402 NC_TrackCloseButton (hwnd, wParam);
1414 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1415 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1417 /* But that is not what WinNT does. Instead it sends this. This
1418 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1419 * SC_MOUSEMENU into wParam.
1421 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1431 /***********************************************************************
1432 * NC_HandleNCLButtonDblClk
1434 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1436 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1439 * if this is an icon, send a restore since we are handling
1444 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1448 switch(wParam) /* Hit test */
1451 /* stop processing if WS_MAXIMIZEBOX is missing */
1452 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1453 SendMessageW( hwnd, WM_SYSCOMMAND,
1454 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1458 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
1459 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1463 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1467 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1474 /***********************************************************************
1475 * NC_HandleSysCommand
1477 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1479 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1481 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1483 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1486 switch (wParam & 0xfff0)
1490 if (USER_Driver.pSysCommandSizeMove)
1491 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
1495 if (hwnd == GetForegroundWindow())
1496 ShowOwnedPopups(hwnd,FALSE);
1497 ShowWindow( hwnd, SW_MINIMIZE );
1501 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1502 ShowOwnedPopups(hwnd,TRUE);
1503 ShowWindow( hwnd, SW_MAXIMIZE );
1507 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1508 ShowOwnedPopups(hwnd,TRUE);
1509 ShowWindow( hwnd, SW_RESTORE );
1513 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1519 pt.x = (short)LOWORD(lParam);
1520 pt.y = (short)HIWORD(lParam);
1521 NC_TrackScrollBar( hwnd, wParam, pt );
1528 pt.x = (short)LOWORD(lParam);
1529 pt.y = (short)HIWORD(lParam);
1530 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1535 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1539 WinExec( "taskman.exe", SW_SHOWNORMAL );
1543 if (wParam == SC_ABOUTWINE)
1545 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1548 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1549 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1550 FreeLibrary( hmodule );
1554 if (wParam == SC_PUTMARK)
1555 DPRINTF("Debug mark requested by user\n");
1562 FIXME("unimplemented!\n");
1568 /*************************************************************
1571 * Stub for the grayed button of the caption
1573 *************************************************************/
1575 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1581 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1586 hdcMask = CreateCompatibleDC (0);
1587 SelectObject (hdcMask, hMaskBmp);
1589 /* Draw the grayed bitmap using the mask */
1590 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1591 BitBlt (hdc, x, y, 12, 10,
1592 hdcMask, 0, 0, 0xB8074A);
1595 SelectObject (hdc, hOldBrush);
1596 DeleteObject(hMaskBmp);
1602 /***********************************************************************
1603 * GetTitleBarInfo (USER32.@)
1604 * TODO: Handle STATE_SYSTEM_PRESSED
1606 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1611 TRACE("(%p %p)\n", hwnd, tbi);
1613 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1614 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1615 SetLastError(ERROR_INVALID_PARAMETER);
1618 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1619 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1620 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1622 GetWindowRect(hwnd, &wndRect);
1624 tbi->rcTitleBar.top += wndRect.top;
1625 tbi->rcTitleBar.left += wndRect.left;
1626 tbi->rcTitleBar.right += wndRect.left;
1628 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1629 if(dwExStyle & WS_EX_TOOLWINDOW)
1630 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1632 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1633 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1636 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1637 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1638 * Under XP it seems to
1640 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1641 if(dwStyle & WS_CAPTION) {
1642 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1643 if(dwStyle & WS_SYSMENU) {
1644 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1645 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1646 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1649 if(!(dwStyle & WS_MINIMIZEBOX))
1650 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1651 if(!(dwStyle & WS_MAXIMIZEBOX))
1652 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1654 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1655 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1656 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1657 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1660 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1661 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1662 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1663 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1667 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;