Added needed string.h includes.
[wine.git] / windows / nonclient.c
blob163411b9971706ac6f3d0bc4b1d783a035ba6300
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 "queue.h"
23 #include "debugtools.h"
24 #include "options.h"
25 #include "shellapi.h"
26 #include "bitmap.h"
28 DEFAULT_DEBUG_CHANNEL(nonclient);
29 DECLARE_DEBUG_CHANNEL(shell);
31 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
33 static HBITMAP hbitmapClose;
34 static HBITMAP hbitmapMinimize;
35 static HBITMAP hbitmapMinimizeD;
36 static HBITMAP hbitmapMaximize;
37 static HBITMAP hbitmapMaximizeD;
38 static HBITMAP hbitmapRestore;
39 static HBITMAP hbitmapRestoreD;
41 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
42 0x55, 0x50,
43 0xAA, 0xA0,
44 0x55, 0x50,
45 0xAA, 0xA0,
46 0x55, 0x50,
47 0xAA, 0xA0,
48 0x55, 0x50,
49 0xAA, 0xA0,
50 0x55, 0x50};
52 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
53 #define SC_PUTMARK (SC_SCREENSAVE+2)
55 /* Some useful macros */
56 #define HAS_DLGFRAME(style,exStyle) \
57 (((exStyle) & WS_EX_DLGMODALFRAME) || \
58 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
60 #define HAS_THICKFRAME(style,exStyle) \
61 (((style) & WS_THICKFRAME) && \
62 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
64 #define HAS_THINFRAME(style) \
65 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
67 #define HAS_BIGFRAME(style,exStyle) \
68 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
69 ((exStyle) & WS_EX_DLGMODALFRAME))
71 #define HAS_ANYFRAME(style,exStyle) \
72 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
73 ((exStyle) & WS_EX_DLGMODALFRAME) || \
74 !((style) & (WS_CHILD | WS_POPUP)))
76 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
78 #define ON_LEFT_BORDER(hit) \
79 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
80 #define ON_RIGHT_BORDER(hit) \
81 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
82 #define ON_TOP_BORDER(hit) \
83 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
84 #define ON_BOTTOM_BORDER(hit) \
85 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
87 /***********************************************************************
88 * WIN_WindowNeedsWMBorder
90 * This method defines the rules for a window to have a WM border,
91 * caption... It is used for consistency purposes.
93 BOOL WIN_WindowNeedsWMBorder( DWORD style, DWORD exStyle )
95 if (!(style & WS_CHILD) &&
96 Options.managed &&
97 !(exStyle & WS_EX_TOOLWINDOW) &&
98 ( ((style & WS_CAPTION) == WS_CAPTION) ||
99 (style & WS_THICKFRAME)))
100 return TRUE;
101 if (exStyle & WS_EX_TRAYWINDOW)
102 return TRUE;
103 return FALSE;
106 /***********************************************************************
107 * NC_AdjustRect
109 * Compute the size of the window rectangle from the size of the
110 * client rectangle.
112 static void NC_AdjustRect( LPRECT16 rect, DWORD style, BOOL menu,
113 DWORD exStyle )
115 if (TWEAK_WineLook > WIN31_LOOK)
116 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
118 if(style & WS_ICONIC) return;
119 /* Decide if the window will be managed (see CreateWindowEx) */
120 if (!WIN_WindowNeedsWMBorder(style, exStyle))
122 if (HAS_THICKFRAME( style, exStyle ))
123 InflateRect16( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
124 else
125 if (HAS_DLGFRAME( style, exStyle ))
126 InflateRect16( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
127 else
128 if (HAS_THINFRAME( style ))
129 InflateRect16( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
131 if ((style & WS_CAPTION) == WS_CAPTION)
132 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
134 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
136 if (style & WS_VSCROLL) {
137 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
138 if(!HAS_ANYFRAME( style, exStyle ))
139 rect->right++;
142 if (style & WS_HSCROLL) {
143 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
144 if(!HAS_ANYFRAME( style, exStyle ))
145 rect->bottom++;
150 /******************************************************************************
151 * NC_AdjustRectOuter95
153 * Computes the size of the "outside" parts of the window based on the
154 * parameters of the client area.
156 + PARAMS
157 * LPRECT16 rect
158 * DWORD style
159 * BOOL menu
160 * DWORD exStyle
162 * NOTES
163 * "Outer" parts of a window means the whole window frame, caption and
164 * menu bar. It does not include "inner" parts of the frame like client
165 * edge, static edge or scroll bars.
167 * Revision history
168 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
169 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
171 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
172 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
173 * NC_AdjustRectInner95 and added handling of Win95 styles.
175 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
176 * Streamlined window style checks.
178 *****************************************************************************/
180 static void
181 NC_AdjustRectOuter95 (LPRECT16 rect, DWORD style, BOOL menu, DWORD exStyle)
183 if(style & WS_ICONIC) return;
185 /* Decide if the window will be managed (see CreateWindowEx) */
186 if (!WIN_WindowNeedsWMBorder(style, exStyle))
188 if (HAS_THICKFRAME( style, exStyle ))
189 InflateRect16( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
190 else
191 if (HAS_DLGFRAME( style, exStyle ))
192 InflateRect16(rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
193 else
194 if (HAS_THINFRAME( style ))
195 InflateRect16( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
197 if ((style & WS_CAPTION) == WS_CAPTION)
199 if (exStyle & WS_EX_TOOLWINDOW)
200 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
201 else
202 rect->top -= GetSystemMetrics(SM_CYCAPTION);
206 if (menu)
207 rect->top -= GetSystemMetrics(SM_CYMENU);
211 /******************************************************************************
212 * NC_AdjustRectInner95
214 * Computes the size of the "inside" part of the window based on the
215 * parameters of the client area.
217 + PARAMS
218 * LPRECT16 rect
219 * DWORD style
220 * DWORD exStyle
222 * NOTES
223 * "Inner" part of a window means the window frame inside of the flat
224 * window frame. It includes the client edge, the static edge and the
225 * scroll bars.
227 * Revision history
228 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
229 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
231 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
232 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
233 * NC_AdjustRectInner95 and added handling of Win95 styles.
235 *****************************************************************************/
237 static void
238 NC_AdjustRectInner95 (LPRECT16 rect, DWORD style, DWORD exStyle)
240 if(style & WS_ICONIC) return;
242 if (exStyle & WS_EX_CLIENTEDGE)
243 InflateRect16 (rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
245 if (exStyle & WS_EX_STATICEDGE)
246 InflateRect16 (rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
248 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
249 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
253 /***********************************************************************
254 * DrawCaption (USER.660) Draws a caption bar
256 * PARAMS
257 * hwnd [I]
258 * hdc [I]
259 * lpRect [I]
260 * uFlags [I]
262 * RETURNS
263 * Success:
264 * Failure:
267 BOOL16 WINAPI
268 DrawCaption16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, UINT16 uFlags)
270 RECT rect32;
272 if (rect)
273 CONV_RECT16TO32 (rect, &rect32);
275 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect ? &rect32 : NULL,
276 0, 0, NULL, uFlags & 0x1F);
280 /***********************************************************************
281 * DrawCaption (USER32.@) Draws a caption bar
283 * PARAMS
284 * hwnd [I]
285 * hdc [I]
286 * lpRect [I]
287 * uFlags [I]
289 * RETURNS
290 * Success:
291 * Failure:
294 BOOL WINAPI
295 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
297 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
301 /***********************************************************************
302 * DrawCaptionTemp (USER.657)
304 * PARAMS
306 * RETURNS
307 * Success:
308 * Failure:
311 BOOL16 WINAPI
312 DrawCaptionTemp16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, HFONT16 hFont,
313 HICON16 hIcon, LPCSTR str, UINT16 uFlags)
315 RECT rect32;
317 if (rect)
318 CONV_RECT16TO32(rect,&rect32);
320 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect?&rect32:NULL, hFont,
321 hIcon, str, uFlags & 0x1F);
325 /***********************************************************************
326 * DrawCaptionTempA (USER32.@)
328 * PARAMS
330 * RETURNS
331 * Success:
332 * Failure:
335 BOOL WINAPI
336 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
337 HICON hIcon, LPCSTR str, UINT uFlags)
339 RECT rc = *rect;
341 TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
342 hwnd, hdc, rect, hFont, hIcon, str, uFlags);
344 /* drawing background */
345 if (uFlags & DC_INBUTTON) {
346 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
348 if (uFlags & DC_ACTIVE) {
349 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
350 PatBlt (hdc, rc.left, rc.top,
351 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
352 SelectObject (hdc, hbr);
355 else {
356 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
357 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
361 /* drawing icon */
362 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
363 POINT pt;
365 pt.x = rc.left + 2;
366 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
368 if (hIcon) {
369 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
370 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
372 else {
373 WND* wndPtr = WIN_FindWndPtr(hwnd);
374 HICON hAppIcon = (HICON) NC_IconForWindow(wndPtr);
375 DrawIconEx (hdc, pt.x, pt.y, hAppIcon, GetSystemMetrics(SM_CXSMICON),
376 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
377 WIN_ReleaseWndPtr(wndPtr);
380 rc.left += (rc.bottom - rc.top);
383 /* drawing text */
384 if (uFlags & DC_TEXT) {
385 HFONT hOldFont;
387 if (uFlags & DC_INBUTTON)
388 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
389 else if (uFlags & DC_ACTIVE)
390 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
391 else
392 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
394 SetBkMode (hdc, TRANSPARENT);
396 if (hFont)
397 hOldFont = SelectObject (hdc, hFont);
398 else {
399 NONCLIENTMETRICSA nclm;
400 HFONT hNewFont;
401 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
402 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
403 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
404 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
405 hOldFont = SelectObject (hdc, hNewFont);
408 if (str)
409 DrawTextA (hdc, str, -1, &rc,
410 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
411 else {
412 CHAR szText[128];
413 INT nLen;
414 nLen = GetWindowTextA (hwnd, szText, 128);
415 DrawTextA (hdc, szText, nLen, &rc,
416 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
419 if (hFont)
420 SelectObject (hdc, hOldFont);
421 else
422 DeleteObject (SelectObject (hdc, hOldFont));
425 /* drawing focus ??? */
426 if (uFlags & 0x2000)
427 FIXME("undocumented flag (0x2000)!\n");
429 return 0;
433 /***********************************************************************
434 * DrawCaptionTempW (USER32.@)
436 * PARAMS
438 * RETURNS
439 * Success:
440 * Failure:
443 BOOL WINAPI
444 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
445 HICON hIcon, LPCWSTR str, UINT uFlags)
447 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
448 BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
449 HeapFree (GetProcessHeap (), 0, p);
450 return res;
454 /***********************************************************************
455 * AdjustWindowRect (USER.102)
457 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
459 return AdjustWindowRectEx16( rect, style, menu, 0 );
463 /***********************************************************************
464 * AdjustWindowRect (USER32.@)
466 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
468 return AdjustWindowRectEx( rect, style, menu, 0 );
472 /***********************************************************************
473 * AdjustWindowRectEx (USER.454)
475 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
476 BOOL16 menu, DWORD exStyle )
478 /* Correct the window style */
480 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
481 style |= WS_CAPTION;
482 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
483 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
484 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
485 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
487 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
488 rect->left, rect->top, rect->right, rect->bottom,
489 style, menu, exStyle );
491 if (TWEAK_WineLook == WIN31_LOOK)
492 NC_AdjustRect( rect, style, menu, exStyle );
493 else {
494 NC_AdjustRectOuter95( rect, style, menu, exStyle );
495 NC_AdjustRectInner95( rect, style, exStyle );
498 return TRUE;
502 /***********************************************************************
503 * AdjustWindowRectEx (USER32.@)
505 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style,
506 BOOL menu, DWORD exStyle )
508 RECT16 rect16;
509 BOOL ret;
511 CONV_RECT32TO16( rect, &rect16 );
512 ret = AdjustWindowRectEx16( &rect16, style, (BOOL16)menu, exStyle );
513 CONV_RECT16TO32( &rect16, rect );
514 return ret;
518 /***********************************************************************
519 * NC_HandleNCCalcSize
521 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
523 LONG NC_HandleNCCalcSize( WND *pWnd, RECT *winRect )
525 RECT16 tmpRect = { 0, 0, 0, 0 };
526 LONG result = 0;
527 UINT style = (UINT) GetClassLongA(pWnd->hwndSelf, GCL_STYLE);
529 if (style & CS_VREDRAW) result |= WVR_VREDRAW;
530 if (style & CS_HREDRAW) result |= WVR_HREDRAW;
532 if( !( pWnd->dwStyle & WS_MINIMIZE ) ) {
533 if (TWEAK_WineLook == WIN31_LOOK)
534 NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
535 else
536 NC_AdjustRectOuter95( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
538 winRect->left -= tmpRect.left;
539 winRect->top -= tmpRect.top;
540 winRect->right -= tmpRect.right;
541 winRect->bottom -= tmpRect.bottom;
543 if (HAS_MENU(pWnd)) {
544 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
545 "at (%d, %d).\n", pWnd->hwndSelf,
546 winRect->right - winRect->left,
547 -tmpRect.left, -tmpRect.top );
549 winRect->top +=
550 MENU_GetMenuBarHeight( pWnd->hwndSelf,
551 winRect->right - winRect->left,
552 -tmpRect.left, -tmpRect.top ) + 1;
555 if (TWEAK_WineLook > WIN31_LOOK) {
556 SetRect16 (&tmpRect, 0, 0, 0, 0);
557 NC_AdjustRectInner95 (&tmpRect, pWnd->dwStyle, pWnd->dwExStyle);
558 winRect->left -= tmpRect.left;
559 winRect->top -= tmpRect.top;
560 winRect->right -= tmpRect.right;
561 winRect->bottom -= tmpRect.bottom;
564 if (winRect->top > winRect->bottom)
565 winRect->bottom = winRect->top;
567 if (winRect->left > winRect->right)
568 winRect->right = winRect->left;
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->dwExStyle & WS_EX_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->dwExStyle & WS_EX_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, POINT pt )
669 RECT rect;
671 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
673 GetWindowRect(wndPtr->hwndSelf, &rect );
674 if (!PtInRect( &rect, pt )) return HTNOWHERE;
676 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
678 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
680 /* Check borders */
681 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
683 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
684 if (!PtInRect( &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 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
720 else if (HAS_THINFRAME( wndPtr->dwStyle ))
721 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
722 if (!PtInRect( &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 (!PtInRect( &rect, pt ))
732 /* Check system menu */
733 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
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 ScreenToClient( wndPtr->hwndSelf, &pt );
754 GetClientRect( wndPtr->hwndSelf, &rect );
755 if (PtInRect( &rect, pt )) return HTCLIENT;
757 /* Check vertical scroll bar */
759 if (wndPtr->dwStyle & WS_VSCROLL)
761 rect.right += GetSystemMetrics(SM_CXVSCROLL);
762 if (PtInRect( &rect, pt )) return HTVSCROLL;
765 /* Check horizontal scroll bar */
767 if (wndPtr->dwStyle & WS_HSCROLL)
769 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
770 if (PtInRect( &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 /* Has to return HTNOWHERE if nothing was found
789 Could happen when a window has a customized non client area */
790 return HTNOWHERE;
794 /***********************************************************************
795 * NC_DoNCHitTest95
797 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
799 * FIXME: Just a modified copy of the Win 3.1 version.
802 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
804 RECT rect;
806 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
808 GetWindowRect(wndPtr->hwndSelf, &rect );
809 if (!PtInRect( &rect, pt )) return HTNOWHERE;
811 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
813 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
815 /* Check borders */
816 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
818 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
819 if (!PtInRect( &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 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
855 else if (HAS_THINFRAME( wndPtr->dwStyle ))
856 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
857 if (!PtInRect( &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 (!PtInRect( &rect, pt ))
870 /* Check system menu */
871 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
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 ScreenToClient( wndPtr->hwndSelf, &pt );
903 GetClientRect( wndPtr->hwndSelf, &rect );
904 if (PtInRect( &rect, pt )) return HTCLIENT;
906 /* Check vertical scroll bar */
908 if (wndPtr->dwStyle & WS_VSCROLL)
910 rect.right += GetSystemMetrics(SM_CXVSCROLL);
911 if (PtInRect( &rect, pt )) return HTVSCROLL;
914 /* Check horizontal scroll bar */
916 if (wndPtr->dwStyle & WS_HSCROLL)
918 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
919 if (PtInRect( &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 /* Has to return HTNOWHERE if nothing was found
938 Could happen when a window has a customized non client area */
939 return HTNOWHERE;
943 /***********************************************************************
944 * NC_HandleNCHitTest
946 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
948 LONG NC_HandleNCHitTest (HWND hwnd , POINT 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->dwExStyle & WS_EX_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->dwExStyle & WS_EX_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->dwExStyle & WS_EX_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->dwExStyle & WS_EX_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 WND *wndPtr = WIN_FindWndPtr( hwnd );
1108 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
1110 NC_GetInsideRect95( hwnd, &rect );
1112 /* A tool window has a smaller Close button */
1113 if(wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
1115 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
1116 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
1117 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1119 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1120 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1121 rect.bottom = rect.top + iBmpHeight;
1122 rect.right = rect.left + iBmpWidth;
1124 else
1126 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
1127 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1128 rect.top += 2;
1129 rect.right -= 2;
1131 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1132 (DFCS_CAPTIONCLOSE |
1133 (down ? DFCS_PUSHED : 0) |
1134 (bGrayed ? DFCS_INACTIVE : 0)) );
1136 WIN_ReleaseWndPtr(wndPtr);
1139 /******************************************************************************
1140 * NC_DrawMaxButton95
1142 * Draws the maximize button for Win95 style windows.
1143 * If bGrayed is true, then draw a disabled Maximize button
1145 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1147 RECT rect;
1148 WND *wndPtr = WIN_FindWndPtr( hwnd );
1150 if( !(wndPtr->dwExStyle & WS_EX_MANAGED))
1152 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1153 NC_GetInsideRect95( hwnd, &rect );
1154 if (wndPtr->dwStyle & WS_SYSMENU)
1155 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1156 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1157 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1158 rect.top += 2;
1159 rect.right -= 2;
1160 if (down) flags |= DFCS_PUSHED;
1161 if (bGrayed) flags |= DFCS_INACTIVE;
1162 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1164 WIN_ReleaseWndPtr(wndPtr);
1167 /******************************************************************************
1168 * NC_DrawMinButton95
1170 * Draws the minimize button for Win95 style windows.
1171 * If bGrayed is true, then draw a disabled Minimize button
1173 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1175 RECT rect;
1176 WND *wndPtr = WIN_FindWndPtr( hwnd );
1178 if( !(wndPtr->dwExStyle & WS_EX_MANAGED))
1180 UINT flags = DFCS_CAPTIONMIN;
1181 NC_GetInsideRect95( hwnd, &rect );
1182 if (wndPtr->dwStyle & WS_SYSMENU)
1183 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1184 if (wndPtr->dwStyle & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1185 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1186 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1187 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1188 rect.top += 2;
1189 rect.right -= 2;
1190 if (down) flags |= DFCS_PUSHED;
1191 if (bGrayed) flags |= DFCS_INACTIVE;
1192 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1194 WIN_ReleaseWndPtr(wndPtr);
1197 /***********************************************************************
1198 * NC_DrawFrame
1200 * Draw a window frame inside the given rectangle, and update the rectangle.
1201 * The correct pen for the frame must be selected in the DC.
1203 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1204 BOOL active )
1206 INT width, height;
1208 if (TWEAK_WineLook != WIN31_LOOK)
1209 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1211 if (dlgFrame)
1213 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1214 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1215 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1216 COLOR_INACTIVECAPTION) );
1218 else
1220 width = GetSystemMetrics(SM_CXFRAME) - 2;
1221 height = GetSystemMetrics(SM_CYFRAME) - 2;
1222 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1223 COLOR_INACTIVEBORDER) );
1226 /* Draw frame */
1227 PatBlt( hdc, rect->left, rect->top,
1228 rect->right - rect->left, height, PATCOPY );
1229 PatBlt( hdc, rect->left, rect->top,
1230 width, rect->bottom - rect->top, PATCOPY );
1231 PatBlt( hdc, rect->left, rect->bottom - 1,
1232 rect->right - rect->left, -height, PATCOPY );
1233 PatBlt( hdc, rect->right - 1, rect->top,
1234 -width, rect->bottom - rect->top, PATCOPY );
1236 if (dlgFrame)
1238 InflateRect( rect, -width, -height );
1240 else
1242 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1243 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1245 /* Draw inner rectangle */
1247 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1248 Rectangle( hdc, rect->left + width, rect->top + height,
1249 rect->right - width , rect->bottom - height );
1251 /* Draw the decorations */
1253 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1254 LineTo( hdc, rect->left + width, rect->top + decYOff );
1255 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1256 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1257 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1258 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1259 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1260 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1262 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1263 LineTo( hdc, rect->left + decXOff, rect->top + height);
1264 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1265 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1266 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1267 LineTo( hdc, rect->right - decXOff, rect->top + height );
1268 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1269 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1271 InflateRect( rect, -width - 1, -height - 1 );
1276 /******************************************************************************
1278 * void NC_DrawFrame95(
1279 * HDC hdc,
1280 * RECT *rect,
1281 * BOOL dlgFrame,
1282 * BOOL active )
1284 * Draw a window frame inside the given rectangle, and update the rectangle.
1285 * The correct pen for the frame must be selected in the DC.
1287 * Bugs
1288 * Many. First, just what IS a frame in Win95? Note that the 3D look
1289 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1290 * edge. The inner rectangle just inside the frame is handled by the
1291 * Caption code.
1293 * In short, for most people, this function should be a nop (unless
1294 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1295 * them lately, but just to get this code right). Even so, it doesn't
1296 * appear to be so. It's being worked on...
1298 * Revision history
1299 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1300 * Original implementation (based on NC_DrawFrame)
1301 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1302 * Some minor fixes.
1303 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1304 * Fixed a fix or something.
1306 *****************************************************************************/
1308 static void NC_DrawFrame95(
1309 HDC hdc,
1310 RECT *rect,
1311 BOOL dlgFrame,
1312 BOOL active )
1314 INT width, height;
1316 if (dlgFrame)
1318 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1319 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1321 else
1323 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXEDGE);
1324 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYEDGE);
1327 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1328 COLOR_INACTIVEBORDER) );
1330 /* Draw frame */
1331 PatBlt( hdc, rect->left, rect->top,
1332 rect->right - rect->left, height, PATCOPY );
1333 PatBlt( hdc, rect->left, rect->top,
1334 width, rect->bottom - rect->top, PATCOPY );
1335 PatBlt( hdc, rect->left, rect->bottom - 1,
1336 rect->right - rect->left, -height, PATCOPY );
1337 PatBlt( hdc, rect->right - 1, rect->top,
1338 -width, rect->bottom - rect->top, PATCOPY );
1340 InflateRect( rect, -width, -height );
1343 /***********************************************************************
1344 * NC_DrawMovingFrame
1346 * Draw the frame used when moving or resizing window.
1348 * FIXME: This causes problems in Win95 mode. (why?)
1350 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
1352 if (thickframe)
1354 RECT16 r16;
1355 CONV_RECT32TO16( rect, &r16 );
1356 FastWindowFrame16( hdc, &r16, GetSystemMetrics(SM_CXFRAME),
1357 GetSystemMetrics(SM_CYFRAME), PATINVERT );
1359 else DrawFocusRect( hdc, rect );
1363 /***********************************************************************
1364 * NC_DrawCaption
1366 * Draw the window caption.
1367 * The correct pen for the window frame must be selected in the DC.
1369 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1370 DWORD style, BOOL active )
1372 RECT r = *rect;
1373 WND * wndPtr = WIN_FindWndPtr( hwnd );
1374 char buffer[256];
1376 if (wndPtr->dwExStyle & WS_EX_MANAGED)
1378 WIN_ReleaseWndPtr(wndPtr);
1379 return;
1382 if (!hbitmapClose)
1384 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) )))
1386 WIN_ReleaseWndPtr(wndPtr);
1387 return;
1389 hbitmapMinimize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
1390 hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
1391 hbitmapMaximize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
1392 hbitmapMaximizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOMD) );
1393 hbitmapRestore = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORE) );
1394 hbitmapRestoreD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
1397 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
1399 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1400 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1401 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1402 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1403 r.left++;
1404 r.right--;
1405 SelectObject( hdc, hbrushOld );
1407 WIN_ReleaseWndPtr(wndPtr);
1408 MoveToEx( hdc, r.left, r.bottom, NULL );
1409 LineTo( hdc, r.right, r.bottom );
1411 if (style & WS_SYSMENU)
1413 NC_DrawSysButton( hwnd, hdc, FALSE );
1414 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1415 MoveToEx( hdc, r.left - 1, r.top, NULL );
1416 LineTo( hdc, r.left - 1, r.bottom );
1418 if (style & WS_MAXIMIZEBOX)
1420 NC_DrawMaxButton( hwnd, hdc, FALSE );
1421 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1423 if (style & WS_MINIMIZEBOX)
1425 NC_DrawMinButton( hwnd, hdc, FALSE );
1426 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1429 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1430 COLOR_INACTIVECAPTION) );
1432 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1434 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1435 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1436 SetBkMode( hdc, TRANSPARENT );
1437 DrawTextA( hdc, buffer, -1, &r,
1438 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1443 /******************************************************************************
1445 * NC_DrawCaption95(
1446 * HDC hdc,
1447 * RECT *rect,
1448 * HWND hwnd,
1449 * DWORD style,
1450 * BOOL active )
1452 * Draw the window caption for Win95 style windows.
1453 * The correct pen for the window frame must be selected in the DC.
1455 * Bugs
1456 * Hey, a function that finally works! Well, almost.
1457 * It's being worked on.
1459 * Revision history
1460 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1461 * Original implementation.
1462 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1463 * Some minor fixes.
1465 *****************************************************************************/
1467 static void NC_DrawCaption95(
1468 HDC hdc,
1469 RECT *rect,
1470 HWND hwnd,
1471 DWORD style,
1472 DWORD exStyle,
1473 BOOL active )
1475 RECT r = *rect;
1476 WND *wndPtr = WIN_FindWndPtr( hwnd );
1477 char buffer[256];
1478 HPEN hPrevPen;
1479 HMENU hSysMenu;
1481 if (wndPtr->dwExStyle & WS_EX_MANAGED)
1483 WIN_ReleaseWndPtr(wndPtr);
1484 return;
1486 WIN_ReleaseWndPtr(wndPtr);
1488 hPrevPen = SelectObject( hdc, GetSysColorPen(COLOR_3DFACE) );
1489 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1490 LineTo( hdc, r.right, r.bottom - 1 );
1491 SelectObject( hdc, hPrevPen );
1492 r.bottom--;
1494 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1495 COLOR_INACTIVECAPTION) );
1497 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1498 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1499 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1502 if (style & WS_SYSMENU)
1504 UINT state;
1506 /* Go get the sysmenu */
1507 hSysMenu = GetSystemMenu(hwnd, FALSE);
1508 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1510 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1511 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1512 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1513 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1515 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1517 /* In win95 the two buttons are always there */
1518 /* But if the menu item is not in the menu they're disabled*/
1520 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1521 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1523 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1524 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1528 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1529 NONCLIENTMETRICSA nclm;
1530 HFONT hFont, hOldFont;
1531 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1532 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1533 if (exStyle & WS_EX_TOOLWINDOW)
1534 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1535 else
1536 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1537 hOldFont = SelectObject (hdc, hFont);
1538 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1539 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1540 SetBkMode( hdc, TRANSPARENT );
1541 r.left += 2;
1542 DrawTextA( hdc, buffer, -1, &r,
1543 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1544 DeleteObject (SelectObject (hdc, hOldFont));
1550 /***********************************************************************
1551 * NC_DoNCPaint
1553 * Paint the non-client area. clip is currently unused.
1555 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1557 HDC hdc;
1558 RECT rect;
1559 BOOL active;
1560 HWND hwnd = wndPtr->hwndSelf;
1562 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1563 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1565 active = wndPtr->flags & WIN_NCACTIVATED;
1567 TRACE("%04x %d\n", hwnd, active );
1569 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1570 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1572 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1573 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1574 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1575 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1576 == NULLREGION)
1578 ReleaseDC( hwnd, hdc );
1579 return;
1582 rect.top = rect.left = 0;
1583 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1584 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1586 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1588 if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
1590 if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1592 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1593 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1594 InflateRect( &rect, -1, -1 );
1597 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1598 NC_DrawFrame(hdc, &rect, FALSE, active );
1599 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1600 NC_DrawFrame( hdc, &rect, TRUE, active );
1602 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1604 RECT r = rect;
1605 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1606 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1607 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1611 if (HAS_MENU(wndPtr))
1613 RECT r = rect;
1614 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1615 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1618 /* Draw the scroll-bars */
1620 if (wndPtr->dwStyle & WS_VSCROLL)
1621 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1622 if (wndPtr->dwStyle & WS_HSCROLL)
1623 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1625 /* Draw the "size-box" */
1627 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1629 RECT r = rect;
1630 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1631 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1632 if(wndPtr->dwStyle & WS_BORDER) {
1633 r.left++;
1634 r.top++;
1636 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1639 ReleaseDC( hwnd, hdc );
1643 /******************************************************************************
1645 * void NC_DoNCPaint95(
1646 * WND *wndPtr,
1647 * HRGN clip,
1648 * BOOL suppress_menupaint )
1650 * Paint the non-client area for Win95 windows. The clip region is
1651 * currently ignored.
1653 * Bugs
1654 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1655 * misc/tweak.c controls/menu.c # :-)
1657 * Revision history
1658 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1659 * Original implementation
1660 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1661 * Fixed some bugs.
1662 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1663 * Streamlined window style checks.
1665 *****************************************************************************/
1667 static void NC_DoNCPaint95(
1668 WND *wndPtr,
1669 HRGN clip,
1670 BOOL suppress_menupaint )
1672 HDC hdc;
1673 RECT rfuzz, rect, rectClip;
1674 BOOL active;
1675 HWND hwnd = wndPtr->hwndSelf;
1677 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1678 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1680 active = wndPtr->flags & WIN_NCACTIVATED;
1682 TRACE("%04x %d\n", hwnd, active );
1684 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1685 the call to GetDCEx implying that it is allowed not to use it either.
1686 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1687 will cause clipRgn to be deleted after ReleaseDC().
1688 Now, how is the "system" supposed to tell what happened?
1691 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1692 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1695 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1696 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1697 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1698 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1699 == NULLREGION)
1701 ReleaseDC( hwnd, hdc );
1702 return;
1705 rect.top = rect.left = 0;
1706 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1707 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1709 if( clip > 1 )
1710 GetRgnBox( clip, &rectClip );
1711 else
1713 clip = 0;
1714 rectClip = rect;
1717 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1719 if(!(wndPtr->dwExStyle & WS_EX_MANAGED)) {
1720 if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1721 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1723 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1724 NC_DrawFrame95(hdc, &rect, FALSE, active );
1725 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1726 NC_DrawFrame95( hdc, &rect, TRUE, active );
1727 else if (HAS_THINFRAME( wndPtr->dwStyle )) {
1728 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1729 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1732 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1734 RECT r = rect;
1735 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1736 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1737 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1739 else {
1740 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1741 rect.top += GetSystemMetrics(SM_CYCAPTION);
1743 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1744 NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1745 wndPtr->dwExStyle, active);
1749 if (HAS_MENU(wndPtr))
1751 RECT r = rect;
1752 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1754 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1755 r.left, r.top, r.right, r.bottom);
1757 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1760 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1761 rect.left, rect.top, rect.right, rect.bottom );
1763 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1764 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1766 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
1767 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1769 /* Draw the scroll-bars */
1771 if (wndPtr->dwStyle & WS_VSCROLL)
1772 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1773 if (wndPtr->dwStyle & WS_HSCROLL)
1774 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1776 /* Draw the "size-box" */
1777 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1779 RECT r = rect;
1780 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1781 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1782 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1785 ReleaseDC( hwnd, hdc );
1791 /***********************************************************************
1792 * NC_HandleNCPaint
1794 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1796 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1798 WND* wndPtr = WIN_FindWndPtr( hwnd );
1800 if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1802 if( wndPtr->dwStyle & WS_MINIMIZE )
1803 WINPOS_RedrawIconTitle( hwnd );
1804 else if (TWEAK_WineLook == WIN31_LOOK)
1805 NC_DoNCPaint( wndPtr, clip, FALSE );
1806 else
1807 NC_DoNCPaint95( wndPtr, clip, FALSE );
1809 WIN_ReleaseWndPtr(wndPtr);
1810 return 0;
1814 /***********************************************************************
1815 * NC_HandleNCActivate
1817 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1819 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM16 wParam )
1821 WORD wStateChange;
1823 if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
1824 else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
1826 if( wStateChange )
1828 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1829 else wndPtr->flags &= ~WIN_NCACTIVATED;
1831 if( wndPtr->dwStyle & WS_MINIMIZE )
1832 WINPOS_RedrawIconTitle( wndPtr->hwndSelf );
1833 else if (TWEAK_WineLook == WIN31_LOOK)
1834 NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1835 else
1836 NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1838 return TRUE;
1842 /***********************************************************************
1843 * NC_HandleSetCursor
1845 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1847 LONG NC_HandleSetCursor( HWND hwnd, WPARAM16 wParam, LPARAM lParam )
1849 if (hwnd != (HWND)wParam) return 0; /* Don't set the cursor for child windows */
1851 switch(LOWORD(lParam))
1853 case HTERROR:
1855 WORD msg = HIWORD( lParam );
1856 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1857 (msg == WM_RBUTTONDOWN))
1858 MessageBeep(0);
1860 break;
1862 case HTCLIENT:
1864 HICON16 hCursor = (HICON16) GetClassWord(hwnd, GCW_HCURSOR);
1865 if(hCursor) {
1866 SetCursor16(hCursor);
1867 return TRUE;
1869 return FALSE;
1872 case HTLEFT:
1873 case HTRIGHT:
1874 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1876 case HTTOP:
1877 case HTBOTTOM:
1878 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1880 case HTTOPLEFT:
1881 case HTBOTTOMRIGHT:
1882 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1884 case HTTOPRIGHT:
1885 case HTBOTTOMLEFT:
1886 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1889 /* Default cursor: arrow */
1890 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1893 /***********************************************************************
1894 * NC_GetSysPopupPos
1896 BOOL NC_GetSysPopupPos( WND* wndPtr, RECT* rect )
1898 if( wndPtr->hSysMenu )
1900 if( wndPtr->dwStyle & WS_MINIMIZE )
1901 GetWindowRect( wndPtr->hwndSelf, rect );
1902 else
1904 if (TWEAK_WineLook == WIN31_LOOK)
1905 NC_GetInsideRect( wndPtr->hwndSelf, rect );
1906 else
1907 NC_GetInsideRect95( wndPtr->hwndSelf, rect );
1908 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1909 if (wndPtr->dwStyle & WS_CHILD)
1910 ClientToScreen( wndPtr->parent->hwndSelf, (POINT *)rect );
1911 if (TWEAK_WineLook == WIN31_LOOK) {
1912 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1913 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1915 else {
1916 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1917 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1920 return TRUE;
1922 return FALSE;
1925 /***********************************************************************
1926 * NC_StartSizeMove
1928 * Initialisation of a move or resize, when initiatied from a menu choice.
1929 * Return hit test code for caption or sizing border.
1931 static LONG NC_StartSizeMove( WND* wndPtr, WPARAM16 wParam,
1932 POINT *capturePoint )
1934 LONG hittest = 0;
1935 POINT pt;
1936 MSG msg;
1937 RECT rectWindow;
1939 GetWindowRect(wndPtr->hwndSelf,&rectWindow);
1941 if ((wParam & 0xfff0) == SC_MOVE)
1943 /* Move pointer at the center of the caption */
1944 RECT rect;
1945 if (TWEAK_WineLook == WIN31_LOOK)
1946 NC_GetInsideRect( wndPtr->hwndSelf, &rect );
1947 else
1948 NC_GetInsideRect95( wndPtr->hwndSelf, &rect );
1949 if (wndPtr->dwStyle & WS_SYSMENU)
1950 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
1951 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
1952 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1953 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
1954 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1955 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
1956 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
1957 hittest = HTCAPTION;
1958 *capturePoint = pt;
1960 else /* SC_SIZE */
1962 while(!hittest)
1964 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE, NULL );
1965 switch(msg.message)
1967 case WM_MOUSEMOVE:
1968 hittest = NC_HandleNCHitTest( wndPtr->hwndSelf, msg.pt );
1969 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
1970 hittest = 0;
1971 break;
1973 case WM_LBUTTONUP:
1974 return 0;
1976 case WM_KEYDOWN:
1977 switch(msg.wParam)
1979 case VK_UP:
1980 hittest = HTTOP;
1981 pt.x =(rectWindow.left+rectWindow.right)/2;
1982 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
1983 break;
1984 case VK_DOWN:
1985 hittest = HTBOTTOM;
1986 pt.x =(rectWindow.left+rectWindow.right)/2;
1987 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
1988 break;
1989 case VK_LEFT:
1990 hittest = HTLEFT;
1991 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
1992 pt.y =(rectWindow.top+rectWindow.bottom)/2;
1993 break;
1994 case VK_RIGHT:
1995 hittest = HTRIGHT;
1996 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
1997 pt.y =(rectWindow.top+rectWindow.bottom)/2;
1998 break;
1999 case VK_RETURN:
2000 case VK_ESCAPE: return 0;
2004 *capturePoint = pt;
2006 SetCursorPos( pt.x, pt.y );
2007 NC_HandleSetCursor( wndPtr->hwndSelf,
2008 wndPtr->hwndSelf, MAKELONG( hittest, WM_MOUSEMOVE ));
2009 return hittest;
2013 /***********************************************************************
2014 * NC_DoSizeMove
2016 * Perform SC_MOVE and SC_SIZE commands. `
2018 static void NC_DoSizeMove( HWND hwnd, WORD wParam )
2020 MSG msg;
2021 RECT sizingRect, mouseRect, origRect;
2022 HDC hdc;
2023 LONG hittest = (LONG)(wParam & 0x0f);
2024 HCURSOR16 hDragCursor = 0, hOldCursor = 0;
2025 POINT minTrack, maxTrack;
2026 POINT capturePoint, pt;
2027 WND * wndPtr = WIN_FindWndPtr( hwnd );
2028 BOOL thickframe = HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle );
2029 BOOL iconic = wndPtr->dwStyle & WS_MINIMIZE;
2030 BOOL moved = FALSE;
2031 DWORD dwPoint = GetMessagePos ();
2032 BOOL DragFullWindows = FALSE;
2033 int iWndsLocks;
2035 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
2037 pt.x = SLOWORD(dwPoint);
2038 pt.y = SHIWORD(dwPoint);
2039 capturePoint = pt;
2041 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) ||
2042 (wndPtr->dwExStyle & WS_EX_MANAGED)) goto END;
2044 if ((wParam & 0xfff0) == SC_MOVE)
2046 if (!hittest)
2047 hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2048 if (!hittest) goto END;
2050 else /* SC_SIZE */
2052 if (!thickframe) goto END;
2053 if ( hittest && hittest != HTSYSMENU ) hittest += 2;
2054 else
2056 SetCapture(hwnd);
2057 hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2058 if (!hittest)
2060 ReleaseCapture();
2061 goto END;
2066 /* Get min/max info */
2068 WINPOS_GetMinMaxInfo( wndPtr, NULL, NULL, &minTrack, &maxTrack );
2069 sizingRect = wndPtr->rectWindow;
2070 origRect = sizingRect;
2071 if (wndPtr->dwStyle & WS_CHILD)
2072 GetClientRect( wndPtr->parent->hwndSelf, &mouseRect );
2073 else
2074 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2075 if (ON_LEFT_BORDER(hittest))
2077 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
2078 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
2080 else if (ON_RIGHT_BORDER(hittest))
2082 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
2083 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
2085 if (ON_TOP_BORDER(hittest))
2087 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
2088 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
2090 else if (ON_BOTTOM_BORDER(hittest))
2092 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
2093 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
2095 if (wndPtr->dwStyle & WS_CHILD)
2097 MapWindowPoints( wndPtr->parent->hwndSelf, 0,
2098 (LPPOINT)&mouseRect, 2 );
2100 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
2102 if (GetCapture() != hwnd) SetCapture( hwnd );
2104 if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
2106 /* Retrieve a default cache DC (without using the window style) */
2107 hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
2109 else
2110 hdc = GetDC( 0 );
2112 if( iconic ) /* create a cursor for dragging */
2114 HICON16 hIcon = GetClassWord(wndPtr->hwndSelf, GCW_HICON);
2115 if(!hIcon) hIcon = (HICON16) SendMessage16( hwnd, WM_QUERYDRAGICON, 0, 0L);
2116 if( hIcon ) hDragCursor = CURSORICON_IconToCursor( hIcon, TRUE );
2117 if( !hDragCursor ) iconic = FALSE;
2120 wndPtr->pDriver->pPreSizeMove(wndPtr);
2122 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
2123 if( !iconic && TWEAK_WineLook == WIN31_LOOK )
2124 if(!DragFullWindows)
2125 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2127 while(1)
2129 int dx = 0, dy = 0;
2131 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE, NULL );
2133 /* Exit on button-up, Return, or Esc */
2134 if ((msg.message == WM_LBUTTONUP) ||
2135 ((msg.message == WM_KEYDOWN) &&
2136 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
2138 if (msg.message == WM_PAINT)
2140 if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2141 UpdateWindow( msg.hwnd );
2142 if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2143 continue;
2146 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
2147 continue; /* We are not interested in other messages */
2149 pt = msg.pt;
2151 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
2153 case VK_UP: pt.y -= 8; break;
2154 case VK_DOWN: pt.y += 8; break;
2155 case VK_LEFT: pt.x -= 8; break;
2156 case VK_RIGHT: pt.x += 8; break;
2159 pt.x = max( pt.x, mouseRect.left );
2160 pt.x = min( pt.x, mouseRect.right );
2161 pt.y = max( pt.y, mouseRect.top );
2162 pt.y = min( pt.y, mouseRect.bottom );
2164 dx = pt.x - capturePoint.x;
2165 dy = pt.y - capturePoint.y;
2167 if (dx || dy)
2169 if( !moved )
2171 moved = TRUE;
2173 if( iconic ) /* ok, no system popup tracking */
2175 hOldCursor = SetCursor(hDragCursor);
2176 ShowCursor( TRUE );
2177 WINPOS_ShowIconTitle( wndPtr, FALSE );
2178 } else if(TWEAK_WineLook != WIN31_LOOK)
2180 if(!DragFullWindows)
2181 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2185 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
2186 else
2188 RECT newRect = sizingRect;
2189 WPARAM wpSizingHit = 0;
2191 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
2192 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
2193 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
2194 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
2195 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
2196 if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2197 capturePoint = pt;
2199 /* determine the hit location */
2200 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
2201 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
2202 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
2204 if (!iconic)
2206 if(!DragFullWindows)
2207 NC_DrawMovingFrame( hdc, &newRect, thickframe );
2208 else {
2209 /* To avoid any deadlocks, all the locks on the windows
2210 structures must be suspended before the SetWindowPos */
2211 iWndsLocks = WIN_SuspendWndsLock();
2212 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
2213 newRect.right - newRect.left,
2214 newRect.bottom - newRect.top,
2215 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2216 WIN_RestoreWndsLock(iWndsLocks);
2219 sizingRect = newRect;
2224 ReleaseCapture();
2225 if( iconic )
2227 if( moved ) /* restore cursors, show icon title later on */
2229 ShowCursor( FALSE );
2230 SetCursor( hOldCursor );
2232 DestroyCursor( hDragCursor );
2234 else if(moved || TWEAK_WineLook == WIN31_LOOK)
2235 if(!DragFullWindows)
2236 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2238 if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
2239 ReleaseDC( wndPtr->parent->hwndSelf, hdc );
2240 else
2241 ReleaseDC( 0, hdc );
2243 wndPtr->pDriver->pPostSizeMove(wndPtr);
2245 if (HOOK_IsHooked( WH_CBT ))
2247 RECT16* pr = SEGPTR_NEW(RECT16);
2248 if( pr )
2250 CONV_RECT32TO16( &sizingRect, pr );
2251 if( HOOK_CallHooks16( WH_CBT, HCBT_MOVESIZE, hwnd,
2252 (LPARAM)SEGPTR_GET(pr)) )
2253 sizingRect = wndPtr->rectWindow;
2254 else
2255 CONV_RECT16TO32( pr, &sizingRect );
2256 SEGPTR_FREE(pr);
2259 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
2260 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic16(hwnd), 0L);
2262 /* window moved or resized */
2263 if (moved)
2265 /* To avoid any deadlocks, all the locks on the windows
2266 structures must be suspended before the SetWindowPos */
2267 iWndsLocks = WIN_SuspendWndsLock();
2269 /* if the moving/resizing isn't canceled call SetWindowPos
2270 * with the new position or the new size of the window
2272 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
2274 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
2275 if(!DragFullWindows)
2276 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
2277 sizingRect.right - sizingRect.left,
2278 sizingRect.bottom - sizingRect.top,
2279 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2281 else { /* restore previous size/position */
2282 if(DragFullWindows)
2283 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
2284 origRect.right - origRect.left,
2285 origRect.bottom - origRect.top,
2286 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2289 WIN_RestoreWndsLock(iWndsLocks);
2292 if( IsWindow(hwnd) )
2293 if( wndPtr->dwStyle & WS_MINIMIZE )
2295 /* Single click brings up the system menu when iconized */
2297 if( !moved )
2299 if( wndPtr->dwStyle & WS_SYSMENU )
2300 SendMessageA( hwnd, WM_SYSCOMMAND,
2301 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
2303 else WINPOS_ShowIconTitle( wndPtr, TRUE );
2306 END:
2307 WIN_ReleaseWndPtr(wndPtr);
2311 /***********************************************************************
2312 * NC_TrackMinMaxBox95
2314 * Track a mouse button press on the minimize or maximize box.
2316 * The big difference between 3.1 and 95 is the disabled button state.
2317 * In win95 the system button can be disabled, so it can ignore the mouse
2318 * event.
2321 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
2323 MSG msg;
2324 HDC hdc = GetWindowDC( hwnd );
2325 BOOL pressed = TRUE;
2326 UINT state;
2327 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
2328 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2330 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
2332 if (wParam == HTMINBUTTON)
2334 /* If the style is not present, do nothing */
2335 if (!(wndStyle & WS_MINIMIZEBOX))
2336 return;
2338 /* Check if the sysmenu item for minimize is there */
2339 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
2341 paintButton = &NC_DrawMinButton95;
2343 else
2345 /* If the style is not present, do nothing */
2346 if (!(wndStyle & WS_MAXIMIZEBOX))
2347 return;
2349 /* Check if the sysmenu item for maximize is there */
2350 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
2352 paintButton = &NC_DrawMaxButton95;
2355 SetCapture( hwnd );
2357 (*paintButton)( hwnd, hdc, TRUE, FALSE);
2359 while(1)
2361 BOOL oldstate = pressed;
2362 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2364 if(msg.message == WM_LBUTTONUP)
2365 break;
2367 if(msg.message != WM_MOUSEMOVE)
2368 continue;
2370 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2371 if (pressed != oldstate)
2372 (*paintButton)( hwnd, hdc, pressed, FALSE);
2375 if(pressed)
2376 (*paintButton)(hwnd, hdc, FALSE, FALSE);
2378 ReleaseCapture();
2379 ReleaseDC( hwnd, hdc );
2381 /* If the item minimize or maximize of the sysmenu are not there */
2382 /* or if the style is not present, do nothing */
2383 if ((!pressed) || (state == 0xFFFFFFFF))
2384 return;
2386 if (wParam == HTMINBUTTON)
2387 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2388 else
2389 SendMessageA( hwnd, WM_SYSCOMMAND,
2390 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2393 /***********************************************************************
2394 * NC_TrackMinMaxBox
2396 * Track a mouse button press on the minimize or maximize box.
2398 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
2400 MSG msg;
2401 HDC hdc = GetWindowDC( hwnd );
2402 BOOL pressed = TRUE;
2403 void (*paintButton)(HWND, HDC16, BOOL);
2405 SetCapture( hwnd );
2407 if (wParam == HTMINBUTTON)
2408 paintButton = &NC_DrawMinButton;
2409 else
2410 paintButton = &NC_DrawMaxButton;
2412 (*paintButton)( hwnd, hdc, TRUE);
2414 while(1)
2416 BOOL oldstate = pressed;
2417 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2419 if(msg.message == WM_LBUTTONUP)
2420 break;
2422 if(msg.message != WM_MOUSEMOVE)
2423 continue;
2425 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2426 if (pressed != oldstate)
2427 (*paintButton)( hwnd, hdc, pressed);
2430 if(pressed)
2431 (*paintButton)( hwnd, hdc, FALSE);
2433 ReleaseCapture();
2434 ReleaseDC( hwnd, hdc );
2436 if (!pressed) return;
2438 if (wParam == HTMINBUTTON)
2439 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2440 else
2441 SendMessageA( hwnd, WM_SYSCOMMAND,
2442 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2446 /***********************************************************************
2447 * NC_TrackCloseButton95
2449 * Track a mouse button press on the Win95 close button.
2451 static void
2452 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
2454 MSG msg;
2455 HDC hdc;
2456 BOOL pressed = TRUE;
2457 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2458 UINT state;
2460 if(hSysMenu == 0)
2461 return;
2463 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
2465 /* If the item close of the sysmenu is disabled or not there do nothing */
2466 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
2467 return;
2469 hdc = GetWindowDC( hwnd );
2471 SetCapture( hwnd );
2473 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
2475 while(1)
2477 BOOL oldstate = pressed;
2478 MSG_InternalGetMessage( QMSG_WIN32A, &msg, 0, 0, 0, PM_REMOVE, FALSE, NULL );
2480 if(msg.message == WM_LBUTTONUP)
2481 break;
2483 if(msg.message != WM_MOUSEMOVE)
2484 continue;
2486 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2487 if (pressed != oldstate)
2488 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
2491 if(pressed)
2492 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
2494 ReleaseCapture();
2495 ReleaseDC( hwnd, hdc );
2496 if (!pressed) return;
2498 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
2502 /***********************************************************************
2503 * NC_TrackScrollBar
2505 * Track a mouse button press on the horizontal or vertical scroll-bar.
2507 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2509 MSG16 *msg;
2510 INT scrollbar;
2511 WND *wndPtr = WIN_FindWndPtr( hwnd );
2513 if ((wParam & 0xfff0) == SC_HSCROLL)
2515 if ((wParam & 0x0f) != HTHSCROLL) goto END;
2516 scrollbar = SB_HORZ;
2518 else /* SC_VSCROLL */
2520 if ((wParam & 0x0f) != HTVSCROLL) goto END;
2521 scrollbar = SB_VERT;
2524 if (!(msg = SEGPTR_NEW(MSG16))) goto END;
2525 pt.x -= wndPtr->rectWindow.left;
2526 pt.y -= wndPtr->rectWindow.top;
2527 SetCapture( hwnd );
2528 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
2532 GetMessage16( SEGPTR_GET(msg), 0, 0, 0 );
2533 switch(msg->message)
2535 case WM_LBUTTONUP:
2536 case WM_MOUSEMOVE:
2537 case WM_SYSTIMER:
2538 pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left -
2539 wndPtr->rectWindow.left;
2540 pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top -
2541 wndPtr->rectWindow.top;
2542 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
2543 break;
2544 default:
2545 TranslateMessage16( msg );
2546 DispatchMessage16( msg );
2547 break;
2549 if (!IsWindow( hwnd ))
2551 ReleaseCapture();
2552 break;
2554 } while (msg->message != WM_LBUTTONUP);
2555 SEGPTR_FREE(msg);
2556 END:
2557 WIN_ReleaseWndPtr(wndPtr);
2560 /***********************************************************************
2561 * NC_HandleNCLButtonDown
2563 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2565 LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
2567 HWND hwnd = pWnd->hwndSelf;
2569 switch(wParam) /* Hit test */
2571 case HTCAPTION:
2572 hwnd = WIN_GetTopParent(hwnd);
2574 if( WINPOS_SetActiveWindow(hwnd, TRUE, TRUE) || (GetActiveWindow() == hwnd) )
2575 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2576 break;
2578 case HTSYSMENU:
2579 if( pWnd->dwStyle & WS_SYSMENU )
2581 if( !(pWnd->dwStyle & WS_MINIMIZE) )
2583 HDC hDC = GetWindowDC(hwnd);
2584 if (TWEAK_WineLook == WIN31_LOOK)
2585 NC_DrawSysButton( hwnd, hDC, TRUE );
2586 else
2587 NC_DrawSysButton95( hwnd, hDC, TRUE );
2588 ReleaseDC( hwnd, hDC );
2590 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2592 break;
2594 case HTMENU:
2595 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2596 break;
2598 case HTHSCROLL:
2599 SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2600 break;
2602 case HTVSCROLL:
2603 SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2604 break;
2606 case HTMINBUTTON:
2607 case HTMAXBUTTON:
2608 if (TWEAK_WineLook == WIN31_LOOK)
2609 NC_TrackMinMaxBox( hwnd, wParam );
2610 else
2611 NC_TrackMinMaxBox95( hwnd, wParam );
2612 break;
2614 case HTCLOSE:
2615 if (TWEAK_WineLook >= WIN95_LOOK)
2616 NC_TrackCloseButton95 (hwnd, wParam);
2617 break;
2619 case HTLEFT:
2620 case HTRIGHT:
2621 case HTTOP:
2622 case HTTOPLEFT:
2623 case HTTOPRIGHT:
2624 case HTBOTTOM:
2625 case HTBOTTOMLEFT:
2626 case HTBOTTOMRIGHT:
2627 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2628 SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2629 break;
2631 case HTBORDER:
2632 break;
2634 return 0;
2638 /***********************************************************************
2639 * NC_HandleNCLButtonDblClk
2641 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2643 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam )
2646 * if this is an icon, send a restore since we are handling
2647 * a double click
2649 if (pWnd->dwStyle & WS_MINIMIZE)
2651 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
2652 return 0;
2655 switch(wParam) /* Hit test */
2657 case HTCAPTION:
2658 /* stop processing if WS_MAXIMIZEBOX is missing */
2659 if (pWnd->dwStyle & WS_MAXIMIZEBOX)
2660 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
2661 (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
2662 lParam );
2663 break;
2665 case HTSYSMENU:
2666 if (!(GetClassWord(pWnd->hwndSelf, GCW_STYLE) & CS_NOCLOSE))
2667 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
2668 break;
2670 case HTHSCROLL:
2671 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL,
2672 lParam );
2673 break;
2675 case HTVSCROLL:
2676 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL,
2677 lParam );
2678 break;
2680 return 0;
2684 /***********************************************************************
2685 * NC_HandleSysCommand
2687 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2689 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
2691 WND *wndPtr = WIN_FindWndPtr( hwnd );
2692 UINT16 uCommand = wParam & 0xFFF0;
2694 TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
2696 if (wndPtr->parent && (uCommand != SC_KEYMENU))
2697 ScreenToClient( wndPtr->parent->hwndSelf, &pt );
2699 switch (uCommand)
2701 case SC_SIZE:
2702 case SC_MOVE:
2703 NC_DoSizeMove( hwnd, wParam );
2704 break;
2706 case SC_MINIMIZE:
2707 if (hwnd == GetForegroundWindow())
2708 ShowOwnedPopups(hwnd,FALSE);
2709 ShowWindow( hwnd, SW_MINIMIZE );
2710 break;
2712 case SC_MAXIMIZE:
2713 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2714 ShowOwnedPopups(hwnd,TRUE);
2715 ShowWindow( hwnd, SW_MAXIMIZE );
2716 break;
2718 case SC_RESTORE:
2719 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2720 ShowOwnedPopups(hwnd,TRUE);
2721 ShowWindow( hwnd, SW_RESTORE );
2722 break;
2724 case SC_CLOSE:
2725 WIN_ReleaseWndPtr(wndPtr);
2726 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2728 case SC_VSCROLL:
2729 case SC_HSCROLL:
2730 NC_TrackScrollBar( hwnd, wParam, pt );
2731 break;
2733 case SC_MOUSEMENU:
2734 MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt );
2735 break;
2737 case SC_KEYMENU:
2738 MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
2739 break;
2741 case SC_TASKLIST:
2742 WinExec( "taskman.exe", SW_SHOWNORMAL );
2743 break;
2745 case SC_SCREENSAVE:
2746 if (wParam == SC_ABOUTWINE)
2748 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2749 if (hmodule)
2751 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2752 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2753 FreeLibrary( hmodule );
2756 else
2757 if (wParam == SC_PUTMARK)
2758 TRACE_(shell)("Mark requested by user\n");
2759 break;
2761 case SC_HOTKEY:
2762 case SC_ARRANGE:
2763 case SC_NEXTWINDOW:
2764 case SC_PREVWINDOW:
2765 FIXME("unimplemented!\n");
2766 break;
2768 WIN_ReleaseWndPtr(wndPtr);
2769 return 0;
2772 /*************************************************************
2773 * NC_DrawGrayButton
2775 * Stub for the grayed button of the caption
2777 *************************************************************/
2779 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2781 HBITMAP hMaskBmp;
2782 HDC hdcMask = CreateCompatibleDC (0);
2783 HBRUSH hOldBrush;
2785 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2787 if(hMaskBmp == 0)
2788 return FALSE;
2790 SelectObject (hdcMask, hMaskBmp);
2792 /* Draw the grayed bitmap using the mask */
2793 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2794 BitBlt (hdc, x, y, 12, 10,
2795 hdcMask, 0, 0, 0xB8074A);
2797 /* Clean up */
2798 SelectObject (hdc, hOldBrush);
2799 DeleteObject(hMaskBmp);
2800 DeleteDC (hdcMask);
2802 return TRUE;
2805 HICON16 NC_IconForWindow(WND *wndPtr)
2807 HICON16 hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICONSM);
2808 if(!hIcon) hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON);
2810 /* If there is no hIcon specified and this is a modal dialog, */
2811 /* get the default one. */
2812 if (!hIcon && (wndPtr->dwStyle & DS_MODALFRAME))
2813 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
2815 return hIcon;