Serge Ivanov
[wine/multimedia.git] / windows / nonclient.c
bloba2bf12d425039a13cc1002de88128b9dbabcddba
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 "cursoricon.h"
18 #include "dialog.h"
19 #include "menu.h"
20 #include "winpos.h"
21 #include "hook.h"
22 #include "scroll.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "selectors.h"
26 #include "tweak.h"
27 #include "debugtools.h"
28 #include "options.h"
29 #include "shellapi.h"
30 #include "cache.h"
31 #include "bitmap.h"
33 DEFAULT_DEBUG_CHANNEL(nonclient)
34 DECLARE_DEBUG_CHANNEL(shell)
36 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
38 static HBITMAP16 hbitmapClose = 0;
39 static HBITMAP16 hbitmapCloseD = 0;
40 static HBITMAP16 hbitmapMinimize = 0;
41 static HBITMAP16 hbitmapMinimizeD = 0;
42 static HBITMAP16 hbitmapMaximize = 0;
43 static HBITMAP16 hbitmapMaximizeD = 0;
44 static HBITMAP16 hbitmapRestore = 0;
45 static HBITMAP16 hbitmapRestoreD = 0;
47 BYTE lpGrayMask[] = { 0xAA, 0xA0,
48 0x55, 0x50,
49 0xAA, 0xA0,
50 0x55, 0x50,
51 0xAA, 0xA0,
52 0x55, 0x50,
53 0xAA, 0xA0,
54 0x55, 0x50,
55 0xAA, 0xA0,
56 0x55, 0x50};
58 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
59 #define SC_PUTMARK (SC_SCREENSAVE+2)
61 /* Some useful macros */
62 #define HAS_DLGFRAME(style,exStyle) \
63 (((exStyle) & WS_EX_DLGMODALFRAME) || \
64 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
66 #define HAS_THICKFRAME(style,exStyle) \
67 (((style) & WS_THICKFRAME) && \
68 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
70 #define HAS_THINFRAME(style) \
71 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
73 #define HAS_BIGFRAME(style,exStyle) \
74 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
75 ((exStyle) & WS_EX_DLGMODALFRAME))
77 #define HAS_ANYFRAME(style,exStyle) \
78 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
79 ((exStyle) & WS_EX_DLGMODALFRAME) || \
80 !((style) & (WS_CHILD | WS_POPUP)))
82 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
84 #define ON_LEFT_BORDER(hit) \
85 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
86 #define ON_RIGHT_BORDER(hit) \
87 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
88 #define ON_TOP_BORDER(hit) \
89 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
90 #define ON_BOTTOM_BORDER(hit) \
91 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
93 /***********************************************************************
94 * WIN_WindowNeedsWMBorder
96 * This method defines the rules for a window to have a WM border,
97 * caption... It is used for consitency purposes.
99 BOOL WIN_WindowNeedsWMBorder( DWORD style, DWORD exStyle )
101 if (!(style & WS_CHILD) &&
102 Options.managed &&
103 !(exStyle & WS_EX_TOOLWINDOW) &&
104 ( ((style & WS_CAPTION) == WS_CAPTION) ||
105 (style & WS_THICKFRAME)))
106 return TRUE;
107 if (exStyle & WS_EX_TRAYWINDOW)
108 return TRUE;
109 return FALSE;
112 /***********************************************************************
113 * NC_AdjustRect
115 * Compute the size of the window rectangle from the size of the
116 * client rectangle.
118 static void NC_AdjustRect( LPRECT16 rect, DWORD style, BOOL menu,
119 DWORD exStyle )
121 if (TWEAK_WineLook > WIN31_LOOK)
122 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
124 if(style & WS_ICONIC) return;
125 /* Decide if the window will be managed (see CreateWindowEx) */
126 if (!WIN_WindowNeedsWMBorder(style, exStyle))
128 if (HAS_THICKFRAME( style, exStyle ))
129 InflateRect16( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
130 else
131 if (HAS_DLGFRAME( style, exStyle ))
132 InflateRect16( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
133 else
134 if (HAS_THINFRAME( style ))
135 InflateRect16( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
137 if ((style & WS_CAPTION) == WS_CAPTION)
138 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
140 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
142 if (style & WS_VSCROLL) {
143 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
144 if(!HAS_ANYFRAME( style, exStyle ))
145 rect->right++;
148 if (style & WS_HSCROLL) {
149 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
150 if(!HAS_ANYFRAME( style, exStyle ))
151 rect->bottom++;
156 /******************************************************************************
157 * NC_AdjustRectOuter95
159 * Computes the size of the "outside" parts of the window based on the
160 * parameters of the client area.
162 + PARAMS
163 * LPRECT16 rect
164 * DWORD style
165 * BOOL menu
166 * DWORD exStyle
168 * NOTES
169 * "Outer" parts of a window means the whole window frame, caption and
170 * menu bar. It does not include "inner" parts of the frame like client
171 * edge, static edge or scroll bars.
173 * Revision history
174 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
175 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
177 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
178 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
179 * NC_AdjustRectInner95 and added handling of Win95 styles.
181 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
182 * Streamlined window style checks.
184 *****************************************************************************/
186 static void
187 NC_AdjustRectOuter95 (LPRECT16 rect, DWORD style, BOOL menu, DWORD exStyle)
189 if(style & WS_ICONIC) return;
191 /* Decide if the window will be managed (see CreateWindowEx) */
192 if (!WIN_WindowNeedsWMBorder(style, exStyle))
194 if (HAS_THICKFRAME( style, exStyle ))
195 InflateRect16( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
196 else
197 if (HAS_DLGFRAME( style, exStyle ))
198 InflateRect16(rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
199 else
200 if (HAS_THINFRAME( style ))
201 InflateRect16( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
203 if ((style & WS_CAPTION) == WS_CAPTION)
205 if (exStyle & WS_EX_TOOLWINDOW)
206 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
207 else
208 rect->top -= GetSystemMetrics(SM_CYCAPTION);
212 if (menu)
213 rect->top -= GetSystemMetrics(SM_CYMENU);
217 /******************************************************************************
218 * NC_AdjustRectInner95
220 * Computes the size of the "inside" part of the window based on the
221 * parameters of the client area.
223 + PARAMS
224 * LPRECT16 rect
225 * DWORD style
226 * DWORD exStyle
228 * NOTES
229 * "Inner" part of a window means the window frame inside of the flat
230 * window frame. It includes the client edge, the static edge and the
231 * scroll bars.
233 * Revision history
234 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
235 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
237 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
238 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
239 * NC_AdjustRectInner95 and added handling of Win95 styles.
241 *****************************************************************************/
243 static void
244 NC_AdjustRectInner95 (LPRECT16 rect, DWORD style, DWORD exStyle)
246 if(style & WS_ICONIC) return;
248 if (exStyle & WS_EX_CLIENTEDGE)
249 InflateRect16 (rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
251 if (exStyle & WS_EX_STATICEDGE)
252 InflateRect16 (rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
254 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
255 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
259 /***********************************************************************
260 * DrawCaption16 [USER.660] Draws a caption bar
262 * PARAMS
263 * hwnd [I]
264 * hdc [I]
265 * lpRect [I]
266 * uFlags [I]
268 * RETURNS
269 * Success:
270 * Failure:
273 BOOL16 WINAPI
274 DrawCaption16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, UINT16 uFlags)
276 RECT rect32;
278 if (rect)
279 CONV_RECT16TO32 (rect, &rect32);
281 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect ? &rect32 : NULL,
282 0, 0, NULL, uFlags & 0x1F);
286 /***********************************************************************
287 * DrawCaption [USER32.154] Draws a caption bar
289 * PARAMS
290 * hwnd [I]
291 * hdc [I]
292 * lpRect [I]
293 * uFlags [I]
295 * RETURNS
296 * Success:
297 * Failure:
300 BOOL WINAPI
301 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
303 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
307 /***********************************************************************
308 * DrawCaptionTemp16 [USER.657]
310 * PARAMS
312 * RETURNS
313 * Success:
314 * Failure:
317 BOOL16 WINAPI
318 DrawCaptionTemp16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, HFONT16 hFont,
319 HICON16 hIcon, LPCSTR str, UINT16 uFlags)
321 RECT rect32;
323 if (rect)
324 CONV_RECT16TO32(rect,&rect32);
326 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect?&rect32:NULL, hFont,
327 hIcon, str, uFlags & 0x1F);
331 /***********************************************************************
332 * DrawCaptionTempA [USER32.599]
334 * PARAMS
336 * RETURNS
337 * Success:
338 * Failure:
341 BOOL WINAPI
342 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
343 HICON hIcon, LPCSTR str, UINT uFlags)
345 RECT rc = *rect;
347 TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
348 hwnd, hdc, rect, hFont, hIcon, str, uFlags);
350 /* drawing background */
351 if (uFlags & DC_INBUTTON) {
352 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
354 if (uFlags & DC_ACTIVE) {
355 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
356 PatBlt (hdc, rc.left, rc.top,
357 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
358 SelectObject (hdc, hbr);
361 else {
362 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
363 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
367 /* drawing icon */
368 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
369 POINT pt;
371 pt.x = rc.left + 2;
372 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
374 if (hIcon) {
375 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
376 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
378 else {
379 WND* wndPtr = WIN_FindWndPtr(hwnd);
380 HICON hAppIcon = (HICON) NC_IconForWindow(wndPtr);
381 DrawIconEx (hdc, pt.x, pt.y, hAppIcon, GetSystemMetrics(SM_CXSMICON),
382 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
383 WIN_ReleaseWndPtr(wndPtr);
386 rc.left += (rc.bottom - rc.top);
389 /* drawing text */
390 if (uFlags & DC_TEXT) {
391 HFONT hOldFont;
393 if (uFlags & DC_INBUTTON)
394 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
395 else if (uFlags & DC_ACTIVE)
396 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
397 else
398 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
400 SetBkMode (hdc, TRANSPARENT);
402 if (hFont)
403 hOldFont = SelectObject (hdc, hFont);
404 else {
405 NONCLIENTMETRICSA nclm;
406 HFONT hNewFont;
407 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
408 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
409 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
410 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
411 hOldFont = SelectObject (hdc, hNewFont);
414 if (str)
415 DrawTextA (hdc, str, -1, &rc,
416 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
417 else {
418 CHAR szText[128];
419 INT nLen;
420 nLen = GetWindowTextA (hwnd, szText, 128);
421 DrawTextA (hdc, szText, nLen, &rc,
422 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
425 if (hFont)
426 SelectObject (hdc, hOldFont);
427 else
428 DeleteObject (SelectObject (hdc, hOldFont));
431 /* drawing focus ??? */
432 if (uFlags & 0x2000)
433 FIXME("undocumented flag (0x2000)!\n");
435 return 0;
439 /***********************************************************************
440 * DrawCaptionTempW [USER32.602]
442 * PARAMS
444 * RETURNS
445 * Success:
446 * Failure:
449 BOOL WINAPI
450 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
451 HICON hIcon, LPCWSTR str, UINT uFlags)
453 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
454 BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
455 HeapFree (GetProcessHeap (), 0, p);
456 return res;
460 /***********************************************************************
461 * AdjustWindowRect16 (USER.102)
463 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
465 return AdjustWindowRectEx16( rect, style, menu, 0 );
469 /***********************************************************************
470 * AdjustWindowRect (USER32.2)
472 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
474 return AdjustWindowRectEx( rect, style, menu, 0 );
478 /***********************************************************************
479 * AdjustWindowRectEx16 (USER.454)
481 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
482 BOOL16 menu, DWORD exStyle )
484 /* Correct the window style */
486 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
487 style |= WS_CAPTION;
488 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
489 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
490 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
491 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
493 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
494 rect->left, rect->top, rect->right, rect->bottom,
495 style, menu, exStyle );
497 if (TWEAK_WineLook == WIN31_LOOK)
498 NC_AdjustRect( rect, style, menu, exStyle );
499 else {
500 NC_AdjustRectOuter95( rect, style, menu, exStyle );
501 NC_AdjustRectInner95( rect, style, exStyle );
504 return TRUE;
508 /***********************************************************************
509 * AdjustWindowRectEx (USER32.3)
511 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style,
512 BOOL menu, DWORD exStyle )
514 RECT16 rect16;
515 BOOL ret;
517 CONV_RECT32TO16( rect, &rect16 );
518 ret = AdjustWindowRectEx16( &rect16, style, (BOOL16)menu, exStyle );
519 CONV_RECT16TO32( &rect16, rect );
520 return ret;
524 /***********************************************************************
525 * NC_HandleNCCalcSize
527 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
529 LONG NC_HandleNCCalcSize( WND *pWnd, RECT *winRect )
531 RECT16 tmpRect = { 0, 0, 0, 0 };
532 LONG result = 0;
533 UINT style = (UINT) GetClassLongA(pWnd->hwndSelf, GCL_STYLE);
535 if (style & CS_VREDRAW) result |= WVR_VREDRAW;
536 if (style & CS_HREDRAW) result |= WVR_HREDRAW;
538 if( !( pWnd->dwStyle & WS_MINIMIZE ) ) {
539 if (TWEAK_WineLook == WIN31_LOOK)
540 NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
541 else
542 NC_AdjustRectOuter95( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
544 winRect->left -= tmpRect.left;
545 winRect->top -= tmpRect.top;
546 winRect->right -= tmpRect.right;
547 winRect->bottom -= tmpRect.bottom;
549 if (HAS_MENU(pWnd)) {
550 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
551 "at (%d, %d).\n", pWnd->hwndSelf,
552 winRect->right - winRect->left,
553 -tmpRect.left, -tmpRect.top );
555 winRect->top +=
556 MENU_GetMenuBarHeight( pWnd->hwndSelf,
557 winRect->right - winRect->left,
558 -tmpRect.left, -tmpRect.top ) + 1;
561 if (TWEAK_WineLook > WIN31_LOOK) {
562 SetRect16 (&tmpRect, 0, 0, 0, 0);
563 NC_AdjustRectInner95 (&tmpRect, pWnd->dwStyle, pWnd->dwExStyle);
564 winRect->left -= tmpRect.left;
565 winRect->top -= tmpRect.top;
566 winRect->right -= tmpRect.right;
567 winRect->bottom -= tmpRect.bottom;
570 return result;
574 /***********************************************************************
575 * NC_GetInsideRect
577 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
578 * but without the borders (if any).
579 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
581 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
583 WND * wndPtr = WIN_FindWndPtr( hwnd );
585 rect->top = rect->left = 0;
586 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
587 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
589 if ((wndPtr->dwStyle & WS_ICONIC) || (wndPtr->flags & WIN_MANAGED)) goto END;
591 /* Remove frame from rectangle */
592 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
593 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
594 else
595 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
597 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
598 /* FIXME: this isn't in NC_AdjustRect? why not? */
599 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
600 InflateRect( rect, -1, 0 );
602 else
603 if (HAS_THINFRAME( wndPtr->dwStyle ))
604 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
605 END:
606 WIN_ReleaseWndPtr(wndPtr);
607 return;
611 /***********************************************************************
612 * NC_GetInsideRect95
614 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
615 * but without the borders (if any).
616 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
619 static void
620 NC_GetInsideRect95 (HWND hwnd, RECT *rect)
622 WND * wndPtr = WIN_FindWndPtr( hwnd );
624 rect->top = rect->left = 0;
625 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
626 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
628 if ((wndPtr->dwStyle & WS_ICONIC) || (wndPtr->flags & WIN_MANAGED)) goto END;
630 /* Remove frame from rectangle */
631 if (HAS_THICKFRAME (wndPtr->dwStyle, wndPtr->dwExStyle))
633 InflateRect( rect, -GetSystemMetrics(SM_CXSIZEFRAME), -GetSystemMetrics(SM_CYSIZEFRAME) );
635 else if (HAS_DLGFRAME (wndPtr->dwStyle, wndPtr->dwExStyle ))
637 InflateRect( rect, -GetSystemMetrics(SM_CXFIXEDFRAME), -GetSystemMetrics(SM_CYFIXEDFRAME));
639 else if (HAS_THINFRAME (wndPtr->dwStyle))
641 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
644 /* We have additional border information if the window
645 * is a child (but not an MDI child) */
646 if ( (wndPtr->dwStyle & WS_CHILD) &&
647 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
649 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
650 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
652 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
653 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
655 END:
656 WIN_ReleaseWndPtr(wndPtr);
657 return;
661 /***********************************************************************
662 * NC_DoNCHitTest
664 * Handle a WM_NCHITTEST message. Called from NC_HandleNcHitTest().
667 static LONG NC_DoNCHitTest (WND *wndPtr, POINT16 pt )
669 RECT16 rect;
671 TRACE("hwnd=%04x pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
673 GetWindowRect16 (wndPtr->hwndSelf, &rect );
674 if (!PtInRect16( &rect, pt )) return HTNOWHERE;
676 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
678 if (!(wndPtr->flags & WIN_MANAGED))
680 /* Check borders */
681 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
683 InflateRect16( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
684 if (!PtInRect16( &rect, pt ))
686 /* Check top sizing border */
687 if (pt.y < rect.top)
689 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
690 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
691 return HTTOP;
693 /* Check bottom sizing border */
694 if (pt.y >= rect.bottom)
696 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
697 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
698 return HTBOTTOM;
700 /* Check left sizing border */
701 if (pt.x < rect.left)
703 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
704 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
705 return HTLEFT;
707 /* Check right sizing border */
708 if (pt.x >= rect.right)
710 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
711 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
712 return HTRIGHT;
716 else /* No thick frame */
718 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
719 InflateRect16(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
720 else if (HAS_THINFRAME( wndPtr->dwStyle ))
721 InflateRect16(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
722 if (!PtInRect16( &rect, pt )) return HTBORDER;
725 /* Check caption */
727 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
729 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
730 if (!PtInRect16( &rect, pt ))
732 /* Check system menu */
733 if (wndPtr->dwStyle & WS_SYSMENU)
734 rect.left += GetSystemMetrics(SM_CXSIZE);
735 if (pt.x <= rect.left) return HTSYSMENU;
737 /* Check maximize box */
738 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
739 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
741 if (pt.x >= rect.right) return HTMAXBUTTON;
742 /* Check minimize box */
743 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
744 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
745 if (pt.x >= rect.right) return HTMINBUTTON;
746 return HTCAPTION;
751 /* Check client area */
753 ScreenToClient16( wndPtr->hwndSelf, &pt );
754 GetClientRect16( wndPtr->hwndSelf, &rect );
755 if (PtInRect16( &rect, pt )) return HTCLIENT;
757 /* Check vertical scroll bar */
759 if (wndPtr->dwStyle & WS_VSCROLL)
761 rect.right += GetSystemMetrics(SM_CXVSCROLL);
762 if (PtInRect16( &rect, pt )) return HTVSCROLL;
765 /* Check horizontal scroll bar */
767 if (wndPtr->dwStyle & WS_HSCROLL)
769 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
770 if (PtInRect16( &rect, pt ))
772 /* Check size box */
773 if ((wndPtr->dwStyle & WS_VSCROLL) &&
774 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
775 return HTSIZE;
776 return HTHSCROLL;
780 /* Check menu bar */
782 if (HAS_MENU(wndPtr))
784 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
785 return HTMENU;
788 /* Should never get here */
789 return HTERROR;
793 /***********************************************************************
794 * NC_DoNCHitTest95
796 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
798 * FIXME: Just a modified copy of the Win 3.1 version.
801 static LONG
802 NC_DoNCHitTest95 (WND *wndPtr, POINT16 pt )
804 RECT16 rect;
806 TRACE("hwnd=%04x pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
808 GetWindowRect16 (wndPtr->hwndSelf, &rect );
809 if (!PtInRect16( &rect, pt )) return HTNOWHERE;
811 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
813 if (!(wndPtr->flags & WIN_MANAGED))
815 /* Check borders */
816 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
818 InflateRect16( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
819 if (!PtInRect16( &rect, pt ))
821 /* Check top sizing border */
822 if (pt.y < rect.top)
824 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
825 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
826 return HTTOP;
828 /* Check bottom sizing border */
829 if (pt.y >= rect.bottom)
831 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
832 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
833 return HTBOTTOM;
835 /* Check left sizing border */
836 if (pt.x < rect.left)
838 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
839 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
840 return HTLEFT;
842 /* Check right sizing border */
843 if (pt.x >= rect.right)
845 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
846 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
847 return HTRIGHT;
851 else /* No thick frame */
853 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
854 InflateRect16(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
855 else if (HAS_THINFRAME( wndPtr->dwStyle ))
856 InflateRect16(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
857 if (!PtInRect16( &rect, pt )) return HTBORDER;
860 /* Check caption */
862 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
864 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
865 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
866 else
867 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
868 if (!PtInRect16( &rect, pt ))
870 /* Check system menu */
871 if(wndPtr->dwStyle & WS_SYSMENU)
873 if (NC_IconForWindow(wndPtr))
874 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
876 if (pt.x < rect.left) return HTSYSMENU;
878 /* Check close button */
879 if (wndPtr->dwStyle & WS_SYSMENU)
880 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
881 if (pt.x > rect.right) return HTCLOSE;
883 /* Check maximize box */
884 /* In win95 there is automatically a Maximize button when there is a minimize one*/
885 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
886 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
887 if (pt.x > rect.right) return HTMAXBUTTON;
889 /* Check minimize box */
890 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
891 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
892 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
894 if (pt.x > rect.right) return HTMINBUTTON;
895 return HTCAPTION;
900 /* Check client area */
902 ScreenToClient16( wndPtr->hwndSelf, &pt );
903 GetClientRect16( wndPtr->hwndSelf, &rect );
904 if (PtInRect16( &rect, pt )) return HTCLIENT;
906 /* Check vertical scroll bar */
908 if (wndPtr->dwStyle & WS_VSCROLL)
910 rect.right += GetSystemMetrics(SM_CXVSCROLL);
911 if (PtInRect16( &rect, pt )) return HTVSCROLL;
914 /* Check horizontal scroll bar */
916 if (wndPtr->dwStyle & WS_HSCROLL)
918 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
919 if (PtInRect16( &rect, pt ))
921 /* Check size box */
922 if ((wndPtr->dwStyle & WS_VSCROLL) &&
923 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
924 return HTSIZE;
925 return HTHSCROLL;
929 /* Check menu bar */
931 if (HAS_MENU(wndPtr))
933 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
934 return HTMENU;
937 /* Should never get here */
938 return HTERROR;
942 /***********************************************************************
943 * NC_HandleNCHitTest
945 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
947 LONG
948 NC_HandleNCHitTest (HWND hwnd , POINT16 pt)
950 LONG retvalue;
951 WND *wndPtr = WIN_FindWndPtr (hwnd);
953 if (!wndPtr)
954 return HTERROR;
956 if (TWEAK_WineLook == WIN31_LOOK)
957 retvalue = NC_DoNCHitTest (wndPtr, pt);
958 else
959 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
960 WIN_ReleaseWndPtr(wndPtr);
961 return retvalue;
965 /***********************************************************************
966 * NC_DrawSysButton
968 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
970 RECT rect;
971 HDC hdcMem;
972 HBITMAP hbitmap;
973 WND *wndPtr = WIN_FindWndPtr( hwnd );
975 if( !(wndPtr->flags & WIN_MANAGED) )
977 NC_GetInsideRect( hwnd, &rect );
978 hdcMem = CreateCompatibleDC( hdc );
979 hbitmap = SelectObject( hdcMem, hbitmapClose );
980 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
981 hdcMem, (wndPtr->dwStyle & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
982 down ? NOTSRCCOPY : SRCCOPY );
983 SelectObject( hdcMem, hbitmap );
984 DeleteDC( hdcMem );
986 WIN_ReleaseWndPtr(wndPtr);
990 /***********************************************************************
991 * NC_DrawMaxButton
993 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
995 RECT rect;
996 WND *wndPtr = WIN_FindWndPtr( hwnd );
997 HDC hdcMem;
999 if( !(wndPtr->flags & WIN_MANAGED) )
1001 NC_GetInsideRect( hwnd, &rect );
1002 hdcMem = CreateCompatibleDC( hdc );
1003 SelectObject( hdcMem, (IsZoomed(hwnd)
1004 ? (down ? hbitmapRestoreD : hbitmapRestore)
1005 : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
1006 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
1007 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
1008 SRCCOPY );
1009 DeleteDC( hdcMem );
1011 WIN_ReleaseWndPtr(wndPtr);
1016 /***********************************************************************
1017 * NC_DrawMinButton
1019 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
1021 RECT rect;
1022 WND *wndPtr = WIN_FindWndPtr( hwnd );
1023 HDC hdcMem;
1025 if( !(wndPtr->flags & WIN_MANAGED) )
1027 NC_GetInsideRect( hwnd, &rect );
1028 hdcMem = CreateCompatibleDC( hdc );
1029 SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
1030 if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
1031 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
1032 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
1033 SRCCOPY );
1034 DeleteDC( hdcMem );
1036 WIN_ReleaseWndPtr(wndPtr);
1040 /******************************************************************************
1042 * void NC_DrawSysButton95(
1043 * HWND hwnd,
1044 * HDC hdc,
1045 * BOOL down )
1047 * Draws the Win95 system icon.
1049 * Revision history
1050 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1051 * Original implementation from NC_DrawSysButton source.
1052 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1053 * Fixed most bugs.
1055 *****************************************************************************/
1057 BOOL
1058 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
1060 WND *wndPtr = WIN_FindWndPtr( hwnd );
1062 if( !(wndPtr->flags & WIN_MANAGED) )
1064 HICON hIcon;
1065 RECT rect;
1067 NC_GetInsideRect95( hwnd, &rect );
1069 hIcon = NC_IconForWindow( wndPtr );
1071 if (hIcon)
1072 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
1073 GetSystemMetrics(SM_CXSMICON),
1074 GetSystemMetrics(SM_CYSMICON),
1075 0, 0, DI_NORMAL);
1077 WIN_ReleaseWndPtr(wndPtr);
1078 return (hIcon != 0);
1080 WIN_ReleaseWndPtr(wndPtr);
1081 return FALSE;
1085 /******************************************************************************
1087 * void NC_DrawCloseButton95(
1088 * HWND hwnd,
1089 * HDC hdc,
1090 * BOOL down,
1091 * BOOL bGrayed )
1093 * Draws the Win95 close button.
1095 * If bGrayed is true, then draw a disabled Close button
1097 * Revision history
1098 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1099 * Original implementation from NC_DrawSysButton95 source.
1101 *****************************************************************************/
1103 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
1105 RECT rect;
1106 HDC hdcMem;
1107 WND *wndPtr = WIN_FindWndPtr( hwnd );
1109 if( !(wndPtr->flags & WIN_MANAGED) )
1111 BITMAP bmp;
1112 HBITMAP hBmp, hOldBmp;
1114 NC_GetInsideRect95( hwnd, &rect );
1116 /* A tool window has a smaller Close button */
1117 if(wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
1119 RECT toolRect;
1120 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
1121 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
1122 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1124 toolRect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1125 toolRect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1126 toolRect.bottom = toolRect.top + iBmpHeight;
1127 toolRect.right = toolRect.left + iBmpWidth;
1128 DrawFrameControl(hdc,&toolRect,
1129 DFC_CAPTION,DFCS_CAPTIONCLOSE |
1130 down ? DFCS_PUSHED : 0 |
1131 bGrayed ? DFCS_INACTIVE : 0);
1133 else
1135 hdcMem = CreateCompatibleDC( hdc );
1136 hBmp = down ? hbitmapCloseD : hbitmapClose;
1137 hOldBmp = SelectObject (hdcMem, hBmp);
1138 GetObjectA (hBmp, sizeof(BITMAP), &bmp);
1140 BitBlt (hdc, rect.right - (GetSystemMetrics(SM_CYCAPTION) + 1 + bmp.bmWidth) / 2,
1141 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
1142 bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY);
1144 if(bGrayed)
1145 NC_DrawGrayButton(hdc,rect.right - (GetSystemMetrics(SM_CYCAPTION) + 1 + bmp.bmWidth) / 2 + 2,
1146 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
1148 SelectObject (hdcMem, hOldBmp);
1149 DeleteDC (hdcMem);
1152 WIN_ReleaseWndPtr(wndPtr);
1155 /******************************************************************************
1157 * NC_DrawMaxButton95(
1158 * HWND hwnd,
1159 * HDC16 hdc,
1160 * BOOL down
1161 * BOOL bGrayed )
1163 * Draws the maximize button for Win95 style windows.
1165 * If bGrayed is true, then draw a disabled Maximize button
1167 * Bugs
1168 * Many. Spacing might still be incorrect. Need to fit a close
1169 * button between the max button and the edge.
1170 * Should scale the image with the title bar. And more...
1172 * Revision history
1173 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1174 * Original implementation.
1176 *****************************************************************************/
1178 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1180 RECT rect;
1181 HDC hdcMem;
1182 WND *wndPtr = WIN_FindWndPtr( hwnd );
1184 if( !(wndPtr->flags & WIN_MANAGED))
1186 BITMAP bmp;
1187 HBITMAP hBmp,hOldBmp;
1189 NC_GetInsideRect95( hwnd, &rect );
1190 hdcMem = CreateCompatibleDC( hdc );
1191 hBmp = IsZoomed(hwnd) ?
1192 (down ? hbitmapRestoreD : hbitmapRestore ) :
1193 (down ? hbitmapMaximizeD: hbitmapMaximize);
1194 hOldBmp=SelectObject( hdcMem, hBmp );
1195 GetObjectA (hBmp, sizeof(BITMAP), &bmp);
1197 if (wndPtr->dwStyle & WS_SYSMENU)
1198 rect.right -= GetSystemMetrics(SM_CYCAPTION) + 1;
1200 BitBlt( hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2,
1201 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
1202 bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY );
1204 if(bGrayed)
1205 NC_DrawGrayButton(hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2 + 2,
1206 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
1209 SelectObject (hdcMem, hOldBmp);
1210 DeleteDC( hdcMem );
1212 WIN_ReleaseWndPtr(wndPtr);
1215 /******************************************************************************
1217 * NC_DrawMinButton95(
1218 * HWND hwnd,
1219 * HDC16 hdc,
1220 * BOOL down,
1221 * BOOL bGrayed )
1223 * Draws the minimize button for Win95 style windows.
1225 * If bGrayed is true, then draw a disabled Minimize button
1227 * Bugs
1228 * Many. Spacing is still incorrect. Should scale the image with the
1229 * title bar. And more...
1231 * Revision history
1232 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1233 * Original implementation.
1235 *****************************************************************************/
1237 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1239 RECT rect;
1240 HDC hdcMem;
1241 WND *wndPtr = WIN_FindWndPtr( hwnd );
1243 if( !(wndPtr->flags & WIN_MANAGED))
1246 BITMAP bmp;
1247 HBITMAP hBmp,hOldBmp;
1249 NC_GetInsideRect95( hwnd, &rect );
1251 hdcMem = CreateCompatibleDC( hdc );
1252 hBmp = down ? hbitmapMinimizeD : hbitmapMinimize;
1253 hOldBmp= SelectObject( hdcMem, hBmp );
1254 GetObjectA (hBmp, sizeof(BITMAP), &bmp);
1256 if (wndPtr->dwStyle & WS_SYSMENU)
1257 rect.right -= GetSystemMetrics(SM_CYCAPTION) + 1;
1259 /* In win 95 there is always a Maximize box when there is a Minimize one */
1260 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX) || (wndPtr->dwStyle & WS_MINIMIZEBOX))
1261 rect.right += -1 - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2;
1263 BitBlt( hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2,
1264 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2,
1265 bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY );
1267 if(bGrayed)
1268 NC_DrawGrayButton(hdc, rect.right - (GetSystemMetrics(SM_CXSIZE) + bmp.bmWidth) / 2 + 2,
1269 rect.top + (GetSystemMetrics(SM_CYCAPTION) - 1 - bmp.bmHeight) / 2 + 2);
1272 SelectObject (hdcMem, hOldBmp);
1273 DeleteDC( hdcMem );
1275 WIN_ReleaseWndPtr(wndPtr);
1278 /***********************************************************************
1279 * NC_DrawFrame
1281 * Draw a window frame inside the given rectangle, and update the rectangle.
1282 * The correct pen for the frame must be selected in the DC.
1284 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1285 BOOL active )
1287 INT width, height;
1289 if (TWEAK_WineLook != WIN31_LOOK)
1290 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1292 if (dlgFrame)
1294 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1295 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1296 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1297 COLOR_INACTIVECAPTION) );
1299 else
1301 width = GetSystemMetrics(SM_CXFRAME) - 2;
1302 height = GetSystemMetrics(SM_CYFRAME) - 2;
1303 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1304 COLOR_INACTIVEBORDER) );
1307 /* Draw frame */
1308 PatBlt( hdc, rect->left, rect->top,
1309 rect->right - rect->left, height, PATCOPY );
1310 PatBlt( hdc, rect->left, rect->top,
1311 width, rect->bottom - rect->top, PATCOPY );
1312 PatBlt( hdc, rect->left, rect->bottom - 1,
1313 rect->right - rect->left, -height, PATCOPY );
1314 PatBlt( hdc, rect->right - 1, rect->top,
1315 -width, rect->bottom - rect->top, PATCOPY );
1317 if (dlgFrame)
1319 InflateRect( rect, -width, -height );
1321 else
1323 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1324 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1326 /* Draw inner rectangle */
1328 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1329 Rectangle( hdc, rect->left + width, rect->top + height,
1330 rect->right - width , rect->bottom - height );
1332 /* Draw the decorations */
1334 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1335 LineTo( hdc, rect->left + width, rect->top + decYOff );
1336 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1337 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1338 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1339 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1340 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1341 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1343 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1344 LineTo( hdc, rect->left + decXOff, rect->top + height);
1345 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1346 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1347 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1348 LineTo( hdc, rect->right - decXOff, rect->top + height );
1349 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1350 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1352 InflateRect( rect, -width - 1, -height - 1 );
1357 /******************************************************************************
1359 * void NC_DrawFrame95(
1360 * HDC hdc,
1361 * RECT *rect,
1362 * BOOL dlgFrame,
1363 * BOOL active )
1365 * Draw a window frame inside the given rectangle, and update the rectangle.
1366 * The correct pen for the frame must be selected in the DC.
1368 * Bugs
1369 * Many. First, just what IS a frame in Win95? Note that the 3D look
1370 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1371 * edge. The inner rectangle just inside the frame is handled by the
1372 * Caption code.
1374 * In short, for most people, this function should be a nop (unless
1375 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1376 * them lately, but just to get this code right). Even so, it doesn't
1377 * appear to be so. It's being worked on...
1379 * Revision history
1380 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1381 * Original implementation (based on NC_DrawFrame)
1382 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1383 * Some minor fixes.
1384 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1385 * Fixed a fix or something.
1387 *****************************************************************************/
1389 static void NC_DrawFrame95(
1390 HDC hdc,
1391 RECT *rect,
1392 BOOL dlgFrame,
1393 BOOL active )
1395 INT width, height;
1397 if (dlgFrame)
1399 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1400 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1402 else
1404 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXEDGE);
1405 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYEDGE);
1408 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1409 COLOR_INACTIVEBORDER) );
1411 /* Draw frame */
1412 PatBlt( hdc, rect->left, rect->top,
1413 rect->right - rect->left, height, PATCOPY );
1414 PatBlt( hdc, rect->left, rect->top,
1415 width, rect->bottom - rect->top, PATCOPY );
1416 PatBlt( hdc, rect->left, rect->bottom - 1,
1417 rect->right - rect->left, -height, PATCOPY );
1418 PatBlt( hdc, rect->right - 1, rect->top,
1419 -width, rect->bottom - rect->top, PATCOPY );
1421 InflateRect( rect, -width, -height );
1424 /***********************************************************************
1425 * NC_DrawMovingFrame
1427 * Draw the frame used when moving or resizing window.
1429 * FIXME: This causes problems in Win95 mode. (why?)
1431 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
1433 if (thickframe)
1435 RECT16 r16;
1436 CONV_RECT32TO16( rect, &r16 );
1437 FastWindowFrame16( hdc, &r16, GetSystemMetrics(SM_CXFRAME),
1438 GetSystemMetrics(SM_CYFRAME), PATINVERT );
1440 else DrawFocusRect( hdc, rect );
1444 /***********************************************************************
1445 * NC_DrawCaption
1447 * Draw the window caption.
1448 * The correct pen for the window frame must be selected in the DC.
1450 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1451 DWORD style, BOOL active )
1453 RECT r = *rect;
1454 WND * wndPtr = WIN_FindWndPtr( hwnd );
1455 char buffer[256];
1457 if (wndPtr->flags & WIN_MANAGED)
1459 WIN_ReleaseWndPtr(wndPtr);
1460 return;
1463 if (!hbitmapClose)
1465 if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSE) )))
1467 WIN_ReleaseWndPtr(wndPtr);
1468 return;
1470 hbitmapCloseD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSED) );
1471 hbitmapMinimize = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCE) );
1472 hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCED) );
1473 hbitmapMaximize = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOM) );
1474 hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOMD) );
1475 hbitmapRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1476 hbitmapRestoreD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORED) );
1479 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
1481 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1482 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1483 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1484 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1485 r.left++;
1486 r.right--;
1487 SelectObject( hdc, hbrushOld );
1489 WIN_ReleaseWndPtr(wndPtr);
1490 MoveTo16( hdc, r.left, r.bottom );
1491 LineTo( hdc, r.right, r.bottom );
1493 if (style & WS_SYSMENU)
1495 NC_DrawSysButton( hwnd, hdc, FALSE );
1496 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1497 MoveTo16( hdc, r.left - 1, r.top );
1498 LineTo( hdc, r.left - 1, r.bottom );
1500 if (style & WS_MAXIMIZEBOX)
1502 NC_DrawMaxButton( hwnd, hdc, FALSE );
1503 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1505 if (style & WS_MINIMIZEBOX)
1507 NC_DrawMinButton( hwnd, hdc, FALSE );
1508 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1511 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1512 COLOR_INACTIVECAPTION) );
1514 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1516 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1517 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1518 SetBkMode( hdc, TRANSPARENT );
1519 DrawTextA( hdc, buffer, -1, &r,
1520 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1525 /******************************************************************************
1527 * NC_DrawCaption95(
1528 * HDC hdc,
1529 * RECT *rect,
1530 * HWND hwnd,
1531 * DWORD style,
1532 * BOOL active )
1534 * Draw the window caption for Win95 style windows.
1535 * The correct pen for the window frame must be selected in the DC.
1537 * Bugs
1538 * Hey, a function that finally works! Well, almost.
1539 * It's being worked on.
1541 * Revision history
1542 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1543 * Original implementation.
1544 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1545 * Some minor fixes.
1547 *****************************************************************************/
1549 static void NC_DrawCaption95(
1550 HDC hdc,
1551 RECT *rect,
1552 HWND hwnd,
1553 DWORD style,
1554 DWORD exStyle,
1555 BOOL active )
1557 RECT r = *rect;
1558 WND *wndPtr = WIN_FindWndPtr( hwnd );
1559 char buffer[256];
1560 HPEN hPrevPen;
1561 HMENU hSysMenu;
1563 if (wndPtr->flags & WIN_MANAGED)
1565 WIN_ReleaseWndPtr(wndPtr);
1566 return;
1568 WIN_ReleaseWndPtr(wndPtr);
1570 hPrevPen = SelectObject( hdc, GetSysColorPen(COLOR_3DFACE) );
1571 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1572 LineTo( hdc, r.right, r.bottom - 1 );
1573 SelectObject( hdc, hPrevPen );
1574 r.bottom--;
1576 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1577 COLOR_INACTIVECAPTION) );
1579 if (!hbitmapClose) {
1580 if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSE) )))
1581 return;
1582 hbitmapCloseD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSED));
1583 hbitmapMinimize = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCE) );
1584 hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCED) );
1585 hbitmapMaximize = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOM) );
1586 hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOMD) );
1587 hbitmapRestore = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
1588 hbitmapRestoreD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORED) );
1591 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1592 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1593 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1596 if (style & WS_SYSMENU)
1598 UINT state;
1600 /* Go get the sysmenu */
1601 hSysMenu = GetSystemMenu(hwnd, FALSE);
1602 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1604 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1605 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1606 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1607 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1609 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1611 /* In win95 the two buttons are always there */
1612 /* But if the menu item is not in the menu they're disabled*/
1614 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1615 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1617 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1618 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1622 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1623 NONCLIENTMETRICSA nclm;
1624 HFONT hFont, hOldFont;
1625 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1626 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1627 if (exStyle & WS_EX_TOOLWINDOW)
1628 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1629 else
1630 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1631 hOldFont = SelectObject (hdc, hFont);
1632 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1633 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1634 SetBkMode( hdc, TRANSPARENT );
1635 r.left += 2;
1636 DrawTextA( hdc, buffer, -1, &r,
1637 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1638 DeleteObject (SelectObject (hdc, hOldFont));
1644 /***********************************************************************
1645 * NC_DoNCPaint
1647 * Paint the non-client area. clip is currently unused.
1649 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1651 HDC hdc;
1652 RECT rect;
1653 BOOL active;
1654 HWND hwnd = wndPtr->hwndSelf;
1656 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1657 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1659 active = wndPtr->flags & WIN_NCACTIVATED;
1661 TRACE("%04x %d\n", hwnd, active );
1663 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1664 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1666 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1667 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1668 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1669 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1670 == NULLREGION)
1672 ReleaseDC( hwnd, hdc );
1673 return;
1676 rect.top = rect.left = 0;
1677 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1678 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1680 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1682 if (!(wndPtr->flags & WIN_MANAGED))
1684 if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1686 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1687 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1688 InflateRect( &rect, -1, -1 );
1691 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1692 NC_DrawFrame(hdc, &rect, FALSE, active );
1693 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1694 NC_DrawFrame( hdc, &rect, TRUE, active );
1696 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1698 RECT r = rect;
1699 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1700 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1701 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1705 if (HAS_MENU(wndPtr))
1707 RECT r = rect;
1708 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1709 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1712 /* Draw the scroll-bars */
1714 if (wndPtr->dwStyle & WS_VSCROLL)
1715 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1716 if (wndPtr->dwStyle & WS_HSCROLL)
1717 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1719 /* Draw the "size-box" */
1721 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1723 RECT r = rect;
1724 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1725 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1726 if(wndPtr->dwStyle & WS_BORDER) {
1727 r.left++;
1728 r.top++;
1730 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1733 ReleaseDC( hwnd, hdc );
1737 /******************************************************************************
1739 * void NC_DoNCPaint95(
1740 * WND *wndPtr,
1741 * HRGN clip,
1742 * BOOL suppress_menupaint )
1744 * Paint the non-client area for Win95 windows. The clip region is
1745 * currently ignored.
1747 * Bugs
1748 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1749 * misc/tweak.c controls/menu.c # :-)
1751 * Revision history
1752 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1753 * Original implementation
1754 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1755 * Fixed some bugs.
1756 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1757 * Streamlined window style checks.
1759 *****************************************************************************/
1761 static void NC_DoNCPaint95(
1762 WND *wndPtr,
1763 HRGN clip,
1764 BOOL suppress_menupaint )
1766 HDC hdc;
1767 RECT rfuzz, rect, rectClip;
1768 BOOL active;
1769 HWND hwnd = wndPtr->hwndSelf;
1771 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1772 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1774 active = wndPtr->flags & WIN_NCACTIVATED;
1776 TRACE("%04x %d\n", hwnd, active );
1778 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1779 the call to GetDCEx implying that it is allowed not to use it either.
1780 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1781 will cause clipRgn to be deleted after ReleaseDC().
1782 Now, how is the "system" supposed to tell what happened?
1785 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1786 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1789 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1790 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1791 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1792 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1793 == NULLREGION)
1795 ReleaseDC( hwnd, hdc );
1796 return;
1799 rect.top = rect.left = 0;
1800 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1801 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1803 if( clip > 1 )
1804 GetRgnBox( clip, &rectClip );
1805 else
1807 clip = 0;
1808 rectClip = rect;
1811 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1813 if(!(wndPtr->flags & WIN_MANAGED)) {
1814 if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1815 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1817 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1818 NC_DrawFrame95(hdc, &rect, FALSE, active );
1819 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1820 NC_DrawFrame95( hdc, &rect, TRUE, active );
1821 else if (HAS_THINFRAME( wndPtr->dwStyle )) {
1822 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1823 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1826 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1828 RECT r = rect;
1829 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1830 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1831 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1833 else {
1834 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1835 rect.top += GetSystemMetrics(SM_CYCAPTION);
1837 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1838 NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1839 wndPtr->dwExStyle, active);
1843 if (HAS_MENU(wndPtr))
1845 RECT r = rect;
1846 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1848 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1849 r.left, r.top, r.right, r.bottom);
1851 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1854 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1855 rect.left, rect.top, rect.right, rect.bottom );
1857 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1858 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1860 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
1861 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1863 /* Draw the scroll-bars */
1865 if (wndPtr->dwStyle & WS_VSCROLL)
1866 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1867 if (wndPtr->dwStyle & WS_HSCROLL)
1868 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1870 /* Draw the "size-box" */
1871 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1873 RECT r = rect;
1874 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1875 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1876 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1879 ReleaseDC( hwnd, hdc );
1885 /***********************************************************************
1886 * NC_HandleNCPaint
1888 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1890 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1892 WND* wndPtr = WIN_FindWndPtr( hwnd );
1894 if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1896 if( wndPtr->dwStyle & WS_MINIMIZE )
1897 WINPOS_RedrawIconTitle( hwnd );
1898 else if (TWEAK_WineLook == WIN31_LOOK)
1899 NC_DoNCPaint( wndPtr, clip, FALSE );
1900 else
1901 NC_DoNCPaint95( wndPtr, clip, FALSE );
1903 WIN_ReleaseWndPtr(wndPtr);
1904 return 0;
1908 /***********************************************************************
1909 * NC_HandleNCActivate
1911 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1913 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM16 wParam )
1915 WORD wStateChange;
1917 if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
1918 else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
1920 if( wStateChange )
1922 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1923 else wndPtr->flags &= ~WIN_NCACTIVATED;
1925 if( wndPtr->dwStyle & WS_MINIMIZE )
1926 WINPOS_RedrawIconTitle( wndPtr->hwndSelf );
1927 else if (TWEAK_WineLook == WIN31_LOOK)
1928 NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1929 else
1930 NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1932 return TRUE;
1936 /***********************************************************************
1937 * NC_HandleSetCursor
1939 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1941 LONG NC_HandleSetCursor( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
1943 if (hwnd != (HWND)wParam) return 0; /* Don't set the cursor for child windows */
1945 switch(LOWORD(lParam))
1947 case HTERROR:
1949 WORD msg = HIWORD( lParam );
1950 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1951 (msg == WM_RBUTTONDOWN))
1952 MessageBeep(0);
1954 break;
1956 case HTCLIENT:
1958 HICON16 hCursor = (HICON16) GetClassWord(hwnd, GCW_HCURSOR);
1959 if(hCursor) {
1960 SetCursor16(hCursor);
1961 return TRUE;
1963 return FALSE;
1966 case HTLEFT:
1967 case HTRIGHT:
1968 return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZEWE16 ) );
1970 case HTTOP:
1971 case HTBOTTOM:
1972 return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENS16 ) );
1974 case HTTOPLEFT:
1975 case HTBOTTOMRIGHT:
1976 return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENWSE16 ) );
1978 case HTTOPRIGHT:
1979 case HTBOTTOMLEFT:
1980 return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENESW16 ) );
1983 /* Default cursor: arrow */
1984 return (LONG)SetCursor16( LoadCursor16( 0, IDC_ARROW16 ) );
1987 /***********************************************************************
1988 * NC_GetSysPopupPos
1990 BOOL NC_GetSysPopupPos( WND* wndPtr, RECT* rect )
1992 if( wndPtr->hSysMenu )
1994 if( wndPtr->dwStyle & WS_MINIMIZE )
1995 GetWindowRect( wndPtr->hwndSelf, rect );
1996 else
1998 if (TWEAK_WineLook == WIN31_LOOK)
1999 NC_GetInsideRect( wndPtr->hwndSelf, rect );
2000 else
2001 NC_GetInsideRect95( wndPtr->hwndSelf, rect );
2002 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
2003 if (wndPtr->dwStyle & WS_CHILD)
2004 ClientToScreen( wndPtr->parent->hwndSelf, (POINT *)rect );
2005 if (TWEAK_WineLook == WIN31_LOOK) {
2006 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
2007 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
2009 else {
2010 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
2011 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
2014 return TRUE;
2016 return FALSE;
2019 /***********************************************************************
2020 * NC_StartSizeMove
2022 * Initialisation of a move or resize, when initiatied from a menu choice.
2023 * Return hit test code for caption or sizing border.
2025 static LONG NC_StartSizeMove( WND* wndPtr, WPARAM16 wParam,
2026 POINT16 *capturePoint )
2028 LONG hittest = 0;
2029 POINT16 pt;
2030 MSG msg;
2031 RECT rectWindow;
2033 GetWindowRect(wndPtr->hwndSelf,&rectWindow);
2035 if ((wParam & 0xfff0) == SC_MOVE)
2037 /* Move pointer at the center of the caption */
2038 RECT rect;
2039 if (TWEAK_WineLook == WIN31_LOOK)
2040 NC_GetInsideRect( wndPtr->hwndSelf, &rect );
2041 else
2042 NC_GetInsideRect95( wndPtr->hwndSelf, &rect );
2043 if (wndPtr->dwStyle & WS_SYSMENU)
2044 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
2045 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
2046 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
2047 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
2048 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
2049 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
2050 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
2051 hittest = HTCAPTION;
2052 *capturePoint = pt;
2054 else /* SC_SIZE */
2056 while(!hittest)
2058 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE, NULL );
2059 switch(msg.message)
2061 case WM_MOUSEMOVE:
2062 CONV_POINT32TO16(&msg.pt, &pt);
2063 hittest = NC_HandleNCHitTest( wndPtr->hwndSelf, pt );
2064 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
2065 hittest = 0;
2066 break;
2068 case WM_LBUTTONUP:
2069 return 0;
2071 case WM_KEYDOWN:
2072 switch(msg.wParam)
2074 case VK_UP:
2075 hittest = HTTOP;
2076 pt.x =(rectWindow.left+rectWindow.right)/2;
2077 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
2078 break;
2079 case VK_DOWN:
2080 hittest = HTBOTTOM;
2081 pt.x =(rectWindow.left+rectWindow.right)/2;
2082 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
2083 break;
2084 case VK_LEFT:
2085 hittest = HTLEFT;
2086 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
2087 pt.y =(rectWindow.top+rectWindow.bottom)/2;
2088 break;
2089 case VK_RIGHT:
2090 hittest = HTRIGHT;
2091 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
2092 pt.y =(rectWindow.top+rectWindow.bottom)/2;
2093 break;
2094 case VK_RETURN:
2095 case VK_ESCAPE: return 0;
2099 *capturePoint = pt;
2101 SetCursorPos( pt.x, pt.y );
2102 NC_HandleSetCursor( wndPtr->hwndSelf,
2103 wndPtr->hwndSelf, MAKELONG( hittest, WM_MOUSEMOVE ));
2104 return hittest;
2108 /***********************************************************************
2109 * NC_DoSizeMove
2111 * Perform SC_MOVE and SC_SIZE commands. `
2113 static void NC_DoSizeMove( HWND hwnd, WORD wParam )
2115 MSG msg;
2116 RECT sizingRect, mouseRect;
2117 HDC hdc;
2118 LONG hittest = (LONG)(wParam & 0x0f);
2119 HCURSOR16 hDragCursor = 0, hOldCursor = 0;
2120 POINT minTrack, maxTrack;
2121 POINT16 capturePoint, pt;
2122 WND * wndPtr = WIN_FindWndPtr( hwnd );
2123 BOOL thickframe = HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle );
2124 BOOL iconic = wndPtr->dwStyle & WS_MINIMIZE;
2125 BOOL moved = FALSE;
2126 DWORD dwPoint = GetMessagePos ();
2128 capturePoint = pt = *(POINT16*)&dwPoint;
2130 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) ||
2131 (wndPtr->flags & WIN_MANAGED)) goto END;
2133 if ((wParam & 0xfff0) == SC_MOVE)
2135 if (!(wndPtr->dwStyle & WS_CAPTION)) goto END;
2136 if (!hittest)
2137 hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2138 if (!hittest) goto END;
2140 else /* SC_SIZE */
2142 if (!thickframe) goto END;
2143 if ( hittest && hittest != HTSYSMENU ) hittest += 2;
2144 else
2146 SetCapture(hwnd);
2147 hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2148 if (!hittest)
2150 ReleaseCapture();
2151 goto END;
2156 /* Get min/max info */
2158 WINPOS_GetMinMaxInfo( wndPtr, NULL, NULL, &minTrack, &maxTrack );
2159 sizingRect = wndPtr->rectWindow;
2160 if (wndPtr->dwStyle & WS_CHILD)
2161 GetClientRect( wndPtr->parent->hwndSelf, &mouseRect );
2162 else
2163 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2164 if (ON_LEFT_BORDER(hittest))
2166 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
2167 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
2169 else if (ON_RIGHT_BORDER(hittest))
2171 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
2172 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
2174 if (ON_TOP_BORDER(hittest))
2176 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
2177 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
2179 else if (ON_BOTTOM_BORDER(hittest))
2181 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
2182 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
2184 if (wndPtr->dwStyle & WS_CHILD)
2186 MapWindowPoints( wndPtr->parent->hwndSelf, 0,
2187 (LPPOINT)&mouseRect, 2 );
2189 SendMessage16( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
2191 if (GetCapture() != hwnd) SetCapture( hwnd );
2193 if (wndPtr->dwStyle & WS_CHILD)
2195 /* Retrieve a default cache DC (without using the window style) */
2196 hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
2198 else
2199 { /* Grab the server only when moving top-level windows without desktop */
2200 hdc = GetDC( 0 );
2203 wndPtr->pDriver->pPreSizeMove(wndPtr);
2205 if( iconic ) /* create a cursor for dragging */
2207 HICON16 hIcon = GetClassWord(wndPtr->hwndSelf, GCW_HICON);
2208 if(!hIcon) hIcon = (HICON16) SendMessage16( hwnd, WM_QUERYDRAGICON, 0, 0L);
2209 if( hIcon ) hDragCursor = CURSORICON_IconToCursor( hIcon, TRUE );
2210 if( !hDragCursor ) iconic = FALSE;
2213 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
2214 if( !iconic && TWEAK_WineLook == WIN31_LOOK )
2215 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2217 while(1)
2219 int dx = 0, dy = 0;
2221 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE, NULL );
2223 /* Exit on button-up, Return, or Esc */
2224 if ((msg.message == WM_LBUTTONUP) ||
2225 ((msg.message == WM_KEYDOWN) &&
2226 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
2228 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
2229 continue; /* We are not interested in other messages */
2231 dwPoint = GetMessagePos ();
2232 pt = *(POINT16*)&dwPoint;
2234 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
2236 case VK_UP: pt.y -= 8; break;
2237 case VK_DOWN: pt.y += 8; break;
2238 case VK_LEFT: pt.x -= 8; break;
2239 case VK_RIGHT: pt.x += 8; break;
2242 pt.x = max( pt.x, mouseRect.left );
2243 pt.x = min( pt.x, mouseRect.right );
2244 pt.y = max( pt.y, mouseRect.top );
2245 pt.y = min( pt.y, mouseRect.bottom );
2247 dx = pt.x - capturePoint.x;
2248 dy = pt.y - capturePoint.y;
2250 if (dx || dy)
2252 if( !moved )
2254 moved = TRUE;
2256 if( iconic ) /* ok, no system popup tracking */
2258 hOldCursor = SetCursor(hDragCursor);
2259 ShowCursor( TRUE );
2260 WINPOS_ShowIconTitle( wndPtr, FALSE );
2261 } else if(TWEAK_WineLook != WIN31_LOOK)
2263 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2267 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
2268 else
2270 RECT newRect = sizingRect;
2271 WPARAM wpSizingHit = 0;
2273 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
2274 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
2275 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
2276 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
2277 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
2278 if(!iconic) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2279 capturePoint = pt;
2281 /* determine the hit location */
2282 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
2283 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
2284 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
2286 if (!iconic) NC_DrawMovingFrame( hdc, &newRect, thickframe );
2287 sizingRect = newRect;
2292 ReleaseCapture();
2293 if( iconic )
2295 if( moved ) /* restore cursors, show icon title later on */
2297 ShowCursor( FALSE );
2298 SetCursor( hOldCursor );
2300 DestroyCursor( hDragCursor );
2302 else if(moved || TWEAK_WineLook == WIN31_LOOK)
2303 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2305 if (wndPtr->dwStyle & WS_CHILD)
2306 ReleaseDC( wndPtr->parent->hwndSelf, hdc );
2307 else
2308 ReleaseDC( 0, hdc );
2310 wndPtr->pDriver->pPostSizeMove(wndPtr);
2312 if (HOOK_IsHooked( WH_CBT ))
2314 RECT16* pr = SEGPTR_NEW(RECT16);
2315 if( pr )
2317 CONV_RECT32TO16( &sizingRect, pr );
2318 if( HOOK_CallHooks16( WH_CBT, HCBT_MOVESIZE, hwnd,
2319 (LPARAM)SEGPTR_GET(pr)) )
2320 sizingRect = wndPtr->rectWindow;
2321 else
2322 CONV_RECT16TO32( pr, &sizingRect );
2323 SEGPTR_FREE(pr);
2326 SendMessage16( hwnd, WM_EXITSIZEMOVE, 0, 0 );
2327 SendMessage16( hwnd, WM_SETVISIBLE, !IsIconic16(hwnd), 0L);
2329 /* window moved or resized */
2330 if (moved)
2332 /* if the moving/resizing isn't canceled call SetWindowPos
2333 * with the new position or the new size of the window
2335 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
2337 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
2338 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
2339 sizingRect.right - sizingRect.left,
2340 sizingRect.bottom - sizingRect.top,
2341 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2345 if( IsWindow(hwnd) )
2346 if( wndPtr->dwStyle & WS_MINIMIZE )
2348 /* Single click brings up the system menu when iconized */
2350 if( !moved )
2352 if( wndPtr->dwStyle & WS_SYSMENU )
2353 SendMessage16( hwnd, WM_SYSCOMMAND,
2354 SC_MOUSEMENU + HTSYSMENU, *((LPARAM*)&pt));
2356 else WINPOS_ShowIconTitle( wndPtr, TRUE );
2359 END:
2360 WIN_ReleaseWndPtr(wndPtr);
2364 /***********************************************************************
2365 * NC_TrackMinMaxBox95
2367 * Track a mouse button press on the minimize or maximize box.
2369 * The big difference between 3.1 and 95 is the disabled button state.
2370 * In win95 the system button can be disabled, so it can ignore the mouse
2371 * event.
2374 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
2376 MSG msg;
2377 POINT16 pt16;
2378 HDC hdc = GetWindowDC( hwnd );
2379 BOOL pressed = TRUE;
2380 UINT state;
2381 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
2382 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2384 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
2386 if (wParam == HTMINBUTTON)
2388 /* If the style is not present, do nothing */
2389 if (!(wndStyle & WS_MINIMIZEBOX))
2390 return;
2392 /* Check if the sysmenu item for minimize is there */
2393 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
2395 paintButton = &NC_DrawMinButton95;
2397 else
2399 /* If the style is not present, do nothing */
2400 if (!(wndStyle & WS_MAXIMIZEBOX))
2401 return;
2403 /* Check if the sysmenu item for maximize is there */
2404 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
2406 paintButton = &NC_DrawMaxButton95;
2409 SetCapture( hwnd );
2411 (*paintButton)( hwnd, hdc, TRUE, FALSE);
2415 BOOL oldstate = pressed;
2416 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2417 CONV_POINT32TO16( &msg.pt, &pt16 );
2419 pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
2420 if (pressed != oldstate)
2421 (*paintButton)( hwnd, hdc, pressed, FALSE);
2422 } while (msg.message != WM_LBUTTONUP);
2424 (*paintButton)( hwnd, hdc, FALSE, FALSE);
2426 ReleaseCapture();
2427 ReleaseDC( hwnd, hdc );
2429 /* If the item minimize or maximize of the sysmenu are not there */
2430 /* or if the style is not present, do nothing */
2431 if ((!pressed) || (state == 0xFFFFFFFF))
2432 return;
2434 if (wParam == HTMINBUTTON)
2435 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&pt16 );
2436 else
2437 SendMessage16( hwnd, WM_SYSCOMMAND,
2438 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, *(LONG*)&pt16 );
2441 /***********************************************************************
2442 * NC_TrackMinMaxBox
2444 * Track a mouse button press on the minimize or maximize box.
2446 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
2448 MSG msg;
2449 POINT16 pt16;
2450 HDC hdc = GetWindowDC( hwnd );
2451 BOOL pressed = TRUE;
2452 void (*paintButton)(HWND, HDC16, BOOL);
2454 SetCapture( hwnd );
2456 if (wParam == HTMINBUTTON)
2457 paintButton = &NC_DrawMinButton;
2458 else
2459 paintButton = &NC_DrawMaxButton;
2461 (*paintButton)( hwnd, hdc, TRUE);
2465 BOOL oldstate = pressed;
2466 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2467 CONV_POINT32TO16( &msg.pt, &pt16 );
2469 pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
2470 if (pressed != oldstate)
2471 (*paintButton)( hwnd, hdc, pressed);
2472 } while (msg.message != WM_LBUTTONUP);
2474 (*paintButton)( hwnd, hdc, FALSE);
2476 ReleaseCapture();
2477 ReleaseDC( hwnd, hdc );
2479 if (!pressed) return;
2481 if (wParam == HTMINBUTTON)
2482 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&pt16 );
2483 else
2484 SendMessage16( hwnd, WM_SYSCOMMAND,
2485 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, *(LONG*)&pt16 );
2489 /***********************************************************************
2490 * NC_TrackCloseButton95
2492 * Track a mouse button press on the Win95 close button.
2494 static void
2495 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
2497 MSG msg;
2498 POINT16 pt16;
2499 HDC hdc;
2500 BOOL pressed = TRUE;
2501 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2502 UINT state;
2504 if(hSysMenu == 0)
2505 return;
2507 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
2509 /* If the item close of the sysmenu is disabled or not there do nothing */
2510 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
2511 return;
2513 hdc = GetWindowDC( hwnd );
2515 SetCapture( hwnd );
2517 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
2521 BOOL oldstate = pressed;
2522 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2523 CONV_POINT32TO16( &msg.pt, &pt16 );
2525 pressed = (NC_HandleNCHitTest( hwnd, pt16 ) == wParam);
2526 if (pressed != oldstate)
2527 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
2528 } while (msg.message != WM_LBUTTONUP);
2530 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
2532 ReleaseCapture();
2533 ReleaseDC( hwnd, hdc );
2534 if (!pressed) return;
2536 SendMessage16( hwnd, WM_SYSCOMMAND, SC_CLOSE, *(LONG*)&pt16 );
2540 /***********************************************************************
2541 * NC_TrackScrollBar
2543 * Track a mouse button press on the horizontal or vertical scroll-bar.
2545 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2547 MSG16 *msg;
2548 INT scrollbar;
2549 WND *wndPtr = WIN_FindWndPtr( hwnd );
2551 if ((wParam & 0xfff0) == SC_HSCROLL)
2553 if ((wParam & 0x0f) != HTHSCROLL) goto END;
2554 scrollbar = SB_HORZ;
2556 else /* SC_VSCROLL */
2558 if ((wParam & 0x0f) != HTVSCROLL) goto END;
2559 scrollbar = SB_VERT;
2562 if (!(msg = SEGPTR_NEW(MSG16))) goto END;
2563 pt.x -= wndPtr->rectWindow.left;
2564 pt.y -= wndPtr->rectWindow.top;
2565 SetCapture( hwnd );
2566 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
2570 GetMessage16( SEGPTR_GET(msg), 0, 0, 0 );
2571 switch(msg->message)
2573 case WM_LBUTTONUP:
2574 case WM_MOUSEMOVE:
2575 case WM_SYSTIMER:
2576 pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left -
2577 wndPtr->rectWindow.left;
2578 pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top -
2579 wndPtr->rectWindow.top;
2580 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
2581 break;
2582 default:
2583 TranslateMessage16( msg );
2584 DispatchMessage16( msg );
2585 break;
2587 if (!IsWindow( hwnd ))
2589 ReleaseCapture();
2590 break;
2592 } while (msg->message != WM_LBUTTONUP);
2593 SEGPTR_FREE(msg);
2594 END:
2595 WIN_ReleaseWndPtr(wndPtr);
2598 /***********************************************************************
2599 * NC_HandleNCLButtonDown
2601 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2603 LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
2605 HWND hwnd = pWnd->hwndSelf;
2607 switch(wParam) /* Hit test */
2609 case HTCAPTION:
2610 hwnd = WIN_GetTopParent(hwnd);
2612 if( WINPOS_SetActiveWindow(hwnd, TRUE, TRUE) || (GetActiveWindow() == hwnd) )
2613 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2614 break;
2616 case HTSYSMENU:
2617 if( pWnd->dwStyle & WS_SYSMENU )
2619 if( !(pWnd->dwStyle & WS_MINIMIZE) )
2621 HDC hDC = GetWindowDC(hwnd);
2622 if (TWEAK_WineLook == WIN31_LOOK)
2623 NC_DrawSysButton( hwnd, hDC, TRUE );
2624 else
2625 NC_DrawSysButton95( hwnd, hDC, TRUE );
2626 ReleaseDC( hwnd, hDC );
2628 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2630 break;
2632 case HTMENU:
2633 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2634 break;
2636 case HTHSCROLL:
2637 SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2638 break;
2640 case HTVSCROLL:
2641 SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2642 break;
2644 case HTMINBUTTON:
2645 case HTMAXBUTTON:
2646 if (TWEAK_WineLook == WIN31_LOOK)
2647 NC_TrackMinMaxBox( hwnd, wParam );
2648 else
2649 NC_TrackMinMaxBox95( hwnd, wParam );
2650 break;
2652 case HTCLOSE:
2653 if (TWEAK_WineLook >= WIN95_LOOK)
2654 NC_TrackCloseButton95 (hwnd, wParam);
2655 break;
2657 case HTLEFT:
2658 case HTRIGHT:
2659 case HTTOP:
2660 case HTTOPLEFT:
2661 case HTTOPRIGHT:
2662 case HTBOTTOM:
2663 case HTBOTTOMLEFT:
2664 case HTBOTTOMRIGHT:
2665 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2666 SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2667 break;
2669 case HTBORDER:
2670 break;
2672 return 0;
2676 /***********************************************************************
2677 * NC_HandleNCLButtonDblClk
2679 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2681 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam )
2684 * if this is an icon, send a restore since we are handling
2685 * a double click
2687 if (pWnd->dwStyle & WS_MINIMIZE)
2689 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
2690 return 0;
2693 switch(wParam) /* Hit test */
2695 case HTCAPTION:
2696 /* stop processing if WS_MAXIMIZEBOX is missing */
2697 if (pWnd->dwStyle & WS_MAXIMIZEBOX)
2698 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
2699 (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
2700 lParam );
2701 break;
2703 case HTSYSMENU:
2704 if (!(GetClassWord(pWnd->hwndSelf, GCW_STYLE) & CS_NOCLOSE))
2705 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
2706 break;
2708 case HTHSCROLL:
2709 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL,
2710 lParam );
2711 break;
2713 case HTVSCROLL:
2714 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL,
2715 lParam );
2716 break;
2718 return 0;
2722 /***********************************************************************
2723 * NC_HandleSysCommand
2725 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2727 LONG NC_HandleSysCommand( HWND hwnd, WPARAM16 wParam, POINT16 pt )
2729 WND *wndPtr = WIN_FindWndPtr( hwnd );
2730 POINT pt32;
2731 UINT16 uCommand = wParam & 0xFFF0;
2733 TRACE("Handling WM_SYSCOMMAND %x %d,%d\n", wParam, pt.x, pt.y );
2735 if (wndPtr->dwStyle & WS_CHILD && uCommand != SC_KEYMENU )
2736 ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
2738 switch (uCommand)
2740 case SC_SIZE:
2741 case SC_MOVE:
2742 NC_DoSizeMove( hwnd, wParam );
2743 break;
2745 case SC_MINIMIZE:
2746 if (hwnd == GetForegroundWindow())
2747 ShowOwnedPopups(hwnd,FALSE);
2748 ShowWindow( hwnd, SW_MINIMIZE );
2749 break;
2751 case SC_MAXIMIZE:
2752 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2753 ShowOwnedPopups(hwnd,TRUE);
2754 ShowWindow( hwnd, SW_MAXIMIZE );
2755 break;
2757 case SC_RESTORE:
2758 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2759 ShowOwnedPopups(hwnd,TRUE);
2760 ShowWindow( hwnd, SW_RESTORE );
2761 break;
2763 case SC_CLOSE:
2764 WIN_ReleaseWndPtr(wndPtr);
2765 return SendMessage16( hwnd, WM_CLOSE, 0, 0 );
2767 case SC_VSCROLL:
2768 case SC_HSCROLL:
2769 CONV_POINT16TO32( &pt, &pt32 );
2770 NC_TrackScrollBar( hwnd, wParam, pt32 );
2771 break;
2773 case SC_MOUSEMENU:
2774 CONV_POINT16TO32( &pt, &pt32 );
2775 MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt32 );
2776 break;
2778 case SC_KEYMENU:
2779 MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
2780 break;
2782 case SC_TASKLIST:
2783 WinExec( "taskman.exe", SW_SHOWNORMAL );
2784 break;
2786 case SC_SCREENSAVE:
2787 if (wParam == SC_ABOUTWINE)
2789 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2790 if (hmodule)
2792 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2793 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2794 FreeLibrary( hmodule );
2797 else
2798 if (wParam == SC_PUTMARK)
2799 TRACE_(shell)("Mark requested by user\n");
2800 break;
2802 case SC_HOTKEY:
2803 case SC_ARRANGE:
2804 case SC_NEXTWINDOW:
2805 case SC_PREVWINDOW:
2806 FIXME("unimplemented!\n");
2807 break;
2809 WIN_ReleaseWndPtr(wndPtr);
2810 return 0;
2813 /*************************************************************
2814 * NC_DrawGrayButton
2816 * Stub for the grayed button of the caption
2818 *************************************************************/
2820 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2822 HBITMAP hMaskBmp;
2823 HDC hdcMask = CreateCompatibleDC (0);
2824 HBRUSH hOldBrush;
2826 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2828 if(hMaskBmp == 0)
2829 return FALSE;
2831 SelectObject (hdcMask, hMaskBmp);
2833 /* Draw the grayed bitmap using the mask */
2834 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2835 BitBlt (hdc, x, y, 12, 10,
2836 hdcMask, 0, 0, 0xB8074A);
2838 /* Clean up */
2839 SelectObject (hdc, hOldBrush);
2840 DeleteObject(hMaskBmp);
2841 DeleteDC (hdcMask);
2843 return TRUE;
2846 HICON16 NC_IconForWindow(WND *wndPtr)
2848 HICON16 hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICONSM);
2849 if(!hIcon) hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON);
2851 /* If there is no hIcon specified and this is a modal dialog, */
2852 /* get the default one. */
2853 if (!hIcon && (wndPtr->dwStyle & DS_MODALFRAME))
2854 hIcon = LoadImageA(0, MAKEINTRESOURCEA(OIC_WINEICON), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
2856 return hIcon;