advapi32: Fix the failing QueryServiceConfig2 test on platforms win2k3 and vista.
[wine/multimedia.git] / dlls / user32 / nonclient.c
blob58671c5ac986fb6a017dd79237674a487e4f4b36
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "win.h"
29 #include "user_private.h"
30 #include "controls.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
35 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
36 #define SC_PUTMARK (SC_SCREENSAVE+2)
38 /* Some useful macros */
39 #define HAS_DLGFRAME(style,exStyle) \
40 (((exStyle) & WS_EX_DLGMODALFRAME) || \
41 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
43 #define HAS_THICKFRAME(style,exStyle) \
44 (((style) & WS_THICKFRAME) && \
45 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47 #define HAS_THINFRAME(style) \
48 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
50 #define HAS_BIGFRAME(style,exStyle) \
51 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
52 ((exStyle) & WS_EX_DLGMODALFRAME))
54 #define HAS_STATICOUTERFRAME(style,exStyle) \
55 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
56 WS_EX_STATICEDGE)
58 #define HAS_ANYFRAME(style,exStyle) \
59 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
60 ((exStyle) & WS_EX_DLGMODALFRAME) || \
61 !((style) & (WS_CHILD | WS_POPUP)))
63 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
66 /******************************************************************************
67 * NC_AdjustRectOuter
69 * Computes the size of the "outside" parts of the window based on the
70 * parameters of the client area.
72 * PARAMS
73 * LPRECT rect
74 * DWORD style
75 * BOOL menu
76 * DWORD exStyle
78 * NOTES
79 * "Outer" parts of a window means the whole window frame, caption and
80 * menu bar. It does not include "inner" parts of the frame like client
81 * edge, static edge or scroll bars.
83 *****************************************************************************/
85 static void
86 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
88 int adjust;
89 if(style & WS_ICONIC) return;
91 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
92 WS_EX_STATICEDGE)
94 adjust = 1; /* for the outer frame always present */
96 else
98 adjust = 0;
99 if ((exStyle & WS_EX_DLGMODALFRAME) ||
100 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
102 if (style & WS_THICKFRAME)
103 adjust += ( GetSystemMetrics (SM_CXFRAME)
104 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
105 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
106 (exStyle & WS_EX_DLGMODALFRAME))
107 adjust++; /* The other border */
109 InflateRect (rect, adjust, adjust);
111 if ((style & WS_CAPTION) == WS_CAPTION)
113 if (exStyle & WS_EX_TOOLWINDOW)
114 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
115 else
116 rect->top -= GetSystemMetrics(SM_CYCAPTION);
118 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
122 /******************************************************************************
123 * NC_AdjustRectInner
125 * Computes the size of the "inside" part of the window based on the
126 * parameters of the client area.
128 * PARAMS
129 * LPRECT rect
130 * DWORD style
131 * DWORD exStyle
133 * NOTES
134 * "Inner" part of a window means the window frame inside of the flat
135 * window frame. It includes the client edge, the static edge and the
136 * scroll bars.
138 *****************************************************************************/
140 static void
141 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
143 if(style & WS_ICONIC) return;
145 if (exStyle & WS_EX_CLIENTEDGE)
146 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
148 if (style & WS_VSCROLL)
150 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
151 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
152 else
153 rect->right += GetSystemMetrics(SM_CXVSCROLL);
155 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
160 static HICON NC_IconForWindow( HWND hwnd )
162 HICON hIcon = 0;
163 WND *wndPtr = WIN_GetPtr( hwnd );
165 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
167 hIcon = wndPtr->hIconSmall;
168 if (!hIcon) hIcon = wndPtr->hIcon;
169 WIN_ReleasePtr( wndPtr );
171 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
172 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
174 /* If there is no hIcon specified and this is a modal dialog,
175 * get the default one.
177 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
178 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
179 return hIcon;
182 /* Draws the bar part(ie the big rectangle) of the caption */
183 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
184 BOOL active, BOOL gradient)
186 if (gradient)
188 TRIVERTEX vertices[6];
189 DWORD colLeft =
190 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
191 DWORD colRight =
192 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
193 : COLOR_GRADIENTINACTIVECAPTION);
194 int v;
195 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
196 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
198 for (v = 0; v < 3; v++)
200 vertices[v].Red = GetRValue (colLeft) << 8;
201 vertices[v].Green = GetGValue (colLeft) << 8;
202 vertices[v].Blue = GetBValue (colLeft) << 8;
203 vertices[v].Alpha = 0x8000;
204 vertices[v+3].Red = GetRValue (colRight) << 8;
205 vertices[v+3].Green = GetGValue (colRight) << 8;
206 vertices[v+3].Blue = GetBValue (colRight) << 8;
207 vertices[v+3].Alpha = 0x8000;
210 if ((dwStyle & WS_SYSMENU)
211 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
212 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
214 /* area behind icon; solid filled with left color */
215 vertices[0].x = rect->left;
216 vertices[0].y = rect->top;
217 if (dwStyle & WS_SYSMENU)
218 vertices[1].x =
219 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
220 else
221 vertices[1].x = vertices[0].x;
222 vertices[1].y = rect->bottom;
224 /* area behind text; gradient */
225 vertices[2].x = vertices[1].x;
226 vertices[2].y = rect->top;
227 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
228 vertices[3].y = rect->bottom;
230 /* area behind buttons; solid filled with right color */
231 vertices[4].x = vertices[3].x;
232 vertices[4].y = rect->top;
233 vertices[5].x = rect->right;
234 vertices[5].y = rect->bottom;
236 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
238 else
239 FillRect (hdc, rect, GetSysColorBrush (active ?
240 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
243 /***********************************************************************
244 * DrawCaption (USER32.@) Draws a caption bar
246 * PARAMS
247 * hwnd [I]
248 * hdc [I]
249 * lpRect [I]
250 * uFlags [I]
252 * RETURNS
253 * Success:
254 * Failure:
257 BOOL WINAPI
258 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
260 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
264 /***********************************************************************
265 * DrawCaptionTempA (USER32.@)
267 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
268 HICON hIcon, LPCSTR str, UINT uFlags)
270 LPWSTR strW;
271 INT len;
272 BOOL ret = FALSE;
274 if (!(uFlags & DC_TEXT) || !str)
275 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
277 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
278 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
280 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
281 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
282 HeapFree( GetProcessHeap (), 0, strW );
284 return ret;
288 /***********************************************************************
289 * DrawCaptionTempW (USER32.@)
291 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
292 HICON hIcon, LPCWSTR str, UINT uFlags)
294 RECT rc = *rect;
296 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
297 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
299 /* drawing background */
300 if (uFlags & DC_INBUTTON) {
301 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
303 if (uFlags & DC_ACTIVE) {
304 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
305 PatBlt (hdc, rc.left, rc.top,
306 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
307 SelectObject (hdc, hbr);
310 else {
311 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
312 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
316 /* drawing icon */
317 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
318 POINT pt;
320 pt.x = rc.left + 2;
321 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
323 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
324 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
325 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
326 rc.left += (rc.bottom - rc.top);
329 /* drawing text */
330 if (uFlags & DC_TEXT) {
331 HFONT hOldFont;
333 if (uFlags & DC_INBUTTON)
334 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
335 else if (uFlags & DC_ACTIVE)
336 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
337 else
338 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
340 SetBkMode (hdc, TRANSPARENT);
342 if (hFont)
343 hOldFont = SelectObject (hdc, hFont);
344 else {
345 NONCLIENTMETRICSW nclm;
346 HFONT hNewFont;
347 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
348 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
349 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
350 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
351 hOldFont = SelectObject (hdc, hNewFont);
354 if (str)
355 DrawTextW (hdc, str, -1, &rc,
356 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
357 else {
358 WCHAR szText[128];
359 INT nLen;
360 nLen = GetWindowTextW (hwnd, szText, 128);
361 DrawTextW (hdc, szText, nLen, &rc,
362 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
365 if (hFont)
366 SelectObject (hdc, hOldFont);
367 else
368 DeleteObject (SelectObject (hdc, hOldFont));
371 /* drawing focus ??? */
372 if (uFlags & 0x2000)
373 FIXME("undocumented flag (0x2000)!\n");
375 return 0;
379 /***********************************************************************
380 * AdjustWindowRect (USER32.@)
382 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
384 return AdjustWindowRectEx( rect, style, menu, 0 );
388 /***********************************************************************
389 * AdjustWindowRectEx (USER32.@)
391 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
393 /* Correct the window style */
394 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
395 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
396 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
397 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
399 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
400 rect->left, rect->top, rect->right, rect->bottom,
401 style, menu, exStyle );
403 NC_AdjustRectOuter( rect, style, menu, exStyle );
404 NC_AdjustRectInner( rect, style, exStyle );
406 return TRUE;
410 /***********************************************************************
411 * NC_HandleNCCalcSize
413 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
415 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
417 RECT tmpRect = { 0, 0, 0, 0 };
418 LRESULT result = 0;
419 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
420 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
421 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
423 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
424 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
426 if (!IsIconic(hwnd))
428 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
430 winRect->left -= tmpRect.left;
431 winRect->top -= tmpRect.top;
432 winRect->right -= tmpRect.right;
433 winRect->bottom -= tmpRect.bottom;
435 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
437 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
438 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
440 winRect->top +=
441 MENU_GetMenuBarHeight( hwnd,
442 winRect->right - winRect->left,
443 -tmpRect.left, -tmpRect.top );
446 if( exStyle & WS_EX_CLIENTEDGE)
447 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
448 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
449 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
450 - GetSystemMetrics(SM_CYEDGE));
452 if (style & WS_VSCROLL)
453 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
454 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
455 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
456 else
457 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
460 if (style & WS_HSCROLL)
461 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
462 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
464 if (winRect->top > winRect->bottom)
465 winRect->bottom = winRect->top;
467 if (winRect->left > winRect->right)
468 winRect->right = winRect->left;
470 return result;
474 /***********************************************************************
475 * NC_GetInsideRect
477 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
478 * but without the borders (if any).
479 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
481 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
483 WND *wndPtr = WIN_GetPtr( hwnd );
485 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
487 rect->top = rect->left = 0;
488 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
489 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
491 if (wndPtr->dwStyle & WS_ICONIC) goto END;
493 /* Remove frame from rectangle */
494 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
496 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
498 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
500 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
502 else if (HAS_THINFRAME( wndPtr->dwStyle ))
504 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
507 /* We have additional border information if the window
508 * is a child (but not an MDI child) */
509 if ( (wndPtr->dwStyle & WS_CHILD) &&
510 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
512 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
513 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
514 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
515 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
518 END:
519 WIN_ReleasePtr( wndPtr );
523 /***********************************************************************
524 * NC_DoNCHitTest
526 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
528 * FIXME: Just a modified copy of the Win 3.1 version.
531 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
533 RECT rect, rcClient;
534 POINT ptClient;
536 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
538 GetWindowRect(wndPtr->hwndSelf, &rect );
539 if (!PtInRect( &rect, pt )) return HTNOWHERE;
541 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
543 /* Check client area */
544 ptClient = pt;
545 ScreenToClient( wndPtr->hwndSelf, &ptClient );
546 GetClientRect( wndPtr->hwndSelf, &rcClient );
547 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
549 /* Check borders */
550 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
552 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
553 if (!PtInRect( &rect, pt ))
555 /* Check top sizing border */
556 if (pt.y < rect.top)
558 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
559 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
560 return HTTOP;
562 /* Check bottom sizing border */
563 if (pt.y >= rect.bottom)
565 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
566 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
567 return HTBOTTOM;
569 /* Check left sizing border */
570 if (pt.x < rect.left)
572 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
573 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
574 return HTLEFT;
576 /* Check right sizing border */
577 if (pt.x >= rect.right)
579 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
580 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
581 return HTRIGHT;
585 else /* No thick frame */
587 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
588 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
589 else if (HAS_THINFRAME( wndPtr->dwStyle ))
590 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
591 if (!PtInRect( &rect, pt )) return HTBORDER;
594 /* Check caption */
596 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
598 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
599 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
600 else
601 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
602 if (!PtInRect( &rect, pt ))
604 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
605 (wndPtr->dwStyle & WS_MINIMIZEBOX);
606 /* Check system menu */
607 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
609 if (NC_IconForWindow(wndPtr->hwndSelf))
610 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
612 if (pt.x < rect.left) return HTSYSMENU;
614 /* Check close button */
615 if (wndPtr->dwStyle & WS_SYSMENU)
616 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
617 if (pt.x > rect.right) return HTCLOSE;
619 /* Check maximize box */
620 /* In win95 there is automatically a Maximize button when there is a minimize one*/
621 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
622 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
623 if (pt.x > rect.right) return HTMAXBUTTON;
625 /* Check minimize box */
626 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
627 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
628 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
630 if (pt.x > rect.right) return HTMINBUTTON;
631 return HTCAPTION;
635 /* Check vertical scroll bar */
637 if (wndPtr->dwStyle & WS_VSCROLL)
639 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
640 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
641 else
642 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
643 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
646 /* Check horizontal scroll bar */
648 if (wndPtr->dwStyle & WS_HSCROLL)
650 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
651 if (PtInRect( &rcClient, ptClient ))
653 /* Check size box */
654 if ((wndPtr->dwStyle & WS_VSCROLL) &&
655 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
656 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
657 return HTSIZE;
658 return HTHSCROLL;
662 /* Check menu bar */
664 if (HAS_MENU(wndPtr))
666 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
667 return HTMENU;
670 /* Has to return HTNOWHERE if nothing was found
671 Could happen when a window has a customized non client area */
672 return HTNOWHERE;
676 /***********************************************************************
677 * NC_HandleNCHitTest
679 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
681 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
683 LRESULT retvalue;
684 WND *wndPtr = WIN_GetPtr( hwnd );
686 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
688 retvalue = NC_DoNCHitTest (wndPtr, pt);
689 WIN_ReleasePtr( wndPtr );
690 return retvalue;
694 /******************************************************************************
696 * NC_DrawSysButton
698 * Draws the system icon.
700 *****************************************************************************/
701 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
703 HICON hIcon = NC_IconForWindow( hwnd );
705 if (hIcon)
707 RECT rect;
708 NC_GetInsideRect( hwnd, &rect );
709 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
710 GetSystemMetrics(SM_CXSMICON),
711 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
713 return (hIcon != 0);
717 /******************************************************************************
719 * NC_DrawCloseButton
721 * Draws the close button.
723 * If bGrayed is true, then draw a disabled Close button
725 *****************************************************************************/
727 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
729 RECT rect;
731 NC_GetInsideRect( hwnd, &rect );
733 /* A tool window has a smaller Close button */
734 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
736 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
737 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
738 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
740 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
741 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
742 rect.bottom = rect.top + iBmpHeight;
743 rect.right = rect.left + iBmpWidth;
745 else
747 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
748 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
749 rect.top += 2;
750 rect.right -= 2;
752 DrawFrameControl( hdc, &rect, DFC_CAPTION,
753 (DFCS_CAPTIONCLOSE |
754 (down ? DFCS_PUSHED : 0) |
755 (bGrayed ? DFCS_INACTIVE : 0)) );
758 /******************************************************************************
759 * NC_DrawMaxButton
761 * Draws the maximize button for windows.
762 * If bGrayed is true, then draw a disabled Maximize button
764 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
766 RECT rect;
767 UINT flags;
769 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
770 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
771 return;
773 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
775 NC_GetInsideRect( hwnd, &rect );
776 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
777 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
778 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
779 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
780 rect.top += 2;
781 rect.right -= 2;
782 if (down) flags |= DFCS_PUSHED;
783 if (bGrayed) flags |= DFCS_INACTIVE;
784 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
787 /******************************************************************************
788 * NC_DrawMinButton
790 * Draws the minimize button for windows.
791 * If bGrayed is true, then draw a disabled Minimize button
793 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
795 RECT rect;
796 UINT flags = DFCS_CAPTIONMIN;
797 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
799 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
800 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
801 return;
803 NC_GetInsideRect( hwnd, &rect );
804 if (style & WS_SYSMENU)
805 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
806 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
807 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
808 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
809 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
810 rect.top += 2;
811 rect.right -= 2;
812 if (down) flags |= DFCS_PUSHED;
813 if (bGrayed) flags |= DFCS_INACTIVE;
814 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
817 /******************************************************************************
819 * NC_DrawFrame
821 * Draw a window frame inside the given rectangle, and update the rectangle.
823 * Bugs
824 * Many. First, just what IS a frame in Win95? Note that the 3D look
825 * on the outer edge is handled by NC_DoNCPaint. As is the inner
826 * edge. The inner rectangle just inside the frame is handled by the
827 * Caption code.
829 * In short, for most people, this function should be a nop (unless
830 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
831 * them lately, but just to get this code right). Even so, it doesn't
832 * appear to be so. It's being worked on...
834 *****************************************************************************/
836 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
838 INT width, height;
840 /* Firstly the "thick" frame */
841 if (style & WS_THICKFRAME)
843 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
844 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
846 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
847 COLOR_INACTIVEBORDER) );
848 /* Draw frame */
849 PatBlt( hdc, rect->left, rect->top,
850 rect->right - rect->left, height, PATCOPY );
851 PatBlt( hdc, rect->left, rect->top,
852 width, rect->bottom - rect->top, PATCOPY );
853 PatBlt( hdc, rect->left, rect->bottom - 1,
854 rect->right - rect->left, -height, PATCOPY );
855 PatBlt( hdc, rect->right - 1, rect->top,
856 -width, rect->bottom - rect->top, PATCOPY );
858 InflateRect( rect, -width, -height );
861 /* Now the other bit of the frame */
862 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
863 (exStyle & WS_EX_DLGMODALFRAME))
865 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
866 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
867 /* This should give a value of 1 that should also work for a border */
869 SelectObject( hdc, GetSysColorBrush(
870 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
871 COLOR_3DFACE :
872 (exStyle & WS_EX_STATICEDGE) ?
873 COLOR_WINDOWFRAME :
874 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
875 COLOR_3DFACE :
876 /* else */
877 COLOR_WINDOWFRAME));
879 /* Draw frame */
880 PatBlt( hdc, rect->left, rect->top,
881 rect->right - rect->left, height, PATCOPY );
882 PatBlt( hdc, rect->left, rect->top,
883 width, rect->bottom - rect->top, PATCOPY );
884 PatBlt( hdc, rect->left, rect->bottom - 1,
885 rect->right - rect->left, -height, PATCOPY );
886 PatBlt( hdc, rect->right - 1, rect->top,
887 -width, rect->bottom - rect->top, PATCOPY );
889 InflateRect( rect, -width, -height );
894 /******************************************************************************
896 * NC_DrawCaption
898 * Draw the window caption for windows.
899 * The correct pen for the window frame must be selected in the DC.
901 *****************************************************************************/
903 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
904 DWORD exStyle, BOOL active )
906 RECT r = *rect;
907 WCHAR buffer[256];
908 HPEN hPrevPen;
909 HMENU hSysMenu;
910 BOOL gradient = FALSE;
912 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
913 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
914 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
915 COLOR_WINDOWFRAME : COLOR_3DFACE) );
916 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
917 LineTo( hdc, r.right, r.bottom - 1 );
918 SelectObject( hdc, hPrevPen );
919 r.bottom--;
921 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
922 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
924 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
925 if (NC_DrawSysButton (hwnd, hdc, FALSE))
926 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
929 if (style & WS_SYSMENU)
931 UINT state;
933 /* Go get the sysmenu */
934 hSysMenu = GetSystemMenu(hwnd, FALSE);
935 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
937 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
938 NC_DrawCloseButton (hwnd, hdc, FALSE,
939 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
940 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
942 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
944 /* In win95 the two buttons are always there */
945 /* But if the menu item is not in the menu they're disabled*/
947 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
948 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
950 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
951 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
955 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
957 NONCLIENTMETRICSW nclm;
958 HFONT hFont, hOldFont;
959 nclm.cbSize = sizeof(nclm);
960 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
961 if (exStyle & WS_EX_TOOLWINDOW)
962 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
963 else
964 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
965 hOldFont = SelectObject (hdc, hFont);
966 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
967 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
968 SetBkMode( hdc, TRANSPARENT );
969 r.left += 2;
970 DrawTextW( hdc, buffer, -1, &r,
971 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
972 DeleteObject (SelectObject (hdc, hOldFont));
977 /******************************************************************************
978 * NC_DoNCPaint
980 * Paint the non-client area for windows.
982 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
984 HDC hdc;
985 RECT rfuzz, rect, rectClip;
986 BOOL active;
987 WND *wndPtr;
988 DWORD dwStyle, dwExStyle;
989 WORD flags;
990 HRGN hrgn;
991 RECT rectClient, rectWindow;
992 int has_menu;
994 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
995 has_menu = HAS_MENU(wndPtr);
996 dwStyle = wndPtr->dwStyle;
997 dwExStyle = wndPtr->dwExStyle;
998 flags = wndPtr->flags;
999 rectWindow = wndPtr->rectWindow;
1000 WIN_ReleasePtr( wndPtr );
1002 if ( dwStyle & WS_MINIMIZE ||
1003 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1005 active = flags & WIN_NCACTIVATED;
1007 TRACE("%p %d\n", hwnd, active );
1009 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1010 the call to GetDCEx implying that it is allowed not to use it either.
1011 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1012 will cause clipRgn to be deleted after ReleaseDC().
1013 Now, how is the "system" supposed to tell what happened?
1016 GetClientRect( hwnd, &rectClient );
1017 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1018 hrgn = CreateRectRgnIndirect( &rectClient );
1020 if (clip > (HRGN)1)
1022 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1023 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1025 else
1027 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1030 if (!hdc) return;
1032 rect.top = rect.left = 0;
1033 rect.right = rectWindow.right - rectWindow.left;
1034 rect.bottom = rectWindow.bottom - rectWindow.top;
1035 GetClipBox( hdc, &rectClip );
1037 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1039 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1040 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1042 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1043 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1046 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1048 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1050 RECT r = rect;
1051 if (dwExStyle & WS_EX_TOOLWINDOW) {
1052 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1053 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1055 else {
1056 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1057 rect.top += GetSystemMetrics(SM_CYCAPTION);
1059 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1060 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1063 if (has_menu)
1065 RECT r = rect;
1066 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1068 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1069 r.left, r.top, r.right, r.bottom);
1071 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1074 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1075 rect.left, rect.top, rect.right, rect.bottom );
1077 if (dwExStyle & WS_EX_CLIENTEDGE)
1078 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1080 /* Draw the scroll-bars */
1082 if (dwStyle & WS_VSCROLL)
1083 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1084 if (dwStyle & WS_HSCROLL)
1085 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1087 /* Draw the "size-box" */
1088 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1090 RECT r = rect;
1091 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1092 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1093 else
1094 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1095 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1096 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1099 ReleaseDC( hwnd, hdc );
1105 /***********************************************************************
1106 * NC_HandleNCPaint
1108 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1110 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1112 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1114 if( dwStyle & WS_VISIBLE )
1116 if( dwStyle & WS_MINIMIZE )
1117 WINPOS_RedrawIconTitle( hwnd );
1118 else
1119 NC_DoNCPaint( hwnd, clip, FALSE );
1121 return 0;
1125 /***********************************************************************
1126 * NC_HandleNCActivate
1128 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1130 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1132 WND* wndPtr = WIN_GetPtr( hwnd );
1134 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1136 /* Lotus Notes draws menu descriptions in the caption of its main
1137 * window. When it wants to restore original "system" view, it just
1138 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1139 * attempt to minimize redrawings lead to a not restored caption.
1141 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1142 else wndPtr->flags &= ~WIN_NCACTIVATED;
1143 WIN_ReleasePtr( wndPtr );
1145 if (IsIconic(hwnd))
1146 WINPOS_RedrawIconTitle( hwnd );
1147 else
1148 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1150 return TRUE;
1154 /***********************************************************************
1155 * NC_HandleSetCursor
1157 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1159 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1161 hwnd = WIN_GetFullHandle( (HWND)wParam );
1163 switch((short)LOWORD(lParam))
1165 case HTERROR:
1167 WORD msg = HIWORD( lParam );
1168 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1169 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1170 MessageBeep(0);
1172 break;
1174 case HTCLIENT:
1176 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1177 if(hCursor) {
1178 SetCursor(hCursor);
1179 return TRUE;
1181 return FALSE;
1184 case HTLEFT:
1185 case HTRIGHT:
1186 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1188 case HTTOP:
1189 case HTBOTTOM:
1190 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1192 case HTTOPLEFT:
1193 case HTBOTTOMRIGHT:
1194 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1196 case HTTOPRIGHT:
1197 case HTBOTTOMLEFT:
1198 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1201 /* Default cursor: arrow */
1202 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1205 /***********************************************************************
1206 * NC_GetSysPopupPos
1208 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1210 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1211 else
1213 WND *wndPtr = WIN_GetPtr( hwnd );
1214 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1216 NC_GetInsideRect( hwnd, rect );
1217 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1218 if (wndPtr->dwStyle & WS_CHILD)
1219 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1220 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1221 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1222 WIN_ReleasePtr( wndPtr );
1226 /***********************************************************************
1227 * NC_TrackMinMaxBox
1229 * Track a mouse button press on the minimize or maximize box.
1231 * The big difference between 3.1 and 95 is the disabled button state.
1232 * In win95 the system button can be disabled, so it can ignore the mouse
1233 * event.
1236 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1238 MSG msg;
1239 HDC hdc = GetWindowDC( hwnd );
1240 BOOL pressed = TRUE;
1241 UINT state;
1242 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1243 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1245 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1247 if (wParam == HTMINBUTTON)
1249 /* If the style is not present, do nothing */
1250 if (!(wndStyle & WS_MINIMIZEBOX))
1251 return;
1253 /* Check if the sysmenu item for minimize is there */
1254 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1256 paintButton = &NC_DrawMinButton;
1258 else
1260 /* If the style is not present, do nothing */
1261 if (!(wndStyle & WS_MAXIMIZEBOX))
1262 return;
1264 /* Check if the sysmenu item for maximize is there */
1265 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1267 paintButton = &NC_DrawMaxButton;
1270 SetCapture( hwnd );
1272 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1274 while(1)
1276 BOOL oldstate = pressed;
1278 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1279 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1281 if(msg.message == WM_LBUTTONUP)
1282 break;
1284 if(msg.message != WM_MOUSEMOVE)
1285 continue;
1287 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1288 if (pressed != oldstate)
1289 (*paintButton)( hwnd, hdc, pressed, FALSE);
1292 if(pressed)
1293 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1295 ReleaseCapture();
1296 ReleaseDC( hwnd, hdc );
1298 /* If the item minimize or maximize of the sysmenu are not there */
1299 /* or if the style is not present, do nothing */
1300 if ((!pressed) || (state == 0xFFFFFFFF))
1301 return;
1303 if (wParam == HTMINBUTTON)
1304 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1305 else
1306 SendMessageW( hwnd, WM_SYSCOMMAND,
1307 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1310 /***********************************************************************
1311 * NC_TrackCloseButton
1313 * Track a mouse button press on the Win95 close button.
1315 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1317 MSG msg;
1318 HDC hdc;
1319 BOOL pressed = TRUE;
1320 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1321 UINT state;
1323 if(hSysMenu == 0)
1324 return;
1326 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1328 /* If the item close of the sysmenu is disabled or not there do nothing */
1329 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1330 return;
1332 hdc = GetWindowDC( hwnd );
1334 SetCapture( hwnd );
1336 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1338 while(1)
1340 BOOL oldstate = pressed;
1342 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1343 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1345 if(msg.message == WM_LBUTTONUP)
1346 break;
1348 if(msg.message != WM_MOUSEMOVE)
1349 continue;
1351 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1352 if (pressed != oldstate)
1353 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1356 if(pressed)
1357 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1359 ReleaseCapture();
1360 ReleaseDC( hwnd, hdc );
1361 if (!pressed) return;
1363 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1367 /***********************************************************************
1368 * NC_TrackScrollBar
1370 * Track a mouse button press on the horizontal or vertical scroll-bar.
1372 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1374 INT scrollbar;
1376 if ((wParam & 0xfff0) == SC_HSCROLL)
1378 if ((wParam & 0x0f) != HTHSCROLL) return;
1379 scrollbar = SB_HORZ;
1381 else /* SC_VSCROLL */
1383 if ((wParam & 0x0f) != HTVSCROLL) return;
1384 scrollbar = SB_VERT;
1386 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1390 /***********************************************************************
1391 * NC_HandleNCLButtonDown
1393 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1395 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1397 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1399 switch(wParam) /* Hit test */
1401 case HTCAPTION:
1403 HWND top = GetAncestor( hwnd, GA_ROOT );
1405 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1406 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1407 break;
1410 case HTSYSMENU:
1411 if( style & WS_SYSMENU )
1413 if( !(style & WS_MINIMIZE) )
1415 HDC hDC = GetWindowDC(hwnd);
1416 NC_DrawSysButton( hwnd, hDC, TRUE );
1417 ReleaseDC( hwnd, hDC );
1419 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1421 break;
1423 case HTMENU:
1424 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1425 break;
1427 case HTHSCROLL:
1428 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1429 break;
1431 case HTVSCROLL:
1432 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1433 break;
1435 case HTMINBUTTON:
1436 case HTMAXBUTTON:
1437 NC_TrackMinMaxBox( hwnd, wParam );
1438 break;
1440 case HTCLOSE:
1441 NC_TrackCloseButton (hwnd, wParam);
1442 break;
1444 case HTLEFT:
1445 case HTRIGHT:
1446 case HTTOP:
1447 case HTTOPLEFT:
1448 case HTTOPRIGHT:
1449 case HTBOTTOM:
1450 case HTBOTTOMLEFT:
1451 case HTBOTTOMRIGHT:
1452 /* Old comment:
1453 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1454 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1456 /* But that is not what WinNT does. Instead it sends this. This
1457 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1458 * SC_MOUSEMENU into wParam.
1460 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1461 break;
1463 case HTBORDER:
1464 break;
1466 return 0;
1470 /***********************************************************************
1471 * NC_HandleNCLButtonDblClk
1473 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1475 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1478 * if this is an icon, send a restore since we are handling
1479 * a double click
1481 if (IsIconic(hwnd))
1483 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1484 return 0;
1487 switch(wParam) /* Hit test */
1489 case HTCAPTION:
1490 /* stop processing if WS_MAXIMIZEBOX is missing */
1491 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1492 SendMessageW( hwnd, WM_SYSCOMMAND,
1493 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1494 break;
1496 case HTSYSMENU:
1498 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1499 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1501 /* If the item close of the sysmenu is disabled or not there do nothing */
1502 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1503 break;
1505 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1506 break;
1509 case HTHSCROLL:
1510 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1511 break;
1513 case HTVSCROLL:
1514 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1515 break;
1517 return 0;
1521 /***********************************************************************
1522 * NC_HandleSysCommand
1524 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1526 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1528 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1530 if (!IsWindowEnabled( hwnd )) return 0;
1532 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1533 return 0;
1535 switch (wParam & 0xfff0)
1537 case SC_SIZE:
1538 case SC_MOVE:
1539 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1540 break;
1542 case SC_MINIMIZE:
1543 if (hwnd == GetForegroundWindow())
1544 ShowOwnedPopups(hwnd,FALSE);
1545 ShowWindow( hwnd, SW_MINIMIZE );
1546 break;
1548 case SC_MAXIMIZE:
1549 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1550 ShowOwnedPopups(hwnd,TRUE);
1551 ShowWindow( hwnd, SW_MAXIMIZE );
1552 break;
1554 case SC_RESTORE:
1555 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1556 ShowOwnedPopups(hwnd,TRUE);
1557 ShowWindow( hwnd, SW_RESTORE );
1558 break;
1560 case SC_CLOSE:
1561 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1563 case SC_VSCROLL:
1564 case SC_HSCROLL:
1566 POINT pt;
1567 pt.x = (short)LOWORD(lParam);
1568 pt.y = (short)HIWORD(lParam);
1569 NC_TrackScrollBar( hwnd, wParam, pt );
1571 break;
1573 case SC_MOUSEMENU:
1575 POINT pt;
1576 pt.x = (short)LOWORD(lParam);
1577 pt.y = (short)HIWORD(lParam);
1578 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1580 break;
1582 case SC_KEYMENU:
1583 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1584 break;
1586 case SC_TASKLIST:
1587 WinExec( "taskman.exe", SW_SHOWNORMAL );
1588 break;
1590 case SC_SCREENSAVE:
1591 if (wParam == SC_ABOUTWINE)
1593 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1594 if (hmodule)
1596 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1597 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1598 FreeLibrary( hmodule );
1601 else
1602 if (wParam == SC_PUTMARK)
1603 DPRINTF("Debug mark requested by user\n");
1604 break;
1606 case SC_HOTKEY:
1607 case SC_ARRANGE:
1608 case SC_NEXTWINDOW:
1609 case SC_PREVWINDOW:
1610 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1611 break;
1613 return 0;
1616 /***********************************************************************
1617 * GetTitleBarInfo (USER32.@)
1618 * TODO: Handle STATE_SYSTEM_PRESSED
1620 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1621 DWORD dwStyle;
1622 DWORD dwExStyle;
1623 RECT wndRect;
1625 TRACE("(%p %p)\n", hwnd, tbi);
1627 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1628 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1629 SetLastError(ERROR_INVALID_PARAMETER);
1630 return FALSE;
1632 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1633 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1634 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1636 GetWindowRect(hwnd, &wndRect);
1638 tbi->rcTitleBar.top += wndRect.top;
1639 tbi->rcTitleBar.left += wndRect.left;
1640 tbi->rcTitleBar.right += wndRect.left;
1642 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1643 if(dwExStyle & WS_EX_TOOLWINDOW)
1644 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1645 else {
1646 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1647 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1650 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1651 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1652 * Under XP it seems to
1654 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1655 if(dwStyle & WS_CAPTION) {
1656 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1657 if(dwStyle & WS_SYSMENU) {
1658 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1659 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1660 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1662 else {
1663 if(!(dwStyle & WS_MINIMIZEBOX))
1664 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1665 if(!(dwStyle & WS_MAXIMIZEBOX))
1666 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1668 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1669 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1670 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1671 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1673 else {
1674 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1675 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1676 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1677 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1680 else
1681 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1682 return TRUE;