configure: Make the font warning more explicit about what package is missing.
[wine/multimedia.git] / dlls / user / nonclient.c
blob2f095ca302d68e95b5add8c282d6de91172f2fe1
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 "winpos.h"
34 #include "shellapi.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
39 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
41 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
42 0x55, 0x50,
43 0xAA, 0xA0,
44 0x55, 0x50,
45 0xAA, 0xA0,
46 0x55, 0x50,
47 0xAA, 0xA0,
48 0x55, 0x50,
49 0xAA, 0xA0,
50 0x55, 0x50};
52 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
53 #define SC_PUTMARK (SC_SCREENSAVE+2)
55 /* Some useful macros */
56 #define HAS_DLGFRAME(style,exStyle) \
57 (((exStyle) & WS_EX_DLGMODALFRAME) || \
58 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
60 #define HAS_THICKFRAME(style,exStyle) \
61 (((style) & WS_THICKFRAME) && \
62 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
64 #define HAS_THINFRAME(style) \
65 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
67 #define HAS_BIGFRAME(style,exStyle) \
68 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
69 ((exStyle) & WS_EX_DLGMODALFRAME))
71 #define HAS_STATICOUTERFRAME(style,exStyle) \
72 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
73 WS_EX_STATICEDGE)
75 #define HAS_ANYFRAME(style,exStyle) \
76 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
77 ((exStyle) & WS_EX_DLGMODALFRAME) || \
78 !((style) & (WS_CHILD | WS_POPUP)))
80 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
83 /******************************************************************************
84 * NC_AdjustRectOuter
86 * Computes the size of the "outside" parts of the window based on the
87 * parameters of the client area.
89 * PARAMS
90 * LPRECT rect
91 * DWORD style
92 * BOOL menu
93 * DWORD exStyle
95 * NOTES
96 * "Outer" parts of a window means the whole window frame, caption and
97 * menu bar. It does not include "inner" parts of the frame like client
98 * edge, static edge or scroll bars.
100 *****************************************************************************/
102 static void
103 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
105 int adjust;
106 if(style & WS_ICONIC) return;
108 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
109 WS_EX_STATICEDGE)
111 adjust = 1; /* for the outer frame always present */
113 else
115 adjust = 0;
116 if ((exStyle & WS_EX_DLGMODALFRAME) ||
117 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
119 if (style & WS_THICKFRAME)
120 adjust += ( GetSystemMetrics (SM_CXFRAME)
121 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
122 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
123 (exStyle & WS_EX_DLGMODALFRAME))
124 adjust++; /* The other border */
126 InflateRect (rect, adjust, adjust);
128 if ((style & WS_CAPTION) == WS_CAPTION)
130 if (exStyle & WS_EX_TOOLWINDOW)
131 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
132 else
133 rect->top -= GetSystemMetrics(SM_CYCAPTION);
135 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
139 /******************************************************************************
140 * NC_AdjustRectInner
142 * Computes the size of the "inside" part of the window based on the
143 * parameters of the client area.
145 * PARAMS
146 * LPRECT rect
147 * DWORD style
148 * DWORD exStyle
150 * NOTES
151 * "Inner" part of a window means the window frame inside of the flat
152 * window frame. It includes the client edge, the static edge and the
153 * scroll bars.
155 *****************************************************************************/
157 static void
158 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
160 if(style & WS_ICONIC) return;
162 if (exStyle & WS_EX_CLIENTEDGE)
163 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
165 if (style & WS_VSCROLL)
167 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
168 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
169 else
170 rect->right += GetSystemMetrics(SM_CXVSCROLL);
172 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
177 static HICON NC_IconForWindow( HWND hwnd )
179 HICON hIcon = 0;
180 WND *wndPtr = WIN_GetPtr( hwnd );
182 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
184 hIcon = wndPtr->hIconSmall;
185 if (!hIcon) hIcon = wndPtr->hIcon;
186 WIN_ReleasePtr( wndPtr );
188 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
189 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
191 /* If there is no hIcon specified and this is a modal dialog,
192 * get the default one.
194 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
195 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
196 return hIcon;
199 /* Draws the bar part(ie the big rectangle) of the caption */
200 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
201 BOOL active, BOOL gradient)
203 if (gradient)
205 TRIVERTEX vertices[6];
206 DWORD colLeft =
207 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
208 DWORD colRight =
209 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
210 : COLOR_GRADIENTINACTIVECAPTION);
211 int v;
212 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
213 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
215 for (v = 0; v < 3; v++)
217 vertices[v].Red = GetRValue (colLeft) << 8;
218 vertices[v].Green = GetGValue (colLeft) << 8;
219 vertices[v].Blue = GetBValue (colLeft) << 8;
220 vertices[v].Alpha = 0x8000;
221 vertices[v+3].Red = GetRValue (colRight) << 8;
222 vertices[v+3].Green = GetGValue (colRight) << 8;
223 vertices[v+3].Blue = GetBValue (colRight) << 8;
224 vertices[v+3].Alpha = 0x8000;
227 if ((dwStyle & WS_SYSMENU)
228 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
229 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
231 /* area behind icon; solid filled with left color */
232 vertices[0].x = rect->left;
233 vertices[0].y = rect->top;
234 if (dwStyle & WS_SYSMENU)
235 vertices[1].x =
236 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
237 else
238 vertices[1].x = vertices[0].x;
239 vertices[1].y = rect->bottom;
241 /* area behind text; gradient */
242 vertices[2].x = vertices[1].x;
243 vertices[2].y = rect->top;
244 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
245 vertices[3].y = rect->bottom;
247 /* area behind buttons; solid filled with right color */
248 vertices[4].x = vertices[3].x;
249 vertices[4].y = rect->top;
250 vertices[5].x = rect->right;
251 vertices[5].y = rect->bottom;
253 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
255 else
256 FillRect (hdc, rect, GetSysColorBrush (active ?
257 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
260 /***********************************************************************
261 * DrawCaption (USER32.@) Draws a caption bar
263 * PARAMS
264 * hwnd [I]
265 * hdc [I]
266 * lpRect [I]
267 * uFlags [I]
269 * RETURNS
270 * Success:
271 * Failure:
274 BOOL WINAPI
275 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
277 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
281 /***********************************************************************
282 * DrawCaptionTempA (USER32.@)
284 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
285 HICON hIcon, LPCSTR str, UINT uFlags)
287 LPWSTR strW;
288 INT len;
289 BOOL ret = FALSE;
291 if (!(uFlags & DC_TEXT) || !str)
292 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
294 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
295 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
297 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
298 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
299 HeapFree( GetProcessHeap (), 0, strW );
301 return ret;
305 /***********************************************************************
306 * DrawCaptionTempW (USER32.@)
308 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
309 HICON hIcon, LPCWSTR str, UINT uFlags)
311 RECT rc = *rect;
313 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
314 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
316 /* drawing background */
317 if (uFlags & DC_INBUTTON) {
318 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
320 if (uFlags & DC_ACTIVE) {
321 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
322 PatBlt (hdc, rc.left, rc.top,
323 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
324 SelectObject (hdc, hbr);
327 else {
328 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
329 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
333 /* drawing icon */
334 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
335 POINT pt;
337 pt.x = rc.left + 2;
338 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
340 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
341 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
342 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
343 rc.left += (rc.bottom - rc.top);
346 /* drawing text */
347 if (uFlags & DC_TEXT) {
348 HFONT hOldFont;
350 if (uFlags & DC_INBUTTON)
351 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
352 else if (uFlags & DC_ACTIVE)
353 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
354 else
355 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
357 SetBkMode (hdc, TRANSPARENT);
359 if (hFont)
360 hOldFont = SelectObject (hdc, hFont);
361 else {
362 NONCLIENTMETRICSW nclm;
363 HFONT hNewFont;
364 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
365 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
366 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
367 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
368 hOldFont = SelectObject (hdc, hNewFont);
371 if (str)
372 DrawTextW (hdc, str, -1, &rc,
373 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
374 else {
375 WCHAR szText[128];
376 INT nLen;
377 nLen = GetWindowTextW (hwnd, szText, 128);
378 DrawTextW (hdc, szText, nLen, &rc,
379 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
382 if (hFont)
383 SelectObject (hdc, hOldFont);
384 else
385 DeleteObject (SelectObject (hdc, hOldFont));
388 /* drawing focus ??? */
389 if (uFlags & 0x2000)
390 FIXME("undocumented flag (0x2000)!\n");
392 return 0;
396 /***********************************************************************
397 * AdjustWindowRect (USER32.@)
399 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
401 return AdjustWindowRectEx( rect, style, menu, 0 );
405 /***********************************************************************
406 * AdjustWindowRectEx (USER32.@)
408 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
410 /* Correct the window style */
411 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
412 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
413 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
414 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
416 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
417 rect->left, rect->top, rect->right, rect->bottom,
418 style, menu, exStyle );
420 NC_AdjustRectOuter( rect, style, menu, exStyle );
421 NC_AdjustRectInner( rect, style, exStyle );
423 return TRUE;
427 /***********************************************************************
428 * NC_HandleNCCalcSize
430 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
432 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
434 RECT tmpRect = { 0, 0, 0, 0 };
435 LRESULT result = 0;
436 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
437 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
438 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
440 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
441 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
443 if (!IsIconic(hwnd))
445 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
447 winRect->left -= tmpRect.left;
448 winRect->top -= tmpRect.top;
449 winRect->right -= tmpRect.right;
450 winRect->bottom -= tmpRect.bottom;
452 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
454 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
455 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
457 winRect->top +=
458 MENU_GetMenuBarHeight( hwnd,
459 winRect->right - winRect->left,
460 -tmpRect.left, -tmpRect.top );
463 if( exStyle & WS_EX_CLIENTEDGE)
464 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
465 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
466 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
467 - GetSystemMetrics(SM_CYEDGE));
469 if (style & WS_VSCROLL)
470 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
471 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
472 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
473 else
474 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
477 if (style & WS_HSCROLL)
478 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
479 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
481 if (winRect->top > winRect->bottom)
482 winRect->bottom = winRect->top;
484 if (winRect->left > winRect->right)
485 winRect->right = winRect->left;
487 return result;
491 /***********************************************************************
492 * NC_GetInsideRect
494 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
495 * but without the borders (if any).
496 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
498 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
500 WND *wndPtr = WIN_GetPtr( hwnd );
502 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
504 rect->top = rect->left = 0;
505 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
506 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
508 if (wndPtr->dwStyle & WS_ICONIC) goto END;
510 /* Remove frame from rectangle */
511 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
515 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
517 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
519 else if (HAS_THINFRAME( wndPtr->dwStyle ))
521 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
524 /* We have additional border information if the window
525 * is a child (but not an MDI child) */
526 if ( (wndPtr->dwStyle & WS_CHILD) &&
527 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
529 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
530 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
531 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
532 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
535 END:
536 WIN_ReleasePtr( wndPtr );
540 /***********************************************************************
541 * NC_DoNCHitTest
543 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
545 * FIXME: Just a modified copy of the Win 3.1 version.
548 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
550 RECT rect, rcClient;
551 POINT ptClient;
553 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
555 GetWindowRect(wndPtr->hwndSelf, &rect );
556 if (!PtInRect( &rect, pt )) return HTNOWHERE;
558 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
560 /* Check client area */
561 ptClient = pt;
562 ScreenToClient( wndPtr->hwndSelf, &ptClient );
563 GetClientRect( wndPtr->hwndSelf, &rcClient );
564 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
566 /* Check borders */
567 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
569 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
570 if (!PtInRect( &rect, pt ))
572 /* Check top sizing border */
573 if (pt.y < rect.top)
575 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
576 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
577 return HTTOP;
579 /* Check bottom sizing border */
580 if (pt.y >= rect.bottom)
582 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
583 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
584 return HTBOTTOM;
586 /* Check left sizing border */
587 if (pt.x < rect.left)
589 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
590 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
591 return HTLEFT;
593 /* Check right sizing border */
594 if (pt.x >= rect.right)
596 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
597 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
598 return HTRIGHT;
602 else /* No thick frame */
604 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
605 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
606 else if (HAS_THINFRAME( wndPtr->dwStyle ))
607 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
608 if (!PtInRect( &rect, pt )) return HTBORDER;
611 /* Check caption */
613 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
615 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
616 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
617 else
618 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
619 if (!PtInRect( &rect, pt ))
621 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
622 (wndPtr->dwStyle & WS_MINIMIZEBOX);
623 /* Check system menu */
624 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
626 if (NC_IconForWindow(wndPtr->hwndSelf))
627 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
629 if (pt.x < rect.left) return HTSYSMENU;
631 /* Check close button */
632 if (wndPtr->dwStyle & WS_SYSMENU)
633 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
634 if (pt.x > rect.right) return HTCLOSE;
636 /* Check maximize box */
637 /* In win95 there is automatically a Maximize button when there is a minimize one*/
638 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
639 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
640 if (pt.x > rect.right) return HTMAXBUTTON;
642 /* Check minimize box */
643 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
644 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
645 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
647 if (pt.x > rect.right) return HTMINBUTTON;
648 return HTCAPTION;
652 /* Check vertical scroll bar */
654 if (wndPtr->dwStyle & WS_VSCROLL)
656 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
657 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
658 else
659 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
660 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
663 /* Check horizontal scroll bar */
665 if (wndPtr->dwStyle & WS_HSCROLL)
667 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
668 if (PtInRect( &rcClient, ptClient ))
670 /* Check size box */
671 if ((wndPtr->dwStyle & WS_VSCROLL) &&
672 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
673 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
674 return HTSIZE;
675 return HTHSCROLL;
679 /* Check menu bar */
681 if (HAS_MENU(wndPtr))
683 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
684 return HTMENU;
687 /* Has to return HTNOWHERE if nothing was found
688 Could happen when a window has a customized non client area */
689 return HTNOWHERE;
693 /***********************************************************************
694 * NC_HandleNCHitTest
696 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
698 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
700 LRESULT retvalue;
701 WND *wndPtr = WIN_GetPtr( hwnd );
703 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
705 retvalue = NC_DoNCHitTest (wndPtr, pt);
706 WIN_ReleasePtr( wndPtr );
707 return retvalue;
711 /******************************************************************************
713 * NC_DrawSysButton
715 * Draws the system icon.
717 *****************************************************************************/
718 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
720 HICON hIcon = NC_IconForWindow( hwnd );
722 if (hIcon)
724 RECT rect;
725 NC_GetInsideRect( hwnd, &rect );
726 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
727 GetSystemMetrics(SM_CXSMICON),
728 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
730 return (hIcon != 0);
734 /******************************************************************************
736 * NC_DrawCloseButton
738 * Draws the close button.
740 * If bGrayed is true, then draw a disabled Close button
742 *****************************************************************************/
744 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
746 RECT rect;
748 NC_GetInsideRect( hwnd, &rect );
750 /* A tool window has a smaller Close button */
751 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
753 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
754 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
755 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
757 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
758 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
759 rect.bottom = rect.top + iBmpHeight;
760 rect.right = rect.left + iBmpWidth;
762 else
764 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
765 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
766 rect.top += 2;
767 rect.right -= 2;
769 DrawFrameControl( hdc, &rect, DFC_CAPTION,
770 (DFCS_CAPTIONCLOSE |
771 (down ? DFCS_PUSHED : 0) |
772 (bGrayed ? DFCS_INACTIVE : 0)) );
775 /******************************************************************************
776 * NC_DrawMaxButton
778 * Draws the maximize button for windows.
779 * If bGrayed is true, then draw a disabled Maximize button
781 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
783 RECT rect;
784 UINT flags;
786 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
787 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
788 return;
790 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
792 NC_GetInsideRect( hwnd, &rect );
793 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
794 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
795 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
796 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
797 rect.top += 2;
798 rect.right -= 2;
799 if (down) flags |= DFCS_PUSHED;
800 if (bGrayed) flags |= DFCS_INACTIVE;
801 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
804 /******************************************************************************
805 * NC_DrawMinButton
807 * Draws the minimize button for windows.
808 * If bGrayed is true, then draw a disabled Minimize button
810 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
812 RECT rect;
813 UINT flags = DFCS_CAPTIONMIN;
814 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
816 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
817 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
818 return;
820 NC_GetInsideRect( hwnd, &rect );
821 if (style & WS_SYSMENU)
822 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
823 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
824 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
825 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
826 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
827 rect.top += 2;
828 rect.right -= 2;
829 if (down) flags |= DFCS_PUSHED;
830 if (bGrayed) flags |= DFCS_INACTIVE;
831 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
834 /******************************************************************************
836 * NC_DrawFrame
838 * Draw a window frame inside the given rectangle, and update the rectangle.
840 * Bugs
841 * Many. First, just what IS a frame in Win95? Note that the 3D look
842 * on the outer edge is handled by NC_DoNCPaint. As is the inner
843 * edge. The inner rectangle just inside the frame is handled by the
844 * Caption code.
846 * In short, for most people, this function should be a nop (unless
847 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
848 * them lately, but just to get this code right). Even so, it doesn't
849 * appear to be so. It's being worked on...
851 *****************************************************************************/
853 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
855 INT width, height;
857 /* Firstly the "thick" frame */
858 if (style & WS_THICKFRAME)
860 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
861 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
863 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
864 COLOR_INACTIVEBORDER) );
865 /* Draw frame */
866 PatBlt( hdc, rect->left, rect->top,
867 rect->right - rect->left, height, PATCOPY );
868 PatBlt( hdc, rect->left, rect->top,
869 width, rect->bottom - rect->top, PATCOPY );
870 PatBlt( hdc, rect->left, rect->bottom - 1,
871 rect->right - rect->left, -height, PATCOPY );
872 PatBlt( hdc, rect->right - 1, rect->top,
873 -width, rect->bottom - rect->top, PATCOPY );
875 InflateRect( rect, -width, -height );
878 /* Now the other bit of the frame */
879 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
880 (exStyle & WS_EX_DLGMODALFRAME))
882 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
883 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
884 /* This should give a value of 1 that should also work for a border */
886 SelectObject( hdc, GetSysColorBrush(
887 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
888 COLOR_3DFACE :
889 (exStyle & WS_EX_STATICEDGE) ?
890 COLOR_WINDOWFRAME :
891 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
892 COLOR_3DFACE :
893 /* else */
894 COLOR_WINDOWFRAME));
896 /* Draw frame */
897 PatBlt( hdc, rect->left, rect->top,
898 rect->right - rect->left, height, PATCOPY );
899 PatBlt( hdc, rect->left, rect->top,
900 width, rect->bottom - rect->top, PATCOPY );
901 PatBlt( hdc, rect->left, rect->bottom - 1,
902 rect->right - rect->left, -height, PATCOPY );
903 PatBlt( hdc, rect->right - 1, rect->top,
904 -width, rect->bottom - rect->top, PATCOPY );
906 InflateRect( rect, -width, -height );
911 /******************************************************************************
913 * NC_DrawCaption
915 * Draw the window caption for windows.
916 * The correct pen for the window frame must be selected in the DC.
918 *****************************************************************************/
920 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
921 DWORD exStyle, BOOL active )
923 RECT r = *rect;
924 WCHAR buffer[256];
925 HPEN hPrevPen;
926 HMENU hSysMenu;
927 BOOL gradient = FALSE;
929 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
930 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
931 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
932 COLOR_WINDOWFRAME : COLOR_3DFACE) );
933 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
934 LineTo( hdc, r.right, r.bottom - 1 );
935 SelectObject( hdc, hPrevPen );
936 r.bottom--;
938 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
939 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
941 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
942 if (NC_DrawSysButton (hwnd, hdc, FALSE))
943 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
946 if (style & WS_SYSMENU)
948 UINT state;
950 /* Go get the sysmenu */
951 hSysMenu = GetSystemMenu(hwnd, FALSE);
952 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
954 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
955 NC_DrawCloseButton (hwnd, hdc, FALSE,
956 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
957 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
959 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
961 /* In win95 the two buttons are always there */
962 /* But if the menu item is not in the menu they're disabled*/
964 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
965 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
967 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
968 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
972 if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
974 NONCLIENTMETRICSW nclm;
975 HFONT hFont, hOldFont;
976 nclm.cbSize = sizeof(nclm);
977 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
978 if (exStyle & WS_EX_TOOLWINDOW)
979 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
980 else
981 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
982 hOldFont = SelectObject (hdc, hFont);
983 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
984 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
985 SetBkMode( hdc, TRANSPARENT );
986 r.left += 2;
987 DrawTextW( hdc, buffer, -1, &r,
988 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
989 DeleteObject (SelectObject (hdc, hOldFont));
994 /******************************************************************************
995 * NC_DoNCPaint
997 * Paint the non-client area for windows.
999 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1001 HDC hdc;
1002 RECT rfuzz, rect, rectClip;
1003 BOOL active;
1004 WND *wndPtr;
1005 DWORD dwStyle, dwExStyle;
1006 WORD flags;
1007 HRGN hrgn;
1008 RECT rectClient, rectWindow;
1009 int has_menu;
1011 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1012 has_menu = HAS_MENU(wndPtr);
1013 dwStyle = wndPtr->dwStyle;
1014 dwExStyle = wndPtr->dwExStyle;
1015 flags = wndPtr->flags;
1016 rectWindow = wndPtr->rectWindow;
1017 WIN_ReleasePtr( wndPtr );
1019 if ( dwStyle & WS_MINIMIZE ||
1020 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1022 active = flags & WIN_NCACTIVATED;
1024 TRACE("%p %d\n", hwnd, active );
1026 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1027 the call to GetDCEx implying that it is allowed not to use it either.
1028 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1029 will cause clipRgn to be deleted after ReleaseDC().
1030 Now, how is the "system" supposed to tell what happened?
1033 GetClientRect( hwnd, &rectClient );
1034 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1035 hrgn = CreateRectRgnIndirect( &rectClient );
1037 if (clip > (HRGN)1)
1039 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1040 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1042 else
1044 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1047 if (!hdc) return;
1049 rect.top = rect.left = 0;
1050 rect.right = rectWindow.right - rectWindow.left;
1051 rect.bottom = rectWindow.bottom - rectWindow.top;
1052 GetClipBox( hdc, &rectClip );
1054 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1056 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1057 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1059 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1060 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1063 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1065 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1067 RECT r = rect;
1068 if (dwExStyle & WS_EX_TOOLWINDOW) {
1069 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1070 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1072 else {
1073 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1074 rect.top += GetSystemMetrics(SM_CYCAPTION);
1076 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1077 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1080 if (has_menu)
1082 RECT r = rect;
1083 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1085 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1086 r.left, r.top, r.right, r.bottom);
1088 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1091 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1092 rect.left, rect.top, rect.right, rect.bottom );
1094 if (dwExStyle & WS_EX_CLIENTEDGE)
1095 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1097 /* Draw the scroll-bars */
1099 if (dwStyle & WS_VSCROLL)
1100 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1101 if (dwStyle & WS_HSCROLL)
1102 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1104 /* Draw the "size-box" */
1105 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1107 RECT r = rect;
1108 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1109 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1110 else
1111 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1112 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1113 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1116 ReleaseDC( hwnd, hdc );
1122 /***********************************************************************
1123 * NC_HandleNCPaint
1125 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1127 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1129 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1131 if( dwStyle & WS_VISIBLE )
1133 if( dwStyle & WS_MINIMIZE )
1134 WINPOS_RedrawIconTitle( hwnd );
1135 else
1136 NC_DoNCPaint( hwnd, clip, FALSE );
1138 return 0;
1142 /***********************************************************************
1143 * NC_HandleNCActivate
1145 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1147 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1149 WND* wndPtr = WIN_GetPtr( hwnd );
1151 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1153 /* Lotus Notes draws menu descriptions in the caption of its main
1154 * window. When it wants to restore original "system" view, it just
1155 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1156 * attempt to minimize redrawings lead to a not restored caption.
1158 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1159 else wndPtr->flags &= ~WIN_NCACTIVATED;
1160 WIN_ReleasePtr( wndPtr );
1162 if (IsIconic(hwnd))
1163 WINPOS_RedrawIconTitle( hwnd );
1164 else
1165 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1167 return TRUE;
1171 /***********************************************************************
1172 * NC_HandleSetCursor
1174 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1176 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1178 hwnd = WIN_GetFullHandle( (HWND)wParam );
1180 switch((short)LOWORD(lParam))
1182 case HTERROR:
1184 WORD msg = HIWORD( lParam );
1185 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1186 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1187 MessageBeep(0);
1189 break;
1191 case HTCLIENT:
1193 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1194 if(hCursor) {
1195 SetCursor(hCursor);
1196 return TRUE;
1198 return FALSE;
1201 case HTLEFT:
1202 case HTRIGHT:
1203 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1205 case HTTOP:
1206 case HTBOTTOM:
1207 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1209 case HTTOPLEFT:
1210 case HTBOTTOMRIGHT:
1211 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1213 case HTTOPRIGHT:
1214 case HTBOTTOMLEFT:
1215 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1218 /* Default cursor: arrow */
1219 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1222 /***********************************************************************
1223 * NC_GetSysPopupPos
1225 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1227 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1228 else
1230 WND *wndPtr = WIN_GetPtr( hwnd );
1231 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1233 NC_GetInsideRect( hwnd, rect );
1234 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1235 if (wndPtr->dwStyle & WS_CHILD)
1236 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1237 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1238 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1239 WIN_ReleasePtr( wndPtr );
1243 /***********************************************************************
1244 * NC_TrackMinMaxBox
1246 * Track a mouse button press on the minimize or maximize box.
1248 * The big difference between 3.1 and 95 is the disabled button state.
1249 * In win95 the system button can be disabled, so it can ignore the mouse
1250 * event.
1253 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1255 MSG msg;
1256 HDC hdc = GetWindowDC( hwnd );
1257 BOOL pressed = TRUE;
1258 UINT state;
1259 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1260 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1262 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1264 if (wParam == HTMINBUTTON)
1266 /* If the style is not present, do nothing */
1267 if (!(wndStyle & WS_MINIMIZEBOX))
1268 return;
1270 /* Check if the sysmenu item for minimize is there */
1271 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1273 paintButton = &NC_DrawMinButton;
1275 else
1277 /* If the style is not present, do nothing */
1278 if (!(wndStyle & WS_MAXIMIZEBOX))
1279 return;
1281 /* Check if the sysmenu item for maximize is there */
1282 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1284 paintButton = &NC_DrawMaxButton;
1287 SetCapture( hwnd );
1289 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1291 while(1)
1293 BOOL oldstate = pressed;
1295 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1296 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1298 if(msg.message == WM_LBUTTONUP)
1299 break;
1301 if(msg.message != WM_MOUSEMOVE)
1302 continue;
1304 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1305 if (pressed != oldstate)
1306 (*paintButton)( hwnd, hdc, pressed, FALSE);
1309 if(pressed)
1310 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1312 ReleaseCapture();
1313 ReleaseDC( hwnd, hdc );
1315 /* If the item minimize or maximize of the sysmenu are not there */
1316 /* or if the style is not present, do nothing */
1317 if ((!pressed) || (state == 0xFFFFFFFF))
1318 return;
1320 if (wParam == HTMINBUTTON)
1321 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1322 else
1323 SendMessageW( hwnd, WM_SYSCOMMAND,
1324 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1327 /***********************************************************************
1328 * NC_TrackCloseButton
1330 * Track a mouse button press on the Win95 close button.
1332 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1334 MSG msg;
1335 HDC hdc;
1336 BOOL pressed = TRUE;
1337 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1338 UINT state;
1340 if(hSysMenu == 0)
1341 return;
1343 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1345 /* If the item close of the sysmenu is disabled or not there do nothing */
1346 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1347 return;
1349 hdc = GetWindowDC( hwnd );
1351 SetCapture( hwnd );
1353 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1355 while(1)
1357 BOOL oldstate = pressed;
1359 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1360 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1362 if(msg.message == WM_LBUTTONUP)
1363 break;
1365 if(msg.message != WM_MOUSEMOVE)
1366 continue;
1368 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1369 if (pressed != oldstate)
1370 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1373 if(pressed)
1374 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1376 ReleaseCapture();
1377 ReleaseDC( hwnd, hdc );
1378 if (!pressed) return;
1380 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1384 /***********************************************************************
1385 * NC_TrackScrollBar
1387 * Track a mouse button press on the horizontal or vertical scroll-bar.
1389 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1391 INT scrollbar;
1393 if ((wParam & 0xfff0) == SC_HSCROLL)
1395 if ((wParam & 0x0f) != HTHSCROLL) return;
1396 scrollbar = SB_HORZ;
1398 else /* SC_VSCROLL */
1400 if ((wParam & 0x0f) != HTVSCROLL) return;
1401 scrollbar = SB_VERT;
1403 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1407 /***********************************************************************
1408 * NC_HandleNCLButtonDown
1410 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1412 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1414 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1416 switch(wParam) /* Hit test */
1418 case HTCAPTION:
1420 HWND top = GetAncestor( hwnd, GA_ROOT );
1422 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1423 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1424 break;
1427 case HTSYSMENU:
1428 if( style & WS_SYSMENU )
1430 if( !(style & WS_MINIMIZE) )
1432 HDC hDC = GetWindowDC(hwnd);
1433 NC_DrawSysButton( hwnd, hDC, TRUE );
1434 ReleaseDC( hwnd, hDC );
1436 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1438 break;
1440 case HTMENU:
1441 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1442 break;
1444 case HTHSCROLL:
1445 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1446 break;
1448 case HTVSCROLL:
1449 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1450 break;
1452 case HTMINBUTTON:
1453 case HTMAXBUTTON:
1454 NC_TrackMinMaxBox( hwnd, wParam );
1455 break;
1457 case HTCLOSE:
1458 NC_TrackCloseButton (hwnd, wParam);
1459 break;
1461 case HTLEFT:
1462 case HTRIGHT:
1463 case HTTOP:
1464 case HTTOPLEFT:
1465 case HTTOPRIGHT:
1466 case HTBOTTOM:
1467 case HTBOTTOMLEFT:
1468 case HTBOTTOMRIGHT:
1469 /* Old comment:
1470 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1471 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1473 /* But that is not what WinNT does. Instead it sends this. This
1474 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1475 * SC_MOUSEMENU into wParam.
1477 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1478 break;
1480 case HTBORDER:
1481 break;
1483 return 0;
1487 /***********************************************************************
1488 * NC_HandleNCLButtonDblClk
1490 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1492 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1495 * if this is an icon, send a restore since we are handling
1496 * a double click
1498 if (IsIconic(hwnd))
1500 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1501 return 0;
1504 switch(wParam) /* Hit test */
1506 case HTCAPTION:
1507 /* stop processing if WS_MAXIMIZEBOX is missing */
1508 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1509 SendMessageW( hwnd, WM_SYSCOMMAND,
1510 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1511 break;
1513 case HTSYSMENU:
1515 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1516 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1518 /* If the item close of the sysmenu is disabled or not there do nothing */
1519 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1520 break;
1522 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1523 break;
1526 case HTHSCROLL:
1527 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1528 break;
1530 case HTVSCROLL:
1531 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1532 break;
1534 return 0;
1538 /***********************************************************************
1539 * NC_HandleSysCommand
1541 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1543 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1545 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
1547 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1548 return 0;
1550 switch (wParam & 0xfff0)
1552 case SC_SIZE:
1553 case SC_MOVE:
1554 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1555 break;
1557 case SC_MINIMIZE:
1558 if (hwnd == GetForegroundWindow())
1559 ShowOwnedPopups(hwnd,FALSE);
1560 ShowWindow( hwnd, SW_MINIMIZE );
1561 break;
1563 case SC_MAXIMIZE:
1564 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1565 ShowOwnedPopups(hwnd,TRUE);
1566 ShowWindow( hwnd, SW_MAXIMIZE );
1567 break;
1569 case SC_RESTORE:
1570 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1571 ShowOwnedPopups(hwnd,TRUE);
1572 ShowWindow( hwnd, SW_RESTORE );
1573 break;
1575 case SC_CLOSE:
1576 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1578 case SC_VSCROLL:
1579 case SC_HSCROLL:
1581 POINT pt;
1582 pt.x = (short)LOWORD(lParam);
1583 pt.y = (short)HIWORD(lParam);
1584 NC_TrackScrollBar( hwnd, wParam, pt );
1586 break;
1588 case SC_MOUSEMENU:
1590 POINT pt;
1591 pt.x = (short)LOWORD(lParam);
1592 pt.y = (short)HIWORD(lParam);
1593 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1595 break;
1597 case SC_KEYMENU:
1598 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1599 break;
1601 case SC_TASKLIST:
1602 WinExec( "taskman.exe", SW_SHOWNORMAL );
1603 break;
1605 case SC_SCREENSAVE:
1606 if (wParam == SC_ABOUTWINE)
1608 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1609 if (hmodule)
1611 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1612 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1613 FreeLibrary( hmodule );
1616 else
1617 if (wParam == SC_PUTMARK)
1618 DPRINTF("Debug mark requested by user\n");
1619 break;
1621 case SC_HOTKEY:
1622 case SC_ARRANGE:
1623 case SC_NEXTWINDOW:
1624 case SC_PREVWINDOW:
1625 FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
1626 break;
1628 return 0;
1631 /*************************************************************
1632 * NC_DrawGrayButton
1634 * Stub for the grayed button of the caption
1636 *************************************************************/
1638 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1640 HBITMAP hMaskBmp;
1641 HDC hdcMask;
1642 HBRUSH hOldBrush;
1644 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1646 if(hMaskBmp == 0)
1647 return FALSE;
1649 hdcMask = CreateCompatibleDC (0);
1650 SelectObject (hdcMask, hMaskBmp);
1652 /* Draw the grayed bitmap using the mask */
1653 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1654 BitBlt (hdc, x, y, 12, 10,
1655 hdcMask, 0, 0, 0xB8074A);
1657 /* Clean up */
1658 SelectObject (hdc, hOldBrush);
1659 DeleteObject(hMaskBmp);
1660 DeleteDC (hdcMask);
1662 return TRUE;
1665 /***********************************************************************
1666 * GetTitleBarInfo (USER32.@)
1667 * TODO: Handle STATE_SYSTEM_PRESSED
1669 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1670 DWORD dwStyle;
1671 DWORD dwExStyle;
1672 RECT wndRect;
1674 TRACE("(%p %p)\n", hwnd, tbi);
1676 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1677 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
1678 SetLastError(ERROR_INVALID_PARAMETER);
1679 return FALSE;
1681 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1682 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1683 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1685 GetWindowRect(hwnd, &wndRect);
1687 tbi->rcTitleBar.top += wndRect.top;
1688 tbi->rcTitleBar.left += wndRect.left;
1689 tbi->rcTitleBar.right += wndRect.left;
1691 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1692 if(dwExStyle & WS_EX_TOOLWINDOW)
1693 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1694 else {
1695 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1696 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1699 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1700 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1701 * Under XP it seems to
1703 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1704 if(dwStyle & WS_CAPTION) {
1705 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1706 if(dwStyle & WS_SYSMENU) {
1707 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1708 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1709 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1711 else {
1712 if(!(dwStyle & WS_MINIMIZEBOX))
1713 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1714 if(!(dwStyle & WS_MAXIMIZEBOX))
1715 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1717 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1718 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1719 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1720 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1722 else {
1723 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1726 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1729 else
1730 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1731 return TRUE;