Release 20030408.
[wine/gsoc-2012-control.git] / windows / nonclient.c
blob354e0eb30fbc19f2e74b3b86b071dd454d791efe
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)
229 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
230 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
231 else
232 rect->right += GetSystemMetrics(SM_CXVSCROLL);
234 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
239 static HICON NC_IconForWindow( HWND hwnd )
241 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
242 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
244 /* If there is no hIcon specified and this is a modal dialog,
245 * get the default one.
247 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
248 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
249 return hIcon;
252 /***********************************************************************
253 * DrawCaption (USER32.@) Draws a caption bar
255 * PARAMS
256 * hwnd [I]
257 * hdc [I]
258 * lpRect [I]
259 * uFlags [I]
261 * RETURNS
262 * Success:
263 * Failure:
266 BOOL WINAPI
267 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
269 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
273 /***********************************************************************
274 * DrawCaptionTempA (USER32.@)
276 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
277 HICON hIcon, LPCSTR str, UINT uFlags)
279 LPWSTR strW;
280 INT len;
281 BOOL ret = FALSE;
283 if (!(uFlags & DC_TEXT) || !str)
284 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
286 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
287 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
289 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
290 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
291 HeapFree( GetProcessHeap (), 0, strW );
293 return ret;
297 /***********************************************************************
298 * DrawCaptionTempW (USER32.@)
300 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
301 HICON hIcon, LPCWSTR str, UINT uFlags)
303 RECT rc = *rect;
305 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
306 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
308 /* drawing background */
309 if (uFlags & DC_INBUTTON) {
310 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
312 if (uFlags & DC_ACTIVE) {
313 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
314 PatBlt (hdc, rc.left, rc.top,
315 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
316 SelectObject (hdc, hbr);
319 else {
320 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
321 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
325 /* drawing icon */
326 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
327 POINT pt;
329 pt.x = rc.left + 2;
330 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
332 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
333 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
334 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
335 rc.left += (rc.bottom - rc.top);
338 /* drawing text */
339 if (uFlags & DC_TEXT) {
340 HFONT hOldFont;
342 if (uFlags & DC_INBUTTON)
343 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
344 else if (uFlags & DC_ACTIVE)
345 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
346 else
347 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
349 SetBkMode (hdc, TRANSPARENT);
351 if (hFont)
352 hOldFont = SelectObject (hdc, hFont);
353 else {
354 NONCLIENTMETRICSW nclm;
355 HFONT hNewFont;
356 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
357 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
358 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
359 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
360 hOldFont = SelectObject (hdc, hNewFont);
363 if (str)
364 DrawTextW (hdc, str, -1, &rc,
365 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
366 else {
367 WCHAR szText[128];
368 INT nLen;
369 nLen = GetWindowTextW (hwnd, szText, 128);
370 DrawTextW (hdc, szText, nLen, &rc,
371 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
374 if (hFont)
375 SelectObject (hdc, hOldFont);
376 else
377 DeleteObject (SelectObject (hdc, hOldFont));
380 /* drawing focus ??? */
381 if (uFlags & 0x2000)
382 FIXME("undocumented flag (0x2000)!\n");
384 return 0;
388 /***********************************************************************
389 * AdjustWindowRect (USER.102)
391 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
393 return AdjustWindowRectEx16( rect, style, menu, 0 );
397 /***********************************************************************
398 * AdjustWindowRect (USER32.@)
400 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
402 return AdjustWindowRectEx( rect, style, menu, 0 );
406 /***********************************************************************
407 * AdjustWindowRectEx (USER.454)
409 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
410 BOOL16 menu, DWORD exStyle )
412 RECT rect32;
413 BOOL ret;
415 CONV_RECT16TO32( rect, &rect32 );
416 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
417 CONV_RECT32TO16( &rect32, rect );
418 return ret;
422 /***********************************************************************
423 * AdjustWindowRectEx (USER32.@)
425 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
427 /* Correct the window style */
428 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
429 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
430 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
431 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
433 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
434 rect->left, rect->top, rect->right, rect->bottom,
435 style, menu, exStyle );
437 if (TWEAK_WineLook == WIN31_LOOK)
438 NC_AdjustRect( rect, style, menu, exStyle );
439 else
441 NC_AdjustRectOuter95( rect, style, menu, exStyle );
442 NC_AdjustRectInner95( rect, style, exStyle );
444 return TRUE;
448 /***********************************************************************
449 * NC_HandleNCCalcSize
451 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
453 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
455 RECT tmpRect = { 0, 0, 0, 0 };
456 LONG result = 0;
457 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
458 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
459 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
461 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
462 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
464 if (!IsIconic(hwnd))
466 if (TWEAK_WineLook == WIN31_LOOK)
467 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
468 else
469 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
471 winRect->left -= tmpRect.left;
472 winRect->top -= tmpRect.top;
473 winRect->right -= tmpRect.right;
474 winRect->bottom -= tmpRect.bottom;
476 if (!(style & WS_CHILD) && GetMenu(hwnd))
478 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
479 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
481 winRect->top +=
482 MENU_GetMenuBarHeight( hwnd,
483 winRect->right - winRect->left,
484 -tmpRect.left, -tmpRect.top ) + 1;
487 if (TWEAK_WineLook > WIN31_LOOK) {
488 SetRect(&tmpRect, 0, 0, 0, 0);
489 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
490 winRect->left -= tmpRect.left;
491 winRect->top -= tmpRect.top;
492 winRect->right -= tmpRect.right;
493 winRect->bottom -= tmpRect.bottom;
496 if (winRect->top > winRect->bottom)
497 winRect->bottom = winRect->top;
499 if (winRect->left > winRect->right)
500 winRect->right = winRect->left;
502 return result;
506 /***********************************************************************
507 * NC_GetInsideRect
509 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
510 * but without the borders (if any).
511 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
513 void NC_GetInsideRect( HWND hwnd, RECT *rect )
515 WND * wndPtr = WIN_FindWndPtr( hwnd );
517 rect->top = rect->left = 0;
518 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
519 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
521 if (wndPtr->dwStyle & WS_ICONIC) goto END;
523 /* Remove frame from rectangle */
524 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
526 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
528 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
530 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
531 /* FIXME: this isn't in NC_AdjustRect? why not? */
532 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
533 InflateRect( rect, -1, 0 );
535 else if (HAS_THINFRAME( wndPtr->dwStyle ))
537 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
540 /* We have additional border information if the window
541 * is a child (but not an MDI child) */
542 if (TWEAK_WineLook != WIN31_LOOK)
544 if ( (wndPtr->dwStyle & WS_CHILD) &&
545 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
547 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
548 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
549 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
550 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
554 END:
555 WIN_ReleaseWndPtr(wndPtr);
556 return;
560 /***********************************************************************
561 * NC_DoNCHitTest
563 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
566 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
568 RECT rect;
570 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
572 GetWindowRect(wndPtr->hwndSelf, &rect );
573 if (!PtInRect( &rect, pt )) return HTNOWHERE;
575 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
577 /* Check borders */
578 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
580 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
581 if (!PtInRect( &rect, pt ))
583 /* Check top sizing border */
584 if (pt.y < rect.top)
586 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
587 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
588 return HTTOP;
590 /* Check bottom sizing border */
591 if (pt.y >= rect.bottom)
593 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
594 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
595 return HTBOTTOM;
597 /* Check left sizing border */
598 if (pt.x < rect.left)
600 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
601 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
602 return HTLEFT;
604 /* Check right sizing border */
605 if (pt.x >= rect.right)
607 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
608 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
609 return HTRIGHT;
613 else /* No thick frame */
615 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
616 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
617 else if (HAS_THINFRAME( wndPtr->dwStyle ))
618 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
619 if (!PtInRect( &rect, pt )) return HTBORDER;
622 /* Check caption */
624 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
626 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
627 if (!PtInRect( &rect, pt ))
629 /* Check system menu */
630 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
631 rect.left += GetSystemMetrics(SM_CXSIZE);
632 if (pt.x <= rect.left) return HTSYSMENU;
634 /* Check maximize box */
635 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
636 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
638 if (pt.x >= rect.right) return HTMAXBUTTON;
639 /* Check minimize box */
640 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
641 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
642 if (pt.x >= rect.right) return HTMINBUTTON;
643 return HTCAPTION;
647 /* Check client area */
649 ScreenToClient( wndPtr->hwndSelf, &pt );
650 GetClientRect( wndPtr->hwndSelf, &rect );
651 if (PtInRect( &rect, pt )) return HTCLIENT;
653 /* Check vertical scroll bar */
655 if (wndPtr->dwStyle & WS_VSCROLL)
657 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
658 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
659 else
660 rect.right += GetSystemMetrics(SM_CXVSCROLL);
661 if (PtInRect( &rect, pt )) return HTVSCROLL;
664 /* Check horizontal scroll bar */
666 if (wndPtr->dwStyle & WS_HSCROLL)
668 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
669 if (PtInRect( &rect, pt ))
671 /* Check size box */
672 if ((wndPtr->dwStyle & WS_VSCROLL) &&
673 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
674 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
675 return HTSIZE;
676 return HTHSCROLL;
680 /* Check menu bar */
682 if (HAS_MENU(wndPtr))
684 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
685 return HTMENU;
688 /* Has to return HTNOWHERE if nothing was found
689 Could happen when a window has a customized non client area */
690 return HTNOWHERE;
694 /***********************************************************************
695 * NC_DoNCHitTest95
697 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
699 * FIXME: Just a modified copy of the Win 3.1 version.
702 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
704 RECT rect;
706 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
708 GetWindowRect(wndPtr->hwndSelf, &rect );
709 if (!PtInRect( &rect, pt )) return HTNOWHERE;
711 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
713 /* Check borders */
714 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
716 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
717 if (!PtInRect( &rect, pt ))
719 /* Check top sizing border */
720 if (pt.y < rect.top)
722 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
723 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
724 return HTTOP;
726 /* Check bottom sizing border */
727 if (pt.y >= rect.bottom)
729 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
730 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
731 return HTBOTTOM;
733 /* Check left sizing border */
734 if (pt.x < rect.left)
736 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
737 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
738 return HTLEFT;
740 /* Check right sizing border */
741 if (pt.x >= rect.right)
743 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
744 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
745 return HTRIGHT;
749 else /* No thick frame */
751 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
752 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
753 else if (HAS_THINFRAME( wndPtr->dwStyle ))
754 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
755 if (!PtInRect( &rect, pt )) return HTBORDER;
758 /* Check caption */
760 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
762 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
763 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
764 else
765 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
766 if (!PtInRect( &rect, pt ))
768 /* Check system menu */
769 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
771 if (NC_IconForWindow(wndPtr->hwndSelf))
772 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
774 if (pt.x < rect.left) return HTSYSMENU;
776 /* Check close button */
777 if (wndPtr->dwStyle & WS_SYSMENU)
778 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
779 if (pt.x > rect.right) return HTCLOSE;
781 /* Check maximize box */
782 /* In win95 there is automatically a Maximize button when there is a minimize one*/
783 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
784 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
785 if (pt.x > rect.right) return HTMAXBUTTON;
787 /* Check minimize box */
788 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
789 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
790 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
792 if (pt.x > rect.right) return HTMINBUTTON;
793 return HTCAPTION;
797 /* Check client area */
799 ScreenToClient( wndPtr->hwndSelf, &pt );
800 GetClientRect( wndPtr->hwndSelf, &rect );
801 if (PtInRect( &rect, pt )) return HTCLIENT;
803 /* Check vertical scroll bar */
805 if (wndPtr->dwStyle & WS_VSCROLL)
807 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
808 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
809 else
810 rect.right += GetSystemMetrics(SM_CXVSCROLL);
811 if (PtInRect( &rect, pt )) return HTVSCROLL;
814 /* Check horizontal scroll bar */
816 if (wndPtr->dwStyle & WS_HSCROLL)
818 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
819 if (PtInRect( &rect, pt ))
821 /* Check size box */
822 if ((wndPtr->dwStyle & WS_VSCROLL) &&
823 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
824 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
825 return HTSIZE;
826 return HTHSCROLL;
830 /* Check menu bar */
832 if (HAS_MENU(wndPtr))
834 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
835 return HTMENU;
838 /* Has to return HTNOWHERE if nothing was found
839 Could happen when a window has a customized non client area */
840 return HTNOWHERE;
844 /***********************************************************************
845 * NC_HandleNCHitTest
847 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
849 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
851 LONG retvalue;
852 WND *wndPtr = WIN_FindWndPtr (hwnd);
854 if (!wndPtr)
855 return HTERROR;
857 if (TWEAK_WineLook == WIN31_LOOK)
858 retvalue = NC_DoNCHitTest (wndPtr, pt);
859 else
860 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
861 WIN_ReleaseWndPtr(wndPtr);
862 return retvalue;
866 /***********************************************************************
867 * NC_DrawSysButton
869 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
871 RECT rect;
872 HDC hdcMem;
873 HBITMAP hbitmap;
875 NC_GetInsideRect( hwnd, &rect );
876 hdcMem = CreateCompatibleDC( hdc );
877 hbitmap = SelectObject( hdcMem, hbitmapClose );
878 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
879 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
880 down ? NOTSRCCOPY : SRCCOPY );
881 SelectObject( hdcMem, hbitmap );
882 DeleteDC( hdcMem );
886 /***********************************************************************
887 * NC_DrawMaxButton
889 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
891 RECT rect;
892 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
894 NC_GetInsideRect( hwnd, &rect );
895 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
896 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
897 rect.top += 1;
898 rect.right -= 1;
899 if (down) flags |= DFCS_PUSHED;
900 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
904 /***********************************************************************
905 * NC_DrawMinButton
907 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
909 RECT rect;
910 UINT flags = DFCS_CAPTIONMIN;
911 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
913 NC_GetInsideRect( hwnd, &rect );
914 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
915 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
916 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
917 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
918 rect.top += 1;
919 rect.right -= 1;
920 if (down) flags |= DFCS_PUSHED;
921 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
925 /******************************************************************************
927 * void NC_DrawSysButton95(
928 * HWND hwnd,
929 * HDC hdc,
930 * BOOL down )
932 * Draws the Win95 system icon.
934 * Revision history
935 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
936 * Original implementation from NC_DrawSysButton source.
937 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
938 * Fixed most bugs.
940 *****************************************************************************/
942 BOOL
943 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
945 HICON hIcon = NC_IconForWindow( hwnd );
947 if (hIcon)
949 RECT rect;
950 NC_GetInsideRect( hwnd, &rect );
951 DrawIconEx (hdc, rect.left + 1, rect.top + 1, hIcon,
952 GetSystemMetrics(SM_CXSIZE) - 1,
953 GetSystemMetrics(SM_CYSIZE) - 1, 0, 0, DI_NORMAL);
955 return (hIcon != 0);
959 /******************************************************************************
961 * void NC_DrawCloseButton95(
962 * HWND hwnd,
963 * HDC hdc,
964 * BOOL down,
965 * BOOL bGrayed )
967 * Draws the Win95 close button.
969 * If bGrayed is true, then draw a disabled Close button
971 * Revision history
972 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
973 * Original implementation from NC_DrawSysButton95 source.
975 *****************************************************************************/
977 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
979 RECT rect;
981 NC_GetInsideRect( hwnd, &rect );
983 /* A tool window has a smaller Close button */
984 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
986 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
987 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
988 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
990 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
991 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
992 rect.bottom = rect.top + iBmpHeight;
993 rect.right = rect.left + iBmpWidth;
995 else
997 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
998 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
999 rect.top += 2;
1000 rect.right -= 2;
1002 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1003 (DFCS_CAPTIONCLOSE |
1004 (down ? DFCS_PUSHED : 0) |
1005 (bGrayed ? DFCS_INACTIVE : 0)) );
1008 /******************************************************************************
1009 * NC_DrawMaxButton95
1011 * Draws the maximize button for Win95 style windows.
1012 * If bGrayed is true, then draw a disabled Maximize button
1014 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1016 RECT rect;
1017 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1019 NC_GetInsideRect( hwnd, &rect );
1020 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1021 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1022 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1023 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1024 rect.top += 2;
1025 rect.right -= 2;
1026 if (down) flags |= DFCS_PUSHED;
1027 if (bGrayed) flags |= DFCS_INACTIVE;
1028 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1031 /******************************************************************************
1032 * NC_DrawMinButton95
1034 * Draws the minimize button for Win95 style windows.
1035 * If bGrayed is true, then draw a disabled Minimize button
1037 static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1039 RECT rect;
1040 UINT flags = DFCS_CAPTIONMIN;
1041 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1043 NC_GetInsideRect( hwnd, &rect );
1044 if (style & WS_SYSMENU)
1045 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1046 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1047 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1048 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1049 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1050 rect.top += 2;
1051 rect.right -= 2;
1052 if (down) flags |= DFCS_PUSHED;
1053 if (bGrayed) flags |= DFCS_INACTIVE;
1054 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1057 /***********************************************************************
1058 * NC_DrawFrame
1060 * Draw a window frame inside the given rectangle, and update the rectangle.
1061 * The correct pen for the frame must be selected in the DC.
1063 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1064 BOOL active )
1066 INT width, height;
1068 if (TWEAK_WineLook != WIN31_LOOK)
1069 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1071 if (dlgFrame)
1073 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1074 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1075 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1076 COLOR_INACTIVECAPTION) );
1078 else
1080 width = GetSystemMetrics(SM_CXFRAME) - 2;
1081 height = GetSystemMetrics(SM_CYFRAME) - 2;
1082 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1083 COLOR_INACTIVEBORDER) );
1086 /* Draw frame */
1087 PatBlt( hdc, rect->left, rect->top,
1088 rect->right - rect->left, height, PATCOPY );
1089 PatBlt( hdc, rect->left, rect->top,
1090 width, rect->bottom - rect->top, PATCOPY );
1091 PatBlt( hdc, rect->left, rect->bottom - 1,
1092 rect->right - rect->left, -height, PATCOPY );
1093 PatBlt( hdc, rect->right - 1, rect->top,
1094 -width, rect->bottom - rect->top, PATCOPY );
1096 if (dlgFrame)
1098 InflateRect( rect, -width, -height );
1100 else
1102 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1103 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1105 /* Draw inner rectangle */
1107 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1108 Rectangle( hdc, rect->left + width, rect->top + height,
1109 rect->right - width , rect->bottom - height );
1111 /* Draw the decorations */
1113 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1114 LineTo( hdc, rect->left + width, rect->top + decYOff );
1115 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1116 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1117 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1118 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1119 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1120 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1122 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1123 LineTo( hdc, rect->left + decXOff, rect->top + height);
1124 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1125 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1126 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1127 LineTo( hdc, rect->right - decXOff, rect->top + height );
1128 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1129 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1131 InflateRect( rect, -width - 1, -height - 1 );
1136 /******************************************************************************
1138 * void NC_DrawFrame95(
1139 * HDC hdc,
1140 * RECT *rect,
1141 * BOOL active,
1142 * DWORD style,
1143 * DWORD exStyle )
1145 * Draw a window frame inside the given rectangle, and update the rectangle.
1147 * Bugs
1148 * Many. First, just what IS a frame in Win95? Note that the 3D look
1149 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1150 * edge. The inner rectangle just inside the frame is handled by the
1151 * Caption code.
1153 * In short, for most people, this function should be a nop (unless
1154 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1155 * them lately, but just to get this code right). Even so, it doesn't
1156 * appear to be so. It's being worked on...
1158 * Revision history
1159 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1160 * Original implementation (based on NC_DrawFrame)
1161 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1162 * Some minor fixes.
1163 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1164 * Fixed a fix or something.
1166 *****************************************************************************/
1168 static void NC_DrawFrame95(
1169 HDC hdc,
1170 RECT *rect,
1171 BOOL active,
1172 DWORD style,
1173 DWORD exStyle)
1175 INT width, height;
1177 /* Firstly the "thick" frame */
1178 if (style & WS_THICKFRAME)
1180 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1181 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1183 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1184 COLOR_INACTIVEBORDER) );
1185 /* Draw frame */
1186 PatBlt( hdc, rect->left, rect->top,
1187 rect->right - rect->left, height, PATCOPY );
1188 PatBlt( hdc, rect->left, rect->top,
1189 width, rect->bottom - rect->top, PATCOPY );
1190 PatBlt( hdc, rect->left, rect->bottom - 1,
1191 rect->right - rect->left, -height, PATCOPY );
1192 PatBlt( hdc, rect->right - 1, rect->top,
1193 -width, rect->bottom - rect->top, PATCOPY );
1195 InflateRect( rect, -width, -height );
1198 /* Now the other bit of the frame */
1199 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1200 (exStyle & WS_EX_DLGMODALFRAME))
1202 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1203 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1204 /* This should give a value of 1 that should also work for a border */
1206 SelectObject( hdc, GetSysColorBrush(
1207 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1208 COLOR_3DFACE :
1209 (exStyle & WS_EX_STATICEDGE) ?
1210 COLOR_WINDOWFRAME :
1211 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1212 COLOR_3DFACE :
1213 /* else */
1214 COLOR_WINDOWFRAME));
1216 /* Draw frame */
1217 PatBlt( hdc, rect->left, rect->top,
1218 rect->right - rect->left, height, PATCOPY );
1219 PatBlt( hdc, rect->left, rect->top,
1220 width, rect->bottom - rect->top, PATCOPY );
1221 PatBlt( hdc, rect->left, rect->bottom - 1,
1222 rect->right - rect->left, -height, PATCOPY );
1223 PatBlt( hdc, rect->right - 1, rect->top,
1224 -width, rect->bottom - rect->top, PATCOPY );
1226 InflateRect( rect, -width, -height );
1231 /***********************************************************************
1232 * NC_DrawCaption
1234 * Draw the window caption.
1235 * The correct pen for the window frame must be selected in the DC.
1237 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1238 DWORD style, BOOL active )
1240 RECT r = *rect;
1241 char buffer[256];
1243 if (!hbitmapClose)
1245 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1248 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1250 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1251 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1252 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1253 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1254 r.left++;
1255 r.right--;
1256 SelectObject( hdc, hbrushOld );
1258 MoveToEx( hdc, r.left, r.bottom, NULL );
1259 LineTo( hdc, r.right, r.bottom );
1261 if (style & WS_SYSMENU)
1263 NC_DrawSysButton( hwnd, hdc, FALSE );
1264 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1265 MoveToEx( hdc, r.left - 1, r.top, NULL );
1266 LineTo( hdc, r.left - 1, r.bottom );
1268 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1269 if (style & WS_MAXIMIZEBOX)
1271 NC_DrawMaxButton( hwnd, hdc, FALSE );
1272 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1274 if (style & WS_MINIMIZEBOX)
1276 NC_DrawMinButton( hwnd, hdc, FALSE );
1277 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1280 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1282 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1283 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1284 SetBkMode( hdc, TRANSPARENT );
1285 DrawTextA( hdc, buffer, -1, &r,
1286 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1291 /******************************************************************************
1293 * NC_DrawCaption95(
1294 * HDC hdc,
1295 * RECT *rect,
1296 * HWND hwnd,
1297 * DWORD style,
1298 * BOOL active )
1300 * Draw the window caption for Win95 style windows.
1301 * The correct pen for the window frame must be selected in the DC.
1303 * Bugs
1304 * Hey, a function that finally works! Well, almost.
1305 * It's being worked on.
1307 * Revision history
1308 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1309 * Original implementation.
1310 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1311 * Some minor fixes.
1313 *****************************************************************************/
1315 static void NC_DrawCaption95(
1316 HDC hdc,
1317 RECT *rect,
1318 HWND hwnd,
1319 DWORD style,
1320 DWORD exStyle,
1321 BOOL active )
1323 RECT r = *rect;
1324 char buffer[256];
1325 HPEN hPrevPen;
1326 HMENU hSysMenu;
1328 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
1329 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1330 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1331 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1332 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1333 LineTo( hdc, r.right, r.bottom - 1 );
1334 SelectObject( hdc, hPrevPen );
1335 r.bottom--;
1337 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1338 COLOR_INACTIVECAPTION) );
1340 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1341 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1342 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1345 if (style & WS_SYSMENU)
1347 UINT state;
1349 /* Go get the sysmenu */
1350 hSysMenu = GetSystemMenu(hwnd, FALSE);
1351 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1353 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1354 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1355 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1356 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1358 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1360 /* In win95 the two buttons are always there */
1361 /* But if the menu item is not in the menu they're disabled*/
1363 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1364 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1366 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1367 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1371 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1372 NONCLIENTMETRICSA nclm;
1373 HFONT hFont, hOldFont;
1374 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1375 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1376 if (exStyle & WS_EX_TOOLWINDOW)
1377 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1378 else
1379 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1380 hOldFont = SelectObject (hdc, hFont);
1381 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1382 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1383 SetBkMode( hdc, TRANSPARENT );
1384 r.left += 2;
1385 DrawTextA( hdc, buffer, -1, &r,
1386 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1387 DeleteObject (SelectObject (hdc, hOldFont));
1393 /***********************************************************************
1394 * NC_DoNCPaint
1396 * Paint the non-client area. clip is currently unused.
1398 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1400 HDC hdc;
1401 RECT rect;
1402 BOOL active;
1403 WND *wndPtr;
1404 DWORD dwStyle, dwExStyle;
1405 WORD flags;
1406 RECT rectClient, rectWindow;
1407 int has_menu;
1409 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1410 has_menu = HAS_MENU(wndPtr);
1411 dwStyle = wndPtr->dwStyle;
1412 dwExStyle = wndPtr->dwExStyle;
1413 flags = wndPtr->flags;
1414 rectClient = wndPtr->rectClient;
1415 rectWindow = wndPtr->rectWindow;
1416 WIN_ReleasePtr( wndPtr );
1418 if ( dwStyle & WS_MINIMIZE ||
1419 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1421 active = flags & WIN_NCACTIVATED;
1423 TRACE("%p %d\n", hwnd, active );
1425 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1426 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1428 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1429 rectClient.top-rectWindow.top,
1430 rectClient.right-rectWindow.left,
1431 rectClient.bottom-rectWindow.top )
1432 == NULLREGION)
1434 ReleaseDC( hwnd, hdc );
1435 return;
1438 rect.top = rect.left = 0;
1439 rect.right = rectWindow.right - rectWindow.left;
1440 rect.bottom = rectWindow.bottom - rectWindow.top;
1442 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1444 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1446 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1447 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1448 InflateRect( &rect, -1, -1 );
1451 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1452 NC_DrawFrame(hdc, &rect, FALSE, active );
1453 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1454 NC_DrawFrame( hdc, &rect, TRUE, active );
1456 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1458 RECT r = rect;
1459 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1460 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1461 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1464 if (has_menu)
1466 RECT r = rect;
1467 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1468 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1471 /* Draw the scroll-bars */
1473 if (dwStyle & WS_VSCROLL)
1474 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1475 if (dwStyle & WS_HSCROLL)
1476 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1478 /* Draw the "size-box" */
1480 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1482 RECT r = rect;
1483 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1484 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1485 else
1486 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1487 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1488 if(wndPtr->dwStyle & WS_BORDER) {
1489 r.left++;
1490 r.top++;
1492 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1495 ReleaseDC( hwnd, hdc );
1499 /******************************************************************************
1501 * void NC_DoNCPaint95(
1502 * HWND hwnd,
1503 * HRGN clip,
1504 * BOOL suppress_menupaint )
1506 * Paint the non-client area for Win95 windows. The clip region is
1507 * currently ignored.
1509 * Bugs
1510 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1511 * misc/tweak.c controls/menu.c # :-)
1513 * Revision history
1514 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1515 * Original implementation
1516 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1517 * Fixed some bugs.
1518 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1519 * Streamlined window style checks.
1521 *****************************************************************************/
1523 static void NC_DoNCPaint95(
1524 HWND hwnd,
1525 HRGN clip,
1526 BOOL suppress_menupaint )
1528 HDC hdc;
1529 RECT rfuzz, rect, rectClip;
1530 BOOL active;
1531 WND *wndPtr;
1532 DWORD dwStyle, dwExStyle;
1533 WORD flags;
1534 RECT rectClient, rectWindow;
1535 int has_menu;
1537 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1538 has_menu = HAS_MENU(wndPtr);
1539 dwStyle = wndPtr->dwStyle;
1540 dwExStyle = wndPtr->dwExStyle;
1541 flags = wndPtr->flags;
1542 rectClient = wndPtr->rectClient;
1543 rectWindow = wndPtr->rectWindow;
1544 WIN_ReleasePtr( wndPtr );
1546 if ( dwStyle & WS_MINIMIZE ||
1547 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1549 active = flags & WIN_NCACTIVATED;
1551 TRACE("%p %d\n", hwnd, active );
1553 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1554 the call to GetDCEx implying that it is allowed not to use it either.
1555 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1556 will cause clipRgn to be deleted after ReleaseDC().
1557 Now, how is the "system" supposed to tell what happened?
1560 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1561 ((clip > (HRGN)1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1564 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1565 rectClient.top-rectWindow.top,
1566 rectClient.right-rectWindow.left,
1567 rectClient.bottom-rectWindow.top )
1568 == NULLREGION)
1570 ReleaseDC( hwnd, hdc );
1571 return;
1574 rect.top = rect.left = 0;
1575 rect.right = rectWindow.right - rectWindow.left;
1576 rect.bottom = rectWindow.bottom - rectWindow.top;
1578 if( clip > (HRGN)1 )
1579 GetRgnBox( clip, &rectClip );
1580 else
1582 clip = 0;
1583 rectClip = rect;
1586 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1588 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1589 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1591 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1592 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1595 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1597 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1599 RECT r = rect;
1600 if (dwExStyle & WS_EX_TOOLWINDOW) {
1601 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1602 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1604 else {
1605 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1606 rect.top += GetSystemMetrics(SM_CYCAPTION);
1608 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1609 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1610 dwExStyle, active);
1613 if (has_menu)
1615 RECT r = rect;
1616 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1618 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1619 r.left, r.top, r.right, r.bottom);
1621 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1624 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1625 rect.left, rect.top, rect.right, rect.bottom );
1627 if (dwExStyle & WS_EX_CLIENTEDGE)
1628 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1630 /* Draw the scroll-bars */
1632 if (dwStyle & WS_VSCROLL)
1633 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1634 if (dwStyle & WS_HSCROLL)
1635 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1637 /* Draw the "size-box" */
1638 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1640 RECT r = rect;
1641 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1642 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1643 else
1644 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1645 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1646 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1649 ReleaseDC( hwnd, hdc );
1655 /***********************************************************************
1656 * NC_HandleNCPaint
1658 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1660 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1662 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1664 if( dwStyle & WS_VISIBLE )
1666 if( dwStyle & WS_MINIMIZE )
1667 WINPOS_RedrawIconTitle( hwnd );
1668 else if (TWEAK_WineLook == WIN31_LOOK)
1669 NC_DoNCPaint( hwnd, clip, FALSE );
1670 else
1671 NC_DoNCPaint95( hwnd, clip, FALSE );
1673 return 0;
1677 /***********************************************************************
1678 * NC_HandleNCActivate
1680 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1682 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1684 WND* wndPtr = WIN_FindWndPtr( hwnd );
1686 /* Lotus Notes draws menu descriptions in the caption of its main
1687 * window. When it wants to restore original "system" view, it just
1688 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1689 * attempt to minimize redrawings lead to a not restored caption.
1691 if (wndPtr)
1693 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1694 else wndPtr->flags &= ~WIN_NCACTIVATED;
1695 WIN_ReleaseWndPtr(wndPtr);
1697 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1698 else if (TWEAK_WineLook == WIN31_LOOK)
1699 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1700 else
1701 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1703 return TRUE;
1707 /***********************************************************************
1708 * NC_HandleSetCursor
1710 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1712 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1714 hwnd = WIN_GetFullHandle( (HWND)wParam );
1716 switch(LOWORD(lParam))
1718 case HTERROR:
1720 WORD msg = HIWORD( lParam );
1721 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1722 (msg == WM_RBUTTONDOWN))
1723 MessageBeep(0);
1725 break;
1727 case HTCLIENT:
1729 HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
1730 if(hCursor) {
1731 SetCursor(hCursor);
1732 return TRUE;
1734 return FALSE;
1737 case HTLEFT:
1738 case HTRIGHT:
1739 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1741 case HTTOP:
1742 case HTBOTTOM:
1743 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1745 case HTTOPLEFT:
1746 case HTBOTTOMRIGHT:
1747 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1749 case HTTOPRIGHT:
1750 case HTBOTTOMLEFT:
1751 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1754 /* Default cursor: arrow */
1755 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1758 /***********************************************************************
1759 * NC_GetSysPopupPos
1761 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1763 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1764 else
1766 WND *wndPtr = WIN_FindWndPtr( hwnd );
1767 if (!wndPtr) return;
1769 NC_GetInsideRect( hwnd, rect );
1770 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1771 if (wndPtr->dwStyle & WS_CHILD)
1772 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1773 if (TWEAK_WineLook == WIN31_LOOK) {
1774 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1775 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1777 else {
1778 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1779 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1781 WIN_ReleaseWndPtr( wndPtr );
1785 /***********************************************************************
1786 * NC_TrackMinMaxBox95
1788 * Track a mouse button press on the minimize or maximize box.
1790 * The big difference between 3.1 and 95 is the disabled button state.
1791 * In win95 the system button can be disabled, so it can ignore the mouse
1792 * event.
1795 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1797 MSG msg;
1798 HDC hdc = GetWindowDC( hwnd );
1799 BOOL pressed = TRUE;
1800 UINT state;
1801 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1802 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1804 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1806 if (wParam == HTMINBUTTON)
1808 /* If the style is not present, do nothing */
1809 if (!(wndStyle & WS_MINIMIZEBOX))
1810 return;
1812 /* Check if the sysmenu item for minimize is there */
1813 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1815 paintButton = &NC_DrawMinButton95;
1817 else
1819 /* If the style is not present, do nothing */
1820 if (!(wndStyle & WS_MAXIMIZEBOX))
1821 return;
1823 /* Check if the sysmenu item for maximize is there */
1824 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1826 paintButton = &NC_DrawMaxButton95;
1829 SetCapture( hwnd );
1831 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1833 while(1)
1835 BOOL oldstate = pressed;
1837 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1838 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1840 if(msg.message == WM_LBUTTONUP)
1841 break;
1843 if(msg.message != WM_MOUSEMOVE)
1844 continue;
1846 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1847 if (pressed != oldstate)
1848 (*paintButton)( hwnd, hdc, pressed, FALSE);
1851 if(pressed)
1852 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1854 ReleaseCapture();
1855 ReleaseDC( hwnd, hdc );
1857 /* If the item minimize or maximize of the sysmenu are not there */
1858 /* or if the style is not present, do nothing */
1859 if ((!pressed) || (state == 0xFFFFFFFF))
1860 return;
1862 if (wParam == HTMINBUTTON)
1863 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1864 else
1865 SendMessageA( hwnd, WM_SYSCOMMAND,
1866 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1869 /***********************************************************************
1870 * NC_TrackMinMaxBox
1872 * Track a mouse button press on the minimize or maximize box.
1874 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1876 MSG msg;
1877 HDC hdc = GetWindowDC( hwnd );
1878 BOOL pressed = TRUE;
1879 void (*paintButton)(HWND, HDC, BOOL);
1881 SetCapture( hwnd );
1883 if (wParam == HTMINBUTTON)
1884 paintButton = &NC_DrawMinButton;
1885 else
1886 paintButton = &NC_DrawMaxButton;
1888 (*paintButton)( hwnd, hdc, TRUE);
1890 while(1)
1892 BOOL oldstate = pressed;
1894 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1895 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1897 if(msg.message == WM_LBUTTONUP)
1898 break;
1900 if(msg.message != WM_MOUSEMOVE)
1901 continue;
1903 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1904 if (pressed != oldstate)
1905 (*paintButton)( hwnd, hdc, pressed);
1908 if(pressed)
1909 (*paintButton)( hwnd, hdc, FALSE);
1911 ReleaseCapture();
1912 ReleaseDC( hwnd, hdc );
1914 if (!pressed) return;
1916 if (wParam == HTMINBUTTON)
1917 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1918 else
1919 SendMessageA( hwnd, WM_SYSCOMMAND,
1920 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1924 /***********************************************************************
1925 * NC_TrackCloseButton95
1927 * Track a mouse button press on the Win95 close button.
1929 static void
1930 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1932 MSG msg;
1933 HDC hdc;
1934 BOOL pressed = TRUE;
1935 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1936 UINT state;
1938 if(hSysMenu == 0)
1939 return;
1941 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1943 /* If the item close of the sysmenu is disabled or not there do nothing */
1944 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1945 return;
1947 hdc = GetWindowDC( hwnd );
1949 SetCapture( hwnd );
1951 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1953 while(1)
1955 BOOL oldstate = pressed;
1957 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1958 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1960 if(msg.message == WM_LBUTTONUP)
1961 break;
1963 if(msg.message != WM_MOUSEMOVE)
1964 continue;
1966 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1967 if (pressed != oldstate)
1968 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1971 if(pressed)
1972 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1974 ReleaseCapture();
1975 ReleaseDC( hwnd, hdc );
1976 if (!pressed) return;
1978 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1982 /***********************************************************************
1983 * NC_TrackScrollBar
1985 * Track a mouse button press on the horizontal or vertical scroll-bar.
1987 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1989 INT scrollbar;
1991 if ((wParam & 0xfff0) == SC_HSCROLL)
1993 if ((wParam & 0x0f) != HTHSCROLL) return;
1994 scrollbar = SB_HORZ;
1996 else /* SC_VSCROLL */
1998 if ((wParam & 0x0f) != HTVSCROLL) return;
1999 scrollbar = SB_VERT;
2001 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
2005 /***********************************************************************
2006 * NC_HandleNCLButtonDown
2008 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2010 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
2012 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
2014 switch(wParam) /* Hit test */
2016 case HTCAPTION:
2018 HWND top = GetAncestor( hwnd, GA_ROOT );
2020 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
2021 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2022 break;
2025 case HTSYSMENU:
2026 if( style & WS_SYSMENU )
2028 if( !(style & WS_MINIMIZE) )
2030 HDC hDC = GetWindowDC(hwnd);
2031 if (TWEAK_WineLook == WIN31_LOOK)
2032 NC_DrawSysButton( hwnd, hDC, TRUE );
2033 else
2034 NC_DrawSysButton95( hwnd, hDC, TRUE );
2035 ReleaseDC( hwnd, hDC );
2037 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2039 break;
2041 case HTMENU:
2042 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2043 break;
2045 case HTHSCROLL:
2046 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2047 break;
2049 case HTVSCROLL:
2050 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2051 break;
2053 case HTMINBUTTON:
2054 case HTMAXBUTTON:
2055 if (TWEAK_WineLook == WIN31_LOOK)
2056 NC_TrackMinMaxBox( hwnd, wParam );
2057 else
2058 NC_TrackMinMaxBox95( hwnd, wParam );
2059 break;
2061 case HTCLOSE:
2062 if (TWEAK_WineLook >= WIN95_LOOK)
2063 NC_TrackCloseButton95 (hwnd, wParam);
2064 break;
2066 case HTLEFT:
2067 case HTRIGHT:
2068 case HTTOP:
2069 case HTTOPLEFT:
2070 case HTTOPRIGHT:
2071 case HTBOTTOM:
2072 case HTBOTTOMLEFT:
2073 case HTBOTTOMRIGHT:
2074 /* Old comment:
2075 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
2076 * This was previously done by setting wParam=SC_SIZE + wParam - 2
2078 /* But that is not what WinNT does. Instead it sends this. This
2079 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
2080 * SC_MOUSEMENU into wParam.
2082 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
2083 break;
2085 case HTBORDER:
2086 break;
2088 return 0;
2092 /***********************************************************************
2093 * NC_HandleNCLButtonDblClk
2095 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2097 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2100 * if this is an icon, send a restore since we are handling
2101 * a double click
2103 if (IsIconic(hwnd))
2105 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2106 return 0;
2109 switch(wParam) /* Hit test */
2111 case HTCAPTION:
2112 /* stop processing if WS_MAXIMIZEBOX is missing */
2113 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2114 SendMessageW( hwnd, WM_SYSCOMMAND,
2115 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2116 break;
2118 case HTSYSMENU:
2119 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2120 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2121 break;
2123 case HTHSCROLL:
2124 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2125 break;
2127 case HTVSCROLL:
2128 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2129 break;
2131 return 0;
2135 /***********************************************************************
2136 * NC_HandleSysCommand
2138 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2140 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2142 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2144 switch (wParam & 0xfff0)
2146 case SC_SIZE:
2147 case SC_MOVE:
2148 if (USER_Driver.pSysCommandSizeMove)
2149 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2150 break;
2152 case SC_MINIMIZE:
2153 if (hwnd == GetForegroundWindow())
2154 ShowOwnedPopups(hwnd,FALSE);
2155 ShowWindow( hwnd, SW_MINIMIZE );
2156 break;
2158 case SC_MAXIMIZE:
2159 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2160 ShowOwnedPopups(hwnd,TRUE);
2161 ShowWindow( hwnd, SW_MAXIMIZE );
2162 break;
2164 case SC_RESTORE:
2165 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2166 ShowOwnedPopups(hwnd,TRUE);
2167 ShowWindow( hwnd, SW_RESTORE );
2168 break;
2170 case SC_CLOSE:
2171 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2173 case SC_VSCROLL:
2174 case SC_HSCROLL:
2176 POINT pt;
2177 pt.x = SLOWORD(lParam);
2178 pt.y = SHIWORD(lParam);
2179 NC_TrackScrollBar( hwnd, wParam, pt );
2181 break;
2183 case SC_MOUSEMENU:
2185 POINT pt;
2186 pt.x = SLOWORD(lParam);
2187 pt.y = SHIWORD(lParam);
2188 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2190 break;
2192 case SC_KEYMENU:
2193 MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2194 break;
2196 case SC_TASKLIST:
2197 WinExec( "taskman.exe", SW_SHOWNORMAL );
2198 break;
2200 case SC_SCREENSAVE:
2201 if (wParam == SC_ABOUTWINE)
2203 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2204 if (hmodule)
2206 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2207 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
2208 FreeLibrary( hmodule );
2211 else
2212 if (wParam == SC_PUTMARK)
2213 TRACE_(shell)("Mark requested by user\n");
2214 break;
2216 case SC_HOTKEY:
2217 case SC_ARRANGE:
2218 case SC_NEXTWINDOW:
2219 case SC_PREVWINDOW:
2220 FIXME("unimplemented!\n");
2221 break;
2223 return 0;
2226 /*************************************************************
2227 * NC_DrawGrayButton
2229 * Stub for the grayed button of the caption
2231 *************************************************************/
2233 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2235 HBITMAP hMaskBmp;
2236 HDC hdcMask;
2237 HBRUSH hOldBrush;
2239 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2241 if(hMaskBmp == 0)
2242 return FALSE;
2244 hdcMask = CreateCompatibleDC (0);
2245 SelectObject (hdcMask, hMaskBmp);
2247 /* Draw the grayed bitmap using the mask */
2248 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
2249 BitBlt (hdc, x, y, 12, 10,
2250 hdcMask, 0, 0, 0xB8074A);
2252 /* Clean up */
2253 SelectObject (hdc, hOldBrush);
2254 DeleteObject(hMaskBmp);
2255 DeleteDC (hdcMask);
2257 return TRUE;