wined3d: Don't create a pbo for system memory surfaces.
[wine/winequartzdrv.git] / dlls / user32 / nonclient.c
blobf93b94feff15609e5ebf131dcce36c40fa4f56f2
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 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
37 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
38 0x55, 0x50,
39 0xAA, 0xA0,
40 0x55, 0x50,
41 0xAA, 0xA0,
42 0x55, 0x50,
43 0xAA, 0xA0,
44 0x55, 0x50,
45 0xAA, 0xA0,
46 0x55, 0x50};
48 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
49 #define SC_PUTMARK (SC_SCREENSAVE+2)
51 /* Some useful macros */
52 #define HAS_DLGFRAME(style,exStyle) \
53 (((exStyle) & WS_EX_DLGMODALFRAME) || \
54 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
56 #define HAS_THICKFRAME(style,exStyle) \
57 (((style) & WS_THICKFRAME) && \
58 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
60 #define HAS_THINFRAME(style) \
61 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_BIGFRAME(style,exStyle) \
64 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
65 ((exStyle) & WS_EX_DLGMODALFRAME))
67 #define HAS_STATICOUTERFRAME(style,exStyle) \
68 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
69 WS_EX_STATICEDGE)
71 #define HAS_ANYFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME) || \
74 !((style) & (WS_CHILD | WS_POPUP)))
76 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
79 /******************************************************************************
80 * NC_AdjustRectOuter
82 * Computes the size of the "outside" parts of the window based on the
83 * parameters of the client area.
85 * PARAMS
86 * LPRECT rect
87 * DWORD style
88 * BOOL menu
89 * DWORD exStyle
91 * NOTES
92 * "Outer" parts of a window means the whole window frame, caption and
93 * menu bar. It does not include "inner" parts of the frame like client
94 * edge, static edge or scroll bars.
96 *****************************************************************************/
98 static void
99 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
101 int adjust;
102 if(style & WS_ICONIC) return;
104 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
105 WS_EX_STATICEDGE)
107 adjust = 1; /* for the outer frame always present */
109 else
111 adjust = 0;
112 if ((exStyle & WS_EX_DLGMODALFRAME) ||
113 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
115 if (style & WS_THICKFRAME)
116 adjust += ( GetSystemMetrics (SM_CXFRAME)
117 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
118 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
119 (exStyle & WS_EX_DLGMODALFRAME))
120 adjust++; /* The other border */
122 InflateRect (rect, adjust, adjust);
124 if ((style & WS_CAPTION) == WS_CAPTION)
126 if (exStyle & WS_EX_TOOLWINDOW)
127 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
128 else
129 rect->top -= GetSystemMetrics(SM_CYCAPTION);
131 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
135 /******************************************************************************
136 * NC_AdjustRectInner
138 * Computes the size of the "inside" part of the window based on the
139 * parameters of the client area.
141 * PARAMS
142 * LPRECT rect
143 * DWORD style
144 * DWORD exStyle
146 * NOTES
147 * "Inner" part of a window means the window frame inside of the flat
148 * window frame. It includes the client edge, the static edge and the
149 * scroll bars.
151 *****************************************************************************/
153 static void
154 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
156 if(style & WS_ICONIC) return;
158 if (exStyle & WS_EX_CLIENTEDGE)
159 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
161 if (style & WS_VSCROLL)
163 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
164 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
165 else
166 rect->right += GetSystemMetrics(SM_CXVSCROLL);
168 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
173 static HICON NC_IconForWindow( HWND hwnd )
175 HICON hIcon = 0;
176 WND *wndPtr = WIN_GetPtr( hwnd );
178 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
180 hIcon = wndPtr->hIconSmall;
181 if (!hIcon) hIcon = wndPtr->hIcon;
182 WIN_ReleasePtr( wndPtr );
184 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
185 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
187 /* If there is no hIcon specified and this is a modal dialog,
188 * get the default one.
190 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
191 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
192 return hIcon;
195 /* Draws the bar part(ie the big rectangle) of the caption */
196 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
197 BOOL active, BOOL gradient)
199 if (gradient)
201 TRIVERTEX vertices[6];
202 DWORD colLeft =
203 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
204 DWORD colRight =
205 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
206 : COLOR_GRADIENTINACTIVECAPTION);
207 int v;
208 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
209 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
211 for (v = 0; v < 3; v++)
213 vertices[v].Red = GetRValue (colLeft) << 8;
214 vertices[v].Green = GetGValue (colLeft) << 8;
215 vertices[v].Blue = GetBValue (colLeft) << 8;
216 vertices[v].Alpha = 0x8000;
217 vertices[v+3].Red = GetRValue (colRight) << 8;
218 vertices[v+3].Green = GetGValue (colRight) << 8;
219 vertices[v+3].Blue = GetBValue (colRight) << 8;
220 vertices[v+3].Alpha = 0x8000;
223 if ((dwStyle & WS_SYSMENU)
224 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
225 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
227 /* area behind icon; solid filled with left color */
228 vertices[0].x = rect->left;
229 vertices[0].y = rect->top;
230 if (dwStyle & WS_SYSMENU)
231 vertices[1].x =
232 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
233 else
234 vertices[1].x = vertices[0].x;
235 vertices[1].y = rect->bottom;
237 /* area behind text; gradient */
238 vertices[2].x = vertices[1].x;
239 vertices[2].y = rect->top;
240 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
241 vertices[3].y = rect->bottom;
243 /* area behind buttons; solid filled with right color */
244 vertices[4].x = vertices[3].x;
245 vertices[4].y = rect->top;
246 vertices[5].x = rect->right;
247 vertices[5].y = rect->bottom;
249 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
251 else
252 FillRect (hdc, rect, GetSysColorBrush (active ?
253 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
256 /***********************************************************************
257 * DrawCaption (USER32.@) Draws a caption bar
259 * PARAMS
260 * hwnd [I]
261 * hdc [I]
262 * lpRect [I]
263 * uFlags [I]
265 * RETURNS
266 * Success:
267 * Failure:
270 BOOL WINAPI
271 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
273 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
277 /***********************************************************************
278 * DrawCaptionTempA (USER32.@)
280 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
281 HICON hIcon, LPCSTR str, UINT uFlags)
283 LPWSTR strW;
284 INT len;
285 BOOL ret = FALSE;
287 if (!(uFlags & DC_TEXT) || !str)
288 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
290 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
291 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
293 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
294 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
295 HeapFree( GetProcessHeap (), 0, strW );
297 return ret;
301 /***********************************************************************
302 * DrawCaptionTempW (USER32.@)
304 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
305 HICON hIcon, LPCWSTR str, UINT uFlags)
307 RECT rc = *rect;
309 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
310 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
312 /* drawing background */
313 if (uFlags & DC_INBUTTON) {
314 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
316 if (uFlags & DC_ACTIVE) {
317 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
318 PatBlt (hdc, rc.left, rc.top,
319 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
320 SelectObject (hdc, hbr);
323 else {
324 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
325 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
329 /* drawing icon */
330 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
331 POINT pt;
333 pt.x = rc.left + 2;
334 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
336 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
337 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
338 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
339 rc.left += (rc.bottom - rc.top);
342 /* drawing text */
343 if (uFlags & DC_TEXT) {
344 HFONT hOldFont;
346 if (uFlags & DC_INBUTTON)
347 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
348 else if (uFlags & DC_ACTIVE)
349 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
350 else
351 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
353 SetBkMode (hdc, TRANSPARENT);
355 if (hFont)
356 hOldFont = SelectObject (hdc, hFont);
357 else {
358 NONCLIENTMETRICSW nclm;
359 HFONT hNewFont;
360 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
361 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
362 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
363 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
364 hOldFont = SelectObject (hdc, hNewFont);
367 if (str)
368 DrawTextW (hdc, str, -1, &rc,
369 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
370 else {
371 WCHAR szText[128];
372 INT nLen;
373 nLen = GetWindowTextW (hwnd, szText, 128);
374 DrawTextW (hdc, szText, nLen, &rc,
375 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
378 if (hFont)
379 SelectObject (hdc, hOldFont);
380 else
381 DeleteObject (SelectObject (hdc, hOldFont));
384 /* drawing focus ??? */
385 if (uFlags & 0x2000)
386 FIXME("undocumented flag (0x2000)!\n");
388 return 0;
392 /***********************************************************************
393 * AdjustWindowRect (USER32.@)
395 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
397 return AdjustWindowRectEx( rect, style, menu, 0 );
401 /***********************************************************************
402 * AdjustWindowRectEx (USER32.@)
404 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
406 /* Correct the window style */
407 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
408 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
409 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
410 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
412 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
413 rect->left, rect->top, rect->right, rect->bottom,
414 style, menu, exStyle );
416 NC_AdjustRectOuter( rect, style, menu, exStyle );
417 NC_AdjustRectInner( rect, style, exStyle );
419 return TRUE;
423 /***********************************************************************
424 * NC_HandleNCCalcSize
426 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
428 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
430 RECT tmpRect = { 0, 0, 0, 0 };
431 LRESULT result = 0;
432 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
433 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
434 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
436 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
437 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
439 if (!IsIconic(hwnd))
441 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
443 winRect->left -= tmpRect.left;
444 winRect->top -= tmpRect.top;
445 winRect->right -= tmpRect.right;
446 winRect->bottom -= tmpRect.bottom;
448 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
450 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
451 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
453 winRect->top +=
454 MENU_GetMenuBarHeight( hwnd,
455 winRect->right - winRect->left,
456 -tmpRect.left, -tmpRect.top );
459 if( exStyle & WS_EX_CLIENTEDGE)
460 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
461 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
462 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
463 - GetSystemMetrics(SM_CYEDGE));
465 if (style & WS_VSCROLL)
466 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
467 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
468 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
469 else
470 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
473 if (style & WS_HSCROLL)
474 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
475 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
477 if (winRect->top > winRect->bottom)
478 winRect->bottom = winRect->top;
480 if (winRect->left > winRect->right)
481 winRect->right = winRect->left;
483 return result;
487 /***********************************************************************
488 * NC_GetInsideRect
490 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
491 * but without the borders (if any).
492 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
494 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
496 WND *wndPtr = WIN_GetPtr( hwnd );
498 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
500 rect->top = rect->left = 0;
501 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
502 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
504 if (wndPtr->dwStyle & WS_ICONIC) goto END;
506 /* Remove frame from rectangle */
507 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
509 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
511 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
515 else if (HAS_THINFRAME( wndPtr->dwStyle ))
517 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
520 /* We have additional border information if the window
521 * is a child (but not an MDI child) */
522 if ( (wndPtr->dwStyle & WS_CHILD) &&
523 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
525 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
526 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
527 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
528 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
531 END:
532 WIN_ReleasePtr( wndPtr );
536 /***********************************************************************
537 * NC_DoNCHitTest
539 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
541 * FIXME: Just a modified copy of the Win 3.1 version.
544 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
546 RECT rect, rcClient;
547 POINT ptClient;
549 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
551 GetWindowRect(wndPtr->hwndSelf, &rect );
552 if (!PtInRect( &rect, pt )) return HTNOWHERE;
554 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
556 /* Check client area */
557 ptClient = pt;
558 ScreenToClient( wndPtr->hwndSelf, &ptClient );
559 GetClientRect( wndPtr->hwndSelf, &rcClient );
560 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
562 /* Check borders */
563 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
565 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
566 if (!PtInRect( &rect, pt ))
568 /* Check top sizing border */
569 if (pt.y < rect.top)
571 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
572 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
573 return HTTOP;
575 /* Check bottom sizing border */
576 if (pt.y >= rect.bottom)
578 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
579 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
580 return HTBOTTOM;
582 /* Check left sizing border */
583 if (pt.x < rect.left)
585 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
586 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
587 return HTLEFT;
589 /* Check right sizing border */
590 if (pt.x >= rect.right)
592 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
593 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
594 return HTRIGHT;
598 else /* No thick frame */
600 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
601 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
602 else if (HAS_THINFRAME( wndPtr->dwStyle ))
603 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
604 if (!PtInRect( &rect, pt )) return HTBORDER;
607 /* Check caption */
609 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
611 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
612 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
613 else
614 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
615 if (!PtInRect( &rect, pt ))
617 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
618 (wndPtr->dwStyle & WS_MINIMIZEBOX);
619 /* Check system menu */
620 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
622 if (NC_IconForWindow(wndPtr->hwndSelf))
623 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
625 if (pt.x < rect.left) return HTSYSMENU;
627 /* Check close button */
628 if (wndPtr->dwStyle & WS_SYSMENU)
629 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
630 if (pt.x > rect.right) return HTCLOSE;
632 /* Check maximize box */
633 /* In win95 there is automatically a Maximize button when there is a minimize one*/
634 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
635 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
636 if (pt.x > rect.right) return HTMAXBUTTON;
638 /* Check minimize box */
639 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
640 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
641 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
643 if (pt.x > rect.right) return HTMINBUTTON;
644 return HTCAPTION;
648 /* Check vertical scroll bar */
650 if (wndPtr->dwStyle & WS_VSCROLL)
652 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
653 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
654 else
655 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
656 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
659 /* Check horizontal scroll bar */
661 if (wndPtr->dwStyle & WS_HSCROLL)
663 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
664 if (PtInRect( &rcClient, ptClient ))
666 /* Check size box */
667 if ((wndPtr->dwStyle & WS_VSCROLL) &&
668 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
669 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
670 return HTSIZE;
671 return HTHSCROLL;
675 /* Check menu bar */
677 if (HAS_MENU(wndPtr))
679 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
680 return HTMENU;
683 /* Has to return HTNOWHERE if nothing was found
684 Could happen when a window has a customized non client area */
685 return HTNOWHERE;
689 /***********************************************************************
690 * NC_HandleNCHitTest
692 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
694 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
696 LRESULT retvalue;
697 WND *wndPtr = WIN_GetPtr( hwnd );
699 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
701 retvalue = NC_DoNCHitTest (wndPtr, pt);
702 WIN_ReleasePtr( wndPtr );
703 return retvalue;
707 /******************************************************************************
709 * NC_DrawSysButton
711 * Draws the system icon.
713 *****************************************************************************/
714 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
716 HICON hIcon = NC_IconForWindow( hwnd );
718 if (hIcon)
720 RECT rect;
721 NC_GetInsideRect( hwnd, &rect );
722 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
723 GetSystemMetrics(SM_CXSMICON),
724 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
726 return (hIcon != 0);
730 /******************************************************************************
732 * NC_DrawCloseButton
734 * Draws the close button.
736 * If bGrayed is true, then draw a disabled Close button
738 *****************************************************************************/
740 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
742 RECT rect;
744 NC_GetInsideRect( hwnd, &rect );
746 /* A tool window has a smaller Close button */
747 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
749 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
750 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
751 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
753 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
754 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
755 rect.bottom = rect.top + iBmpHeight;
756 rect.right = rect.left + iBmpWidth;
758 else
760 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
761 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
762 rect.top += 2;
763 rect.right -= 2;
765 DrawFrameControl( hdc, &rect, DFC_CAPTION,
766 (DFCS_CAPTIONCLOSE |
767 (down ? DFCS_PUSHED : 0) |
768 (bGrayed ? DFCS_INACTIVE : 0)) );
771 /******************************************************************************
772 * NC_DrawMaxButton
774 * Draws the maximize button for windows.
775 * If bGrayed is true, then draw a disabled Maximize button
777 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
779 RECT rect;
780 UINT flags;
782 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
783 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
784 return;
786 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
788 NC_GetInsideRect( hwnd, &rect );
789 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
790 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
791 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
792 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
793 rect.top += 2;
794 rect.right -= 2;
795 if (down) flags |= DFCS_PUSHED;
796 if (bGrayed) flags |= DFCS_INACTIVE;
797 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
800 /******************************************************************************
801 * NC_DrawMinButton
803 * Draws the minimize button for windows.
804 * If bGrayed is true, then draw a disabled Minimize button
806 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
808 RECT rect;
809 UINT flags = DFCS_CAPTIONMIN;
810 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
812 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
813 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
814 return;
816 NC_GetInsideRect( hwnd, &rect );
817 if (style & WS_SYSMENU)
818 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
819 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
820 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
821 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
822 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
823 rect.top += 2;
824 rect.right -= 2;
825 if (down) flags |= DFCS_PUSHED;
826 if (bGrayed) flags |= DFCS_INACTIVE;
827 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
830 /******************************************************************************
832 * NC_DrawFrame
834 * Draw a window frame inside the given rectangle, and update the rectangle.
836 * Bugs
837 * Many. First, just what IS a frame in Win95? Note that the 3D look
838 * on the outer edge is handled by NC_DoNCPaint. As is the inner
839 * edge. The inner rectangle just inside the frame is handled by the
840 * Caption code.
842 * In short, for most people, this function should be a nop (unless
843 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
844 * them lately, but just to get this code right). Even so, it doesn't
845 * appear to be so. It's being worked on...
847 *****************************************************************************/
849 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
851 INT width, height;
853 /* Firstly the "thick" frame */
854 if (style & WS_THICKFRAME)
856 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
857 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
859 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
860 COLOR_INACTIVEBORDER) );
861 /* Draw frame */
862 PatBlt( hdc, rect->left, rect->top,
863 rect->right - rect->left, height, PATCOPY );
864 PatBlt( hdc, rect->left, rect->top,
865 width, rect->bottom - rect->top, PATCOPY );
866 PatBlt( hdc, rect->left, rect->bottom - 1,
867 rect->right - rect->left, -height, PATCOPY );
868 PatBlt( hdc, rect->right - 1, rect->top,
869 -width, rect->bottom - rect->top, PATCOPY );
871 InflateRect( rect, -width, -height );
874 /* Now the other bit of the frame */
875 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
876 (exStyle & WS_EX_DLGMODALFRAME))
878 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
879 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
880 /* This should give a value of 1 that should also work for a border */
882 SelectObject( hdc, GetSysColorBrush(
883 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
884 COLOR_3DFACE :
885 (exStyle & WS_EX_STATICEDGE) ?
886 COLOR_WINDOWFRAME :
887 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
888 COLOR_3DFACE :
889 /* else */
890 COLOR_WINDOWFRAME));
892 /* Draw frame */
893 PatBlt( hdc, rect->left, rect->top,
894 rect->right - rect->left, height, PATCOPY );
895 PatBlt( hdc, rect->left, rect->top,
896 width, rect->bottom - rect->top, PATCOPY );
897 PatBlt( hdc, rect->left, rect->bottom - 1,
898 rect->right - rect->left, -height, PATCOPY );
899 PatBlt( hdc, rect->right - 1, rect->top,
900 -width, rect->bottom - rect->top, PATCOPY );
902 InflateRect( rect, -width, -height );
907 /******************************************************************************
909 * NC_DrawCaption
911 * Draw the window caption for windows.
912 * The correct pen for the window frame must be selected in the DC.
914 *****************************************************************************/
916 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
917 DWORD exStyle, BOOL active )
919 RECT r = *rect;
920 WCHAR buffer[256];
921 HPEN hPrevPen;
922 HMENU hSysMenu;
923 BOOL gradient = FALSE;
925 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
926 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
927 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
928 COLOR_WINDOWFRAME : COLOR_3DFACE) );
929 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
930 LineTo( hdc, r.right, r.bottom - 1 );
931 SelectObject( hdc, hPrevPen );
932 r.bottom--;
934 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
935 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
937 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
938 if (NC_DrawSysButton (hwnd, hdc, FALSE))
939 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
942 if (style & WS_SYSMENU)
944 UINT state;
946 /* Go get the sysmenu */
947 hSysMenu = GetSystemMenu(hwnd, FALSE);
948 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
950 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
951 NC_DrawCloseButton (hwnd, hdc, FALSE,
952 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
953 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
955 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
957 /* In win95 the two buttons are always there */
958 /* But if the menu item is not in the menu they're disabled*/
960 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
961 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
963 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
964 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
968 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
970 NONCLIENTMETRICSW nclm;
971 HFONT hFont, hOldFont;
972 nclm.cbSize = sizeof(nclm);
973 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
974 if (exStyle & WS_EX_TOOLWINDOW)
975 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
976 else
977 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
978 hOldFont = SelectObject (hdc, hFont);
979 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
980 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
981 SetBkMode( hdc, TRANSPARENT );
982 r.left += 2;
983 DrawTextW( hdc, buffer, -1, &r,
984 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
985 DeleteObject (SelectObject (hdc, hOldFont));
990 /******************************************************************************
991 * NC_DoNCPaint
993 * Paint the non-client area for windows.
995 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
997 HDC hdc;
998 RECT rfuzz, rect, rectClip;
999 BOOL active;
1000 WND *wndPtr;
1001 DWORD dwStyle, dwExStyle;
1002 WORD flags;
1003 HRGN hrgn;
1004 RECT rectClient, rectWindow;
1005 int has_menu;
1007 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1008 has_menu = HAS_MENU(wndPtr);
1009 dwStyle = wndPtr->dwStyle;
1010 dwExStyle = wndPtr->dwExStyle;
1011 flags = wndPtr->flags;
1012 rectWindow = wndPtr->rectWindow;
1013 WIN_ReleasePtr( wndPtr );
1015 if ( dwStyle & WS_MINIMIZE ||
1016 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1018 active = flags & WIN_NCACTIVATED;
1020 TRACE("%p %d\n", hwnd, active );
1022 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1023 the call to GetDCEx implying that it is allowed not to use it either.
1024 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1025 will cause clipRgn to be deleted after ReleaseDC().
1026 Now, how is the "system" supposed to tell what happened?
1029 GetClientRect( hwnd, &rectClient );
1030 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1031 hrgn = CreateRectRgnIndirect( &rectClient );
1033 if (clip > (HRGN)1)
1035 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1036 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1038 else
1040 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1043 if (!hdc) return;
1045 rect.top = rect.left = 0;
1046 rect.right = rectWindow.right - rectWindow.left;
1047 rect.bottom = rectWindow.bottom - rectWindow.top;
1048 GetClipBox( hdc, &rectClip );
1050 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1052 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1053 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1055 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1056 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1059 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1061 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1063 RECT r = rect;
1064 if (dwExStyle & WS_EX_TOOLWINDOW) {
1065 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1066 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1068 else {
1069 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1070 rect.top += GetSystemMetrics(SM_CYCAPTION);
1072 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1073 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1076 if (has_menu)
1078 RECT r = rect;
1079 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1081 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1082 r.left, r.top, r.right, r.bottom);
1084 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1087 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1088 rect.left, rect.top, rect.right, rect.bottom );
1090 if (dwExStyle & WS_EX_CLIENTEDGE)
1091 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1093 /* Draw the scroll-bars */
1095 if (dwStyle & WS_VSCROLL)
1096 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1097 if (dwStyle & WS_HSCROLL)
1098 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1100 /* Draw the "size-box" */
1101 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1103 RECT r = rect;
1104 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1105 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1106 else
1107 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1108 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1109 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1112 ReleaseDC( hwnd, hdc );
1118 /***********************************************************************
1119 * NC_HandleNCPaint
1121 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1123 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1125 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1127 if( dwStyle & WS_VISIBLE )
1129 if( dwStyle & WS_MINIMIZE )
1130 WINPOS_RedrawIconTitle( hwnd );
1131 else
1132 NC_DoNCPaint( hwnd, clip, FALSE );
1134 return 0;
1138 /***********************************************************************
1139 * NC_HandleNCActivate
1141 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1143 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1145 WND* wndPtr = WIN_GetPtr( hwnd );
1147 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1149 /* Lotus Notes draws menu descriptions in the caption of its main
1150 * window. When it wants to restore original "system" view, it just
1151 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1152 * attempt to minimize redrawings lead to a not restored caption.
1154 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1155 else wndPtr->flags &= ~WIN_NCACTIVATED;
1156 WIN_ReleasePtr( wndPtr );
1158 if (IsIconic(hwnd))
1159 WINPOS_RedrawIconTitle( hwnd );
1160 else
1161 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1163 return TRUE;
1167 /***********************************************************************
1168 * NC_HandleSetCursor
1170 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1172 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1174 hwnd = WIN_GetFullHandle( (HWND)wParam );
1176 switch((short)LOWORD(lParam))
1178 case HTERROR:
1180 WORD msg = HIWORD( lParam );
1181 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1182 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1183 MessageBeep(0);
1185 break;
1187 case HTCLIENT:
1189 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1190 if(hCursor) {
1191 SetCursor(hCursor);
1192 return TRUE;
1194 return FALSE;
1197 case HTLEFT:
1198 case HTRIGHT:
1199 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1201 case HTTOP:
1202 case HTBOTTOM:
1203 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1205 case HTTOPLEFT:
1206 case HTBOTTOMRIGHT:
1207 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1209 case HTTOPRIGHT:
1210 case HTBOTTOMLEFT:
1211 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1214 /* Default cursor: arrow */
1215 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1218 /***********************************************************************
1219 * NC_GetSysPopupPos
1221 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1223 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1224 else
1226 WND *wndPtr = WIN_GetPtr( hwnd );
1227 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1229 NC_GetInsideRect( hwnd, rect );
1230 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1231 if (wndPtr->dwStyle & WS_CHILD)
1232 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1233 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1234 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1235 WIN_ReleasePtr( wndPtr );
1239 /***********************************************************************
1240 * NC_TrackMinMaxBox
1242 * Track a mouse button press on the minimize or maximize box.
1244 * The big difference between 3.1 and 95 is the disabled button state.
1245 * In win95 the system button can be disabled, so it can ignore the mouse
1246 * event.
1249 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1251 MSG msg;
1252 HDC hdc = GetWindowDC( hwnd );
1253 BOOL pressed = TRUE;
1254 UINT state;
1255 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1256 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1258 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1260 if (wParam == HTMINBUTTON)
1262 /* If the style is not present, do nothing */
1263 if (!(wndStyle & WS_MINIMIZEBOX))
1264 return;
1266 /* Check if the sysmenu item for minimize is there */
1267 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1269 paintButton = &NC_DrawMinButton;
1271 else
1273 /* If the style is not present, do nothing */
1274 if (!(wndStyle & WS_MAXIMIZEBOX))
1275 return;
1277 /* Check if the sysmenu item for maximize is there */
1278 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1280 paintButton = &NC_DrawMaxButton;
1283 SetCapture( hwnd );
1285 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1287 while(1)
1289 BOOL oldstate = pressed;
1291 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1292 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1294 if(msg.message == WM_LBUTTONUP)
1295 break;
1297 if(msg.message != WM_MOUSEMOVE)
1298 continue;
1300 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1301 if (pressed != oldstate)
1302 (*paintButton)( hwnd, hdc, pressed, FALSE);
1305 if(pressed)
1306 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1308 ReleaseCapture();
1309 ReleaseDC( hwnd, hdc );
1311 /* If the item minimize or maximize of the sysmenu are not there */
1312 /* or if the style is not present, do nothing */
1313 if ((!pressed) || (state == 0xFFFFFFFF))
1314 return;
1316 if (wParam == HTMINBUTTON)
1317 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1318 else
1319 SendMessageW( hwnd, WM_SYSCOMMAND,
1320 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1323 /***********************************************************************
1324 * NC_TrackCloseButton
1326 * Track a mouse button press on the Win95 close button.
1328 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1330 MSG msg;
1331 HDC hdc;
1332 BOOL pressed = TRUE;
1333 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1334 UINT state;
1336 if(hSysMenu == 0)
1337 return;
1339 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1341 /* If the item close of the sysmenu is disabled or not there do nothing */
1342 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1343 return;
1345 hdc = GetWindowDC( hwnd );
1347 SetCapture( hwnd );
1349 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1351 while(1)
1353 BOOL oldstate = pressed;
1355 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1356 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1358 if(msg.message == WM_LBUTTONUP)
1359 break;
1361 if(msg.message != WM_MOUSEMOVE)
1362 continue;
1364 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1365 if (pressed != oldstate)
1366 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1369 if(pressed)
1370 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1372 ReleaseCapture();
1373 ReleaseDC( hwnd, hdc );
1374 if (!pressed) return;
1376 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1380 /***********************************************************************
1381 * NC_TrackScrollBar
1383 * Track a mouse button press on the horizontal or vertical scroll-bar.
1385 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1387 INT scrollbar;
1389 if ((wParam & 0xfff0) == SC_HSCROLL)
1391 if ((wParam & 0x0f) != HTHSCROLL) return;
1392 scrollbar = SB_HORZ;
1394 else /* SC_VSCROLL */
1396 if ((wParam & 0x0f) != HTVSCROLL) return;
1397 scrollbar = SB_VERT;
1399 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1403 /***********************************************************************
1404 * NC_HandleNCLButtonDown
1406 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1408 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1410 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1412 switch(wParam) /* Hit test */
1414 case HTCAPTION:
1416 HWND top = GetAncestor( hwnd, GA_ROOT );
1418 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1419 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1420 break;
1423 case HTSYSMENU:
1424 if( style & WS_SYSMENU )
1426 if( !(style & WS_MINIMIZE) )
1428 HDC hDC = GetWindowDC(hwnd);
1429 NC_DrawSysButton( hwnd, hDC, TRUE );
1430 ReleaseDC( hwnd, hDC );
1432 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1434 break;
1436 case HTMENU:
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1438 break;
1440 case HTHSCROLL:
1441 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1442 break;
1444 case HTVSCROLL:
1445 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1446 break;
1448 case HTMINBUTTON:
1449 case HTMAXBUTTON:
1450 NC_TrackMinMaxBox( hwnd, wParam );
1451 break;
1453 case HTCLOSE:
1454 NC_TrackCloseButton (hwnd, wParam);
1455 break;
1457 case HTLEFT:
1458 case HTRIGHT:
1459 case HTTOP:
1460 case HTTOPLEFT:
1461 case HTTOPRIGHT:
1462 case HTBOTTOM:
1463 case HTBOTTOMLEFT:
1464 case HTBOTTOMRIGHT:
1465 /* Old comment:
1466 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1467 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1469 /* But that is not what WinNT does. Instead it sends this. This
1470 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1471 * SC_MOUSEMENU into wParam.
1473 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1474 break;
1476 case HTBORDER:
1477 break;
1479 return 0;
1483 /***********************************************************************
1484 * NC_HandleNCLButtonDblClk
1486 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1488 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1491 * if this is an icon, send a restore since we are handling
1492 * a double click
1494 if (IsIconic(hwnd))
1496 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1497 return 0;
1500 switch(wParam) /* Hit test */
1502 case HTCAPTION:
1503 /* stop processing if WS_MAXIMIZEBOX is missing */
1504 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1505 SendMessageW( hwnd, WM_SYSCOMMAND,
1506 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1507 break;
1509 case HTSYSMENU:
1511 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1512 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1514 /* If the item close of the sysmenu is disabled or not there do nothing */
1515 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1516 break;
1518 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1519 break;
1522 case HTHSCROLL:
1523 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1524 break;
1526 case HTVSCROLL:
1527 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1528 break;
1530 return 0;
1534 /***********************************************************************
1535 * NC_HandleSysCommand
1537 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1539 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1541 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1543 if (!IsWindowEnabled( hwnd )) return 0;
1545 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1546 return 0;
1548 switch (wParam & 0xfff0)
1550 case SC_SIZE:
1551 case SC_MOVE:
1552 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1553 break;
1555 case SC_MINIMIZE:
1556 if (hwnd == GetForegroundWindow())
1557 ShowOwnedPopups(hwnd,FALSE);
1558 ShowWindow( hwnd, SW_MINIMIZE );
1559 break;
1561 case SC_MAXIMIZE:
1562 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1563 ShowOwnedPopups(hwnd,TRUE);
1564 ShowWindow( hwnd, SW_MAXIMIZE );
1565 break;
1567 case SC_RESTORE:
1568 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1569 ShowOwnedPopups(hwnd,TRUE);
1570 ShowWindow( hwnd, SW_RESTORE );
1571 break;
1573 case SC_CLOSE:
1574 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1576 case SC_VSCROLL:
1577 case SC_HSCROLL:
1579 POINT pt;
1580 pt.x = (short)LOWORD(lParam);
1581 pt.y = (short)HIWORD(lParam);
1582 NC_TrackScrollBar( hwnd, wParam, pt );
1584 break;
1586 case SC_MOUSEMENU:
1588 POINT pt;
1589 pt.x = (short)LOWORD(lParam);
1590 pt.y = (short)HIWORD(lParam);
1591 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1593 break;
1595 case SC_KEYMENU:
1596 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1597 break;
1599 case SC_TASKLIST:
1600 WinExec( "taskman.exe", SW_SHOWNORMAL );
1601 break;
1603 case SC_SCREENSAVE:
1604 if (wParam == SC_ABOUTWINE)
1606 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1607 if (hmodule)
1609 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1610 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1611 FreeLibrary( hmodule );
1614 else
1615 if (wParam == SC_PUTMARK)
1616 DPRINTF("Debug mark requested by user\n");
1617 break;
1619 case SC_HOTKEY:
1620 case SC_ARRANGE:
1621 case SC_NEXTWINDOW:
1622 case SC_PREVWINDOW:
1623 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1624 break;
1626 return 0;
1629 /*************************************************************
1630 * NC_DrawGrayButton
1632 * Stub for the grayed button of the caption
1634 *************************************************************/
1636 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1638 HBITMAP hMaskBmp;
1639 HDC hdcMask;
1640 HBRUSH hOldBrush;
1642 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1644 if(hMaskBmp == 0)
1645 return FALSE;
1647 hdcMask = CreateCompatibleDC (0);
1648 SelectObject (hdcMask, hMaskBmp);
1650 /* Draw the grayed bitmap using the mask */
1651 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1652 BitBlt (hdc, x, y, 12, 10,
1653 hdcMask, 0, 0, 0xB8074A);
1655 /* Clean up */
1656 SelectObject (hdc, hOldBrush);
1657 DeleteObject(hMaskBmp);
1658 DeleteDC (hdcMask);
1660 return TRUE;
1663 /***********************************************************************
1664 * GetTitleBarInfo (USER32.@)
1665 * TODO: Handle STATE_SYSTEM_PRESSED
1667 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1668 DWORD dwStyle;
1669 DWORD dwExStyle;
1670 RECT wndRect;
1672 TRACE("(%p %p)\n", hwnd, tbi);
1674 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1675 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1676 SetLastError(ERROR_INVALID_PARAMETER);
1677 return FALSE;
1679 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1680 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1681 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1683 GetWindowRect(hwnd, &wndRect);
1685 tbi->rcTitleBar.top += wndRect.top;
1686 tbi->rcTitleBar.left += wndRect.left;
1687 tbi->rcTitleBar.right += wndRect.left;
1689 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1690 if(dwExStyle & WS_EX_TOOLWINDOW)
1691 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1692 else {
1693 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1694 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1697 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1698 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1699 * Under XP it seems to
1701 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1702 if(dwStyle & WS_CAPTION) {
1703 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1704 if(dwStyle & WS_SYSMENU) {
1705 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1706 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1707 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1709 else {
1710 if(!(dwStyle & WS_MINIMIZEBOX))
1711 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1712 if(!(dwStyle & WS_MAXIMIZEBOX))
1713 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1715 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1716 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1717 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1718 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1720 else {
1721 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1722 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1723 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1727 else
1728 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1729 return TRUE;