Assorted spelling fixes.
[wine/wine-kai.git] / dlls / user / nonclient.c
blob4d6dfd433b2f9be5780846878537b5657712394f
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/winuser16.h"
29 #include "wownt32.h"
30 #include "win.h"
31 #include "user_private.h"
32 #include "controls.h"
33 #include "winpos.h"
34 #include "shellapi.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
38 WINE_DECLARE_DEBUG_CHANNEL(shell);
40 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
42 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
43 0x55, 0x50,
44 0xAA, 0xA0,
45 0x55, 0x50,
46 0xAA, 0xA0,
47 0x55, 0x50,
48 0xAA, 0xA0,
49 0x55, 0x50,
50 0xAA, 0xA0,
51 0x55, 0x50};
53 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
54 #define SC_PUTMARK (SC_SCREENSAVE+2)
56 /* Some useful macros */
57 #define HAS_DLGFRAME(style,exStyle) \
58 (((exStyle) & WS_EX_DLGMODALFRAME) || \
59 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
61 #define HAS_THICKFRAME(style,exStyle) \
62 (((style) & WS_THICKFRAME) && \
63 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
65 #define HAS_THINFRAME(style) \
66 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
68 #define HAS_BIGFRAME(style,exStyle) \
69 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
70 ((exStyle) & WS_EX_DLGMODALFRAME))
72 #define HAS_STATICOUTERFRAME(style,exStyle) \
73 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
74 WS_EX_STATICEDGE)
76 #define HAS_ANYFRAME(style,exStyle) \
77 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
78 ((exStyle) & WS_EX_DLGMODALFRAME) || \
79 !((style) & (WS_CHILD | WS_POPUP)))
81 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
84 /******************************************************************************
85 * NC_AdjustRectOuter
87 * Computes the size of the "outside" parts of the window based on the
88 * parameters of the client area.
90 * PARAMS
91 * LPRECT rect
92 * DWORD style
93 * BOOL menu
94 * DWORD exStyle
96 * NOTES
97 * "Outer" parts of a window means the whole window frame, caption and
98 * menu bar. It does not include "inner" parts of the frame like client
99 * edge, static edge or scroll bars.
101 *****************************************************************************/
103 static void
104 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
106 int adjust;
107 if(style & WS_ICONIC) return;
109 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
110 WS_EX_STATICEDGE)
112 adjust = 1; /* for the outer frame always present */
114 else
116 adjust = 0;
117 if ((exStyle & WS_EX_DLGMODALFRAME) ||
118 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
120 if (style & WS_THICKFRAME)
121 adjust += ( GetSystemMetrics (SM_CXFRAME)
122 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
123 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
124 (exStyle & WS_EX_DLGMODALFRAME))
125 adjust++; /* The other border */
127 InflateRect (rect, adjust, adjust);
129 if ((style & WS_CAPTION) == WS_CAPTION)
131 if (exStyle & WS_EX_TOOLWINDOW)
132 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
133 else
134 rect->top -= GetSystemMetrics(SM_CYCAPTION);
136 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
140 /******************************************************************************
141 * NC_AdjustRectInner
143 * Computes the size of the "inside" part of the window based on the
144 * parameters of the client area.
146 * PARAMS
147 * LPRECT rect
148 * DWORD style
149 * DWORD exStyle
151 * NOTES
152 * "Inner" part of a window means the window frame inside of the flat
153 * window frame. It includes the client edge, the static edge and the
154 * scroll bars.
156 *****************************************************************************/
158 static void
159 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
161 if(style & WS_ICONIC) return;
163 if (exStyle & WS_EX_CLIENTEDGE)
164 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
166 if (style & WS_VSCROLL)
168 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
169 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
170 else
171 rect->right += GetSystemMetrics(SM_CXVSCROLL);
173 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
178 static HICON NC_IconForWindow( HWND hwnd )
180 HICON hIcon = 0;
181 WND *wndPtr = WIN_GetPtr( hwnd );
183 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
185 hIcon = wndPtr->hIconSmall;
186 if (!hIcon) hIcon = wndPtr->hIcon;
187 WIN_ReleasePtr( wndPtr );
189 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
190 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
192 /* If there is no hIcon specified and this is a modal dialog,
193 * get the default one.
195 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
196 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
197 return hIcon;
200 /* Draws the bar part(ie the big rectangle) of the caption */
201 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
202 BOOL active, BOOL gradient)
204 if (gradient)
206 TRIVERTEX vertices[6];
207 DWORD colLeft =
208 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
209 DWORD colRight =
210 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
211 : COLOR_GRADIENTINACTIVECAPTION);
212 int v;
213 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
214 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
216 for (v = 0; v < 3; v++)
218 vertices[v].Red = GetRValue (colLeft) << 8;
219 vertices[v].Green = GetGValue (colLeft) << 8;
220 vertices[v].Blue = GetBValue (colLeft) << 8;
221 vertices[v].Alpha = 0x8000;
222 vertices[v+3].Red = GetRValue (colRight) << 8;
223 vertices[v+3].Green = GetGValue (colRight) << 8;
224 vertices[v+3].Blue = GetBValue (colRight) << 8;
225 vertices[v+3].Alpha = 0x8000;
228 if ((dwStyle & WS_SYSMENU)
229 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
230 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
232 /* area behind icon; solid filled with left color */
233 vertices[0].x = rect->left;
234 vertices[0].y = rect->top;
235 if (dwStyle & WS_SYSMENU)
236 vertices[1].x =
237 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
238 else
239 vertices[1].x = vertices[0].x;
240 vertices[1].y = rect->bottom;
242 /* area behind text; gradient */
243 vertices[2].x = vertices[1].x;
244 vertices[2].y = rect->top;
245 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
246 vertices[3].y = rect->bottom;
248 /* area behind buttons; solid filled with right color */
249 vertices[4].x = vertices[3].x;
250 vertices[4].y = rect->top;
251 vertices[5].x = rect->right;
252 vertices[5].y = rect->bottom;
254 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
256 else
257 FillRect (hdc, rect, GetSysColorBrush (active ?
258 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
261 /***********************************************************************
262 * DrawCaption (USER32.@) Draws a caption bar
264 * PARAMS
265 * hwnd [I]
266 * hdc [I]
267 * lpRect [I]
268 * uFlags [I]
270 * RETURNS
271 * Success:
272 * Failure:
275 BOOL WINAPI
276 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
278 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
282 /***********************************************************************
283 * DrawCaptionTempA (USER32.@)
285 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
286 HICON hIcon, LPCSTR str, UINT uFlags)
288 LPWSTR strW;
289 INT len;
290 BOOL ret = FALSE;
292 if (!(uFlags & DC_TEXT) || !str)
293 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
295 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
296 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
298 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
299 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
300 HeapFree( GetProcessHeap (), 0, strW );
302 return ret;
306 /***********************************************************************
307 * DrawCaptionTempW (USER32.@)
309 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
310 HICON hIcon, LPCWSTR str, UINT uFlags)
312 RECT rc = *rect;
314 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
315 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
317 /* drawing background */
318 if (uFlags & DC_INBUTTON) {
319 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
321 if (uFlags & DC_ACTIVE) {
322 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
323 PatBlt (hdc, rc.left, rc.top,
324 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
325 SelectObject (hdc, hbr);
328 else {
329 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
330 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
334 /* drawing icon */
335 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
336 POINT pt;
338 pt.x = rc.left + 2;
339 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
341 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
342 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
343 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
344 rc.left += (rc.bottom - rc.top);
347 /* drawing text */
348 if (uFlags & DC_TEXT) {
349 HFONT hOldFont;
351 if (uFlags & DC_INBUTTON)
352 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
353 else if (uFlags & DC_ACTIVE)
354 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
355 else
356 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
358 SetBkMode (hdc, TRANSPARENT);
360 if (hFont)
361 hOldFont = SelectObject (hdc, hFont);
362 else {
363 NONCLIENTMETRICSW nclm;
364 HFONT hNewFont;
365 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
366 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
367 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
368 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
369 hOldFont = SelectObject (hdc, hNewFont);
372 if (str)
373 DrawTextW (hdc, str, -1, &rc,
374 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
375 else {
376 WCHAR szText[128];
377 INT nLen;
378 nLen = GetWindowTextW (hwnd, szText, 128);
379 DrawTextW (hdc, szText, nLen, &rc,
380 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
383 if (hFont)
384 SelectObject (hdc, hOldFont);
385 else
386 DeleteObject (SelectObject (hdc, hOldFont));
389 /* drawing focus ??? */
390 if (uFlags & 0x2000)
391 FIXME("undocumented flag (0x2000)!\n");
393 return 0;
397 /***********************************************************************
398 * AdjustWindowRect (USER32.@)
400 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
402 return AdjustWindowRectEx( rect, style, menu, 0 );
406 /***********************************************************************
407 * AdjustWindowRectEx (USER32.@)
409 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
411 /* Correct the window style */
412 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
413 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
414 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
415 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
417 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
418 rect->left, rect->top, rect->right, rect->bottom,
419 style, menu, exStyle );
421 NC_AdjustRectOuter( rect, style, menu, exStyle );
422 NC_AdjustRectInner( rect, style, exStyle );
424 return TRUE;
428 /***********************************************************************
429 * NC_HandleNCCalcSize
431 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
433 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
435 RECT tmpRect = { 0, 0, 0, 0 };
436 LONG result = 0;
437 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
438 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
439 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
441 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
442 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
444 if (!IsIconic(hwnd))
446 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
448 winRect->left -= tmpRect.left;
449 winRect->top -= tmpRect.top;
450 winRect->right -= tmpRect.right;
451 winRect->bottom -= tmpRect.bottom;
453 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
455 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
456 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
458 winRect->top +=
459 MENU_GetMenuBarHeight( hwnd,
460 winRect->right - winRect->left,
461 -tmpRect.left, -tmpRect.top );
464 if( exStyle & WS_EX_CLIENTEDGE)
465 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
466 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
467 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
468 - GetSystemMetrics(SM_CYEDGE));
470 if (style & WS_VSCROLL)
471 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
472 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
473 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
474 else
475 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
478 if (style & WS_HSCROLL)
479 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
480 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
482 if (winRect->top > winRect->bottom)
483 winRect->bottom = winRect->top;
485 if (winRect->left > winRect->right)
486 winRect->right = winRect->left;
488 return result;
492 /***********************************************************************
493 * NC_GetInsideRect
495 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
496 * but without the borders (if any).
497 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
499 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
501 WND *wndPtr = WIN_GetPtr( hwnd );
503 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
505 rect->top = rect->left = 0;
506 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
507 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
509 if (wndPtr->dwStyle & WS_ICONIC) goto END;
511 /* Remove frame from rectangle */
512 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
514 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
516 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
518 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
520 else if (HAS_THINFRAME( wndPtr->dwStyle ))
522 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
525 /* We have additional border information if the window
526 * is a child (but not an MDI child) */
527 if ( (wndPtr->dwStyle & WS_CHILD) &&
528 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
530 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
531 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
532 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
533 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
536 END:
537 WIN_ReleasePtr( wndPtr );
541 /***********************************************************************
542 * NC_DoNCHitTest
544 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
546 * FIXME: Just a modified copy of the Win 3.1 version.
549 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
551 RECT rect, rcClient;
552 POINT ptClient;
554 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
556 GetWindowRect(wndPtr->hwndSelf, &rect );
557 if (!PtInRect( &rect, pt )) return HTNOWHERE;
559 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
561 /* Check client area */
562 ptClient = pt;
563 ScreenToClient( wndPtr->hwndSelf, &ptClient );
564 GetClientRect( wndPtr->hwndSelf, &rcClient );
565 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
567 /* Check borders */
568 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
570 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
571 if (!PtInRect( &rect, pt ))
573 /* Check top sizing border */
574 if (pt.y < rect.top)
576 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
577 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
578 return HTTOP;
580 /* Check bottom sizing border */
581 if (pt.y >= rect.bottom)
583 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
584 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
585 return HTBOTTOM;
587 /* Check left sizing border */
588 if (pt.x < rect.left)
590 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
591 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
592 return HTLEFT;
594 /* Check right sizing border */
595 if (pt.x >= rect.right)
597 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
598 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
599 return HTRIGHT;
603 else /* No thick frame */
605 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
606 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
607 else if (HAS_THINFRAME( wndPtr->dwStyle ))
608 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
609 if (!PtInRect( &rect, pt )) return HTBORDER;
612 /* Check caption */
614 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
616 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
617 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
618 else
619 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
620 if (!PtInRect( &rect, pt ))
622 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
623 (wndPtr->dwStyle & WS_MINIMIZEBOX);
624 /* Check system menu */
625 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
627 if (NC_IconForWindow(wndPtr->hwndSelf))
628 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
630 if (pt.x < rect.left) return HTSYSMENU;
632 /* Check close button */
633 if (wndPtr->dwStyle & WS_SYSMENU)
634 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
635 if (pt.x > rect.right) return HTCLOSE;
637 /* Check maximize box */
638 /* In win95 there is automatically a Maximize button when there is a minimize one*/
639 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
640 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
641 if (pt.x > rect.right) return HTMAXBUTTON;
643 /* Check minimize box */
644 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
645 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
646 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
648 if (pt.x > rect.right) return HTMINBUTTON;
649 return HTCAPTION;
653 /* Check vertical scroll bar */
655 if (wndPtr->dwStyle & WS_VSCROLL)
657 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
658 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
659 else
660 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
661 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
664 /* Check horizontal scroll bar */
666 if (wndPtr->dwStyle & WS_HSCROLL)
668 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
669 if (PtInRect( &rcClient, ptClient ))
671 /* Check size box */
672 if ((wndPtr->dwStyle & WS_VSCROLL) &&
673 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
674 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
675 return HTSIZE;
676 return HTHSCROLL;
680 /* Check menu bar */
682 if (HAS_MENU(wndPtr))
684 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
685 return HTMENU;
688 /* Has to return HTNOWHERE if nothing was found
689 Could happen when a window has a customized non client area */
690 return HTNOWHERE;
694 /***********************************************************************
695 * NC_HandleNCHitTest
697 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
699 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
701 LONG retvalue;
702 WND *wndPtr = WIN_GetPtr( hwnd );
704 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
706 retvalue = NC_DoNCHitTest (wndPtr, pt);
707 WIN_ReleasePtr( wndPtr );
708 return retvalue;
712 /******************************************************************************
714 * NC_DrawSysButton
716 * Draws the system icon.
718 *****************************************************************************/
719 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
721 HICON hIcon = NC_IconForWindow( hwnd );
723 if (hIcon)
725 RECT rect;
726 NC_GetInsideRect( hwnd, &rect );
727 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
728 GetSystemMetrics(SM_CXSMICON),
729 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
731 return (hIcon != 0);
735 /******************************************************************************
737 * NC_DrawCloseButton
739 * Draws the close button.
741 * If bGrayed is true, then draw a disabled Close button
743 *****************************************************************************/
745 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
747 RECT rect;
749 NC_GetInsideRect( hwnd, &rect );
751 /* A tool window has a smaller Close button */
752 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
754 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
755 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
756 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
758 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
759 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
760 rect.bottom = rect.top + iBmpHeight;
761 rect.right = rect.left + iBmpWidth;
763 else
765 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
766 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
767 rect.top += 2;
768 rect.right -= 2;
770 DrawFrameControl( hdc, &rect, DFC_CAPTION,
771 (DFCS_CAPTIONCLOSE |
772 (down ? DFCS_PUSHED : 0) |
773 (bGrayed ? DFCS_INACTIVE : 0)) );
776 /******************************************************************************
777 * NC_DrawMaxButton
779 * Draws the maximize button for windows.
780 * If bGrayed is true, then draw a disabled Maximize button
782 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
784 RECT rect;
785 UINT flags;
787 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
788 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
789 return;
791 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
793 NC_GetInsideRect( hwnd, &rect );
794 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
795 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
796 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
797 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
798 rect.top += 2;
799 rect.right -= 2;
800 if (down) flags |= DFCS_PUSHED;
801 if (bGrayed) flags |= DFCS_INACTIVE;
802 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
805 /******************************************************************************
806 * NC_DrawMinButton
808 * Draws the minimize button for windows.
809 * If bGrayed is true, then draw a disabled Minimize button
811 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
813 RECT rect;
814 UINT flags = DFCS_CAPTIONMIN;
815 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
817 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
818 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
819 return;
821 NC_GetInsideRect( hwnd, &rect );
822 if (style & WS_SYSMENU)
823 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
824 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
825 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
826 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
827 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
828 rect.top += 2;
829 rect.right -= 2;
830 if (down) flags |= DFCS_PUSHED;
831 if (bGrayed) flags |= DFCS_INACTIVE;
832 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
835 /******************************************************************************
837 * NC_DrawFrame
839 * Draw a window frame inside the given rectangle, and update the rectangle.
841 * Bugs
842 * Many. First, just what IS a frame in Win95? Note that the 3D look
843 * on the outer edge is handled by NC_DoNCPaint. As is the inner
844 * edge. The inner rectangle just inside the frame is handled by the
845 * Caption code.
847 * In short, for most people, this function should be a nop (unless
848 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
849 * them lately, but just to get this code right). Even so, it doesn't
850 * appear to be so. It's being worked on...
852 *****************************************************************************/
854 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
856 INT width, height;
858 /* Firstly the "thick" frame */
859 if (style & WS_THICKFRAME)
861 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
862 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
864 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
865 COLOR_INACTIVEBORDER) );
866 /* Draw frame */
867 PatBlt( hdc, rect->left, rect->top,
868 rect->right - rect->left, height, PATCOPY );
869 PatBlt( hdc, rect->left, rect->top,
870 width, rect->bottom - rect->top, PATCOPY );
871 PatBlt( hdc, rect->left, rect->bottom - 1,
872 rect->right - rect->left, -height, PATCOPY );
873 PatBlt( hdc, rect->right - 1, rect->top,
874 -width, rect->bottom - rect->top, PATCOPY );
876 InflateRect( rect, -width, -height );
879 /* Now the other bit of the frame */
880 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
881 (exStyle & WS_EX_DLGMODALFRAME))
883 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
884 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
885 /* This should give a value of 1 that should also work for a border */
887 SelectObject( hdc, GetSysColorBrush(
888 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
889 COLOR_3DFACE :
890 (exStyle & WS_EX_STATICEDGE) ?
891 COLOR_WINDOWFRAME :
892 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
893 COLOR_3DFACE :
894 /* else */
895 COLOR_WINDOWFRAME));
897 /* Draw frame */
898 PatBlt( hdc, rect->left, rect->top,
899 rect->right - rect->left, height, PATCOPY );
900 PatBlt( hdc, rect->left, rect->top,
901 width, rect->bottom - rect->top, PATCOPY );
902 PatBlt( hdc, rect->left, rect->bottom - 1,
903 rect->right - rect->left, -height, PATCOPY );
904 PatBlt( hdc, rect->right - 1, rect->top,
905 -width, rect->bottom - rect->top, PATCOPY );
907 InflateRect( rect, -width, -height );
912 /******************************************************************************
914 * NC_DrawCaption
916 * Draw the window caption for windows.
917 * The correct pen for the window frame must be selected in the DC.
919 *****************************************************************************/
921 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
922 DWORD exStyle, BOOL active )
924 RECT r = *rect;
925 WCHAR buffer[256];
926 HPEN hPrevPen;
927 HMENU hSysMenu;
928 BOOL gradient = FALSE;
930 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
931 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
932 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
933 COLOR_WINDOWFRAME : COLOR_3DFACE) );
934 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
935 LineTo( hdc, r.right, r.bottom - 1 );
936 SelectObject( hdc, hPrevPen );
937 r.bottom--;
939 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
940 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
942 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
943 if (NC_DrawSysButton (hwnd, hdc, FALSE))
944 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
947 if (style & WS_SYSMENU)
949 UINT state;
951 /* Go get the sysmenu */
952 hSysMenu = GetSystemMenu(hwnd, FALSE);
953 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
955 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
956 NC_DrawCloseButton (hwnd, hdc, FALSE,
957 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
958 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
960 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
962 /* In win95 the two buttons are always there */
963 /* But if the menu item is not in the menu they're disabled*/
965 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
966 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
968 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
969 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
973 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
975 NONCLIENTMETRICSW nclm;
976 HFONT hFont, hOldFont;
977 nclm.cbSize = sizeof(nclm);
978 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
979 if (exStyle & WS_EX_TOOLWINDOW)
980 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
981 else
982 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
983 hOldFont = SelectObject (hdc, hFont);
984 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
985 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
986 SetBkMode( hdc, TRANSPARENT );
987 r.left += 2;
988 DrawTextW( hdc, buffer, -1, &r,
989 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
990 DeleteObject (SelectObject (hdc, hOldFont));
995 /******************************************************************************
996 * NC_DoNCPaint
998 * Paint the non-client area for windows.
1000 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1002 HDC hdc;
1003 RECT rfuzz, rect, rectClip;
1004 BOOL active;
1005 WND *wndPtr;
1006 DWORD dwStyle, dwExStyle;
1007 WORD flags;
1008 HRGN hrgn;
1009 RECT rectClient, rectWindow;
1010 int has_menu;
1012 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1013 has_menu = HAS_MENU(wndPtr);
1014 dwStyle = wndPtr->dwStyle;
1015 dwExStyle = wndPtr->dwExStyle;
1016 flags = wndPtr->flags;
1017 rectWindow = wndPtr->rectWindow;
1018 WIN_ReleasePtr( wndPtr );
1020 if ( dwStyle & WS_MINIMIZE ||
1021 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1023 active = flags & WIN_NCACTIVATED;
1025 TRACE("%p %d\n", hwnd, active );
1027 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1028 the call to GetDCEx implying that it is allowed not to use it either.
1029 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1030 will cause clipRgn to be deleted after ReleaseDC().
1031 Now, how is the "system" supposed to tell what happened?
1034 GetClientRect( hwnd, &rectClient );
1035 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1036 hrgn = CreateRectRgnIndirect( &rectClient );
1038 if (clip > (HRGN)1)
1040 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1041 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1043 else
1045 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1048 if (!hdc) return;
1050 rect.top = rect.left = 0;
1051 rect.right = rectWindow.right - rectWindow.left;
1052 rect.bottom = rectWindow.bottom - rectWindow.top;
1053 GetClipBox( hdc, &rectClip );
1055 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1057 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1058 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1060 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1061 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1064 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1066 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1068 RECT r = rect;
1069 if (dwExStyle & WS_EX_TOOLWINDOW) {
1070 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1071 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1073 else {
1074 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1075 rect.top += GetSystemMetrics(SM_CYCAPTION);
1077 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1078 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1081 if (has_menu)
1083 RECT r = rect;
1084 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1086 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1087 r.left, r.top, r.right, r.bottom);
1089 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1092 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1093 rect.left, rect.top, rect.right, rect.bottom );
1095 if (dwExStyle & WS_EX_CLIENTEDGE)
1096 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1098 /* Draw the scroll-bars */
1100 if (dwStyle & WS_VSCROLL)
1101 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1102 if (dwStyle & WS_HSCROLL)
1103 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1105 /* Draw the "size-box" */
1106 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1108 RECT r = rect;
1109 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1110 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1111 else
1112 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1113 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1114 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1117 ReleaseDC( hwnd, hdc );
1123 /***********************************************************************
1124 * NC_HandleNCPaint
1126 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1128 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1130 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1132 if( dwStyle & WS_VISIBLE )
1134 if( dwStyle & WS_MINIMIZE )
1135 WINPOS_RedrawIconTitle( hwnd );
1136 else
1137 NC_DoNCPaint( hwnd, clip, FALSE );
1139 return 0;
1143 /***********************************************************************
1144 * NC_HandleNCActivate
1146 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1148 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1150 WND* wndPtr = WIN_GetPtr( hwnd );
1152 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1154 /* Lotus Notes draws menu descriptions in the caption of its main
1155 * window. When it wants to restore original "system" view, it just
1156 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1157 * attempt to minimize redrawings lead to a not restored caption.
1159 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1160 else wndPtr->flags &= ~WIN_NCACTIVATED;
1161 WIN_ReleasePtr( wndPtr );
1163 if (IsIconic(hwnd))
1164 WINPOS_RedrawIconTitle( hwnd );
1165 else
1166 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1168 return TRUE;
1172 /***********************************************************************
1173 * NC_HandleSetCursor
1175 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1177 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1179 hwnd = WIN_GetFullHandle( (HWND)wParam );
1181 switch((short)LOWORD(lParam))
1183 case HTERROR:
1185 WORD msg = HIWORD( lParam );
1186 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1187 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1188 MessageBeep(0);
1190 break;
1192 case HTCLIENT:
1194 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1195 if(hCursor) {
1196 SetCursor(hCursor);
1197 return TRUE;
1199 return FALSE;
1202 case HTLEFT:
1203 case HTRIGHT:
1204 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1206 case HTTOP:
1207 case HTBOTTOM:
1208 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1210 case HTTOPLEFT:
1211 case HTBOTTOMRIGHT:
1212 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1214 case HTTOPRIGHT:
1215 case HTBOTTOMLEFT:
1216 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1219 /* Default cursor: arrow */
1220 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1223 /***********************************************************************
1224 * NC_GetSysPopupPos
1226 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1228 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1229 else
1231 WND *wndPtr = WIN_GetPtr( hwnd );
1232 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1234 NC_GetInsideRect( hwnd, rect );
1235 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1236 if (wndPtr->dwStyle & WS_CHILD)
1237 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1238 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1239 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1240 WIN_ReleasePtr( wndPtr );
1244 /***********************************************************************
1245 * NC_TrackMinMaxBox
1247 * Track a mouse button press on the minimize or maximize box.
1249 * The big difference between 3.1 and 95 is the disabled button state.
1250 * In win95 the system button can be disabled, so it can ignore the mouse
1251 * event.
1254 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1256 MSG msg;
1257 HDC hdc = GetWindowDC( hwnd );
1258 BOOL pressed = TRUE;
1259 UINT state;
1260 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1261 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1263 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1265 if (wParam == HTMINBUTTON)
1267 /* If the style is not present, do nothing */
1268 if (!(wndStyle & WS_MINIMIZEBOX))
1269 return;
1271 /* Check if the sysmenu item for minimize is there */
1272 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1274 paintButton = &NC_DrawMinButton;
1276 else
1278 /* If the style is not present, do nothing */
1279 if (!(wndStyle & WS_MAXIMIZEBOX))
1280 return;
1282 /* Check if the sysmenu item for maximize is there */
1283 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1285 paintButton = &NC_DrawMaxButton;
1288 SetCapture( hwnd );
1290 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1292 while(1)
1294 BOOL oldstate = pressed;
1296 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1297 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1299 if(msg.message == WM_LBUTTONUP)
1300 break;
1302 if(msg.message != WM_MOUSEMOVE)
1303 continue;
1305 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1306 if (pressed != oldstate)
1307 (*paintButton)( hwnd, hdc, pressed, FALSE);
1310 if(pressed)
1311 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1313 ReleaseCapture();
1314 ReleaseDC( hwnd, hdc );
1316 /* If the item minimize or maximize of the sysmenu are not there */
1317 /* or if the style is not present, do nothing */
1318 if ((!pressed) || (state == 0xFFFFFFFF))
1319 return;
1321 if (wParam == HTMINBUTTON)
1322 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1323 else
1324 SendMessageA( hwnd, WM_SYSCOMMAND,
1325 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1328 /***********************************************************************
1329 * NC_TrackCloseButton
1331 * Track a mouse button press on the Win95 close button.
1333 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1335 MSG msg;
1336 HDC hdc;
1337 BOOL pressed = TRUE;
1338 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1339 UINT state;
1341 if(hSysMenu == 0)
1342 return;
1344 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1346 /* If the item close of the sysmenu is disabled or not there do nothing */
1347 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1348 return;
1350 hdc = GetWindowDC( hwnd );
1352 SetCapture( hwnd );
1354 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1356 while(1)
1358 BOOL oldstate = pressed;
1360 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1361 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1363 if(msg.message == WM_LBUTTONUP)
1364 break;
1366 if(msg.message != WM_MOUSEMOVE)
1367 continue;
1369 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1370 if (pressed != oldstate)
1371 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1374 if(pressed)
1375 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1377 ReleaseCapture();
1378 ReleaseDC( hwnd, hdc );
1379 if (!pressed) return;
1381 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1385 /***********************************************************************
1386 * NC_TrackScrollBar
1388 * Track a mouse button press on the horizontal or vertical scroll-bar.
1390 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1392 INT scrollbar;
1394 if ((wParam & 0xfff0) == SC_HSCROLL)
1396 if ((wParam & 0x0f) != HTHSCROLL) return;
1397 scrollbar = SB_HORZ;
1399 else /* SC_VSCROLL */
1401 if ((wParam & 0x0f) != HTVSCROLL) return;
1402 scrollbar = SB_VERT;
1404 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1408 /***********************************************************************
1409 * NC_HandleNCLButtonDown
1411 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1413 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1415 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1417 switch(wParam) /* Hit test */
1419 case HTCAPTION:
1421 HWND top = GetAncestor( hwnd, GA_ROOT );
1423 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1424 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1425 break;
1428 case HTSYSMENU:
1429 if( style & WS_SYSMENU )
1431 if( !(style & WS_MINIMIZE) )
1433 HDC hDC = GetWindowDC(hwnd);
1434 NC_DrawSysButton( hwnd, hDC, TRUE );
1435 ReleaseDC( hwnd, hDC );
1437 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1439 break;
1441 case HTMENU:
1442 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1443 break;
1445 case HTHSCROLL:
1446 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1447 break;
1449 case HTVSCROLL:
1450 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1451 break;
1453 case HTMINBUTTON:
1454 case HTMAXBUTTON:
1455 NC_TrackMinMaxBox( hwnd, wParam );
1456 break;
1458 case HTCLOSE:
1459 NC_TrackCloseButton (hwnd, wParam);
1460 break;
1462 case HTLEFT:
1463 case HTRIGHT:
1464 case HTTOP:
1465 case HTTOPLEFT:
1466 case HTTOPRIGHT:
1467 case HTBOTTOM:
1468 case HTBOTTOMLEFT:
1469 case HTBOTTOMRIGHT:
1470 /* Old comment:
1471 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1472 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1474 /* But that is not what WinNT does. Instead it sends this. This
1475 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1476 * SC_MOUSEMENU into wParam.
1478 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1479 break;
1481 case HTBORDER:
1482 break;
1484 return 0;
1488 /***********************************************************************
1489 * NC_HandleNCLButtonDblClk
1491 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1493 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1496 * if this is an icon, send a restore since we are handling
1497 * a double click
1499 if (IsIconic(hwnd))
1501 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1502 return 0;
1505 switch(wParam) /* Hit test */
1507 case HTCAPTION:
1508 /* stop processing if WS_MAXIMIZEBOX is missing */
1509 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1510 SendMessageW( hwnd, WM_SYSCOMMAND,
1511 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1512 break;
1514 case HTSYSMENU:
1516 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1517 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1519 /* If the item close of the sysmenu is disabled or not there do nothing */
1520 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1521 break;
1523 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1524 break;
1527 case HTHSCROLL:
1528 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1529 break;
1531 case HTVSCROLL:
1532 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1533 break;
1535 return 0;
1539 /***********************************************************************
1540 * NC_HandleSysCommand
1542 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1544 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1546 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1548 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1549 return 0;
1551 switch (wParam & 0xfff0)
1553 case SC_SIZE:
1554 case SC_MOVE:
1555 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1556 break;
1558 case SC_MINIMIZE:
1559 if (hwnd == GetForegroundWindow())
1560 ShowOwnedPopups(hwnd,FALSE);
1561 ShowWindow( hwnd, SW_MINIMIZE );
1562 break;
1564 case SC_MAXIMIZE:
1565 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1566 ShowOwnedPopups(hwnd,TRUE);
1567 ShowWindow( hwnd, SW_MAXIMIZE );
1568 break;
1570 case SC_RESTORE:
1571 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1572 ShowOwnedPopups(hwnd,TRUE);
1573 ShowWindow( hwnd, SW_RESTORE );
1574 break;
1576 case SC_CLOSE:
1577 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
1579 case SC_VSCROLL:
1580 case SC_HSCROLL:
1582 POINT pt;
1583 pt.x = (short)LOWORD(lParam);
1584 pt.y = (short)HIWORD(lParam);
1585 NC_TrackScrollBar( hwnd, wParam, pt );
1587 break;
1589 case SC_MOUSEMENU:
1591 POINT pt;
1592 pt.x = (short)LOWORD(lParam);
1593 pt.y = (short)HIWORD(lParam);
1594 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1596 break;
1598 case SC_KEYMENU:
1599 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1600 break;
1602 case SC_TASKLIST:
1603 WinExec( "taskman.exe", SW_SHOWNORMAL );
1604 break;
1606 case SC_SCREENSAVE:
1607 if (wParam == SC_ABOUTWINE)
1609 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1610 if (hmodule)
1612 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1613 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1614 FreeLibrary( hmodule );
1617 else
1618 if (wParam == SC_PUTMARK)
1619 DPRINTF("Debug mark requested by user\n");
1620 break;
1622 case SC_HOTKEY:
1623 case SC_ARRANGE:
1624 case SC_NEXTWINDOW:
1625 case SC_PREVWINDOW:
1626 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1627 break;
1629 return 0;
1632 /*************************************************************
1633 * NC_DrawGrayButton
1635 * Stub for the grayed button of the caption
1637 *************************************************************/
1639 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1641 HBITMAP hMaskBmp;
1642 HDC hdcMask;
1643 HBRUSH hOldBrush;
1645 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1647 if(hMaskBmp == 0)
1648 return FALSE;
1650 hdcMask = CreateCompatibleDC (0);
1651 SelectObject (hdcMask, hMaskBmp);
1653 /* Draw the grayed bitmap using the mask */
1654 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1655 BitBlt (hdc, x, y, 12, 10,
1656 hdcMask, 0, 0, 0xB8074A);
1658 /* Clean up */
1659 SelectObject (hdc, hOldBrush);
1660 DeleteObject(hMaskBmp);
1661 DeleteDC (hdcMask);
1663 return TRUE;
1666 /***********************************************************************
1667 * GetTitleBarInfo (USER32.@)
1668 * TODO: Handle STATE_SYSTEM_PRESSED
1670 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1671 DWORD dwStyle;
1672 DWORD dwExStyle;
1673 RECT wndRect;
1675 TRACE("(%p %p)\n", hwnd, tbi);
1677 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1678 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1679 SetLastError(ERROR_INVALID_PARAMETER);
1680 return FALSE;
1682 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1683 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1684 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1686 GetWindowRect(hwnd, &wndRect);
1688 tbi->rcTitleBar.top += wndRect.top;
1689 tbi->rcTitleBar.left += wndRect.left;
1690 tbi->rcTitleBar.right += wndRect.left;
1692 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1693 if(dwExStyle & WS_EX_TOOLWINDOW)
1694 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1695 else {
1696 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1697 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1700 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1701 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1702 * Under XP it seems to
1704 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1705 if(dwStyle & WS_CAPTION) {
1706 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1707 if(dwStyle & WS_SYSMENU) {
1708 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1709 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1710 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1712 else {
1713 if(!(dwStyle & WS_MINIMIZEBOX))
1714 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1715 if(!(dwStyle & WS_MAXIMIZEBOX))
1716 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1718 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1719 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1720 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1721 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1723 else {
1724 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1726 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1727 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1730 else
1731 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1732 return TRUE;