2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "user_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
36 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
38 /* Some useful macros */
39 #define HAS_DLGFRAME(style,exStyle) \
40 (((exStyle) & WS_EX_DLGMODALFRAME) || \
41 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
43 #define HAS_THICKFRAME(style,exStyle) \
44 (((style) & WS_THICKFRAME) && \
45 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47 #define HAS_THINFRAME(style) \
48 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
50 #define HAS_BIGFRAME(style,exStyle) \
51 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
52 ((exStyle) & WS_EX_DLGMODALFRAME))
54 #define HAS_STATICOUTERFRAME(style,exStyle) \
55 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
58 #define HAS_ANYFRAME(style,exStyle) \
59 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
60 ((exStyle) & WS_EX_DLGMODALFRAME) || \
61 !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_MENU(hwnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
66 /******************************************************************************
69 * Computes the size of the "outside" parts of the window based on the
70 * parameters of the client area.
79 * "Outer" parts of a window means the whole window frame, caption and
80 * menu bar. It does not include "inner" parts of the frame like client
81 * edge, static edge or scroll bars.
83 *****************************************************************************/
86 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
89 if(style & WS_ICONIC) return;
91 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
94 adjust = 1; /* for the outer frame always present */
99 if ((exStyle & WS_EX_DLGMODALFRAME) ||
100 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
102 if (style & WS_THICKFRAME)
103 adjust += ( GetSystemMetrics (SM_CXFRAME)
104 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
105 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
106 (exStyle & WS_EX_DLGMODALFRAME))
107 adjust++; /* The other border */
109 InflateRect (rect, adjust, adjust);
111 if ((style & WS_CAPTION) == WS_CAPTION)
113 if (exStyle & WS_EX_TOOLWINDOW)
114 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
116 rect->top -= GetSystemMetrics(SM_CYCAPTION);
118 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
122 /******************************************************************************
125 * Computes the size of the "inside" part of the window based on the
126 * parameters of the client area.
134 * "Inner" part of a window means the window frame inside of the flat
135 * window frame. It includes the client edge, the static edge and the
138 *****************************************************************************/
141 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
143 if(style & WS_ICONIC) return;
145 if (exStyle & WS_EX_CLIENTEDGE)
146 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
148 if (style & WS_VSCROLL)
150 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
151 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
153 rect->right += GetSystemMetrics(SM_CXVSCROLL);
155 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
160 static HICON NC_IconForWindow( HWND hwnd )
163 WND *wndPtr = WIN_GetPtr( hwnd );
165 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
167 hIcon = wndPtr->hIconSmall;
168 if (!hIcon) hIcon = wndPtr->hIcon;
169 WIN_ReleasePtr( wndPtr );
171 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
172 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
174 /* If there is no hIcon specified and this is a modal dialog,
175 * get the default one.
177 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
178 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
182 /* Draws the bar part(ie the big rectangle) of the caption */
183 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
184 BOOL active, BOOL gradient)
188 TRIVERTEX vertices[6];
190 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
192 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
193 : COLOR_GRADIENTINACTIVECAPTION);
195 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
196 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
198 for (v = 0; v < 3; v++)
200 vertices[v].Red = GetRValue (colLeft) << 8;
201 vertices[v].Green = GetGValue (colLeft) << 8;
202 vertices[v].Blue = GetBValue (colLeft) << 8;
203 vertices[v].Alpha = 0x8000;
204 vertices[v+3].Red = GetRValue (colRight) << 8;
205 vertices[v+3].Green = GetGValue (colRight) << 8;
206 vertices[v+3].Blue = GetBValue (colRight) << 8;
207 vertices[v+3].Alpha = 0x8000;
210 if ((dwStyle & WS_SYSMENU)
211 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
212 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
214 /* area behind icon; solid filled with left color */
215 vertices[0].x = rect->left;
216 vertices[0].y = rect->top;
217 if (dwStyle & WS_SYSMENU)
219 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
221 vertices[1].x = vertices[0].x;
222 vertices[1].y = rect->bottom;
224 /* area behind text; gradient */
225 vertices[2].x = vertices[1].x;
226 vertices[2].y = rect->top;
227 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
228 vertices[3].y = rect->bottom;
230 /* area behind buttons; solid filled with right color */
231 vertices[4].x = vertices[3].x;
232 vertices[4].y = rect->top;
233 vertices[5].x = rect->right;
234 vertices[5].y = rect->bottom;
236 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
239 FillRect (hdc, rect, GetSysColorBrush (active ?
240 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
243 /***********************************************************************
244 * DrawCaption (USER32.@) Draws a caption bar
258 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
260 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
264 /***********************************************************************
265 * DrawCaptionTempA (USER32.@)
267 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
268 HICON hIcon, LPCSTR str, UINT uFlags)
274 if (!(uFlags & DC_TEXT) || !str)
275 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
277 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
278 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
280 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
281 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
282 HeapFree( GetProcessHeap (), 0, strW );
288 /***********************************************************************
289 * DrawCaptionTempW (USER32.@)
291 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
292 HICON hIcon, LPCWSTR str, UINT uFlags)
296 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
297 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
299 /* drawing background */
300 if (uFlags & DC_INBUTTON) {
301 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
303 if (uFlags & DC_ACTIVE) {
304 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
305 PatBlt (hdc, rc.left, rc.top,
306 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
307 SelectObject (hdc, hbr);
311 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
312 NC_DrawCaptionBar (hdc, &rc, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
317 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
321 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
323 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
324 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
325 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
326 rc.left += (rc.bottom - rc.top);
330 if (uFlags & DC_TEXT) {
333 if (uFlags & DC_INBUTTON)
334 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
335 else if (uFlags & DC_ACTIVE)
336 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
338 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
340 SetBkMode (hdc, TRANSPARENT);
343 hOldFont = SelectObject (hdc, hFont);
345 NONCLIENTMETRICSW nclm;
347 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
348 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
349 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
350 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
351 hOldFont = SelectObject (hdc, hNewFont);
355 DrawTextW (hdc, str, -1, &rc,
356 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
360 nLen = GetWindowTextW (hwnd, szText, 128);
361 DrawTextW (hdc, szText, nLen, &rc,
362 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
366 SelectObject (hdc, hOldFont);
368 DeleteObject (SelectObject (hdc, hOldFont));
371 /* drawing focus ??? */
373 FIXME("undocumented flag (0x2000)!\n");
379 /***********************************************************************
380 * AdjustWindowRect (USER32.@)
382 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
384 return AdjustWindowRectEx( rect, style, menu, 0 );
388 /***********************************************************************
389 * AdjustWindowRectEx (USER32.@)
391 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
393 /* Correct the window style */
394 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
395 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
396 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
397 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
399 TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect), style, menu, exStyle );
401 NC_AdjustRectOuter( rect, style, menu, exStyle );
402 NC_AdjustRectInner( rect, style, exStyle );
408 /***********************************************************************
409 * NC_HandleNCCalcSize
411 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
413 LRESULT NC_HandleNCCalcSize( HWND hwnd, WPARAM wparam, RECT *winRect )
415 RECT tmpRect = { 0, 0, 0, 0 };
417 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
418 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
419 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
424 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
425 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
429 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
431 winRect->left -= tmpRect.left;
432 winRect->top -= tmpRect.top;
433 winRect->right -= tmpRect.right;
434 winRect->bottom -= tmpRect.bottom;
436 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
438 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
439 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
442 MENU_GetMenuBarHeight( hwnd,
443 winRect->right - winRect->left,
444 -tmpRect.left, -tmpRect.top );
447 if( exStyle & WS_EX_CLIENTEDGE)
448 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
449 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
450 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
451 - GetSystemMetrics(SM_CYEDGE));
453 if (style & WS_VSCROLL)
454 if (winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL))
456 /* rectangle is in screen coords when wparam is false */
457 if (!wparam && (exStyle & WS_EX_LAYOUTRTL)) exStyle ^= WS_EX_LEFTSCROLLBAR;
459 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
460 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
462 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
465 if (style & WS_HSCROLL)
466 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
467 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
469 if (winRect->top > winRect->bottom)
470 winRect->bottom = winRect->top;
472 if (winRect->left > winRect->right)
473 winRect->right = winRect->left;
479 /***********************************************************************
482 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
483 * but without the borders (if any).
485 static void NC_GetInsideRect( HWND hwnd, enum coords_relative relative, RECT *rect,
486 DWORD style, DWORD ex_style )
488 WIN_GetRectangles( hwnd, relative, rect, NULL );
490 if (style & WS_ICONIC) return;
492 /* Remove frame from rectangle */
493 if (HAS_THICKFRAME( style, ex_style ))
495 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
497 else if (HAS_DLGFRAME( style, ex_style ))
499 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
501 else if (HAS_THINFRAME( style ))
503 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
506 /* We have additional border information if the window
507 * is a child (but not an MDI child) */
508 if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD))
510 if (ex_style & WS_EX_CLIENTEDGE)
511 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
512 if (ex_style & WS_EX_STATICEDGE)
513 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
518 /***********************************************************************
521 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
523 LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt )
526 DWORD style, ex_style;
528 TRACE("hwnd=%p pt=%d,%d\n", hwnd, pt.x, pt.y );
530 ScreenToClient( hwnd, &pt );
531 WIN_GetRectangles( hwnd, COORDS_CLIENT, &rect, &rcClient );
532 if (!PtInRect( &rect, pt )) return HTNOWHERE;
534 style = GetWindowLongW( hwnd, GWL_STYLE );
535 ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
536 if (style & WS_MINIMIZE) return HTCAPTION;
538 if (PtInRect( &rcClient, pt )) return HTCLIENT;
541 if (HAS_THICKFRAME( style, ex_style ))
543 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
544 if (!PtInRect( &rect, pt ))
546 /* Check top sizing border */
549 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
550 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
553 /* Check bottom sizing border */
554 if (pt.y >= rect.bottom)
556 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
557 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
560 /* Check left sizing border */
561 if (pt.x < rect.left)
563 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
564 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
567 /* Check right sizing border */
568 if (pt.x >= rect.right)
570 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
571 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
576 else /* No thick frame */
578 if (HAS_DLGFRAME( style, ex_style ))
579 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
580 else if (HAS_THINFRAME( style ))
581 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
582 if (!PtInRect( &rect, pt )) return HTBORDER;
587 if ((style & WS_CAPTION) == WS_CAPTION)
589 if (ex_style & WS_EX_TOOLWINDOW)
590 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
592 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
593 if (!PtInRect( &rect, pt ))
595 BOOL min_or_max_box = (style & WS_MAXIMIZEBOX) ||
596 (style & WS_MINIMIZEBOX);
597 /* Check system menu */
598 if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW))
600 if (NC_IconForWindow(hwnd)) rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
602 if (pt.x < rect.left) return HTSYSMENU;
604 /* Check close button */
605 if (style & WS_SYSMENU)
606 rect.right -= GetSystemMetrics(SM_CYCAPTION);
607 if (pt.x > rect.right) return HTCLOSE;
609 /* Check maximize box */
610 /* In win95 there is automatically a Maximize button when there is a minimize one*/
611 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
612 rect.right -= GetSystemMetrics(SM_CXSIZE);
613 if (pt.x > rect.right) return HTMAXBUTTON;
615 /* Check minimize box */
616 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
617 if (min_or_max_box && !(ex_style & WS_EX_TOOLWINDOW))
618 rect.right -= GetSystemMetrics(SM_CXSIZE);
620 if (pt.x > rect.right) return HTMINBUTTON;
625 /* Check vertical scroll bar */
627 if (style & WS_VSCROLL)
629 if((ex_style & WS_EX_LEFTSCROLLBAR) != 0)
630 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
632 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
633 if (PtInRect( &rcClient, pt )) return HTVSCROLL;
636 /* Check horizontal scroll bar */
638 if (style & WS_HSCROLL)
640 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
641 if (PtInRect( &rcClient, pt ))
644 if ((style & WS_VSCROLL) &&
645 ((((ex_style & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
646 (((ex_style & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
654 if (HAS_MENU( hwnd, style ))
656 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rcClient.right))
660 /* Has to return HTNOWHERE if nothing was found
661 Could happen when a window has a customized non client area */
666 /******************************************************************************
670 * Draws the system icon.
672 *****************************************************************************/
673 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
675 HICON hIcon = NC_IconForWindow( hwnd );
680 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
681 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
683 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
684 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
685 GetSystemMetrics(SM_CXSMICON),
686 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
692 /******************************************************************************
696 * Draws the close button.
698 * If bGrayed is true, then draw a disabled Close button
700 *****************************************************************************/
702 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
705 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
706 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
708 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
710 /* A tool window has a smaller Close button */
711 if (ex_style & WS_EX_TOOLWINDOW)
713 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
714 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
715 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
717 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
718 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
719 rect.bottom = rect.top + iBmpHeight;
720 rect.right = rect.left + iBmpWidth;
724 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
725 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
729 DrawFrameControl( hdc, &rect, DFC_CAPTION,
731 (down ? DFCS_PUSHED : 0) |
732 (bGrayed ? DFCS_INACTIVE : 0)) );
735 /******************************************************************************
738 * Draws the maximize button for windows.
739 * If bGrayed is true, then draw a disabled Maximize button
741 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
745 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
746 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
748 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
749 if (ex_style & WS_EX_TOOLWINDOW) return;
751 flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
753 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
754 if (style & WS_SYSMENU)
755 rect.right -= GetSystemMetrics(SM_CXSIZE);
756 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
757 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
760 if (down) flags |= DFCS_PUSHED;
761 if (bGrayed) flags |= DFCS_INACTIVE;
762 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
765 /******************************************************************************
768 * Draws the minimize button for windows.
769 * If bGrayed is true, then draw a disabled Minimize button
771 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
774 UINT flags = DFCS_CAPTIONMIN;
775 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
776 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
778 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
779 if (ex_style & WS_EX_TOOLWINDOW) return;
781 NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
782 if (style & WS_SYSMENU)
783 rect.right -= GetSystemMetrics(SM_CXSIZE);
784 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
785 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
786 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
787 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 2;
790 if (down) flags |= DFCS_PUSHED;
791 if (bGrayed) flags |= DFCS_INACTIVE;
792 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
795 /******************************************************************************
799 * Draw a window frame inside the given rectangle, and update the rectangle.
802 * Many. First, just what IS a frame in Win95? Note that the 3D look
803 * on the outer edge is handled by NC_DoNCPaint. As is the inner
804 * edge. The inner rectangle just inside the frame is handled by the
807 * In short, for most people, this function should be a nop (unless
808 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
809 * them lately, but just to get this code right). Even so, it doesn't
810 * appear to be so. It's being worked on...
812 *****************************************************************************/
814 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
818 /* Firstly the "thick" frame */
819 if (style & WS_THICKFRAME)
821 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
822 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
824 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
825 COLOR_INACTIVEBORDER) );
827 PatBlt( hdc, rect->left, rect->top,
828 rect->right - rect->left, height, PATCOPY );
829 PatBlt( hdc, rect->left, rect->top,
830 width, rect->bottom - rect->top, PATCOPY );
831 PatBlt( hdc, rect->left, rect->bottom - 1,
832 rect->right - rect->left, -height, PATCOPY );
833 PatBlt( hdc, rect->right - 1, rect->top,
834 -width, rect->bottom - rect->top, PATCOPY );
836 InflateRect( rect, -width, -height );
839 /* Now the other bit of the frame */
840 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
841 (exStyle & WS_EX_DLGMODALFRAME))
843 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
844 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
845 /* This should give a value of 1 that should also work for a border */
847 SelectObject( hdc, GetSysColorBrush(
848 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
850 (exStyle & WS_EX_STATICEDGE) ?
852 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
858 PatBlt( hdc, rect->left, rect->top,
859 rect->right - rect->left, height, PATCOPY );
860 PatBlt( hdc, rect->left, rect->top,
861 width, rect->bottom - rect->top, PATCOPY );
862 PatBlt( hdc, rect->left, rect->bottom - 1,
863 rect->right - rect->left, -height, PATCOPY );
864 PatBlt( hdc, rect->right - 1, rect->top,
865 -width, rect->bottom - rect->top, PATCOPY );
867 InflateRect( rect, -width, -height );
872 /******************************************************************************
876 * Draw the window caption for windows.
877 * The correct pen for the window frame must be selected in the DC.
879 *****************************************************************************/
881 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
882 DWORD exStyle, BOOL active )
888 BOOL gradient = FALSE;
890 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
891 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
892 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
893 COLOR_WINDOWFRAME : COLOR_3DFACE) );
894 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
895 LineTo( hdc, r.right, r.bottom - 1 );
896 SelectObject( hdc, hPrevPen );
899 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
900 NC_DrawCaptionBar (hdc, &r, style, active, gradient);
902 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
903 if (NC_DrawSysButton (hwnd, hdc, FALSE))
904 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
907 if (style & WS_SYSMENU)
911 /* Go get the sysmenu */
912 hSysMenu = GetSystemMenu(hwnd, FALSE);
913 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
915 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
916 NC_DrawCloseButton (hwnd, hdc, FALSE,
917 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
918 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
920 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
922 /* In win95 the two buttons are always there */
923 /* But if the menu item is not in the menu they're disabled*/
925 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
926 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
928 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
929 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
933 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
935 NONCLIENTMETRICSW nclm;
936 HFONT hFont, hOldFont;
937 nclm.cbSize = sizeof(nclm);
938 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
939 if (exStyle & WS_EX_TOOLWINDOW)
940 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
942 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
943 hOldFont = SelectObject (hdc, hFont);
944 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
945 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
946 SetBkMode( hdc, TRANSPARENT );
948 DrawTextW( hdc, buffer, -1, &r,
949 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
950 DeleteObject (SelectObject (hdc, hOldFont));
955 /******************************************************************************
958 * Paint the non-client area for windows.
960 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
963 RECT rfuzz, rect, rectClip;
966 DWORD dwStyle, dwExStyle;
971 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
972 dwStyle = wndPtr->dwStyle;
973 dwExStyle = wndPtr->dwExStyle;
974 flags = wndPtr->flags;
975 WIN_ReleasePtr( wndPtr );
977 if ( dwStyle & WS_MINIMIZE ||
978 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
980 active = flags & WIN_NCACTIVATED;
982 TRACE("%p %d\n", hwnd, active );
984 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
985 the call to GetDCEx implying that it is allowed not to use it either.
986 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
987 will cause clipRgn to be deleted after ReleaseDC().
988 Now, how is the "system" supposed to tell what happened?
991 WIN_GetRectangles( hwnd, COORDS_SCREEN, NULL, &rectClient );
992 hrgn = CreateRectRgnIndirect( &rectClient );
996 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
997 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1001 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1006 WIN_GetRectangles( hwnd, COORDS_WINDOW, &rect, NULL );
1007 GetClipBox( hdc, &rectClip );
1009 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1011 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1012 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1014 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1015 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1018 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1020 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1023 if (dwExStyle & WS_EX_TOOLWINDOW) {
1024 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1025 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1028 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1029 rect.top += GetSystemMetrics(SM_CYCAPTION);
1031 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1032 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1035 if (HAS_MENU( hwnd, dwStyle ))
1038 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1040 TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r));
1042 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1045 TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect));
1047 if (dwExStyle & WS_EX_CLIENTEDGE)
1048 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1050 /* Draw the scroll-bars */
1052 if (dwStyle & WS_VSCROLL)
1053 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1054 if (dwStyle & WS_HSCROLL)
1055 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1057 /* Draw the "size-box" */
1058 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1061 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1062 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1064 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1065 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1066 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1069 ReleaseDC( hwnd, hdc );
1075 /***********************************************************************
1078 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1080 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1082 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1084 if( dwStyle & WS_VISIBLE )
1086 if( dwStyle & WS_MINIMIZE )
1087 WINPOS_RedrawIconTitle( hwnd );
1089 NC_DoNCPaint( hwnd, clip, FALSE );
1095 /***********************************************************************
1096 * NC_HandleNCActivate
1098 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1100 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam )
1102 WND* wndPtr = WIN_GetPtr( hwnd );
1104 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1106 /* Lotus Notes draws menu descriptions in the caption of its main
1107 * window. When it wants to restore original "system" view, it just
1108 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1109 * attempt to minimize redrawings lead to a not restored caption.
1111 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1112 else wndPtr->flags &= ~WIN_NCACTIVATED;
1113 WIN_ReleasePtr( wndPtr );
1115 /* This isn't documented but is reproducible in at least XP SP2 and
1116 * Outlook 2007 depends on it
1121 WINPOS_RedrawIconTitle( hwnd );
1123 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1130 /***********************************************************************
1131 * NC_HandleSetCursor
1133 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1135 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1137 hwnd = WIN_GetFullHandle( (HWND)wParam );
1139 switch((short)LOWORD(lParam))
1143 WORD msg = HIWORD( lParam );
1144 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1145 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1152 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1162 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1166 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1170 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1174 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1177 /* Default cursor: arrow */
1178 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1181 /***********************************************************************
1184 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1186 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1189 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
1190 DWORD ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE );
1192 NC_GetInsideRect( hwnd, COORDS_CLIENT, rect, style, ex_style );
1193 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1194 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1195 MapWindowPoints( hwnd, 0, (POINT *)rect, 2 );
1199 /***********************************************************************
1202 * Track a mouse button press on the minimize or maximize box.
1204 * The big difference between 3.1 and 95 is the disabled button state.
1205 * In win95 the system button can be disabled, so it can ignore the mouse
1209 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1212 HDC hdc = GetWindowDC( hwnd );
1213 BOOL pressed = TRUE;
1215 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1216 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1218 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1220 if (wParam == HTMINBUTTON)
1222 /* If the style is not present, do nothing */
1223 if (!(wndStyle & WS_MINIMIZEBOX))
1226 /* Check if the sysmenu item for minimize is there */
1227 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1229 paintButton = NC_DrawMinButton;
1233 /* If the style is not present, do nothing */
1234 if (!(wndStyle & WS_MAXIMIZEBOX))
1237 /* Check if the sysmenu item for maximize is there */
1238 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1240 paintButton = NC_DrawMaxButton;
1245 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1249 BOOL oldstate = pressed;
1251 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1252 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1254 if(msg.message == WM_LBUTTONUP)
1257 if(msg.message != WM_MOUSEMOVE)
1260 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1261 if (pressed != oldstate)
1262 (*paintButton)( hwnd, hdc, pressed, FALSE);
1266 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1269 ReleaseDC( hwnd, hdc );
1271 /* If the item minimize or maximize of the sysmenu are not there */
1272 /* or if the style is not present, do nothing */
1273 if ((!pressed) || (state == 0xFFFFFFFF))
1276 if (wParam == HTMINBUTTON)
1277 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1279 SendMessageW( hwnd, WM_SYSCOMMAND,
1280 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1283 /***********************************************************************
1284 * NC_TrackCloseButton
1286 * Track a mouse button press on the Win95 close button.
1288 static void NC_TrackCloseButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1292 BOOL pressed = TRUE;
1293 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1299 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1301 /* If the item close of the sysmenu is disabled or not there do nothing */
1302 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1305 hdc = GetWindowDC( hwnd );
1309 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1313 BOOL oldstate = pressed;
1315 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1316 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1318 if(msg.message == WM_LBUTTONUP)
1321 if(msg.message != WM_MOUSEMOVE)
1324 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1325 if (pressed != oldstate)
1326 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1330 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1333 ReleaseDC( hwnd, hdc );
1334 if (!pressed) return;
1336 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1340 /***********************************************************************
1343 * Track a mouse button press on the horizontal or vertical scroll-bar.
1345 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1349 if ((wParam & 0xfff0) == SC_HSCROLL)
1351 if ((wParam & 0x0f) != HTHSCROLL) return;
1352 scrollbar = SB_HORZ;
1354 else /* SC_VSCROLL */
1356 if ((wParam & 0x0f) != HTVSCROLL) return;
1357 scrollbar = SB_VERT;
1359 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1363 /***********************************************************************
1364 * NC_HandleNCLButtonDown
1366 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1368 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1370 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1372 switch(wParam) /* Hit test */
1376 HWND top = GetAncestor( hwnd, GA_ROOT );
1378 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1379 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1384 if( style & WS_SYSMENU )
1386 if( !(style & WS_MINIMIZE) )
1388 HDC hDC = GetWindowDC(hwnd);
1389 NC_DrawSysButton( hwnd, hDC, TRUE );
1390 ReleaseDC( hwnd, hDC );
1392 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1397 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1401 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1405 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1410 NC_TrackMinMaxBox( hwnd, wParam );
1414 NC_TrackCloseButton (hwnd, wParam, lParam);
1426 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1427 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1429 /* But that is not what WinNT does. Instead it sends this. This
1430 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1431 * SC_MOUSEMENU into wParam.
1433 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1443 /***********************************************************************
1444 * NC_HandleNCLButtonDblClk
1446 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1448 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1451 * if this is an icon, send a restore since we are handling
1456 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1460 switch(wParam) /* Hit test */
1463 /* stop processing if WS_MAXIMIZEBOX is missing */
1464 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1465 SendMessageW( hwnd, WM_SYSCOMMAND,
1466 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1471 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1472 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1474 /* If the item close of the sysmenu is disabled or not there do nothing */
1475 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1478 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1483 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1487 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1494 /***********************************************************************
1495 * NC_HandleSysCommand
1497 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1499 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1501 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1503 if (!IsWindowEnabled( hwnd )) return 0;
1505 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1508 if (!USER_Driver->pSysCommand( hwnd, wParam, lParam ))
1511 switch (wParam & 0xfff0)
1515 WINPOS_SysCommandSizeMove( hwnd, wParam );
1519 if (hwnd == GetActiveWindow())
1520 ShowOwnedPopups(hwnd,FALSE);
1521 ShowWindow( hwnd, SW_MINIMIZE );
1525 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1526 ShowOwnedPopups(hwnd,TRUE);
1527 ShowWindow( hwnd, SW_MAXIMIZE );
1531 if (IsIconic(hwnd) && hwnd == GetActiveWindow())
1532 ShowOwnedPopups(hwnd,TRUE);
1533 ShowWindow( hwnd, SW_RESTORE );
1537 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1543 pt.x = (short)LOWORD(lParam);
1544 pt.y = (short)HIWORD(lParam);
1545 NC_TrackScrollBar( hwnd, wParam, pt );
1552 pt.x = (short)LOWORD(lParam);
1553 pt.y = (short)HIWORD(lParam);
1554 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1559 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1563 WinExec( "taskman.exe", SW_SHOWNORMAL );
1567 if (wParam == SC_ABOUTWINE)
1569 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1572 BOOL (WINAPI *aboutproc)(HWND, LPCSTR, LPCSTR, HICON);
1574 aboutproc = (void *)GetProcAddress( hmodule, "ShellAboutA" );
1575 if (aboutproc) aboutproc( hwnd, PACKAGE_STRING, NULL, 0 );
1576 FreeLibrary( hmodule );
1585 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1591 /***********************************************************************
1592 * GetTitleBarInfo (USER32.@)
1593 * TODO: Handle STATE_SYSTEM_PRESSED
1595 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1599 TRACE("(%p %p)\n", hwnd, tbi);
1602 SetLastError(ERROR_NOACCESS);
1606 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1607 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1608 SetLastError(ERROR_INVALID_PARAMETER);
1611 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1612 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1613 NC_GetInsideRect(hwnd, COORDS_SCREEN, &tbi->rcTitleBar, dwStyle, dwExStyle);
1615 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1616 if(dwExStyle & WS_EX_TOOLWINDOW)
1617 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1619 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1620 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1623 ZeroMemory(tbi->rgstate, sizeof(tbi->rgstate));
1624 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1625 * Under XP it seems to
1627 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1628 if(dwStyle & WS_CAPTION) {
1629 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1630 if(dwStyle & WS_SYSMENU) {
1631 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1632 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1633 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1636 if(!(dwStyle & WS_MINIMIZEBOX))
1637 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1638 if(!(dwStyle & WS_MAXIMIZEBOX))
1639 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1641 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1642 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1643 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1644 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1647 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1648 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1649 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1650 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1654 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;