Add stub for __lconv_init().
[wine/multimedia.git] / windows / nonclient.c
blob999b5a6500d5181f11226714f97def89d85b57a0
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 "windef.h"
22 #include "wingdi.h"
23 #include "wine/winuser16.h"
24 #include "wine/version.h"
25 #include "win.h"
26 #include "user.h"
27 #include "dce.h"
28 #include "controls.h"
29 #include "cursoricon.h"
30 #include "winpos.h"
31 #include "hook.h"
32 #include "nonclient.h"
33 #include "wine/debug.h"
34 #include "shellapi.h"
35 #include "bitmap.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
38 WINE_DECLARE_DEBUG_CHANNEL(shell);
40 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
42 static HBITMAP hbitmapClose;
44 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
45 0x55, 0x50,
46 0xAA, 0xA0,
47 0x55, 0x50,
48 0xAA, 0xA0,
49 0x55, 0x50,
50 0xAA, 0xA0,
51 0x55, 0x50,
52 0xAA, 0xA0,
53 0x55, 0x50};
55 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
56 #define SC_PUTMARK (SC_SCREENSAVE+2)
58 /* Some useful macros */
59 #define HAS_DLGFRAME(style,exStyle) \
60 (((exStyle) & WS_EX_DLGMODALFRAME) || \
61 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
63 #define HAS_THICKFRAME(style,exStyle) \
64 (((style) & WS_THICKFRAME) && \
65 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
67 #define HAS_THINFRAME(style) \
68 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
70 #define HAS_BIGFRAME(style,exStyle) \
71 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
72 ((exStyle) & WS_EX_DLGMODALFRAME))
74 #define HAS_STATICOUTERFRAME(style,exStyle) \
75 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
76 WS_EX_STATICEDGE)
78 #define HAS_ANYFRAME(style,exStyle) \
79 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
80 ((exStyle) & WS_EX_DLGMODALFRAME) || \
81 !((style) & (WS_CHILD | WS_POPUP)))
83 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
86 /***********************************************************************
87 * NC_AdjustRect
89 * Compute the size of the window rectangle from the size of the
90 * client rectangle.
92 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
94 if (TWEAK_WineLook > WIN31_LOOK)
95 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
97 if(style & WS_ICONIC) return;
99 if (HAS_THICKFRAME( style, exStyle ))
100 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
101 else if (HAS_DLGFRAME( style, exStyle ))
102 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
103 else if (HAS_THINFRAME( style ))
104 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
106 if ((style & WS_CAPTION) == WS_CAPTION)
107 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
109 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
111 if (style & WS_VSCROLL) {
112 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
113 if(!HAS_ANYFRAME( style, exStyle ))
114 rect->right++;
117 if (style & WS_HSCROLL) {
118 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
119 if(!HAS_ANYFRAME( style, exStyle ))
120 rect->bottom++;
125 /******************************************************************************
126 * NC_AdjustRectOuter95
128 * Computes the size of the "outside" parts of the window based on the
129 * parameters of the client area.
131 + PARAMS
132 * LPRECT16 rect
133 * DWORD style
134 * BOOL menu
135 * DWORD exStyle
137 * NOTES
138 * "Outer" parts of a window means the whole window frame, caption and
139 * menu bar. It does not include "inner" parts of the frame like client
140 * edge, static edge or scroll bars.
142 * Revision history
143 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
144 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
146 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
147 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
148 * NC_AdjustRectInner95 and added handling of Win95 styles.
150 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
151 * Streamlined window style checks.
153 *****************************************************************************/
155 static void
156 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
158 int adjust;
159 if(style & WS_ICONIC) return;
161 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
162 WS_EX_STATICEDGE)
164 adjust = 1; /* for the outer frame always present */
166 else
168 adjust = 0;
169 if ((exStyle & WS_EX_DLGMODALFRAME) ||
170 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
172 if (style & WS_THICKFRAME)
173 adjust += ( GetSystemMetrics (SM_CXFRAME)
174 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
175 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
176 (exStyle & WS_EX_DLGMODALFRAME))
177 adjust++; /* The other border */
179 InflateRect (rect, adjust, adjust);
181 if ((style & WS_CAPTION) == WS_CAPTION)
183 if (exStyle & WS_EX_TOOLWINDOW)
184 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
185 else
186 rect->top -= GetSystemMetrics(SM_CYCAPTION);
188 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
192 /******************************************************************************
193 * NC_AdjustRectInner95
195 * Computes the size of the "inside" part of the window based on the
196 * parameters of the client area.
198 + PARAMS
199 * LPRECT16 rect
200 * DWORD style
201 * DWORD exStyle
203 * NOTES
204 * "Inner" part of a window means the window frame inside of the flat
205 * window frame. It includes the client edge, the static edge and the
206 * scroll bars.
208 * Revision history
209 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
210 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
212 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
213 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
214 * NC_AdjustRectInner95 and added handling of Win95 styles.
216 *****************************************************************************/
218 static void
219 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
221 if(style & WS_ICONIC) return;
223 if (exStyle & WS_EX_CLIENTEDGE)
224 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
226 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
227 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
232 static HICON NC_IconForWindow( HWND hwnd )
234 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
235 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
237 /* If there is no hIcon specified and this is a modal dialog,
238 * get the default one.
240 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
241 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
242 return hIcon;
245 /***********************************************************************
246 * DrawCaption (USER32.@) Draws a caption bar
248 * PARAMS
249 * hwnd [I]
250 * hdc [I]
251 * lpRect [I]
252 * uFlags [I]
254 * RETURNS
255 * Success:
256 * Failure:
259 BOOL WINAPI
260 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
262 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
266 /***********************************************************************
267 * DrawCaptionTempA (USER32.@)
269 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
270 HICON hIcon, LPCSTR str, UINT uFlags)
272 LPWSTR strW;
273 INT len;
274 BOOL ret = FALSE;
276 if (!(uFlags & DC_TEXT) || !str)
277 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
279 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
280 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
282 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
283 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
284 HeapFree( GetProcessHeap (), 0, strW );
286 return ret;
290 /***********************************************************************
291 * DrawCaptionTempW (USER32.@)
293 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
294 HICON hIcon, LPCWSTR str, UINT uFlags)
296 RECT rc = *rect;
298 TRACE("(%08x,%08x,%p,%08x,%08x,%s,%08x)\n",
299 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
301 /* drawing background */
302 if (uFlags & DC_INBUTTON) {
303 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
305 if (uFlags & DC_ACTIVE) {
306 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
307 PatBlt (hdc, rc.left, rc.top,
308 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
309 SelectObject (hdc, hbr);
312 else {
313 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
314 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
318 /* drawing icon */
319 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
320 POINT pt;
322 pt.x = rc.left + 2;
323 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
325 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
326 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
327 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
328 rc.left += (rc.bottom - rc.top);
331 /* drawing text */
332 if (uFlags & DC_TEXT) {
333 HFONT hOldFont;
335 if (uFlags & DC_INBUTTON)
336 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
337 else if (uFlags & DC_ACTIVE)
338 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
339 else
340 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
342 SetBkMode (hdc, TRANSPARENT);
344 if (hFont)
345 hOldFont = SelectObject (hdc, hFont);
346 else {
347 NONCLIENTMETRICSA nclm;
348 HFONT hNewFont;
349 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
350 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
351 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
352 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
353 hOldFont = SelectObject (hdc, hNewFont);
356 if (str)
357 DrawTextW (hdc, str, -1, &rc,
358 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
359 else {
360 WCHAR szText[128];
361 INT nLen;
362 nLen = GetWindowTextW (hwnd, szText, 128);
363 DrawTextW (hdc, szText, nLen, &rc,
364 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
367 if (hFont)
368 SelectObject (hdc, hOldFont);
369 else
370 DeleteObject (SelectObject (hdc, hOldFont));
373 /* drawing focus ??? */
374 if (uFlags & 0x2000)
375 FIXME("undocumented flag (0x2000)!\n");
377 return 0;
381 /***********************************************************************
382 * AdjustWindowRect (USER.102)
384 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
386 return AdjustWindowRectEx16( rect, style, menu, 0 );
390 /***********************************************************************
391 * AdjustWindowRect (USER32.@)
393 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
395 return AdjustWindowRectEx( rect, style, menu, 0 );
399 /***********************************************************************
400 * AdjustWindowRectEx (USER.454)
402 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
403 BOOL16 menu, DWORD exStyle )
405 RECT rect32;
406 BOOL ret;
408 CONV_RECT16TO32( rect, &rect32 );
409 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
410 CONV_RECT32TO16( &rect32, rect );
411 return ret;
415 /***********************************************************************
416 * AdjustWindowRectEx (USER32.@)
418 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
420 /* Correct the window style */
421 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
422 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
423 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
424 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
426 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
427 rect->left, rect->top, rect->right, rect->bottom,
428 style, menu, exStyle );
430 if (TWEAK_WineLook == WIN31_LOOK)
431 NC_AdjustRect( rect, style, menu, exStyle );
432 else
434 NC_AdjustRectOuter95( rect, style, menu, exStyle );
435 NC_AdjustRectInner95( rect, style, exStyle );
437 return TRUE;
441 /***********************************************************************
442 * NC_HandleNCCalcSize
444 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
446 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
448 RECT tmpRect = { 0, 0, 0, 0 };
449 LONG result = 0;
450 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
451 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
452 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
454 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
455 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
457 if (!IsIconic(hwnd))
459 if (TWEAK_WineLook == WIN31_LOOK)
460 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
461 else
462 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
464 winRect->left -= tmpRect.left;
465 winRect->top -= tmpRect.top;
466 winRect->right -= tmpRect.right;
467 winRect->bottom -= tmpRect.bottom;
469 if (!(style & WS_CHILD) && GetMenu(hwnd))
471 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
472 "at (%d, %d).\n", hwnd,
473 winRect->right - winRect->left,
474 -tmpRect.left, -tmpRect.top );
476 winRect->top +=
477 MENU_GetMenuBarHeight( hwnd,
478 winRect->right - winRect->left,
479 -tmpRect.left, -tmpRect.top ) + 1;
482 if (TWEAK_WineLook > WIN31_LOOK) {
483 SetRect(&tmpRect, 0, 0, 0, 0);
484 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
485 winRect->left -= tmpRect.left;
486 winRect->top -= tmpRect.top;
487 winRect->right -= tmpRect.right;
488 winRect->bottom -= tmpRect.bottom;
491 if (winRect->top > winRect->bottom)
492 winRect->bottom = winRect->top;
494 if (winRect->left > winRect->right)
495 winRect->right = winRect->left;
497 return result;
501 /***********************************************************************
502 * NC_GetInsideRect
504 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
505 * but without the borders (if any).
506 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
508 void NC_GetInsideRect( HWND hwnd, RECT *rect )
510 WND * wndPtr = WIN_FindWndPtr( hwnd );
512 rect->top = rect->left = 0;
513 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
514 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
516 if (wndPtr->dwStyle & WS_ICONIC) goto END;
518 /* Remove frame from rectangle */
519 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
521 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
523 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
525 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
526 /* FIXME: this isn't in NC_AdjustRect? why not? */
527 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
528 InflateRect( rect, -1, 0 );
530 else if (HAS_THINFRAME( wndPtr->dwStyle ))
532 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
535 /* We have additional border information if the window
536 * is a child (but not an MDI child) */
537 if (TWEAK_WineLook != WIN31_LOOK)
539 if ( (wndPtr->dwStyle & WS_CHILD) &&
540 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
542 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
543 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
544 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
545 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
549 END:
550 WIN_ReleaseWndPtr(wndPtr);
551 return;
555 /***********************************************************************
556 * NC_DoNCHitTest
558 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
561 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
563 RECT rect;
565 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
567 GetWindowRect(wndPtr->hwndSelf, &rect );
568 if (!PtInRect( &rect, pt )) return HTNOWHERE;
570 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
572 /* Check borders */
573 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
575 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
576 if (!PtInRect( &rect, pt ))
578 /* Check top sizing border */
579 if (pt.y < rect.top)
581 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
582 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
583 return HTTOP;
585 /* Check bottom sizing border */
586 if (pt.y >= rect.bottom)
588 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
589 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
590 return HTBOTTOM;
592 /* Check left sizing border */
593 if (pt.x < rect.left)
595 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
596 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
597 return HTLEFT;
599 /* Check right sizing border */
600 if (pt.x >= rect.right)
602 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
603 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
604 return HTRIGHT;
608 else /* No thick frame */
610 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
611 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
612 else if (HAS_THINFRAME( wndPtr->dwStyle ))
613 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
614 if (!PtInRect( &rect, pt )) return HTBORDER;
617 /* Check caption */
619 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
621 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
622 if (!PtInRect( &rect, pt ))
624 /* Check system menu */
625 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
626 rect.left += GetSystemMetrics(SM_CXSIZE);
627 if (pt.x <= rect.left) return HTSYSMENU;
629 /* Check maximize box */
630 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
631 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
633 if (pt.x >= rect.right) return HTMAXBUTTON;
634 /* Check minimize box */
635 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
636 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
637 if (pt.x >= rect.right) return HTMINBUTTON;
638 return HTCAPTION;
642 /* Check client area */
644 ScreenToClient( wndPtr->hwndSelf, &pt );
645 GetClientRect( wndPtr->hwndSelf, &rect );
646 if (PtInRect( &rect, pt )) return HTCLIENT;
648 /* Check vertical scroll bar */
650 if (wndPtr->dwStyle & WS_VSCROLL)
652 rect.right += GetSystemMetrics(SM_CXVSCROLL);
653 if (PtInRect( &rect, pt )) return HTVSCROLL;
656 /* Check horizontal scroll bar */
658 if (wndPtr->dwStyle & WS_HSCROLL)
660 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
661 if (PtInRect( &rect, pt ))
663 /* Check size box */
664 if ((wndPtr->dwStyle & WS_VSCROLL) &&
665 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
666 return HTSIZE;
667 return HTHSCROLL;
671 /* Check menu bar */
673 if (HAS_MENU(wndPtr))
675 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
676 return HTMENU;
679 /* Has to return HTNOWHERE if nothing was found
680 Could happen when a window has a customized non client area */
681 return HTNOWHERE;
685 /***********************************************************************
686 * NC_DoNCHitTest95
688 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
690 * FIXME: Just a modified copy of the Win 3.1 version.
693 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
695 RECT rect;
697 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
699 GetWindowRect(wndPtr->hwndSelf, &rect );
700 if (!PtInRect( &rect, pt )) return HTNOWHERE;
702 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
704 /* Check borders */
705 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
707 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
708 if (!PtInRect( &rect, pt ))
710 /* Check top sizing border */
711 if (pt.y < rect.top)
713 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
714 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
715 return HTTOP;
717 /* Check bottom sizing border */
718 if (pt.y >= rect.bottom)
720 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
721 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
722 return HTBOTTOM;
724 /* Check left sizing border */
725 if (pt.x < rect.left)
727 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
728 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
729 return HTLEFT;
731 /* Check right sizing border */
732 if (pt.x >= rect.right)
734 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
735 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
736 return HTRIGHT;
740 else /* No thick frame */
742 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
743 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
744 else if (HAS_THINFRAME( wndPtr->dwStyle ))
745 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
746 if (!PtInRect( &rect, pt )) return HTBORDER;
749 /* Check caption */
751 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
753 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
754 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
755 else
756 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
757 if (!PtInRect( &rect, pt ))
759 /* Check system menu */
760 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
762 if (NC_IconForWindow(wndPtr->hwndSelf))
763 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
765 if (pt.x < rect.left) return HTSYSMENU;
767 /* Check close button */
768 if (wndPtr->dwStyle & WS_SYSMENU)
769 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
770 if (pt.x > rect.right) return HTCLOSE;
772 /* Check maximize box */
773 /* In win95 there is automatically a Maximize button when there is a minimize one*/
774 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
775 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
776 if (pt.x > rect.right) return HTMAXBUTTON;
778 /* Check minimize box */
779 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
780 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
781 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
783 if (pt.x > rect.right) return HTMINBUTTON;
784 return HTCAPTION;
788 /* Check client area */
790 ScreenToClient( wndPtr->hwndSelf, &pt );
791 GetClientRect( wndPtr->hwndSelf, &rect );
792 if (PtInRect( &rect, pt )) return HTCLIENT;
794 /* Check vertical scroll bar */
796 if (wndPtr->dwStyle & WS_VSCROLL)
798 rect.right += GetSystemMetrics(SM_CXVSCROLL);
799 if (PtInRect( &rect, pt )) return HTVSCROLL;
802 /* Check horizontal scroll bar */
804 if (wndPtr->dwStyle & WS_HSCROLL)
806 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
807 if (PtInRect( &rect, pt ))
809 /* Check size box */
810 if ((wndPtr->dwStyle & WS_VSCROLL) &&
811 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
812 return HTSIZE;
813 return HTHSCROLL;
817 /* Check menu bar */
819 if (HAS_MENU(wndPtr))
821 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
822 return HTMENU;
825 /* Has to return HTNOWHERE if nothing was found
826 Could happen when a window has a customized non client area */
827 return HTNOWHERE;
831 /***********************************************************************
832 * NC_HandleNCHitTest
834 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
836 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
838 LONG retvalue;
839 WND *wndPtr = WIN_FindWndPtr (hwnd);
841 if (!wndPtr)
842 return HTERROR;
844 if (TWEAK_WineLook == WIN31_LOOK)
845 retvalue = NC_DoNCHitTest (wndPtr, pt);
846 else
847 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
848 WIN_ReleaseWndPtr(wndPtr);
849 return retvalue;
853 /***********************************************************************
854 * NC_DrawSysButton
856 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
858 RECT rect;
859 HDC hdcMem;
860 HBITMAP hbitmap;
862 NC_GetInsideRect( hwnd, &rect );
863 hdcMem = CreateCompatibleDC( hdc );
864 hbitmap = SelectObject( hdcMem, hbitmapClose );
865 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
866 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
867 down ? NOTSRCCOPY : SRCCOPY );
868 SelectObject( hdcMem, hbitmap );
869 DeleteDC( hdcMem );
873 /***********************************************************************
874 * NC_DrawMaxButton
876 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
878 RECT rect;
879 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
881 NC_GetInsideRect( hwnd, &rect );
882 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
883 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
884 rect.top += 1;
885 rect.right -= 1;
886 if (down) flags |= DFCS_PUSHED;
887 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
891 /***********************************************************************
892 * NC_DrawMinButton
894 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
896 RECT rect;
897 UINT flags = DFCS_CAPTIONMIN;
898 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
900 NC_GetInsideRect( hwnd, &rect );
901 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
902 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
903 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
904 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
905 rect.top += 1;
906 rect.right -= 1;
907 if (down) flags |= DFCS_PUSHED;
908 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
912 /******************************************************************************
914 * void NC_DrawSysButton95(
915 * HWND hwnd,
916 * HDC hdc,
917 * BOOL down )
919 * Draws the Win95 system icon.
921 * Revision history
922 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
923 * Original implementation from NC_DrawSysButton source.
924 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
925 * Fixed most bugs.
927 *****************************************************************************/
929 BOOL
930 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
932 HICON hIcon = NC_IconForWindow( hwnd );
934 if (hIcon)
936 RECT rect;
937 NC_GetInsideRect( hwnd, &rect );
938 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
939 GetSystemMetrics(SM_CXSMICON),
940 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
942 return (hIcon != 0);
946 /******************************************************************************
948 * void NC_DrawCloseButton95(
949 * HWND hwnd,
950 * HDC hdc,
951 * BOOL down,
952 * BOOL bGrayed )
954 * Draws the Win95 close button.
956 * If bGrayed is true, then draw a disabled Close button
958 * Revision history
959 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
960 * Original implementation from NC_DrawSysButton95 source.
962 *****************************************************************************/
964 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
966 RECT rect;
968 NC_GetInsideRect( hwnd, &rect );
970 /* A tool window has a smaller Close button */
971 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
973 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
974 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
975 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
977 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
978 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
979 rect.bottom = rect.top + iBmpHeight;
980 rect.right = rect.left + iBmpWidth;
982 else
984 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
985 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
986 rect.top += 2;
987 rect.right -= 2;
989 DrawFrameControl( hdc, &rect, DFC_CAPTION,
990 (DFCS_CAPTIONCLOSE |
991 (down ? DFCS_PUSHED : 0) |
992 (bGrayed ? DFCS_INACTIVE : 0)) );
995 /******************************************************************************
996 * NC_DrawMaxButton95
998 * Draws the maximize button for Win95 style windows.
999 * If bGrayed is true, then draw a disabled Maximize button
1001 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1003 RECT rect;
1004 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1006 NC_GetInsideRect( hwnd, &rect );
1007 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1008 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1009 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1010 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1011 rect.top += 2;
1012 rect.right -= 2;
1013 if (down) flags |= DFCS_PUSHED;
1014 if (bGrayed) flags |= DFCS_INACTIVE;
1015 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1018 /******************************************************************************
1019 * NC_DrawMinButton95
1021 * Draws the minimize button for Win95 style windows.
1022 * If bGrayed is true, then draw a disabled Minimize button
1024 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1026 RECT rect;
1027 UINT flags = DFCS_CAPTIONMIN;
1028 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1030 NC_GetInsideRect( hwnd, &rect );
1031 if (style & WS_SYSMENU)
1032 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1033 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1034 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1035 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1036 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1037 rect.top += 2;
1038 rect.right -= 2;
1039 if (down) flags |= DFCS_PUSHED;
1040 if (bGrayed) flags |= DFCS_INACTIVE;
1041 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1044 /***********************************************************************
1045 * NC_DrawFrame
1047 * Draw a window frame inside the given rectangle, and update the rectangle.
1048 * The correct pen for the frame must be selected in the DC.
1050 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1051 BOOL active )
1053 INT width, height;
1055 if (TWEAK_WineLook != WIN31_LOOK)
1056 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1058 if (dlgFrame)
1060 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1061 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1062 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1063 COLOR_INACTIVECAPTION) );
1065 else
1067 width = GetSystemMetrics(SM_CXFRAME) - 2;
1068 height = GetSystemMetrics(SM_CYFRAME) - 2;
1069 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1070 COLOR_INACTIVEBORDER) );
1073 /* Draw frame */
1074 PatBlt( hdc, rect->left, rect->top,
1075 rect->right - rect->left, height, PATCOPY );
1076 PatBlt( hdc, rect->left, rect->top,
1077 width, rect->bottom - rect->top, PATCOPY );
1078 PatBlt( hdc, rect->left, rect->bottom - 1,
1079 rect->right - rect->left, -height, PATCOPY );
1080 PatBlt( hdc, rect->right - 1, rect->top,
1081 -width, rect->bottom - rect->top, PATCOPY );
1083 if (dlgFrame)
1085 InflateRect( rect, -width, -height );
1087 else
1089 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1090 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1092 /* Draw inner rectangle */
1094 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1095 Rectangle( hdc, rect->left + width, rect->top + height,
1096 rect->right - width , rect->bottom - height );
1098 /* Draw the decorations */
1100 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1101 LineTo( hdc, rect->left + width, rect->top + decYOff );
1102 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1103 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1104 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1105 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1106 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1107 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1109 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1110 LineTo( hdc, rect->left + decXOff, rect->top + height);
1111 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1112 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1113 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1114 LineTo( hdc, rect->right - decXOff, rect->top + height );
1115 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1116 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1118 InflateRect( rect, -width - 1, -height - 1 );
1123 /******************************************************************************
1125 * void NC_DrawFrame95(
1126 * HDC hdc,
1127 * RECT *rect,
1128 * BOOL active,
1129 * DWORD style,
1130 * DWORD exStyle )
1132 * Draw a window frame inside the given rectangle, and update the rectangle.
1134 * Bugs
1135 * Many. First, just what IS a frame in Win95? Note that the 3D look
1136 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1137 * edge. The inner rectangle just inside the frame is handled by the
1138 * Caption code.
1140 * In short, for most people, this function should be a nop (unless
1141 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1142 * them lately, but just to get this code right). Even so, it doesn't
1143 * appear to be so. It's being worked on...
1145 * Revision history
1146 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1147 * Original implementation (based on NC_DrawFrame)
1148 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1149 * Some minor fixes.
1150 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1151 * Fixed a fix or something.
1153 *****************************************************************************/
1155 static void NC_DrawFrame95(
1156 HDC hdc,
1157 RECT *rect,
1158 BOOL active,
1159 DWORD style,
1160 DWORD exStyle)
1162 INT width, height;
1164 /* Firstly the "thick" frame */
1165 if (style & WS_THICKFRAME)
1167 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1168 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1170 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1171 COLOR_INACTIVEBORDER) );
1172 /* Draw frame */
1173 PatBlt( hdc, rect->left, rect->top,
1174 rect->right - rect->left, height, PATCOPY );
1175 PatBlt( hdc, rect->left, rect->top,
1176 width, rect->bottom - rect->top, PATCOPY );
1177 PatBlt( hdc, rect->left, rect->bottom - 1,
1178 rect->right - rect->left, -height, PATCOPY );
1179 PatBlt( hdc, rect->right - 1, rect->top,
1180 -width, rect->bottom - rect->top, PATCOPY );
1182 InflateRect( rect, -width, -height );
1185 /* Now the other bit of the frame */
1186 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1187 (exStyle & WS_EX_DLGMODALFRAME))
1189 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1190 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1191 /* This should give a value of 1 that should also work for a border */
1193 SelectObject( hdc, GetSysColorBrush(
1194 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1195 COLOR_3DFACE :
1196 (exStyle & WS_EX_STATICEDGE) ?
1197 COLOR_WINDOWFRAME :
1198 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1199 COLOR_3DFACE :
1200 /* else */
1201 COLOR_WINDOWFRAME));
1203 /* Draw frame */
1204 PatBlt( hdc, rect->left, rect->top,
1205 rect->right - rect->left, height, PATCOPY );
1206 PatBlt( hdc, rect->left, rect->top,
1207 width, rect->bottom - rect->top, PATCOPY );
1208 PatBlt( hdc, rect->left, rect->bottom - 1,
1209 rect->right - rect->left, -height, PATCOPY );
1210 PatBlt( hdc, rect->right - 1, rect->top,
1211 -width, rect->bottom - rect->top, PATCOPY );
1213 InflateRect( rect, -width, -height );
1218 /***********************************************************************
1219 * NC_DrawCaption
1221 * Draw the window caption.
1222 * The correct pen for the window frame must be selected in the DC.
1224 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1225 DWORD style, BOOL active )
1227 RECT r = *rect;
1228 char buffer[256];
1230 if (!hbitmapClose)
1232 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1235 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1237 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1238 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1239 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1240 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1241 r.left++;
1242 r.right--;
1243 SelectObject( hdc, hbrushOld );
1245 MoveToEx( hdc, r.left, r.bottom, NULL );
1246 LineTo( hdc, r.right, r.bottom );
1248 if (style & WS_SYSMENU)
1250 NC_DrawSysButton( hwnd, hdc, FALSE );
1251 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1252 MoveToEx( hdc, r.left - 1, r.top, NULL );
1253 LineTo( hdc, r.left - 1, r.bottom );
1255 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1256 if (style & WS_MAXIMIZEBOX)
1258 NC_DrawMaxButton( hwnd, hdc, FALSE );
1259 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1261 if (style & WS_MINIMIZEBOX)
1263 NC_DrawMinButton( hwnd, hdc, FALSE );
1264 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1267 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1269 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1270 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1271 SetBkMode( hdc, TRANSPARENT );
1272 DrawTextA( hdc, buffer, -1, &r,
1273 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1278 /******************************************************************************
1280 * NC_DrawCaption95(
1281 * HDC hdc,
1282 * RECT *rect,
1283 * HWND hwnd,
1284 * DWORD style,
1285 * BOOL active )
1287 * Draw the window caption for Win95 style windows.
1288 * The correct pen for the window frame must be selected in the DC.
1290 * Bugs
1291 * Hey, a function that finally works! Well, almost.
1292 * It's being worked on.
1294 * Revision history
1295 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1296 * Original implementation.
1297 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1298 * Some minor fixes.
1300 *****************************************************************************/
1302 static void NC_DrawCaption95(
1303 HDC hdc,
1304 RECT *rect,
1305 HWND hwnd,
1306 DWORD style,
1307 DWORD exStyle,
1308 BOOL active )
1310 RECT r = *rect;
1311 char buffer[256];
1312 HPEN hPrevPen;
1313 HMENU hSysMenu;
1315 hPrevPen = SelectObject( hdc, GetSysColorPen(
1316 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1317 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1318 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1319 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1320 LineTo( hdc, r.right, r.bottom - 1 );
1321 SelectObject( hdc, hPrevPen );
1322 r.bottom--;
1324 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1325 COLOR_INACTIVECAPTION) );
1327 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1328 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1329 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1332 if (style & WS_SYSMENU)
1334 UINT state;
1336 /* Go get the sysmenu */
1337 hSysMenu = GetSystemMenu(hwnd, FALSE);
1338 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1340 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1341 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1342 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1343 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1345 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1347 /* In win95 the two buttons are always there */
1348 /* But if the menu item is not in the menu they're disabled*/
1350 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1351 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1353 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1354 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1358 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1359 NONCLIENTMETRICSA nclm;
1360 HFONT hFont, hOldFont;
1361 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1362 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1363 if (exStyle & WS_EX_TOOLWINDOW)
1364 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1365 else
1366 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1367 hOldFont = SelectObject (hdc, hFont);
1368 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1369 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1370 SetBkMode( hdc, TRANSPARENT );
1371 r.left += 2;
1372 DrawTextA( hdc, buffer, -1, &r,
1373 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1374 DeleteObject (SelectObject (hdc, hOldFont));
1380 /***********************************************************************
1381 * NC_DoNCPaint
1383 * Paint the non-client area. clip is currently unused.
1385 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1387 HDC hdc;
1388 RECT rect;
1389 BOOL active;
1390 WND *wndPtr;
1391 DWORD dwStyle, dwExStyle;
1392 WORD flags;
1393 RECT rectClient, rectWindow;
1394 int has_menu;
1396 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1397 has_menu = HAS_MENU(wndPtr);
1398 dwStyle = wndPtr->dwStyle;
1399 dwExStyle = wndPtr->dwExStyle;
1400 flags = wndPtr->flags;
1401 rectClient = wndPtr->rectClient;
1402 rectWindow = wndPtr->rectWindow;
1403 WIN_ReleasePtr( wndPtr );
1405 if ( dwStyle & WS_MINIMIZE ||
1406 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1408 active = flags & WIN_NCACTIVATED;
1410 TRACE("%04x %d\n", hwnd, active );
1412 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1413 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1415 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1416 rectClient.top-rectWindow.top,
1417 rectClient.right-rectWindow.left,
1418 rectClient.bottom-rectWindow.top )
1419 == NULLREGION)
1421 ReleaseDC( hwnd, hdc );
1422 return;
1425 rect.top = rect.left = 0;
1426 rect.right = rectWindow.right - rectWindow.left;
1427 rect.bottom = rectWindow.bottom - rectWindow.top;
1429 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1431 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1433 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1434 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1435 InflateRect( &rect, -1, -1 );
1438 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1439 NC_DrawFrame(hdc, &rect, FALSE, active );
1440 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1441 NC_DrawFrame( hdc, &rect, TRUE, active );
1443 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1445 RECT r = rect;
1446 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1447 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1448 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1451 if (has_menu)
1453 RECT r = rect;
1454 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1455 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1458 /* Draw the scroll-bars */
1460 if (dwStyle & WS_VSCROLL)
1461 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1462 if (dwStyle & WS_HSCROLL)
1463 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1465 /* Draw the "size-box" */
1467 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1469 RECT r = rect;
1470 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1471 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1472 if(wndPtr->dwStyle & WS_BORDER) {
1473 r.left++;
1474 r.top++;
1476 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1479 ReleaseDC( hwnd, hdc );
1483 /******************************************************************************
1485 * void NC_DoNCPaint95(
1486 * HWND hwnd,
1487 * HRGN clip,
1488 * BOOL suppress_menupaint )
1490 * Paint the non-client area for Win95 windows. The clip region is
1491 * currently ignored.
1493 * Bugs
1494 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1495 * misc/tweak.c controls/menu.c # :-)
1497 * Revision history
1498 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1499 * Original implementation
1500 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1501 * Fixed some bugs.
1502 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1503 * Streamlined window style checks.
1505 *****************************************************************************/
1507 static void NC_DoNCPaint95(
1508 HWND hwnd,
1509 HRGN clip,
1510 BOOL suppress_menupaint )
1512 HDC hdc;
1513 RECT rfuzz, rect, rectClip;
1514 BOOL active;
1515 WND *wndPtr;
1516 DWORD dwStyle, dwExStyle;
1517 WORD flags;
1518 RECT rectClient, rectWindow;
1519 int has_menu;
1521 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1522 has_menu = HAS_MENU(wndPtr);
1523 dwStyle = wndPtr->dwStyle;
1524 dwExStyle = wndPtr->dwExStyle;
1525 flags = wndPtr->flags;
1526 rectClient = wndPtr->rectClient;
1527 rectWindow = wndPtr->rectWindow;
1528 WIN_ReleasePtr( wndPtr );
1530 if ( dwStyle & WS_MINIMIZE ||
1531 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1533 active = flags & WIN_NCACTIVATED;
1535 TRACE("%04x %d\n", hwnd, active );
1537 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1538 the call to GetDCEx implying that it is allowed not to use it either.
1539 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1540 will cause clipRgn to be deleted after ReleaseDC().
1541 Now, how is the "system" supposed to tell what happened?
1544 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1545 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1548 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1549 rectClient.top-rectWindow.top,
1550 rectClient.right-rectWindow.left,
1551 rectClient.bottom-rectWindow.top )
1552 == NULLREGION)
1554 ReleaseDC( hwnd, hdc );
1555 return;
1558 rect.top = rect.left = 0;
1559 rect.right = rectWindow.right - rectWindow.left;
1560 rect.bottom = rectWindow.bottom - rectWindow.top;
1562 if( clip > 1 )
1563 GetRgnBox( clip, &rectClip );
1564 else
1566 clip = 0;
1567 rectClip = rect;
1570 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1572 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1573 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1575 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1576 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1579 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1581 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1583 RECT r = rect;
1584 if (dwExStyle & WS_EX_TOOLWINDOW) {
1585 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1586 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1588 else {
1589 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1590 rect.top += GetSystemMetrics(SM_CYCAPTION);
1592 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1593 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1594 dwExStyle, active);
1597 if (has_menu)
1599 RECT r = rect;
1600 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1602 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1603 r.left, r.top, r.right, r.bottom);
1605 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1608 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1609 rect.left, rect.top, rect.right, rect.bottom );
1611 if (dwExStyle & WS_EX_CLIENTEDGE)
1612 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1614 /* Draw the scroll-bars */
1616 if (dwStyle & WS_VSCROLL)
1617 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1618 if (dwStyle & WS_HSCROLL)
1619 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1621 /* Draw the "size-box" */
1622 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1624 RECT r = rect;
1625 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1626 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1627 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1630 ReleaseDC( hwnd, hdc );
1636 /***********************************************************************
1637 * NC_HandleNCPaint
1639 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1641 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1643 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1645 if( dwStyle & WS_VISIBLE )
1647 if( dwStyle & WS_MINIMIZE )
1648 WINPOS_RedrawIconTitle( hwnd );
1649 else if (TWEAK_WineLook == WIN31_LOOK)
1650 NC_DoNCPaint( hwnd, clip, FALSE );
1651 else
1652 NC_DoNCPaint95( hwnd, clip, FALSE );
1654 return 0;
1658 /***********************************************************************
1659 * NC_HandleNCActivate
1661 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1663 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1665 WND* wndPtr = WIN_FindWndPtr( hwnd );
1667 /* Lotus Notes draws menu descriptions in the caption of its main
1668 * window. When it wants to restore original "system" view, it just
1669 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1670 * attempt to minimize redrawings lead to a not restored caption.
1672 if (wndPtr)
1674 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1675 else wndPtr->flags &= ~WIN_NCACTIVATED;
1676 WIN_ReleaseWndPtr(wndPtr);
1678 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1679 else if (TWEAK_WineLook == WIN31_LOOK)
1680 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1681 else
1682 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1684 return TRUE;
1688 /***********************************************************************
1689 * NC_HandleSetCursor
1691 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1693 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1695 if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1696 return 0; /* Don't set the cursor for child windows */
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, "Wine", WINE_RELEASE_INFO, 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;