mshtml: Added GetCurMoniker implementation.
[wine.git] / dlls / user32 / nonclient.c
blob0410d66ba2dbae653626c939fb0102bec2f9f375
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 "win.h"
30 #include "user_private.h"
31 #include "controls.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
36 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
38 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
39 0x55, 0x50,
40 0xAA, 0xA0,
41 0x55, 0x50,
42 0xAA, 0xA0,
43 0x55, 0x50,
44 0xAA, 0xA0,
45 0x55, 0x50,
46 0xAA, 0xA0,
47 0x55, 0x50};
49 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
50 #define SC_PUTMARK (SC_SCREENSAVE+2)
52 /* Some useful macros */
53 #define HAS_DLGFRAME(style,exStyle) \
54 (((exStyle) & WS_EX_DLGMODALFRAME) || \
55 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
57 #define HAS_THICKFRAME(style,exStyle) \
58 (((style) & WS_THICKFRAME) && \
59 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
61 #define HAS_THINFRAME(style) \
62 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
64 #define HAS_BIGFRAME(style,exStyle) \
65 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
66 ((exStyle) & WS_EX_DLGMODALFRAME))
68 #define HAS_STATICOUTERFRAME(style,exStyle) \
69 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
70 WS_EX_STATICEDGE)
72 #define HAS_ANYFRAME(style,exStyle) \
73 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
74 ((exStyle) & WS_EX_DLGMODALFRAME) || \
75 !((style) & (WS_CHILD | WS_POPUP)))
77 #define HAS_MENU(w) ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
80 /******************************************************************************
81 * NC_AdjustRectOuter
83 * Computes the size of the "outside" parts of the window based on the
84 * parameters of the client area.
86 * PARAMS
87 * LPRECT rect
88 * DWORD style
89 * BOOL menu
90 * DWORD exStyle
92 * NOTES
93 * "Outer" parts of a window means the whole window frame, caption and
94 * menu bar. It does not include "inner" parts of the frame like client
95 * edge, static edge or scroll bars.
97 *****************************************************************************/
99 static void
100 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
102 int adjust;
103 if(style & WS_ICONIC) return;
105 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
106 WS_EX_STATICEDGE)
108 adjust = 1; /* for the outer frame always present */
110 else
112 adjust = 0;
113 if ((exStyle & WS_EX_DLGMODALFRAME) ||
114 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
116 if (style & WS_THICKFRAME)
117 adjust += ( GetSystemMetrics (SM_CXFRAME)
118 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
119 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
120 (exStyle & WS_EX_DLGMODALFRAME))
121 adjust++; /* The other border */
123 InflateRect (rect, adjust, adjust);
125 if ((style & WS_CAPTION) == WS_CAPTION)
127 if (exStyle & WS_EX_TOOLWINDOW)
128 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
129 else
130 rect->top -= GetSystemMetrics(SM_CYCAPTION);
132 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
136 /******************************************************************************
137 * NC_AdjustRectInner
139 * Computes the size of the "inside" part of the window based on the
140 * parameters of the client area.
142 * PARAMS
143 * LPRECT rect
144 * DWORD style
145 * DWORD exStyle
147 * NOTES
148 * "Inner" part of a window means the window frame inside of the flat
149 * window frame. It includes the client edge, the static edge and the
150 * scroll bars.
152 *****************************************************************************/
154 static void
155 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
157 if(style & WS_ICONIC) return;
159 if (exStyle & WS_EX_CLIENTEDGE)
160 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
162 if (style & WS_VSCROLL)
164 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
165 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
166 else
167 rect->right += GetSystemMetrics(SM_CXVSCROLL);
169 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
174 static HICON NC_IconForWindow( HWND hwnd )
176 HICON hIcon = 0;
177 WND *wndPtr = WIN_GetPtr( hwnd );
179 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
181 hIcon = wndPtr->hIconSmall;
182 if (!hIcon) hIcon = wndPtr->hIcon;
183 WIN_ReleasePtr( wndPtr );
185 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
186 if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
188 /* If there is no hIcon specified and this is a modal dialog,
189 * get the default one.
191 if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
192 hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
193 return hIcon;
196 /* Draws the bar part(ie the big rectangle) of the caption */
197 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle,
198 BOOL active, BOOL gradient)
200 if (gradient)
202 TRIVERTEX vertices[6];
203 DWORD colLeft =
204 GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
205 DWORD colRight =
206 GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION
207 : COLOR_GRADIENTINACTIVECAPTION);
208 int v;
209 int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
210 static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
212 for (v = 0; v < 3; v++)
214 vertices[v].Red = GetRValue (colLeft) << 8;
215 vertices[v].Green = GetGValue (colLeft) << 8;
216 vertices[v].Blue = GetBValue (colLeft) << 8;
217 vertices[v].Alpha = 0x8000;
218 vertices[v+3].Red = GetRValue (colRight) << 8;
219 vertices[v+3].Green = GetGValue (colRight) << 8;
220 vertices[v+3].Blue = GetBValue (colRight) << 8;
221 vertices[v+3].Alpha = 0x8000;
224 if ((dwStyle & WS_SYSMENU)
225 && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
226 buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
228 /* area behind icon; solid filled with left color */
229 vertices[0].x = rect->left;
230 vertices[0].y = rect->top;
231 if (dwStyle & WS_SYSMENU)
232 vertices[1].x =
233 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
234 else
235 vertices[1].x = vertices[0].x;
236 vertices[1].y = rect->bottom;
238 /* area behind text; gradient */
239 vertices[2].x = vertices[1].x;
240 vertices[2].y = rect->top;
241 vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
242 vertices[3].y = rect->bottom;
244 /* area behind buttons; solid filled with right color */
245 vertices[4].x = vertices[3].x;
246 vertices[4].y = rect->top;
247 vertices[5].x = rect->right;
248 vertices[5].y = rect->bottom;
250 GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
252 else
253 FillRect (hdc, rect, GetSysColorBrush (active ?
254 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
257 /***********************************************************************
258 * DrawCaption (USER32.@) Draws a caption bar
260 * PARAMS
261 * hwnd [I]
262 * hdc [I]
263 * lpRect [I]
264 * uFlags [I]
266 * RETURNS
267 * Success:
268 * Failure:
271 BOOL WINAPI
272 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
274 return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
278 /***********************************************************************
279 * DrawCaptionTempA (USER32.@)
281 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
282 HICON hIcon, LPCSTR str, UINT uFlags)
284 LPWSTR strW;
285 INT len;
286 BOOL ret = FALSE;
288 if (!(uFlags & DC_TEXT) || !str)
289 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
291 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
292 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
294 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
295 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
296 HeapFree( GetProcessHeap (), 0, strW );
298 return ret;
302 /***********************************************************************
303 * DrawCaptionTempW (USER32.@)
305 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
306 HICON hIcon, LPCWSTR str, UINT uFlags)
308 RECT rc = *rect;
310 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
311 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
313 /* drawing background */
314 if (uFlags & DC_INBUTTON) {
315 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
317 if (uFlags & DC_ACTIVE) {
318 HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
319 PatBlt (hdc, rc.left, rc.top,
320 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
321 SelectObject (hdc, hbr);
324 else {
325 DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
326 NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
330 /* drawing icon */
331 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
332 POINT pt;
334 pt.x = rc.left + 2;
335 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
337 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
338 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
339 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
340 rc.left += (rc.bottom - rc.top);
343 /* drawing text */
344 if (uFlags & DC_TEXT) {
345 HFONT hOldFont;
347 if (uFlags & DC_INBUTTON)
348 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
349 else if (uFlags & DC_ACTIVE)
350 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
351 else
352 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
354 SetBkMode (hdc, TRANSPARENT);
356 if (hFont)
357 hOldFont = SelectObject (hdc, hFont);
358 else {
359 NONCLIENTMETRICSW nclm;
360 HFONT hNewFont;
361 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
362 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
363 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
364 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
365 hOldFont = SelectObject (hdc, hNewFont);
368 if (str)
369 DrawTextW (hdc, str, -1, &rc,
370 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
371 else {
372 WCHAR szText[128];
373 INT nLen;
374 nLen = GetWindowTextW (hwnd, szText, 128);
375 DrawTextW (hdc, szText, nLen, &rc,
376 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
379 if (hFont)
380 SelectObject (hdc, hOldFont);
381 else
382 DeleteObject (SelectObject (hdc, hOldFont));
385 /* drawing focus ??? */
386 if (uFlags & 0x2000)
387 FIXME("undocumented flag (0x2000)!\n");
389 return 0;
393 /***********************************************************************
394 * AdjustWindowRect (USER32.@)
396 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
398 return AdjustWindowRectEx( rect, style, menu, 0 );
402 /***********************************************************************
403 * AdjustWindowRectEx (USER32.@)
405 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
407 /* Correct the window style */
408 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
409 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
410 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
411 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
413 TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
414 rect->left, rect->top, rect->right, rect->bottom,
415 style, menu, exStyle );
417 NC_AdjustRectOuter( rect, style, menu, exStyle );
418 NC_AdjustRectInner( rect, style, exStyle );
420 return TRUE;
424 /***********************************************************************
425 * NC_HandleNCCalcSize
427 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
429 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
431 RECT tmpRect = { 0, 0, 0, 0 };
432 LRESULT result = 0;
433 LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
434 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
435 LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
437 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
438 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
440 if (!IsIconic(hwnd))
442 NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
444 winRect->left -= tmpRect.left;
445 winRect->top -= tmpRect.top;
446 winRect->right -= tmpRect.right;
447 winRect->bottom -= tmpRect.bottom;
449 if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
451 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
452 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
454 winRect->top +=
455 MENU_GetMenuBarHeight( hwnd,
456 winRect->right - winRect->left,
457 -tmpRect.left, -tmpRect.top );
460 if( exStyle & WS_EX_CLIENTEDGE)
461 if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
462 winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
463 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
464 - GetSystemMetrics(SM_CYEDGE));
466 if (style & WS_VSCROLL)
467 if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
468 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
469 winRect->left += GetSystemMetrics(SM_CXVSCROLL);
470 else
471 winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
474 if (style & WS_HSCROLL)
475 if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
476 winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
478 if (winRect->top > winRect->bottom)
479 winRect->bottom = winRect->top;
481 if (winRect->left > winRect->right)
482 winRect->right = winRect->left;
484 return result;
488 /***********************************************************************
489 * NC_GetInsideRect
491 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
492 * but without the borders (if any).
493 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
495 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
497 WND *wndPtr = WIN_GetPtr( hwnd );
499 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
501 rect->top = rect->left = 0;
502 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
503 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
505 if (wndPtr->dwStyle & WS_ICONIC) goto END;
507 /* Remove frame from rectangle */
508 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
510 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
512 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
514 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
516 else if (HAS_THINFRAME( wndPtr->dwStyle ))
518 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
521 /* We have additional border information if the window
522 * is a child (but not an MDI child) */
523 if ( (wndPtr->dwStyle & WS_CHILD) &&
524 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
526 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
527 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
528 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
529 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
532 END:
533 WIN_ReleasePtr( wndPtr );
537 /***********************************************************************
538 * NC_DoNCHitTest
540 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
542 * FIXME: Just a modified copy of the Win 3.1 version.
545 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
547 RECT rect, rcClient;
548 POINT ptClient;
550 TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
552 GetWindowRect(wndPtr->hwndSelf, &rect );
553 if (!PtInRect( &rect, pt )) return HTNOWHERE;
555 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
557 /* Check client area */
558 ptClient = pt;
559 ScreenToClient( wndPtr->hwndSelf, &ptClient );
560 GetClientRect( wndPtr->hwndSelf, &rcClient );
561 if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
563 /* Check borders */
564 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
566 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
567 if (!PtInRect( &rect, pt ))
569 /* Check top sizing border */
570 if (pt.y < rect.top)
572 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
573 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
574 return HTTOP;
576 /* Check bottom sizing border */
577 if (pt.y >= rect.bottom)
579 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
580 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
581 return HTBOTTOM;
583 /* Check left sizing border */
584 if (pt.x < rect.left)
586 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
587 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
588 return HTLEFT;
590 /* Check right sizing border */
591 if (pt.x >= rect.right)
593 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
594 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
595 return HTRIGHT;
599 else /* No thick frame */
601 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
602 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
603 else if (HAS_THINFRAME( wndPtr->dwStyle ))
604 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
605 if (!PtInRect( &rect, pt )) return HTBORDER;
608 /* Check caption */
610 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
612 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
613 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
614 else
615 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
616 if (!PtInRect( &rect, pt ))
618 BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
619 (wndPtr->dwStyle & WS_MINIMIZEBOX);
620 /* Check system menu */
621 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
623 if (NC_IconForWindow(wndPtr->hwndSelf))
624 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
626 if (pt.x < rect.left) return HTSYSMENU;
628 /* Check close button */
629 if (wndPtr->dwStyle & WS_SYSMENU)
630 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
631 if (pt.x > rect.right) return HTCLOSE;
633 /* Check maximize box */
634 /* In win95 there is automatically a Maximize button when there is a minimize one*/
635 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
636 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
637 if (pt.x > rect.right) return HTMAXBUTTON;
639 /* Check minimize box */
640 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
641 if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
642 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
644 if (pt.x > rect.right) return HTMINBUTTON;
645 return HTCAPTION;
649 /* Check vertical scroll bar */
651 if (wndPtr->dwStyle & WS_VSCROLL)
653 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
654 rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
655 else
656 rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
657 if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
660 /* Check horizontal scroll bar */
662 if (wndPtr->dwStyle & WS_HSCROLL)
664 rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
665 if (PtInRect( &rcClient, ptClient ))
667 /* Check size box */
668 if ((wndPtr->dwStyle & WS_VSCROLL) &&
669 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
670 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
671 return HTSIZE;
672 return HTHSCROLL;
676 /* Check menu bar */
678 if (HAS_MENU(wndPtr))
680 if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
681 return HTMENU;
684 /* Has to return HTNOWHERE if nothing was found
685 Could happen when a window has a customized non client area */
686 return HTNOWHERE;
690 /***********************************************************************
691 * NC_HandleNCHitTest
693 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
695 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
697 LRESULT retvalue;
698 WND *wndPtr = WIN_GetPtr( hwnd );
700 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
702 retvalue = NC_DoNCHitTest (wndPtr, pt);
703 WIN_ReleasePtr( wndPtr );
704 return retvalue;
708 /******************************************************************************
710 * NC_DrawSysButton
712 * Draws the system icon.
714 *****************************************************************************/
715 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
717 HICON hIcon = NC_IconForWindow( hwnd );
719 if (hIcon)
721 RECT rect;
722 NC_GetInsideRect( hwnd, &rect );
723 DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
724 GetSystemMetrics(SM_CXSMICON),
725 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
727 return (hIcon != 0);
731 /******************************************************************************
733 * NC_DrawCloseButton
735 * Draws the close button.
737 * If bGrayed is true, then draw a disabled Close button
739 *****************************************************************************/
741 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
743 RECT rect;
745 NC_GetInsideRect( hwnd, &rect );
747 /* A tool window has a smaller Close button */
748 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
750 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
751 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
752 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
754 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
755 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
756 rect.bottom = rect.top + iBmpHeight;
757 rect.right = rect.left + iBmpWidth;
759 else
761 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
762 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
763 rect.top += 2;
764 rect.right -= 2;
766 DrawFrameControl( hdc, &rect, DFC_CAPTION,
767 (DFCS_CAPTIONCLOSE |
768 (down ? DFCS_PUSHED : 0) |
769 (bGrayed ? DFCS_INACTIVE : 0)) );
772 /******************************************************************************
773 * NC_DrawMaxButton
775 * Draws the maximize button for windows.
776 * If bGrayed is true, then draw a disabled Maximize button
778 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
780 RECT rect;
781 UINT flags;
783 /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
784 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
785 return;
787 flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
789 NC_GetInsideRect( hwnd, &rect );
790 if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
791 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
792 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
793 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
794 rect.top += 2;
795 rect.right -= 2;
796 if (down) flags |= DFCS_PUSHED;
797 if (bGrayed) flags |= DFCS_INACTIVE;
798 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
801 /******************************************************************************
802 * NC_DrawMinButton
804 * Draws the minimize button for windows.
805 * If bGrayed is true, then draw a disabled Minimize button
807 static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
809 RECT rect;
810 UINT flags = DFCS_CAPTIONMIN;
811 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
813 /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
814 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
815 return;
817 NC_GetInsideRect( hwnd, &rect );
818 if (style & WS_SYSMENU)
819 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
820 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
821 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
822 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
823 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
824 rect.top += 2;
825 rect.right -= 2;
826 if (down) flags |= DFCS_PUSHED;
827 if (bGrayed) flags |= DFCS_INACTIVE;
828 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
831 /******************************************************************************
833 * NC_DrawFrame
835 * Draw a window frame inside the given rectangle, and update the rectangle.
837 * Bugs
838 * Many. First, just what IS a frame in Win95? Note that the 3D look
839 * on the outer edge is handled by NC_DoNCPaint. As is the inner
840 * edge. The inner rectangle just inside the frame is handled by the
841 * Caption code.
843 * In short, for most people, this function should be a nop (unless
844 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
845 * them lately, but just to get this code right). Even so, it doesn't
846 * appear to be so. It's being worked on...
848 *****************************************************************************/
850 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
852 INT width, height;
854 /* Firstly the "thick" frame */
855 if (style & WS_THICKFRAME)
857 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
858 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
860 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
861 COLOR_INACTIVEBORDER) );
862 /* Draw frame */
863 PatBlt( hdc, rect->left, rect->top,
864 rect->right - rect->left, height, PATCOPY );
865 PatBlt( hdc, rect->left, rect->top,
866 width, rect->bottom - rect->top, PATCOPY );
867 PatBlt( hdc, rect->left, rect->bottom - 1,
868 rect->right - rect->left, -height, PATCOPY );
869 PatBlt( hdc, rect->right - 1, rect->top,
870 -width, rect->bottom - rect->top, PATCOPY );
872 InflateRect( rect, -width, -height );
875 /* Now the other bit of the frame */
876 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
877 (exStyle & WS_EX_DLGMODALFRAME))
879 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
880 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
881 /* This should give a value of 1 that should also work for a border */
883 SelectObject( hdc, GetSysColorBrush(
884 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
885 COLOR_3DFACE :
886 (exStyle & WS_EX_STATICEDGE) ?
887 COLOR_WINDOWFRAME :
888 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
889 COLOR_3DFACE :
890 /* else */
891 COLOR_WINDOWFRAME));
893 /* Draw frame */
894 PatBlt( hdc, rect->left, rect->top,
895 rect->right - rect->left, height, PATCOPY );
896 PatBlt( hdc, rect->left, rect->top,
897 width, rect->bottom - rect->top, PATCOPY );
898 PatBlt( hdc, rect->left, rect->bottom - 1,
899 rect->right - rect->left, -height, PATCOPY );
900 PatBlt( hdc, rect->right - 1, rect->top,
901 -width, rect->bottom - rect->top, PATCOPY );
903 InflateRect( rect, -width, -height );
908 /******************************************************************************
910 * NC_DrawCaption
912 * Draw the window caption for windows.
913 * The correct pen for the window frame must be selected in the DC.
915 *****************************************************************************/
917 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
918 DWORD exStyle, BOOL active )
920 RECT r = *rect;
921 WCHAR buffer[256];
922 HPEN hPrevPen;
923 HMENU hSysMenu;
924 BOOL gradient = FALSE;
926 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
927 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
928 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
929 COLOR_WINDOWFRAME : COLOR_3DFACE) );
930 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
931 LineTo( hdc, r.right, r.bottom - 1 );
932 SelectObject( hdc, hPrevPen );
933 r.bottom--;
935 SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
936 NC_DrawCaptionBar (hdc, rect, style, active, gradient);
938 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
939 if (NC_DrawSysButton (hwnd, hdc, FALSE))
940 r.left += GetSystemMetrics(SM_CXSMICON) + 2;
943 if (style & WS_SYSMENU)
945 UINT state;
947 /* Go get the sysmenu */
948 hSysMenu = GetSystemMenu(hwnd, FALSE);
949 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
951 /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
952 NC_DrawCloseButton (hwnd, hdc, FALSE,
953 (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
954 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
956 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
958 /* In win95 the two buttons are always there */
959 /* But if the menu item is not in the menu they're disabled*/
961 NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
962 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
964 NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
965 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
969 if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
971 NONCLIENTMETRICSW nclm;
972 HFONT hFont, hOldFont;
973 nclm.cbSize = sizeof(nclm);
974 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
975 if (exStyle & WS_EX_TOOLWINDOW)
976 hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
977 else
978 hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
979 hOldFont = SelectObject (hdc, hFont);
980 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
981 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
982 SetBkMode( hdc, TRANSPARENT );
983 r.left += 2;
984 DrawTextW( hdc, buffer, -1, &r,
985 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
986 DeleteObject (SelectObject (hdc, hOldFont));
991 /******************************************************************************
992 * NC_DoNCPaint
994 * Paint the non-client area for windows.
996 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
998 HDC hdc;
999 RECT rfuzz, rect, rectClip;
1000 BOOL active;
1001 WND *wndPtr;
1002 DWORD dwStyle, dwExStyle;
1003 WORD flags;
1004 HRGN hrgn;
1005 RECT rectClient, rectWindow;
1006 int has_menu;
1008 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1009 has_menu = HAS_MENU(wndPtr);
1010 dwStyle = wndPtr->dwStyle;
1011 dwExStyle = wndPtr->dwExStyle;
1012 flags = wndPtr->flags;
1013 rectWindow = wndPtr->rectWindow;
1014 WIN_ReleasePtr( wndPtr );
1016 if ( dwStyle & WS_MINIMIZE ||
1017 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1019 active = flags & WIN_NCACTIVATED;
1021 TRACE("%p %d\n", hwnd, active );
1023 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1024 the call to GetDCEx implying that it is allowed not to use it either.
1025 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1026 will cause clipRgn to be deleted after ReleaseDC().
1027 Now, how is the "system" supposed to tell what happened?
1030 GetClientRect( hwnd, &rectClient );
1031 MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1032 hrgn = CreateRectRgnIndirect( &rectClient );
1034 if (clip > (HRGN)1)
1036 CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1037 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1039 else
1041 hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1044 if (!hdc) return;
1046 rect.top = rect.left = 0;
1047 rect.right = rectWindow.right - rectWindow.left;
1048 rect.bottom = rectWindow.bottom - rectWindow.top;
1049 GetClipBox( hdc, &rectClip );
1051 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1053 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1054 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1056 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1057 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1060 NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1062 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1064 RECT r = rect;
1065 if (dwExStyle & WS_EX_TOOLWINDOW) {
1066 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1067 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1069 else {
1070 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1071 rect.top += GetSystemMetrics(SM_CYCAPTION);
1073 if( IntersectRect( &rfuzz, &r, &rectClip ) )
1074 NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1077 if (has_menu)
1079 RECT r = rect;
1080 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1082 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1083 r.left, r.top, r.right, r.bottom);
1085 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1088 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1089 rect.left, rect.top, rect.right, rect.bottom );
1091 if (dwExStyle & WS_EX_CLIENTEDGE)
1092 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1094 /* Draw the scroll-bars */
1096 if (dwStyle & WS_VSCROLL)
1097 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1098 if (dwStyle & WS_HSCROLL)
1099 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1101 /* Draw the "size-box" */
1102 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1104 RECT r = rect;
1105 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1106 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1107 else
1108 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1109 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1110 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1113 ReleaseDC( hwnd, hdc );
1119 /***********************************************************************
1120 * NC_HandleNCPaint
1122 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1124 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1126 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1128 if( dwStyle & WS_VISIBLE )
1130 if( dwStyle & WS_MINIMIZE )
1131 WINPOS_RedrawIconTitle( hwnd );
1132 else
1133 NC_DoNCPaint( hwnd, clip, FALSE );
1135 return 0;
1139 /***********************************************************************
1140 * NC_HandleNCActivate
1142 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1144 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1146 WND* wndPtr = WIN_GetPtr( hwnd );
1148 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1150 /* Lotus Notes draws menu descriptions in the caption of its main
1151 * window. When it wants to restore original "system" view, it just
1152 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1153 * attempt to minimize redrawings lead to a not restored caption.
1155 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1156 else wndPtr->flags &= ~WIN_NCACTIVATED;
1157 WIN_ReleasePtr( wndPtr );
1159 if (IsIconic(hwnd))
1160 WINPOS_RedrawIconTitle( hwnd );
1161 else
1162 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1164 return TRUE;
1168 /***********************************************************************
1169 * NC_HandleSetCursor
1171 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1173 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1175 hwnd = WIN_GetFullHandle( (HWND)wParam );
1177 switch((short)LOWORD(lParam))
1179 case HTERROR:
1181 WORD msg = HIWORD( lParam );
1182 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1183 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1184 MessageBeep(0);
1186 break;
1188 case HTCLIENT:
1190 HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1191 if(hCursor) {
1192 SetCursor(hCursor);
1193 return TRUE;
1195 return FALSE;
1198 case HTLEFT:
1199 case HTRIGHT:
1200 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1202 case HTTOP:
1203 case HTBOTTOM:
1204 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1206 case HTTOPLEFT:
1207 case HTBOTTOMRIGHT:
1208 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1210 case HTTOPRIGHT:
1211 case HTBOTTOMLEFT:
1212 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1215 /* Default cursor: arrow */
1216 return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1219 /***********************************************************************
1220 * NC_GetSysPopupPos
1222 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1224 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1225 else
1227 WND *wndPtr = WIN_GetPtr( hwnd );
1228 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1230 NC_GetInsideRect( hwnd, rect );
1231 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1232 if (wndPtr->dwStyle & WS_CHILD)
1233 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1234 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1235 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1236 WIN_ReleasePtr( wndPtr );
1240 /***********************************************************************
1241 * NC_TrackMinMaxBox
1243 * Track a mouse button press on the minimize or maximize box.
1245 * The big difference between 3.1 and 95 is the disabled button state.
1246 * In win95 the system button can be disabled, so it can ignore the mouse
1247 * event.
1250 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1252 MSG msg;
1253 HDC hdc = GetWindowDC( hwnd );
1254 BOOL pressed = TRUE;
1255 UINT state;
1256 DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1257 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1259 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1261 if (wParam == HTMINBUTTON)
1263 /* If the style is not present, do nothing */
1264 if (!(wndStyle & WS_MINIMIZEBOX))
1265 return;
1267 /* Check if the sysmenu item for minimize is there */
1268 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1270 paintButton = &NC_DrawMinButton;
1272 else
1274 /* If the style is not present, do nothing */
1275 if (!(wndStyle & WS_MAXIMIZEBOX))
1276 return;
1278 /* Check if the sysmenu item for maximize is there */
1279 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1281 paintButton = &NC_DrawMaxButton;
1284 SetCapture( hwnd );
1286 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1288 while(1)
1290 BOOL oldstate = pressed;
1292 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1293 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1295 if(msg.message == WM_LBUTTONUP)
1296 break;
1298 if(msg.message != WM_MOUSEMOVE)
1299 continue;
1301 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1302 if (pressed != oldstate)
1303 (*paintButton)( hwnd, hdc, pressed, FALSE);
1306 if(pressed)
1307 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1309 ReleaseCapture();
1310 ReleaseDC( hwnd, hdc );
1312 /* If the item minimize or maximize of the sysmenu are not there */
1313 /* or if the style is not present, do nothing */
1314 if ((!pressed) || (state == 0xFFFFFFFF))
1315 return;
1317 if (wParam == HTMINBUTTON)
1318 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1319 else
1320 SendMessageW( hwnd, WM_SYSCOMMAND,
1321 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1324 /***********************************************************************
1325 * NC_TrackCloseButton
1327 * Track a mouse button press on the Win95 close button.
1329 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1331 MSG msg;
1332 HDC hdc;
1333 BOOL pressed = TRUE;
1334 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1335 UINT state;
1337 if(hSysMenu == 0)
1338 return;
1340 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1342 /* If the item close of the sysmenu is disabled or not there do nothing */
1343 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1344 return;
1346 hdc = GetWindowDC( hwnd );
1348 SetCapture( hwnd );
1350 NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1352 while(1)
1354 BOOL oldstate = pressed;
1356 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1357 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1359 if(msg.message == WM_LBUTTONUP)
1360 break;
1362 if(msg.message != WM_MOUSEMOVE)
1363 continue;
1365 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1366 if (pressed != oldstate)
1367 NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1370 if(pressed)
1371 NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1373 ReleaseCapture();
1374 ReleaseDC( hwnd, hdc );
1375 if (!pressed) return;
1377 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1381 /***********************************************************************
1382 * NC_TrackScrollBar
1384 * Track a mouse button press on the horizontal or vertical scroll-bar.
1386 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1388 INT scrollbar;
1390 if ((wParam & 0xfff0) == SC_HSCROLL)
1392 if ((wParam & 0x0f) != HTHSCROLL) return;
1393 scrollbar = SB_HORZ;
1395 else /* SC_VSCROLL */
1397 if ((wParam & 0x0f) != HTVSCROLL) return;
1398 scrollbar = SB_VERT;
1400 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1404 /***********************************************************************
1405 * NC_HandleNCLButtonDown
1407 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1409 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1411 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1413 switch(wParam) /* Hit test */
1415 case HTCAPTION:
1417 HWND top = GetAncestor( hwnd, GA_ROOT );
1419 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1420 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1421 break;
1424 case HTSYSMENU:
1425 if( style & WS_SYSMENU )
1427 if( !(style & WS_MINIMIZE) )
1429 HDC hDC = GetWindowDC(hwnd);
1430 NC_DrawSysButton( hwnd, hDC, TRUE );
1431 ReleaseDC( hwnd, hDC );
1433 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1435 break;
1437 case HTMENU:
1438 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1439 break;
1441 case HTHSCROLL:
1442 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1443 break;
1445 case HTVSCROLL:
1446 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1447 break;
1449 case HTMINBUTTON:
1450 case HTMAXBUTTON:
1451 NC_TrackMinMaxBox( hwnd, wParam );
1452 break;
1454 case HTCLOSE:
1455 NC_TrackCloseButton (hwnd, wParam);
1456 break;
1458 case HTLEFT:
1459 case HTRIGHT:
1460 case HTTOP:
1461 case HTTOPLEFT:
1462 case HTTOPRIGHT:
1463 case HTBOTTOM:
1464 case HTBOTTOMLEFT:
1465 case HTBOTTOMRIGHT:
1466 /* Old comment:
1467 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1468 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1470 /* But that is not what WinNT does. Instead it sends this. This
1471 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1472 * SC_MOUSEMENU into wParam.
1474 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1475 break;
1477 case HTBORDER:
1478 break;
1480 return 0;
1484 /***********************************************************************
1485 * NC_HandleNCLButtonDblClk
1487 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1489 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1492 * if this is an icon, send a restore since we are handling
1493 * a double click
1495 if (IsIconic(hwnd))
1497 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1498 return 0;
1501 switch(wParam) /* Hit test */
1503 case HTCAPTION:
1504 /* stop processing if WS_MAXIMIZEBOX is missing */
1505 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1506 SendMessageW( hwnd, WM_SYSCOMMAND,
1507 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1508 break;
1510 case HTSYSMENU:
1512 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1513 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1515 /* If the item close of the sysmenu is disabled or not there do nothing */
1516 if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1517 break;
1519 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1520 break;
1523 case HTHSCROLL:
1524 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1525 break;
1527 case HTVSCROLL:
1528 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1529 break;
1531 return 0;
1535 /***********************************************************************
1536 * NC_HandleSysCommand
1538 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1540 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1542 TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1544 if (!IsWindowEnabled( hwnd )) return 0;
1546 if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1547 return 0;
1549 switch (wParam & 0xfff0)
1551 case SC_SIZE:
1552 case SC_MOVE:
1553 USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1554 break;
1556 case SC_MINIMIZE:
1557 if (hwnd == GetForegroundWindow())
1558 ShowOwnedPopups(hwnd,FALSE);
1559 ShowWindow( hwnd, SW_MINIMIZE );
1560 break;
1562 case SC_MAXIMIZE:
1563 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1564 ShowOwnedPopups(hwnd,TRUE);
1565 ShowWindow( hwnd, SW_MAXIMIZE );
1566 break;
1568 case SC_RESTORE:
1569 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1570 ShowOwnedPopups(hwnd,TRUE);
1571 ShowWindow( hwnd, SW_RESTORE );
1572 break;
1574 case SC_CLOSE:
1575 return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1577 case SC_VSCROLL:
1578 case SC_HSCROLL:
1580 POINT pt;
1581 pt.x = (short)LOWORD(lParam);
1582 pt.y = (short)HIWORD(lParam);
1583 NC_TrackScrollBar( hwnd, wParam, pt );
1585 break;
1587 case SC_MOUSEMENU:
1589 POINT pt;
1590 pt.x = (short)LOWORD(lParam);
1591 pt.y = (short)HIWORD(lParam);
1592 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1594 break;
1596 case SC_KEYMENU:
1597 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1598 break;
1600 case SC_TASKLIST:
1601 WinExec( "taskman.exe", SW_SHOWNORMAL );
1602 break;
1604 case SC_SCREENSAVE:
1605 if (wParam == SC_ABOUTWINE)
1607 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1608 if (hmodule)
1610 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1611 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1612 FreeLibrary( hmodule );
1615 else
1616 if (wParam == SC_PUTMARK)
1617 DPRINTF("Debug mark requested by user\n");
1618 break;
1620 case SC_HOTKEY:
1621 case SC_ARRANGE:
1622 case SC_NEXTWINDOW:
1623 case SC_PREVWINDOW:
1624 FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1625 break;
1627 return 0;
1630 /*************************************************************
1631 * NC_DrawGrayButton
1633 * Stub for the grayed button of the caption
1635 *************************************************************/
1637 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1639 HBITMAP hMaskBmp;
1640 HDC hdcMask;
1641 HBRUSH hOldBrush;
1643 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1645 if(hMaskBmp == 0)
1646 return FALSE;
1648 hdcMask = CreateCompatibleDC (0);
1649 SelectObject (hdcMask, hMaskBmp);
1651 /* Draw the grayed bitmap using the mask */
1652 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1653 BitBlt (hdc, x, y, 12, 10,
1654 hdcMask, 0, 0, 0xB8074A);
1656 /* Clean up */
1657 SelectObject (hdc, hOldBrush);
1658 DeleteObject(hMaskBmp);
1659 DeleteDC (hdcMask);
1661 return TRUE;
1664 /***********************************************************************
1665 * GetTitleBarInfo (USER32.@)
1666 * TODO: Handle STATE_SYSTEM_PRESSED
1668 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1669 DWORD dwStyle;
1670 DWORD dwExStyle;
1671 RECT wndRect;
1673 TRACE("(%p %p)\n", hwnd, tbi);
1675 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1676 TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1677 SetLastError(ERROR_INVALID_PARAMETER);
1678 return FALSE;
1680 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1681 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1682 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1684 GetWindowRect(hwnd, &wndRect);
1686 tbi->rcTitleBar.top += wndRect.top;
1687 tbi->rcTitleBar.left += wndRect.left;
1688 tbi->rcTitleBar.right += wndRect.left;
1690 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1691 if(dwExStyle & WS_EX_TOOLWINDOW)
1692 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1693 else {
1694 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1695 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1698 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1699 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1700 * Under XP it seems to
1702 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1703 if(dwStyle & WS_CAPTION) {
1704 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1705 if(dwStyle & WS_SYSMENU) {
1706 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1707 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1708 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1710 else {
1711 if(!(dwStyle & WS_MINIMIZEBOX))
1712 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1713 if(!(dwStyle & WS_MAXIMIZEBOX))
1714 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1716 if(!(dwExStyle & WS_EX_CONTEXTHELP))
1717 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1718 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1719 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1721 else {
1722 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1723 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1724 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1725 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1728 else
1729 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1730 return TRUE;