Fix bad logic in == NULL test.
[wine/multimedia.git] / windows / nonclient.c
blob5c53ba3054d5c3d4c6f764a067ea938770f0cb25
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "wine/winuser16.h"
26 #include "wownt32.h"
27 #include "win.h"
28 #include "user.h"
29 #include "dce.h"
30 #include "controls.h"
31 #include "cursoricon.h"
32 #include "winpos.h"
33 #include "nonclient.h"
34 #include "shellapi.h"
35 #include "bitmap.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
39 WINE_DECLARE_DEBUG_CHANNEL(shell);
41 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
43 static HBITMAP hbitmapClose;
45 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
46 0x55, 0x50,
47 0xAA, 0xA0,
48 0x55, 0x50,
49 0xAA, 0xA0,
50 0x55, 0x50,
51 0xAA, 0xA0,
52 0x55, 0x50,
53 0xAA, 0xA0,
54 0x55, 0x50};
56 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
57 #define SC_PUTMARK (SC_SCREENSAVE+2)
59 /* Some useful macros */
60 #define HAS_DLGFRAME(style,exStyle) \
61 (((exStyle) & WS_EX_DLGMODALFRAME) || \
62 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
64 #define HAS_THICKFRAME(style,exStyle) \
65 (((style) & WS_THICKFRAME) && \
66 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
68 #define HAS_THINFRAME(style) \
69 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
71 #define HAS_BIGFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME))
75 #define HAS_STATICOUTERFRAME(style,exStyle) \
76 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
77 WS_EX_STATICEDGE)
79 #define HAS_ANYFRAME(style,exStyle) \
80 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
81 ((exStyle) & WS_EX_DLGMODALFRAME) || \
82 !((style) & (WS_CHILD | WS_POPUP)))
84 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
87 /***********************************************************************
88 * NC_AdjustRect
90 * Compute the size of the window rectangle from the size of the
91 * client rectangle.
93 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
95 if (TWEAK_WineLook > WIN31_LOOK)
96 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
98 if(style & WS_ICONIC) return;
100 if (HAS_THICKFRAME( style, exStyle ))
101 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
102 else if (HAS_DLGFRAME( style, exStyle ))
103 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
104 else if (HAS_THINFRAME( style ))
105 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
107 if ((style & WS_CAPTION) == WS_CAPTION)
108 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
110 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
112 if (style & WS_VSCROLL) {
113 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
114 if(!HAS_ANYFRAME( style, exStyle ))
115 rect->right++;
118 if (style & WS_HSCROLL) {
119 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
120 if(!HAS_ANYFRAME( style, exStyle ))
121 rect->bottom++;
126 /******************************************************************************
127 * NC_AdjustRectOuter95
129 * Computes the size of the "outside" parts of the window based on the
130 * parameters of the client area.
132 + PARAMS
133 * LPRECT16 rect
134 * DWORD style
135 * BOOL menu
136 * DWORD exStyle
138 * NOTES
139 * "Outer" parts of a window means the whole window frame, caption and
140 * menu bar. It does not include "inner" parts of the frame like client
141 * edge, static edge or scroll bars.
143 * Revision history
144 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
145 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
147 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
148 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
149 * NC_AdjustRectInner95 and added handling of Win95 styles.
151 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
152 * Streamlined window style checks.
154 *****************************************************************************/
156 static void
157 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
159 int adjust;
160 if(style & WS_ICONIC) return;
162 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
163 WS_EX_STATICEDGE)
165 adjust = 1; /* for the outer frame always present */
167 else
169 adjust = 0;
170 if ((exStyle & WS_EX_DLGMODALFRAME) ||
171 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
173 if (style & WS_THICKFRAME)
174 adjust += ( GetSystemMetrics (SM_CXFRAME)
175 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
176 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
177 (exStyle & WS_EX_DLGMODALFRAME))
178 adjust++; /* The other border */
180 InflateRect (rect, adjust, adjust);
182 if ((style & WS_CAPTION) == WS_CAPTION)
184 if (exStyle & WS_EX_TOOLWINDOW)
185 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
186 else
187 rect->top -= GetSystemMetrics(SM_CYCAPTION);
189 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
193 /******************************************************************************
194 * NC_AdjustRectInner95
196 * Computes the size of the "inside" part of the window based on the
197 * parameters of the client area.
199 + PARAMS
200 * LPRECT16 rect
201 * DWORD style
202 * DWORD exStyle
204 * NOTES
205 * "Inner" part of a window means the window frame inside of the flat
206 * window frame. It includes the client edge, the static edge and the
207 * scroll bars.
209 * Revision history
210 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
211 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
213 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
214 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
215 * NC_AdjustRectInner95 and added handling of Win95 styles.
217 *****************************************************************************/
219 static void
220 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
222 if(style & WS_ICONIC) return;
224 if (exStyle & WS_EX_CLIENTEDGE)
225 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
227 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
228 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
233 static HICON NC_IconForWindow( HWND hwnd )
235 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
236 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
238 /* If there is no hIcon specified and this is a modal dialog,
239 * get the default one.
241 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
242 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
243 return hIcon;
246 /***********************************************************************
247 * DrawCaption (USER32.@) Draws a caption bar
249 * PARAMS
250 * hwnd [I]
251 * hdc [I]
252 * lpRect [I]
253 * uFlags [I]
255 * RETURNS
256 * Success:
257 * Failure:
260 BOOL WINAPI
261 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
263 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
267 /***********************************************************************
268 * DrawCaptionTempA (USER32.@)
270 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
271 HICON hIcon, LPCSTR str, UINT uFlags)
273 LPWSTR strW;
274 INT len;
275 BOOL ret = FALSE;
277 if (!(uFlags & DC_TEXT) || !str)
278 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
280 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
281 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
283 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
284 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
285 HeapFree( GetProcessHeap (), 0, strW );
287 return ret;
291 /***********************************************************************
292 * DrawCaptionTempW (USER32.@)
294 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
295 HICON hIcon, LPCWSTR str, UINT uFlags)
297 RECT rc = *rect;
299 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
300 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
302 /* drawing background */
303 if (uFlags & DC_INBUTTON) {
304 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
306 if (uFlags & DC_ACTIVE) {
307 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
308 PatBlt (hdc, rc.left, rc.top,
309 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
310 SelectObject (hdc, hbr);
313 else {
314 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
315 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
319 /* drawing icon */
320 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
321 POINT pt;
323 pt.x = rc.left + 2;
324 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
326 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
327 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
328 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
329 rc.left += (rc.bottom - rc.top);
332 /* drawing text */
333 if (uFlags & DC_TEXT) {
334 HFONT hOldFont;
336 if (uFlags & DC_INBUTTON)
337 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
338 else if (uFlags & DC_ACTIVE)
339 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
340 else
341 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
343 SetBkMode (hdc, TRANSPARENT);
345 if (hFont)
346 hOldFont = SelectObject (hdc, hFont);
347 else {
348 NONCLIENTMETRICSW nclm;
349 HFONT hNewFont;
350 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
351 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
352 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
353 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
354 hOldFont = SelectObject (hdc, hNewFont);
357 if (str)
358 DrawTextW (hdc, str, -1, &rc,
359 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
360 else {
361 WCHAR szText[128];
362 INT nLen;
363 nLen = GetWindowTextW (hwnd, szText, 128);
364 DrawTextW (hdc, szText, nLen, &rc,
365 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
368 if (hFont)
369 SelectObject (hdc, hOldFont);
370 else
371 DeleteObject (SelectObject (hdc, hOldFont));
374 /* drawing focus ??? */
375 if (uFlags & 0x2000)
376 FIXME("undocumented flag (0x2000)!\n");
378 return 0;
382 /***********************************************************************
383 * AdjustWindowRect (USER.102)
385 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
387 return AdjustWindowRectEx16( rect, style, menu, 0 );
391 /***********************************************************************
392 * AdjustWindowRect (USER32.@)
394 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
396 return AdjustWindowRectEx( rect, style, menu, 0 );
400 /***********************************************************************
401 * AdjustWindowRectEx (USER.454)
403 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
404 BOOL16 menu, DWORD exStyle )
406 RECT rect32;
407 BOOL ret;
409 CONV_RECT16TO32( rect, &rect32 );
410 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
411 CONV_RECT32TO16( &rect32, rect );
412 return ret;
416 /***********************************************************************
417 * AdjustWindowRectEx (USER32.@)
419 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
421 /* Correct the window style */
422 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
423 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
424 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
425 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
427 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
428 rect->left, rect->top, rect->right, rect->bottom,
429 style, menu, exStyle );
431 if (TWEAK_WineLook == WIN31_LOOK)
432 NC_AdjustRect( rect, style, menu, exStyle );
433 else
435 NC_AdjustRectOuter95( rect, style, menu, exStyle );
436 NC_AdjustRectInner95( rect, style, exStyle );
438 return TRUE;
442 /***********************************************************************
443 * NC_HandleNCCalcSize
445 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
447 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
449 RECT tmpRect = { 0, 0, 0, 0 };
450 LONG result = 0;
451 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
452 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
453 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
455 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
456 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
458 if (!IsIconic(hwnd))
460 if (TWEAK_WineLook == WIN31_LOOK)
461 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
462 else
463 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
465 winRect->left -= tmpRect.left;
466 winRect->top -= tmpRect.top;
467 winRect->right -= tmpRect.right;
468 winRect->bottom -= tmpRect.bottom;
470 if (!(style & WS_CHILD) && GetMenu(hwnd))
472 TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
473 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
475 winRect->top +=
476 MENU_GetMenuBarHeight( hwnd,
477 winRect->right - winRect->left,
478 -tmpRect.left, -tmpRect.top ) + 1;
481 if (TWEAK_WineLook > WIN31_LOOK) {
482 SetRect(&tmpRect, 0, 0, 0, 0);
483 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
484 winRect->left -= tmpRect.left;
485 winRect->top -= tmpRect.top;
486 winRect->right -= tmpRect.right;
487 winRect->bottom -= tmpRect.bottom;
490 if (winRect->top > winRect->bottom)
491 winRect->bottom = winRect->top;
493 if (winRect->left > winRect->right)
494 winRect->right = winRect->left;
496 return result;
500 /***********************************************************************
501 * NC_GetInsideRect
503 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
504 * but without the borders (if any).
505 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
507 void NC_GetInsideRect( HWND hwnd, RECT *rect )
509 WND * wndPtr = WIN_FindWndPtr( hwnd );
511 rect->top = rect->left = 0;
512 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
513 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
515 if (wndPtr->dwStyle & WS_ICONIC) goto END;
517 /* Remove frame from rectangle */
518 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
520 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
522 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
524 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
525 /* FIXME: this isn't in NC_AdjustRect? why not? */
526 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
527 InflateRect( rect, -1, 0 );
529 else if (HAS_THINFRAME( wndPtr->dwStyle ))
531 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
534 /* We have additional border information if the window
535 * is a child (but not an MDI child) */
536 if (TWEAK_WineLook != WIN31_LOOK)
538 if ( (wndPtr->dwStyle & WS_CHILD) &&
539 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
541 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
542 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
543 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
544 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
548 END:
549 WIN_ReleaseWndPtr(wndPtr);
550 return;
554 /***********************************************************************
555 * NC_DoNCHitTest
557 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
560 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
562 RECT rect;
564 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
566 GetWindowRect(wndPtr->hwndSelf, &rect );
567 if (!PtInRect( &rect, pt )) return HTNOWHERE;
569 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
571 /* Check borders */
572 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
574 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
575 if (!PtInRect( &rect, pt ))
577 /* Check top sizing border */
578 if (pt.y < rect.top)
580 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
581 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
582 return HTTOP;
584 /* Check bottom sizing border */
585 if (pt.y >= rect.bottom)
587 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
588 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
589 return HTBOTTOM;
591 /* Check left sizing border */
592 if (pt.x < rect.left)
594 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
595 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
596 return HTLEFT;
598 /* Check right sizing border */
599 if (pt.x >= rect.right)
601 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
602 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
603 return HTRIGHT;
607 else /* No thick frame */
609 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
610 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
611 else if (HAS_THINFRAME( wndPtr->dwStyle ))
612 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
613 if (!PtInRect( &rect, pt )) return HTBORDER;
616 /* Check caption */
618 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
620 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
621 if (!PtInRect( &rect, pt ))
623 /* Check system menu */
624 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
625 rect.left += GetSystemMetrics(SM_CXSIZE);
626 if (pt.x <= rect.left) return HTSYSMENU;
628 /* Check maximize box */
629 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
630 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
632 if (pt.x >= rect.right) return HTMAXBUTTON;
633 /* Check minimize box */
634 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
635 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
636 if (pt.x >= rect.right) return HTMINBUTTON;
637 return HTCAPTION;
641 /* Check client area */
643 ScreenToClient( wndPtr->hwndSelf, &pt );
644 GetClientRect( wndPtr->hwndSelf, &rect );
645 if (PtInRect( &rect, pt )) return HTCLIENT;
647 /* Check vertical scroll bar */
649 if (wndPtr->dwStyle & WS_VSCROLL)
651 rect.right += GetSystemMetrics(SM_CXVSCROLL);
652 if (PtInRect( &rect, pt )) return HTVSCROLL;
655 /* Check horizontal scroll bar */
657 if (wndPtr->dwStyle & WS_HSCROLL)
659 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
660 if (PtInRect( &rect, pt ))
662 /* Check size box */
663 if ((wndPtr->dwStyle & WS_VSCROLL) &&
664 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
665 return HTSIZE;
666 return HTHSCROLL;
670 /* Check menu bar */
672 if (HAS_MENU(wndPtr))
674 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
675 return HTMENU;
678 /* Has to return HTNOWHERE if nothing was found
679 Could happen when a window has a customized non client area */
680 return HTNOWHERE;
684 /***********************************************************************
685 * NC_DoNCHitTest95
687 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
689 * FIXME: Just a modified copy of the Win 3.1 version.
692 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
694 RECT rect;
696 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
698 GetWindowRect(wndPtr->hwndSelf, &rect );
699 if (!PtInRect( &rect, pt )) return HTNOWHERE;
701 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
703 /* Check borders */
704 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
706 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
707 if (!PtInRect( &rect, pt ))
709 /* Check top sizing border */
710 if (pt.y < rect.top)
712 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
713 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
714 return HTTOP;
716 /* Check bottom sizing border */
717 if (pt.y >= rect.bottom)
719 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
720 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
721 return HTBOTTOM;
723 /* Check left sizing border */
724 if (pt.x < rect.left)
726 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
727 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
728 return HTLEFT;
730 /* Check right sizing border */
731 if (pt.x >= rect.right)
733 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
734 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
735 return HTRIGHT;
739 else /* No thick frame */
741 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
742 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
743 else if (HAS_THINFRAME( wndPtr->dwStyle ))
744 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
745 if (!PtInRect( &rect, pt )) return HTBORDER;
748 /* Check caption */
750 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
752 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
753 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
754 else
755 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
756 if (!PtInRect( &rect, pt ))
758 /* Check system menu */
759 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
761 if (NC_IconForWindow(wndPtr->hwndSelf))
762 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
764 if (pt.x < rect.left) return HTSYSMENU;
766 /* Check close button */
767 if (wndPtr->dwStyle & WS_SYSMENU)
768 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
769 if (pt.x > rect.right) return HTCLOSE;
771 /* Check maximize box */
772 /* In win95 there is automatically a Maximize button when there is a minimize one*/
773 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
774 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
775 if (pt.x > rect.right) return HTMAXBUTTON;
777 /* Check minimize box */
778 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
779 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
780 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
782 if (pt.x > rect.right) return HTMINBUTTON;
783 return HTCAPTION;
787 /* Check client area */
789 ScreenToClient( wndPtr->hwndSelf, &pt );
790 GetClientRect( wndPtr->hwndSelf, &rect );
791 if (PtInRect( &rect, pt )) return HTCLIENT;
793 /* Check vertical scroll bar */
795 if (wndPtr->dwStyle & WS_VSCROLL)
797 rect.right += GetSystemMetrics(SM_CXVSCROLL);
798 if (PtInRect( &rect, pt )) return HTVSCROLL;
801 /* Check horizontal scroll bar */
803 if (wndPtr->dwStyle & WS_HSCROLL)
805 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
806 if (PtInRect( &rect, pt ))
808 /* Check size box */
809 if ((wndPtr->dwStyle & WS_VSCROLL) &&
810 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
811 return HTSIZE;
812 return HTHSCROLL;
816 /* Check menu bar */
818 if (HAS_MENU(wndPtr))
820 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
821 return HTMENU;
824 /* Has to return HTNOWHERE if nothing was found
825 Could happen when a window has a customized non client area */
826 return HTNOWHERE;
830 /***********************************************************************
831 * NC_HandleNCHitTest
833 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
835 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
837 LONG retvalue;
838 WND *wndPtr = WIN_FindWndPtr (hwnd);
840 if (!wndPtr)
841 return HTERROR;
843 if (TWEAK_WineLook == WIN31_LOOK)
844 retvalue = NC_DoNCHitTest (wndPtr, pt);
845 else
846 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
847 WIN_ReleaseWndPtr(wndPtr);
848 return retvalue;
852 /***********************************************************************
853 * NC_DrawSysButton
855 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
857 RECT rect;
858 HDC hdcMem;
859 HBITMAP hbitmap;
861 NC_GetInsideRect( hwnd, &rect );
862 hdcMem = CreateCompatibleDC( hdc );
863 hbitmap = SelectObject( hdcMem, hbitmapClose );
864 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
865 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
866 down ? NOTSRCCOPY : SRCCOPY );
867 SelectObject( hdcMem, hbitmap );
868 DeleteDC( hdcMem );
872 /***********************************************************************
873 * NC_DrawMaxButton
875 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
877 RECT rect;
878 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
880 NC_GetInsideRect( hwnd, &rect );
881 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
882 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
883 rect.top += 1;
884 rect.right -= 1;
885 if (down) flags |= DFCS_PUSHED;
886 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
890 /***********************************************************************
891 * NC_DrawMinButton
893 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
895 RECT rect;
896 UINT flags = DFCS_CAPTIONMIN;
897 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
899 NC_GetInsideRect( hwnd, &rect );
900 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
901 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
902 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
903 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
904 rect.top += 1;
905 rect.right -= 1;
906 if (down) flags |= DFCS_PUSHED;
907 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
911 /******************************************************************************
913 * void NC_DrawSysButton95(
914 * HWND hwnd,
915 * HDC hdc,
916 * BOOL down )
918 * Draws the Win95 system icon.
920 * Revision history
921 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
922 * Original implementation from NC_DrawSysButton source.
923 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
924 * Fixed most bugs.
926 *****************************************************************************/
928 BOOL
929 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
931 HICON hIcon = NC_IconForWindow( hwnd );
933 if (hIcon)
935 RECT rect;
936 NC_GetInsideRect( hwnd, &rect );
937 DrawIconEx (hdc, rect.left + 1, rect.top + 1, hIcon,
938 GetSystemMetrics(SM_CXSIZE) - 1,
939 GetSystemMetrics(SM_CYSIZE) - 1, 0, 0, DI_NORMAL);
941 return (hIcon != 0);
945 /******************************************************************************
947 * void NC_DrawCloseButton95(
948 * HWND hwnd,
949 * HDC hdc,
950 * BOOL down,
951 * BOOL bGrayed )
953 * Draws the Win95 close button.
955 * If bGrayed is true, then draw a disabled Close button
957 * Revision history
958 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
959 * Original implementation from NC_DrawSysButton95 source.
961 *****************************************************************************/
963 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
965 RECT rect;
967 NC_GetInsideRect( hwnd, &rect );
969 /* A tool window has a smaller Close button */
970 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
972 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
973 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
974 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
976 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
977 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
978 rect.bottom = rect.top + iBmpHeight;
979 rect.right = rect.left + iBmpWidth;
981 else
983 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
984 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
985 rect.top += 2;
986 rect.right -= 2;
988 DrawFrameControl( hdc, &rect, DFC_CAPTION,
989 (DFCS_CAPTIONCLOSE |
990 (down ? DFCS_PUSHED : 0) |
991 (bGrayed ? DFCS_INACTIVE : 0)) );
994 /******************************************************************************
995 * NC_DrawMaxButton95
997 * Draws the maximize button for Win95 style windows.
998 * If bGrayed is true, then draw a disabled Maximize button
1000 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1002 RECT rect;
1003 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1005 NC_GetInsideRect( hwnd, &rect );
1006 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1007 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1008 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1009 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1010 rect.top += 2;
1011 rect.right -= 2;
1012 if (down) flags |= DFCS_PUSHED;
1013 if (bGrayed) flags |= DFCS_INACTIVE;
1014 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1017 /******************************************************************************
1018 * NC_DrawMinButton95
1020 * Draws the minimize button for Win95 style windows.
1021 * If bGrayed is true, then draw a disabled Minimize button
1023 static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1025 RECT rect;
1026 UINT flags = DFCS_CAPTIONMIN;
1027 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1029 NC_GetInsideRect( hwnd, &rect );
1030 if (style & WS_SYSMENU)
1031 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1032 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1033 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1034 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1035 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1036 rect.top += 2;
1037 rect.right -= 2;
1038 if (down) flags |= DFCS_PUSHED;
1039 if (bGrayed) flags |= DFCS_INACTIVE;
1040 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1043 /***********************************************************************
1044 * NC_DrawFrame
1046 * Draw a window frame inside the given rectangle, and update the rectangle.
1047 * The correct pen for the frame must be selected in the DC.
1049 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1050 BOOL active )
1052 INT width, height;
1054 if (TWEAK_WineLook != WIN31_LOOK)
1055 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1057 if (dlgFrame)
1059 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1060 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1061 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1062 COLOR_INACTIVECAPTION) );
1064 else
1066 width = GetSystemMetrics(SM_CXFRAME) - 2;
1067 height = GetSystemMetrics(SM_CYFRAME) - 2;
1068 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1069 COLOR_INACTIVEBORDER) );
1072 /* Draw frame */
1073 PatBlt( hdc, rect->left, rect->top,
1074 rect->right - rect->left, height, PATCOPY );
1075 PatBlt( hdc, rect->left, rect->top,
1076 width, rect->bottom - rect->top, PATCOPY );
1077 PatBlt( hdc, rect->left, rect->bottom - 1,
1078 rect->right - rect->left, -height, PATCOPY );
1079 PatBlt( hdc, rect->right - 1, rect->top,
1080 -width, rect->bottom - rect->top, PATCOPY );
1082 if (dlgFrame)
1084 InflateRect( rect, -width, -height );
1086 else
1088 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1089 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1091 /* Draw inner rectangle */
1093 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1094 Rectangle( hdc, rect->left + width, rect->top + height,
1095 rect->right - width , rect->bottom - height );
1097 /* Draw the decorations */
1099 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1100 LineTo( hdc, rect->left + width, rect->top + decYOff );
1101 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1102 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1103 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1104 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1105 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1106 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1108 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1109 LineTo( hdc, rect->left + decXOff, rect->top + height);
1110 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1111 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1112 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1113 LineTo( hdc, rect->right - decXOff, rect->top + height );
1114 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1115 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1117 InflateRect( rect, -width - 1, -height - 1 );
1122 /******************************************************************************
1124 * void NC_DrawFrame95(
1125 * HDC hdc,
1126 * RECT *rect,
1127 * BOOL active,
1128 * DWORD style,
1129 * DWORD exStyle )
1131 * Draw a window frame inside the given rectangle, and update the rectangle.
1133 * Bugs
1134 * Many. First, just what IS a frame in Win95? Note that the 3D look
1135 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1136 * edge. The inner rectangle just inside the frame is handled by the
1137 * Caption code.
1139 * In short, for most people, this function should be a nop (unless
1140 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1141 * them lately, but just to get this code right). Even so, it doesn't
1142 * appear to be so. It's being worked on...
1144 * Revision history
1145 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1146 * Original implementation (based on NC_DrawFrame)
1147 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1148 * Some minor fixes.
1149 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1150 * Fixed a fix or something.
1152 *****************************************************************************/
1154 static void NC_DrawFrame95(
1155 HDC hdc,
1156 RECT *rect,
1157 BOOL active,
1158 DWORD style,
1159 DWORD exStyle)
1161 INT width, height;
1163 /* Firstly the "thick" frame */
1164 if (style & WS_THICKFRAME)
1166 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1167 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1169 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1170 COLOR_INACTIVEBORDER) );
1171 /* Draw frame */
1172 PatBlt( hdc, rect->left, rect->top,
1173 rect->right - rect->left, height, PATCOPY );
1174 PatBlt( hdc, rect->left, rect->top,
1175 width, rect->bottom - rect->top, PATCOPY );
1176 PatBlt( hdc, rect->left, rect->bottom - 1,
1177 rect->right - rect->left, -height, PATCOPY );
1178 PatBlt( hdc, rect->right - 1, rect->top,
1179 -width, rect->bottom - rect->top, PATCOPY );
1181 InflateRect( rect, -width, -height );
1184 /* Now the other bit of the frame */
1185 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1186 (exStyle & WS_EX_DLGMODALFRAME))
1188 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1189 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1190 /* This should give a value of 1 that should also work for a border */
1192 SelectObject( hdc, GetSysColorBrush(
1193 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1194 COLOR_3DFACE :
1195 (exStyle & WS_EX_STATICEDGE) ?
1196 COLOR_WINDOWFRAME :
1197 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1198 COLOR_3DFACE :
1199 /* else */
1200 COLOR_WINDOWFRAME));
1202 /* Draw frame */
1203 PatBlt( hdc, rect->left, rect->top,
1204 rect->right - rect->left, height, PATCOPY );
1205 PatBlt( hdc, rect->left, rect->top,
1206 width, rect->bottom - rect->top, PATCOPY );
1207 PatBlt( hdc, rect->left, rect->bottom - 1,
1208 rect->right - rect->left, -height, PATCOPY );
1209 PatBlt( hdc, rect->right - 1, rect->top,
1210 -width, rect->bottom - rect->top, PATCOPY );
1212 InflateRect( rect, -width, -height );
1217 /***********************************************************************
1218 * NC_DrawCaption
1220 * Draw the window caption.
1221 * The correct pen for the window frame must be selected in the DC.
1223 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1224 DWORD style, BOOL active )
1226 RECT r = *rect;
1227 char buffer[256];
1229 if (!hbitmapClose)
1231 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1234 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1236 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1237 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1238 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1239 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1240 r.left++;
1241 r.right--;
1242 SelectObject( hdc, hbrushOld );
1244 MoveToEx( hdc, r.left, r.bottom, NULL );
1245 LineTo( hdc, r.right, r.bottom );
1247 if (style & WS_SYSMENU)
1249 NC_DrawSysButton( hwnd, hdc, FALSE );
1250 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1251 MoveToEx( hdc, r.left - 1, r.top, NULL );
1252 LineTo( hdc, r.left - 1, r.bottom );
1254 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1255 if (style & WS_MAXIMIZEBOX)
1257 NC_DrawMaxButton( hwnd, hdc, FALSE );
1258 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1260 if (style & WS_MINIMIZEBOX)
1262 NC_DrawMinButton( hwnd, hdc, FALSE );
1263 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1266 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1268 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1269 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1270 SetBkMode( hdc, TRANSPARENT );
1271 DrawTextA( hdc, buffer, -1, &r,
1272 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1277 /******************************************************************************
1279 * NC_DrawCaption95(
1280 * HDC hdc,
1281 * RECT *rect,
1282 * HWND hwnd,
1283 * DWORD style,
1284 * BOOL active )
1286 * Draw the window caption for Win95 style windows.
1287 * The correct pen for the window frame must be selected in the DC.
1289 * Bugs
1290 * Hey, a function that finally works! Well, almost.
1291 * It's being worked on.
1293 * Revision history
1294 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1295 * Original implementation.
1296 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1297 * Some minor fixes.
1299 *****************************************************************************/
1301 static void NC_DrawCaption95(
1302 HDC hdc,
1303 RECT *rect,
1304 HWND hwnd,
1305 DWORD style,
1306 DWORD exStyle,
1307 BOOL active )
1309 RECT r = *rect;
1310 char buffer[256];
1311 HPEN hPrevPen;
1312 HMENU hSysMenu;
1314 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
1315 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1316 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1317 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1318 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1319 LineTo( hdc, r.right, r.bottom - 1 );
1320 SelectObject( hdc, hPrevPen );
1321 r.bottom--;
1323 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1324 COLOR_INACTIVECAPTION) );
1326 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1327 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1328 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1331 if (style & WS_SYSMENU)
1333 UINT state;
1335 /* Go get the sysmenu */
1336 hSysMenu = GetSystemMenu(hwnd, FALSE);
1337 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1339 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1340 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1341 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1342 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1344 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1346 /* In win95 the two buttons are always there */
1347 /* But if the menu item is not in the menu they're disabled*/
1349 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1350 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1352 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1353 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1357 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1358 NONCLIENTMETRICSA nclm;
1359 HFONT hFont, hOldFont;
1360 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1361 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1362 if (exStyle & WS_EX_TOOLWINDOW)
1363 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1364 else
1365 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1366 hOldFont = SelectObject (hdc, hFont);
1367 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1368 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1369 SetBkMode( hdc, TRANSPARENT );
1370 r.left += 2;
1371 DrawTextA( hdc, buffer, -1, &r,
1372 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1373 DeleteObject (SelectObject (hdc, hOldFont));
1379 /***********************************************************************
1380 * NC_DoNCPaint
1382 * Paint the non-client area. clip is currently unused.
1384 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1386 HDC hdc;
1387 RECT rect;
1388 BOOL active;
1389 WND *wndPtr;
1390 DWORD dwStyle, dwExStyle;
1391 WORD flags;
1392 RECT rectClient, rectWindow;
1393 int has_menu;
1395 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1396 has_menu = HAS_MENU(wndPtr);
1397 dwStyle = wndPtr->dwStyle;
1398 dwExStyle = wndPtr->dwExStyle;
1399 flags = wndPtr->flags;
1400 rectClient = wndPtr->rectClient;
1401 rectWindow = wndPtr->rectWindow;
1402 WIN_ReleasePtr( wndPtr );
1404 if ( dwStyle & WS_MINIMIZE ||
1405 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1407 active = flags & WIN_NCACTIVATED;
1409 TRACE("%p %d\n", hwnd, active );
1411 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1412 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1414 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1415 rectClient.top-rectWindow.top,
1416 rectClient.right-rectWindow.left,
1417 rectClient.bottom-rectWindow.top )
1418 == NULLREGION)
1420 ReleaseDC( hwnd, hdc );
1421 return;
1424 rect.top = rect.left = 0;
1425 rect.right = rectWindow.right - rectWindow.left;
1426 rect.bottom = rectWindow.bottom - rectWindow.top;
1428 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1430 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1432 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1433 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1434 InflateRect( &rect, -1, -1 );
1437 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1438 NC_DrawFrame(hdc, &rect, FALSE, active );
1439 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1440 NC_DrawFrame( hdc, &rect, TRUE, active );
1442 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1444 RECT r = rect;
1445 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1446 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1447 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1450 if (has_menu)
1452 RECT r = rect;
1453 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1454 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1457 /* Draw the scroll-bars */
1459 if (dwStyle & WS_VSCROLL)
1460 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1461 if (dwStyle & WS_HSCROLL)
1462 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1464 /* Draw the "size-box" */
1466 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1468 RECT r = rect;
1469 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1470 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1471 if(wndPtr->dwStyle & WS_BORDER) {
1472 r.left++;
1473 r.top++;
1475 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1478 ReleaseDC( hwnd, hdc );
1482 /******************************************************************************
1484 * void NC_DoNCPaint95(
1485 * HWND hwnd,
1486 * HRGN clip,
1487 * BOOL suppress_menupaint )
1489 * Paint the non-client area for Win95 windows. The clip region is
1490 * currently ignored.
1492 * Bugs
1493 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1494 * misc/tweak.c controls/menu.c # :-)
1496 * Revision history
1497 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1498 * Original implementation
1499 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1500 * Fixed some bugs.
1501 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1502 * Streamlined window style checks.
1504 *****************************************************************************/
1506 static void NC_DoNCPaint95(
1507 HWND hwnd,
1508 HRGN clip,
1509 BOOL suppress_menupaint )
1511 HDC hdc;
1512 RECT rfuzz, rect, rectClip;
1513 BOOL active;
1514 WND *wndPtr;
1515 DWORD dwStyle, dwExStyle;
1516 WORD flags;
1517 RECT rectClient, rectWindow;
1518 int has_menu;
1520 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1521 has_menu = HAS_MENU(wndPtr);
1522 dwStyle = wndPtr->dwStyle;
1523 dwExStyle = wndPtr->dwExStyle;
1524 flags = wndPtr->flags;
1525 rectClient = wndPtr->rectClient;
1526 rectWindow = wndPtr->rectWindow;
1527 WIN_ReleasePtr( wndPtr );
1529 if ( dwStyle & WS_MINIMIZE ||
1530 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1532 active = flags & WIN_NCACTIVATED;
1534 TRACE("%p %d\n", hwnd, active );
1536 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1537 the call to GetDCEx implying that it is allowed not to use it either.
1538 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1539 will cause clipRgn to be deleted after ReleaseDC().
1540 Now, how is the "system" supposed to tell what happened?
1543 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1544 ((clip > (HRGN)1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1547 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1548 rectClient.top-rectWindow.top,
1549 rectClient.right-rectWindow.left,
1550 rectClient.bottom-rectWindow.top )
1551 == NULLREGION)
1553 ReleaseDC( hwnd, hdc );
1554 return;
1557 rect.top = rect.left = 0;
1558 rect.right = rectWindow.right - rectWindow.left;
1559 rect.bottom = rectWindow.bottom - rectWindow.top;
1561 if( clip > (HRGN)1 )
1562 GetRgnBox( clip, &rectClip );
1563 else
1565 clip = 0;
1566 rectClip = rect;
1569 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1571 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1572 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1574 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1575 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1578 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1580 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1582 RECT r = rect;
1583 if (dwExStyle & WS_EX_TOOLWINDOW) {
1584 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1585 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1587 else {
1588 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1589 rect.top += GetSystemMetrics(SM_CYCAPTION);
1591 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1592 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1593 dwExStyle, active);
1596 if (has_menu)
1598 RECT r = rect;
1599 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1601 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1602 r.left, r.top, r.right, r.bottom);
1604 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1607 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1608 rect.left, rect.top, rect.right, rect.bottom );
1610 if (dwExStyle & WS_EX_CLIENTEDGE)
1611 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1613 /* Draw the scroll-bars */
1615 if (dwStyle & WS_VSCROLL)
1616 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1617 if (dwStyle & WS_HSCROLL)
1618 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1620 /* Draw the "size-box" */
1621 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1623 RECT r = rect;
1624 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1625 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1626 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1629 ReleaseDC( hwnd, hdc );
1635 /***********************************************************************
1636 * NC_HandleNCPaint
1638 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1640 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1642 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1644 if( dwStyle & WS_VISIBLE )
1646 if( dwStyle & WS_MINIMIZE )
1647 WINPOS_RedrawIconTitle( hwnd );
1648 else if (TWEAK_WineLook == WIN31_LOOK)
1649 NC_DoNCPaint( hwnd, clip, FALSE );
1650 else
1651 NC_DoNCPaint95( hwnd, clip, FALSE );
1653 return 0;
1657 /***********************************************************************
1658 * NC_HandleNCActivate
1660 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1662 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1664 WND* wndPtr = WIN_FindWndPtr( hwnd );
1666 /* Lotus Notes draws menu descriptions in the caption of its main
1667 * window. When it wants to restore original "system" view, it just
1668 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1669 * attempt to minimize redrawings lead to a not restored caption.
1671 if (wndPtr)
1673 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1674 else wndPtr->flags &= ~WIN_NCACTIVATED;
1675 WIN_ReleaseWndPtr(wndPtr);
1677 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1678 else if (TWEAK_WineLook == WIN31_LOOK)
1679 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1680 else
1681 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1683 return TRUE;
1687 /***********************************************************************
1688 * NC_HandleSetCursor
1690 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1692 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1694 hwnd = WIN_GetFullHandle( (HWND)wParam );
1696 switch(LOWORD(lParam))
1698 case HTERROR:
1700 WORD msg = HIWORD( lParam );
1701 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1702 (msg == WM_RBUTTONDOWN))
1703 MessageBeep(0);
1705 break;
1707 case HTCLIENT:
1709 HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
1710 if(hCursor) {
1711 SetCursor(hCursor);
1712 return TRUE;
1714 return FALSE;
1717 case HTLEFT:
1718 case HTRIGHT:
1719 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1721 case HTTOP:
1722 case HTBOTTOM:
1723 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1725 case HTTOPLEFT:
1726 case HTBOTTOMRIGHT:
1727 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1729 case HTTOPRIGHT:
1730 case HTBOTTOMLEFT:
1731 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1734 /* Default cursor: arrow */
1735 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1738 /***********************************************************************
1739 * NC_GetSysPopupPos
1741 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1743 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1744 else
1746 WND *wndPtr = WIN_FindWndPtr( hwnd );
1747 if (!wndPtr) return;
1749 NC_GetInsideRect( hwnd, rect );
1750 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1751 if (wndPtr->dwStyle & WS_CHILD)
1752 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1753 if (TWEAK_WineLook == WIN31_LOOK) {
1754 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1755 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1757 else {
1758 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1759 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1761 WIN_ReleaseWndPtr( wndPtr );
1765 /***********************************************************************
1766 * NC_TrackMinMaxBox95
1768 * Track a mouse button press on the minimize or maximize box.
1770 * The big difference between 3.1 and 95 is the disabled button state.
1771 * In win95 the system button can be disabled, so it can ignore the mouse
1772 * event.
1775 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1777 MSG msg;
1778 HDC hdc = GetWindowDC( hwnd );
1779 BOOL pressed = TRUE;
1780 UINT state;
1781 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1782 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1784 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1786 if (wParam == HTMINBUTTON)
1788 /* If the style is not present, do nothing */
1789 if (!(wndStyle & WS_MINIMIZEBOX))
1790 return;
1792 /* Check if the sysmenu item for minimize is there */
1793 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1795 paintButton = &NC_DrawMinButton95;
1797 else
1799 /* If the style is not present, do nothing */
1800 if (!(wndStyle & WS_MAXIMIZEBOX))
1801 return;
1803 /* Check if the sysmenu item for maximize is there */
1804 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1806 paintButton = &NC_DrawMaxButton95;
1809 SetCapture( hwnd );
1811 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1813 while(1)
1815 BOOL oldstate = pressed;
1817 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1818 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1820 if(msg.message == WM_LBUTTONUP)
1821 break;
1823 if(msg.message != WM_MOUSEMOVE)
1824 continue;
1826 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1827 if (pressed != oldstate)
1828 (*paintButton)( hwnd, hdc, pressed, FALSE);
1831 if(pressed)
1832 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1834 ReleaseCapture();
1835 ReleaseDC( hwnd, hdc );
1837 /* If the item minimize or maximize of the sysmenu are not there */
1838 /* or if the style is not present, do nothing */
1839 if ((!pressed) || (state == 0xFFFFFFFF))
1840 return;
1842 if (wParam == HTMINBUTTON)
1843 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1844 else
1845 SendMessageA( hwnd, WM_SYSCOMMAND,
1846 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1849 /***********************************************************************
1850 * NC_TrackMinMaxBox
1852 * Track a mouse button press on the minimize or maximize box.
1854 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1856 MSG msg;
1857 HDC hdc = GetWindowDC( hwnd );
1858 BOOL pressed = TRUE;
1859 void (*paintButton)(HWND, HDC, BOOL);
1861 SetCapture( hwnd );
1863 if (wParam == HTMINBUTTON)
1864 paintButton = &NC_DrawMinButton;
1865 else
1866 paintButton = &NC_DrawMaxButton;
1868 (*paintButton)( hwnd, hdc, TRUE);
1870 while(1)
1872 BOOL oldstate = pressed;
1874 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1875 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1877 if(msg.message == WM_LBUTTONUP)
1878 break;
1880 if(msg.message != WM_MOUSEMOVE)
1881 continue;
1883 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1884 if (pressed != oldstate)
1885 (*paintButton)( hwnd, hdc, pressed);
1888 if(pressed)
1889 (*paintButton)( hwnd, hdc, FALSE);
1891 ReleaseCapture();
1892 ReleaseDC( hwnd, hdc );
1894 if (!pressed) return;
1896 if (wParam == HTMINBUTTON)
1897 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1898 else
1899 SendMessageA( hwnd, WM_SYSCOMMAND,
1900 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1904 /***********************************************************************
1905 * NC_TrackCloseButton95
1907 * Track a mouse button press on the Win95 close button.
1909 static void
1910 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1912 MSG msg;
1913 HDC hdc;
1914 BOOL pressed = TRUE;
1915 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1916 UINT state;
1918 if(hSysMenu == 0)
1919 return;
1921 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1923 /* If the item close of the sysmenu is disabled or not there do nothing */
1924 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1925 return;
1927 hdc = GetWindowDC( hwnd );
1929 SetCapture( hwnd );
1931 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1933 while(1)
1935 BOOL oldstate = pressed;
1937 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1938 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1940 if(msg.message == WM_LBUTTONUP)
1941 break;
1943 if(msg.message != WM_MOUSEMOVE)
1944 continue;
1946 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1947 if (pressed != oldstate)
1948 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1951 if(pressed)
1952 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1954 ReleaseCapture();
1955 ReleaseDC( hwnd, hdc );
1956 if (!pressed) return;
1958 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1962 /***********************************************************************
1963 * NC_TrackScrollBar
1965 * Track a mouse button press on the horizontal or vertical scroll-bar.
1967 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1969 INT scrollbar;
1971 if ((wParam & 0xfff0) == SC_HSCROLL)
1973 if ((wParam & 0x0f) != HTHSCROLL) return;
1974 scrollbar = SB_HORZ;
1976 else /* SC_VSCROLL */
1978 if ((wParam & 0x0f) != HTVSCROLL) return;
1979 scrollbar = SB_VERT;
1981 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1985 /***********************************************************************
1986 * NC_HandleNCLButtonDown
1988 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1990 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1992 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1994 switch(wParam) /* Hit test */
1996 case HTCAPTION:
1998 HWND top = GetAncestor( hwnd, GA_ROOT );
2000 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
2001 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2002 break;
2005 case HTSYSMENU:
2006 if( style & WS_SYSMENU )
2008 if( !(style & WS_MINIMIZE) )
2010 HDC hDC = GetWindowDC(hwnd);
2011 if (TWEAK_WineLook == WIN31_LOOK)
2012 NC_DrawSysButton( hwnd, hDC, TRUE );
2013 else
2014 NC_DrawSysButton95( hwnd, hDC, TRUE );
2015 ReleaseDC( hwnd, hDC );
2017 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2019 break;
2021 case HTMENU:
2022 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2023 break;
2025 case HTHSCROLL:
2026 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2027 break;
2029 case HTVSCROLL:
2030 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2031 break;
2033 case HTMINBUTTON:
2034 case HTMAXBUTTON:
2035 if (TWEAK_WineLook == WIN31_LOOK)
2036 NC_TrackMinMaxBox( hwnd, wParam );
2037 else
2038 NC_TrackMinMaxBox95( hwnd, wParam );
2039 break;
2041 case HTCLOSE:
2042 if (TWEAK_WineLook >= WIN95_LOOK)
2043 NC_TrackCloseButton95 (hwnd, wParam);
2044 break;
2046 case HTLEFT:
2047 case HTRIGHT:
2048 case HTTOP:
2049 case HTTOPLEFT:
2050 case HTTOPRIGHT:
2051 case HTBOTTOM:
2052 case HTBOTTOMLEFT:
2053 case HTBOTTOMRIGHT:
2054 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2055 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2056 break;
2058 case HTBORDER:
2059 break;
2061 return 0;
2065 /***********************************************************************
2066 * NC_HandleNCLButtonDblClk
2068 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2070 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2073 * if this is an icon, send a restore since we are handling
2074 * a double click
2076 if (IsIconic(hwnd))
2078 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2079 return 0;
2082 switch(wParam) /* Hit test */
2084 case HTCAPTION:
2085 /* stop processing if WS_MAXIMIZEBOX is missing */
2086 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2087 SendMessageW( hwnd, WM_SYSCOMMAND,
2088 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2089 break;
2091 case HTSYSMENU:
2092 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2093 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2094 break;
2096 case HTHSCROLL:
2097 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2098 break;
2100 case HTVSCROLL:
2101 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2102 break;
2104 return 0;
2108 /***********************************************************************
2109 * NC_HandleSysCommand
2111 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2113 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2115 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2117 switch (wParam & 0xfff0)
2119 case SC_SIZE:
2120 case SC_MOVE:
2121 if (USER_Driver.pSysCommandSizeMove)
2122 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2123 break;
2125 case SC_MINIMIZE:
2126 if (hwnd == GetForegroundWindow())
2127 ShowOwnedPopups(hwnd,FALSE);
2128 ShowWindow( hwnd, SW_MINIMIZE );
2129 break;
2131 case SC_MAXIMIZE:
2132 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2133 ShowOwnedPopups(hwnd,TRUE);
2134 ShowWindow( hwnd, SW_MAXIMIZE );
2135 break;
2137 case SC_RESTORE:
2138 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2139 ShowOwnedPopups(hwnd,TRUE);
2140 ShowWindow( hwnd, SW_RESTORE );
2141 break;
2143 case SC_CLOSE:
2144 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2146 case SC_VSCROLL:
2147 case SC_HSCROLL:
2149 POINT pt;
2150 pt.x = SLOWORD(lParam);
2151 pt.y = SHIWORD(lParam);
2152 NC_TrackScrollBar( hwnd, wParam, pt );
2154 break;
2156 case SC_MOUSEMENU:
2158 POINT pt;
2159 pt.x = SLOWORD(lParam);
2160 pt.y = SHIWORD(lParam);
2161 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2163 break;
2165 case SC_KEYMENU:
2166 MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2167 break;
2169 case SC_TASKLIST:
2170 WinExec( "taskman.exe", SW_SHOWNORMAL );
2171 break;
2173 case SC_SCREENSAVE:
2174 if (wParam == SC_ABOUTWINE)
2176 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2177 if (hmodule)
2179 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2180 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
2181 FreeLibrary( hmodule );
2184 else
2185 if (wParam == SC_PUTMARK)
2186 TRACE_(shell)("Mark requested by user\n");
2187 break;
2189 case SC_HOTKEY:
2190 case SC_ARRANGE:
2191 case SC_NEXTWINDOW:
2192 case SC_PREVWINDOW:
2193 FIXME("unimplemented!\n");
2194 break;
2196 return 0;
2199 /*************************************************************
2200 * NC_DrawGrayButton
2202 * Stub for the grayed button of the caption
2204 *************************************************************/
2206 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2208 HBITMAP hMaskBmp;
2209 HDC hdcMask;
2210 HBRUSH hOldBrush;
2212 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2214 if(hMaskBmp == 0)
2215 return FALSE;
2217 hdcMask = CreateCompatibleDC (0);
2218 SelectObject (hdcMask, hMaskBmp);
2220 /* Draw the grayed bitmap using the mask */
2221 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
2222 BitBlt (hdc, x, y, 12, 10,
2223 hdcMask, 0, 0, 0xB8074A);
2225 /* Clean up */
2226 SelectObject (hdc, hOldBrush);
2227 DeleteObject(hMaskBmp);
2228 DeleteDC (hdcMask);
2230 return TRUE;