oleaut32: Fix parsing of hex numbers with 'e' in the string by moving
[wine/wine64.git] / dlls / user / nonclient.c
blob00c29133b42b5bf8853936c64d506eec207436a1
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 "wine/winuser16.h"
29 #include "wownt32.h"
30 #include "win.h"
31 #include "user_private.h"
32 #include "controls.h"
33 #include "shellapi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
38 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
40 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
41 0x55, 0x50,
42 0xAA, 0xA0,
43 0x55, 0x50,
44 0xAA, 0xA0,
45 0x55, 0x50,
46 0xAA, 0xA0,
47 0x55, 0x50,
48 0xAA, 0xA0,
49 0x55, 0x50};
51 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
52 #define SC_PUTMARK (SC_SCREENSAVE+2)
54 /* Some useful macros */
55 #define HAS_DLGFRAME(style,exStyle) \
56 (((exStyle) & WS_EX_DLGMODALFRAME) || \
57 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
59 #define HAS_THICKFRAME(style,exStyle) \
60 (((style) & WS_THICKFRAME) && \
61 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
63 #define HAS_THINFRAME(style) \
64 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
66 #define HAS_BIGFRAME(style,exStyle) \
67 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
68 ((exStyle) & WS_EX_DLGMODALFRAME))
70 #define HAS_STATICOUTERFRAME(style,exStyle) \
71 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
72 WS_EX_STATICEDGE)
74 #define HAS_ANYFRAME(style,exStyle) \
75 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
76 ((exStyle) & WS_EX_DLGMODALFRAME) || \
77 !((style) & (WS_CHILD | WS_POPUP)))
79 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
82 /******************************************************************************
83 * NC_AdjustRectOuter
85 * Computes the size of the "outside" parts of the window based on the
86 * parameters of the client area.
88 * PARAMS
89 * LPRECT rect
90 * DWORD style
91 * BOOL menu
92 * DWORD exStyle
94 * NOTES
95 * "Outer" parts of a window means the whole window frame, caption and
96 * menu bar. It does not include "inner" parts of the frame like client
97 * edge, static edge or scroll bars.
99 *****************************************************************************/
101 static void
102 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
104 int adjust;
105 if(style & WS_ICONIC) return;
107 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
108 WS_EX_STATICEDGE)
110 adjust = 1; /* for the outer frame always present */
112 else
114 adjust = 0;
115 if ((exStyle & WS_EX_DLGMODALFRAME) ||
116 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
118 if (style & WS_THICKFRAME)
119 adjust += ( GetSystemMetrics (SM_CXFRAME)
120 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
121 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
122 (exStyle & WS_EX_DLGMODALFRAME))
123 adjust++; /* The other border */
125 InflateRect (rect, adjust, adjust);
127 if ((style & WS_CAPTION) == WS_CAPTION)
129 if (exStyle & WS_EX_TOOLWINDOW)
130 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
131 else
132 rect->top -= GetSystemMetrics(SM_CYCAPTION);
134 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
138 /******************************************************************************
139 * NC_AdjustRectInner
141 * Computes the size of the "inside" part of the window based on the
142 * parameters of the client area.
144 * PARAMS
145 * LPRECT rect
146 * DWORD style
147 * DWORD exStyle
149 * NOTES
150 * "Inner" part of a window means the window frame inside of the flat
151 * window frame. It includes the client edge, the static edge and the
152 * scroll bars.
154 *****************************************************************************/
156 static void
157 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
159 if(style & WS_ICONIC) return;
161 if (exStyle & WS_EX_CLIENTEDGE)
162 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
164 if (style & WS_VSCROLL)
166 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
167 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
168 else
169 rect->right += GetSystemMetrics(SM_CXVSCROLL);
171 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
176 static HICON NC_IconForWindow( HWND hwnd )
178 HICON hIcon = 0;
179 WND *wndPtr = WIN_GetPtr( hwnd );
181 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
183 hIcon = wndPtr->hIconSmall;
184 if (!hIcon) hIcon = wndPtr->hIcon;
185 WIN_ReleasePtr( wndPtr );
187 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
188 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
190 /* If there is no hIcon specified and this is a modal dialog,
191 * get the default one.
193 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
194 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
195 return hIcon;
198 /* Draws the bar part(ie the big rectangle) of the caption */
199 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
200 BOOL active, BOOL gradient)
202 if (gradient)
204 TRIVERTEX vertices[6];
205 DWORD colLeft =
206 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
207 DWORD colRight =
208 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
209 : COLOR_GRADIENTINACTIVECAPTION);
210 int v;
211 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
212 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
214 for (v = 0; v < 3; v++)
216 vertices[v].Red = GetRValue (colLeft) << 8;
217 vertices[v].Green = GetGValue (colLeft) << 8;
218 vertices[v].Blue = GetBValue (colLeft) << 8;
219 vertices[v].Alpha = 0x8000;
220 vertices[v+3].Red = GetRValue (colRight) << 8;
221 vertices[v+3].Green = GetGValue (colRight) << 8;
222 vertices[v+3].Blue = GetBValue (colRight) << 8;
223 vertices[v+3].Alpha = 0x8000;
226 if ((dwStyle & WS_SYSMENU)
227 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
228 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
230 /* area behind icon; solid filled with left color */
231 vertices[0].x = rect->left;
232 vertices[0].y = rect->top;
233 if (dwStyle & WS_SYSMENU)
234 vertices[1].x =
235 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
236 else
237 vertices[1].x = vertices[0].x;
238 vertices[1].y = rect->bottom;
240 /* area behind text; gradient */
241 vertices[2].x = vertices[1].x;
242 vertices[2].y = rect->top;
243 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
244 vertices[3].y = rect->bottom;
246 /* area behind buttons; solid filled with right color */
247 vertices[4].x = vertices[3].x;
248 vertices[4].y = rect->top;
249 vertices[5].x = rect->right;
250 vertices[5].y = rect->bottom;
252 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
254 else
255 FillRect (hdc, rect, GetSysColorBrush (active ?
256 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
259 /***********************************************************************
260 * DrawCaption (USER32.@) Draws a caption bar
262 * PARAMS
263 * hwnd [I]
264 * hdc [I]
265 * lpRect [I]
266 * uFlags [I]
268 * RETURNS
269 * Success:
270 * Failure:
273 BOOL WINAPI
274 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
276 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
280 /***********************************************************************
281 * DrawCaptionTempA (USER32.@)
283 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
284 HICON hIcon, LPCSTR str, UINT uFlags)
286 LPWSTR strW;
287 INT len;
288 BOOL ret = FALSE;
290 if (!(uFlags & DC_TEXT) || !str)
291 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
293 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
294 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
296 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
297 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
298 HeapFree( GetProcessHeap (), 0, strW );
300 return ret;
304 /***********************************************************************
305 * DrawCaptionTempW (USER32.@)
307 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
308 HICON hIcon, LPCWSTR str, UINT uFlags)
310 RECT rc = *rect;
312 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
313 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
315 /* drawing background */
316 if (uFlags & DC_INBUTTON) {
317 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
319 if (uFlags & DC_ACTIVE) {
320 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
321 PatBlt (hdc, rc.left, rc.top,
322 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
323 SelectObject (hdc, hbr);
326 else {
327 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
328 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
332 /* drawing icon */
333 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
334 POINT pt;
336 pt.x = rc.left + 2;
337 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
339 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
340 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
341 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
342 rc.left += (rc.bottom - rc.top);
345 /* drawing text */
346 if (uFlags & DC_TEXT) {
347 HFONT hOldFont;
349 if (uFlags & DC_INBUTTON)
350 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
351 else if (uFlags & DC_ACTIVE)
352 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
353 else
354 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
356 SetBkMode (hdc, TRANSPARENT);
358 if (hFont)
359 hOldFont = SelectObject (hdc, hFont);
360 else {
361 NONCLIENTMETRICSW nclm;
362 HFONT hNewFont;
363 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
364 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
365 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
366 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
367 hOldFont = SelectObject (hdc, hNewFont);
370 if (str)
371 DrawTextW (hdc, str, -1, &rc,
372 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
373 else {
374 WCHAR szText[128];
375 INT nLen;
376 nLen = GetWindowTextW (hwnd, szText, 128);
377 DrawTextW (hdc, szText, nLen, &rc,
378 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
381 if (hFont)
382 SelectObject (hdc, hOldFont);
383 else
384 DeleteObject (SelectObject (hdc, hOldFont));
387 /* drawing focus ??? */
388 if (uFlags & 0x2000)
389 FIXME("undocumented flag (0x2000)!\n");
391 return 0;
395 /***********************************************************************
396 * AdjustWindowRect (USER32.@)
398 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
400 return AdjustWindowRectEx( rect, style, menu, 0 );
404 /***********************************************************************
405 * AdjustWindowRectEx (USER32.@)
407 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
409 /* Correct the window style */
410 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
411 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
412 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
413 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
415 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
416 rect->left, rect->top, rect->right, rect->bottom,
417 style, menu, exStyle );
419 NC_AdjustRectOuter( rect, style, menu, exStyle );
420 NC_AdjustRectInner( rect, style, exStyle );
422 return TRUE;
426 /***********************************************************************
427 * NC_HandleNCCalcSize
429 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
431 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
433 RECT tmpRect = { 0, 0, 0, 0 };
434 LRESULT result = 0;
435 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
436 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
437 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
439 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
440 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
442 if (!IsIconic(hwnd))
444 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
446 winRect->left -= tmpRect.left;
447 winRect->top -= tmpRect.top;
448 winRect->right -= tmpRect.right;
449 winRect->bottom -= tmpRect.bottom;
451 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
453 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
454 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
456 winRect->top +=
457 MENU_GetMenuBarHeight( hwnd,
458 winRect->right - winRect->left,
459 -tmpRect.left, -tmpRect.top );
462 if( exStyle & WS_EX_CLIENTEDGE)
463 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
464 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
465 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
466 - GetSystemMetrics(SM_CYEDGE));
468 if (style & WS_VSCROLL)
469 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
470 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
471 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
472 else
473 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
476 if (style & WS_HSCROLL)
477 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
478 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
480 if (winRect->top > winRect->bottom)
481 winRect->bottom = winRect->top;
483 if (winRect->left > winRect->right)
484 winRect->right = winRect->left;
486 return result;
490 /***********************************************************************
491 * NC_GetInsideRect
493 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
494 * but without the borders (if any).
495 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
497 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
499 WND *wndPtr = WIN_GetPtr( hwnd );
501 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
503 rect->top = rect->left = 0;
504 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
505 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
507 if (wndPtr->dwStyle & WS_ICONIC) goto END;
509 /* Remove frame from rectangle */
510 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
512 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
514 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
516 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
518 else if (HAS_THINFRAME( wndPtr->dwStyle ))
520 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
523 /* We have additional border information if the window
524 * is a child (but not an MDI child) */
525 if ( (wndPtr->dwStyle & WS_CHILD) &&
526 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
528 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
529 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
530 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
531 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
534 END:
535 WIN_ReleasePtr( wndPtr );
539 /***********************************************************************
540 * NC_DoNCHitTest
542 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
544 * FIXME: Just a modified copy of the Win 3.1 version.
547 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
549 RECT rect, rcClient;
550 POINT ptClient;
552 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
554 GetWindowRect(wndPtr->hwndSelf, &rect );
555 if (!PtInRect( &rect, pt )) return HTNOWHERE;
557 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
559 /* Check client area */
560 ptClient = pt;
561 ScreenToClient( wndPtr->hwndSelf, &ptClient );
562 GetClientRect( wndPtr->hwndSelf, &rcClient );
563 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
565 /* Check borders */
566 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
568 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
569 if (!PtInRect( &rect, pt ))
571 /* Check top sizing border */
572 if (pt.y < rect.top)
574 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
575 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
576 return HTTOP;
578 /* Check bottom sizing border */
579 if (pt.y >= rect.bottom)
581 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
582 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
583 return HTBOTTOM;
585 /* Check left sizing border */
586 if (pt.x < rect.left)
588 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
589 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
590 return HTLEFT;
592 /* Check right sizing border */
593 if (pt.x >= rect.right)
595 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
596 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
597 return HTRIGHT;
601 else /* No thick frame */
603 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
604 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
605 else if (HAS_THINFRAME( wndPtr->dwStyle ))
606 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
607 if (!PtInRect( &rect, pt )) return HTBORDER;
610 /* Check caption */
612 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
614 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
615 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
616 else
617 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
618 if (!PtInRect( &rect, pt ))
620 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
621 (wndPtr->dwStyle & WS_MINIMIZEBOX);
622 /* Check system menu */
623 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
625 if (NC_IconForWindow(wndPtr->hwndSelf))
626 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
628 if (pt.x < rect.left) return HTSYSMENU;
630 /* Check close button */
631 if (wndPtr->dwStyle & WS_SYSMENU)
632 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
633 if (pt.x > rect.right) return HTCLOSE;
635 /* Check maximize box */
636 /* In win95 there is automatically a Maximize button when there is a minimize one*/
637 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
638 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
639 if (pt.x > rect.right) return HTMAXBUTTON;
641 /* Check minimize box */
642 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
643 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
644 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
646 if (pt.x > rect.right) return HTMINBUTTON;
647 return HTCAPTION;
651 /* Check vertical scroll bar */
653 if (wndPtr->dwStyle & WS_VSCROLL)
655 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
656 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
657 else
658 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
659 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
662 /* Check horizontal scroll bar */
664 if (wndPtr->dwStyle & WS_HSCROLL)
666 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
667 if (PtInRect( &rcClient, ptClient ))
669 /* Check size box */
670 if ((wndPtr->dwStyle & WS_VSCROLL) &&
671 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
672 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
673 return HTSIZE;
674 return HTHSCROLL;
678 /* Check menu bar */
680 if (HAS_MENU(wndPtr))
682 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
683 return HTMENU;
686 /* Has to return HTNOWHERE if nothing was found
687 Could happen when a window has a customized non client area */
688 return HTNOWHERE;
692 /***********************************************************************
693 * NC_HandleNCHitTest
695 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
697 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
699 LRESULT retvalue;
700 WND *wndPtr = WIN_GetPtr( hwnd );
702 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
704 retvalue = NC_DoNCHitTest (wndPtr, pt);
705 WIN_ReleasePtr( wndPtr );
706 return retvalue;
710 /******************************************************************************
712 * NC_DrawSysButton
714 * Draws the system icon.
716 *****************************************************************************/
717 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
719 HICON hIcon = NC_IconForWindow( hwnd );
721 if (hIcon)
723 RECT rect;
724 NC_GetInsideRect( hwnd, &rect );
725 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
726 GetSystemMetrics(SM_CXSMICON),
727 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
729 return (hIcon != 0);
733 /******************************************************************************
735 * NC_DrawCloseButton
737 * Draws the close button.
739 * If bGrayed is true, then draw a disabled Close button
741 *****************************************************************************/
743 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
745 RECT rect;
747 NC_GetInsideRect( hwnd, &rect );
749 /* A tool window has a smaller Close button */
750 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
752 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
753 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
754 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
756 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
757 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
758 rect.bottom = rect.top + iBmpHeight;
759 rect.right = rect.left + iBmpWidth;
761 else
763 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
764 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
765 rect.top += 2;
766 rect.right -= 2;
768 DrawFrameControl( hdc, &rect, DFC_CAPTION,
769 (DFCS_CAPTIONCLOSE |
770 (down ? DFCS_PUSHED : 0) |
771 (bGrayed ? DFCS_INACTIVE : 0)) );
774 /******************************************************************************
775 * NC_DrawMaxButton
777 * Draws the maximize button for windows.
778 * If bGrayed is true, then draw a disabled Maximize button
780 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
782 RECT rect;
783 UINT flags;
785 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
786 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
787 return;
789 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
791 NC_GetInsideRect( hwnd, &rect );
792 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
793 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
794 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
795 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
796 rect.top += 2;
797 rect.right -= 2;
798 if (down) flags |= DFCS_PUSHED;
799 if (bGrayed) flags |= DFCS_INACTIVE;
800 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
803 /******************************************************************************
804 * NC_DrawMinButton
806 * Draws the minimize button for windows.
807 * If bGrayed is true, then draw a disabled Minimize button
809 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
811 RECT rect;
812 UINT flags = DFCS_CAPTIONMIN;
813 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
815 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
816 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
817 return;
819 NC_GetInsideRect( hwnd, &rect );
820 if (style & WS_SYSMENU)
821 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
822 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
823 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
824 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
825 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
826 rect.top += 2;
827 rect.right -= 2;
828 if (down) flags |= DFCS_PUSHED;
829 if (bGrayed) flags |= DFCS_INACTIVE;
830 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
833 /******************************************************************************
835 * NC_DrawFrame
837 * Draw a window frame inside the given rectangle, and update the rectangle.
839 * Bugs
840 * Many. First, just what IS a frame in Win95? Note that the 3D look
841 * on the outer edge is handled by NC_DoNCPaint. As is the inner
842 * edge. The inner rectangle just inside the frame is handled by the
843 * Caption code.
845 * In short, for most people, this function should be a nop (unless
846 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
847 * them lately, but just to get this code right). Even so, it doesn't
848 * appear to be so. It's being worked on...
850 *****************************************************************************/
852 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
854 INT width, height;
856 /* Firstly the "thick" frame */
857 if (style & WS_THICKFRAME)
859 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
860 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
862 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
863 COLOR_INACTIVEBORDER) );
864 /* Draw frame */
865 PatBlt( hdc, rect->left, rect->top,
866 rect->right - rect->left, height, PATCOPY );
867 PatBlt( hdc, rect->left, rect->top,
868 width, rect->bottom - rect->top, PATCOPY );
869 PatBlt( hdc, rect->left, rect->bottom - 1,
870 rect->right - rect->left, -height, PATCOPY );
871 PatBlt( hdc, rect->right - 1, rect->top,
872 -width, rect->bottom - rect->top, PATCOPY );
874 InflateRect( rect, -width, -height );
877 /* Now the other bit of the frame */
878 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
879 (exStyle & WS_EX_DLGMODALFRAME))
881 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
882 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
883 /* This should give a value of 1 that should also work for a border */
885 SelectObject( hdc, GetSysColorBrush(
886 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
887 COLOR_3DFACE :
888 (exStyle & WS_EX_STATICEDGE) ?
889 COLOR_WINDOWFRAME :
890 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
891 COLOR_3DFACE :
892 /* else */
893 COLOR_WINDOWFRAME));
895 /* Draw frame */
896 PatBlt( hdc, rect->left, rect->top,
897 rect->right - rect->left, height, PATCOPY );
898 PatBlt( hdc, rect->left, rect->top,
899 width, rect->bottom - rect->top, PATCOPY );
900 PatBlt( hdc, rect->left, rect->bottom - 1,
901 rect->right - rect->left, -height, PATCOPY );
902 PatBlt( hdc, rect->right - 1, rect->top,
903 -width, rect->bottom - rect->top, PATCOPY );
905 InflateRect( rect, -width, -height );
910 /******************************************************************************
912 * NC_DrawCaption
914 * Draw the window caption for windows.
915 * The correct pen for the window frame must be selected in the DC.
917 *****************************************************************************/
919 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
920 DWORD exStyle, BOOL active )
922 RECT r = *rect;
923 WCHAR buffer[256];
924 HPEN hPrevPen;
925 HMENU hSysMenu;
926 BOOL gradient = FALSE;
928 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
929 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
930 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
931 COLOR_WINDOWFRAME : COLOR_3DFACE) );
932 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
933 LineTo( hdc, r.right, r.bottom - 1 );
934 SelectObject( hdc, hPrevPen );
935 r.bottom--;
937 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
938 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
940 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
941 if (NC_DrawSysButton (hwnd, hdc, FALSE))
942 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
945 if (style & WS_SYSMENU)
947 UINT state;
949 /* Go get the sysmenu */
950 hSysMenu = GetSystemMenu(hwnd, FALSE);
951 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
953 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
954 NC_DrawCloseButton (hwnd, hdc, FALSE,
955 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
956 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
958 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
960 /* In win95 the two buttons are always there */
961 /* But if the menu item is not in the menu they're disabled*/
963 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
964 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
966 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
967 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
971 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
973 NONCLIENTMETRICSW nclm;
974 HFONT hFont, hOldFont;
975 nclm.cbSize = sizeof(nclm);
976 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
977 if (exStyle & WS_EX_TOOLWINDOW)
978 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
979 else
980 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
981 hOldFont = SelectObject (hdc, hFont);
982 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
983 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
984 SetBkMode( hdc, TRANSPARENT );
985 r.left += 2;
986 DrawTextW( hdc, buffer, -1, &r,
987 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
988 DeleteObject (SelectObject (hdc, hOldFont));
993 /******************************************************************************
994 * NC_DoNCPaint
996 * Paint the non-client area for windows.
998 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1000 HDC hdc;
1001 RECT rfuzz, rect, rectClip;
1002 BOOL active;
1003 WND *wndPtr;
1004 DWORD dwStyle, dwExStyle;
1005 WORD flags;
1006 HRGN hrgn;
1007 RECT rectClient, rectWindow;
1008 int has_menu;
1010 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1011 has_menu = HAS_MENU(wndPtr);
1012 dwStyle = wndPtr->dwStyle;
1013 dwExStyle = wndPtr->dwExStyle;
1014 flags = wndPtr->flags;
1015 rectWindow = wndPtr->rectWindow;
1016 WIN_ReleasePtr( wndPtr );
1018 if ( dwStyle & WS_MINIMIZE ||
1019 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1021 active = flags & WIN_NCACTIVATED;
1023 TRACE("%p %d\n", hwnd, active );
1025 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1026 the call to GetDCEx implying that it is allowed not to use it either.
1027 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1028 will cause clipRgn to be deleted after ReleaseDC().
1029 Now, how is the "system" supposed to tell what happened?
1032 GetClientRect( hwnd, &rectClient );
1033 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1034 hrgn = CreateRectRgnIndirect( &rectClient );
1036 if (clip > (HRGN)1)
1038 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1039 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1041 else
1043 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1046 if (!hdc) return;
1048 rect.top = rect.left = 0;
1049 rect.right = rectWindow.right - rectWindow.left;
1050 rect.bottom = rectWindow.bottom - rectWindow.top;
1051 GetClipBox( hdc, &rectClip );
1053 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1055 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1056 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1058 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1059 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1062 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1064 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1066 RECT r = rect;
1067 if (dwExStyle & WS_EX_TOOLWINDOW) {
1068 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1069 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1071 else {
1072 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1073 rect.top += GetSystemMetrics(SM_CYCAPTION);
1075 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1076 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1079 if (has_menu)
1081 RECT r = rect;
1082 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1084 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1085 r.left, r.top, r.right, r.bottom);
1087 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1090 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1091 rect.left, rect.top, rect.right, rect.bottom );
1093 if (dwExStyle & WS_EX_CLIENTEDGE)
1094 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1096 /* Draw the scroll-bars */
1098 if (dwStyle & WS_VSCROLL)
1099 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1100 if (dwStyle & WS_HSCROLL)
1101 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1103 /* Draw the "size-box" */
1104 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1106 RECT r = rect;
1107 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1108 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1109 else
1110 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1111 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1112 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1115 ReleaseDC( hwnd, hdc );
1121 /***********************************************************************
1122 * NC_HandleNCPaint
1124 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1126 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1128 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1130 if( dwStyle & WS_VISIBLE )
1132 if( dwStyle & WS_MINIMIZE )
1133 WINPOS_RedrawIconTitle( hwnd );
1134 else
1135 NC_DoNCPaint( hwnd, clip, FALSE );
1137 return 0;
1141 /***********************************************************************
1142 * NC_HandleNCActivate
1144 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1146 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1148 WND* wndPtr = WIN_GetPtr( hwnd );
1150 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1152 /* Lotus Notes draws menu descriptions in the caption of its main
1153 * window. When it wants to restore original "system" view, it just
1154 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1155 * attempt to minimize redrawings lead to a not restored caption.
1157 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1158 else wndPtr->flags &= ~WIN_NCACTIVATED;
1159 WIN_ReleasePtr( wndPtr );
1161 if (IsIconic(hwnd))
1162 WINPOS_RedrawIconTitle( hwnd );
1163 else
1164 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1166 return TRUE;
1170 /***********************************************************************
1171 * NC_HandleSetCursor
1173 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1175 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1177 hwnd = WIN_GetFullHandle( (HWND)wParam );
1179 switch((short)LOWORD(lParam))
1181 case HTERROR:
1183 WORD msg = HIWORD( lParam );
1184 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1185 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1186 MessageBeep(0);
1188 break;
1190 case HTCLIENT:
1192 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1193 if(hCursor) {
1194 SetCursor(hCursor);
1195 return TRUE;
1197 return FALSE;
1200 case HTLEFT:
1201 case HTRIGHT:
1202 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1204 case HTTOP:
1205 case HTBOTTOM:
1206 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1208 case HTTOPLEFT:
1209 case HTBOTTOMRIGHT:
1210 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1212 case HTTOPRIGHT:
1213 case HTBOTTOMLEFT:
1214 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1217 /* Default cursor: arrow */
1218 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1221 /***********************************************************************
1222 * NC_GetSysPopupPos
1224 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1226 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1227 else
1229 WND *wndPtr = WIN_GetPtr( hwnd );
1230 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1232 NC_GetInsideRect( hwnd, rect );
1233 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1234 if (wndPtr->dwStyle & WS_CHILD)
1235 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1236 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1237 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1238 WIN_ReleasePtr( wndPtr );
1242 /***********************************************************************
1243 * NC_TrackMinMaxBox
1245 * Track a mouse button press on the minimize or maximize box.
1247 * The big difference between 3.1 and 95 is the disabled button state.
1248 * In win95 the system button can be disabled, so it can ignore the mouse
1249 * event.
1252 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1254 MSG msg;
1255 HDC hdc = GetWindowDC( hwnd );
1256 BOOL pressed = TRUE;
1257 UINT state;
1258 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1259 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1261 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1263 if (wParam == HTMINBUTTON)
1265 /* If the style is not present, do nothing */
1266 if (!(wndStyle & WS_MINIMIZEBOX))
1267 return;
1269 /* Check if the sysmenu item for minimize is there */
1270 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1272 paintButton = &NC_DrawMinButton;
1274 else
1276 /* If the style is not present, do nothing */
1277 if (!(wndStyle & WS_MAXIMIZEBOX))
1278 return;
1280 /* Check if the sysmenu item for maximize is there */
1281 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1283 paintButton = &NC_DrawMaxButton;
1286 SetCapture( hwnd );
1288 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1290 while(1)
1292 BOOL oldstate = pressed;
1294 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1295 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1297 if(msg.message == WM_LBUTTONUP)
1298 break;
1300 if(msg.message != WM_MOUSEMOVE)
1301 continue;
1303 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1304 if (pressed != oldstate)
1305 (*paintButton)( hwnd, hdc, pressed, FALSE);
1308 if(pressed)
1309 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1311 ReleaseCapture();
1312 ReleaseDC( hwnd, hdc );
1314 /* If the item minimize or maximize of the sysmenu are not there */
1315 /* or if the style is not present, do nothing */
1316 if ((!pressed) || (state == 0xFFFFFFFF))
1317 return;
1319 if (wParam == HTMINBUTTON)
1320 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1321 else
1322 SendMessageW( hwnd, WM_SYSCOMMAND,
1323 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1326 /***********************************************************************
1327 * NC_TrackCloseButton
1329 * Track a mouse button press on the Win95 close button.
1331 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1333 MSG msg;
1334 HDC hdc;
1335 BOOL pressed = TRUE;
1336 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1337 UINT state;
1339 if(hSysMenu == 0)
1340 return;
1342 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1344 /* If the item close of the sysmenu is disabled or not there do nothing */
1345 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1346 return;
1348 hdc = GetWindowDC( hwnd );
1350 SetCapture( hwnd );
1352 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1354 while(1)
1356 BOOL oldstate = pressed;
1358 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1359 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1361 if(msg.message == WM_LBUTTONUP)
1362 break;
1364 if(msg.message != WM_MOUSEMOVE)
1365 continue;
1367 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1368 if (pressed != oldstate)
1369 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1372 if(pressed)
1373 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1375 ReleaseCapture();
1376 ReleaseDC( hwnd, hdc );
1377 if (!pressed) return;
1379 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1383 /***********************************************************************
1384 * NC_TrackScrollBar
1386 * Track a mouse button press on the horizontal or vertical scroll-bar.
1388 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1390 INT scrollbar;
1392 if ((wParam & 0xfff0) == SC_HSCROLL)
1394 if ((wParam & 0x0f) != HTHSCROLL) return;
1395 scrollbar = SB_HORZ;
1397 else /* SC_VSCROLL */
1399 if ((wParam & 0x0f) != HTVSCROLL) return;
1400 scrollbar = SB_VERT;
1402 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1406 /***********************************************************************
1407 * NC_HandleNCLButtonDown
1409 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1411 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1413 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1415 switch(wParam) /* Hit test */
1417 case HTCAPTION:
1419 HWND top = GetAncestor( hwnd, GA_ROOT );
1421 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1422 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1423 break;
1426 case HTSYSMENU:
1427 if( style & WS_SYSMENU )
1429 if( !(style & WS_MINIMIZE) )
1431 HDC hDC = GetWindowDC(hwnd);
1432 NC_DrawSysButton( hwnd, hDC, TRUE );
1433 ReleaseDC( hwnd, hDC );
1435 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1437 break;
1439 case HTMENU:
1440 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1441 break;
1443 case HTHSCROLL:
1444 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1445 break;
1447 case HTVSCROLL:
1448 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1449 break;
1451 case HTMINBUTTON:
1452 case HTMAXBUTTON:
1453 NC_TrackMinMaxBox( hwnd, wParam );
1454 break;
1456 case HTCLOSE:
1457 NC_TrackCloseButton (hwnd, wParam);
1458 break;
1460 case HTLEFT:
1461 case HTRIGHT:
1462 case HTTOP:
1463 case HTTOPLEFT:
1464 case HTTOPRIGHT:
1465 case HTBOTTOM:
1466 case HTBOTTOMLEFT:
1467 case HTBOTTOMRIGHT:
1468 /* Old comment:
1469 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1470 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1472 /* But that is not what WinNT does. Instead it sends this. This
1473 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1474 * SC_MOUSEMENU into wParam.
1476 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1477 break;
1479 case HTBORDER:
1480 break;
1482 return 0;
1486 /***********************************************************************
1487 * NC_HandleNCLButtonDblClk
1489 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1491 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1494 * if this is an icon, send a restore since we are handling
1495 * a double click
1497 if (IsIconic(hwnd))
1499 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1500 return 0;
1503 switch(wParam) /* Hit test */
1505 case HTCAPTION:
1506 /* stop processing if WS_MAXIMIZEBOX is missing */
1507 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1508 SendMessageW( hwnd, WM_SYSCOMMAND,
1509 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1510 break;
1512 case HTSYSMENU:
1514 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1515 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1517 /* If the item close of the sysmenu is disabled or not there do nothing */
1518 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1519 break;
1521 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1522 break;
1525 case HTHSCROLL:
1526 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1527 break;
1529 case HTVSCROLL:
1530 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1531 break;
1533 return 0;
1537 /***********************************************************************
1538 * NC_HandleSysCommand
1540 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1542 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1544 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1546 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1547 return 0;
1549 switch (wParam & 0xfff0)
1551 case SC_SIZE:
1552 case SC_MOVE:
1553 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1554 break;
1556 case SC_MINIMIZE:
1557 if (hwnd == GetForegroundWindow())
1558 ShowOwnedPopups(hwnd,FALSE);
1559 ShowWindow( hwnd, SW_MINIMIZE );
1560 break;
1562 case SC_MAXIMIZE:
1563 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1564 ShowOwnedPopups(hwnd,TRUE);
1565 ShowWindow( hwnd, SW_MAXIMIZE );
1566 break;
1568 case SC_RESTORE:
1569 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1570 ShowOwnedPopups(hwnd,TRUE);
1571 ShowWindow( hwnd, SW_RESTORE );
1572 break;
1574 case SC_CLOSE:
1575 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1577 case SC_VSCROLL:
1578 case SC_HSCROLL:
1580 POINT pt;
1581 pt.x = (short)LOWORD(lParam);
1582 pt.y = (short)HIWORD(lParam);
1583 NC_TrackScrollBar( hwnd, wParam, pt );
1585 break;
1587 case SC_MOUSEMENU:
1589 POINT pt;
1590 pt.x = (short)LOWORD(lParam);
1591 pt.y = (short)HIWORD(lParam);
1592 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1594 break;
1596 case SC_KEYMENU:
1597 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1598 break;
1600 case SC_TASKLIST:
1601 WinExec( "taskman.exe", SW_SHOWNORMAL );
1602 break;
1604 case SC_SCREENSAVE:
1605 if (wParam == SC_ABOUTWINE)
1607 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1608 if (hmodule)
1610 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1611 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1612 FreeLibrary( hmodule );
1615 else
1616 if (wParam == SC_PUTMARK)
1617 DPRINTF("Debug mark requested by user\n");
1618 break;
1620 case SC_HOTKEY:
1621 case SC_ARRANGE:
1622 case SC_NEXTWINDOW:
1623 case SC_PREVWINDOW:
1624 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1625 break;
1627 return 0;
1630 /*************************************************************
1631 * NC_DrawGrayButton
1633 * Stub for the grayed button of the caption
1635 *************************************************************/
1637 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1639 HBITMAP hMaskBmp;
1640 HDC hdcMask;
1641 HBRUSH hOldBrush;
1643 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1645 if(hMaskBmp == 0)
1646 return FALSE;
1648 hdcMask = CreateCompatibleDC (0);
1649 SelectObject (hdcMask, hMaskBmp);
1651 /* Draw the grayed bitmap using the mask */
1652 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1653 BitBlt (hdc, x, y, 12, 10,
1654 hdcMask, 0, 0, 0xB8074A);
1656 /* Clean up */
1657 SelectObject (hdc, hOldBrush);
1658 DeleteObject(hMaskBmp);
1659 DeleteDC (hdcMask);
1661 return TRUE;
1664 /***********************************************************************
1665 * GetTitleBarInfo (USER32.@)
1666 * TODO: Handle STATE_SYSTEM_PRESSED
1668 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1669 DWORD dwStyle;
1670 DWORD dwExStyle;
1671 RECT wndRect;
1673 TRACE("(%p %p)\n", hwnd, tbi);
1675 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1676 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1677 SetLastError(ERROR_INVALID_PARAMETER);
1678 return FALSE;
1680 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1681 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1682 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1684 GetWindowRect(hwnd, &wndRect);
1686 tbi->rcTitleBar.top += wndRect.top;
1687 tbi->rcTitleBar.left += wndRect.left;
1688 tbi->rcTitleBar.right += wndRect.left;
1690 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1691 if(dwExStyle & WS_EX_TOOLWINDOW)
1692 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1693 else {
1694 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1695 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1698 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1699 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1700 * Under XP it seems to
1702 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1703 if(dwStyle & WS_CAPTION) {
1704 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1705 if(dwStyle & WS_SYSMENU) {
1706 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1707 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1708 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1710 else {
1711 if(!(dwStyle & WS_MINIMIZEBOX))
1712 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1713 if(!(dwStyle & WS_MAXIMIZEBOX))
1714 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1716 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1717 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1718 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1719 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1721 else {
1722 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1723 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1728 else
1729 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1730 return TRUE;