Yet another major reorganization and a few new features.
[wine/wine64.git] / windows / nonclient.c
blob287c6fb9153646bee7bd149af94b0a673455a06a
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 "message.h"
14 #include "user.h"
15 #include "heap.h"
16 #include "dce.h"
17 #include "controls.h"
18 #include "cursoricon.h"
19 #include "winpos.h"
20 #include "hook.h"
21 #include "nonclient.h"
22 #include "debugtools.h"
23 #include "shellapi.h"
24 #include "bitmap.h"
26 DEFAULT_DEBUG_CHANNEL(nonclient);
27 DECLARE_DEBUG_CHANNEL(shell);
29 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
31 static HBITMAP hbitmapClose;
32 static HBITMAP hbitmapMinimize;
33 static HBITMAP hbitmapMinimizeD;
34 static HBITMAP hbitmapMaximize;
35 static HBITMAP hbitmapMaximizeD;
36 static HBITMAP hbitmapRestore;
37 static HBITMAP hbitmapRestoreD;
39 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
40 0x55, 0x50,
41 0xAA, 0xA0,
42 0x55, 0x50,
43 0xAA, 0xA0,
44 0x55, 0x50,
45 0xAA, 0xA0,
46 0x55, 0x50,
47 0xAA, 0xA0,
48 0x55, 0x50};
50 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
51 #define SC_PUTMARK (SC_SCREENSAVE+2)
53 /* Some useful macros */
54 #define HAS_DLGFRAME(style,exStyle) \
55 (((exStyle) & WS_EX_DLGMODALFRAME) || \
56 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
58 #define HAS_THICKFRAME(style,exStyle) \
59 (((style) & WS_THICKFRAME) && \
60 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
62 #define HAS_THINFRAME(style) \
63 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
65 #define HAS_BIGFRAME(style,exStyle) \
66 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
67 ((exStyle) & WS_EX_DLGMODALFRAME))
69 #define HAS_STATICOUTERFRAME(style,exStyle) \
70 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
71 WS_EX_STATICEDGE)
73 #define HAS_ANYFRAME(style,exStyle) \
74 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
75 ((exStyle) & WS_EX_DLGMODALFRAME) || \
76 !((style) & (WS_CHILD | WS_POPUP)))
78 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
81 /***********************************************************************
82 * NC_AdjustRect
84 * Compute the size of the window rectangle from the size of the
85 * client rectangle.
87 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
89 if (TWEAK_WineLook > WIN31_LOOK)
90 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
92 if(style & WS_ICONIC) return;
94 if (HAS_THICKFRAME( style, exStyle ))
95 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
96 else if (HAS_DLGFRAME( style, exStyle ))
97 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
98 else if (HAS_THINFRAME( style ))
99 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
101 if ((style & WS_CAPTION) == WS_CAPTION)
102 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
104 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
106 if (style & WS_VSCROLL) {
107 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
108 if(!HAS_ANYFRAME( style, exStyle ))
109 rect->right++;
112 if (style & WS_HSCROLL) {
113 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
114 if(!HAS_ANYFRAME( style, exStyle ))
115 rect->bottom++;
120 /******************************************************************************
121 * NC_AdjustRectOuter95
123 * Computes the size of the "outside" parts of the window based on the
124 * parameters of the client area.
126 + PARAMS
127 * LPRECT16 rect
128 * DWORD style
129 * BOOL menu
130 * DWORD exStyle
132 * NOTES
133 * "Outer" parts of a window means the whole window frame, caption and
134 * menu bar. It does not include "inner" parts of the frame like client
135 * edge, static edge or scroll bars.
137 * Revision history
138 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
139 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
141 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
142 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
143 * NC_AdjustRectInner95 and added handling of Win95 styles.
145 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
146 * Streamlined window style checks.
148 *****************************************************************************/
150 static void
151 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
153 int adjust;
154 if(style & WS_ICONIC) return;
156 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
157 WS_EX_STATICEDGE)
159 adjust = 1; /* for the outer frame always present */
161 else
163 adjust = 0;
164 if ((exStyle & WS_EX_DLGMODALFRAME) ||
165 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
167 if (style & WS_THICKFRAME)
168 adjust += ( GetSystemMetrics (SM_CXFRAME)
169 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
170 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
171 (exStyle & WS_EX_DLGMODALFRAME))
172 adjust++; /* The other border */
174 InflateRect (rect, adjust, adjust);
176 if ((style & WS_CAPTION) == WS_CAPTION)
178 if (exStyle & WS_EX_TOOLWINDOW)
179 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
180 else
181 rect->top -= GetSystemMetrics(SM_CYCAPTION);
183 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
187 /******************************************************************************
188 * NC_AdjustRectInner95
190 * Computes the size of the "inside" part of the window based on the
191 * parameters of the client area.
193 + PARAMS
194 * LPRECT16 rect
195 * DWORD style
196 * DWORD exStyle
198 * NOTES
199 * "Inner" part of a window means the window frame inside of the flat
200 * window frame. It includes the client edge, the static edge and the
201 * scroll bars.
203 * Revision history
204 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
205 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
207 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
208 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
209 * NC_AdjustRectInner95 and added handling of Win95 styles.
211 *****************************************************************************/
213 static void
214 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
216 if(style & WS_ICONIC) return;
218 if (exStyle & WS_EX_CLIENTEDGE)
219 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
221 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
222 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
227 static HICON NC_IconForWindow( HWND hwnd )
229 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
230 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
232 /* If there is no hIcon specified and this is a modal dialog,
233 * get the default one.
235 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
236 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
237 return hIcon;
240 /***********************************************************************
241 * DrawCaption (USER.660) Draws a caption bar
243 * PARAMS
244 * hwnd [I]
245 * hdc [I]
246 * lpRect [I]
247 * uFlags [I]
249 * RETURNS
250 * Success:
251 * Failure:
254 BOOL16 WINAPI
255 DrawCaption16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, UINT16 uFlags)
257 RECT rect32;
259 if (rect)
260 CONV_RECT16TO32 (rect, &rect32);
262 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect ? &rect32 : NULL,
263 0, 0, NULL, uFlags & 0x1F);
267 /***********************************************************************
268 * DrawCaption (USER32.@) Draws a caption bar
270 * PARAMS
271 * hwnd [I]
272 * hdc [I]
273 * lpRect [I]
274 * uFlags [I]
276 * RETURNS
277 * Success:
278 * Failure:
281 BOOL WINAPI
282 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
284 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
288 /***********************************************************************
289 * DrawCaptionTemp (USER.657)
291 * PARAMS
293 * RETURNS
294 * Success:
295 * Failure:
298 BOOL16 WINAPI
299 DrawCaptionTemp16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, HFONT16 hFont,
300 HICON16 hIcon, LPCSTR str, UINT16 uFlags)
302 RECT rect32;
304 if (rect)
305 CONV_RECT16TO32(rect,&rect32);
307 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect?&rect32:NULL, hFont,
308 hIcon, str, uFlags & 0x1F);
312 /***********************************************************************
313 * DrawCaptionTempA (USER32.@)
315 * PARAMS
317 * RETURNS
318 * Success:
319 * Failure:
322 BOOL WINAPI
323 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
324 HICON hIcon, LPCSTR str, UINT uFlags)
326 RECT rc = *rect;
328 TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
329 hwnd, hdc, rect, hFont, hIcon, str, uFlags);
331 /* drawing background */
332 if (uFlags & DC_INBUTTON) {
333 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
335 if (uFlags & DC_ACTIVE) {
336 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
337 PatBlt (hdc, rc.left, rc.top,
338 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
339 SelectObject (hdc, hbr);
342 else {
343 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
344 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
348 /* drawing icon */
349 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
350 POINT pt;
352 pt.x = rc.left + 2;
353 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
355 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
356 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
357 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
358 rc.left += (rc.bottom - rc.top);
361 /* drawing text */
362 if (uFlags & DC_TEXT) {
363 HFONT hOldFont;
365 if (uFlags & DC_INBUTTON)
366 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
367 else if (uFlags & DC_ACTIVE)
368 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
369 else
370 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
372 SetBkMode (hdc, TRANSPARENT);
374 if (hFont)
375 hOldFont = SelectObject (hdc, hFont);
376 else {
377 NONCLIENTMETRICSA nclm;
378 HFONT hNewFont;
379 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
380 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
381 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
382 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
383 hOldFont = SelectObject (hdc, hNewFont);
386 if (str)
387 DrawTextA (hdc, str, -1, &rc,
388 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
389 else {
390 CHAR szText[128];
391 INT nLen;
392 nLen = GetWindowTextA (hwnd, szText, 128);
393 DrawTextA (hdc, szText, nLen, &rc,
394 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
397 if (hFont)
398 SelectObject (hdc, hOldFont);
399 else
400 DeleteObject (SelectObject (hdc, hOldFont));
403 /* drawing focus ??? */
404 if (uFlags & 0x2000)
405 FIXME("undocumented flag (0x2000)!\n");
407 return 0;
411 /***********************************************************************
412 * DrawCaptionTempW (USER32.@)
414 * PARAMS
416 * RETURNS
417 * Success:
418 * Failure:
421 BOOL WINAPI
422 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
423 HICON hIcon, LPCWSTR str, UINT uFlags)
425 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
426 BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
427 HeapFree (GetProcessHeap (), 0, p);
428 return res;
432 /***********************************************************************
433 * AdjustWindowRect (USER.102)
435 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
437 return AdjustWindowRectEx16( rect, style, menu, 0 );
441 /***********************************************************************
442 * AdjustWindowRect (USER32.@)
444 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
446 return AdjustWindowRectEx( rect, style, menu, 0 );
450 /***********************************************************************
451 * AdjustWindowRectEx (USER.454)
453 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
454 BOOL16 menu, DWORD exStyle )
456 RECT rect32;
457 BOOL ret;
459 CONV_RECT16TO32( rect, &rect32 );
460 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
461 CONV_RECT32TO16( &rect32, rect );
462 return ret;
466 /***********************************************************************
467 * AdjustWindowRectEx (USER32.@)
469 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
471 /* Correct the window style */
473 if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
474 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
475 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
476 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
477 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
479 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
480 rect->left, rect->top, rect->right, rect->bottom,
481 style, menu, exStyle );
483 if (TWEAK_WineLook == WIN31_LOOK)
484 NC_AdjustRect( rect, style, menu, exStyle );
485 else
487 NC_AdjustRectOuter95( rect, style, menu, exStyle );
488 NC_AdjustRectInner95( rect, style, exStyle );
490 return TRUE;
494 /***********************************************************************
495 * NC_HandleNCCalcSize
497 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
499 LONG NC_HandleNCCalcSize( WND *pWnd, RECT *winRect )
501 RECT tmpRect = { 0, 0, 0, 0 };
502 LONG result = 0;
503 UINT style = (UINT) GetClassLongA(pWnd->hwndSelf, GCL_STYLE);
505 if (style & CS_VREDRAW) result |= WVR_VREDRAW;
506 if (style & CS_HREDRAW) result |= WVR_HREDRAW;
508 if( !( pWnd->dwStyle & WS_MINIMIZE ) ) {
509 if (TWEAK_WineLook == WIN31_LOOK)
510 NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
511 else
512 NC_AdjustRectOuter95( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
514 winRect->left -= tmpRect.left;
515 winRect->top -= tmpRect.top;
516 winRect->right -= tmpRect.right;
517 winRect->bottom -= tmpRect.bottom;
519 if (HAS_MENU(pWnd)) {
520 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
521 "at (%d, %d).\n", pWnd->hwndSelf,
522 winRect->right - winRect->left,
523 -tmpRect.left, -tmpRect.top );
525 winRect->top +=
526 MENU_GetMenuBarHeight( pWnd->hwndSelf,
527 winRect->right - winRect->left,
528 -tmpRect.left, -tmpRect.top ) + 1;
531 if (TWEAK_WineLook > WIN31_LOOK) {
532 SetRect(&tmpRect, 0, 0, 0, 0);
533 NC_AdjustRectInner95 (&tmpRect, pWnd->dwStyle, pWnd->dwExStyle);
534 winRect->left -= tmpRect.left;
535 winRect->top -= tmpRect.top;
536 winRect->right -= tmpRect.right;
537 winRect->bottom -= tmpRect.bottom;
540 if (winRect->top > winRect->bottom)
541 winRect->bottom = winRect->top;
543 if (winRect->left > winRect->right)
544 winRect->right = winRect->left;
546 return result;
550 /***********************************************************************
551 * NC_GetInsideRect
553 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
554 * but without the borders (if any).
555 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
557 void NC_GetInsideRect( HWND hwnd, RECT *rect )
559 WND * wndPtr = WIN_FindWndPtr( hwnd );
561 rect->top = rect->left = 0;
562 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
563 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
565 if (wndPtr->dwStyle & WS_ICONIC) goto END;
567 /* Remove frame from rectangle */
568 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
570 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
572 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
574 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
575 /* FIXME: this isn't in NC_AdjustRect? why not? */
576 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
577 InflateRect( rect, -1, 0 );
579 else if (HAS_THINFRAME( wndPtr->dwStyle ))
581 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
584 /* We have additional border information if the window
585 * is a child (but not an MDI child) */
586 if (TWEAK_WineLook != WIN31_LOOK)
588 if ( (wndPtr->dwStyle & WS_CHILD) &&
589 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
591 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
592 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
593 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
594 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
598 END:
599 WIN_ReleaseWndPtr(wndPtr);
600 return;
604 /***********************************************************************
605 * NC_DoNCHitTest
607 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
610 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
612 RECT rect;
614 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
616 GetWindowRect(wndPtr->hwndSelf, &rect );
617 if (!PtInRect( &rect, pt )) return HTNOWHERE;
619 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
621 /* Check borders */
622 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
624 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
625 if (!PtInRect( &rect, pt ))
627 /* Check top sizing border */
628 if (pt.y < rect.top)
630 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
631 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
632 return HTTOP;
634 /* Check bottom sizing border */
635 if (pt.y >= rect.bottom)
637 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
638 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
639 return HTBOTTOM;
641 /* Check left sizing border */
642 if (pt.x < rect.left)
644 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
645 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
646 return HTLEFT;
648 /* Check right sizing border */
649 if (pt.x >= rect.right)
651 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
652 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
653 return HTRIGHT;
657 else /* No thick frame */
659 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
660 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
661 else if (HAS_THINFRAME( wndPtr->dwStyle ))
662 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
663 if (!PtInRect( &rect, pt )) return HTBORDER;
666 /* Check caption */
668 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
670 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
671 if (!PtInRect( &rect, pt ))
673 /* Check system menu */
674 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
675 rect.left += GetSystemMetrics(SM_CXSIZE);
676 if (pt.x <= rect.left) return HTSYSMENU;
678 /* Check maximize box */
679 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
680 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
682 if (pt.x >= rect.right) return HTMAXBUTTON;
683 /* Check minimize box */
684 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
685 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
686 if (pt.x >= rect.right) return HTMINBUTTON;
687 return HTCAPTION;
691 /* Check client area */
693 ScreenToClient( wndPtr->hwndSelf, &pt );
694 GetClientRect( wndPtr->hwndSelf, &rect );
695 if (PtInRect( &rect, pt )) return HTCLIENT;
697 /* Check vertical scroll bar */
699 if (wndPtr->dwStyle & WS_VSCROLL)
701 rect.right += GetSystemMetrics(SM_CXVSCROLL);
702 if (PtInRect( &rect, pt )) return HTVSCROLL;
705 /* Check horizontal scroll bar */
707 if (wndPtr->dwStyle & WS_HSCROLL)
709 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
710 if (PtInRect( &rect, pt ))
712 /* Check size box */
713 if ((wndPtr->dwStyle & WS_VSCROLL) &&
714 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
715 return HTSIZE;
716 return HTHSCROLL;
720 /* Check menu bar */
722 if (HAS_MENU(wndPtr))
724 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
725 return HTMENU;
728 /* Has to return HTNOWHERE if nothing was found
729 Could happen when a window has a customized non client area */
730 return HTNOWHERE;
734 /***********************************************************************
735 * NC_DoNCHitTest95
737 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
739 * FIXME: Just a modified copy of the Win 3.1 version.
742 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
744 RECT rect;
746 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
748 GetWindowRect(wndPtr->hwndSelf, &rect );
749 if (!PtInRect( &rect, pt )) return HTNOWHERE;
751 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
753 /* Check borders */
754 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
756 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
757 if (!PtInRect( &rect, pt ))
759 /* Check top sizing border */
760 if (pt.y < rect.top)
762 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
763 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
764 return HTTOP;
766 /* Check bottom sizing border */
767 if (pt.y >= rect.bottom)
769 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
770 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
771 return HTBOTTOM;
773 /* Check left sizing border */
774 if (pt.x < rect.left)
776 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
777 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
778 return HTLEFT;
780 /* Check right sizing border */
781 if (pt.x >= rect.right)
783 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
784 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
785 return HTRIGHT;
789 else /* No thick frame */
791 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
792 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
793 else if (HAS_THINFRAME( wndPtr->dwStyle ))
794 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
795 if (!PtInRect( &rect, pt )) return HTBORDER;
798 /* Check caption */
800 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
802 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
803 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
804 else
805 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
806 if (!PtInRect( &rect, pt ))
808 /* Check system menu */
809 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
811 if (NC_IconForWindow(wndPtr->hwndSelf))
812 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
814 if (pt.x < rect.left) return HTSYSMENU;
816 /* Check close button */
817 if (wndPtr->dwStyle & WS_SYSMENU)
818 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
819 if (pt.x > rect.right) return HTCLOSE;
821 /* Check maximize box */
822 /* In win95 there is automatically a Maximize button when there is a minimize one*/
823 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
824 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
825 if (pt.x > rect.right) return HTMAXBUTTON;
827 /* Check minimize box */
828 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
829 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
830 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
832 if (pt.x > rect.right) return HTMINBUTTON;
833 return HTCAPTION;
837 /* Check client area */
839 ScreenToClient( wndPtr->hwndSelf, &pt );
840 GetClientRect( wndPtr->hwndSelf, &rect );
841 if (PtInRect( &rect, pt )) return HTCLIENT;
843 /* Check vertical scroll bar */
845 if (wndPtr->dwStyle & WS_VSCROLL)
847 rect.right += GetSystemMetrics(SM_CXVSCROLL);
848 if (PtInRect( &rect, pt )) return HTVSCROLL;
851 /* Check horizontal scroll bar */
853 if (wndPtr->dwStyle & WS_HSCROLL)
855 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
856 if (PtInRect( &rect, pt ))
858 /* Check size box */
859 if ((wndPtr->dwStyle & WS_VSCROLL) &&
860 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
861 return HTSIZE;
862 return HTHSCROLL;
866 /* Check menu bar */
868 if (HAS_MENU(wndPtr))
870 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
871 return HTMENU;
874 /* Has to return HTNOWHERE if nothing was found
875 Could happen when a window has a customized non client area */
876 return HTNOWHERE;
880 /***********************************************************************
881 * NC_HandleNCHitTest
883 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
885 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
887 LONG retvalue;
888 WND *wndPtr = WIN_FindWndPtr (hwnd);
890 if (!wndPtr)
891 return HTERROR;
893 if (TWEAK_WineLook == WIN31_LOOK)
894 retvalue = NC_DoNCHitTest (wndPtr, pt);
895 else
896 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
897 WIN_ReleaseWndPtr(wndPtr);
898 return retvalue;
902 /***********************************************************************
903 * NC_DrawSysButton
905 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
907 RECT rect;
908 HDC hdcMem;
909 HBITMAP hbitmap;
911 NC_GetInsideRect( hwnd, &rect );
912 hdcMem = CreateCompatibleDC( hdc );
913 hbitmap = SelectObject( hdcMem, hbitmapClose );
914 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
915 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
916 down ? NOTSRCCOPY : SRCCOPY );
917 SelectObject( hdcMem, hbitmap );
918 DeleteDC( hdcMem );
922 /***********************************************************************
923 * NC_DrawMaxButton
925 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
927 RECT rect;
928 HDC hdcMem;
930 NC_GetInsideRect( hwnd, &rect );
931 hdcMem = CreateCompatibleDC( hdc );
932 SelectObject( hdcMem, (IsZoomed(hwnd)
933 ? (down ? hbitmapRestoreD : hbitmapRestore)
934 : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
935 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
936 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
937 SRCCOPY );
938 DeleteDC( hdcMem );
943 /***********************************************************************
944 * NC_DrawMinButton
946 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
948 RECT rect;
949 HDC hdcMem;
951 NC_GetInsideRect( hwnd, &rect );
952 hdcMem = CreateCompatibleDC( hdc );
953 SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
954 if (GetWindowLongA(hwnd,GWL_STYLE) & WS_MAXIMIZEBOX)
955 rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
956 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
957 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
958 SRCCOPY );
959 DeleteDC( hdcMem );
963 /******************************************************************************
965 * void NC_DrawSysButton95(
966 * HWND hwnd,
967 * HDC hdc,
968 * BOOL down )
970 * Draws the Win95 system icon.
972 * Revision history
973 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
974 * Original implementation from NC_DrawSysButton source.
975 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
976 * Fixed most bugs.
978 *****************************************************************************/
980 BOOL
981 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
983 HICON hIcon = NC_IconForWindow( hwnd );
985 if (hIcon)
987 RECT rect;
988 NC_GetInsideRect( hwnd, &rect );
989 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
990 GetSystemMetrics(SM_CXSMICON),
991 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
993 return (hIcon != 0);
997 /******************************************************************************
999 * void NC_DrawCloseButton95(
1000 * HWND hwnd,
1001 * HDC hdc,
1002 * BOOL down,
1003 * BOOL bGrayed )
1005 * Draws the Win95 close button.
1007 * If bGrayed is true, then draw a disabled Close button
1009 * Revision history
1010 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1011 * Original implementation from NC_DrawSysButton95 source.
1013 *****************************************************************************/
1015 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
1017 RECT rect;
1019 NC_GetInsideRect( hwnd, &rect );
1021 /* A tool window has a smaller Close button */
1022 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
1024 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
1025 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
1026 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1028 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1029 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1030 rect.bottom = rect.top + iBmpHeight;
1031 rect.right = rect.left + iBmpWidth;
1033 else
1035 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
1036 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1037 rect.top += 2;
1038 rect.right -= 2;
1040 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1041 (DFCS_CAPTIONCLOSE |
1042 (down ? DFCS_PUSHED : 0) |
1043 (bGrayed ? DFCS_INACTIVE : 0)) );
1046 /******************************************************************************
1047 * NC_DrawMaxButton95
1049 * Draws the maximize button for Win95 style windows.
1050 * If bGrayed is true, then draw a disabled Maximize button
1052 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1054 RECT rect;
1055 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1057 NC_GetInsideRect( hwnd, &rect );
1058 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1059 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1060 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1061 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1062 rect.top += 2;
1063 rect.right -= 2;
1064 if (down) flags |= DFCS_PUSHED;
1065 if (bGrayed) flags |= DFCS_INACTIVE;
1066 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1069 /******************************************************************************
1070 * NC_DrawMinButton95
1072 * Draws the minimize button for Win95 style windows.
1073 * If bGrayed is true, then draw a disabled Minimize button
1075 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1077 RECT rect;
1078 UINT flags = DFCS_CAPTIONMIN;
1079 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1081 NC_GetInsideRect( hwnd, &rect );
1082 if (style & WS_SYSMENU)
1083 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1084 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1085 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1086 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1087 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1088 rect.top += 2;
1089 rect.right -= 2;
1090 if (down) flags |= DFCS_PUSHED;
1091 if (bGrayed) flags |= DFCS_INACTIVE;
1092 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1095 /***********************************************************************
1096 * NC_DrawFrame
1098 * Draw a window frame inside the given rectangle, and update the rectangle.
1099 * The correct pen for the frame must be selected in the DC.
1101 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1102 BOOL active )
1104 INT width, height;
1106 if (TWEAK_WineLook != WIN31_LOOK)
1107 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1109 if (dlgFrame)
1111 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1112 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1113 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1114 COLOR_INACTIVECAPTION) );
1116 else
1118 width = GetSystemMetrics(SM_CXFRAME) - 2;
1119 height = GetSystemMetrics(SM_CYFRAME) - 2;
1120 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1121 COLOR_INACTIVEBORDER) );
1124 /* Draw frame */
1125 PatBlt( hdc, rect->left, rect->top,
1126 rect->right - rect->left, height, PATCOPY );
1127 PatBlt( hdc, rect->left, rect->top,
1128 width, rect->bottom - rect->top, PATCOPY );
1129 PatBlt( hdc, rect->left, rect->bottom - 1,
1130 rect->right - rect->left, -height, PATCOPY );
1131 PatBlt( hdc, rect->right - 1, rect->top,
1132 -width, rect->bottom - rect->top, PATCOPY );
1134 if (dlgFrame)
1136 InflateRect( rect, -width, -height );
1138 else
1140 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1141 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1143 /* Draw inner rectangle */
1145 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1146 Rectangle( hdc, rect->left + width, rect->top + height,
1147 rect->right - width , rect->bottom - height );
1149 /* Draw the decorations */
1151 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1152 LineTo( hdc, rect->left + width, rect->top + decYOff );
1153 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1154 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1155 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1156 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1157 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1158 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1160 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1161 LineTo( hdc, rect->left + decXOff, rect->top + height);
1162 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1163 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1164 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1165 LineTo( hdc, rect->right - decXOff, rect->top + height );
1166 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1167 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1169 InflateRect( rect, -width - 1, -height - 1 );
1174 /******************************************************************************
1176 * void NC_DrawFrame95(
1177 * HDC hdc,
1178 * RECT *rect,
1179 * BOOL active,
1180 * DWORD style,
1181 * DWORD exStyle )
1183 * Draw a window frame inside the given rectangle, and update the rectangle.
1185 * Bugs
1186 * Many. First, just what IS a frame in Win95? Note that the 3D look
1187 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1188 * edge. The inner rectangle just inside the frame is handled by the
1189 * Caption code.
1191 * In short, for most people, this function should be a nop (unless
1192 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1193 * them lately, but just to get this code right). Even so, it doesn't
1194 * appear to be so. It's being worked on...
1196 * Revision history
1197 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1198 * Original implementation (based on NC_DrawFrame)
1199 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1200 * Some minor fixes.
1201 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1202 * Fixed a fix or something.
1204 *****************************************************************************/
1206 static void NC_DrawFrame95(
1207 HDC hdc,
1208 RECT *rect,
1209 BOOL active,
1210 DWORD style,
1211 DWORD exStyle)
1213 INT width, height;
1215 /* Firstly the "thick" frame */
1216 if (style & WS_THICKFRAME)
1218 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1219 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1221 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1222 COLOR_INACTIVEBORDER) );
1223 /* Draw frame */
1224 PatBlt( hdc, rect->left, rect->top,
1225 rect->right - rect->left, height, PATCOPY );
1226 PatBlt( hdc, rect->left, rect->top,
1227 width, rect->bottom - rect->top, PATCOPY );
1228 PatBlt( hdc, rect->left, rect->bottom - 1,
1229 rect->right - rect->left, -height, PATCOPY );
1230 PatBlt( hdc, rect->right - 1, rect->top,
1231 -width, rect->bottom - rect->top, PATCOPY );
1233 InflateRect( rect, -width, -height );
1236 /* Now the other bit of the frame */
1237 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1238 (exStyle & WS_EX_DLGMODALFRAME))
1240 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1241 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1242 /* This should give a value of 1 that should also work for a border */
1244 SelectObject( hdc, GetSysColorBrush(
1245 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1246 COLOR_3DFACE :
1247 (exStyle & WS_EX_STATICEDGE) ?
1248 COLOR_WINDOWFRAME :
1249 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1250 COLOR_3DFACE :
1251 /* else */
1252 COLOR_WINDOWFRAME));
1254 /* Draw frame */
1255 PatBlt( hdc, rect->left, rect->top,
1256 rect->right - rect->left, height, PATCOPY );
1257 PatBlt( hdc, rect->left, rect->top,
1258 width, rect->bottom - rect->top, PATCOPY );
1259 PatBlt( hdc, rect->left, rect->bottom - 1,
1260 rect->right - rect->left, -height, PATCOPY );
1261 PatBlt( hdc, rect->right - 1, rect->top,
1262 -width, rect->bottom - rect->top, PATCOPY );
1264 InflateRect( rect, -width, -height );
1269 /***********************************************************************
1270 * NC_DrawCaption
1272 * Draw the window caption.
1273 * The correct pen for the window frame must be selected in the DC.
1275 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1276 DWORD style, BOOL active )
1278 RECT r = *rect;
1279 char buffer[256];
1281 if (!hbitmapClose)
1283 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) ))) return;
1284 hbitmapMinimize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
1285 hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
1286 hbitmapMaximize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
1287 hbitmapMaximizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOMD) );
1288 hbitmapRestore = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORE) );
1289 hbitmapRestoreD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
1292 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1294 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1295 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1296 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1297 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1298 r.left++;
1299 r.right--;
1300 SelectObject( hdc, hbrushOld );
1302 MoveToEx( hdc, r.left, r.bottom, NULL );
1303 LineTo( hdc, r.right, r.bottom );
1305 if (style & WS_SYSMENU)
1307 NC_DrawSysButton( hwnd, hdc, FALSE );
1308 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1309 MoveToEx( hdc, r.left - 1, r.top, NULL );
1310 LineTo( hdc, r.left - 1, r.bottom );
1312 if (style & WS_MAXIMIZEBOX)
1314 NC_DrawMaxButton( hwnd, hdc, FALSE );
1315 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1317 if (style & WS_MINIMIZEBOX)
1319 NC_DrawMinButton( hwnd, hdc, FALSE );
1320 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1323 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1324 COLOR_INACTIVECAPTION) );
1326 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1328 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1329 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1330 SetBkMode( hdc, TRANSPARENT );
1331 DrawTextA( hdc, buffer, -1, &r,
1332 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1337 /******************************************************************************
1339 * NC_DrawCaption95(
1340 * HDC hdc,
1341 * RECT *rect,
1342 * HWND hwnd,
1343 * DWORD style,
1344 * BOOL active )
1346 * Draw the window caption for Win95 style windows.
1347 * The correct pen for the window frame must be selected in the DC.
1349 * Bugs
1350 * Hey, a function that finally works! Well, almost.
1351 * It's being worked on.
1353 * Revision history
1354 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1355 * Original implementation.
1356 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1357 * Some minor fixes.
1359 *****************************************************************************/
1361 static void NC_DrawCaption95(
1362 HDC hdc,
1363 RECT *rect,
1364 HWND hwnd,
1365 DWORD style,
1366 DWORD exStyle,
1367 BOOL active )
1369 RECT r = *rect;
1370 char buffer[256];
1371 HPEN hPrevPen;
1372 HMENU hSysMenu;
1374 hPrevPen = SelectObject( hdc, GetSysColorPen(
1375 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1376 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1377 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1378 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1379 LineTo( hdc, r.right, r.bottom - 1 );
1380 SelectObject( hdc, hPrevPen );
1381 r.bottom--;
1383 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1384 COLOR_INACTIVECAPTION) );
1386 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1387 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1388 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1391 if (style & WS_SYSMENU)
1393 UINT state;
1395 /* Go get the sysmenu */
1396 hSysMenu = GetSystemMenu(hwnd, FALSE);
1397 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1399 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1400 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1401 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1402 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1404 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1406 /* In win95 the two buttons are always there */
1407 /* But if the menu item is not in the menu they're disabled*/
1409 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1410 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1412 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1413 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1417 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1418 NONCLIENTMETRICSA nclm;
1419 HFONT hFont, hOldFont;
1420 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1421 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1422 if (exStyle & WS_EX_TOOLWINDOW)
1423 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1424 else
1425 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1426 hOldFont = SelectObject (hdc, hFont);
1427 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1428 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1429 SetBkMode( hdc, TRANSPARENT );
1430 r.left += 2;
1431 DrawTextA( hdc, buffer, -1, &r,
1432 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1433 DeleteObject (SelectObject (hdc, hOldFont));
1439 /***********************************************************************
1440 * NC_DoNCPaint
1442 * Paint the non-client area. clip is currently unused.
1444 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1446 HDC hdc;
1447 RECT rect;
1448 BOOL active;
1449 HWND hwnd = wndPtr->hwndSelf;
1451 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1452 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1454 active = wndPtr->flags & WIN_NCACTIVATED;
1456 TRACE("%04x %d\n", hwnd, active );
1458 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1459 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1461 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1462 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1463 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1464 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1465 == NULLREGION)
1467 ReleaseDC( hwnd, hdc );
1468 return;
1471 rect.top = rect.left = 0;
1472 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1473 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1475 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1477 if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1479 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1480 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1481 InflateRect( &rect, -1, -1 );
1484 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1485 NC_DrawFrame(hdc, &rect, FALSE, active );
1486 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1487 NC_DrawFrame( hdc, &rect, TRUE, active );
1489 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1491 RECT r = rect;
1492 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1493 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1494 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1497 if (HAS_MENU(wndPtr))
1499 RECT r = rect;
1500 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1501 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1504 /* Draw the scroll-bars */
1506 if (wndPtr->dwStyle & WS_VSCROLL)
1507 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1508 if (wndPtr->dwStyle & WS_HSCROLL)
1509 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1511 /* Draw the "size-box" */
1513 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1515 RECT r = rect;
1516 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1517 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1518 if(wndPtr->dwStyle & WS_BORDER) {
1519 r.left++;
1520 r.top++;
1522 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1525 ReleaseDC( hwnd, hdc );
1529 /******************************************************************************
1531 * void NC_DoNCPaint95(
1532 * WND *wndPtr,
1533 * HRGN clip,
1534 * BOOL suppress_menupaint )
1536 * Paint the non-client area for Win95 windows. The clip region is
1537 * currently ignored.
1539 * Bugs
1540 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1541 * misc/tweak.c controls/menu.c # :-)
1543 * Revision history
1544 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1545 * Original implementation
1546 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1547 * Fixed some bugs.
1548 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1549 * Streamlined window style checks.
1551 *****************************************************************************/
1553 static void NC_DoNCPaint95(
1554 WND *wndPtr,
1555 HRGN clip,
1556 BOOL suppress_menupaint )
1558 HDC hdc;
1559 RECT rfuzz, rect, rectClip;
1560 BOOL active;
1561 HWND hwnd = wndPtr->hwndSelf;
1563 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1564 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1566 active = wndPtr->flags & WIN_NCACTIVATED;
1568 TRACE("%04x %d\n", hwnd, active );
1570 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1571 the call to GetDCEx implying that it is allowed not to use it either.
1572 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1573 will cause clipRgn to be deleted after ReleaseDC().
1574 Now, how is the "system" supposed to tell what happened?
1577 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1578 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1581 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1582 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1583 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1584 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1585 == NULLREGION)
1587 ReleaseDC( hwnd, hdc );
1588 return;
1591 rect.top = rect.left = 0;
1592 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1593 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1595 if( clip > 1 )
1596 GetRgnBox( clip, &rectClip );
1597 else
1599 clip = 0;
1600 rectClip = rect;
1603 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1605 if (HAS_STATICOUTERFRAME(wndPtr->dwStyle, wndPtr->dwExStyle)) {
1606 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1608 else if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1609 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1612 NC_DrawFrame95(hdc, &rect, active, wndPtr->dwStyle, wndPtr->dwExStyle );
1614 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1616 RECT r = rect;
1617 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1618 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1619 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1621 else {
1622 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1623 rect.top += GetSystemMetrics(SM_CYCAPTION);
1625 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1626 NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1627 wndPtr->dwExStyle, active);
1630 if (HAS_MENU(wndPtr))
1632 RECT r = rect;
1633 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1635 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1636 r.left, r.top, r.right, r.bottom);
1638 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1641 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1642 rect.left, rect.top, rect.right, rect.bottom );
1644 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1645 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1647 /* Draw the scroll-bars */
1649 if (wndPtr->dwStyle & WS_VSCROLL)
1650 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1651 if (wndPtr->dwStyle & WS_HSCROLL)
1652 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1654 /* Draw the "size-box" */
1655 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1657 RECT r = rect;
1658 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1659 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1660 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1663 ReleaseDC( hwnd, hdc );
1669 /***********************************************************************
1670 * NC_HandleNCPaint
1672 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1674 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1676 WND* wndPtr = WIN_FindWndPtr( hwnd );
1678 if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1680 if( wndPtr->dwStyle & WS_MINIMIZE )
1681 WINPOS_RedrawIconTitle( hwnd );
1682 else if (TWEAK_WineLook == WIN31_LOOK)
1683 NC_DoNCPaint( wndPtr, clip, FALSE );
1684 else
1685 NC_DoNCPaint95( wndPtr, clip, FALSE );
1687 WIN_ReleaseWndPtr(wndPtr);
1688 return 0;
1692 /***********************************************************************
1693 * NC_HandleNCActivate
1695 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1697 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM16 wParam )
1699 /* Lotus Notes draws menu descriptions in the caption of its main
1700 * window. When it wants to restore original "system" view, it just
1701 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1702 * attempt to minimize redrawings lead to a not restored caption.
1705 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1706 else wndPtr->flags &= ~WIN_NCACTIVATED;
1708 if( wndPtr->dwStyle & WS_MINIMIZE )
1709 WINPOS_RedrawIconTitle( wndPtr->hwndSelf );
1710 else if (TWEAK_WineLook == WIN31_LOOK)
1711 NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1712 else
1713 NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1715 return TRUE;
1719 /***********************************************************************
1720 * NC_HandleSetCursor
1722 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1724 LONG NC_HandleSetCursor( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
1726 if (hwnd != (HWND)wParam) return 0; /* Don't set the cursor for child windows */
1728 switch(LOWORD(lParam))
1730 case HTERROR:
1732 WORD msg = HIWORD( lParam );
1733 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1734 (msg == WM_RBUTTONDOWN))
1735 MessageBeep(0);
1737 break;
1739 case HTCLIENT:
1741 HICON16 hCursor = (HICON16) GetClassWord(hwnd, GCW_HCURSOR);
1742 if(hCursor) {
1743 SetCursor16(hCursor);
1744 return TRUE;
1746 return FALSE;
1749 case HTLEFT:
1750 case HTRIGHT:
1751 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1753 case HTTOP:
1754 case HTBOTTOM:
1755 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1757 case HTTOPLEFT:
1758 case HTBOTTOMRIGHT:
1759 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1761 case HTTOPRIGHT:
1762 case HTBOTTOMLEFT:
1763 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1766 /* Default cursor: arrow */
1767 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1770 /***********************************************************************
1771 * NC_GetSysPopupPos
1773 BOOL NC_GetSysPopupPos( WND* wndPtr, RECT* rect )
1775 if( wndPtr->hSysMenu )
1777 if( wndPtr->dwStyle & WS_MINIMIZE )
1778 GetWindowRect( wndPtr->hwndSelf, rect );
1779 else
1781 NC_GetInsideRect( wndPtr->hwndSelf, rect );
1782 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1783 if (wndPtr->dwStyle & WS_CHILD)
1784 ClientToScreen( wndPtr->parent->hwndSelf, (POINT *)rect );
1785 if (TWEAK_WineLook == WIN31_LOOK) {
1786 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1787 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1789 else {
1790 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1791 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1794 return TRUE;
1796 return FALSE;
1799 /***********************************************************************
1800 * NC_TrackMinMaxBox95
1802 * Track a mouse button press on the minimize or maximize box.
1804 * The big difference between 3.1 and 95 is the disabled button state.
1805 * In win95 the system button can be disabled, so it can ignore the mouse
1806 * event.
1809 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1811 MSG msg;
1812 HDC hdc = GetWindowDC( hwnd );
1813 BOOL pressed = TRUE;
1814 UINT state;
1815 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1816 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1818 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
1820 if (wParam == HTMINBUTTON)
1822 /* If the style is not present, do nothing */
1823 if (!(wndStyle & WS_MINIMIZEBOX))
1824 return;
1826 /* Check if the sysmenu item for minimize is there */
1827 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1829 paintButton = &NC_DrawMinButton95;
1831 else
1833 /* If the style is not present, do nothing */
1834 if (!(wndStyle & WS_MAXIMIZEBOX))
1835 return;
1837 /* Check if the sysmenu item for maximize is there */
1838 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1840 paintButton = &NC_DrawMaxButton95;
1843 SetCapture( hwnd );
1845 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1847 while(1)
1849 BOOL oldstate = pressed;
1850 MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
1851 0, PM_REMOVE, FALSE, NULL );
1853 if(msg.message == WM_LBUTTONUP)
1854 break;
1856 if(msg.message != WM_MOUSEMOVE)
1857 continue;
1859 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1860 if (pressed != oldstate)
1861 (*paintButton)( hwnd, hdc, pressed, FALSE);
1864 if(pressed)
1865 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1867 ReleaseCapture();
1868 ReleaseDC( hwnd, hdc );
1870 /* If the item minimize or maximize of the sysmenu are not there */
1871 /* or if the style is not present, do nothing */
1872 if ((!pressed) || (state == 0xFFFFFFFF))
1873 return;
1875 if (wParam == HTMINBUTTON)
1876 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1877 else
1878 SendMessageA( hwnd, WM_SYSCOMMAND,
1879 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1882 /***********************************************************************
1883 * NC_TrackMinMaxBox
1885 * Track a mouse button press on the minimize or maximize box.
1887 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1889 MSG msg;
1890 HDC hdc = GetWindowDC( hwnd );
1891 BOOL pressed = TRUE;
1892 void (*paintButton)(HWND, HDC16, BOOL);
1894 SetCapture( hwnd );
1896 if (wParam == HTMINBUTTON)
1897 paintButton = &NC_DrawMinButton;
1898 else
1899 paintButton = &NC_DrawMaxButton;
1901 (*paintButton)( hwnd, hdc, TRUE);
1903 while(1)
1905 BOOL oldstate = pressed;
1906 MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
1907 0, PM_REMOVE, FALSE, NULL );
1909 if(msg.message == WM_LBUTTONUP)
1910 break;
1912 if(msg.message != WM_MOUSEMOVE)
1913 continue;
1915 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1916 if (pressed != oldstate)
1917 (*paintButton)( hwnd, hdc, pressed);
1920 if(pressed)
1921 (*paintButton)( hwnd, hdc, FALSE);
1923 ReleaseCapture();
1924 ReleaseDC( hwnd, hdc );
1926 if (!pressed) return;
1928 if (wParam == HTMINBUTTON)
1929 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1930 else
1931 SendMessageA( hwnd, WM_SYSCOMMAND,
1932 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1936 /***********************************************************************
1937 * NC_TrackCloseButton95
1939 * Track a mouse button press on the Win95 close button.
1941 static void
1942 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1944 MSG msg;
1945 HDC hdc;
1946 BOOL pressed = TRUE;
1947 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1948 UINT state;
1950 if(hSysMenu == 0)
1951 return;
1953 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1955 /* If the item close of the sysmenu is disabled or not there do nothing */
1956 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1957 return;
1959 hdc = GetWindowDC( hwnd );
1961 SetCapture( hwnd );
1963 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1965 while(1)
1967 BOOL oldstate = pressed;
1968 MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
1969 0, PM_REMOVE, FALSE, NULL );
1971 if(msg.message == WM_LBUTTONUP)
1972 break;
1974 if(msg.message != WM_MOUSEMOVE)
1975 continue;
1977 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1978 if (pressed != oldstate)
1979 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1982 if(pressed)
1983 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1985 ReleaseCapture();
1986 ReleaseDC( hwnd, hdc );
1987 if (!pressed) return;
1989 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1993 /***********************************************************************
1994 * NC_TrackScrollBar
1996 * Track a mouse button press on the horizontal or vertical scroll-bar.
1998 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2000 MSG16 *msg;
2001 INT scrollbar;
2002 WND *wndPtr = WIN_FindWndPtr( hwnd );
2004 if ((wParam & 0xfff0) == SC_HSCROLL)
2006 if ((wParam & 0x0f) != HTHSCROLL) goto END;
2007 scrollbar = SB_HORZ;
2009 else /* SC_VSCROLL */
2011 if ((wParam & 0x0f) != HTVSCROLL) goto END;
2012 scrollbar = SB_VERT;
2015 if (!(msg = SEGPTR_NEW(MSG16))) goto END;
2016 pt.x -= wndPtr->rectWindow.left;
2017 pt.y -= wndPtr->rectWindow.top;
2018 SetCapture( hwnd );
2019 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
2023 GetMessage16( SEGPTR_GET(msg), 0, 0, 0 );
2024 switch(msg->message)
2026 case WM_LBUTTONUP:
2027 case WM_MOUSEMOVE:
2028 case WM_SYSTIMER:
2029 pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left -
2030 wndPtr->rectWindow.left;
2031 pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top -
2032 wndPtr->rectWindow.top;
2033 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
2034 break;
2035 default:
2036 TranslateMessage16( msg );
2037 DispatchMessage16( msg );
2038 break;
2040 if (!IsWindow( hwnd ))
2042 ReleaseCapture();
2043 break;
2045 } while (msg->message != WM_LBUTTONUP);
2046 SEGPTR_FREE(msg);
2047 END:
2048 WIN_ReleaseWndPtr(wndPtr);
2051 /***********************************************************************
2052 * NC_HandleNCLButtonDown
2054 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2056 LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
2058 HWND hwnd = pWnd->hwndSelf;
2060 switch(wParam) /* Hit test */
2062 case HTCAPTION:
2063 hwnd = WIN_GetTopParent(hwnd);
2065 if( WINPOS_SetActiveWindow(hwnd, TRUE, TRUE) || (GetActiveWindow() == hwnd) )
2066 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2067 break;
2069 case HTSYSMENU:
2070 if( pWnd->dwStyle & WS_SYSMENU )
2072 if( !(pWnd->dwStyle & WS_MINIMIZE) )
2074 HDC hDC = GetWindowDC(hwnd);
2075 if (TWEAK_WineLook == WIN31_LOOK)
2076 NC_DrawSysButton( hwnd, hDC, TRUE );
2077 else
2078 NC_DrawSysButton95( hwnd, hDC, TRUE );
2079 ReleaseDC( hwnd, hDC );
2081 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2083 break;
2085 case HTMENU:
2086 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2087 break;
2089 case HTHSCROLL:
2090 SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2091 break;
2093 case HTVSCROLL:
2094 SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2095 break;
2097 case HTMINBUTTON:
2098 case HTMAXBUTTON:
2099 if (TWEAK_WineLook == WIN31_LOOK)
2100 NC_TrackMinMaxBox( hwnd, wParam );
2101 else
2102 NC_TrackMinMaxBox95( hwnd, wParam );
2103 break;
2105 case HTCLOSE:
2106 if (TWEAK_WineLook >= WIN95_LOOK)
2107 NC_TrackCloseButton95 (hwnd, wParam);
2108 break;
2110 case HTLEFT:
2111 case HTRIGHT:
2112 case HTTOP:
2113 case HTTOPLEFT:
2114 case HTTOPRIGHT:
2115 case HTBOTTOM:
2116 case HTBOTTOMLEFT:
2117 case HTBOTTOMRIGHT:
2118 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2119 SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2120 break;
2122 case HTBORDER:
2123 break;
2125 return 0;
2129 /***********************************************************************
2130 * NC_HandleNCLButtonDblClk
2132 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2134 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam )
2137 * if this is an icon, send a restore since we are handling
2138 * a double click
2140 if (pWnd->dwStyle & WS_MINIMIZE)
2142 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
2143 return 0;
2146 switch(wParam) /* Hit test */
2148 case HTCAPTION:
2149 /* stop processing if WS_MAXIMIZEBOX is missing */
2150 if (pWnd->dwStyle & WS_MAXIMIZEBOX)
2151 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
2152 (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
2153 lParam );
2154 break;
2156 case HTSYSMENU:
2157 if (!(GetClassWord(pWnd->hwndSelf, GCW_STYLE) & CS_NOCLOSE))
2158 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
2159 break;
2161 case HTHSCROLL:
2162 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL,
2163 lParam );
2164 break;
2166 case HTVSCROLL:
2167 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL,
2168 lParam );
2169 break;
2171 return 0;
2175 /***********************************************************************
2176 * NC_HandleSysCommand
2178 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2180 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
2182 WND *wndPtr = WIN_FindWndPtr( hwnd );
2183 UINT16 uCommand = wParam & 0xFFF0;
2185 TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
2187 if (wndPtr->parent && (uCommand != SC_KEYMENU))
2188 ScreenToClient( wndPtr->parent->hwndSelf, &pt );
2190 switch (uCommand)
2192 case SC_SIZE:
2193 case SC_MOVE:
2194 if (USER_Driver.pSysCommandSizeMove)
2195 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2196 break;
2198 case SC_MINIMIZE:
2199 if (hwnd == GetForegroundWindow())
2200 ShowOwnedPopups(hwnd,FALSE);
2201 ShowWindow( hwnd, SW_MINIMIZE );
2202 break;
2204 case SC_MAXIMIZE:
2205 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2206 ShowOwnedPopups(hwnd,TRUE);
2207 ShowWindow( hwnd, SW_MAXIMIZE );
2208 break;
2210 case SC_RESTORE:
2211 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2212 ShowOwnedPopups(hwnd,TRUE);
2213 ShowWindow( hwnd, SW_RESTORE );
2214 break;
2216 case SC_CLOSE:
2217 WIN_ReleaseWndPtr(wndPtr);
2218 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2220 case SC_VSCROLL:
2221 case SC_HSCROLL:
2222 NC_TrackScrollBar( hwnd, wParam, pt );
2223 break;
2225 case SC_MOUSEMENU:
2226 MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt );
2227 break;
2229 case SC_KEYMENU:
2230 MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
2231 break;
2233 case SC_TASKLIST:
2234 WinExec( "taskman.exe", SW_SHOWNORMAL );
2235 break;
2237 case SC_SCREENSAVE:
2238 if (wParam == SC_ABOUTWINE)
2240 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2241 if (hmodule)
2243 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2244 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2245 FreeLibrary( hmodule );
2248 else
2249 if (wParam == SC_PUTMARK)
2250 TRACE_(shell)("Mark requested by user\n");
2251 break;
2253 case SC_HOTKEY:
2254 case SC_ARRANGE:
2255 case SC_NEXTWINDOW:
2256 case SC_PREVWINDOW:
2257 FIXME("unimplemented!\n");
2258 break;
2260 WIN_ReleaseWndPtr(wndPtr);
2261 return 0;
2264 /*************************************************************
2265 * NC_DrawGrayButton
2267 * Stub for the grayed button of the caption
2269 *************************************************************/
2271 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2273 HBITMAP hMaskBmp;
2274 HDC hdcMask = CreateCompatibleDC (0);
2275 HBRUSH hOldBrush;
2277 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2279 if(hMaskBmp == 0)
2280 return FALSE;
2282 SelectObject (hdcMask, hMaskBmp);
2284 /* Draw the grayed bitmap using the mask */
2285 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2286 BitBlt (hdc, x, y, 12, 10,
2287 hdcMask, 0, 0, 0xB8074A);
2289 /* Clean up */
2290 SelectObject (hdc, hOldBrush);
2291 DeleteObject(hMaskBmp);
2292 DeleteDC (hdcMask);
2294 return TRUE;