Added, update information about AppDefault.
[wine/wine64.git] / windows / nonclient.c
blob1da7c36717979f56453e3f80591bdc7b06fe4e42
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 */
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "version.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "controls.h"
16 #include "cursoricon.h"
17 #include "winpos.h"
18 #include "hook.h"
19 #include "nonclient.h"
20 #include "debugtools.h"
21 #include "shellapi.h"
22 #include "bitmap.h"
24 DEFAULT_DEBUG_CHANNEL(nonclient);
25 DECLARE_DEBUG_CHANNEL(shell);
27 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
29 static HBITMAP hbitmapClose;
31 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
32 0x55, 0x50,
33 0xAA, 0xA0,
34 0x55, 0x50,
35 0xAA, 0xA0,
36 0x55, 0x50,
37 0xAA, 0xA0,
38 0x55, 0x50,
39 0xAA, 0xA0,
40 0x55, 0x50};
42 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
43 #define SC_PUTMARK (SC_SCREENSAVE+2)
45 /* Some useful macros */
46 #define HAS_DLGFRAME(style,exStyle) \
47 (((exStyle) & WS_EX_DLGMODALFRAME) || \
48 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
50 #define HAS_THICKFRAME(style,exStyle) \
51 (((style) & WS_THICKFRAME) && \
52 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
54 #define HAS_THINFRAME(style) \
55 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
57 #define HAS_BIGFRAME(style,exStyle) \
58 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
59 ((exStyle) & WS_EX_DLGMODALFRAME))
61 #define HAS_STATICOUTERFRAME(style,exStyle) \
62 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
63 WS_EX_STATICEDGE)
65 #define HAS_ANYFRAME(style,exStyle) \
66 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
67 ((exStyle) & WS_EX_DLGMODALFRAME) || \
68 !((style) & (WS_CHILD | WS_POPUP)))
70 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
73 /***********************************************************************
74 * NC_AdjustRect
76 * Compute the size of the window rectangle from the size of the
77 * client rectangle.
79 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
81 if (TWEAK_WineLook > WIN31_LOOK)
82 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
84 if(style & WS_ICONIC) return;
86 if (HAS_THICKFRAME( style, exStyle ))
87 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
88 else if (HAS_DLGFRAME( style, exStyle ))
89 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
90 else if (HAS_THINFRAME( style ))
91 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
93 if ((style & WS_CAPTION) == WS_CAPTION)
94 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
96 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
98 if (style & WS_VSCROLL) {
99 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
100 if(!HAS_ANYFRAME( style, exStyle ))
101 rect->right++;
104 if (style & WS_HSCROLL) {
105 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
106 if(!HAS_ANYFRAME( style, exStyle ))
107 rect->bottom++;
112 /******************************************************************************
113 * NC_AdjustRectOuter95
115 * Computes the size of the "outside" parts of the window based on the
116 * parameters of the client area.
118 + PARAMS
119 * LPRECT16 rect
120 * DWORD style
121 * BOOL menu
122 * DWORD exStyle
124 * NOTES
125 * "Outer" parts of a window means the whole window frame, caption and
126 * menu bar. It does not include "inner" parts of the frame like client
127 * edge, static edge or scroll bars.
129 * Revision history
130 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
131 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
133 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
134 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
135 * NC_AdjustRectInner95 and added handling of Win95 styles.
137 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
138 * Streamlined window style checks.
140 *****************************************************************************/
142 static void
143 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
145 int adjust;
146 if(style & WS_ICONIC) return;
148 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
149 WS_EX_STATICEDGE)
151 adjust = 1; /* for the outer frame always present */
153 else
155 adjust = 0;
156 if ((exStyle & WS_EX_DLGMODALFRAME) ||
157 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
159 if (style & WS_THICKFRAME)
160 adjust += ( GetSystemMetrics (SM_CXFRAME)
161 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
162 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
163 (exStyle & WS_EX_DLGMODALFRAME))
164 adjust++; /* The other border */
166 InflateRect (rect, adjust, adjust);
168 if ((style & WS_CAPTION) == WS_CAPTION)
170 if (exStyle & WS_EX_TOOLWINDOW)
171 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
172 else
173 rect->top -= GetSystemMetrics(SM_CYCAPTION);
175 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
179 /******************************************************************************
180 * NC_AdjustRectInner95
182 * Computes the size of the "inside" part of the window based on the
183 * parameters of the client area.
185 + PARAMS
186 * LPRECT16 rect
187 * DWORD style
188 * DWORD exStyle
190 * NOTES
191 * "Inner" part of a window means the window frame inside of the flat
192 * window frame. It includes the client edge, the static edge and the
193 * scroll bars.
195 * Revision history
196 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
197 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
199 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
200 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
201 * NC_AdjustRectInner95 and added handling of Win95 styles.
203 *****************************************************************************/
205 static void
206 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
208 if(style & WS_ICONIC) return;
210 if (exStyle & WS_EX_CLIENTEDGE)
211 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
213 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
214 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
219 static HICON NC_IconForWindow( HWND hwnd )
221 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
222 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
224 /* If there is no hIcon specified and this is a modal dialog,
225 * get the default one.
227 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
228 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
229 return hIcon;
232 /***********************************************************************
233 * DrawCaption (USER32.@) Draws a caption bar
235 * PARAMS
236 * hwnd [I]
237 * hdc [I]
238 * lpRect [I]
239 * uFlags [I]
241 * RETURNS
242 * Success:
243 * Failure:
246 BOOL WINAPI
247 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
249 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
253 /***********************************************************************
254 * DrawCaptionTempA (USER32.@)
256 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
257 HICON hIcon, LPCSTR str, UINT uFlags)
259 LPWSTR strW;
260 INT len;
261 BOOL ret = FALSE;
263 if (!(uFlags & DC_TEXT) || !str)
264 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
266 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
267 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
269 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
270 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
271 HeapFree( GetProcessHeap (), 0, strW );
273 return ret;
277 /***********************************************************************
278 * DrawCaptionTempW (USER32.@)
280 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
281 HICON hIcon, LPCWSTR str, UINT uFlags)
283 RECT rc = *rect;
285 TRACE("(%08x,%08x,%p,%08x,%08x,%s,%08x)\n",
286 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
288 /* drawing background */
289 if (uFlags & DC_INBUTTON) {
290 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
292 if (uFlags & DC_ACTIVE) {
293 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
294 PatBlt (hdc, rc.left, rc.top,
295 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
296 SelectObject (hdc, hbr);
299 else {
300 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
301 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
305 /* drawing icon */
306 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
307 POINT pt;
309 pt.x = rc.left + 2;
310 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
312 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
313 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
314 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
315 rc.left += (rc.bottom - rc.top);
318 /* drawing text */
319 if (uFlags & DC_TEXT) {
320 HFONT hOldFont;
322 if (uFlags & DC_INBUTTON)
323 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
324 else if (uFlags & DC_ACTIVE)
325 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
326 else
327 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
329 SetBkMode (hdc, TRANSPARENT);
331 if (hFont)
332 hOldFont = SelectObject (hdc, hFont);
333 else {
334 NONCLIENTMETRICSA nclm;
335 HFONT hNewFont;
336 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
337 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
338 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
339 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
340 hOldFont = SelectObject (hdc, hNewFont);
343 if (str)
344 DrawTextW (hdc, str, -1, &rc,
345 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
346 else {
347 WCHAR szText[128];
348 INT nLen;
349 nLen = GetWindowTextW (hwnd, szText, 128);
350 DrawTextW (hdc, szText, nLen, &rc,
351 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
354 if (hFont)
355 SelectObject (hdc, hOldFont);
356 else
357 DeleteObject (SelectObject (hdc, hOldFont));
360 /* drawing focus ??? */
361 if (uFlags & 0x2000)
362 FIXME("undocumented flag (0x2000)!\n");
364 return 0;
368 /***********************************************************************
369 * AdjustWindowRect (USER.102)
371 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
373 return AdjustWindowRectEx16( rect, style, menu, 0 );
377 /***********************************************************************
378 * AdjustWindowRect (USER32.@)
380 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
382 return AdjustWindowRectEx( rect, style, menu, 0 );
386 /***********************************************************************
387 * AdjustWindowRectEx (USER.454)
389 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
390 BOOL16 menu, DWORD exStyle )
392 RECT rect32;
393 BOOL ret;
395 CONV_RECT16TO32( rect, &rect32 );
396 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
397 CONV_RECT32TO16( &rect32, rect );
398 return ret;
402 /***********************************************************************
403 * AdjustWindowRectEx (USER32.@)
405 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
407 /* Correct the window style */
409 if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
410 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
411 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
412 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
413 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
415 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
416 rect->left, rect->top, rect->right, rect->bottom,
417 style, menu, exStyle );
419 if (TWEAK_WineLook == WIN31_LOOK)
420 NC_AdjustRect( rect, style, menu, exStyle );
421 else
423 NC_AdjustRectOuter95( rect, style, menu, exStyle );
424 NC_AdjustRectInner95( rect, style, exStyle );
426 return TRUE;
430 /***********************************************************************
431 * NC_HandleNCCalcSize
433 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
435 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
437 RECT tmpRect = { 0, 0, 0, 0 };
438 LONG result = 0;
439 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
440 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
441 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
443 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
444 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
446 if (!IsIconic(hwnd))
448 if (TWEAK_WineLook == WIN31_LOOK)
449 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
450 else
451 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
453 winRect->left -= tmpRect.left;
454 winRect->top -= tmpRect.top;
455 winRect->right -= tmpRect.right;
456 winRect->bottom -= tmpRect.bottom;
458 if (!(style & WS_CHILD) && GetMenu(hwnd))
460 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
461 "at (%d, %d).\n", hwnd,
462 winRect->right - winRect->left,
463 -tmpRect.left, -tmpRect.top );
465 winRect->top +=
466 MENU_GetMenuBarHeight( hwnd,
467 winRect->right - winRect->left,
468 -tmpRect.left, -tmpRect.top ) + 1;
471 if (TWEAK_WineLook > WIN31_LOOK) {
472 SetRect(&tmpRect, 0, 0, 0, 0);
473 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
474 winRect->left -= tmpRect.left;
475 winRect->top -= tmpRect.top;
476 winRect->right -= tmpRect.right;
477 winRect->bottom -= tmpRect.bottom;
480 if (winRect->top > winRect->bottom)
481 winRect->bottom = winRect->top;
483 if (winRect->left > winRect->right)
484 winRect->right = winRect->left;
486 return result;
490 /***********************************************************************
491 * NC_GetInsideRect
493 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
494 * but without the borders (if any).
495 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
497 void NC_GetInsideRect( HWND hwnd, RECT *rect )
499 WND * wndPtr = WIN_FindWndPtr( hwnd );
501 rect->top = rect->left = 0;
502 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
503 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
505 if (wndPtr->dwStyle & WS_ICONIC) goto END;
507 /* Remove frame from rectangle */
508 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
510 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
512 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
514 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
515 /* FIXME: this isn't in NC_AdjustRect? why not? */
516 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
517 InflateRect( rect, -1, 0 );
519 else if (HAS_THINFRAME( wndPtr->dwStyle ))
521 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
524 /* We have additional border information if the window
525 * is a child (but not an MDI child) */
526 if (TWEAK_WineLook != WIN31_LOOK)
528 if ( (wndPtr->dwStyle & WS_CHILD) &&
529 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
531 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
532 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
533 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
534 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
538 END:
539 WIN_ReleaseWndPtr(wndPtr);
540 return;
544 /***********************************************************************
545 * NC_DoNCHitTest
547 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
550 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
552 RECT rect;
554 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
556 GetWindowRect(wndPtr->hwndSelf, &rect );
557 if (!PtInRect( &rect, pt )) return HTNOWHERE;
559 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
561 /* Check borders */
562 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
564 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
565 if (!PtInRect( &rect, pt ))
567 /* Check top sizing border */
568 if (pt.y < rect.top)
570 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
571 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
572 return HTTOP;
574 /* Check bottom sizing border */
575 if (pt.y >= rect.bottom)
577 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
578 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
579 return HTBOTTOM;
581 /* Check left sizing border */
582 if (pt.x < rect.left)
584 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
585 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
586 return HTLEFT;
588 /* Check right sizing border */
589 if (pt.x >= rect.right)
591 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
592 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
593 return HTRIGHT;
597 else /* No thick frame */
599 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
600 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
601 else if (HAS_THINFRAME( wndPtr->dwStyle ))
602 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
603 if (!PtInRect( &rect, pt )) return HTBORDER;
606 /* Check caption */
608 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
610 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
611 if (!PtInRect( &rect, pt ))
613 /* Check system menu */
614 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
615 rect.left += GetSystemMetrics(SM_CXSIZE);
616 if (pt.x <= rect.left) return HTSYSMENU;
618 /* Check maximize box */
619 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
620 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
622 if (pt.x >= rect.right) return HTMAXBUTTON;
623 /* Check minimize box */
624 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
625 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
626 if (pt.x >= rect.right) return HTMINBUTTON;
627 return HTCAPTION;
631 /* Check client area */
633 ScreenToClient( wndPtr->hwndSelf, &pt );
634 GetClientRect( wndPtr->hwndSelf, &rect );
635 if (PtInRect( &rect, pt )) return HTCLIENT;
637 /* Check vertical scroll bar */
639 if (wndPtr->dwStyle & WS_VSCROLL)
641 rect.right += GetSystemMetrics(SM_CXVSCROLL);
642 if (PtInRect( &rect, pt )) return HTVSCROLL;
645 /* Check horizontal scroll bar */
647 if (wndPtr->dwStyle & WS_HSCROLL)
649 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
650 if (PtInRect( &rect, pt ))
652 /* Check size box */
653 if ((wndPtr->dwStyle & WS_VSCROLL) &&
654 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
655 return HTSIZE;
656 return HTHSCROLL;
660 /* Check menu bar */
662 if (HAS_MENU(wndPtr))
664 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
665 return HTMENU;
668 /* Has to return HTNOWHERE if nothing was found
669 Could happen when a window has a customized non client area */
670 return HTNOWHERE;
674 /***********************************************************************
675 * NC_DoNCHitTest95
677 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
679 * FIXME: Just a modified copy of the Win 3.1 version.
682 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
684 RECT rect;
686 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
688 GetWindowRect(wndPtr->hwndSelf, &rect );
689 if (!PtInRect( &rect, pt )) return HTNOWHERE;
691 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
693 /* Check borders */
694 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
696 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
697 if (!PtInRect( &rect, pt ))
699 /* Check top sizing border */
700 if (pt.y < rect.top)
702 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
703 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
704 return HTTOP;
706 /* Check bottom sizing border */
707 if (pt.y >= rect.bottom)
709 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
710 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
711 return HTBOTTOM;
713 /* Check left sizing border */
714 if (pt.x < rect.left)
716 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
717 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
718 return HTLEFT;
720 /* Check right sizing border */
721 if (pt.x >= rect.right)
723 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
724 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
725 return HTRIGHT;
729 else /* No thick frame */
731 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
732 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
733 else if (HAS_THINFRAME( wndPtr->dwStyle ))
734 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
735 if (!PtInRect( &rect, pt )) return HTBORDER;
738 /* Check caption */
740 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
742 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
743 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
744 else
745 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
746 if (!PtInRect( &rect, pt ))
748 /* Check system menu */
749 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
751 if (NC_IconForWindow(wndPtr->hwndSelf))
752 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
754 if (pt.x < rect.left) return HTSYSMENU;
756 /* Check close button */
757 if (wndPtr->dwStyle & WS_SYSMENU)
758 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
759 if (pt.x > rect.right) return HTCLOSE;
761 /* Check maximize box */
762 /* In win95 there is automatically a Maximize button when there is a minimize one*/
763 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
764 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
765 if (pt.x > rect.right) return HTMAXBUTTON;
767 /* Check minimize box */
768 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
769 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
770 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
772 if (pt.x > rect.right) return HTMINBUTTON;
773 return HTCAPTION;
777 /* Check client area */
779 ScreenToClient( wndPtr->hwndSelf, &pt );
780 GetClientRect( wndPtr->hwndSelf, &rect );
781 if (PtInRect( &rect, pt )) return HTCLIENT;
783 /* Check vertical scroll bar */
785 if (wndPtr->dwStyle & WS_VSCROLL)
787 rect.right += GetSystemMetrics(SM_CXVSCROLL);
788 if (PtInRect( &rect, pt )) return HTVSCROLL;
791 /* Check horizontal scroll bar */
793 if (wndPtr->dwStyle & WS_HSCROLL)
795 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
796 if (PtInRect( &rect, pt ))
798 /* Check size box */
799 if ((wndPtr->dwStyle & WS_VSCROLL) &&
800 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
801 return HTSIZE;
802 return HTHSCROLL;
806 /* Check menu bar */
808 if (HAS_MENU(wndPtr))
810 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
811 return HTMENU;
814 /* Has to return HTNOWHERE if nothing was found
815 Could happen when a window has a customized non client area */
816 return HTNOWHERE;
820 /***********************************************************************
821 * NC_HandleNCHitTest
823 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
825 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
827 LONG retvalue;
828 WND *wndPtr = WIN_FindWndPtr (hwnd);
830 if (!wndPtr)
831 return HTERROR;
833 if (TWEAK_WineLook == WIN31_LOOK)
834 retvalue = NC_DoNCHitTest (wndPtr, pt);
835 else
836 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
837 WIN_ReleaseWndPtr(wndPtr);
838 return retvalue;
842 /***********************************************************************
843 * NC_DrawSysButton
845 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
847 RECT rect;
848 HDC hdcMem;
849 HBITMAP hbitmap;
851 NC_GetInsideRect( hwnd, &rect );
852 hdcMem = CreateCompatibleDC( hdc );
853 hbitmap = SelectObject( hdcMem, hbitmapClose );
854 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
855 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
856 down ? NOTSRCCOPY : SRCCOPY );
857 SelectObject( hdcMem, hbitmap );
858 DeleteDC( hdcMem );
862 /***********************************************************************
863 * NC_DrawMaxButton
865 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
867 RECT rect;
868 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
870 NC_GetInsideRect( hwnd, &rect );
871 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
872 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
873 rect.top += 1;
874 rect.right -= 1;
875 if (down) flags |= DFCS_PUSHED;
876 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
880 /***********************************************************************
881 * NC_DrawMinButton
883 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
885 RECT rect;
886 UINT flags = DFCS_CAPTIONMIN;
887 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
889 NC_GetInsideRect( hwnd, &rect );
890 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
891 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
892 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
893 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
894 rect.top += 1;
895 rect.right -= 1;
896 if (down) flags |= DFCS_PUSHED;
897 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
901 /******************************************************************************
903 * void NC_DrawSysButton95(
904 * HWND hwnd,
905 * HDC hdc,
906 * BOOL down )
908 * Draws the Win95 system icon.
910 * Revision history
911 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
912 * Original implementation from NC_DrawSysButton source.
913 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
914 * Fixed most bugs.
916 *****************************************************************************/
918 BOOL
919 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
921 HICON hIcon = NC_IconForWindow( hwnd );
923 if (hIcon)
925 RECT rect;
926 NC_GetInsideRect( hwnd, &rect );
927 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
928 GetSystemMetrics(SM_CXSMICON),
929 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
931 return (hIcon != 0);
935 /******************************************************************************
937 * void NC_DrawCloseButton95(
938 * HWND hwnd,
939 * HDC hdc,
940 * BOOL down,
941 * BOOL bGrayed )
943 * Draws the Win95 close button.
945 * If bGrayed is true, then draw a disabled Close button
947 * Revision history
948 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
949 * Original implementation from NC_DrawSysButton95 source.
951 *****************************************************************************/
953 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
955 RECT rect;
957 NC_GetInsideRect( hwnd, &rect );
959 /* A tool window has a smaller Close button */
960 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
962 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
963 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
964 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
966 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
967 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
968 rect.bottom = rect.top + iBmpHeight;
969 rect.right = rect.left + iBmpWidth;
971 else
973 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
974 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
975 rect.top += 2;
976 rect.right -= 2;
978 DrawFrameControl( hdc, &rect, DFC_CAPTION,
979 (DFCS_CAPTIONCLOSE |
980 (down ? DFCS_PUSHED : 0) |
981 (bGrayed ? DFCS_INACTIVE : 0)) );
984 /******************************************************************************
985 * NC_DrawMaxButton95
987 * Draws the maximize button for Win95 style windows.
988 * If bGrayed is true, then draw a disabled Maximize button
990 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
992 RECT rect;
993 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
995 NC_GetInsideRect( hwnd, &rect );
996 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
997 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
998 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
999 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1000 rect.top += 2;
1001 rect.right -= 2;
1002 if (down) flags |= DFCS_PUSHED;
1003 if (bGrayed) flags |= DFCS_INACTIVE;
1004 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1007 /******************************************************************************
1008 * NC_DrawMinButton95
1010 * Draws the minimize button for Win95 style windows.
1011 * If bGrayed is true, then draw a disabled Minimize button
1013 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1015 RECT rect;
1016 UINT flags = DFCS_CAPTIONMIN;
1017 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1019 NC_GetInsideRect( hwnd, &rect );
1020 if (style & WS_SYSMENU)
1021 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1022 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1023 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1024 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1025 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1026 rect.top += 2;
1027 rect.right -= 2;
1028 if (down) flags |= DFCS_PUSHED;
1029 if (bGrayed) flags |= DFCS_INACTIVE;
1030 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1033 /***********************************************************************
1034 * NC_DrawFrame
1036 * Draw a window frame inside the given rectangle, and update the rectangle.
1037 * The correct pen for the frame must be selected in the DC.
1039 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1040 BOOL active )
1042 INT width, height;
1044 if (TWEAK_WineLook != WIN31_LOOK)
1045 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1047 if (dlgFrame)
1049 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1050 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1051 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1052 COLOR_INACTIVECAPTION) );
1054 else
1056 width = GetSystemMetrics(SM_CXFRAME) - 2;
1057 height = GetSystemMetrics(SM_CYFRAME) - 2;
1058 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1059 COLOR_INACTIVEBORDER) );
1062 /* Draw frame */
1063 PatBlt( hdc, rect->left, rect->top,
1064 rect->right - rect->left, height, PATCOPY );
1065 PatBlt( hdc, rect->left, rect->top,
1066 width, rect->bottom - rect->top, PATCOPY );
1067 PatBlt( hdc, rect->left, rect->bottom - 1,
1068 rect->right - rect->left, -height, PATCOPY );
1069 PatBlt( hdc, rect->right - 1, rect->top,
1070 -width, rect->bottom - rect->top, PATCOPY );
1072 if (dlgFrame)
1074 InflateRect( rect, -width, -height );
1076 else
1078 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1079 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1081 /* Draw inner rectangle */
1083 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1084 Rectangle( hdc, rect->left + width, rect->top + height,
1085 rect->right - width , rect->bottom - height );
1087 /* Draw the decorations */
1089 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1090 LineTo( hdc, rect->left + width, rect->top + decYOff );
1091 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1092 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1093 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1094 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1095 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1096 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1098 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1099 LineTo( hdc, rect->left + decXOff, rect->top + height);
1100 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1101 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1102 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1103 LineTo( hdc, rect->right - decXOff, rect->top + height );
1104 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1105 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1107 InflateRect( rect, -width - 1, -height - 1 );
1112 /******************************************************************************
1114 * void NC_DrawFrame95(
1115 * HDC hdc,
1116 * RECT *rect,
1117 * BOOL active,
1118 * DWORD style,
1119 * DWORD exStyle )
1121 * Draw a window frame inside the given rectangle, and update the rectangle.
1123 * Bugs
1124 * Many. First, just what IS a frame in Win95? Note that the 3D look
1125 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1126 * edge. The inner rectangle just inside the frame is handled by the
1127 * Caption code.
1129 * In short, for most people, this function should be a nop (unless
1130 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1131 * them lately, but just to get this code right). Even so, it doesn't
1132 * appear to be so. It's being worked on...
1134 * Revision history
1135 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1136 * Original implementation (based on NC_DrawFrame)
1137 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1138 * Some minor fixes.
1139 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1140 * Fixed a fix or something.
1142 *****************************************************************************/
1144 static void NC_DrawFrame95(
1145 HDC hdc,
1146 RECT *rect,
1147 BOOL active,
1148 DWORD style,
1149 DWORD exStyle)
1151 INT width, height;
1153 /* Firstly the "thick" frame */
1154 if (style & WS_THICKFRAME)
1156 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1157 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1159 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1160 COLOR_INACTIVEBORDER) );
1161 /* Draw frame */
1162 PatBlt( hdc, rect->left, rect->top,
1163 rect->right - rect->left, height, PATCOPY );
1164 PatBlt( hdc, rect->left, rect->top,
1165 width, rect->bottom - rect->top, PATCOPY );
1166 PatBlt( hdc, rect->left, rect->bottom - 1,
1167 rect->right - rect->left, -height, PATCOPY );
1168 PatBlt( hdc, rect->right - 1, rect->top,
1169 -width, rect->bottom - rect->top, PATCOPY );
1171 InflateRect( rect, -width, -height );
1174 /* Now the other bit of the frame */
1175 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1176 (exStyle & WS_EX_DLGMODALFRAME))
1178 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1179 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1180 /* This should give a value of 1 that should also work for a border */
1182 SelectObject( hdc, GetSysColorBrush(
1183 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1184 COLOR_3DFACE :
1185 (exStyle & WS_EX_STATICEDGE) ?
1186 COLOR_WINDOWFRAME :
1187 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1188 COLOR_3DFACE :
1189 /* else */
1190 COLOR_WINDOWFRAME));
1192 /* Draw frame */
1193 PatBlt( hdc, rect->left, rect->top,
1194 rect->right - rect->left, height, PATCOPY );
1195 PatBlt( hdc, rect->left, rect->top,
1196 width, rect->bottom - rect->top, PATCOPY );
1197 PatBlt( hdc, rect->left, rect->bottom - 1,
1198 rect->right - rect->left, -height, PATCOPY );
1199 PatBlt( hdc, rect->right - 1, rect->top,
1200 -width, rect->bottom - rect->top, PATCOPY );
1202 InflateRect( rect, -width, -height );
1207 /***********************************************************************
1208 * NC_DrawCaption
1210 * Draw the window caption.
1211 * The correct pen for the window frame must be selected in the DC.
1213 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1214 DWORD style, BOOL active )
1216 RECT r = *rect;
1217 char buffer[256];
1219 if (!hbitmapClose)
1221 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1224 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1226 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1227 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1228 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1229 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1230 r.left++;
1231 r.right--;
1232 SelectObject( hdc, hbrushOld );
1234 MoveToEx( hdc, r.left, r.bottom, NULL );
1235 LineTo( hdc, r.right, r.bottom );
1237 if (style & WS_SYSMENU)
1239 NC_DrawSysButton( hwnd, hdc, FALSE );
1240 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1241 MoveToEx( hdc, r.left - 1, r.top, NULL );
1242 LineTo( hdc, r.left - 1, r.bottom );
1244 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1245 if (style & WS_MAXIMIZEBOX)
1247 NC_DrawMaxButton( hwnd, hdc, FALSE );
1248 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1250 if (style & WS_MINIMIZEBOX)
1252 NC_DrawMinButton( hwnd, hdc, FALSE );
1253 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1256 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1258 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1259 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1260 SetBkMode( hdc, TRANSPARENT );
1261 DrawTextA( hdc, buffer, -1, &r,
1262 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1267 /******************************************************************************
1269 * NC_DrawCaption95(
1270 * HDC hdc,
1271 * RECT *rect,
1272 * HWND hwnd,
1273 * DWORD style,
1274 * BOOL active )
1276 * Draw the window caption for Win95 style windows.
1277 * The correct pen for the window frame must be selected in the DC.
1279 * Bugs
1280 * Hey, a function that finally works! Well, almost.
1281 * It's being worked on.
1283 * Revision history
1284 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1285 * Original implementation.
1286 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1287 * Some minor fixes.
1289 *****************************************************************************/
1291 static void NC_DrawCaption95(
1292 HDC hdc,
1293 RECT *rect,
1294 HWND hwnd,
1295 DWORD style,
1296 DWORD exStyle,
1297 BOOL active )
1299 RECT r = *rect;
1300 char buffer[256];
1301 HPEN hPrevPen;
1302 HMENU hSysMenu;
1304 hPrevPen = SelectObject( hdc, GetSysColorPen(
1305 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1306 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1307 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1308 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1309 LineTo( hdc, r.right, r.bottom - 1 );
1310 SelectObject( hdc, hPrevPen );
1311 r.bottom--;
1313 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1314 COLOR_INACTIVECAPTION) );
1316 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1317 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1318 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1321 if (style & WS_SYSMENU)
1323 UINT state;
1325 /* Go get the sysmenu */
1326 hSysMenu = GetSystemMenu(hwnd, FALSE);
1327 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1329 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1330 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1331 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1332 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1334 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1336 /* In win95 the two buttons are always there */
1337 /* But if the menu item is not in the menu they're disabled*/
1339 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1340 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1342 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1343 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1347 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1348 NONCLIENTMETRICSA nclm;
1349 HFONT hFont, hOldFont;
1350 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1351 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1352 if (exStyle & WS_EX_TOOLWINDOW)
1353 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1354 else
1355 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1356 hOldFont = SelectObject (hdc, hFont);
1357 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1358 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1359 SetBkMode( hdc, TRANSPARENT );
1360 r.left += 2;
1361 DrawTextA( hdc, buffer, -1, &r,
1362 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1363 DeleteObject (SelectObject (hdc, hOldFont));
1369 /***********************************************************************
1370 * NC_DoNCPaint
1372 * Paint the non-client area. clip is currently unused.
1374 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1376 HDC hdc;
1377 RECT rect;
1378 BOOL active;
1379 WND *wndPtr;
1380 DWORD dwStyle, dwExStyle;
1381 WORD flags;
1382 RECT rectClient, rectWindow;
1383 int has_menu;
1385 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1386 has_menu = HAS_MENU(wndPtr);
1387 dwStyle = wndPtr->dwStyle;
1388 dwExStyle = wndPtr->dwExStyle;
1389 flags = wndPtr->flags;
1390 rectClient = wndPtr->rectClient;
1391 rectWindow = wndPtr->rectWindow;
1392 WIN_ReleasePtr( wndPtr );
1394 if ( dwStyle & WS_MINIMIZE ||
1395 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1397 active = flags & WIN_NCACTIVATED;
1399 TRACE("%04x %d\n", hwnd, active );
1401 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1402 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1404 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1405 rectClient.top-rectWindow.top,
1406 rectClient.right-rectWindow.left,
1407 rectClient.bottom-rectWindow.top )
1408 == NULLREGION)
1410 ReleaseDC( hwnd, hdc );
1411 return;
1414 rect.top = rect.left = 0;
1415 rect.right = rectWindow.right - rectWindow.left;
1416 rect.bottom = rectWindow.bottom - rectWindow.top;
1418 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1420 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1422 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1423 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1424 InflateRect( &rect, -1, -1 );
1427 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1428 NC_DrawFrame(hdc, &rect, FALSE, active );
1429 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1430 NC_DrawFrame( hdc, &rect, TRUE, active );
1432 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1434 RECT r = rect;
1435 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1436 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1437 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1440 if (has_menu)
1442 RECT r = rect;
1443 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1444 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1447 /* Draw the scroll-bars */
1449 if (dwStyle & WS_VSCROLL)
1450 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1451 if (dwStyle & WS_HSCROLL)
1452 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1454 /* Draw the "size-box" */
1456 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1458 RECT r = rect;
1459 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1460 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1461 if(wndPtr->dwStyle & WS_BORDER) {
1462 r.left++;
1463 r.top++;
1465 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1468 ReleaseDC( hwnd, hdc );
1472 /******************************************************************************
1474 * void NC_DoNCPaint95(
1475 * HWND hwnd,
1476 * HRGN clip,
1477 * BOOL suppress_menupaint )
1479 * Paint the non-client area for Win95 windows. The clip region is
1480 * currently ignored.
1482 * Bugs
1483 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1484 * misc/tweak.c controls/menu.c # :-)
1486 * Revision history
1487 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1488 * Original implementation
1489 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1490 * Fixed some bugs.
1491 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1492 * Streamlined window style checks.
1494 *****************************************************************************/
1496 static void NC_DoNCPaint95(
1497 HWND hwnd,
1498 HRGN clip,
1499 BOOL suppress_menupaint )
1501 HDC hdc;
1502 RECT rfuzz, rect, rectClip;
1503 BOOL active;
1504 WND *wndPtr;
1505 DWORD dwStyle, dwExStyle;
1506 WORD flags;
1507 RECT rectClient, rectWindow;
1508 int has_menu;
1510 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1511 has_menu = HAS_MENU(wndPtr);
1512 dwStyle = wndPtr->dwStyle;
1513 dwExStyle = wndPtr->dwExStyle;
1514 flags = wndPtr->flags;
1515 rectClient = wndPtr->rectClient;
1516 rectWindow = wndPtr->rectWindow;
1517 WIN_ReleasePtr( wndPtr );
1519 if ( dwStyle & WS_MINIMIZE ||
1520 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1522 active = flags & WIN_NCACTIVATED;
1524 TRACE("%04x %d\n", hwnd, active );
1526 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1527 the call to GetDCEx implying that it is allowed not to use it either.
1528 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1529 will cause clipRgn to be deleted after ReleaseDC().
1530 Now, how is the "system" supposed to tell what happened?
1533 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1534 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1537 if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1538 rectClient.top-rectWindow.top,
1539 rectClient.right-rectWindow.left,
1540 rectClient.bottom-rectWindow.top )
1541 == NULLREGION)
1543 ReleaseDC( hwnd, hdc );
1544 return;
1547 rect.top = rect.left = 0;
1548 rect.right = rectWindow.right - rectWindow.left;
1549 rect.bottom = rectWindow.bottom - rectWindow.top;
1551 if( clip > 1 )
1552 GetRgnBox( clip, &rectClip );
1553 else
1555 clip = 0;
1556 rectClip = rect;
1559 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1561 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1562 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1564 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1565 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1568 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1570 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1572 RECT r = rect;
1573 if (dwExStyle & WS_EX_TOOLWINDOW) {
1574 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1575 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1577 else {
1578 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1579 rect.top += GetSystemMetrics(SM_CYCAPTION);
1581 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1582 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1583 dwExStyle, active);
1586 if (has_menu)
1588 RECT r = rect;
1589 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1591 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1592 r.left, r.top, r.right, r.bottom);
1594 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1597 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1598 rect.left, rect.top, rect.right, rect.bottom );
1600 if (dwExStyle & WS_EX_CLIENTEDGE)
1601 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1603 /* Draw the scroll-bars */
1605 if (dwStyle & WS_VSCROLL)
1606 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1607 if (dwStyle & WS_HSCROLL)
1608 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1610 /* Draw the "size-box" */
1611 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1613 RECT r = rect;
1614 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1615 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1616 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1619 ReleaseDC( hwnd, hdc );
1625 /***********************************************************************
1626 * NC_HandleNCPaint
1628 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1630 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1632 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1634 if( dwStyle & WS_VISIBLE )
1636 if( dwStyle & WS_MINIMIZE )
1637 WINPOS_RedrawIconTitle( hwnd );
1638 else if (TWEAK_WineLook == WIN31_LOOK)
1639 NC_DoNCPaint( hwnd, clip, FALSE );
1640 else
1641 NC_DoNCPaint95( hwnd, clip, FALSE );
1643 return 0;
1647 /***********************************************************************
1648 * NC_HandleNCActivate
1650 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1652 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1654 WND* wndPtr = WIN_FindWndPtr( hwnd );
1656 /* Lotus Notes draws menu descriptions in the caption of its main
1657 * window. When it wants to restore original "system" view, it just
1658 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1659 * attempt to minimize redrawings lead to a not restored caption.
1661 if (wndPtr)
1663 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1664 else wndPtr->flags &= ~WIN_NCACTIVATED;
1665 WIN_ReleaseWndPtr(wndPtr);
1667 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1668 else if (TWEAK_WineLook == WIN31_LOOK)
1669 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1670 else
1671 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1673 return TRUE;
1677 /***********************************************************************
1678 * NC_HandleSetCursor
1680 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1682 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1684 if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1685 return 0; /* Don't set the cursor for child windows */
1687 switch(LOWORD(lParam))
1689 case HTERROR:
1691 WORD msg = HIWORD( lParam );
1692 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1693 (msg == WM_RBUTTONDOWN))
1694 MessageBeep(0);
1696 break;
1698 case HTCLIENT:
1700 HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1701 if(hCursor) {
1702 SetCursor(hCursor);
1703 return TRUE;
1705 return FALSE;
1708 case HTLEFT:
1709 case HTRIGHT:
1710 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1712 case HTTOP:
1713 case HTBOTTOM:
1714 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1716 case HTTOPLEFT:
1717 case HTBOTTOMRIGHT:
1718 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1720 case HTTOPRIGHT:
1721 case HTBOTTOMLEFT:
1722 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1725 /* Default cursor: arrow */
1726 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1729 /***********************************************************************
1730 * NC_GetSysPopupPos
1732 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1734 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1735 else
1737 WND *wndPtr = WIN_FindWndPtr( hwnd );
1738 if (!wndPtr) return;
1740 NC_GetInsideRect( hwnd, rect );
1741 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1742 if (wndPtr->dwStyle & WS_CHILD)
1743 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1744 if (TWEAK_WineLook == WIN31_LOOK) {
1745 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1746 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1748 else {
1749 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1750 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1752 WIN_ReleaseWndPtr( wndPtr );
1756 /***********************************************************************
1757 * NC_TrackMinMaxBox95
1759 * Track a mouse button press on the minimize or maximize box.
1761 * The big difference between 3.1 and 95 is the disabled button state.
1762 * In win95 the system button can be disabled, so it can ignore the mouse
1763 * event.
1766 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1768 MSG msg;
1769 HDC hdc = GetWindowDC( hwnd );
1770 BOOL pressed = TRUE;
1771 UINT state;
1772 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1773 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1775 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
1777 if (wParam == HTMINBUTTON)
1779 /* If the style is not present, do nothing */
1780 if (!(wndStyle & WS_MINIMIZEBOX))
1781 return;
1783 /* Check if the sysmenu item for minimize is there */
1784 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1786 paintButton = &NC_DrawMinButton95;
1788 else
1790 /* If the style is not present, do nothing */
1791 if (!(wndStyle & WS_MAXIMIZEBOX))
1792 return;
1794 /* Check if the sysmenu item for maximize is there */
1795 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1797 paintButton = &NC_DrawMaxButton95;
1800 SetCapture( hwnd );
1802 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1804 while(1)
1806 BOOL oldstate = pressed;
1808 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1809 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1811 if(msg.message == WM_LBUTTONUP)
1812 break;
1814 if(msg.message != WM_MOUSEMOVE)
1815 continue;
1817 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1818 if (pressed != oldstate)
1819 (*paintButton)( hwnd, hdc, pressed, FALSE);
1822 if(pressed)
1823 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1825 ReleaseCapture();
1826 ReleaseDC( hwnd, hdc );
1828 /* If the item minimize or maximize of the sysmenu are not there */
1829 /* or if the style is not present, do nothing */
1830 if ((!pressed) || (state == 0xFFFFFFFF))
1831 return;
1833 if (wParam == HTMINBUTTON)
1834 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1835 else
1836 SendMessageA( hwnd, WM_SYSCOMMAND,
1837 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1840 /***********************************************************************
1841 * NC_TrackMinMaxBox
1843 * Track a mouse button press on the minimize or maximize box.
1845 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1847 MSG msg;
1848 HDC hdc = GetWindowDC( hwnd );
1849 BOOL pressed = TRUE;
1850 void (*paintButton)(HWND, HDC16, BOOL);
1852 SetCapture( hwnd );
1854 if (wParam == HTMINBUTTON)
1855 paintButton = &NC_DrawMinButton;
1856 else
1857 paintButton = &NC_DrawMaxButton;
1859 (*paintButton)( hwnd, hdc, TRUE);
1861 while(1)
1863 BOOL oldstate = pressed;
1865 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1866 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1868 if(msg.message == WM_LBUTTONUP)
1869 break;
1871 if(msg.message != WM_MOUSEMOVE)
1872 continue;
1874 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1875 if (pressed != oldstate)
1876 (*paintButton)( hwnd, hdc, pressed);
1879 if(pressed)
1880 (*paintButton)( hwnd, hdc, FALSE);
1882 ReleaseCapture();
1883 ReleaseDC( hwnd, hdc );
1885 if (!pressed) return;
1887 if (wParam == HTMINBUTTON)
1888 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1889 else
1890 SendMessageA( hwnd, WM_SYSCOMMAND,
1891 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1895 /***********************************************************************
1896 * NC_TrackCloseButton95
1898 * Track a mouse button press on the Win95 close button.
1900 static void
1901 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1903 MSG msg;
1904 HDC hdc;
1905 BOOL pressed = TRUE;
1906 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1907 UINT state;
1909 if(hSysMenu == 0)
1910 return;
1912 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1914 /* If the item close of the sysmenu is disabled or not there do nothing */
1915 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1916 return;
1918 hdc = GetWindowDC( hwnd );
1920 SetCapture( hwnd );
1922 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1924 while(1)
1926 BOOL oldstate = pressed;
1928 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1929 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1931 if(msg.message == WM_LBUTTONUP)
1932 break;
1934 if(msg.message != WM_MOUSEMOVE)
1935 continue;
1937 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1938 if (pressed != oldstate)
1939 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1942 if(pressed)
1943 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1945 ReleaseCapture();
1946 ReleaseDC( hwnd, hdc );
1947 if (!pressed) return;
1949 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1953 /***********************************************************************
1954 * NC_TrackScrollBar
1956 * Track a mouse button press on the horizontal or vertical scroll-bar.
1958 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1960 INT scrollbar;
1962 if ((wParam & 0xfff0) == SC_HSCROLL)
1964 if ((wParam & 0x0f) != HTHSCROLL) return;
1965 scrollbar = SB_HORZ;
1967 else /* SC_VSCROLL */
1969 if ((wParam & 0x0f) != HTVSCROLL) return;
1970 scrollbar = SB_VERT;
1972 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1976 /***********************************************************************
1977 * NC_HandleNCLButtonDown
1979 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1981 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1983 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1985 switch(wParam) /* Hit test */
1987 case HTCAPTION:
1989 HWND top = GetAncestor( hwnd, GA_ROOT );
1991 if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
1992 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1993 break;
1996 case HTSYSMENU:
1997 if( style & WS_SYSMENU )
1999 if( !(style & WS_MINIMIZE) )
2001 HDC hDC = GetWindowDC(hwnd);
2002 if (TWEAK_WineLook == WIN31_LOOK)
2003 NC_DrawSysButton( hwnd, hDC, TRUE );
2004 else
2005 NC_DrawSysButton95( hwnd, hDC, TRUE );
2006 ReleaseDC( hwnd, hDC );
2008 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2010 break;
2012 case HTMENU:
2013 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2014 break;
2016 case HTHSCROLL:
2017 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2018 break;
2020 case HTVSCROLL:
2021 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2022 break;
2024 case HTMINBUTTON:
2025 case HTMAXBUTTON:
2026 if (TWEAK_WineLook == WIN31_LOOK)
2027 NC_TrackMinMaxBox( hwnd, wParam );
2028 else
2029 NC_TrackMinMaxBox95( hwnd, wParam );
2030 break;
2032 case HTCLOSE:
2033 if (TWEAK_WineLook >= WIN95_LOOK)
2034 NC_TrackCloseButton95 (hwnd, wParam);
2035 break;
2037 case HTLEFT:
2038 case HTRIGHT:
2039 case HTTOP:
2040 case HTTOPLEFT:
2041 case HTTOPRIGHT:
2042 case HTBOTTOM:
2043 case HTBOTTOMLEFT:
2044 case HTBOTTOMRIGHT:
2045 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2046 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2047 break;
2049 case HTBORDER:
2050 break;
2052 return 0;
2056 /***********************************************************************
2057 * NC_HandleNCLButtonDblClk
2059 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2061 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2064 * if this is an icon, send a restore since we are handling
2065 * a double click
2067 if (IsIconic(hwnd))
2069 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2070 return 0;
2073 switch(wParam) /* Hit test */
2075 case HTCAPTION:
2076 /* stop processing if WS_MAXIMIZEBOX is missing */
2077 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2078 SendMessageW( hwnd, WM_SYSCOMMAND,
2079 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2080 break;
2082 case HTSYSMENU:
2083 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2084 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2085 break;
2087 case HTHSCROLL:
2088 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2089 break;
2091 case HTVSCROLL:
2092 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2093 break;
2095 return 0;
2099 /***********************************************************************
2100 * NC_HandleSysCommand
2102 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2104 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2106 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2108 switch (wParam & 0xfff0)
2110 case SC_SIZE:
2111 case SC_MOVE:
2112 if (USER_Driver.pSysCommandSizeMove)
2113 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2114 break;
2116 case SC_MINIMIZE:
2117 if (hwnd == GetForegroundWindow())
2118 ShowOwnedPopups(hwnd,FALSE);
2119 ShowWindow( hwnd, SW_MINIMIZE );
2120 break;
2122 case SC_MAXIMIZE:
2123 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2124 ShowOwnedPopups(hwnd,TRUE);
2125 ShowWindow( hwnd, SW_MAXIMIZE );
2126 break;
2128 case SC_RESTORE:
2129 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2130 ShowOwnedPopups(hwnd,TRUE);
2131 ShowWindow( hwnd, SW_RESTORE );
2132 break;
2134 case SC_CLOSE:
2135 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2137 case SC_VSCROLL:
2138 case SC_HSCROLL:
2140 POINT pt;
2141 pt.x = SLOWORD(lParam);
2142 pt.y = SHIWORD(lParam);
2143 NC_TrackScrollBar( hwnd, wParam, pt );
2145 break;
2147 case SC_MOUSEMENU:
2149 POINT pt;
2150 pt.x = SLOWORD(lParam);
2151 pt.y = SHIWORD(lParam);
2152 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2154 break;
2156 case SC_KEYMENU:
2157 MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2158 break;
2160 case SC_TASKLIST:
2161 WinExec( "taskman.exe", SW_SHOWNORMAL );
2162 break;
2164 case SC_SCREENSAVE:
2165 if (wParam == SC_ABOUTWINE)
2167 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2168 if (hmodule)
2170 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2171 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2172 FreeLibrary( hmodule );
2175 else
2176 if (wParam == SC_PUTMARK)
2177 TRACE_(shell)("Mark requested by user\n");
2178 break;
2180 case SC_HOTKEY:
2181 case SC_ARRANGE:
2182 case SC_NEXTWINDOW:
2183 case SC_PREVWINDOW:
2184 FIXME("unimplemented!\n");
2185 break;
2187 return 0;
2190 /*************************************************************
2191 * NC_DrawGrayButton
2193 * Stub for the grayed button of the caption
2195 *************************************************************/
2197 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2199 HBITMAP hMaskBmp;
2200 HDC hdcMask = CreateCompatibleDC (0);
2201 HBRUSH hOldBrush;
2203 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2205 if(hMaskBmp == 0)
2206 return FALSE;
2208 SelectObject (hdcMask, hMaskBmp);
2210 /* Draw the grayed bitmap using the mask */
2211 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2212 BitBlt (hdc, x, y, 12, 10,
2213 hdcMask, 0, 0, 0xB8074A);
2215 /* Clean up */
2216 SelectObject (hdc, hOldBrush);
2217 DeleteObject(hMaskBmp);
2218 DeleteDC (hdcMask);
2220 return TRUE;