Rename "SystemTime" to "t" (this is *not* SYSTEMTIME - avoid
[wine/wine-kai.git] / windows / nonclient.c
blobc3bb72d2235d46efcd945b54abe4e20686339c80
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 */
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "version.h"
12 #include "win.h"
13 #include "user.h"
14 #include "heap.h"
15 #include "dce.h"
16 #include "controls.h"
17 #include "cursoricon.h"
18 #include "winpos.h"
19 #include "hook.h"
20 #include "nonclient.h"
21 #include "debugtools.h"
22 #include "shellapi.h"
23 #include "bitmap.h"
25 DEFAULT_DEBUG_CHANNEL(nonclient);
26 DECLARE_DEBUG_CHANNEL(shell);
28 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
30 static HBITMAP hbitmapClose;
31 static HBITMAP hbitmapMinimize;
32 static HBITMAP hbitmapMinimizeD;
33 static HBITMAP hbitmapMaximize;
34 static HBITMAP hbitmapMaximizeD;
35 static HBITMAP hbitmapRestore;
36 static HBITMAP hbitmapRestoreD;
38 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
39 0x55, 0x50,
40 0xAA, 0xA0,
41 0x55, 0x50,
42 0xAA, 0xA0,
43 0x55, 0x50,
44 0xAA, 0xA0,
45 0x55, 0x50,
46 0xAA, 0xA0,
47 0x55, 0x50};
49 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
50 #define SC_PUTMARK (SC_SCREENSAVE+2)
52 /* Some useful macros */
53 #define HAS_DLGFRAME(style,exStyle) \
54 (((exStyle) & WS_EX_DLGMODALFRAME) || \
55 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
57 #define HAS_THICKFRAME(style,exStyle) \
58 (((style) & WS_THICKFRAME) && \
59 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
61 #define HAS_THINFRAME(style) \
62 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
64 #define HAS_BIGFRAME(style,exStyle) \
65 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
66 ((exStyle) & WS_EX_DLGMODALFRAME))
68 #define HAS_STATICOUTERFRAME(style,exStyle) \
69 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
70 WS_EX_STATICEDGE)
72 #define HAS_ANYFRAME(style,exStyle) \
73 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
74 ((exStyle) & WS_EX_DLGMODALFRAME) || \
75 !((style) & (WS_CHILD | WS_POPUP)))
77 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
80 /***********************************************************************
81 * NC_AdjustRect
83 * Compute the size of the window rectangle from the size of the
84 * client rectangle.
86 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
88 if (TWEAK_WineLook > WIN31_LOOK)
89 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
91 if(style & WS_ICONIC) return;
93 if (HAS_THICKFRAME( style, exStyle ))
94 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
95 else if (HAS_DLGFRAME( style, exStyle ))
96 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
97 else if (HAS_THINFRAME( style ))
98 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
100 if ((style & WS_CAPTION) == WS_CAPTION)
101 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
103 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
105 if (style & WS_VSCROLL) {
106 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
107 if(!HAS_ANYFRAME( style, exStyle ))
108 rect->right++;
111 if (style & WS_HSCROLL) {
112 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
113 if(!HAS_ANYFRAME( style, exStyle ))
114 rect->bottom++;
119 /******************************************************************************
120 * NC_AdjustRectOuter95
122 * Computes the size of the "outside" parts of the window based on the
123 * parameters of the client area.
125 + PARAMS
126 * LPRECT16 rect
127 * DWORD style
128 * BOOL menu
129 * DWORD exStyle
131 * NOTES
132 * "Outer" parts of a window means the whole window frame, caption and
133 * menu bar. It does not include "inner" parts of the frame like client
134 * edge, static edge or scroll bars.
136 * Revision history
137 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
138 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
140 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
141 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
142 * NC_AdjustRectInner95 and added handling of Win95 styles.
144 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
145 * Streamlined window style checks.
147 *****************************************************************************/
149 static void
150 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
152 int adjust;
153 if(style & WS_ICONIC) return;
155 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
156 WS_EX_STATICEDGE)
158 adjust = 1; /* for the outer frame always present */
160 else
162 adjust = 0;
163 if ((exStyle & WS_EX_DLGMODALFRAME) ||
164 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
166 if (style & WS_THICKFRAME)
167 adjust += ( GetSystemMetrics (SM_CXFRAME)
168 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
169 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
170 (exStyle & WS_EX_DLGMODALFRAME))
171 adjust++; /* The other border */
173 InflateRect (rect, adjust, adjust);
175 if ((style & WS_CAPTION) == WS_CAPTION)
177 if (exStyle & WS_EX_TOOLWINDOW)
178 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
179 else
180 rect->top -= GetSystemMetrics(SM_CYCAPTION);
182 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
186 /******************************************************************************
187 * NC_AdjustRectInner95
189 * Computes the size of the "inside" part of the window based on the
190 * parameters of the client area.
192 + PARAMS
193 * LPRECT16 rect
194 * DWORD style
195 * DWORD exStyle
197 * NOTES
198 * "Inner" part of a window means the window frame inside of the flat
199 * window frame. It includes the client edge, the static edge and the
200 * scroll bars.
202 * Revision history
203 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
204 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
206 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
207 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
208 * NC_AdjustRectInner95 and added handling of Win95 styles.
210 *****************************************************************************/
212 static void
213 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
215 if(style & WS_ICONIC) return;
217 if (exStyle & WS_EX_CLIENTEDGE)
218 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
220 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
221 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
226 static HICON NC_IconForWindow( HWND hwnd )
228 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
229 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
231 /* If there is no hIcon specified and this is a modal dialog,
232 * get the default one.
234 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
235 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
236 return hIcon;
239 /***********************************************************************
240 * DrawCaption (USER.660) Draws a caption bar
242 * PARAMS
243 * hwnd [I]
244 * hdc [I]
245 * lpRect [I]
246 * uFlags [I]
248 * RETURNS
249 * Success:
250 * Failure:
253 BOOL16 WINAPI
254 DrawCaption16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, UINT16 uFlags)
256 RECT rect32;
258 if (rect)
259 CONV_RECT16TO32 (rect, &rect32);
261 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect ? &rect32 : NULL,
262 0, 0, NULL, uFlags & 0x1F);
266 /***********************************************************************
267 * DrawCaption (USER32.@) Draws a caption bar
269 * PARAMS
270 * hwnd [I]
271 * hdc [I]
272 * lpRect [I]
273 * uFlags [I]
275 * RETURNS
276 * Success:
277 * Failure:
280 BOOL WINAPI
281 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
283 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
287 /***********************************************************************
288 * DrawCaptionTemp (USER.657)
290 * PARAMS
292 * RETURNS
293 * Success:
294 * Failure:
297 BOOL16 WINAPI
298 DrawCaptionTemp16 (HWND16 hwnd, HDC16 hdc, const RECT16 *rect, HFONT16 hFont,
299 HICON16 hIcon, LPCSTR str, UINT16 uFlags)
301 RECT rect32;
303 if (rect)
304 CONV_RECT16TO32(rect,&rect32);
306 return (BOOL16)DrawCaptionTempA (hwnd, hdc, rect?&rect32:NULL, hFont,
307 hIcon, str, uFlags & 0x1F);
311 /***********************************************************************
312 * DrawCaptionTempA (USER32.@)
314 * PARAMS
316 * RETURNS
317 * Success:
318 * Failure:
321 BOOL WINAPI
322 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
323 HICON hIcon, LPCSTR str, UINT uFlags)
325 RECT rc = *rect;
327 TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
328 hwnd, hdc, rect, hFont, hIcon, str, uFlags);
330 /* drawing background */
331 if (uFlags & DC_INBUTTON) {
332 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
334 if (uFlags & DC_ACTIVE) {
335 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
336 PatBlt (hdc, rc.left, rc.top,
337 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
338 SelectObject (hdc, hbr);
341 else {
342 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
343 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
347 /* drawing icon */
348 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
349 POINT pt;
351 pt.x = rc.left + 2;
352 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
354 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
355 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
356 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
357 rc.left += (rc.bottom - rc.top);
360 /* drawing text */
361 if (uFlags & DC_TEXT) {
362 HFONT hOldFont;
364 if (uFlags & DC_INBUTTON)
365 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
366 else if (uFlags & DC_ACTIVE)
367 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
368 else
369 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
371 SetBkMode (hdc, TRANSPARENT);
373 if (hFont)
374 hOldFont = SelectObject (hdc, hFont);
375 else {
376 NONCLIENTMETRICSA nclm;
377 HFONT hNewFont;
378 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
379 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
380 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
381 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
382 hOldFont = SelectObject (hdc, hNewFont);
385 if (str)
386 DrawTextA (hdc, str, -1, &rc,
387 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
388 else {
389 CHAR szText[128];
390 INT nLen;
391 nLen = GetWindowTextA (hwnd, szText, 128);
392 DrawTextA (hdc, szText, nLen, &rc,
393 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
396 if (hFont)
397 SelectObject (hdc, hOldFont);
398 else
399 DeleteObject (SelectObject (hdc, hOldFont));
402 /* drawing focus ??? */
403 if (uFlags & 0x2000)
404 FIXME("undocumented flag (0x2000)!\n");
406 return 0;
410 /***********************************************************************
411 * DrawCaptionTempW (USER32.@)
413 * PARAMS
415 * RETURNS
416 * Success:
417 * Failure:
420 BOOL WINAPI
421 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
422 HICON hIcon, LPCWSTR str, UINT uFlags)
424 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
425 BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
426 HeapFree (GetProcessHeap (), 0, p);
427 return res;
431 /***********************************************************************
432 * AdjustWindowRect (USER.102)
434 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
436 return AdjustWindowRectEx16( rect, style, menu, 0 );
440 /***********************************************************************
441 * AdjustWindowRect (USER32.@)
443 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
445 return AdjustWindowRectEx( rect, style, menu, 0 );
449 /***********************************************************************
450 * AdjustWindowRectEx (USER.454)
452 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
453 BOOL16 menu, DWORD exStyle )
455 RECT rect32;
456 BOOL ret;
458 CONV_RECT16TO32( rect, &rect32 );
459 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
460 CONV_RECT32TO16( &rect32, rect );
461 return ret;
465 /***********************************************************************
466 * AdjustWindowRectEx (USER32.@)
468 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
470 /* Correct the window style */
472 if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
473 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
474 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
475 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
476 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
478 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
479 rect->left, rect->top, rect->right, rect->bottom,
480 style, menu, exStyle );
482 if (TWEAK_WineLook == WIN31_LOOK)
483 NC_AdjustRect( rect, style, menu, exStyle );
484 else
486 NC_AdjustRectOuter95( rect, style, menu, exStyle );
487 NC_AdjustRectInner95( rect, style, exStyle );
489 return TRUE;
493 /***********************************************************************
494 * NC_HandleNCCalcSize
496 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
498 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
500 RECT tmpRect = { 0, 0, 0, 0 };
501 LONG result = 0;
502 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
503 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
504 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
506 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
507 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
509 if (!IsIconic(hwnd))
511 if (TWEAK_WineLook == WIN31_LOOK)
512 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
513 else
514 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
516 winRect->left -= tmpRect.left;
517 winRect->top -= tmpRect.top;
518 winRect->right -= tmpRect.right;
519 winRect->bottom -= tmpRect.bottom;
521 if (!(style & WS_CHILD) && GetMenu(hwnd))
523 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
524 "at (%d, %d).\n", hwnd,
525 winRect->right - winRect->left,
526 -tmpRect.left, -tmpRect.top );
528 winRect->top +=
529 MENU_GetMenuBarHeight( hwnd,
530 winRect->right - winRect->left,
531 -tmpRect.left, -tmpRect.top ) + 1;
534 if (TWEAK_WineLook > WIN31_LOOK) {
535 SetRect(&tmpRect, 0, 0, 0, 0);
536 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
537 winRect->left -= tmpRect.left;
538 winRect->top -= tmpRect.top;
539 winRect->right -= tmpRect.right;
540 winRect->bottom -= tmpRect.bottom;
543 if (winRect->top > winRect->bottom)
544 winRect->bottom = winRect->top;
546 if (winRect->left > winRect->right)
547 winRect->right = winRect->left;
549 return result;
553 /***********************************************************************
554 * NC_GetInsideRect
556 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
557 * but without the borders (if any).
558 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
560 void NC_GetInsideRect( HWND hwnd, RECT *rect )
562 WND * wndPtr = WIN_FindWndPtr( hwnd );
564 rect->top = rect->left = 0;
565 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
566 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
568 if (wndPtr->dwStyle & WS_ICONIC) goto END;
570 /* Remove frame from rectangle */
571 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
573 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
575 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
577 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
578 /* FIXME: this isn't in NC_AdjustRect? why not? */
579 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
580 InflateRect( rect, -1, 0 );
582 else if (HAS_THINFRAME( wndPtr->dwStyle ))
584 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
587 /* We have additional border information if the window
588 * is a child (but not an MDI child) */
589 if (TWEAK_WineLook != WIN31_LOOK)
591 if ( (wndPtr->dwStyle & WS_CHILD) &&
592 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
594 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
595 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
596 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
597 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
601 END:
602 WIN_ReleaseWndPtr(wndPtr);
603 return;
607 /***********************************************************************
608 * NC_DoNCHitTest
610 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
613 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
615 RECT rect;
617 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
619 GetWindowRect(wndPtr->hwndSelf, &rect );
620 if (!PtInRect( &rect, pt )) return HTNOWHERE;
622 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
624 /* Check borders */
625 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
627 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
628 if (!PtInRect( &rect, pt ))
630 /* Check top sizing border */
631 if (pt.y < rect.top)
633 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
634 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
635 return HTTOP;
637 /* Check bottom sizing border */
638 if (pt.y >= rect.bottom)
640 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
641 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
642 return HTBOTTOM;
644 /* Check left sizing border */
645 if (pt.x < rect.left)
647 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
648 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
649 return HTLEFT;
651 /* Check right sizing border */
652 if (pt.x >= rect.right)
654 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
655 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
656 return HTRIGHT;
660 else /* No thick frame */
662 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
663 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
664 else if (HAS_THINFRAME( wndPtr->dwStyle ))
665 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
666 if (!PtInRect( &rect, pt )) return HTBORDER;
669 /* Check caption */
671 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
673 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
674 if (!PtInRect( &rect, pt ))
676 /* Check system menu */
677 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
678 rect.left += GetSystemMetrics(SM_CXSIZE);
679 if (pt.x <= rect.left) return HTSYSMENU;
681 /* Check maximize box */
682 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
683 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
685 if (pt.x >= rect.right) return HTMAXBUTTON;
686 /* Check minimize box */
687 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
688 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
689 if (pt.x >= rect.right) return HTMINBUTTON;
690 return HTCAPTION;
694 /* Check client area */
696 ScreenToClient( wndPtr->hwndSelf, &pt );
697 GetClientRect( wndPtr->hwndSelf, &rect );
698 if (PtInRect( &rect, pt )) return HTCLIENT;
700 /* Check vertical scroll bar */
702 if (wndPtr->dwStyle & WS_VSCROLL)
704 rect.right += GetSystemMetrics(SM_CXVSCROLL);
705 if (PtInRect( &rect, pt )) return HTVSCROLL;
708 /* Check horizontal scroll bar */
710 if (wndPtr->dwStyle & WS_HSCROLL)
712 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
713 if (PtInRect( &rect, pt ))
715 /* Check size box */
716 if ((wndPtr->dwStyle & WS_VSCROLL) &&
717 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
718 return HTSIZE;
719 return HTHSCROLL;
723 /* Check menu bar */
725 if (HAS_MENU(wndPtr))
727 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
728 return HTMENU;
731 /* Has to return HTNOWHERE if nothing was found
732 Could happen when a window has a customized non client area */
733 return HTNOWHERE;
737 /***********************************************************************
738 * NC_DoNCHitTest95
740 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
742 * FIXME: Just a modified copy of the Win 3.1 version.
745 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
747 RECT rect;
749 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
751 GetWindowRect(wndPtr->hwndSelf, &rect );
752 if (!PtInRect( &rect, pt )) return HTNOWHERE;
754 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
756 /* Check borders */
757 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
759 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
760 if (!PtInRect( &rect, pt ))
762 /* Check top sizing border */
763 if (pt.y < rect.top)
765 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
766 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
767 return HTTOP;
769 /* Check bottom sizing border */
770 if (pt.y >= rect.bottom)
772 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
773 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
774 return HTBOTTOM;
776 /* Check left sizing border */
777 if (pt.x < rect.left)
779 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
780 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
781 return HTLEFT;
783 /* Check right sizing border */
784 if (pt.x >= rect.right)
786 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
787 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
788 return HTRIGHT;
792 else /* No thick frame */
794 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
795 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
796 else if (HAS_THINFRAME( wndPtr->dwStyle ))
797 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
798 if (!PtInRect( &rect, pt )) return HTBORDER;
801 /* Check caption */
803 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
805 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
806 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
807 else
808 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
809 if (!PtInRect( &rect, pt ))
811 /* Check system menu */
812 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
814 if (NC_IconForWindow(wndPtr->hwndSelf))
815 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
817 if (pt.x < rect.left) return HTSYSMENU;
819 /* Check close button */
820 if (wndPtr->dwStyle & WS_SYSMENU)
821 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
822 if (pt.x > rect.right) return HTCLOSE;
824 /* Check maximize box */
825 /* In win95 there is automatically a Maximize button when there is a minimize one*/
826 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
827 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
828 if (pt.x > rect.right) return HTMAXBUTTON;
830 /* Check minimize box */
831 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
832 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
833 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
835 if (pt.x > rect.right) return HTMINBUTTON;
836 return HTCAPTION;
840 /* Check client area */
842 ScreenToClient( wndPtr->hwndSelf, &pt );
843 GetClientRect( wndPtr->hwndSelf, &rect );
844 if (PtInRect( &rect, pt )) return HTCLIENT;
846 /* Check vertical scroll bar */
848 if (wndPtr->dwStyle & WS_VSCROLL)
850 rect.right += GetSystemMetrics(SM_CXVSCROLL);
851 if (PtInRect( &rect, pt )) return HTVSCROLL;
854 /* Check horizontal scroll bar */
856 if (wndPtr->dwStyle & WS_HSCROLL)
858 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
859 if (PtInRect( &rect, pt ))
861 /* Check size box */
862 if ((wndPtr->dwStyle & WS_VSCROLL) &&
863 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
864 return HTSIZE;
865 return HTHSCROLL;
869 /* Check menu bar */
871 if (HAS_MENU(wndPtr))
873 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
874 return HTMENU;
877 /* Has to return HTNOWHERE if nothing was found
878 Could happen when a window has a customized non client area */
879 return HTNOWHERE;
883 /***********************************************************************
884 * NC_HandleNCHitTest
886 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
888 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
890 LONG retvalue;
891 WND *wndPtr = WIN_FindWndPtr (hwnd);
893 if (!wndPtr)
894 return HTERROR;
896 if (TWEAK_WineLook == WIN31_LOOK)
897 retvalue = NC_DoNCHitTest (wndPtr, pt);
898 else
899 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
900 WIN_ReleaseWndPtr(wndPtr);
901 return retvalue;
905 /***********************************************************************
906 * NC_DrawSysButton
908 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
910 RECT rect;
911 HDC hdcMem;
912 HBITMAP hbitmap;
914 NC_GetInsideRect( hwnd, &rect );
915 hdcMem = CreateCompatibleDC( hdc );
916 hbitmap = SelectObject( hdcMem, hbitmapClose );
917 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
918 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
919 down ? NOTSRCCOPY : SRCCOPY );
920 SelectObject( hdcMem, hbitmap );
921 DeleteDC( hdcMem );
925 /***********************************************************************
926 * NC_DrawMaxButton
928 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
930 RECT rect;
931 HDC hdcMem;
933 NC_GetInsideRect( hwnd, &rect );
934 hdcMem = CreateCompatibleDC( hdc );
935 SelectObject( hdcMem, (IsZoomed(hwnd)
936 ? (down ? hbitmapRestoreD : hbitmapRestore)
937 : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
938 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
939 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
940 SRCCOPY );
941 DeleteDC( hdcMem );
946 /***********************************************************************
947 * NC_DrawMinButton
949 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
951 RECT rect;
952 HDC hdcMem;
954 NC_GetInsideRect( hwnd, &rect );
955 hdcMem = CreateCompatibleDC( hdc );
956 SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
957 if (GetWindowLongA(hwnd,GWL_STYLE) & WS_MAXIMIZEBOX)
958 rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
959 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
960 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
961 SRCCOPY );
962 DeleteDC( hdcMem );
966 /******************************************************************************
968 * void NC_DrawSysButton95(
969 * HWND hwnd,
970 * HDC hdc,
971 * BOOL down )
973 * Draws the Win95 system icon.
975 * Revision history
976 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
977 * Original implementation from NC_DrawSysButton source.
978 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
979 * Fixed most bugs.
981 *****************************************************************************/
983 BOOL
984 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
986 HICON hIcon = NC_IconForWindow( hwnd );
988 if (hIcon)
990 RECT rect;
991 NC_GetInsideRect( hwnd, &rect );
992 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
993 GetSystemMetrics(SM_CXSMICON),
994 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
996 return (hIcon != 0);
1000 /******************************************************************************
1002 * void NC_DrawCloseButton95(
1003 * HWND hwnd,
1004 * HDC hdc,
1005 * BOOL down,
1006 * BOOL bGrayed )
1008 * Draws the Win95 close button.
1010 * If bGrayed is true, then draw a disabled Close button
1012 * Revision history
1013 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1014 * Original implementation from NC_DrawSysButton95 source.
1016 *****************************************************************************/
1018 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
1020 RECT rect;
1022 NC_GetInsideRect( hwnd, &rect );
1024 /* A tool window has a smaller Close button */
1025 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
1027 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
1028 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
1029 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1031 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1032 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1033 rect.bottom = rect.top + iBmpHeight;
1034 rect.right = rect.left + iBmpWidth;
1036 else
1038 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
1039 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1040 rect.top += 2;
1041 rect.right -= 2;
1043 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1044 (DFCS_CAPTIONCLOSE |
1045 (down ? DFCS_PUSHED : 0) |
1046 (bGrayed ? DFCS_INACTIVE : 0)) );
1049 /******************************************************************************
1050 * NC_DrawMaxButton95
1052 * Draws the maximize button for Win95 style windows.
1053 * If bGrayed is true, then draw a disabled Maximize button
1055 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1057 RECT rect;
1058 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1060 NC_GetInsideRect( hwnd, &rect );
1061 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1062 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1063 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1064 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1065 rect.top += 2;
1066 rect.right -= 2;
1067 if (down) flags |= DFCS_PUSHED;
1068 if (bGrayed) flags |= DFCS_INACTIVE;
1069 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1072 /******************************************************************************
1073 * NC_DrawMinButton95
1075 * Draws the minimize button for Win95 style windows.
1076 * If bGrayed is true, then draw a disabled Minimize button
1078 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1080 RECT rect;
1081 UINT flags = DFCS_CAPTIONMIN;
1082 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1084 NC_GetInsideRect( hwnd, &rect );
1085 if (style & WS_SYSMENU)
1086 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1087 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1088 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1089 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1090 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1091 rect.top += 2;
1092 rect.right -= 2;
1093 if (down) flags |= DFCS_PUSHED;
1094 if (bGrayed) flags |= DFCS_INACTIVE;
1095 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1098 /***********************************************************************
1099 * NC_DrawFrame
1101 * Draw a window frame inside the given rectangle, and update the rectangle.
1102 * The correct pen for the frame must be selected in the DC.
1104 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1105 BOOL active )
1107 INT width, height;
1109 if (TWEAK_WineLook != WIN31_LOOK)
1110 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1112 if (dlgFrame)
1114 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1115 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1116 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1117 COLOR_INACTIVECAPTION) );
1119 else
1121 width = GetSystemMetrics(SM_CXFRAME) - 2;
1122 height = GetSystemMetrics(SM_CYFRAME) - 2;
1123 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1124 COLOR_INACTIVEBORDER) );
1127 /* Draw frame */
1128 PatBlt( hdc, rect->left, rect->top,
1129 rect->right - rect->left, height, PATCOPY );
1130 PatBlt( hdc, rect->left, rect->top,
1131 width, rect->bottom - rect->top, PATCOPY );
1132 PatBlt( hdc, rect->left, rect->bottom - 1,
1133 rect->right - rect->left, -height, PATCOPY );
1134 PatBlt( hdc, rect->right - 1, rect->top,
1135 -width, rect->bottom - rect->top, PATCOPY );
1137 if (dlgFrame)
1139 InflateRect( rect, -width, -height );
1141 else
1143 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1144 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1146 /* Draw inner rectangle */
1148 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1149 Rectangle( hdc, rect->left + width, rect->top + height,
1150 rect->right - width , rect->bottom - height );
1152 /* Draw the decorations */
1154 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1155 LineTo( hdc, rect->left + width, rect->top + decYOff );
1156 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1157 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1158 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1159 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1160 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1161 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1163 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1164 LineTo( hdc, rect->left + decXOff, rect->top + height);
1165 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1166 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1167 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1168 LineTo( hdc, rect->right - decXOff, rect->top + height );
1169 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1170 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1172 InflateRect( rect, -width - 1, -height - 1 );
1177 /******************************************************************************
1179 * void NC_DrawFrame95(
1180 * HDC hdc,
1181 * RECT *rect,
1182 * BOOL active,
1183 * DWORD style,
1184 * DWORD exStyle )
1186 * Draw a window frame inside the given rectangle, and update the rectangle.
1188 * Bugs
1189 * Many. First, just what IS a frame in Win95? Note that the 3D look
1190 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1191 * edge. The inner rectangle just inside the frame is handled by the
1192 * Caption code.
1194 * In short, for most people, this function should be a nop (unless
1195 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1196 * them lately, but just to get this code right). Even so, it doesn't
1197 * appear to be so. It's being worked on...
1199 * Revision history
1200 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1201 * Original implementation (based on NC_DrawFrame)
1202 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1203 * Some minor fixes.
1204 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1205 * Fixed a fix or something.
1207 *****************************************************************************/
1209 static void NC_DrawFrame95(
1210 HDC hdc,
1211 RECT *rect,
1212 BOOL active,
1213 DWORD style,
1214 DWORD exStyle)
1216 INT width, height;
1218 /* Firstly the "thick" frame */
1219 if (style & WS_THICKFRAME)
1221 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1222 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1224 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1225 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 InflateRect( rect, -width, -height );
1239 /* Now the other bit of the frame */
1240 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1241 (exStyle & WS_EX_DLGMODALFRAME))
1243 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1244 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1245 /* This should give a value of 1 that should also work for a border */
1247 SelectObject( hdc, GetSysColorBrush(
1248 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1249 COLOR_3DFACE :
1250 (exStyle & WS_EX_STATICEDGE) ?
1251 COLOR_WINDOWFRAME :
1252 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1253 COLOR_3DFACE :
1254 /* else */
1255 COLOR_WINDOWFRAME));
1257 /* Draw frame */
1258 PatBlt( hdc, rect->left, rect->top,
1259 rect->right - rect->left, height, PATCOPY );
1260 PatBlt( hdc, rect->left, rect->top,
1261 width, rect->bottom - rect->top, PATCOPY );
1262 PatBlt( hdc, rect->left, rect->bottom - 1,
1263 rect->right - rect->left, -height, PATCOPY );
1264 PatBlt( hdc, rect->right - 1, rect->top,
1265 -width, rect->bottom - rect->top, PATCOPY );
1267 InflateRect( rect, -width, -height );
1272 /***********************************************************************
1273 * NC_DrawCaption
1275 * Draw the window caption.
1276 * The correct pen for the window frame must be selected in the DC.
1278 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1279 DWORD style, BOOL active )
1281 RECT r = *rect;
1282 char buffer[256];
1284 if (!hbitmapClose)
1286 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) ))) return;
1287 hbitmapMinimize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
1288 hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
1289 hbitmapMaximize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
1290 hbitmapMaximizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOMD) );
1291 hbitmapRestore = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORE) );
1292 hbitmapRestoreD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
1295 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1297 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1298 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1299 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1300 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1301 r.left++;
1302 r.right--;
1303 SelectObject( hdc, hbrushOld );
1305 MoveToEx( hdc, r.left, r.bottom, NULL );
1306 LineTo( hdc, r.right, r.bottom );
1308 if (style & WS_SYSMENU)
1310 NC_DrawSysButton( hwnd, hdc, FALSE );
1311 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1312 MoveToEx( hdc, r.left - 1, r.top, NULL );
1313 LineTo( hdc, r.left - 1, r.bottom );
1315 if (style & WS_MAXIMIZEBOX)
1317 NC_DrawMaxButton( hwnd, hdc, FALSE );
1318 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1320 if (style & WS_MINIMIZEBOX)
1322 NC_DrawMinButton( hwnd, hdc, FALSE );
1323 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1326 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1327 COLOR_INACTIVECAPTION) );
1329 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1331 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1332 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1333 SetBkMode( hdc, TRANSPARENT );
1334 DrawTextA( hdc, buffer, -1, &r,
1335 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1340 /******************************************************************************
1342 * NC_DrawCaption95(
1343 * HDC hdc,
1344 * RECT *rect,
1345 * HWND hwnd,
1346 * DWORD style,
1347 * BOOL active )
1349 * Draw the window caption for Win95 style windows.
1350 * The correct pen for the window frame must be selected in the DC.
1352 * Bugs
1353 * Hey, a function that finally works! Well, almost.
1354 * It's being worked on.
1356 * Revision history
1357 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1358 * Original implementation.
1359 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1360 * Some minor fixes.
1362 *****************************************************************************/
1364 static void NC_DrawCaption95(
1365 HDC hdc,
1366 RECT *rect,
1367 HWND hwnd,
1368 DWORD style,
1369 DWORD exStyle,
1370 BOOL active )
1372 RECT r = *rect;
1373 char buffer[256];
1374 HPEN hPrevPen;
1375 HMENU hSysMenu;
1377 hPrevPen = SelectObject( hdc, GetSysColorPen(
1378 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1379 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1380 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1381 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1382 LineTo( hdc, r.right, r.bottom - 1 );
1383 SelectObject( hdc, hPrevPen );
1384 r.bottom--;
1386 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1387 COLOR_INACTIVECAPTION) );
1389 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1390 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1391 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1394 if (style & WS_SYSMENU)
1396 UINT state;
1398 /* Go get the sysmenu */
1399 hSysMenu = GetSystemMenu(hwnd, FALSE);
1400 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1402 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1403 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1404 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1405 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1407 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1409 /* In win95 the two buttons are always there */
1410 /* But if the menu item is not in the menu they're disabled*/
1412 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1413 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1415 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1416 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1420 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1421 NONCLIENTMETRICSA nclm;
1422 HFONT hFont, hOldFont;
1423 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1424 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1425 if (exStyle & WS_EX_TOOLWINDOW)
1426 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1427 else
1428 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1429 hOldFont = SelectObject (hdc, hFont);
1430 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1431 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1432 SetBkMode( hdc, TRANSPARENT );
1433 r.left += 2;
1434 DrawTextA( hdc, buffer, -1, &r,
1435 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1436 DeleteObject (SelectObject (hdc, hOldFont));
1442 /***********************************************************************
1443 * NC_DoNCPaint
1445 * Paint the non-client area. clip is currently unused.
1447 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1449 HDC hdc;
1450 RECT rect;
1451 BOOL active;
1452 HWND hwnd = wndPtr->hwndSelf;
1454 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1455 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1457 active = wndPtr->flags & WIN_NCACTIVATED;
1459 TRACE("%04x %d\n", hwnd, active );
1461 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1462 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1464 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1465 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1466 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1467 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1468 == NULLREGION)
1470 ReleaseDC( hwnd, hdc );
1471 return;
1474 rect.top = rect.left = 0;
1475 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1476 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1478 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1480 if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1482 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1483 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1484 InflateRect( &rect, -1, -1 );
1487 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1488 NC_DrawFrame(hdc, &rect, FALSE, active );
1489 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1490 NC_DrawFrame( hdc, &rect, TRUE, active );
1492 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1494 RECT r = rect;
1495 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1496 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1497 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1500 if (HAS_MENU(wndPtr))
1502 RECT r = rect;
1503 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1504 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1507 /* Draw the scroll-bars */
1509 if (wndPtr->dwStyle & WS_VSCROLL)
1510 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1511 if (wndPtr->dwStyle & WS_HSCROLL)
1512 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1514 /* Draw the "size-box" */
1516 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1518 RECT r = rect;
1519 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1520 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1521 if(wndPtr->dwStyle & WS_BORDER) {
1522 r.left++;
1523 r.top++;
1525 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1528 ReleaseDC( hwnd, hdc );
1532 /******************************************************************************
1534 * void NC_DoNCPaint95(
1535 * WND *wndPtr,
1536 * HRGN clip,
1537 * BOOL suppress_menupaint )
1539 * Paint the non-client area for Win95 windows. The clip region is
1540 * currently ignored.
1542 * Bugs
1543 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1544 * misc/tweak.c controls/menu.c # :-)
1546 * Revision history
1547 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1548 * Original implementation
1549 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1550 * Fixed some bugs.
1551 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1552 * Streamlined window style checks.
1554 *****************************************************************************/
1556 static void NC_DoNCPaint95(
1557 WND *wndPtr,
1558 HRGN clip,
1559 BOOL suppress_menupaint )
1561 HDC hdc;
1562 RECT rfuzz, rect, rectClip;
1563 BOOL active;
1564 HWND hwnd = wndPtr->hwndSelf;
1566 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1567 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1569 active = wndPtr->flags & WIN_NCACTIVATED;
1571 TRACE("%04x %d\n", hwnd, active );
1573 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1574 the call to GetDCEx implying that it is allowed not to use it either.
1575 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1576 will cause clipRgn to be deleted after ReleaseDC().
1577 Now, how is the "system" supposed to tell what happened?
1580 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1581 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1584 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1585 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1586 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1587 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1588 == NULLREGION)
1590 ReleaseDC( hwnd, hdc );
1591 return;
1594 rect.top = rect.left = 0;
1595 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1596 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1598 if( clip > 1 )
1599 GetRgnBox( clip, &rectClip );
1600 else
1602 clip = 0;
1603 rectClip = rect;
1606 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1608 if (HAS_STATICOUTERFRAME(wndPtr->dwStyle, wndPtr->dwExStyle)) {
1609 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1611 else if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1612 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1615 NC_DrawFrame95(hdc, &rect, active, wndPtr->dwStyle, wndPtr->dwExStyle );
1617 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1619 RECT r = rect;
1620 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1621 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1622 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1624 else {
1625 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1626 rect.top += GetSystemMetrics(SM_CYCAPTION);
1628 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1629 NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1630 wndPtr->dwExStyle, active);
1633 if (HAS_MENU(wndPtr))
1635 RECT r = rect;
1636 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1638 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1639 r.left, r.top, r.right, r.bottom);
1641 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1644 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1645 rect.left, rect.top, rect.right, rect.bottom );
1647 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1648 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1650 /* Draw the scroll-bars */
1652 if (wndPtr->dwStyle & WS_VSCROLL)
1653 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1654 if (wndPtr->dwStyle & WS_HSCROLL)
1655 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1657 /* Draw the "size-box" */
1658 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1660 RECT r = rect;
1661 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1662 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1663 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1666 ReleaseDC( hwnd, hdc );
1672 /***********************************************************************
1673 * NC_HandleNCPaint
1675 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1677 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1679 WND* wndPtr = WIN_FindWndPtr( hwnd );
1681 if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1683 if( wndPtr->dwStyle & WS_MINIMIZE )
1684 WINPOS_RedrawIconTitle( hwnd );
1685 else if (TWEAK_WineLook == WIN31_LOOK)
1686 NC_DoNCPaint( wndPtr, clip, FALSE );
1687 else
1688 NC_DoNCPaint95( wndPtr, clip, FALSE );
1690 WIN_ReleaseWndPtr(wndPtr);
1691 return 0;
1695 /***********************************************************************
1696 * NC_HandleNCActivate
1698 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1700 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1702 WND* wndPtr = WIN_FindWndPtr( hwnd );
1704 /* Lotus Notes draws menu descriptions in the caption of its main
1705 * window. When it wants to restore original "system" view, it just
1706 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1707 * attempt to minimize redrawings lead to a not restored caption.
1709 if (wndPtr)
1711 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1712 else wndPtr->flags &= ~WIN_NCACTIVATED;
1714 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1715 else if (TWEAK_WineLook == WIN31_LOOK)
1716 NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1717 else
1718 NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1719 WIN_ReleaseWndPtr(wndPtr);
1721 return TRUE;
1725 /***********************************************************************
1726 * NC_HandleSetCursor
1728 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1730 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1732 if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1733 return 0; /* Don't set the cursor for child windows */
1735 switch(LOWORD(lParam))
1737 case HTERROR:
1739 WORD msg = HIWORD( lParam );
1740 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1741 (msg == WM_RBUTTONDOWN))
1742 MessageBeep(0);
1744 break;
1746 case HTCLIENT:
1748 HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1749 if(hCursor) {
1750 SetCursor(hCursor);
1751 return TRUE;
1753 return FALSE;
1756 case HTLEFT:
1757 case HTRIGHT:
1758 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1760 case HTTOP:
1761 case HTBOTTOM:
1762 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1764 case HTTOPLEFT:
1765 case HTBOTTOMRIGHT:
1766 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1768 case HTTOPRIGHT:
1769 case HTBOTTOMLEFT:
1770 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1773 /* Default cursor: arrow */
1774 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1777 /***********************************************************************
1778 * NC_GetSysPopupPos
1780 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1782 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1783 else
1785 WND *wndPtr = WIN_FindWndPtr( hwnd );
1786 if (!wndPtr) return;
1788 NC_GetInsideRect( hwnd, rect );
1789 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1790 if (wndPtr->dwStyle & WS_CHILD)
1791 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1792 if (TWEAK_WineLook == WIN31_LOOK) {
1793 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1794 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1796 else {
1797 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1798 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1800 WIN_ReleaseWndPtr( wndPtr );
1804 /***********************************************************************
1805 * NC_TrackMinMaxBox95
1807 * Track a mouse button press on the minimize or maximize box.
1809 * The big difference between 3.1 and 95 is the disabled button state.
1810 * In win95 the system button can be disabled, so it can ignore the mouse
1811 * event.
1814 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1816 MSG msg;
1817 HDC hdc = GetWindowDC( hwnd );
1818 BOOL pressed = TRUE;
1819 UINT state;
1820 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1821 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1823 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
1825 if (wParam == HTMINBUTTON)
1827 /* If the style is not present, do nothing */
1828 if (!(wndStyle & WS_MINIMIZEBOX))
1829 return;
1831 /* Check if the sysmenu item for minimize is there */
1832 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1834 paintButton = &NC_DrawMinButton95;
1836 else
1838 /* If the style is not present, do nothing */
1839 if (!(wndStyle & WS_MAXIMIZEBOX))
1840 return;
1842 /* Check if the sysmenu item for maximize is there */
1843 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1845 paintButton = &NC_DrawMaxButton95;
1848 SetCapture( hwnd );
1850 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1852 while(1)
1854 BOOL oldstate = pressed;
1856 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1857 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1859 if(msg.message == WM_LBUTTONUP)
1860 break;
1862 if(msg.message != WM_MOUSEMOVE)
1863 continue;
1865 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1866 if (pressed != oldstate)
1867 (*paintButton)( hwnd, hdc, pressed, FALSE);
1870 if(pressed)
1871 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1873 ReleaseCapture();
1874 ReleaseDC( hwnd, hdc );
1876 /* If the item minimize or maximize of the sysmenu are not there */
1877 /* or if the style is not present, do nothing */
1878 if ((!pressed) || (state == 0xFFFFFFFF))
1879 return;
1881 if (wParam == HTMINBUTTON)
1882 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1883 else
1884 SendMessageA( hwnd, WM_SYSCOMMAND,
1885 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1888 /***********************************************************************
1889 * NC_TrackMinMaxBox
1891 * Track a mouse button press on the minimize or maximize box.
1893 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1895 MSG msg;
1896 HDC hdc = GetWindowDC( hwnd );
1897 BOOL pressed = TRUE;
1898 void (*paintButton)(HWND, HDC16, BOOL);
1900 SetCapture( hwnd );
1902 if (wParam == HTMINBUTTON)
1903 paintButton = &NC_DrawMinButton;
1904 else
1905 paintButton = &NC_DrawMaxButton;
1907 (*paintButton)( hwnd, hdc, TRUE);
1909 while(1)
1911 BOOL oldstate = pressed;
1913 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1914 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1916 if(msg.message == WM_LBUTTONUP)
1917 break;
1919 if(msg.message != WM_MOUSEMOVE)
1920 continue;
1922 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1923 if (pressed != oldstate)
1924 (*paintButton)( hwnd, hdc, pressed);
1927 if(pressed)
1928 (*paintButton)( hwnd, hdc, FALSE);
1930 ReleaseCapture();
1931 ReleaseDC( hwnd, hdc );
1933 if (!pressed) return;
1935 if (wParam == HTMINBUTTON)
1936 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1937 else
1938 SendMessageA( hwnd, WM_SYSCOMMAND,
1939 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1943 /***********************************************************************
1944 * NC_TrackCloseButton95
1946 * Track a mouse button press on the Win95 close button.
1948 static void
1949 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1951 MSG msg;
1952 HDC hdc;
1953 BOOL pressed = TRUE;
1954 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1955 UINT state;
1957 if(hSysMenu == 0)
1958 return;
1960 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1962 /* If the item close of the sysmenu is disabled or not there do nothing */
1963 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1964 return;
1966 hdc = GetWindowDC( hwnd );
1968 SetCapture( hwnd );
1970 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1972 while(1)
1974 BOOL oldstate = pressed;
1976 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1977 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1979 if(msg.message == WM_LBUTTONUP)
1980 break;
1982 if(msg.message != WM_MOUSEMOVE)
1983 continue;
1985 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1986 if (pressed != oldstate)
1987 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1990 if(pressed)
1991 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1993 ReleaseCapture();
1994 ReleaseDC( hwnd, hdc );
1995 if (!pressed) return;
1997 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
2001 /***********************************************************************
2002 * NC_TrackScrollBar
2004 * Track a mouse button press on the horizontal or vertical scroll-bar.
2006 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2008 MSG msg;
2009 INT scrollbar;
2010 WND *wndPtr = WIN_FindWndPtr( hwnd );
2012 if ((wParam & 0xfff0) == SC_HSCROLL)
2014 if ((wParam & 0x0f) != HTHSCROLL) goto END;
2015 scrollbar = SB_HORZ;
2017 else /* SC_VSCROLL */
2019 if ((wParam & 0x0f) != HTVSCROLL) goto END;
2020 scrollbar = SB_VERT;
2023 pt.x -= wndPtr->rectWindow.left;
2024 pt.y -= wndPtr->rectWindow.top;
2025 SetCapture( hwnd );
2026 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
2030 if (!GetMessageW( &msg, 0, 0, 0 )) break;
2031 if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue;
2032 switch(msg.message)
2034 case WM_LBUTTONUP:
2035 case WM_MOUSEMOVE:
2036 case WM_SYSTIMER:
2037 pt.x = LOWORD(msg.lParam) + wndPtr->rectClient.left - wndPtr->rectWindow.left;
2038 pt.y = HIWORD(msg.lParam) + wndPtr->rectClient.top - wndPtr->rectWindow.top;
2039 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
2040 break;
2041 default:
2042 TranslateMessage( &msg );
2043 DispatchMessageW( &msg );
2044 break;
2046 if (!IsWindow( hwnd ))
2048 ReleaseCapture();
2049 break;
2051 } while (msg.message != WM_LBUTTONUP);
2052 END:
2053 WIN_ReleaseWndPtr(wndPtr);
2056 /***********************************************************************
2057 * NC_HandleNCLButtonDown
2059 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2061 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
2063 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
2065 switch(wParam) /* Hit test */
2067 case HTCAPTION:
2069 HWND top = GetAncestor( hwnd, GA_ROOT );
2071 if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
2072 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2073 break;
2076 case HTSYSMENU:
2077 if( style & WS_SYSMENU )
2079 if( !(style & WS_MINIMIZE) )
2081 HDC hDC = GetWindowDC(hwnd);
2082 if (TWEAK_WineLook == WIN31_LOOK)
2083 NC_DrawSysButton( hwnd, hDC, TRUE );
2084 else
2085 NC_DrawSysButton95( hwnd, hDC, TRUE );
2086 ReleaseDC( hwnd, hDC );
2088 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2090 break;
2092 case HTMENU:
2093 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2094 break;
2096 case HTHSCROLL:
2097 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2098 break;
2100 case HTVSCROLL:
2101 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2102 break;
2104 case HTMINBUTTON:
2105 case HTMAXBUTTON:
2106 if (TWEAK_WineLook == WIN31_LOOK)
2107 NC_TrackMinMaxBox( hwnd, wParam );
2108 else
2109 NC_TrackMinMaxBox95( hwnd, wParam );
2110 break;
2112 case HTCLOSE:
2113 if (TWEAK_WineLook >= WIN95_LOOK)
2114 NC_TrackCloseButton95 (hwnd, wParam);
2115 break;
2117 case HTLEFT:
2118 case HTRIGHT:
2119 case HTTOP:
2120 case HTTOPLEFT:
2121 case HTTOPRIGHT:
2122 case HTBOTTOM:
2123 case HTBOTTOMLEFT:
2124 case HTBOTTOMRIGHT:
2125 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2126 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2127 break;
2129 case HTBORDER:
2130 break;
2132 return 0;
2136 /***********************************************************************
2137 * NC_HandleNCLButtonDblClk
2139 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2141 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2144 * if this is an icon, send a restore since we are handling
2145 * a double click
2147 if (IsIconic(hwnd))
2149 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2150 return 0;
2153 switch(wParam) /* Hit test */
2155 case HTCAPTION:
2156 /* stop processing if WS_MAXIMIZEBOX is missing */
2157 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2158 SendMessageW( hwnd, WM_SYSCOMMAND,
2159 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2160 break;
2162 case HTSYSMENU:
2163 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2164 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2165 break;
2167 case HTHSCROLL:
2168 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2169 break;
2171 case HTVSCROLL:
2172 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2173 break;
2175 return 0;
2179 /***********************************************************************
2180 * NC_HandleSysCommand
2182 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2184 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
2186 WND *wndPtr = WIN_FindWndPtr( hwnd );
2187 UINT16 uCommand = wParam & 0xFFF0;
2189 TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
2191 if (uCommand != SC_KEYMENU)
2193 HWND parent = GetAncestor( hwnd, GA_PARENT );
2194 if (parent != GetDesktopWindow()) ScreenToClient( parent, &pt );
2197 switch (uCommand)
2199 case SC_SIZE:
2200 case SC_MOVE:
2201 if (USER_Driver.pSysCommandSizeMove)
2202 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2203 break;
2205 case SC_MINIMIZE:
2206 if (hwnd == GetForegroundWindow())
2207 ShowOwnedPopups(hwnd,FALSE);
2208 ShowWindow( hwnd, SW_MINIMIZE );
2209 break;
2211 case SC_MAXIMIZE:
2212 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2213 ShowOwnedPopups(hwnd,TRUE);
2214 ShowWindow( hwnd, SW_MAXIMIZE );
2215 break;
2217 case SC_RESTORE:
2218 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2219 ShowOwnedPopups(hwnd,TRUE);
2220 ShowWindow( hwnd, SW_RESTORE );
2221 break;
2223 case SC_CLOSE:
2224 WIN_ReleaseWndPtr(wndPtr);
2225 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2227 case SC_VSCROLL:
2228 case SC_HSCROLL:
2229 NC_TrackScrollBar( hwnd, wParam, pt );
2230 break;
2232 case SC_MOUSEMENU:
2233 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2234 break;
2236 case SC_KEYMENU:
2237 MENU_TrackKbdMenuBar( hwnd, wParam , pt.x );
2238 break;
2240 case SC_TASKLIST:
2241 WinExec( "taskman.exe", SW_SHOWNORMAL );
2242 break;
2244 case SC_SCREENSAVE:
2245 if (wParam == SC_ABOUTWINE)
2247 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2248 if (hmodule)
2250 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2251 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2252 FreeLibrary( hmodule );
2255 else
2256 if (wParam == SC_PUTMARK)
2257 TRACE_(shell)("Mark requested by user\n");
2258 break;
2260 case SC_HOTKEY:
2261 case SC_ARRANGE:
2262 case SC_NEXTWINDOW:
2263 case SC_PREVWINDOW:
2264 FIXME("unimplemented!\n");
2265 break;
2267 WIN_ReleaseWndPtr(wndPtr);
2268 return 0;
2271 /*************************************************************
2272 * NC_DrawGrayButton
2274 * Stub for the grayed button of the caption
2276 *************************************************************/
2278 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2280 HBITMAP hMaskBmp;
2281 HDC hdcMask = CreateCompatibleDC (0);
2282 HBRUSH hOldBrush;
2284 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2286 if(hMaskBmp == 0)
2287 return FALSE;
2289 SelectObject (hdcMask, hMaskBmp);
2291 /* Draw the grayed bitmap using the mask */
2292 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2293 BitBlt (hdc, x, y, 12, 10,
2294 hdcMask, 0, 0, 0xB8074A);
2296 /* Clean up */
2297 SelectObject (hdc, hOldBrush);
2298 DeleteObject(hMaskBmp);
2299 DeleteDC (hdcMask);
2301 return TRUE;