qmgrprxy: Queue manager proxy generated using an IDL compiler and bits.idl.
[wine/multimedia.git] / dlls / user32 / nonclient.c
blob45ac8cf2a6f8ec39bbcc1100c37d96a9ce4e267e
1 /*
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
21 #include "config.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "win.h"
29 #include "user_private.h"
30 #include "controls.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
35 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
36 0x55, 0x50,
37 0xAA, 0xA0,
38 0x55, 0x50,
39 0xAA, 0xA0,
40 0x55, 0x50,
41 0xAA, 0xA0,
42 0x55, 0x50,
43 0xAA, 0xA0,
44 0x55, 0x50};
46 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
47 #define SC_PUTMARK (SC_SCREENSAVE+2)
49 /* Some useful macros */
50 #define HAS_DLGFRAME(style,exStyle) \
51 (((exStyle) & WS_EX_DLGMODALFRAME) || \
52 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
54 #define HAS_THICKFRAME(style,exStyle) \
55 (((style) & WS_THICKFRAME) && \
56 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
58 #define HAS_THINFRAME(style) \
59 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
61 #define HAS_BIGFRAME(style,exStyle) \
62 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
63 ((exStyle) & WS_EX_DLGMODALFRAME))
65 #define HAS_STATICOUTERFRAME(style,exStyle) \
66 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
67 WS_EX_STATICEDGE)
69 #define HAS_ANYFRAME(style,exStyle) \
70 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
71 ((exStyle) & WS_EX_DLGMODALFRAME) || \
72 !((style) & (WS_CHILD | WS_POPUP)))
74 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
77 /******************************************************************************
78 * NC_AdjustRectOuter
80 * Computes the size of the "outside" parts of the window based on the
81 * parameters of the client area.
83 * PARAMS
84 * LPRECT rect
85 * DWORD style
86 * BOOL menu
87 * DWORD exStyle
89 * NOTES
90 * "Outer" parts of a window means the whole window frame, caption and
91 * menu bar. It does not include "inner" parts of the frame like client
92 * edge, static edge or scroll bars.
94 *****************************************************************************/
96 static void
97 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
99 int adjust;
100 if(style & WS_ICONIC) return;
102 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
103 WS_EX_STATICEDGE)
105 adjust = 1; /* for the outer frame always present */
107 else
109 adjust = 0;
110 if ((exStyle & WS_EX_DLGMODALFRAME) ||
111 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
113 if (style & WS_THICKFRAME)
114 adjust += ( GetSystemMetrics (SM_CXFRAME)
115 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
116 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
117 (exStyle & WS_EX_DLGMODALFRAME))
118 adjust++; /* The other border */
120 InflateRect (rect, adjust, adjust);
122 if ((style & WS_CAPTION) == WS_CAPTION)
124 if (exStyle & WS_EX_TOOLWINDOW)
125 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
126 else
127 rect->top -= GetSystemMetrics(SM_CYCAPTION);
129 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
133 /******************************************************************************
134 * NC_AdjustRectInner
136 * Computes the size of the "inside" part of the window based on the
137 * parameters of the client area.
139 * PARAMS
140 * LPRECT rect
141 * DWORD style
142 * DWORD exStyle
144 * NOTES
145 * "Inner" part of a window means the window frame inside of the flat
146 * window frame. It includes the client edge, the static edge and the
147 * scroll bars.
149 *****************************************************************************/
151 static void
152 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
154 if(style & WS_ICONIC) return;
156 if (exStyle & WS_EX_CLIENTEDGE)
157 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
159 if (style & WS_VSCROLL)
161 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
162 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
163 else
164 rect->right += GetSystemMetrics(SM_CXVSCROLL);
166 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
171 static HICON NC_IconForWindow( HWND hwnd )
173 HICON hIcon = 0;
174 WND *wndPtr = WIN_GetPtr( hwnd );
176 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
178 hIcon = wndPtr->hIconSmall;
179 if (!hIcon) hIcon = wndPtr->hIcon;
180 WIN_ReleasePtr( wndPtr );
182 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
183 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
185 /* If there is no hIcon specified and this is a modal dialog,
186 * get the default one.
188 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
189 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
190 return hIcon;
193 /* Draws the bar part(ie the big rectangle) of the caption */
194 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
195 BOOL active, BOOL gradient)
197 if (gradient)
199 TRIVERTEX vertices[6];
200 DWORD colLeft =
201 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
202 DWORD colRight =
203 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
204 : COLOR_GRADIENTINACTIVECAPTION);
205 int v;
206 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
207 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
209 for (v = 0; v < 3; v++)
211 vertices[v].Red = GetRValue (colLeft) << 8;
212 vertices[v].Green = GetGValue (colLeft) << 8;
213 vertices[v].Blue = GetBValue (colLeft) << 8;
214 vertices[v].Alpha = 0x8000;
215 vertices[v+3].Red = GetRValue (colRight) << 8;
216 vertices[v+3].Green = GetGValue (colRight) << 8;
217 vertices[v+3].Blue = GetBValue (colRight) << 8;
218 vertices[v+3].Alpha = 0x8000;
221 if ((dwStyle & WS_SYSMENU)
222 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
223 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
225 /* area behind icon; solid filled with left color */
226 vertices[0].x = rect->left;
227 vertices[0].y = rect->top;
228 if (dwStyle & WS_SYSMENU)
229 vertices[1].x =
230 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
231 else
232 vertices[1].x = vertices[0].x;
233 vertices[1].y = rect->bottom;
235 /* area behind text; gradient */
236 vertices[2].x = vertices[1].x;
237 vertices[2].y = rect->top;
238 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
239 vertices[3].y = rect->bottom;
241 /* area behind buttons; solid filled with right color */
242 vertices[4].x = vertices[3].x;
243 vertices[4].y = rect->top;
244 vertices[5].x = rect->right;
245 vertices[5].y = rect->bottom;
247 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
249 else
250 FillRect (hdc, rect, GetSysColorBrush (active ?
251 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
254 /***********************************************************************
255 * DrawCaption (USER32.@) Draws a caption bar
257 * PARAMS
258 * hwnd [I]
259 * hdc [I]
260 * lpRect [I]
261 * uFlags [I]
263 * RETURNS
264 * Success:
265 * Failure:
268 BOOL WINAPI
269 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
271 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
275 /***********************************************************************
276 * DrawCaptionTempA (USER32.@)
278 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
279 HICON hIcon, LPCSTR str, UINT uFlags)
281 LPWSTR strW;
282 INT len;
283 BOOL ret = FALSE;
285 if (!(uFlags & DC_TEXT) || !str)
286 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
288 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
289 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
291 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
292 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
293 HeapFree( GetProcessHeap (), 0, strW );
295 return ret;
299 /***********************************************************************
300 * DrawCaptionTempW (USER32.@)
302 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
303 HICON hIcon, LPCWSTR str, UINT uFlags)
305 RECT rc = *rect;
307 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
308 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
310 /* drawing background */
311 if (uFlags & DC_INBUTTON) {
312 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
314 if (uFlags & DC_ACTIVE) {
315 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
316 PatBlt (hdc, rc.left, rc.top,
317 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
318 SelectObject (hdc, hbr);
321 else {
322 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
323 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
327 /* drawing icon */
328 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
329 POINT pt;
331 pt.x = rc.left + 2;
332 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
334 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
335 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
336 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
337 rc.left += (rc.bottom - rc.top);
340 /* drawing text */
341 if (uFlags & DC_TEXT) {
342 HFONT hOldFont;
344 if (uFlags & DC_INBUTTON)
345 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
346 else if (uFlags & DC_ACTIVE)
347 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
348 else
349 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
351 SetBkMode (hdc, TRANSPARENT);
353 if (hFont)
354 hOldFont = SelectObject (hdc, hFont);
355 else {
356 NONCLIENTMETRICSW nclm;
357 HFONT hNewFont;
358 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
359 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
360 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
361 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
362 hOldFont = SelectObject (hdc, hNewFont);
365 if (str)
366 DrawTextW (hdc, str, -1, &rc,
367 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
368 else {
369 WCHAR szText[128];
370 INT nLen;
371 nLen = GetWindowTextW (hwnd, szText, 128);
372 DrawTextW (hdc, szText, nLen, &rc,
373 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
376 if (hFont)
377 SelectObject (hdc, hOldFont);
378 else
379 DeleteObject (SelectObject (hdc, hOldFont));
382 /* drawing focus ??? */
383 if (uFlags & 0x2000)
384 FIXME("undocumented flag (0x2000)!\n");
386 return 0;
390 /***********************************************************************
391 * AdjustWindowRect (USER32.@)
393 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
395 return AdjustWindowRectEx( rect, style, menu, 0 );
399 /***********************************************************************
400 * AdjustWindowRectEx (USER32.@)
402 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
404 /* Correct the window style */
405 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
406 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
407 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
408 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
410 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
411 rect->left, rect->top, rect->right, rect->bottom,
412 style, menu, exStyle );
414 NC_AdjustRectOuter( rect, style, menu, exStyle );
415 NC_AdjustRectInner( rect, style, exStyle );
417 return TRUE;
421 /***********************************************************************
422 * NC_HandleNCCalcSize
424 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
426 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
428 RECT tmpRect = { 0, 0, 0, 0 };
429 LRESULT result = 0;
430 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
431 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
432 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
434 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
435 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
437 if (!IsIconic(hwnd))
439 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
441 winRect->left -= tmpRect.left;
442 winRect->top -= tmpRect.top;
443 winRect->right -= tmpRect.right;
444 winRect->bottom -= tmpRect.bottom;
446 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
448 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
449 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
451 winRect->top +=
452 MENU_GetMenuBarHeight( hwnd,
453 winRect->right - winRect->left,
454 -tmpRect.left, -tmpRect.top );
457 if( exStyle & WS_EX_CLIENTEDGE)
458 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
459 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
460 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
461 - GetSystemMetrics(SM_CYEDGE));
463 if (style & WS_VSCROLL)
464 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
465 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
466 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
467 else
468 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
471 if (style & WS_HSCROLL)
472 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
473 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
475 if (winRect->top > winRect->bottom)
476 winRect->bottom = winRect->top;
478 if (winRect->left > winRect->right)
479 winRect->right = winRect->left;
481 return result;
485 /***********************************************************************
486 * NC_GetInsideRect
488 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
489 * but without the borders (if any).
490 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
492 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
494 WND *wndPtr = WIN_GetPtr( hwnd );
496 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
498 rect->top = rect->left = 0;
499 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
500 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
502 if (wndPtr->dwStyle & WS_ICONIC) goto END;
504 /* Remove frame from rectangle */
505 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
507 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
509 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
511 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
513 else if (HAS_THINFRAME( wndPtr->dwStyle ))
515 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
518 /* We have additional border information if the window
519 * is a child (but not an MDI child) */
520 if ( (wndPtr->dwStyle & WS_CHILD) &&
521 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
523 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
524 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
525 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
526 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
529 END:
530 WIN_ReleasePtr( wndPtr );
534 /***********************************************************************
535 * NC_DoNCHitTest
537 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
539 * FIXME: Just a modified copy of the Win 3.1 version.
542 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
544 RECT rect, rcClient;
545 POINT ptClient;
547 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
549 GetWindowRect(wndPtr->hwndSelf, &rect );
550 if (!PtInRect( &rect, pt )) return HTNOWHERE;
552 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
554 /* Check client area */
555 ptClient = pt;
556 ScreenToClient( wndPtr->hwndSelf, &ptClient );
557 GetClientRect( wndPtr->hwndSelf, &rcClient );
558 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
560 /* Check borders */
561 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
563 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
564 if (!PtInRect( &rect, pt ))
566 /* Check top sizing border */
567 if (pt.y < rect.top)
569 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
570 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
571 return HTTOP;
573 /* Check bottom sizing border */
574 if (pt.y >= rect.bottom)
576 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
577 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
578 return HTBOTTOM;
580 /* Check left sizing border */
581 if (pt.x < rect.left)
583 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
584 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
585 return HTLEFT;
587 /* Check right sizing border */
588 if (pt.x >= rect.right)
590 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
591 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
592 return HTRIGHT;
596 else /* No thick frame */
598 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
599 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
600 else if (HAS_THINFRAME( wndPtr->dwStyle ))
601 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
602 if (!PtInRect( &rect, pt )) return HTBORDER;
605 /* Check caption */
607 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
609 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
610 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
611 else
612 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
613 if (!PtInRect( &rect, pt ))
615 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
616 (wndPtr->dwStyle & WS_MINIMIZEBOX);
617 /* Check system menu */
618 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
620 if (NC_IconForWindow(wndPtr->hwndSelf))
621 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
623 if (pt.x < rect.left) return HTSYSMENU;
625 /* Check close button */
626 if (wndPtr->dwStyle & WS_SYSMENU)
627 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
628 if (pt.x > rect.right) return HTCLOSE;
630 /* Check maximize box */
631 /* In win95 there is automatically a Maximize button when there is a minimize one*/
632 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
633 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
634 if (pt.x > rect.right) return HTMAXBUTTON;
636 /* Check minimize box */
637 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
638 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
639 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
641 if (pt.x > rect.right) return HTMINBUTTON;
642 return HTCAPTION;
646 /* Check vertical scroll bar */
648 if (wndPtr->dwStyle & WS_VSCROLL)
650 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
651 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
652 else
653 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
654 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
657 /* Check horizontal scroll bar */
659 if (wndPtr->dwStyle & WS_HSCROLL)
661 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
662 if (PtInRect( &rcClient, ptClient ))
664 /* Check size box */
665 if ((wndPtr->dwStyle & WS_VSCROLL) &&
666 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
667 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
668 return HTSIZE;
669 return HTHSCROLL;
673 /* Check menu bar */
675 if (HAS_MENU(wndPtr))
677 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
678 return HTMENU;
681 /* Has to return HTNOWHERE if nothing was found
682 Could happen when a window has a customized non client area */
683 return HTNOWHERE;
687 /***********************************************************************
688 * NC_HandleNCHitTest
690 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
692 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
694 LRESULT retvalue;
695 WND *wndPtr = WIN_GetPtr( hwnd );
697 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
699 retvalue = NC_DoNCHitTest (wndPtr, pt);
700 WIN_ReleasePtr( wndPtr );
701 return retvalue;
705 /******************************************************************************
707 * NC_DrawSysButton
709 * Draws the system icon.
711 *****************************************************************************/
712 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
714 HICON hIcon = NC_IconForWindow( hwnd );
716 if (hIcon)
718 RECT rect;
719 NC_GetInsideRect( hwnd, &rect );
720 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
721 GetSystemMetrics(SM_CXSMICON),
722 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
724 return (hIcon != 0);
728 /******************************************************************************
730 * NC_DrawCloseButton
732 * Draws the close button.
734 * If bGrayed is true, then draw a disabled Close button
736 *****************************************************************************/
738 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
740 RECT rect;
742 NC_GetInsideRect( hwnd, &rect );
744 /* A tool window has a smaller Close button */
745 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
747 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
748 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
749 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
751 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
752 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
753 rect.bottom = rect.top + iBmpHeight;
754 rect.right = rect.left + iBmpWidth;
756 else
758 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
759 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
760 rect.top += 2;
761 rect.right -= 2;
763 DrawFrameControl( hdc, &rect, DFC_CAPTION,
764 (DFCS_CAPTIONCLOSE |
765 (down ? DFCS_PUSHED : 0) |
766 (bGrayed ? DFCS_INACTIVE : 0)) );
769 /******************************************************************************
770 * NC_DrawMaxButton
772 * Draws the maximize button for windows.
773 * If bGrayed is true, then draw a disabled Maximize button
775 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
777 RECT rect;
778 UINT flags;
780 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
781 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
782 return;
784 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
786 NC_GetInsideRect( hwnd, &rect );
787 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
788 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
789 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
790 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
791 rect.top += 2;
792 rect.right -= 2;
793 if (down) flags |= DFCS_PUSHED;
794 if (bGrayed) flags |= DFCS_INACTIVE;
795 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
798 /******************************************************************************
799 * NC_DrawMinButton
801 * Draws the minimize button for windows.
802 * If bGrayed is true, then draw a disabled Minimize button
804 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
806 RECT rect;
807 UINT flags = DFCS_CAPTIONMIN;
808 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
810 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
811 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
812 return;
814 NC_GetInsideRect( hwnd, &rect );
815 if (style & WS_SYSMENU)
816 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
817 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
818 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
819 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
820 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
821 rect.top += 2;
822 rect.right -= 2;
823 if (down) flags |= DFCS_PUSHED;
824 if (bGrayed) flags |= DFCS_INACTIVE;
825 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
828 /******************************************************************************
830 * NC_DrawFrame
832 * Draw a window frame inside the given rectangle, and update the rectangle.
834 * Bugs
835 * Many. First, just what IS a frame in Win95? Note that the 3D look
836 * on the outer edge is handled by NC_DoNCPaint. As is the inner
837 * edge. The inner rectangle just inside the frame is handled by the
838 * Caption code.
840 * In short, for most people, this function should be a nop (unless
841 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
842 * them lately, but just to get this code right). Even so, it doesn't
843 * appear to be so. It's being worked on...
845 *****************************************************************************/
847 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
849 INT width, height;
851 /* Firstly the "thick" frame */
852 if (style & WS_THICKFRAME)
854 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
855 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
857 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
858 COLOR_INACTIVEBORDER) );
859 /* Draw frame */
860 PatBlt( hdc, rect->left, rect->top,
861 rect->right - rect->left, height, PATCOPY );
862 PatBlt( hdc, rect->left, rect->top,
863 width, rect->bottom - rect->top, PATCOPY );
864 PatBlt( hdc, rect->left, rect->bottom - 1,
865 rect->right - rect->left, -height, PATCOPY );
866 PatBlt( hdc, rect->right - 1, rect->top,
867 -width, rect->bottom - rect->top, PATCOPY );
869 InflateRect( rect, -width, -height );
872 /* Now the other bit of the frame */
873 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
874 (exStyle & WS_EX_DLGMODALFRAME))
876 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
877 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
878 /* This should give a value of 1 that should also work for a border */
880 SelectObject( hdc, GetSysColorBrush(
881 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
882 COLOR_3DFACE :
883 (exStyle & WS_EX_STATICEDGE) ?
884 COLOR_WINDOWFRAME :
885 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
886 COLOR_3DFACE :
887 /* else */
888 COLOR_WINDOWFRAME));
890 /* Draw frame */
891 PatBlt( hdc, rect->left, rect->top,
892 rect->right - rect->left, height, PATCOPY );
893 PatBlt( hdc, rect->left, rect->top,
894 width, rect->bottom - rect->top, PATCOPY );
895 PatBlt( hdc, rect->left, rect->bottom - 1,
896 rect->right - rect->left, -height, PATCOPY );
897 PatBlt( hdc, rect->right - 1, rect->top,
898 -width, rect->bottom - rect->top, PATCOPY );
900 InflateRect( rect, -width, -height );
905 /******************************************************************************
907 * NC_DrawCaption
909 * Draw the window caption for windows.
910 * The correct pen for the window frame must be selected in the DC.
912 *****************************************************************************/
914 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
915 DWORD exStyle, BOOL active )
917 RECT r = *rect;
918 WCHAR buffer[256];
919 HPEN hPrevPen;
920 HMENU hSysMenu;
921 BOOL gradient = FALSE;
923 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
924 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
925 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
926 COLOR_WINDOWFRAME : COLOR_3DFACE) );
927 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
928 LineTo( hdc, r.right, r.bottom - 1 );
929 SelectObject( hdc, hPrevPen );
930 r.bottom--;
932 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
933 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
935 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
936 if (NC_DrawSysButton (hwnd, hdc, FALSE))
937 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
940 if (style & WS_SYSMENU)
942 UINT state;
944 /* Go get the sysmenu */
945 hSysMenu = GetSystemMenu(hwnd, FALSE);
946 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
948 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
949 NC_DrawCloseButton (hwnd, hdc, FALSE,
950 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
951 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
953 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
955 /* In win95 the two buttons are always there */
956 /* But if the menu item is not in the menu they're disabled*/
958 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
959 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
961 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
962 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
966 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
968 NONCLIENTMETRICSW nclm;
969 HFONT hFont, hOldFont;
970 nclm.cbSize = sizeof(nclm);
971 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
972 if (exStyle & WS_EX_TOOLWINDOW)
973 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
974 else
975 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
976 hOldFont = SelectObject (hdc, hFont);
977 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
978 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
979 SetBkMode( hdc, TRANSPARENT );
980 r.left += 2;
981 DrawTextW( hdc, buffer, -1, &r,
982 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
983 DeleteObject (SelectObject (hdc, hOldFont));
988 /******************************************************************************
989 * NC_DoNCPaint
991 * Paint the non-client area for windows.
993 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
995 HDC hdc;
996 RECT rfuzz, rect, rectClip;
997 BOOL active;
998 WND *wndPtr;
999 DWORD dwStyle, dwExStyle;
1000 WORD flags;
1001 HRGN hrgn;
1002 RECT rectClient, rectWindow;
1003 int has_menu;
1005 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1006 has_menu = HAS_MENU(wndPtr);
1007 dwStyle = wndPtr->dwStyle;
1008 dwExStyle = wndPtr->dwExStyle;
1009 flags = wndPtr->flags;
1010 rectWindow = wndPtr->rectWindow;
1011 WIN_ReleasePtr( wndPtr );
1013 if ( dwStyle & WS_MINIMIZE ||
1014 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1016 active = flags & WIN_NCACTIVATED;
1018 TRACE("%p %d\n", hwnd, active );
1020 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1021 the call to GetDCEx implying that it is allowed not to use it either.
1022 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1023 will cause clipRgn to be deleted after ReleaseDC().
1024 Now, how is the "system" supposed to tell what happened?
1027 GetClientRect( hwnd, &rectClient );
1028 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1029 hrgn = CreateRectRgnIndirect( &rectClient );
1031 if (clip > (HRGN)1)
1033 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1034 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1036 else
1038 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1041 if (!hdc) return;
1043 rect.top = rect.left = 0;
1044 rect.right = rectWindow.right - rectWindow.left;
1045 rect.bottom = rectWindow.bottom - rectWindow.top;
1046 GetClipBox( hdc, &rectClip );
1048 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1050 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1051 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1053 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1054 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1057 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1059 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1061 RECT r = rect;
1062 if (dwExStyle & WS_EX_TOOLWINDOW) {
1063 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1064 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1066 else {
1067 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1068 rect.top += GetSystemMetrics(SM_CYCAPTION);
1070 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1071 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1074 if (has_menu)
1076 RECT r = rect;
1077 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1079 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1080 r.left, r.top, r.right, r.bottom);
1082 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1085 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1086 rect.left, rect.top, rect.right, rect.bottom );
1088 if (dwExStyle & WS_EX_CLIENTEDGE)
1089 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1091 /* Draw the scroll-bars */
1093 if (dwStyle & WS_VSCROLL)
1094 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1095 if (dwStyle & WS_HSCROLL)
1096 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1098 /* Draw the "size-box" */
1099 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1101 RECT r = rect;
1102 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1103 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1104 else
1105 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1106 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1107 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1110 ReleaseDC( hwnd, hdc );
1116 /***********************************************************************
1117 * NC_HandleNCPaint
1119 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1121 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1123 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1125 if( dwStyle & WS_VISIBLE )
1127 if( dwStyle & WS_MINIMIZE )
1128 WINPOS_RedrawIconTitle( hwnd );
1129 else
1130 NC_DoNCPaint( hwnd, clip, FALSE );
1132 return 0;
1136 /***********************************************************************
1137 * NC_HandleNCActivate
1139 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1141 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1143 WND* wndPtr = WIN_GetPtr( hwnd );
1145 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1147 /* Lotus Notes draws menu descriptions in the caption of its main
1148 * window. When it wants to restore original "system" view, it just
1149 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1150 * attempt to minimize redrawings lead to a not restored caption.
1152 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1153 else wndPtr->flags &= ~WIN_NCACTIVATED;
1154 WIN_ReleasePtr( wndPtr );
1156 if (IsIconic(hwnd))
1157 WINPOS_RedrawIconTitle( hwnd );
1158 else
1159 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1161 return TRUE;
1165 /***********************************************************************
1166 * NC_HandleSetCursor
1168 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1170 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1172 hwnd = WIN_GetFullHandle( (HWND)wParam );
1174 switch((short)LOWORD(lParam))
1176 case HTERROR:
1178 WORD msg = HIWORD( lParam );
1179 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1180 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1181 MessageBeep(0);
1183 break;
1185 case HTCLIENT:
1187 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1188 if(hCursor) {
1189 SetCursor(hCursor);
1190 return TRUE;
1192 return FALSE;
1195 case HTLEFT:
1196 case HTRIGHT:
1197 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1199 case HTTOP:
1200 case HTBOTTOM:
1201 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1203 case HTTOPLEFT:
1204 case HTBOTTOMRIGHT:
1205 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1207 case HTTOPRIGHT:
1208 case HTBOTTOMLEFT:
1209 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1212 /* Default cursor: arrow */
1213 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1216 /***********************************************************************
1217 * NC_GetSysPopupPos
1219 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1221 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1222 else
1224 WND *wndPtr = WIN_GetPtr( hwnd );
1225 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1227 NC_GetInsideRect( hwnd, rect );
1228 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1229 if (wndPtr->dwStyle & WS_CHILD)
1230 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1231 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1232 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1233 WIN_ReleasePtr( wndPtr );
1237 /***********************************************************************
1238 * NC_TrackMinMaxBox
1240 * Track a mouse button press on the minimize or maximize box.
1242 * The big difference between 3.1 and 95 is the disabled button state.
1243 * In win95 the system button can be disabled, so it can ignore the mouse
1244 * event.
1247 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1249 MSG msg;
1250 HDC hdc = GetWindowDC( hwnd );
1251 BOOL pressed = TRUE;
1252 UINT state;
1253 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1254 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1256 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1258 if (wParam == HTMINBUTTON)
1260 /* If the style is not present, do nothing */
1261 if (!(wndStyle & WS_MINIMIZEBOX))
1262 return;
1264 /* Check if the sysmenu item for minimize is there */
1265 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1267 paintButton = &NC_DrawMinButton;
1269 else
1271 /* If the style is not present, do nothing */
1272 if (!(wndStyle & WS_MAXIMIZEBOX))
1273 return;
1275 /* Check if the sysmenu item for maximize is there */
1276 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1278 paintButton = &NC_DrawMaxButton;
1281 SetCapture( hwnd );
1283 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1285 while(1)
1287 BOOL oldstate = pressed;
1289 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1290 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1292 if(msg.message == WM_LBUTTONUP)
1293 break;
1295 if(msg.message != WM_MOUSEMOVE)
1296 continue;
1298 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1299 if (pressed != oldstate)
1300 (*paintButton)( hwnd, hdc, pressed, FALSE);
1303 if(pressed)
1304 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1306 ReleaseCapture();
1307 ReleaseDC( hwnd, hdc );
1309 /* If the item minimize or maximize of the sysmenu are not there */
1310 /* or if the style is not present, do nothing */
1311 if ((!pressed) || (state == 0xFFFFFFFF))
1312 return;
1314 if (wParam == HTMINBUTTON)
1315 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1316 else
1317 SendMessageW( hwnd, WM_SYSCOMMAND,
1318 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1321 /***********************************************************************
1322 * NC_TrackCloseButton
1324 * Track a mouse button press on the Win95 close button.
1326 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1328 MSG msg;
1329 HDC hdc;
1330 BOOL pressed = TRUE;
1331 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1332 UINT state;
1334 if(hSysMenu == 0)
1335 return;
1337 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1339 /* If the item close of the sysmenu is disabled or not there do nothing */
1340 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1341 return;
1343 hdc = GetWindowDC( hwnd );
1345 SetCapture( hwnd );
1347 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1349 while(1)
1351 BOOL oldstate = pressed;
1353 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1354 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1356 if(msg.message == WM_LBUTTONUP)
1357 break;
1359 if(msg.message != WM_MOUSEMOVE)
1360 continue;
1362 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1363 if (pressed != oldstate)
1364 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1367 if(pressed)
1368 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1370 ReleaseCapture();
1371 ReleaseDC( hwnd, hdc );
1372 if (!pressed) return;
1374 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1378 /***********************************************************************
1379 * NC_TrackScrollBar
1381 * Track a mouse button press on the horizontal or vertical scroll-bar.
1383 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1385 INT scrollbar;
1387 if ((wParam & 0xfff0) == SC_HSCROLL)
1389 if ((wParam & 0x0f) != HTHSCROLL) return;
1390 scrollbar = SB_HORZ;
1392 else /* SC_VSCROLL */
1394 if ((wParam & 0x0f) != HTVSCROLL) return;
1395 scrollbar = SB_VERT;
1397 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1401 /***********************************************************************
1402 * NC_HandleNCLButtonDown
1404 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1406 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1408 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1410 switch(wParam) /* Hit test */
1412 case HTCAPTION:
1414 HWND top = GetAncestor( hwnd, GA_ROOT );
1416 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1417 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1418 break;
1421 case HTSYSMENU:
1422 if( style & WS_SYSMENU )
1424 if( !(style & WS_MINIMIZE) )
1426 HDC hDC = GetWindowDC(hwnd);
1427 NC_DrawSysButton( hwnd, hDC, TRUE );
1428 ReleaseDC( hwnd, hDC );
1430 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1432 break;
1434 case HTMENU:
1435 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1436 break;
1438 case HTHSCROLL:
1439 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1440 break;
1442 case HTVSCROLL:
1443 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1444 break;
1446 case HTMINBUTTON:
1447 case HTMAXBUTTON:
1448 NC_TrackMinMaxBox( hwnd, wParam );
1449 break;
1451 case HTCLOSE:
1452 NC_TrackCloseButton (hwnd, wParam);
1453 break;
1455 case HTLEFT:
1456 case HTRIGHT:
1457 case HTTOP:
1458 case HTTOPLEFT:
1459 case HTTOPRIGHT:
1460 case HTBOTTOM:
1461 case HTBOTTOMLEFT:
1462 case HTBOTTOMRIGHT:
1463 /* Old comment:
1464 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1465 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1467 /* But that is not what WinNT does. Instead it sends this. This
1468 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1469 * SC_MOUSEMENU into wParam.
1471 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1472 break;
1474 case HTBORDER:
1475 break;
1477 return 0;
1481 /***********************************************************************
1482 * NC_HandleNCLButtonDblClk
1484 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1486 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1489 * if this is an icon, send a restore since we are handling
1490 * a double click
1492 if (IsIconic(hwnd))
1494 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1495 return 0;
1498 switch(wParam) /* Hit test */
1500 case HTCAPTION:
1501 /* stop processing if WS_MAXIMIZEBOX is missing */
1502 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1503 SendMessageW( hwnd, WM_SYSCOMMAND,
1504 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1505 break;
1507 case HTSYSMENU:
1509 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1510 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1512 /* If the item close of the sysmenu is disabled or not there do nothing */
1513 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1514 break;
1516 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1517 break;
1520 case HTHSCROLL:
1521 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1522 break;
1524 case HTVSCROLL:
1525 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1526 break;
1528 return 0;
1532 /***********************************************************************
1533 * NC_HandleSysCommand
1535 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1537 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1539 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1541 if (!IsWindowEnabled( hwnd )) return 0;
1543 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1544 return 0;
1546 switch (wParam & 0xfff0)
1548 case SC_SIZE:
1549 case SC_MOVE:
1550 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1551 break;
1553 case SC_MINIMIZE:
1554 if (hwnd == GetForegroundWindow())
1555 ShowOwnedPopups(hwnd,FALSE);
1556 ShowWindow( hwnd, SW_MINIMIZE );
1557 break;
1559 case SC_MAXIMIZE:
1560 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1561 ShowOwnedPopups(hwnd,TRUE);
1562 ShowWindow( hwnd, SW_MAXIMIZE );
1563 break;
1565 case SC_RESTORE:
1566 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1567 ShowOwnedPopups(hwnd,TRUE);
1568 ShowWindow( hwnd, SW_RESTORE );
1569 break;
1571 case SC_CLOSE:
1572 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1574 case SC_VSCROLL:
1575 case SC_HSCROLL:
1577 POINT pt;
1578 pt.x = (short)LOWORD(lParam);
1579 pt.y = (short)HIWORD(lParam);
1580 NC_TrackScrollBar( hwnd, wParam, pt );
1582 break;
1584 case SC_MOUSEMENU:
1586 POINT pt;
1587 pt.x = (short)LOWORD(lParam);
1588 pt.y = (short)HIWORD(lParam);
1589 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1591 break;
1593 case SC_KEYMENU:
1594 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1595 break;
1597 case SC_TASKLIST:
1598 WinExec( "taskman.exe", SW_SHOWNORMAL );
1599 break;
1601 case SC_SCREENSAVE:
1602 if (wParam == SC_ABOUTWINE)
1604 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1605 if (hmodule)
1607 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1608 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1609 FreeLibrary( hmodule );
1612 else
1613 if (wParam == SC_PUTMARK)
1614 DPRINTF("Debug mark requested by user\n");
1615 break;
1617 case SC_HOTKEY:
1618 case SC_ARRANGE:
1619 case SC_NEXTWINDOW:
1620 case SC_PREVWINDOW:
1621 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1622 break;
1624 return 0;
1627 /***********************************************************************
1628 * GetTitleBarInfo (USER32.@)
1629 * TODO: Handle STATE_SYSTEM_PRESSED
1631 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1632 DWORD dwStyle;
1633 DWORD dwExStyle;
1634 RECT wndRect;
1636 TRACE("(%p %p)\n", hwnd, tbi);
1638 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1639 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1640 SetLastError(ERROR_INVALID_PARAMETER);
1641 return FALSE;
1643 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1644 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1645 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1647 GetWindowRect(hwnd, &wndRect);
1649 tbi->rcTitleBar.top += wndRect.top;
1650 tbi->rcTitleBar.left += wndRect.left;
1651 tbi->rcTitleBar.right += wndRect.left;
1653 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1654 if(dwExStyle & WS_EX_TOOLWINDOW)
1655 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1656 else {
1657 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1658 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1661 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1662 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1663 * Under XP it seems to
1665 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1666 if(dwStyle & WS_CAPTION) {
1667 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1668 if(dwStyle & WS_SYSMENU) {
1669 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1670 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1671 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1673 else {
1674 if(!(dwStyle & WS_MINIMIZEBOX))
1675 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1676 if(!(dwStyle & WS_MAXIMIZEBOX))
1677 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1679 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1680 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1681 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1682 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1684 else {
1685 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1686 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1687 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1688 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1691 else
1692 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1693 return TRUE;