Added version info to 16-bit shell.dll.
[wine/multimedia.git] / windows / nonclient.c
blob658b74138aaefe9b1970c8f528d8d162389400a0
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 "win.h"
27 #include "user.h"
28 #include "dce.h"
29 #include "controls.h"
30 #include "cursoricon.h"
31 #include "winpos.h"
32 #include "hook.h"
33 #include "nonclient.h"
34 #include "wine/debug.h"
35 #include "shellapi.h"
36 #include "bitmap.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("(%08x,%08x,%p,%08x,%08x,%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 NONCLIENTMETRICSA nclm;
349 HFONT hNewFont;
350 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
351 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
352 hNewFont = CreateFontIndirectA ((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 0x%x, width %d, "
473 "at (%d, %d).\n", hwnd,
474 winRect->right - winRect->left,
475 -tmpRect.left, -tmpRect.top );
477 winRect->top +=
478 MENU_GetMenuBarHeight( hwnd,
479 winRect->right - winRect->left,
480 -tmpRect.left, -tmpRect.top ) + 1;
483 if (TWEAK_WineLook > WIN31_LOOK) {
484 SetRect(&tmpRect, 0, 0, 0, 0);
485 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
486 winRect->left -= tmpRect.left;
487 winRect->top -= tmpRect.top;
488 winRect->right -= tmpRect.right;
489 winRect->bottom -= tmpRect.bottom;
492 if (winRect->top > winRect->bottom)
493 winRect->bottom = winRect->top;
495 if (winRect->left > winRect->right)
496 winRect->right = winRect->left;
498 return result;
502 /***********************************************************************
503 * NC_GetInsideRect
505 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
506 * but without the borders (if any).
507 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
509 void NC_GetInsideRect( HWND hwnd, RECT *rect )
511 WND * wndPtr = WIN_FindWndPtr( hwnd );
513 rect->top = rect->left = 0;
514 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
515 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
517 if (wndPtr->dwStyle & WS_ICONIC) goto END;
519 /* Remove frame from rectangle */
520 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
522 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
524 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
526 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
527 /* FIXME: this isn't in NC_AdjustRect? why not? */
528 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
529 InflateRect( rect, -1, 0 );
531 else if (HAS_THINFRAME( wndPtr->dwStyle ))
533 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
536 /* We have additional border information if the window
537 * is a child (but not an MDI child) */
538 if (TWEAK_WineLook != WIN31_LOOK)
540 if ( (wndPtr->dwStyle & WS_CHILD) &&
541 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
543 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
544 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
545 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
546 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
550 END:
551 WIN_ReleaseWndPtr(wndPtr);
552 return;
556 /***********************************************************************
557 * NC_DoNCHitTest
559 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
562 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
564 RECT rect;
566 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
568 GetWindowRect(wndPtr->hwndSelf, &rect );
569 if (!PtInRect( &rect, pt )) return HTNOWHERE;
571 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
573 /* Check borders */
574 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
576 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
577 if (!PtInRect( &rect, pt ))
579 /* Check top sizing border */
580 if (pt.y < rect.top)
582 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
583 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
584 return HTTOP;
586 /* Check bottom sizing border */
587 if (pt.y >= rect.bottom)
589 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
590 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
591 return HTBOTTOM;
593 /* Check left sizing border */
594 if (pt.x < rect.left)
596 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
597 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
598 return HTLEFT;
600 /* Check right sizing border */
601 if (pt.x >= rect.right)
603 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
604 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
605 return HTRIGHT;
609 else /* No thick frame */
611 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
612 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
613 else if (HAS_THINFRAME( wndPtr->dwStyle ))
614 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
615 if (!PtInRect( &rect, pt )) return HTBORDER;
618 /* Check caption */
620 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
622 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
623 if (!PtInRect( &rect, pt ))
625 /* Check system menu */
626 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
627 rect.left += GetSystemMetrics(SM_CXSIZE);
628 if (pt.x <= rect.left) return HTSYSMENU;
630 /* Check maximize box */
631 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
632 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
634 if (pt.x >= rect.right) return HTMAXBUTTON;
635 /* Check minimize box */
636 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
637 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
638 if (pt.x >= rect.right) return HTMINBUTTON;
639 return HTCAPTION;
643 /* Check client area */
645 ScreenToClient( wndPtr->hwndSelf, &pt );
646 GetClientRect( wndPtr->hwndSelf, &rect );
647 if (PtInRect( &rect, pt )) return HTCLIENT;
649 /* Check vertical scroll bar */
651 if (wndPtr->dwStyle & WS_VSCROLL)
653 rect.right += GetSystemMetrics(SM_CXVSCROLL);
654 if (PtInRect( &rect, pt )) return HTVSCROLL;
657 /* Check horizontal scroll bar */
659 if (wndPtr->dwStyle & WS_HSCROLL)
661 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
662 if (PtInRect( &rect, pt ))
664 /* Check size box */
665 if ((wndPtr->dwStyle & WS_VSCROLL) &&
666 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
667 return HTSIZE;
668 return HTHSCROLL;
672 /* Check menu bar */
674 if (HAS_MENU(wndPtr))
676 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
677 return HTMENU;
680 /* Has to return HTNOWHERE if nothing was found
681 Could happen when a window has a customized non client area */
682 return HTNOWHERE;
686 /***********************************************************************
687 * NC_DoNCHitTest95
689 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
691 * FIXME: Just a modified copy of the Win 3.1 version.
694 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
696 RECT rect;
698 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
700 GetWindowRect(wndPtr->hwndSelf, &rect );
701 if (!PtInRect( &rect, pt )) return HTNOWHERE;
703 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
705 /* Check borders */
706 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
708 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
709 if (!PtInRect( &rect, pt ))
711 /* Check top sizing border */
712 if (pt.y < rect.top)
714 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
715 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
716 return HTTOP;
718 /* Check bottom sizing border */
719 if (pt.y >= rect.bottom)
721 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
722 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
723 return HTBOTTOM;
725 /* Check left sizing border */
726 if (pt.x < rect.left)
728 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
729 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
730 return HTLEFT;
732 /* Check right sizing border */
733 if (pt.x >= rect.right)
735 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
736 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
737 return HTRIGHT;
741 else /* No thick frame */
743 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
744 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
745 else if (HAS_THINFRAME( wndPtr->dwStyle ))
746 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
747 if (!PtInRect( &rect, pt )) return HTBORDER;
750 /* Check caption */
752 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
754 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
755 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
756 else
757 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
758 if (!PtInRect( &rect, pt ))
760 /* Check system menu */
761 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
763 if (NC_IconForWindow(wndPtr->hwndSelf))
764 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
766 if (pt.x < rect.left) return HTSYSMENU;
768 /* Check close button */
769 if (wndPtr->dwStyle & WS_SYSMENU)
770 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
771 if (pt.x > rect.right) return HTCLOSE;
773 /* Check maximize box */
774 /* In win95 there is automatically a Maximize button when there is a minimize one*/
775 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
776 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
777 if (pt.x > rect.right) return HTMAXBUTTON;
779 /* Check minimize box */
780 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
781 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
782 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
784 if (pt.x > rect.right) return HTMINBUTTON;
785 return HTCAPTION;
789 /* Check client area */
791 ScreenToClient( wndPtr->hwndSelf, &pt );
792 GetClientRect( wndPtr->hwndSelf, &rect );
793 if (PtInRect( &rect, pt )) return HTCLIENT;
795 /* Check vertical scroll bar */
797 if (wndPtr->dwStyle & WS_VSCROLL)
799 rect.right += GetSystemMetrics(SM_CXVSCROLL);
800 if (PtInRect( &rect, pt )) return HTVSCROLL;
803 /* Check horizontal scroll bar */
805 if (wndPtr->dwStyle & WS_HSCROLL)
807 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
808 if (PtInRect( &rect, pt ))
810 /* Check size box */
811 if ((wndPtr->dwStyle & WS_VSCROLL) &&
812 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
813 return HTSIZE;
814 return HTHSCROLL;
818 /* Check menu bar */
820 if (HAS_MENU(wndPtr))
822 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
823 return HTMENU;
826 /* Has to return HTNOWHERE if nothing was found
827 Could happen when a window has a customized non client area */
828 return HTNOWHERE;
832 /***********************************************************************
833 * NC_HandleNCHitTest
835 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
837 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
839 LONG retvalue;
840 WND *wndPtr = WIN_FindWndPtr (hwnd);
842 if (!wndPtr)
843 return HTERROR;
845 if (TWEAK_WineLook == WIN31_LOOK)
846 retvalue = NC_DoNCHitTest (wndPtr, pt);
847 else
848 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
849 WIN_ReleaseWndPtr(wndPtr);
850 return retvalue;
854 /***********************************************************************
855 * NC_DrawSysButton
857 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
859 RECT rect;
860 HDC hdcMem;
861 HBITMAP hbitmap;
863 NC_GetInsideRect( hwnd, &rect );
864 hdcMem = CreateCompatibleDC( hdc );
865 hbitmap = SelectObject( hdcMem, hbitmapClose );
866 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
867 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
868 down ? NOTSRCCOPY : SRCCOPY );
869 SelectObject( hdcMem, hbitmap );
870 DeleteDC( hdcMem );
874 /***********************************************************************
875 * NC_DrawMaxButton
877 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
879 RECT rect;
880 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
882 NC_GetInsideRect( hwnd, &rect );
883 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
884 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
885 rect.top += 1;
886 rect.right -= 1;
887 if (down) flags |= DFCS_PUSHED;
888 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
892 /***********************************************************************
893 * NC_DrawMinButton
895 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
897 RECT rect;
898 UINT flags = DFCS_CAPTIONMIN;
899 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
901 NC_GetInsideRect( hwnd, &rect );
902 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
903 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
904 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
905 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
906 rect.top += 1;
907 rect.right -= 1;
908 if (down) flags |= DFCS_PUSHED;
909 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
913 /******************************************************************************
915 * void NC_DrawSysButton95(
916 * HWND hwnd,
917 * HDC hdc,
918 * BOOL down )
920 * Draws the Win95 system icon.
922 * Revision history
923 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
924 * Original implementation from NC_DrawSysButton source.
925 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
926 * Fixed most bugs.
928 *****************************************************************************/
930 BOOL
931 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
933 HICON hIcon = NC_IconForWindow( hwnd );
935 if (hIcon)
937 RECT rect;
938 NC_GetInsideRect( hwnd, &rect );
939 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
940 GetSystemMetrics(SM_CXSMICON),
941 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
943 return (hIcon != 0);
947 /******************************************************************************
949 * void NC_DrawCloseButton95(
950 * HWND hwnd,
951 * HDC hdc,
952 * BOOL down,
953 * BOOL bGrayed )
955 * Draws the Win95 close button.
957 * If bGrayed is true, then draw a disabled Close button
959 * Revision history
960 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
961 * Original implementation from NC_DrawSysButton95 source.
963 *****************************************************************************/
965 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
967 RECT rect;
969 NC_GetInsideRect( hwnd, &rect );
971 /* A tool window has a smaller Close button */
972 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
974 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
975 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
976 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
978 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
979 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
980 rect.bottom = rect.top + iBmpHeight;
981 rect.right = rect.left + iBmpWidth;
983 else
985 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
986 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
987 rect.top += 2;
988 rect.right -= 2;
990 DrawFrameControl( hdc, &rect, DFC_CAPTION,
991 (DFCS_CAPTIONCLOSE |
992 (down ? DFCS_PUSHED : 0) |
993 (bGrayed ? DFCS_INACTIVE : 0)) );
996 /******************************************************************************
997 * NC_DrawMaxButton95
999 * Draws the maximize button for Win95 style windows.
1000 * If bGrayed is true, then draw a disabled Maximize button
1002 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1004 RECT rect;
1005 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1007 NC_GetInsideRect( hwnd, &rect );
1008 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1009 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1010 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1011 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1012 rect.top += 2;
1013 rect.right -= 2;
1014 if (down) flags |= DFCS_PUSHED;
1015 if (bGrayed) flags |= DFCS_INACTIVE;
1016 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1019 /******************************************************************************
1020 * NC_DrawMinButton95
1022 * Draws the minimize button for Win95 style windows.
1023 * If bGrayed is true, then draw a disabled Minimize button
1025 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1027 RECT rect;
1028 UINT flags = DFCS_CAPTIONMIN;
1029 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1031 NC_GetInsideRect( hwnd, &rect );
1032 if (style & WS_SYSMENU)
1033 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1034 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1035 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1036 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1037 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1038 rect.top += 2;
1039 rect.right -= 2;
1040 if (down) flags |= DFCS_PUSHED;
1041 if (bGrayed) flags |= DFCS_INACTIVE;
1042 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1045 /***********************************************************************
1046 * NC_DrawFrame
1048 * Draw a window frame inside the given rectangle, and update the rectangle.
1049 * The correct pen for the frame must be selected in the DC.
1051 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1052 BOOL active )
1054 INT width, height;
1056 if (TWEAK_WineLook != WIN31_LOOK)
1057 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1059 if (dlgFrame)
1061 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1062 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1063 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1064 COLOR_INACTIVECAPTION) );
1066 else
1068 width = GetSystemMetrics(SM_CXFRAME) - 2;
1069 height = GetSystemMetrics(SM_CYFRAME) - 2;
1070 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1071 COLOR_INACTIVEBORDER) );
1074 /* Draw frame */
1075 PatBlt( hdc, rect->left, rect->top,
1076 rect->right - rect->left, height, PATCOPY );
1077 PatBlt( hdc, rect->left, rect->top,
1078 width, rect->bottom - rect->top, PATCOPY );
1079 PatBlt( hdc, rect->left, rect->bottom - 1,
1080 rect->right - rect->left, -height, PATCOPY );
1081 PatBlt( hdc, rect->right - 1, rect->top,
1082 -width, rect->bottom - rect->top, PATCOPY );
1084 if (dlgFrame)
1086 InflateRect( rect, -width, -height );
1088 else
1090 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1091 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1093 /* Draw inner rectangle */
1095 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1096 Rectangle( hdc, rect->left + width, rect->top + height,
1097 rect->right - width , rect->bottom - height );
1099 /* Draw the decorations */
1101 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1102 LineTo( hdc, rect->left + width, rect->top + decYOff );
1103 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1104 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1105 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1106 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1107 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1108 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1110 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1111 LineTo( hdc, rect->left + decXOff, rect->top + height);
1112 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1113 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1114 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1115 LineTo( hdc, rect->right - decXOff, rect->top + height );
1116 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1117 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1119 InflateRect( rect, -width - 1, -height - 1 );
1124 /******************************************************************************
1126 * void NC_DrawFrame95(
1127 * HDC hdc,
1128 * RECT *rect,
1129 * BOOL active,
1130 * DWORD style,
1131 * DWORD exStyle )
1133 * Draw a window frame inside the given rectangle, and update the rectangle.
1135 * Bugs
1136 * Many. First, just what IS a frame in Win95? Note that the 3D look
1137 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1138 * edge. The inner rectangle just inside the frame is handled by the
1139 * Caption code.
1141 * In short, for most people, this function should be a nop (unless
1142 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1143 * them lately, but just to get this code right). Even so, it doesn't
1144 * appear to be so. It's being worked on...
1146 * Revision history
1147 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1148 * Original implementation (based on NC_DrawFrame)
1149 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1150 * Some minor fixes.
1151 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1152 * Fixed a fix or something.
1154 *****************************************************************************/
1156 static void NC_DrawFrame95(
1157 HDC hdc,
1158 RECT *rect,
1159 BOOL active,
1160 DWORD style,
1161 DWORD exStyle)
1163 INT width, height;
1165 /* Firstly the "thick" frame */
1166 if (style & WS_THICKFRAME)
1168 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1169 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1171 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1172 COLOR_INACTIVEBORDER) );
1173 /* Draw frame */
1174 PatBlt( hdc, rect->left, rect->top,
1175 rect->right - rect->left, height, PATCOPY );
1176 PatBlt( hdc, rect->left, rect->top,
1177 width, rect->bottom - rect->top, PATCOPY );
1178 PatBlt( hdc, rect->left, rect->bottom - 1,
1179 rect->right - rect->left, -height, PATCOPY );
1180 PatBlt( hdc, rect->right - 1, rect->top,
1181 -width, rect->bottom - rect->top, PATCOPY );
1183 InflateRect( rect, -width, -height );
1186 /* Now the other bit of the frame */
1187 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1188 (exStyle & WS_EX_DLGMODALFRAME))
1190 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1191 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1192 /* This should give a value of 1 that should also work for a border */
1194 SelectObject( hdc, GetSysColorBrush(
1195 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1196 COLOR_3DFACE :
1197 (exStyle & WS_EX_STATICEDGE) ?
1198 COLOR_WINDOWFRAME :
1199 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1200 COLOR_3DFACE :
1201 /* else */
1202 COLOR_WINDOWFRAME));
1204 /* Draw frame */
1205 PatBlt( hdc, rect->left, rect->top,
1206 rect->right - rect->left, height, PATCOPY );
1207 PatBlt( hdc, rect->left, rect->top,
1208 width, rect->bottom - rect->top, PATCOPY );
1209 PatBlt( hdc, rect->left, rect->bottom - 1,
1210 rect->right - rect->left, -height, PATCOPY );
1211 PatBlt( hdc, rect->right - 1, rect->top,
1212 -width, rect->bottom - rect->top, PATCOPY );
1214 InflateRect( rect, -width, -height );
1219 /***********************************************************************
1220 * NC_DrawCaption
1222 * Draw the window caption.
1223 * The correct pen for the window frame must be selected in the DC.
1225 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1226 DWORD style, BOOL active )
1228 RECT r = *rect;
1229 char buffer[256];
1231 if (!hbitmapClose)
1233 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1236 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1238 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1239 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1240 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1241 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1242 r.left++;
1243 r.right--;
1244 SelectObject( hdc, hbrushOld );
1246 MoveToEx( hdc, r.left, r.bottom, NULL );
1247 LineTo( hdc, r.right, r.bottom );
1249 if (style & WS_SYSMENU)
1251 NC_DrawSysButton( hwnd, hdc, FALSE );
1252 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1253 MoveToEx( hdc, r.left - 1, r.top, NULL );
1254 LineTo( hdc, r.left - 1, r.bottom );
1256 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1257 if (style & WS_MAXIMIZEBOX)
1259 NC_DrawMaxButton( hwnd, hdc, FALSE );
1260 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1262 if (style & WS_MINIMIZEBOX)
1264 NC_DrawMinButton( hwnd, hdc, FALSE );
1265 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1268 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1270 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1271 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1272 SetBkMode( hdc, TRANSPARENT );
1273 DrawTextA( hdc, buffer, -1, &r,
1274 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1279 /******************************************************************************
1281 * NC_DrawCaption95(
1282 * HDC hdc,
1283 * RECT *rect,
1284 * HWND hwnd,
1285 * DWORD style,
1286 * BOOL active )
1288 * Draw the window caption for Win95 style windows.
1289 * The correct pen for the window frame must be selected in the DC.
1291 * Bugs
1292 * Hey, a function that finally works! Well, almost.
1293 * It's being worked on.
1295 * Revision history
1296 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1297 * Original implementation.
1298 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1299 * Some minor fixes.
1301 *****************************************************************************/
1303 static void NC_DrawCaption95(
1304 HDC hdc,
1305 RECT *rect,
1306 HWND hwnd,
1307 DWORD style,
1308 DWORD exStyle,
1309 BOOL active )
1311 RECT r = *rect;
1312 char buffer[256];
1313 HPEN hPrevPen;
1314 HMENU hSysMenu;
1316 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
1317 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1318 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1319 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1320 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1321 LineTo( hdc, r.right, r.bottom - 1 );
1322 SelectObject( hdc, hPrevPen );
1323 r.bottom--;
1325 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1326 COLOR_INACTIVECAPTION) );
1328 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1329 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1330 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1333 if (style & WS_SYSMENU)
1335 UINT state;
1337 /* Go get the sysmenu */
1338 hSysMenu = GetSystemMenu(hwnd, FALSE);
1339 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1341 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1342 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1343 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1344 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1346 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1348 /* In win95 the two buttons are always there */
1349 /* But if the menu item is not in the menu they're disabled*/
1351 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1352 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1354 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1355 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1359 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1360 NONCLIENTMETRICSA nclm;
1361 HFONT hFont, hOldFont;
1362 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1363 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1364 if (exStyle & WS_EX_TOOLWINDOW)
1365 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1366 else
1367 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1368 hOldFont = SelectObject (hdc, hFont);
1369 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1370 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1371 SetBkMode( hdc, TRANSPARENT );
1372 r.left += 2;
1373 DrawTextA( hdc, buffer, -1, &r,
1374 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1375 DeleteObject (SelectObject (hdc, hOldFont));
1381 /***********************************************************************
1382 * NC_DoNCPaint
1384 * Paint the non-client area. clip is currently unused.
1386 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1388 HDC hdc;
1389 RECT rect;
1390 BOOL active;
1391 WND *wndPtr;
1392 DWORD dwStyle, dwExStyle;
1393 WORD flags;
1394 RECT rectClient, rectWindow;
1395 int has_menu;
1397 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1398 has_menu = HAS_MENU(wndPtr);
1399 dwStyle = wndPtr->dwStyle;
1400 dwExStyle = wndPtr->dwExStyle;
1401 flags = wndPtr->flags;
1402 rectClient = wndPtr->rectClient;
1403 rectWindow = wndPtr->rectWindow;
1404 WIN_ReleasePtr( wndPtr );
1406 if ( dwStyle & WS_MINIMIZE ||
1407 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1409 active = flags & WIN_NCACTIVATED;
1411 TRACE("%04x %d\n", hwnd, active );
1413 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1414 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1416 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1417 rectClient.top-rectWindow.top,
1418 rectClient.right-rectWindow.left,
1419 rectClient.bottom-rectWindow.top )
1420 == NULLREGION)
1422 ReleaseDC( hwnd, hdc );
1423 return;
1426 rect.top = rect.left = 0;
1427 rect.right = rectWindow.right - rectWindow.left;
1428 rect.bottom = rectWindow.bottom - rectWindow.top;
1430 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1432 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1434 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1435 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1436 InflateRect( &rect, -1, -1 );
1439 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1440 NC_DrawFrame(hdc, &rect, FALSE, active );
1441 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1442 NC_DrawFrame( hdc, &rect, TRUE, active );
1444 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1446 RECT r = rect;
1447 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1448 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1449 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1452 if (has_menu)
1454 RECT r = rect;
1455 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1456 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1459 /* Draw the scroll-bars */
1461 if (dwStyle & WS_VSCROLL)
1462 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1463 if (dwStyle & WS_HSCROLL)
1464 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1466 /* Draw the "size-box" */
1468 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1470 RECT r = rect;
1471 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1472 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1473 if(wndPtr->dwStyle & WS_BORDER) {
1474 r.left++;
1475 r.top++;
1477 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1480 ReleaseDC( hwnd, hdc );
1484 /******************************************************************************
1486 * void NC_DoNCPaint95(
1487 * HWND hwnd,
1488 * HRGN clip,
1489 * BOOL suppress_menupaint )
1491 * Paint the non-client area for Win95 windows. The clip region is
1492 * currently ignored.
1494 * Bugs
1495 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1496 * misc/tweak.c controls/menu.c # :-)
1498 * Revision history
1499 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1500 * Original implementation
1501 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1502 * Fixed some bugs.
1503 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1504 * Streamlined window style checks.
1506 *****************************************************************************/
1508 static void NC_DoNCPaint95(
1509 HWND hwnd,
1510 HRGN clip,
1511 BOOL suppress_menupaint )
1513 HDC hdc;
1514 RECT rfuzz, rect, rectClip;
1515 BOOL active;
1516 WND *wndPtr;
1517 DWORD dwStyle, dwExStyle;
1518 WORD flags;
1519 RECT rectClient, rectWindow;
1520 int has_menu;
1522 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1523 has_menu = HAS_MENU(wndPtr);
1524 dwStyle = wndPtr->dwStyle;
1525 dwExStyle = wndPtr->dwExStyle;
1526 flags = wndPtr->flags;
1527 rectClient = wndPtr->rectClient;
1528 rectWindow = wndPtr->rectWindow;
1529 WIN_ReleasePtr( wndPtr );
1531 if ( dwStyle & WS_MINIMIZE ||
1532 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1534 active = flags & WIN_NCACTIVATED;
1536 TRACE("%04x %d\n", hwnd, active );
1538 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1539 the call to GetDCEx implying that it is allowed not to use it either.
1540 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1541 will cause clipRgn to be deleted after ReleaseDC().
1542 Now, how is the "system" supposed to tell what happened?
1545 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1546 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1549 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1550 rectClient.top-rectWindow.top,
1551 rectClient.right-rectWindow.left,
1552 rectClient.bottom-rectWindow.top )
1553 == NULLREGION)
1555 ReleaseDC( hwnd, hdc );
1556 return;
1559 rect.top = rect.left = 0;
1560 rect.right = rectWindow.right - rectWindow.left;
1561 rect.bottom = rectWindow.bottom - rectWindow.top;
1563 if( clip > 1 )
1564 GetRgnBox( clip, &rectClip );
1565 else
1567 clip = 0;
1568 rectClip = rect;
1571 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1573 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1574 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1576 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1577 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1580 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1582 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1584 RECT r = rect;
1585 if (dwExStyle & WS_EX_TOOLWINDOW) {
1586 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1587 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1589 else {
1590 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1591 rect.top += GetSystemMetrics(SM_CYCAPTION);
1593 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1594 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1595 dwExStyle, active);
1598 if (has_menu)
1600 RECT r = rect;
1601 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1603 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1604 r.left, r.top, r.right, r.bottom);
1606 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1609 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1610 rect.left, rect.top, rect.right, rect.bottom );
1612 if (dwExStyle & WS_EX_CLIENTEDGE)
1613 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1615 /* Draw the scroll-bars */
1617 if (dwStyle & WS_VSCROLL)
1618 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1619 if (dwStyle & WS_HSCROLL)
1620 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1622 /* Draw the "size-box" */
1623 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1625 RECT r = rect;
1626 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1627 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1628 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1631 ReleaseDC( hwnd, hdc );
1637 /***********************************************************************
1638 * NC_HandleNCPaint
1640 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1642 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1644 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1646 if( dwStyle & WS_VISIBLE )
1648 if( dwStyle & WS_MINIMIZE )
1649 WINPOS_RedrawIconTitle( hwnd );
1650 else if (TWEAK_WineLook == WIN31_LOOK)
1651 NC_DoNCPaint( hwnd, clip, FALSE );
1652 else
1653 NC_DoNCPaint95( hwnd, clip, FALSE );
1655 return 0;
1659 /***********************************************************************
1660 * NC_HandleNCActivate
1662 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1664 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1666 WND* wndPtr = WIN_FindWndPtr( hwnd );
1668 /* Lotus Notes draws menu descriptions in the caption of its main
1669 * window. When it wants to restore original "system" view, it just
1670 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1671 * attempt to minimize redrawings lead to a not restored caption.
1673 if (wndPtr)
1675 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1676 else wndPtr->flags &= ~WIN_NCACTIVATED;
1677 WIN_ReleaseWndPtr(wndPtr);
1679 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1680 else if (TWEAK_WineLook == WIN31_LOOK)
1681 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1682 else
1683 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1685 return TRUE;
1689 /***********************************************************************
1690 * NC_HandleSetCursor
1692 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1694 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1696 hwnd = WIN_GetFullHandle( (HWND)wParam );
1698 switch(LOWORD(lParam))
1700 case HTERROR:
1702 WORD msg = HIWORD( lParam );
1703 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1704 (msg == WM_RBUTTONDOWN))
1705 MessageBeep(0);
1707 break;
1709 case HTCLIENT:
1711 HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1712 if(hCursor) {
1713 SetCursor(hCursor);
1714 return TRUE;
1716 return FALSE;
1719 case HTLEFT:
1720 case HTRIGHT:
1721 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1723 case HTTOP:
1724 case HTBOTTOM:
1725 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1727 case HTTOPLEFT:
1728 case HTBOTTOMRIGHT:
1729 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1731 case HTTOPRIGHT:
1732 case HTBOTTOMLEFT:
1733 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1736 /* Default cursor: arrow */
1737 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1740 /***********************************************************************
1741 * NC_GetSysPopupPos
1743 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1745 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1746 else
1748 WND *wndPtr = WIN_FindWndPtr( hwnd );
1749 if (!wndPtr) return;
1751 NC_GetInsideRect( hwnd, rect );
1752 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1753 if (wndPtr->dwStyle & WS_CHILD)
1754 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1755 if (TWEAK_WineLook == WIN31_LOOK) {
1756 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1757 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1759 else {
1760 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1761 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1763 WIN_ReleaseWndPtr( wndPtr );
1767 /***********************************************************************
1768 * NC_TrackMinMaxBox95
1770 * Track a mouse button press on the minimize or maximize box.
1772 * The big difference between 3.1 and 95 is the disabled button state.
1773 * In win95 the system button can be disabled, so it can ignore the mouse
1774 * event.
1777 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1779 MSG msg;
1780 HDC hdc = GetWindowDC( hwnd );
1781 BOOL pressed = TRUE;
1782 UINT state;
1783 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1784 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1786 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
1788 if (wParam == HTMINBUTTON)
1790 /* If the style is not present, do nothing */
1791 if (!(wndStyle & WS_MINIMIZEBOX))
1792 return;
1794 /* Check if the sysmenu item for minimize is there */
1795 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1797 paintButton = &NC_DrawMinButton95;
1799 else
1801 /* If the style is not present, do nothing */
1802 if (!(wndStyle & WS_MAXIMIZEBOX))
1803 return;
1805 /* Check if the sysmenu item for maximize is there */
1806 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1808 paintButton = &NC_DrawMaxButton95;
1811 SetCapture( hwnd );
1813 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1815 while(1)
1817 BOOL oldstate = pressed;
1819 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1820 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1822 if(msg.message == WM_LBUTTONUP)
1823 break;
1825 if(msg.message != WM_MOUSEMOVE)
1826 continue;
1828 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1829 if (pressed != oldstate)
1830 (*paintButton)( hwnd, hdc, pressed, FALSE);
1833 if(pressed)
1834 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1836 ReleaseCapture();
1837 ReleaseDC( hwnd, hdc );
1839 /* If the item minimize or maximize of the sysmenu are not there */
1840 /* or if the style is not present, do nothing */
1841 if ((!pressed) || (state == 0xFFFFFFFF))
1842 return;
1844 if (wParam == HTMINBUTTON)
1845 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1846 else
1847 SendMessageA( hwnd, WM_SYSCOMMAND,
1848 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1851 /***********************************************************************
1852 * NC_TrackMinMaxBox
1854 * Track a mouse button press on the minimize or maximize box.
1856 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1858 MSG msg;
1859 HDC hdc = GetWindowDC( hwnd );
1860 BOOL pressed = TRUE;
1861 void (*paintButton)(HWND, HDC16, BOOL);
1863 SetCapture( hwnd );
1865 if (wParam == HTMINBUTTON)
1866 paintButton = &NC_DrawMinButton;
1867 else
1868 paintButton = &NC_DrawMaxButton;
1870 (*paintButton)( hwnd, hdc, TRUE);
1872 while(1)
1874 BOOL oldstate = pressed;
1876 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1877 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1879 if(msg.message == WM_LBUTTONUP)
1880 break;
1882 if(msg.message != WM_MOUSEMOVE)
1883 continue;
1885 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1886 if (pressed != oldstate)
1887 (*paintButton)( hwnd, hdc, pressed);
1890 if(pressed)
1891 (*paintButton)( hwnd, hdc, FALSE);
1893 ReleaseCapture();
1894 ReleaseDC( hwnd, hdc );
1896 if (!pressed) return;
1898 if (wParam == HTMINBUTTON)
1899 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1900 else
1901 SendMessageA( hwnd, WM_SYSCOMMAND,
1902 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1906 /***********************************************************************
1907 * NC_TrackCloseButton95
1909 * Track a mouse button press on the Win95 close button.
1911 static void
1912 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1914 MSG msg;
1915 HDC hdc;
1916 BOOL pressed = TRUE;
1917 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1918 UINT state;
1920 if(hSysMenu == 0)
1921 return;
1923 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1925 /* If the item close of the sysmenu is disabled or not there do nothing */
1926 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1927 return;
1929 hdc = GetWindowDC( hwnd );
1931 SetCapture( hwnd );
1933 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1935 while(1)
1937 BOOL oldstate = pressed;
1939 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1940 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1942 if(msg.message == WM_LBUTTONUP)
1943 break;
1945 if(msg.message != WM_MOUSEMOVE)
1946 continue;
1948 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1949 if (pressed != oldstate)
1950 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1953 if(pressed)
1954 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1956 ReleaseCapture();
1957 ReleaseDC( hwnd, hdc );
1958 if (!pressed) return;
1960 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1964 /***********************************************************************
1965 * NC_TrackScrollBar
1967 * Track a mouse button press on the horizontal or vertical scroll-bar.
1969 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1971 INT scrollbar;
1973 if ((wParam & 0xfff0) == SC_HSCROLL)
1975 if ((wParam & 0x0f) != HTHSCROLL) return;
1976 scrollbar = SB_HORZ;
1978 else /* SC_VSCROLL */
1980 if ((wParam & 0x0f) != HTVSCROLL) return;
1981 scrollbar = SB_VERT;
1983 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1987 /***********************************************************************
1988 * NC_HandleNCLButtonDown
1990 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1992 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1994 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1996 switch(wParam) /* Hit test */
1998 case HTCAPTION:
2000 HWND top = GetAncestor( hwnd, GA_ROOT );
2002 if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
2003 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2004 break;
2007 case HTSYSMENU:
2008 if( style & WS_SYSMENU )
2010 if( !(style & WS_MINIMIZE) )
2012 HDC hDC = GetWindowDC(hwnd);
2013 if (TWEAK_WineLook == WIN31_LOOK)
2014 NC_DrawSysButton( hwnd, hDC, TRUE );
2015 else
2016 NC_DrawSysButton95( hwnd, hDC, TRUE );
2017 ReleaseDC( hwnd, hDC );
2019 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2021 break;
2023 case HTMENU:
2024 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2025 break;
2027 case HTHSCROLL:
2028 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2029 break;
2031 case HTVSCROLL:
2032 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2033 break;
2035 case HTMINBUTTON:
2036 case HTMAXBUTTON:
2037 if (TWEAK_WineLook == WIN31_LOOK)
2038 NC_TrackMinMaxBox( hwnd, wParam );
2039 else
2040 NC_TrackMinMaxBox95( hwnd, wParam );
2041 break;
2043 case HTCLOSE:
2044 if (TWEAK_WineLook >= WIN95_LOOK)
2045 NC_TrackCloseButton95 (hwnd, wParam);
2046 break;
2048 case HTLEFT:
2049 case HTRIGHT:
2050 case HTTOP:
2051 case HTTOPLEFT:
2052 case HTTOPRIGHT:
2053 case HTBOTTOM:
2054 case HTBOTTOMLEFT:
2055 case HTBOTTOMRIGHT:
2056 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2057 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2058 break;
2060 case HTBORDER:
2061 break;
2063 return 0;
2067 /***********************************************************************
2068 * NC_HandleNCLButtonDblClk
2070 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2072 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2075 * if this is an icon, send a restore since we are handling
2076 * a double click
2078 if (IsIconic(hwnd))
2080 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2081 return 0;
2084 switch(wParam) /* Hit test */
2086 case HTCAPTION:
2087 /* stop processing if WS_MAXIMIZEBOX is missing */
2088 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2089 SendMessageW( hwnd, WM_SYSCOMMAND,
2090 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2091 break;
2093 case HTSYSMENU:
2094 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2095 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2096 break;
2098 case HTHSCROLL:
2099 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2100 break;
2102 case HTVSCROLL:
2103 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2104 break;
2106 return 0;
2110 /***********************************************************************
2111 * NC_HandleSysCommand
2113 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2115 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2117 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2119 switch (wParam & 0xfff0)
2121 case SC_SIZE:
2122 case SC_MOVE:
2123 if (USER_Driver.pSysCommandSizeMove)
2124 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2125 break;
2127 case SC_MINIMIZE:
2128 if (hwnd == GetForegroundWindow())
2129 ShowOwnedPopups(hwnd,FALSE);
2130 ShowWindow( hwnd, SW_MINIMIZE );
2131 break;
2133 case SC_MAXIMIZE:
2134 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2135 ShowOwnedPopups(hwnd,TRUE);
2136 ShowWindow( hwnd, SW_MAXIMIZE );
2137 break;
2139 case SC_RESTORE:
2140 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2141 ShowOwnedPopups(hwnd,TRUE);
2142 ShowWindow( hwnd, SW_RESTORE );
2143 break;
2145 case SC_CLOSE:
2146 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2148 case SC_VSCROLL:
2149 case SC_HSCROLL:
2151 POINT pt;
2152 pt.x = SLOWORD(lParam);
2153 pt.y = SHIWORD(lParam);
2154 NC_TrackScrollBar( hwnd, wParam, pt );
2156 break;
2158 case SC_MOUSEMENU:
2160 POINT pt;
2161 pt.x = SLOWORD(lParam);
2162 pt.y = SHIWORD(lParam);
2163 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2165 break;
2167 case SC_KEYMENU:
2168 MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2169 break;
2171 case SC_TASKLIST:
2172 WinExec( "taskman.exe", SW_SHOWNORMAL );
2173 break;
2175 case SC_SCREENSAVE:
2176 if (wParam == SC_ABOUTWINE)
2178 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2179 if (hmodule)
2181 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2182 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
2183 FreeLibrary( hmodule );
2186 else
2187 if (wParam == SC_PUTMARK)
2188 TRACE_(shell)("Mark requested by user\n");
2189 break;
2191 case SC_HOTKEY:
2192 case SC_ARRANGE:
2193 case SC_NEXTWINDOW:
2194 case SC_PREVWINDOW:
2195 FIXME("unimplemented!\n");
2196 break;
2198 return 0;
2201 /*************************************************************
2202 * NC_DrawGrayButton
2204 * Stub for the grayed button of the caption
2206 *************************************************************/
2208 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2210 HBITMAP hMaskBmp;
2211 HDC hdcMask = CreateCompatibleDC (0);
2212 HBRUSH hOldBrush;
2214 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2216 if(hMaskBmp == 0)
2217 return FALSE;
2219 SelectObject (hdcMask, hMaskBmp);
2221 /* Draw the grayed bitmap using the mask */
2222 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2223 BitBlt (hdc, x, y, 12, 10,
2224 hdcMask, 0, 0, 0xB8074A);
2226 /* Clean up */
2227 SelectObject (hdc, hOldBrush);
2228 DeleteObject(hMaskBmp);
2229 DeleteDC (hdcMask);
2231 return TRUE;