A couple of optimizations.
[wine/multimedia.git] / windows / nonclient.c
blob66bb6eb74396bb3250c2db9d81d22ed64f3bcb0a
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 (USER32.@) 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 BOOL WINAPI
254 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
256 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
260 /***********************************************************************
261 * DrawCaptionTempA (USER32.@)
263 * PARAMS
265 * RETURNS
266 * Success:
267 * Failure:
270 BOOL WINAPI
271 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
272 HICON hIcon, LPCSTR str, UINT uFlags)
274 RECT rc = *rect;
276 TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
277 hwnd, hdc, rect, hFont, hIcon, str, uFlags);
279 /* drawing background */
280 if (uFlags & DC_INBUTTON) {
281 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
283 if (uFlags & DC_ACTIVE) {
284 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
285 PatBlt (hdc, rc.left, rc.top,
286 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
287 SelectObject (hdc, hbr);
290 else {
291 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
292 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
296 /* drawing icon */
297 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
298 POINT pt;
300 pt.x = rc.left + 2;
301 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
303 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
304 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
305 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
306 rc.left += (rc.bottom - rc.top);
309 /* drawing text */
310 if (uFlags & DC_TEXT) {
311 HFONT hOldFont;
313 if (uFlags & DC_INBUTTON)
314 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
315 else if (uFlags & DC_ACTIVE)
316 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
317 else
318 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
320 SetBkMode (hdc, TRANSPARENT);
322 if (hFont)
323 hOldFont = SelectObject (hdc, hFont);
324 else {
325 NONCLIENTMETRICSA nclm;
326 HFONT hNewFont;
327 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
328 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
329 hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
330 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
331 hOldFont = SelectObject (hdc, hNewFont);
334 if (str)
335 DrawTextA (hdc, str, -1, &rc,
336 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
337 else {
338 CHAR szText[128];
339 INT nLen;
340 nLen = GetWindowTextA (hwnd, szText, 128);
341 DrawTextA (hdc, szText, nLen, &rc,
342 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
345 if (hFont)
346 SelectObject (hdc, hOldFont);
347 else
348 DeleteObject (SelectObject (hdc, hOldFont));
351 /* drawing focus ??? */
352 if (uFlags & 0x2000)
353 FIXME("undocumented flag (0x2000)!\n");
355 return 0;
359 /***********************************************************************
360 * DrawCaptionTempW (USER32.@)
362 * PARAMS
364 * RETURNS
365 * Success:
366 * Failure:
369 BOOL WINAPI
370 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
371 HICON hIcon, LPCWSTR str, UINT uFlags)
373 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
374 BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
375 HeapFree (GetProcessHeap (), 0, p);
376 return res;
380 /***********************************************************************
381 * AdjustWindowRect (USER.102)
383 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
385 return AdjustWindowRectEx16( rect, style, menu, 0 );
389 /***********************************************************************
390 * AdjustWindowRect (USER32.@)
392 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
394 return AdjustWindowRectEx( rect, style, menu, 0 );
398 /***********************************************************************
399 * AdjustWindowRectEx (USER.454)
401 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
402 BOOL16 menu, DWORD exStyle )
404 RECT rect32;
405 BOOL ret;
407 CONV_RECT16TO32( rect, &rect32 );
408 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
409 CONV_RECT32TO16( &rect32, rect );
410 return ret;
414 /***********************************************************************
415 * AdjustWindowRectEx (USER32.@)
417 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
419 /* Correct the window style */
421 if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
422 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
423 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
424 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
425 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
427 TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
428 rect->left, rect->top, rect->right, rect->bottom,
429 style, menu, exStyle );
431 if (TWEAK_WineLook == WIN31_LOOK)
432 NC_AdjustRect( rect, style, menu, exStyle );
433 else
435 NC_AdjustRectOuter95( rect, style, menu, exStyle );
436 NC_AdjustRectInner95( rect, style, exStyle );
438 return TRUE;
442 /***********************************************************************
443 * NC_HandleNCCalcSize
445 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
447 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
449 RECT tmpRect = { 0, 0, 0, 0 };
450 LONG result = 0;
451 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
452 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
453 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
455 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
456 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
458 if (!IsIconic(hwnd))
460 if (TWEAK_WineLook == WIN31_LOOK)
461 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
462 else
463 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
465 winRect->left -= tmpRect.left;
466 winRect->top -= tmpRect.top;
467 winRect->right -= tmpRect.right;
468 winRect->bottom -= tmpRect.bottom;
470 if (!(style & WS_CHILD) && GetMenu(hwnd))
472 TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
473 "at (%d, %d).\n", hwnd,
474 winRect->right - winRect->left,
475 -tmpRect.left, -tmpRect.top );
477 winRect->top +=
478 MENU_GetMenuBarHeight( hwnd,
479 winRect->right - winRect->left,
480 -tmpRect.left, -tmpRect.top ) + 1;
483 if (TWEAK_WineLook > WIN31_LOOK) {
484 SetRect(&tmpRect, 0, 0, 0, 0);
485 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
486 winRect->left -= tmpRect.left;
487 winRect->top -= tmpRect.top;
488 winRect->right -= tmpRect.right;
489 winRect->bottom -= tmpRect.bottom;
492 if (winRect->top > winRect->bottom)
493 winRect->bottom = winRect->top;
495 if (winRect->left > winRect->right)
496 winRect->right = winRect->left;
498 return result;
502 /***********************************************************************
503 * NC_GetInsideRect
505 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
506 * but without the borders (if any).
507 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
509 void NC_GetInsideRect( HWND hwnd, RECT *rect )
511 WND * wndPtr = WIN_FindWndPtr( hwnd );
513 rect->top = rect->left = 0;
514 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
515 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
517 if (wndPtr->dwStyle & WS_ICONIC) goto END;
519 /* Remove frame from rectangle */
520 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
522 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
524 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
526 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
527 /* FIXME: this isn't in NC_AdjustRect? why not? */
528 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
529 InflateRect( rect, -1, 0 );
531 else if (HAS_THINFRAME( wndPtr->dwStyle ))
533 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
536 /* We have additional border information if the window
537 * is a child (but not an MDI child) */
538 if (TWEAK_WineLook != WIN31_LOOK)
540 if ( (wndPtr->dwStyle & WS_CHILD) &&
541 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
543 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
544 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
545 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
546 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
550 END:
551 WIN_ReleaseWndPtr(wndPtr);
552 return;
556 /***********************************************************************
557 * NC_DoNCHitTest
559 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
562 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
564 RECT rect;
566 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
568 GetWindowRect(wndPtr->hwndSelf, &rect );
569 if (!PtInRect( &rect, pt )) return HTNOWHERE;
571 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
573 /* Check borders */
574 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
576 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
577 if (!PtInRect( &rect, pt ))
579 /* Check top sizing border */
580 if (pt.y < rect.top)
582 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
583 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
584 return HTTOP;
586 /* Check bottom sizing border */
587 if (pt.y >= rect.bottom)
589 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
590 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
591 return HTBOTTOM;
593 /* Check left sizing border */
594 if (pt.x < rect.left)
596 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
597 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
598 return HTLEFT;
600 /* Check right sizing border */
601 if (pt.x >= rect.right)
603 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
604 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
605 return HTRIGHT;
609 else /* No thick frame */
611 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
612 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
613 else if (HAS_THINFRAME( wndPtr->dwStyle ))
614 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
615 if (!PtInRect( &rect, pt )) return HTBORDER;
618 /* Check caption */
620 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
622 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
623 if (!PtInRect( &rect, pt ))
625 /* Check system menu */
626 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
627 rect.left += GetSystemMetrics(SM_CXSIZE);
628 if (pt.x <= rect.left) return HTSYSMENU;
630 /* Check maximize box */
631 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
632 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
634 if (pt.x >= rect.right) return HTMAXBUTTON;
635 /* Check minimize box */
636 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
637 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
638 if (pt.x >= rect.right) return HTMINBUTTON;
639 return HTCAPTION;
643 /* Check client area */
645 ScreenToClient( wndPtr->hwndSelf, &pt );
646 GetClientRect( wndPtr->hwndSelf, &rect );
647 if (PtInRect( &rect, pt )) return HTCLIENT;
649 /* Check vertical scroll bar */
651 if (wndPtr->dwStyle & WS_VSCROLL)
653 rect.right += GetSystemMetrics(SM_CXVSCROLL);
654 if (PtInRect( &rect, pt )) return HTVSCROLL;
657 /* Check horizontal scroll bar */
659 if (wndPtr->dwStyle & WS_HSCROLL)
661 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
662 if (PtInRect( &rect, pt ))
664 /* Check size box */
665 if ((wndPtr->dwStyle & WS_VSCROLL) &&
666 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
667 return HTSIZE;
668 return HTHSCROLL;
672 /* Check menu bar */
674 if (HAS_MENU(wndPtr))
676 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
677 return HTMENU;
680 /* Has to return HTNOWHERE if nothing was found
681 Could happen when a window has a customized non client area */
682 return HTNOWHERE;
686 /***********************************************************************
687 * NC_DoNCHitTest95
689 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
691 * FIXME: Just a modified copy of the Win 3.1 version.
694 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
696 RECT rect;
698 TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
700 GetWindowRect(wndPtr->hwndSelf, &rect );
701 if (!PtInRect( &rect, pt )) return HTNOWHERE;
703 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
705 /* Check borders */
706 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
708 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
709 if (!PtInRect( &rect, pt ))
711 /* Check top sizing border */
712 if (pt.y < rect.top)
714 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
715 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
716 return HTTOP;
718 /* Check bottom sizing border */
719 if (pt.y >= rect.bottom)
721 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
722 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
723 return HTBOTTOM;
725 /* Check left sizing border */
726 if (pt.x < rect.left)
728 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
729 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
730 return HTLEFT;
732 /* Check right sizing border */
733 if (pt.x >= rect.right)
735 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
736 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
737 return HTRIGHT;
741 else /* No thick frame */
743 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
744 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
745 else if (HAS_THINFRAME( wndPtr->dwStyle ))
746 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
747 if (!PtInRect( &rect, pt )) return HTBORDER;
750 /* Check caption */
752 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
754 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
755 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
756 else
757 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
758 if (!PtInRect( &rect, pt ))
760 /* Check system menu */
761 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
763 if (NC_IconForWindow(wndPtr->hwndSelf))
764 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
766 if (pt.x < rect.left) return HTSYSMENU;
768 /* Check close button */
769 if (wndPtr->dwStyle & WS_SYSMENU)
770 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
771 if (pt.x > rect.right) return HTCLOSE;
773 /* Check maximize box */
774 /* In win95 there is automatically a Maximize button when there is a minimize one*/
775 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
776 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
777 if (pt.x > rect.right) return HTMAXBUTTON;
779 /* Check minimize box */
780 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
781 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
782 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
784 if (pt.x > rect.right) return HTMINBUTTON;
785 return HTCAPTION;
789 /* Check client area */
791 ScreenToClient( wndPtr->hwndSelf, &pt );
792 GetClientRect( wndPtr->hwndSelf, &rect );
793 if (PtInRect( &rect, pt )) return HTCLIENT;
795 /* Check vertical scroll bar */
797 if (wndPtr->dwStyle & WS_VSCROLL)
799 rect.right += GetSystemMetrics(SM_CXVSCROLL);
800 if (PtInRect( &rect, pt )) return HTVSCROLL;
803 /* Check horizontal scroll bar */
805 if (wndPtr->dwStyle & WS_HSCROLL)
807 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
808 if (PtInRect( &rect, pt ))
810 /* Check size box */
811 if ((wndPtr->dwStyle & WS_VSCROLL) &&
812 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
813 return HTSIZE;
814 return HTHSCROLL;
818 /* Check menu bar */
820 if (HAS_MENU(wndPtr))
822 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
823 return HTMENU;
826 /* Has to return HTNOWHERE if nothing was found
827 Could happen when a window has a customized non client area */
828 return HTNOWHERE;
832 /***********************************************************************
833 * NC_HandleNCHitTest
835 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
837 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
839 LONG retvalue;
840 WND *wndPtr = WIN_FindWndPtr (hwnd);
842 if (!wndPtr)
843 return HTERROR;
845 if (TWEAK_WineLook == WIN31_LOOK)
846 retvalue = NC_DoNCHitTest (wndPtr, pt);
847 else
848 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
849 WIN_ReleaseWndPtr(wndPtr);
850 return retvalue;
854 /***********************************************************************
855 * NC_DrawSysButton
857 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
859 RECT rect;
860 HDC hdcMem;
861 HBITMAP hbitmap;
863 NC_GetInsideRect( hwnd, &rect );
864 hdcMem = CreateCompatibleDC( hdc );
865 hbitmap = SelectObject( hdcMem, hbitmapClose );
866 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
867 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
868 down ? NOTSRCCOPY : SRCCOPY );
869 SelectObject( hdcMem, hbitmap );
870 DeleteDC( hdcMem );
874 /***********************************************************************
875 * NC_DrawMaxButton
877 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
879 RECT rect;
880 HDC hdcMem;
882 NC_GetInsideRect( hwnd, &rect );
883 hdcMem = CreateCompatibleDC( hdc );
884 SelectObject( hdcMem, (IsZoomed(hwnd)
885 ? (down ? hbitmapRestoreD : hbitmapRestore)
886 : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
887 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
888 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
889 SRCCOPY );
890 DeleteDC( hdcMem );
895 /***********************************************************************
896 * NC_DrawMinButton
898 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
900 RECT rect;
901 HDC hdcMem;
903 NC_GetInsideRect( hwnd, &rect );
904 hdcMem = CreateCompatibleDC( hdc );
905 SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
906 if (GetWindowLongA(hwnd,GWL_STYLE) & WS_MAXIMIZEBOX)
907 rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
908 BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
909 GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
910 SRCCOPY );
911 DeleteDC( hdcMem );
915 /******************************************************************************
917 * void NC_DrawSysButton95(
918 * HWND hwnd,
919 * HDC hdc,
920 * BOOL down )
922 * Draws the Win95 system icon.
924 * Revision history
925 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
926 * Original implementation from NC_DrawSysButton source.
927 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
928 * Fixed most bugs.
930 *****************************************************************************/
932 BOOL
933 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
935 HICON hIcon = NC_IconForWindow( hwnd );
937 if (hIcon)
939 RECT rect;
940 NC_GetInsideRect( hwnd, &rect );
941 DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
942 GetSystemMetrics(SM_CXSMICON),
943 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
945 return (hIcon != 0);
949 /******************************************************************************
951 * void NC_DrawCloseButton95(
952 * HWND hwnd,
953 * HDC hdc,
954 * BOOL down,
955 * BOOL bGrayed )
957 * Draws the Win95 close button.
959 * If bGrayed is true, then draw a disabled Close button
961 * Revision history
962 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
963 * Original implementation from NC_DrawSysButton95 source.
965 *****************************************************************************/
967 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
969 RECT rect;
971 NC_GetInsideRect( hwnd, &rect );
973 /* A tool window has a smaller Close button */
974 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
976 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
977 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
978 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
980 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
981 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
982 rect.bottom = rect.top + iBmpHeight;
983 rect.right = rect.left + iBmpWidth;
985 else
987 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
988 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
989 rect.top += 2;
990 rect.right -= 2;
992 DrawFrameControl( hdc, &rect, DFC_CAPTION,
993 (DFCS_CAPTIONCLOSE |
994 (down ? DFCS_PUSHED : 0) |
995 (bGrayed ? DFCS_INACTIVE : 0)) );
998 /******************************************************************************
999 * NC_DrawMaxButton95
1001 * Draws the maximize button for Win95 style windows.
1002 * If bGrayed is true, then draw a disabled Maximize button
1004 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1006 RECT rect;
1007 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1009 NC_GetInsideRect( hwnd, &rect );
1010 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1011 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1012 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1013 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1014 rect.top += 2;
1015 rect.right -= 2;
1016 if (down) flags |= DFCS_PUSHED;
1017 if (bGrayed) flags |= DFCS_INACTIVE;
1018 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1021 /******************************************************************************
1022 * NC_DrawMinButton95
1024 * Draws the minimize button for Win95 style windows.
1025 * If bGrayed is true, then draw a disabled Minimize button
1027 static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1029 RECT rect;
1030 UINT flags = DFCS_CAPTIONMIN;
1031 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1033 NC_GetInsideRect( hwnd, &rect );
1034 if (style & WS_SYSMENU)
1035 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1036 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1037 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1038 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1039 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1040 rect.top += 2;
1041 rect.right -= 2;
1042 if (down) flags |= DFCS_PUSHED;
1043 if (bGrayed) flags |= DFCS_INACTIVE;
1044 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1047 /***********************************************************************
1048 * NC_DrawFrame
1050 * Draw a window frame inside the given rectangle, and update the rectangle.
1051 * The correct pen for the frame must be selected in the DC.
1053 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1054 BOOL active )
1056 INT width, height;
1058 if (TWEAK_WineLook != WIN31_LOOK)
1059 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1061 if (dlgFrame)
1063 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1064 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1065 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1066 COLOR_INACTIVECAPTION) );
1068 else
1070 width = GetSystemMetrics(SM_CXFRAME) - 2;
1071 height = GetSystemMetrics(SM_CYFRAME) - 2;
1072 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1073 COLOR_INACTIVEBORDER) );
1076 /* Draw frame */
1077 PatBlt( hdc, rect->left, rect->top,
1078 rect->right - rect->left, height, PATCOPY );
1079 PatBlt( hdc, rect->left, rect->top,
1080 width, rect->bottom - rect->top, PATCOPY );
1081 PatBlt( hdc, rect->left, rect->bottom - 1,
1082 rect->right - rect->left, -height, PATCOPY );
1083 PatBlt( hdc, rect->right - 1, rect->top,
1084 -width, rect->bottom - rect->top, PATCOPY );
1086 if (dlgFrame)
1088 InflateRect( rect, -width, -height );
1090 else
1092 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1093 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1095 /* Draw inner rectangle */
1097 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1098 Rectangle( hdc, rect->left + width, rect->top + height,
1099 rect->right - width , rect->bottom - height );
1101 /* Draw the decorations */
1103 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1104 LineTo( hdc, rect->left + width, rect->top + decYOff );
1105 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1106 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1107 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1108 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1109 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1110 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1112 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1113 LineTo( hdc, rect->left + decXOff, rect->top + height);
1114 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1115 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1116 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1117 LineTo( hdc, rect->right - decXOff, rect->top + height );
1118 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1119 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1121 InflateRect( rect, -width - 1, -height - 1 );
1126 /******************************************************************************
1128 * void NC_DrawFrame95(
1129 * HDC hdc,
1130 * RECT *rect,
1131 * BOOL active,
1132 * DWORD style,
1133 * DWORD exStyle )
1135 * Draw a window frame inside the given rectangle, and update the rectangle.
1137 * Bugs
1138 * Many. First, just what IS a frame in Win95? Note that the 3D look
1139 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1140 * edge. The inner rectangle just inside the frame is handled by the
1141 * Caption code.
1143 * In short, for most people, this function should be a nop (unless
1144 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1145 * them lately, but just to get this code right). Even so, it doesn't
1146 * appear to be so. It's being worked on...
1148 * Revision history
1149 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1150 * Original implementation (based on NC_DrawFrame)
1151 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1152 * Some minor fixes.
1153 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1154 * Fixed a fix or something.
1156 *****************************************************************************/
1158 static void NC_DrawFrame95(
1159 HDC hdc,
1160 RECT *rect,
1161 BOOL active,
1162 DWORD style,
1163 DWORD exStyle)
1165 INT width, height;
1167 /* Firstly the "thick" frame */
1168 if (style & WS_THICKFRAME)
1170 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1171 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1173 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1174 COLOR_INACTIVEBORDER) );
1175 /* Draw frame */
1176 PatBlt( hdc, rect->left, rect->top,
1177 rect->right - rect->left, height, PATCOPY );
1178 PatBlt( hdc, rect->left, rect->top,
1179 width, rect->bottom - rect->top, PATCOPY );
1180 PatBlt( hdc, rect->left, rect->bottom - 1,
1181 rect->right - rect->left, -height, PATCOPY );
1182 PatBlt( hdc, rect->right - 1, rect->top,
1183 -width, rect->bottom - rect->top, PATCOPY );
1185 InflateRect( rect, -width, -height );
1188 /* Now the other bit of the frame */
1189 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1190 (exStyle & WS_EX_DLGMODALFRAME))
1192 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1193 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1194 /* This should give a value of 1 that should also work for a border */
1196 SelectObject( hdc, GetSysColorBrush(
1197 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1198 COLOR_3DFACE :
1199 (exStyle & WS_EX_STATICEDGE) ?
1200 COLOR_WINDOWFRAME :
1201 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1202 COLOR_3DFACE :
1203 /* else */
1204 COLOR_WINDOWFRAME));
1206 /* Draw frame */
1207 PatBlt( hdc, rect->left, rect->top,
1208 rect->right - rect->left, height, PATCOPY );
1209 PatBlt( hdc, rect->left, rect->top,
1210 width, rect->bottom - rect->top, PATCOPY );
1211 PatBlt( hdc, rect->left, rect->bottom - 1,
1212 rect->right - rect->left, -height, PATCOPY );
1213 PatBlt( hdc, rect->right - 1, rect->top,
1214 -width, rect->bottom - rect->top, PATCOPY );
1216 InflateRect( rect, -width, -height );
1221 /***********************************************************************
1222 * NC_DrawCaption
1224 * Draw the window caption.
1225 * The correct pen for the window frame must be selected in the DC.
1227 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1228 DWORD style, BOOL active )
1230 RECT r = *rect;
1231 char buffer[256];
1233 if (!hbitmapClose)
1235 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) ))) return;
1236 hbitmapMinimize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
1237 hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
1238 hbitmapMaximize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
1239 hbitmapMaximizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOMD) );
1240 hbitmapRestore = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORE) );
1241 hbitmapRestoreD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
1244 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1246 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1247 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1248 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1249 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1250 r.left++;
1251 r.right--;
1252 SelectObject( hdc, hbrushOld );
1254 MoveToEx( hdc, r.left, r.bottom, NULL );
1255 LineTo( hdc, r.right, r.bottom );
1257 if (style & WS_SYSMENU)
1259 NC_DrawSysButton( hwnd, hdc, FALSE );
1260 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1261 MoveToEx( hdc, r.left - 1, r.top, NULL );
1262 LineTo( hdc, r.left - 1, r.bottom );
1264 if (style & WS_MAXIMIZEBOX)
1266 NC_DrawMaxButton( hwnd, hdc, FALSE );
1267 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1269 if (style & WS_MINIMIZEBOX)
1271 NC_DrawMinButton( hwnd, hdc, FALSE );
1272 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1275 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1276 COLOR_INACTIVECAPTION) );
1278 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1280 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1281 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1282 SetBkMode( hdc, TRANSPARENT );
1283 DrawTextA( hdc, buffer, -1, &r,
1284 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1289 /******************************************************************************
1291 * NC_DrawCaption95(
1292 * HDC hdc,
1293 * RECT *rect,
1294 * HWND hwnd,
1295 * DWORD style,
1296 * BOOL active )
1298 * Draw the window caption for Win95 style windows.
1299 * The correct pen for the window frame must be selected in the DC.
1301 * Bugs
1302 * Hey, a function that finally works! Well, almost.
1303 * It's being worked on.
1305 * Revision history
1306 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1307 * Original implementation.
1308 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1309 * Some minor fixes.
1311 *****************************************************************************/
1313 static void NC_DrawCaption95(
1314 HDC hdc,
1315 RECT *rect,
1316 HWND hwnd,
1317 DWORD style,
1318 DWORD exStyle,
1319 BOOL active )
1321 RECT r = *rect;
1322 char buffer[256];
1323 HPEN hPrevPen;
1324 HMENU hSysMenu;
1326 hPrevPen = SelectObject( hdc, GetSysColorPen(
1327 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1328 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1329 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1330 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1331 LineTo( hdc, r.right, r.bottom - 1 );
1332 SelectObject( hdc, hPrevPen );
1333 r.bottom--;
1335 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1336 COLOR_INACTIVECAPTION) );
1338 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1339 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1340 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1343 if (style & WS_SYSMENU)
1345 UINT state;
1347 /* Go get the sysmenu */
1348 hSysMenu = GetSystemMenu(hwnd, FALSE);
1349 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1351 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1352 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1353 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1354 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1356 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1358 /* In win95 the two buttons are always there */
1359 /* But if the menu item is not in the menu they're disabled*/
1361 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1362 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1364 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1365 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1369 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1370 NONCLIENTMETRICSA nclm;
1371 HFONT hFont, hOldFont;
1372 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1373 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1374 if (exStyle & WS_EX_TOOLWINDOW)
1375 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1376 else
1377 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1378 hOldFont = SelectObject (hdc, hFont);
1379 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1380 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1381 SetBkMode( hdc, TRANSPARENT );
1382 r.left += 2;
1383 DrawTextA( hdc, buffer, -1, &r,
1384 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1385 DeleteObject (SelectObject (hdc, hOldFont));
1391 /***********************************************************************
1392 * NC_DoNCPaint
1394 * Paint the non-client area. clip is currently unused.
1396 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1398 HDC hdc;
1399 RECT rect;
1400 BOOL active;
1401 HWND hwnd = wndPtr->hwndSelf;
1403 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1404 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1406 active = wndPtr->flags & WIN_NCACTIVATED;
1408 TRACE("%04x %d\n", hwnd, active );
1410 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1411 ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1413 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1414 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1415 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1416 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1417 == NULLREGION)
1419 ReleaseDC( hwnd, hdc );
1420 return;
1423 rect.top = rect.left = 0;
1424 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1425 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1427 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1429 if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1431 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1432 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1433 InflateRect( &rect, -1, -1 );
1436 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1437 NC_DrawFrame(hdc, &rect, FALSE, active );
1438 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1439 NC_DrawFrame( hdc, &rect, TRUE, active );
1441 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1443 RECT r = rect;
1444 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1445 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1446 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1449 if (HAS_MENU(wndPtr))
1451 RECT r = rect;
1452 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1453 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1456 /* Draw the scroll-bars */
1458 if (wndPtr->dwStyle & WS_VSCROLL)
1459 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1460 if (wndPtr->dwStyle & WS_HSCROLL)
1461 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1463 /* Draw the "size-box" */
1465 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1467 RECT r = rect;
1468 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1469 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1470 if(wndPtr->dwStyle & WS_BORDER) {
1471 r.left++;
1472 r.top++;
1474 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1477 ReleaseDC( hwnd, hdc );
1481 /******************************************************************************
1483 * void NC_DoNCPaint95(
1484 * WND *wndPtr,
1485 * HRGN clip,
1486 * BOOL suppress_menupaint )
1488 * Paint the non-client area for Win95 windows. The clip region is
1489 * currently ignored.
1491 * Bugs
1492 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1493 * misc/tweak.c controls/menu.c # :-)
1495 * Revision history
1496 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1497 * Original implementation
1498 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1499 * Fixed some bugs.
1500 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1501 * Streamlined window style checks.
1503 *****************************************************************************/
1505 static void NC_DoNCPaint95(
1506 WND *wndPtr,
1507 HRGN clip,
1508 BOOL suppress_menupaint )
1510 HDC hdc;
1511 RECT rfuzz, rect, rectClip;
1512 BOOL active;
1513 HWND hwnd = wndPtr->hwndSelf;
1515 if ( wndPtr->dwStyle & WS_MINIMIZE ||
1516 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1518 active = wndPtr->flags & WIN_NCACTIVATED;
1520 TRACE("%04x %d\n", hwnd, active );
1522 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1523 the call to GetDCEx implying that it is allowed not to use it either.
1524 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1525 will cause clipRgn to be deleted after ReleaseDC().
1526 Now, how is the "system" supposed to tell what happened?
1529 if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1530 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1533 if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1534 wndPtr->rectClient.top-wndPtr->rectWindow.top,
1535 wndPtr->rectClient.right-wndPtr->rectWindow.left,
1536 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1537 == NULLREGION)
1539 ReleaseDC( hwnd, hdc );
1540 return;
1543 rect.top = rect.left = 0;
1544 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1545 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1547 if( clip > 1 )
1548 GetRgnBox( clip, &rectClip );
1549 else
1551 clip = 0;
1552 rectClip = rect;
1555 SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1557 if (HAS_STATICOUTERFRAME(wndPtr->dwStyle, wndPtr->dwExStyle)) {
1558 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1560 else if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1561 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1564 NC_DrawFrame95(hdc, &rect, active, wndPtr->dwStyle, wndPtr->dwExStyle );
1566 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1568 RECT r = rect;
1569 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1570 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1571 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1573 else {
1574 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1575 rect.top += GetSystemMetrics(SM_CYCAPTION);
1577 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1578 NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1579 wndPtr->dwExStyle, active);
1582 if (HAS_MENU(wndPtr))
1584 RECT r = rect;
1585 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1587 TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1588 r.left, r.top, r.right, r.bottom);
1590 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1593 TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1594 rect.left, rect.top, rect.right, rect.bottom );
1596 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1597 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1599 /* Draw the scroll-bars */
1601 if (wndPtr->dwStyle & WS_VSCROLL)
1602 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1603 if (wndPtr->dwStyle & WS_HSCROLL)
1604 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1606 /* Draw the "size-box" */
1607 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1609 RECT r = rect;
1610 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1611 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1612 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1615 ReleaseDC( hwnd, hdc );
1621 /***********************************************************************
1622 * NC_HandleNCPaint
1624 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1626 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1628 WND* wndPtr = WIN_FindWndPtr( hwnd );
1630 if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1632 if( wndPtr->dwStyle & WS_MINIMIZE )
1633 WINPOS_RedrawIconTitle( hwnd );
1634 else if (TWEAK_WineLook == WIN31_LOOK)
1635 NC_DoNCPaint( wndPtr, clip, FALSE );
1636 else
1637 NC_DoNCPaint95( wndPtr, clip, FALSE );
1639 WIN_ReleaseWndPtr(wndPtr);
1640 return 0;
1644 /***********************************************************************
1645 * NC_HandleNCActivate
1647 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1649 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1651 WND* wndPtr = WIN_FindWndPtr( hwnd );
1653 /* Lotus Notes draws menu descriptions in the caption of its main
1654 * window. When it wants to restore original "system" view, it just
1655 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1656 * attempt to minimize redrawings lead to a not restored caption.
1658 if (wndPtr)
1660 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1661 else wndPtr->flags &= ~WIN_NCACTIVATED;
1663 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1664 else if (TWEAK_WineLook == WIN31_LOOK)
1665 NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1666 else
1667 NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1668 WIN_ReleaseWndPtr(wndPtr);
1670 return TRUE;
1674 /***********************************************************************
1675 * NC_HandleSetCursor
1677 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1679 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1681 if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1682 return 0; /* Don't set the cursor for child windows */
1684 switch(LOWORD(lParam))
1686 case HTERROR:
1688 WORD msg = HIWORD( lParam );
1689 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1690 (msg == WM_RBUTTONDOWN))
1691 MessageBeep(0);
1693 break;
1695 case HTCLIENT:
1697 HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1698 if(hCursor) {
1699 SetCursor(hCursor);
1700 return TRUE;
1702 return FALSE;
1705 case HTLEFT:
1706 case HTRIGHT:
1707 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1709 case HTTOP:
1710 case HTBOTTOM:
1711 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1713 case HTTOPLEFT:
1714 case HTBOTTOMRIGHT:
1715 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1717 case HTTOPRIGHT:
1718 case HTBOTTOMLEFT:
1719 return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1722 /* Default cursor: arrow */
1723 return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1726 /***********************************************************************
1727 * NC_GetSysPopupPos
1729 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1731 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1732 else
1734 WND *wndPtr = WIN_FindWndPtr( hwnd );
1735 if (!wndPtr) return;
1737 NC_GetInsideRect( hwnd, rect );
1738 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1739 if (wndPtr->dwStyle & WS_CHILD)
1740 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1741 if (TWEAK_WineLook == WIN31_LOOK) {
1742 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1743 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1745 else {
1746 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1747 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1749 WIN_ReleaseWndPtr( wndPtr );
1753 /***********************************************************************
1754 * NC_TrackMinMaxBox95
1756 * Track a mouse button press on the minimize or maximize box.
1758 * The big difference between 3.1 and 95 is the disabled button state.
1759 * In win95 the system button can be disabled, so it can ignore the mouse
1760 * event.
1763 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1765 MSG msg;
1766 HDC hdc = GetWindowDC( hwnd );
1767 BOOL pressed = TRUE;
1768 UINT state;
1769 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1770 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1772 void (*paintButton)(HWND, HDC16, BOOL, BOOL);
1774 if (wParam == HTMINBUTTON)
1776 /* If the style is not present, do nothing */
1777 if (!(wndStyle & WS_MINIMIZEBOX))
1778 return;
1780 /* Check if the sysmenu item for minimize is there */
1781 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1783 paintButton = &NC_DrawMinButton95;
1785 else
1787 /* If the style is not present, do nothing */
1788 if (!(wndStyle & WS_MAXIMIZEBOX))
1789 return;
1791 /* Check if the sysmenu item for maximize is there */
1792 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1794 paintButton = &NC_DrawMaxButton95;
1797 SetCapture( hwnd );
1799 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1801 while(1)
1803 BOOL oldstate = pressed;
1805 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1806 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1808 if(msg.message == WM_LBUTTONUP)
1809 break;
1811 if(msg.message != WM_MOUSEMOVE)
1812 continue;
1814 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1815 if (pressed != oldstate)
1816 (*paintButton)( hwnd, hdc, pressed, FALSE);
1819 if(pressed)
1820 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1822 ReleaseCapture();
1823 ReleaseDC( hwnd, hdc );
1825 /* If the item minimize or maximize of the sysmenu are not there */
1826 /* or if the style is not present, do nothing */
1827 if ((!pressed) || (state == 0xFFFFFFFF))
1828 return;
1830 if (wParam == HTMINBUTTON)
1831 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1832 else
1833 SendMessageA( hwnd, WM_SYSCOMMAND,
1834 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1837 /***********************************************************************
1838 * NC_TrackMinMaxBox
1840 * Track a mouse button press on the minimize or maximize box.
1842 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1844 MSG msg;
1845 HDC hdc = GetWindowDC( hwnd );
1846 BOOL pressed = TRUE;
1847 void (*paintButton)(HWND, HDC16, BOOL);
1849 SetCapture( hwnd );
1851 if (wParam == HTMINBUTTON)
1852 paintButton = &NC_DrawMinButton;
1853 else
1854 paintButton = &NC_DrawMaxButton;
1856 (*paintButton)( hwnd, hdc, TRUE);
1858 while(1)
1860 BOOL oldstate = pressed;
1862 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1863 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1865 if(msg.message == WM_LBUTTONUP)
1866 break;
1868 if(msg.message != WM_MOUSEMOVE)
1869 continue;
1871 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1872 if (pressed != oldstate)
1873 (*paintButton)( hwnd, hdc, pressed);
1876 if(pressed)
1877 (*paintButton)( hwnd, hdc, FALSE);
1879 ReleaseCapture();
1880 ReleaseDC( hwnd, hdc );
1882 if (!pressed) return;
1884 if (wParam == HTMINBUTTON)
1885 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1886 else
1887 SendMessageA( hwnd, WM_SYSCOMMAND,
1888 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1892 /***********************************************************************
1893 * NC_TrackCloseButton95
1895 * Track a mouse button press on the Win95 close button.
1897 static void
1898 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1900 MSG msg;
1901 HDC hdc;
1902 BOOL pressed = TRUE;
1903 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1904 UINT state;
1906 if(hSysMenu == 0)
1907 return;
1909 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1911 /* If the item close of the sysmenu is disabled or not there do nothing */
1912 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1913 return;
1915 hdc = GetWindowDC( hwnd );
1917 SetCapture( hwnd );
1919 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1921 while(1)
1923 BOOL oldstate = pressed;
1925 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1926 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1928 if(msg.message == WM_LBUTTONUP)
1929 break;
1931 if(msg.message != WM_MOUSEMOVE)
1932 continue;
1934 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1935 if (pressed != oldstate)
1936 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1939 if(pressed)
1940 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1942 ReleaseCapture();
1943 ReleaseDC( hwnd, hdc );
1944 if (!pressed) return;
1946 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1950 /***********************************************************************
1951 * NC_TrackScrollBar
1953 * Track a mouse button press on the horizontal or vertical scroll-bar.
1955 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1957 INT scrollbar;
1959 if ((wParam & 0xfff0) == SC_HSCROLL)
1961 if ((wParam & 0x0f) != HTHSCROLL) return;
1962 scrollbar = SB_HORZ;
1964 else /* SC_VSCROLL */
1966 if ((wParam & 0x0f) != HTVSCROLL) return;
1967 scrollbar = SB_VERT;
1969 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1973 /***********************************************************************
1974 * NC_HandleNCLButtonDown
1976 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1978 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1980 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1982 switch(wParam) /* Hit test */
1984 case HTCAPTION:
1986 HWND top = GetAncestor( hwnd, GA_ROOT );
1988 if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
1989 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1990 break;
1993 case HTSYSMENU:
1994 if( style & WS_SYSMENU )
1996 if( !(style & WS_MINIMIZE) )
1998 HDC hDC = GetWindowDC(hwnd);
1999 if (TWEAK_WineLook == WIN31_LOOK)
2000 NC_DrawSysButton( hwnd, hDC, TRUE );
2001 else
2002 NC_DrawSysButton95( hwnd, hDC, TRUE );
2003 ReleaseDC( hwnd, hDC );
2005 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2007 break;
2009 case HTMENU:
2010 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2011 break;
2013 case HTHSCROLL:
2014 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2015 break;
2017 case HTVSCROLL:
2018 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2019 break;
2021 case HTMINBUTTON:
2022 case HTMAXBUTTON:
2023 if (TWEAK_WineLook == WIN31_LOOK)
2024 NC_TrackMinMaxBox( hwnd, wParam );
2025 else
2026 NC_TrackMinMaxBox95( hwnd, wParam );
2027 break;
2029 case HTCLOSE:
2030 if (TWEAK_WineLook >= WIN95_LOOK)
2031 NC_TrackCloseButton95 (hwnd, wParam);
2032 break;
2034 case HTLEFT:
2035 case HTRIGHT:
2036 case HTTOP:
2037 case HTTOPLEFT:
2038 case HTTOPRIGHT:
2039 case HTBOTTOM:
2040 case HTBOTTOMLEFT:
2041 case HTBOTTOMRIGHT:
2042 /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2043 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2044 break;
2046 case HTBORDER:
2047 break;
2049 return 0;
2053 /***********************************************************************
2054 * NC_HandleNCLButtonDblClk
2056 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2058 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2061 * if this is an icon, send a restore since we are handling
2062 * a double click
2064 if (IsIconic(hwnd))
2066 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2067 return 0;
2070 switch(wParam) /* Hit test */
2072 case HTCAPTION:
2073 /* stop processing if WS_MAXIMIZEBOX is missing */
2074 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2075 SendMessageW( hwnd, WM_SYSCOMMAND,
2076 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2077 break;
2079 case HTSYSMENU:
2080 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2081 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2082 break;
2084 case HTHSCROLL:
2085 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2086 break;
2088 case HTVSCROLL:
2089 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2090 break;
2092 return 0;
2096 /***********************************************************************
2097 * NC_HandleSysCommand
2099 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2101 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2103 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2105 switch (wParam & 0xfff0)
2107 case SC_SIZE:
2108 case SC_MOVE:
2109 if (USER_Driver.pSysCommandSizeMove)
2110 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2111 break;
2113 case SC_MINIMIZE:
2114 if (hwnd == GetForegroundWindow())
2115 ShowOwnedPopups(hwnd,FALSE);
2116 ShowWindow( hwnd, SW_MINIMIZE );
2117 break;
2119 case SC_MAXIMIZE:
2120 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2121 ShowOwnedPopups(hwnd,TRUE);
2122 ShowWindow( hwnd, SW_MAXIMIZE );
2123 break;
2125 case SC_RESTORE:
2126 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2127 ShowOwnedPopups(hwnd,TRUE);
2128 ShowWindow( hwnd, SW_RESTORE );
2129 break;
2131 case SC_CLOSE:
2132 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2134 case SC_VSCROLL:
2135 case SC_HSCROLL:
2137 POINT pt;
2138 pt.x = SLOWORD(lParam);
2139 pt.y = SHIWORD(lParam);
2140 NC_TrackScrollBar( hwnd, wParam, pt );
2142 break;
2144 case SC_MOUSEMENU:
2146 POINT pt;
2147 pt.x = SLOWORD(lParam);
2148 pt.y = SHIWORD(lParam);
2149 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2151 break;
2153 case SC_KEYMENU:
2154 MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2155 break;
2157 case SC_TASKLIST:
2158 WinExec( "taskman.exe", SW_SHOWNORMAL );
2159 break;
2161 case SC_SCREENSAVE:
2162 if (wParam == SC_ABOUTWINE)
2164 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2165 if (hmodule)
2167 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2168 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2169 FreeLibrary( hmodule );
2172 else
2173 if (wParam == SC_PUTMARK)
2174 TRACE_(shell)("Mark requested by user\n");
2175 break;
2177 case SC_HOTKEY:
2178 case SC_ARRANGE:
2179 case SC_NEXTWINDOW:
2180 case SC_PREVWINDOW:
2181 FIXME("unimplemented!\n");
2182 break;
2184 return 0;
2187 /*************************************************************
2188 * NC_DrawGrayButton
2190 * Stub for the grayed button of the caption
2192 *************************************************************/
2194 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2196 HBITMAP hMaskBmp;
2197 HDC hdcMask = CreateCompatibleDC (0);
2198 HBRUSH hOldBrush;
2200 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2202 if(hMaskBmp == 0)
2203 return FALSE;
2205 SelectObject (hdcMask, hMaskBmp);
2207 /* Draw the grayed bitmap using the mask */
2208 hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2209 BitBlt (hdc, x, y, 12, 10,
2210 hdcMask, 0, 0, 0xB8074A);
2212 /* Clean up */
2213 SelectObject (hdc, hOldBrush);
2214 DeleteObject(hMaskBmp);
2215 DeleteDC (hdcMask);
2217 return TRUE;