Split OpenFile implementation in separate 16- and 32-bit versions, and
[wine.git] / windows / nonclient.c
blob185b05e744f5affa9f11a2858e584ec09a4d8604
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/winuser16.h"
29 #include "wownt32.h"
30 #include "win.h"
31 #include "user.h"
32 #include "dce.h"
33 #include "controls.h"
34 #include "cursoricon.h"
35 #include "winpos.h"
36 #include "nonclient.h"
37 #include "shellapi.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
41 WINE_DECLARE_DEBUG_CHANNEL(shell);
43 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
45 static HBITMAP hbitmapClose;
47 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
48 0x55, 0x50,
49 0xAA, 0xA0,
50 0x55, 0x50,
51 0xAA, 0xA0,
52 0x55, 0x50,
53 0xAA, 0xA0,
54 0x55, 0x50,
55 0xAA, 0xA0,
56 0x55, 0x50};
58 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
59 #define SC_PUTMARK (SC_SCREENSAVE+2)
61 /* Some useful macros */
62 #define HAS_DLGFRAME(style,exStyle) \
63 (((exStyle) & WS_EX_DLGMODALFRAME) || \
64 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
66 #define HAS_THICKFRAME(style,exStyle) \
67 (((style) & WS_THICKFRAME) && \
68 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
70 #define HAS_THINFRAME(style) \
71 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
73 #define HAS_BIGFRAME(style,exStyle) \
74 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
75 ((exStyle) & WS_EX_DLGMODALFRAME))
77 #define HAS_STATICOUTERFRAME(style,exStyle) \
78 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
79 WS_EX_STATICEDGE)
81 #define HAS_ANYFRAME(style,exStyle) \
82 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
83 ((exStyle) & WS_EX_DLGMODALFRAME) || \
84 !((style) & (WS_CHILD | WS_POPUP)))
86 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
89 /***********************************************************************
90 * NC_AdjustRect
92 * Compute the size of the window rectangle from the size of the
93 * client rectangle.
95 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
97 if (TWEAK_WineLook > WIN31_LOOK)
98 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
100 if(style & WS_ICONIC) return;
102 if (HAS_THICKFRAME( style, exStyle ))
103 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
104 else if (HAS_DLGFRAME( style, exStyle ))
105 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
106 else if (HAS_THINFRAME( style ))
107 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
109 if ((style & WS_CAPTION) == WS_CAPTION)
110 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
112 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
114 if (style & WS_VSCROLL) {
115 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
116 if(!HAS_ANYFRAME( style, exStyle ))
117 rect->right++;
120 if (style & WS_HSCROLL) {
121 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
122 if(!HAS_ANYFRAME( style, exStyle ))
123 rect->bottom++;
128 /******************************************************************************
129 * NC_AdjustRectOuter95
131 * Computes the size of the "outside" parts of the window based on the
132 * parameters of the client area.
134 + PARAMS
135 * LPRECT16 rect
136 * DWORD style
137 * BOOL menu
138 * DWORD exStyle
140 * NOTES
141 * "Outer" parts of a window means the whole window frame, caption and
142 * menu bar. It does not include "inner" parts of the frame like client
143 * edge, static edge or scroll bars.
145 * Revision history
146 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
147 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
149 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
150 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
151 * NC_AdjustRectInner95 and added handling of Win95 styles.
153 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
154 * Streamlined window style checks.
156 *****************************************************************************/
158 static void
159 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
161 int adjust;
162 if(style & WS_ICONIC) return;
164 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
165 WS_EX_STATICEDGE)
167 adjust = 1; /* for the outer frame always present */
169 else
171 adjust = 0;
172 if ((exStyle & WS_EX_DLGMODALFRAME) ||
173 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
175 if (style & WS_THICKFRAME)
176 adjust += ( GetSystemMetrics (SM_CXFRAME)
177 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
178 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
179 (exStyle & WS_EX_DLGMODALFRAME))
180 adjust++; /* The other border */
182 InflateRect (rect, adjust, adjust);
184 if ((style & WS_CAPTION) == WS_CAPTION)
186 if (exStyle & WS_EX_TOOLWINDOW)
187 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
188 else
189 rect->top -= GetSystemMetrics(SM_CYCAPTION);
191 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
195 /******************************************************************************
196 * NC_AdjustRectInner95
198 * Computes the size of the "inside" part of the window based on the
199 * parameters of the client area.
201 + PARAMS
202 * LPRECT16 rect
203 * DWORD style
204 * DWORD exStyle
206 * NOTES
207 * "Inner" part of a window means the window frame inside of the flat
208 * window frame. It includes the client edge, the static edge and the
209 * scroll bars.
211 * Revision history
212 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
213 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
215 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
216 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
217 * NC_AdjustRectInner95 and added handling of Win95 styles.
219 *****************************************************************************/
221 static void
222 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
224 if(style & WS_ICONIC) return;
226 if (exStyle & WS_EX_CLIENTEDGE)
227 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
229 if (style & WS_VSCROLL)
231 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
232 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
233 else
234 rect->right += GetSystemMetrics(SM_CXVSCROLL);
236 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
241 static HICON NC_IconForWindow( HWND hwnd )
243 HICON hIcon = 0;
244 WND *wndPtr = WIN_GetPtr( hwnd );
246 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
248 hIcon = wndPtr->hIconSmall;
249 if (!hIcon) hIcon = wndPtr->hIcon;
250 WIN_ReleasePtr( wndPtr );
252 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
253 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
255 /* If there is no hIcon specified and this is a modal dialog,
256 * get the default one.
258 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
259 hIcon = LoadImageA(0, (LPSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
260 return hIcon;
263 /***********************************************************************
264 * DrawCaption (USER32.@) Draws a caption bar
266 * PARAMS
267 * hwnd [I]
268 * hdc [I]
269 * lpRect [I]
270 * uFlags [I]
272 * RETURNS
273 * Success:
274 * Failure:
277 BOOL WINAPI
278 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
280 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
284 /***********************************************************************
285 * DrawCaptionTempA (USER32.@)
287 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
288 HICON hIcon, LPCSTR str, UINT uFlags)
290 LPWSTR strW;
291 INT len;
292 BOOL ret = FALSE;
294 if (!(uFlags & DC_TEXT) || !str)
295 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
297 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
298 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
300 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
301 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
302 HeapFree( GetProcessHeap (), 0, strW );
304 return ret;
308 /***********************************************************************
309 * DrawCaptionTempW (USER32.@)
311 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
312 HICON hIcon, LPCWSTR str, UINT uFlags)
314 RECT rc = *rect;
316 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
317 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
319 /* drawing background */
320 if (uFlags & DC_INBUTTON) {
321 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
323 if (uFlags & DC_ACTIVE) {
324 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
325 PatBlt (hdc, rc.left, rc.top,
326 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
327 SelectObject (hdc, hbr);
330 else {
331 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
332 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
336 /* drawing icon */
337 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
338 POINT pt;
340 pt.x = rc.left + 2;
341 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
343 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
344 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
345 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
346 rc.left += (rc.bottom - rc.top);
349 /* drawing text */
350 if (uFlags & DC_TEXT) {
351 HFONT hOldFont;
353 if (uFlags & DC_INBUTTON)
354 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
355 else if (uFlags & DC_ACTIVE)
356 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
357 else
358 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
360 SetBkMode (hdc, TRANSPARENT);
362 if (hFont)
363 hOldFont = SelectObject (hdc, hFont);
364 else {
365 NONCLIENTMETRICSW nclm;
366 HFONT hNewFont;
367 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
368 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
369 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
370 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
371 hOldFont = SelectObject (hdc, hNewFont);
374 if (str)
375 DrawTextW (hdc, str, -1, &rc,
376 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
377 else {
378 WCHAR szText[128];
379 INT nLen;
380 nLen = GetWindowTextW (hwnd, szText, 128);
381 DrawTextW (hdc, szText, nLen, &rc,
382 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
385 if (hFont)
386 SelectObject (hdc, hOldFont);
387 else
388 DeleteObject (SelectObject (hdc, hOldFont));
391 /* drawing focus ??? */
392 if (uFlags & 0x2000)
393 FIXME("undocumented flag (0x2000)!\n");
395 return 0;
399 /***********************************************************************
400 * AdjustWindowRect (USER.102)
402 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
404 return AdjustWindowRectEx16( rect, style, menu, 0 );
408 /***********************************************************************
409 * AdjustWindowRect (USER32.@)
411 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
413 return AdjustWindowRectEx( rect, style, menu, 0 );
417 /***********************************************************************
418 * AdjustWindowRectEx (USER.454)
420 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
421 BOOL16 menu, DWORD exStyle )
423 RECT rect32;
424 BOOL ret;
426 CONV_RECT16TO32( rect, &rect32 );
427 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
428 CONV_RECT32TO16( &rect32, rect );
429 return ret;
433 /***********************************************************************
434 * AdjustWindowRectEx (USER32.@)
436 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
438 /* Correct the window style */
439 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
440 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
441 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
442 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
444 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
445 rect->left, rect->top, rect->right, rect->bottom,
446 style, menu, exStyle );
448 if (TWEAK_WineLook == WIN31_LOOK)
449 NC_AdjustRect( rect, style, menu, exStyle );
450 else
452 NC_AdjustRectOuter95( rect, style, menu, exStyle );
453 NC_AdjustRectInner95( rect, style, exStyle );
455 return TRUE;
459 /***********************************************************************
460 * NC_HandleNCCalcSize
462 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
464 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
466 RECT tmpRect = { 0, 0, 0, 0 };
467 LONG result = 0;
468 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
469 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
470 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
472 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
473 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
475 if (!IsIconic(hwnd))
477 if (TWEAK_WineLook == WIN31_LOOK)
478 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
479 else
480 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
482 winRect->left -= tmpRect.left;
483 winRect->top -= tmpRect.top;
484 winRect->right -= tmpRect.right;
485 winRect->bottom -= tmpRect.bottom;
487 if (!(style & WS_CHILD) && GetMenu(hwnd))
489 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
490 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
492 winRect->top +=
493 MENU_GetMenuBarHeight( hwnd,
494 winRect->right - winRect->left,
495 -tmpRect.left, -tmpRect.top ) + 1;
498 if (TWEAK_WineLook > WIN31_LOOK) {
499 SetRect(&tmpRect, 0, 0, 0, 0);
500 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
501 winRect->left -= tmpRect.left;
502 winRect->top -= tmpRect.top;
503 winRect->right -= tmpRect.right;
504 winRect->bottom -= tmpRect.bottom;
507 if (winRect->top > winRect->bottom)
508 winRect->bottom = winRect->top;
510 if (winRect->left > winRect->right)
511 winRect->right = winRect->left;
513 return result;
517 /***********************************************************************
518 * NC_GetInsideRect
520 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
521 * but without the borders (if any).
522 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
524 void NC_GetInsideRect( HWND hwnd, RECT *rect )
526 WND * wndPtr = WIN_FindWndPtr( hwnd );
528 rect->top = rect->left = 0;
529 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
530 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
532 if (wndPtr->dwStyle & WS_ICONIC) goto END;
534 /* Remove frame from rectangle */
535 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
537 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
539 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
541 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
542 /* FIXME: this isn't in NC_AdjustRect? why not? */
543 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
544 InflateRect( rect, -1, 0 );
546 else if (HAS_THINFRAME( wndPtr->dwStyle ))
548 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
551 /* We have additional border information if the window
552 * is a child (but not an MDI child) */
553 if (TWEAK_WineLook != WIN31_LOOK)
555 if ( (wndPtr->dwStyle & WS_CHILD) &&
556 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
558 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
559 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
560 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
561 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
565 END:
566 WIN_ReleaseWndPtr(wndPtr);
567 return;
571 /***********************************************************************
572 * NC_DoNCHitTest
574 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
577 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
579 RECT rect;
581 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
583 GetWindowRect(wndPtr->hwndSelf, &rect );
584 if (!PtInRect( &rect, pt )) return HTNOWHERE;
586 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
588 /* Check borders */
589 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
591 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
592 if (!PtInRect( &rect, pt ))
594 /* Check top sizing border */
595 if (pt.y < rect.top)
597 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
598 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
599 return HTTOP;
601 /* Check bottom sizing border */
602 if (pt.y >= rect.bottom)
604 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
605 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
606 return HTBOTTOM;
608 /* Check left sizing border */
609 if (pt.x < rect.left)
611 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
612 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
613 return HTLEFT;
615 /* Check right sizing border */
616 if (pt.x >= rect.right)
618 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
619 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
620 return HTRIGHT;
624 else /* No thick frame */
626 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
627 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
628 else if (HAS_THINFRAME( wndPtr->dwStyle ))
629 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
630 if (!PtInRect( &rect, pt )) return HTBORDER;
633 /* Check caption */
635 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
637 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
638 if (!PtInRect( &rect, pt ))
640 /* Check system menu */
641 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
642 rect.left += GetSystemMetrics(SM_CXSIZE);
643 if (pt.x <= rect.left) return HTSYSMENU;
645 /* Check maximize box */
646 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
647 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
649 if (pt.x >= rect.right) return HTMAXBUTTON;
650 /* Check minimize box */
651 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
652 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
653 if (pt.x >= rect.right) return HTMINBUTTON;
654 return HTCAPTION;
658 /* Check client area */
660 ScreenToClient( wndPtr->hwndSelf, &pt );
661 GetClientRect( wndPtr->hwndSelf, &rect );
662 if (PtInRect( &rect, pt )) return HTCLIENT;
664 /* Check vertical scroll bar */
666 if (wndPtr->dwStyle & WS_VSCROLL)
668 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
669 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
670 else
671 rect.right += GetSystemMetrics(SM_CXVSCROLL);
672 if (PtInRect( &rect, pt )) return HTVSCROLL;
675 /* Check horizontal scroll bar */
677 if (wndPtr->dwStyle & WS_HSCROLL)
679 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
680 if (PtInRect( &rect, pt ))
682 /* Check size box */
683 if ((wndPtr->dwStyle & WS_VSCROLL) &&
684 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
685 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
686 return HTSIZE;
687 return HTHSCROLL;
691 /* Check menu bar */
693 if (HAS_MENU(wndPtr))
695 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
696 return HTMENU;
699 /* Has to return HTNOWHERE if nothing was found
700 Could happen when a window has a customized non client area */
701 return HTNOWHERE;
705 /***********************************************************************
706 * NC_DoNCHitTest95
708 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
710 * FIXME: Just a modified copy of the Win 3.1 version.
713 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
715 RECT rect;
717 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
719 GetWindowRect(wndPtr->hwndSelf, &rect );
720 if (!PtInRect( &rect, pt )) return HTNOWHERE;
722 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
724 /* Check borders */
725 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
727 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
728 if (!PtInRect( &rect, pt ))
730 /* Check top sizing border */
731 if (pt.y < rect.top)
733 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
734 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
735 return HTTOP;
737 /* Check bottom sizing border */
738 if (pt.y >= rect.bottom)
740 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
741 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
742 return HTBOTTOM;
744 /* Check left sizing border */
745 if (pt.x < rect.left)
747 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
748 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
749 return HTLEFT;
751 /* Check right sizing border */
752 if (pt.x >= rect.right)
754 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
755 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
756 return HTRIGHT;
760 else /* No thick frame */
762 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
763 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
764 else if (HAS_THINFRAME( wndPtr->dwStyle ))
765 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
766 if (!PtInRect( &rect, pt )) return HTBORDER;
769 /* Check caption */
771 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
773 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
774 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
775 else
776 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
777 if (!PtInRect( &rect, pt ))
779 /* Check system menu */
780 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
782 if (NC_IconForWindow(wndPtr->hwndSelf))
783 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
785 if (pt.x < rect.left) return HTSYSMENU;
787 /* Check close button */
788 if (wndPtr->dwStyle & WS_SYSMENU)
789 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
790 if (pt.x > rect.right) return HTCLOSE;
792 /* Check maximize box */
793 /* In win95 there is automatically a Maximize button when there is a minimize one*/
794 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
795 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
796 if (pt.x > rect.right) return HTMAXBUTTON;
798 /* Check minimize box */
799 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
800 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
801 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
803 if (pt.x > rect.right) return HTMINBUTTON;
804 return HTCAPTION;
808 /* Check client area */
810 ScreenToClient( wndPtr->hwndSelf, &pt );
811 GetClientRect( wndPtr->hwndSelf, &rect );
812 if (PtInRect( &rect, pt )) return HTCLIENT;
814 /* Check vertical scroll bar */
816 if (wndPtr->dwStyle & WS_VSCROLL)
818 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
819 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
820 else
821 rect.right += GetSystemMetrics(SM_CXVSCROLL);
822 if (PtInRect( &rect, pt )) return HTVSCROLL;
825 /* Check horizontal scroll bar */
827 if (wndPtr->dwStyle & WS_HSCROLL)
829 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
830 if (PtInRect( &rect, pt ))
832 /* Check size box */
833 if ((wndPtr->dwStyle & WS_VSCROLL) &&
834 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
835 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
836 return HTSIZE;
837 return HTHSCROLL;
841 /* Check menu bar */
843 if (HAS_MENU(wndPtr))
845 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
846 return HTMENU;
849 /* Has to return HTNOWHERE if nothing was found
850 Could happen when a window has a customized non client area */
851 return HTNOWHERE;
855 /***********************************************************************
856 * NC_HandleNCHitTest
858 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
860 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
862 LONG retvalue;
863 WND *wndPtr = WIN_FindWndPtr (hwnd);
865 if (!wndPtr)
866 return HTERROR;
868 if (TWEAK_WineLook == WIN31_LOOK)
869 retvalue = NC_DoNCHitTest (wndPtr, pt);
870 else
871 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
872 WIN_ReleaseWndPtr(wndPtr);
873 return retvalue;
877 /***********************************************************************
878 * NC_DrawSysButton
880 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
882 RECT rect;
883 HDC hdcMem;
884 HBITMAP hbitmap;
886 NC_GetInsideRect( hwnd, &rect );
887 hdcMem = CreateCompatibleDC( hdc );
888 hbitmap = SelectObject( hdcMem, hbitmapClose );
889 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
890 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
891 down ? NOTSRCCOPY : SRCCOPY );
892 SelectObject( hdcMem, hbitmap );
893 DeleteDC( hdcMem );
897 /***********************************************************************
898 * NC_DrawMaxButton
900 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
902 RECT rect;
903 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
905 NC_GetInsideRect( hwnd, &rect );
906 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
907 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
908 rect.top += 1;
909 rect.right -= 1;
910 if (down) flags |= DFCS_PUSHED;
911 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
915 /***********************************************************************
916 * NC_DrawMinButton
918 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
920 RECT rect;
921 UINT flags = DFCS_CAPTIONMIN;
922 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
924 NC_GetInsideRect( hwnd, &rect );
925 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
926 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
927 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
928 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
929 rect.top += 1;
930 rect.right -= 1;
931 if (down) flags |= DFCS_PUSHED;
932 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
936 /******************************************************************************
938 * void NC_DrawSysButton95(
939 * HWND hwnd,
940 * HDC hdc,
941 * BOOL down )
943 * Draws the Win95 system icon.
945 * Revision history
946 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
947 * Original implementation from NC_DrawSysButton source.
948 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
949 * Fixed most bugs.
951 *****************************************************************************/
953 BOOL
954 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
956 HICON hIcon = NC_IconForWindow( hwnd );
958 if (hIcon)
960 RECT rect;
961 NC_GetInsideRect( hwnd, &rect );
962 DrawIconEx (hdc, rect.left + 1, rect.top + 1, hIcon,
963 GetSystemMetrics(SM_CXSIZE) - 1,
964 GetSystemMetrics(SM_CYSIZE) - 1, 0, 0, DI_NORMAL);
966 return (hIcon != 0);
970 /******************************************************************************
972 * void NC_DrawCloseButton95(
973 * HWND hwnd,
974 * HDC hdc,
975 * BOOL down,
976 * BOOL bGrayed )
978 * Draws the Win95 close button.
980 * If bGrayed is true, then draw a disabled Close button
982 * Revision history
983 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
984 * Original implementation from NC_DrawSysButton95 source.
986 *****************************************************************************/
988 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
990 RECT rect;
992 NC_GetInsideRect( hwnd, &rect );
994 /* A tool window has a smaller Close button */
995 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
997 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
998 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
999 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1001 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1002 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1003 rect.bottom = rect.top + iBmpHeight;
1004 rect.right = rect.left + iBmpWidth;
1006 else
1008 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
1009 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1010 rect.top += 2;
1011 rect.right -= 2;
1013 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1014 (DFCS_CAPTIONCLOSE |
1015 (down ? DFCS_PUSHED : 0) |
1016 (bGrayed ? DFCS_INACTIVE : 0)) );
1019 /******************************************************************************
1020 * NC_DrawMaxButton95
1022 * Draws the maximize button for Win95 style windows.
1023 * If bGrayed is true, then draw a disabled Maximize button
1025 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1027 RECT rect;
1028 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1030 NC_GetInsideRect( hwnd, &rect );
1031 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1032 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1033 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1034 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1035 rect.top += 2;
1036 rect.right -= 2;
1037 if (down) flags |= DFCS_PUSHED;
1038 if (bGrayed) flags |= DFCS_INACTIVE;
1039 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1042 /******************************************************************************
1043 * NC_DrawMinButton95
1045 * Draws the minimize button for Win95 style windows.
1046 * If bGrayed is true, then draw a disabled Minimize button
1048 static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1050 RECT rect;
1051 UINT flags = DFCS_CAPTIONMIN;
1052 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1054 NC_GetInsideRect( hwnd, &rect );
1055 if (style & WS_SYSMENU)
1056 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1057 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1058 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1059 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1060 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1061 rect.top += 2;
1062 rect.right -= 2;
1063 if (down) flags |= DFCS_PUSHED;
1064 if (bGrayed) flags |= DFCS_INACTIVE;
1065 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1068 /***********************************************************************
1069 * NC_DrawFrame
1071 * Draw a window frame inside the given rectangle, and update the rectangle.
1072 * The correct pen for the frame must be selected in the DC.
1074 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1075 BOOL active )
1077 INT width, height;
1079 if (TWEAK_WineLook != WIN31_LOOK)
1080 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1082 if (dlgFrame)
1084 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1085 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1086 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1087 COLOR_INACTIVECAPTION) );
1089 else
1091 width = GetSystemMetrics(SM_CXFRAME) - 2;
1092 height = GetSystemMetrics(SM_CYFRAME) - 2;
1093 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1094 COLOR_INACTIVEBORDER) );
1097 /* Draw frame */
1098 PatBlt( hdc, rect->left, rect->top,
1099 rect->right - rect->left, height, PATCOPY );
1100 PatBlt( hdc, rect->left, rect->top,
1101 width, rect->bottom - rect->top, PATCOPY );
1102 PatBlt( hdc, rect->left, rect->bottom - 1,
1103 rect->right - rect->left, -height, PATCOPY );
1104 PatBlt( hdc, rect->right - 1, rect->top,
1105 -width, rect->bottom - rect->top, PATCOPY );
1107 if (dlgFrame)
1109 InflateRect( rect, -width, -height );
1111 else
1113 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1114 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1116 /* Draw inner rectangle */
1118 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1119 Rectangle( hdc, rect->left + width, rect->top + height,
1120 rect->right - width , rect->bottom - height );
1122 /* Draw the decorations */
1124 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1125 LineTo( hdc, rect->left + width, rect->top + decYOff );
1126 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1127 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1128 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1129 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1130 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1131 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1133 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1134 LineTo( hdc, rect->left + decXOff, rect->top + height);
1135 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1136 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1137 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1138 LineTo( hdc, rect->right - decXOff, rect->top + height );
1139 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1140 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1142 InflateRect( rect, -width - 1, -height - 1 );
1147 /******************************************************************************
1149 * void NC_DrawFrame95(
1150 * HDC hdc,
1151 * RECT *rect,
1152 * BOOL active,
1153 * DWORD style,
1154 * DWORD exStyle )
1156 * Draw a window frame inside the given rectangle, and update the rectangle.
1158 * Bugs
1159 * Many. First, just what IS a frame in Win95? Note that the 3D look
1160 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1161 * edge. The inner rectangle just inside the frame is handled by the
1162 * Caption code.
1164 * In short, for most people, this function should be a nop (unless
1165 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1166 * them lately, but just to get this code right). Even so, it doesn't
1167 * appear to be so. It's being worked on...
1169 * Revision history
1170 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1171 * Original implementation (based on NC_DrawFrame)
1172 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1173 * Some minor fixes.
1174 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1175 * Fixed a fix or something.
1177 *****************************************************************************/
1179 static void NC_DrawFrame95(
1180 HDC hdc,
1181 RECT *rect,
1182 BOOL active,
1183 DWORD style,
1184 DWORD exStyle)
1186 INT width, height;
1188 /* Firstly the "thick" frame */
1189 if (style & WS_THICKFRAME)
1191 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1192 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1194 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1195 COLOR_INACTIVEBORDER) );
1196 /* Draw frame */
1197 PatBlt( hdc, rect->left, rect->top,
1198 rect->right - rect->left, height, PATCOPY );
1199 PatBlt( hdc, rect->left, rect->top,
1200 width, rect->bottom - rect->top, PATCOPY );
1201 PatBlt( hdc, rect->left, rect->bottom - 1,
1202 rect->right - rect->left, -height, PATCOPY );
1203 PatBlt( hdc, rect->right - 1, rect->top,
1204 -width, rect->bottom - rect->top, PATCOPY );
1206 InflateRect( rect, -width, -height );
1209 /* Now the other bit of the frame */
1210 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1211 (exStyle & WS_EX_DLGMODALFRAME))
1213 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1214 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1215 /* This should give a value of 1 that should also work for a border */
1217 SelectObject( hdc, GetSysColorBrush(
1218 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1219 COLOR_3DFACE :
1220 (exStyle & WS_EX_STATICEDGE) ?
1221 COLOR_WINDOWFRAME :
1222 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1223 COLOR_3DFACE :
1224 /* else */
1225 COLOR_WINDOWFRAME));
1227 /* Draw frame */
1228 PatBlt( hdc, rect->left, rect->top,
1229 rect->right - rect->left, height, PATCOPY );
1230 PatBlt( hdc, rect->left, rect->top,
1231 width, rect->bottom - rect->top, PATCOPY );
1232 PatBlt( hdc, rect->left, rect->bottom - 1,
1233 rect->right - rect->left, -height, PATCOPY );
1234 PatBlt( hdc, rect->right - 1, rect->top,
1235 -width, rect->bottom - rect->top, PATCOPY );
1237 InflateRect( rect, -width, -height );
1242 /***********************************************************************
1243 * NC_DrawCaption
1245 * Draw the window caption.
1246 * The correct pen for the window frame must be selected in the DC.
1248 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1249 DWORD style, BOOL active )
1251 RECT r = *rect;
1252 char buffer[256];
1254 if (!hbitmapClose)
1256 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1259 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1261 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1262 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1263 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1264 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1265 r.left++;
1266 r.right--;
1267 SelectObject( hdc, hbrushOld );
1269 MoveToEx( hdc, r.left, r.bottom, NULL );
1270 LineTo( hdc, r.right, r.bottom );
1272 if (style & WS_SYSMENU)
1274 NC_DrawSysButton( hwnd, hdc, FALSE );
1275 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1276 MoveToEx( hdc, r.left - 1, r.top, NULL );
1277 LineTo( hdc, r.left - 1, r.bottom );
1279 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1280 if (style & WS_MAXIMIZEBOX)
1282 NC_DrawMaxButton( hwnd, hdc, FALSE );
1283 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1285 if (style & WS_MINIMIZEBOX)
1287 NC_DrawMinButton( hwnd, hdc, FALSE );
1288 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1291 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1293 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1294 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1295 SetBkMode( hdc, TRANSPARENT );
1296 DrawTextA( hdc, buffer, -1, &r,
1297 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1302 /******************************************************************************
1304 * NC_DrawCaption95(
1305 * HDC hdc,
1306 * RECT *rect,
1307 * HWND hwnd,
1308 * DWORD style,
1309 * BOOL active )
1311 * Draw the window caption for Win95 style windows.
1312 * The correct pen for the window frame must be selected in the DC.
1314 * Bugs
1315 * Hey, a function that finally works! Well, almost.
1316 * It's being worked on.
1318 * Revision history
1319 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1320 * Original implementation.
1321 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1322 * Some minor fixes.
1324 *****************************************************************************/
1326 static void NC_DrawCaption95(
1327 HDC hdc,
1328 RECT *rect,
1329 HWND hwnd,
1330 DWORD style,
1331 DWORD exStyle,
1332 BOOL active )
1334 RECT r = *rect;
1335 char buffer[256];
1336 HPEN hPrevPen;
1337 HMENU hSysMenu;
1339 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
1340 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1341 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1342 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1343 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1344 LineTo( hdc, r.right, r.bottom - 1 );
1345 SelectObject( hdc, hPrevPen );
1346 r.bottom--;
1348 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1349 COLOR_INACTIVECAPTION) );
1351 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1352 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1353 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1356 if (style & WS_SYSMENU)
1358 UINT state;
1360 /* Go get the sysmenu */
1361 hSysMenu = GetSystemMenu(hwnd, FALSE);
1362 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1364 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1365 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1366 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1367 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1369 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1371 /* In win95 the two buttons are always there */
1372 /* But if the menu item is not in the menu they're disabled*/
1374 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1375 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1377 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1378 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1382 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1383 NONCLIENTMETRICSA nclm;
1384 HFONT hFont, hOldFont;
1385 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1386 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1387 if (exStyle & WS_EX_TOOLWINDOW)
1388 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1389 else
1390 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1391 hOldFont = SelectObject (hdc, hFont);
1392 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1393 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1394 SetBkMode( hdc, TRANSPARENT );
1395 r.left += 2;
1396 DrawTextA( hdc, buffer, -1, &r,
1397 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1398 DeleteObject (SelectObject (hdc, hOldFont));
1404 /***********************************************************************
1405 * NC_DoNCPaint
1407 * Paint the non-client area. clip is currently unused.
1409 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1411 HDC hdc;
1412 RECT rect;
1413 BOOL active;
1414 WND *wndPtr;
1415 DWORD dwStyle, dwExStyle;
1416 WORD flags;
1417 RECT rectClient, rectWindow;
1418 int has_menu;
1420 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1421 has_menu = HAS_MENU(wndPtr);
1422 dwStyle = wndPtr->dwStyle;
1423 dwExStyle = wndPtr->dwExStyle;
1424 flags = wndPtr->flags;
1425 rectClient = wndPtr->rectClient;
1426 rectWindow = wndPtr->rectWindow;
1427 WIN_ReleasePtr( wndPtr );
1429 if ( dwStyle & WS_MINIMIZE ||
1430 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1432 active = flags & WIN_NCACTIVATED;
1434 TRACE("%p %d\n", hwnd, active );
1436 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1437 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1439 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1440 rectClient.top-rectWindow.top,
1441 rectClient.right-rectWindow.left,
1442 rectClient.bottom-rectWindow.top )
1443 == NULLREGION)
1445 ReleaseDC( hwnd, hdc );
1446 return;
1449 rect.top = rect.left = 0;
1450 rect.right = rectWindow.right - rectWindow.left;
1451 rect.bottom = rectWindow.bottom - rectWindow.top;
1453 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1455 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1457 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1458 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1459 InflateRect( &rect, -1, -1 );
1462 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1463 NC_DrawFrame(hdc, &rect, FALSE, active );
1464 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1465 NC_DrawFrame( hdc, &rect, TRUE, active );
1467 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1469 RECT r = rect;
1470 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1471 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1472 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1475 if (has_menu)
1477 RECT r = rect;
1478 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1479 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1482 /* Draw the scroll-bars */
1484 if (dwStyle & WS_VSCROLL)
1485 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1486 if (dwStyle & WS_HSCROLL)
1487 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1489 /* Draw the "size-box" */
1491 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1493 RECT r = rect;
1494 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1495 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1496 else
1497 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1498 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1499 if(wndPtr->dwStyle & WS_BORDER) {
1500 r.left++;
1501 r.top++;
1503 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1506 ReleaseDC( hwnd, hdc );
1510 /******************************************************************************
1512 * void NC_DoNCPaint95(
1513 * HWND hwnd,
1514 * HRGN clip,
1515 * BOOL suppress_menupaint )
1517 * Paint the non-client area for Win95 windows. The clip region is
1518 * currently ignored.
1520 * Bugs
1521 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1522 * misc/tweak.c controls/menu.c # :-)
1524 * Revision history
1525 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1526 * Original implementation
1527 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1528 * Fixed some bugs.
1529 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1530 * Streamlined window style checks.
1532 *****************************************************************************/
1534 static void NC_DoNCPaint95(
1535 HWND hwnd,
1536 HRGN clip,
1537 BOOL suppress_menupaint )
1539 HDC hdc;
1540 RECT rfuzz, rect, rectClip;
1541 BOOL active;
1542 WND *wndPtr;
1543 DWORD dwStyle, dwExStyle;
1544 WORD flags;
1545 RECT rectClient, rectWindow;
1546 int has_menu;
1548 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1549 has_menu = HAS_MENU(wndPtr);
1550 dwStyle = wndPtr->dwStyle;
1551 dwExStyle = wndPtr->dwExStyle;
1552 flags = wndPtr->flags;
1553 rectClient = wndPtr->rectClient;
1554 rectWindow = wndPtr->rectWindow;
1555 WIN_ReleasePtr( wndPtr );
1557 if ( dwStyle & WS_MINIMIZE ||
1558 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1560 active = flags & WIN_NCACTIVATED;
1562 TRACE("%p %d\n", hwnd, active );
1564 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1565 the call to GetDCEx implying that it is allowed not to use it either.
1566 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1567 will cause clipRgn to be deleted after ReleaseDC().
1568 Now, how is the "system" supposed to tell what happened?
1571 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1572 ((clip > (HRGN)1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1575 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1576 rectClient.top-rectWindow.top,
1577 rectClient.right-rectWindow.left,
1578 rectClient.bottom-rectWindow.top )
1579 == NULLREGION)
1581 ReleaseDC( hwnd, hdc );
1582 return;
1585 rect.top = rect.left = 0;
1586 rect.right = rectWindow.right - rectWindow.left;
1587 rect.bottom = rectWindow.bottom - rectWindow.top;
1589 if( clip > (HRGN)1 )
1590 GetRgnBox( clip, &rectClip );
1591 else
1593 clip = 0;
1594 rectClip = rect;
1597 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1599 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1600 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1602 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1603 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1606 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1608 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1610 RECT r = rect;
1611 if (dwExStyle & WS_EX_TOOLWINDOW) {
1612 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1613 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1615 else {
1616 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1617 rect.top += GetSystemMetrics(SM_CYCAPTION);
1619 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1620 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1621 dwExStyle, active);
1624 if (has_menu)
1626 RECT r = rect;
1627 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1629 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1630 r.left, r.top, r.right, r.bottom);
1632 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1635 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1636 rect.left, rect.top, rect.right, rect.bottom );
1638 if (dwExStyle & WS_EX_CLIENTEDGE)
1639 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1641 /* Draw the scroll-bars */
1643 if (dwStyle & WS_VSCROLL)
1644 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1645 if (dwStyle & WS_HSCROLL)
1646 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1648 /* Draw the "size-box" */
1649 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1651 RECT r = rect;
1652 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1653 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1654 else
1655 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1656 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1657 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1660 ReleaseDC( hwnd, hdc );
1666 /***********************************************************************
1667 * NC_HandleNCPaint
1669 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1671 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1673 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1675 if( dwStyle & WS_VISIBLE )
1677 if( dwStyle & WS_MINIMIZE )
1678 WINPOS_RedrawIconTitle( hwnd );
1679 else if (TWEAK_WineLook == WIN31_LOOK)
1680 NC_DoNCPaint( hwnd, clip, FALSE );
1681 else
1682 NC_DoNCPaint95( hwnd, clip, FALSE );
1684 return 0;
1688 /***********************************************************************
1689 * NC_HandleNCActivate
1691 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1693 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1695 WND* wndPtr = WIN_FindWndPtr( hwnd );
1697 /* Lotus Notes draws menu descriptions in the caption of its main
1698 * window. When it wants to restore original "system" view, it just
1699 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1700 * attempt to minimize redrawings lead to a not restored caption.
1702 if (wndPtr)
1704 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1705 else wndPtr->flags &= ~WIN_NCACTIVATED;
1706 WIN_ReleaseWndPtr(wndPtr);
1708 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1709 else if (TWEAK_WineLook == WIN31_LOOK)
1710 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1711 else
1712 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1714 return TRUE;
1718 /***********************************************************************
1719 * NC_HandleSetCursor
1721 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1723 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1725 hwnd = WIN_GetFullHandle( (HWND)wParam );
1727 switch(LOWORD(lParam))
1729 case HTERROR:
1731 WORD msg = HIWORD( lParam );
1732 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1733 (msg == WM_RBUTTONDOWN))
1734 MessageBeep(0);
1736 break;
1738 case HTCLIENT:
1740 HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
1741 if(hCursor) {
1742 SetCursor(hCursor);
1743 return TRUE;
1745 return FALSE;
1748 case HTLEFT:
1749 case HTRIGHT:
1750 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1752 case HTTOP:
1753 case HTBOTTOM:
1754 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1756 case HTTOPLEFT:
1757 case HTBOTTOMRIGHT:
1758 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1760 case HTTOPRIGHT:
1761 case HTBOTTOMLEFT:
1762 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1765 /* Default cursor: arrow */
1766 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1769 /***********************************************************************
1770 * NC_GetSysPopupPos
1772 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1774 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1775 else
1777 WND *wndPtr = WIN_FindWndPtr( hwnd );
1778 if (!wndPtr) return;
1780 NC_GetInsideRect( hwnd, rect );
1781 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1782 if (wndPtr->dwStyle & WS_CHILD)
1783 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1784 if (TWEAK_WineLook == WIN31_LOOK) {
1785 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1786 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1788 else {
1789 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1790 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1792 WIN_ReleaseWndPtr( wndPtr );
1796 /***********************************************************************
1797 * NC_TrackMinMaxBox95
1799 * Track a mouse button press on the minimize or maximize box.
1801 * The big difference between 3.1 and 95 is the disabled button state.
1802 * In win95 the system button can be disabled, so it can ignore the mouse
1803 * event.
1806 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1808 MSG msg;
1809 HDC hdc = GetWindowDC( hwnd );
1810 BOOL pressed = TRUE;
1811 UINT state;
1812 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1813 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1815 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1817 if (wParam == HTMINBUTTON)
1819 /* If the style is not present, do nothing */
1820 if (!(wndStyle & WS_MINIMIZEBOX))
1821 return;
1823 /* Check if the sysmenu item for minimize is there */
1824 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1826 paintButton = &NC_DrawMinButton95;
1828 else
1830 /* If the style is not present, do nothing */
1831 if (!(wndStyle & WS_MAXIMIZEBOX))
1832 return;
1834 /* Check if the sysmenu item for maximize is there */
1835 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1837 paintButton = &NC_DrawMaxButton95;
1840 SetCapture( hwnd );
1842 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1844 while(1)
1846 BOOL oldstate = pressed;
1848 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1849 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1851 if(msg.message == WM_LBUTTONUP)
1852 break;
1854 if(msg.message != WM_MOUSEMOVE)
1855 continue;
1857 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1858 if (pressed != oldstate)
1859 (*paintButton)( hwnd, hdc, pressed, FALSE);
1862 if(pressed)
1863 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1865 ReleaseCapture();
1866 ReleaseDC( hwnd, hdc );
1868 /* If the item minimize or maximize of the sysmenu are not there */
1869 /* or if the style is not present, do nothing */
1870 if ((!pressed) || (state == 0xFFFFFFFF))
1871 return;
1873 if (wParam == HTMINBUTTON)
1874 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1875 else
1876 SendMessageA( hwnd, WM_SYSCOMMAND,
1877 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1880 /***********************************************************************
1881 * NC_TrackMinMaxBox
1883 * Track a mouse button press on the minimize or maximize box.
1885 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1887 MSG msg;
1888 HDC hdc = GetWindowDC( hwnd );
1889 BOOL pressed = TRUE;
1890 void (*paintButton)(HWND, HDC, BOOL);
1892 SetCapture( hwnd );
1894 if (wParam == HTMINBUTTON)
1895 paintButton = &NC_DrawMinButton;
1896 else
1897 paintButton = &NC_DrawMaxButton;
1899 (*paintButton)( hwnd, hdc, TRUE);
1901 while(1)
1903 BOOL oldstate = pressed;
1905 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1906 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1908 if(msg.message == WM_LBUTTONUP)
1909 break;
1911 if(msg.message != WM_MOUSEMOVE)
1912 continue;
1914 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1915 if (pressed != oldstate)
1916 (*paintButton)( hwnd, hdc, pressed);
1919 if(pressed)
1920 (*paintButton)( hwnd, hdc, FALSE);
1922 ReleaseCapture();
1923 ReleaseDC( hwnd, hdc );
1925 if (!pressed) return;
1927 if (wParam == HTMINBUTTON)
1928 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1929 else
1930 SendMessageA( hwnd, WM_SYSCOMMAND,
1931 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1935 /***********************************************************************
1936 * NC_TrackCloseButton95
1938 * Track a mouse button press on the Win95 close button.
1940 static void
1941 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1943 MSG msg;
1944 HDC hdc;
1945 BOOL pressed = TRUE;
1946 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1947 UINT state;
1949 if(hSysMenu == 0)
1950 return;
1952 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1954 /* If the item close of the sysmenu is disabled or not there do nothing */
1955 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1956 return;
1958 hdc = GetWindowDC( hwnd );
1960 SetCapture( hwnd );
1962 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1964 while(1)
1966 BOOL oldstate = pressed;
1968 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1969 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1971 if(msg.message == WM_LBUTTONUP)
1972 break;
1974 if(msg.message != WM_MOUSEMOVE)
1975 continue;
1977 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1978 if (pressed != oldstate)
1979 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1982 if(pressed)
1983 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1985 ReleaseCapture();
1986 ReleaseDC( hwnd, hdc );
1987 if (!pressed) return;
1989 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1993 /***********************************************************************
1994 * NC_TrackScrollBar
1996 * Track a mouse button press on the horizontal or vertical scroll-bar.
1998 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2000 INT scrollbar;
2002 if ((wParam & 0xfff0) == SC_HSCROLL)
2004 if ((wParam & 0x0f) != HTHSCROLL) return;
2005 scrollbar = SB_HORZ;
2007 else /* SC_VSCROLL */
2009 if ((wParam & 0x0f) != HTVSCROLL) return;
2010 scrollbar = SB_VERT;
2012 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
2016 /***********************************************************************
2017 * NC_HandleNCLButtonDown
2019 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2021 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
2023 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
2025 switch(wParam) /* Hit test */
2027 case HTCAPTION:
2029 HWND top = GetAncestor( hwnd, GA_ROOT );
2031 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
2032 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2033 break;
2036 case HTSYSMENU:
2037 if( style & WS_SYSMENU )
2039 if( !(style & WS_MINIMIZE) )
2041 HDC hDC = GetWindowDC(hwnd);
2042 if (TWEAK_WineLook == WIN31_LOOK)
2043 NC_DrawSysButton( hwnd, hDC, TRUE );
2044 else
2045 NC_DrawSysButton95( hwnd, hDC, TRUE );
2046 ReleaseDC( hwnd, hDC );
2048 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2050 break;
2052 case HTMENU:
2053 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2054 break;
2056 case HTHSCROLL:
2057 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2058 break;
2060 case HTVSCROLL:
2061 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2062 break;
2064 case HTMINBUTTON:
2065 case HTMAXBUTTON:
2066 if (TWEAK_WineLook == WIN31_LOOK)
2067 NC_TrackMinMaxBox( hwnd, wParam );
2068 else
2069 NC_TrackMinMaxBox95( hwnd, wParam );
2070 break;
2072 case HTCLOSE:
2073 if (TWEAK_WineLook >= WIN95_LOOK)
2074 NC_TrackCloseButton95 (hwnd, wParam);
2075 break;
2077 case HTLEFT:
2078 case HTRIGHT:
2079 case HTTOP:
2080 case HTTOPLEFT:
2081 case HTTOPRIGHT:
2082 case HTBOTTOM:
2083 case HTBOTTOMLEFT:
2084 case HTBOTTOMRIGHT:
2085 /* Old comment:
2086 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
2087 * This was previously done by setting wParam=SC_SIZE + wParam - 2
2089 /* But that is not what WinNT does. Instead it sends this. This
2090 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
2091 * SC_MOUSEMENU into wParam.
2093 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
2094 break;
2096 case HTBORDER:
2097 break;
2099 return 0;
2103 /***********************************************************************
2104 * NC_HandleNCLButtonDblClk
2106 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2108 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2111 * if this is an icon, send a restore since we are handling
2112 * a double click
2114 if (IsIconic(hwnd))
2116 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2117 return 0;
2120 switch(wParam) /* Hit test */
2122 case HTCAPTION:
2123 /* stop processing if WS_MAXIMIZEBOX is missing */
2124 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2125 SendMessageW( hwnd, WM_SYSCOMMAND,
2126 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2127 break;
2129 case HTSYSMENU:
2130 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2131 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2132 break;
2134 case HTHSCROLL:
2135 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2136 break;
2138 case HTVSCROLL:
2139 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2140 break;
2142 return 0;
2146 /***********************************************************************
2147 * NC_HandleSysCommand
2149 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2151 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2153 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2155 switch (wParam & 0xfff0)
2157 case SC_SIZE:
2158 case SC_MOVE:
2159 if (USER_Driver.pSysCommandSizeMove)
2160 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2161 break;
2163 case SC_MINIMIZE:
2164 if (hwnd == GetForegroundWindow())
2165 ShowOwnedPopups(hwnd,FALSE);
2166 ShowWindow( hwnd, SW_MINIMIZE );
2167 break;
2169 case SC_MAXIMIZE:
2170 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2171 ShowOwnedPopups(hwnd,TRUE);
2172 ShowWindow( hwnd, SW_MAXIMIZE );
2173 break;
2175 case SC_RESTORE:
2176 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2177 ShowOwnedPopups(hwnd,TRUE);
2178 ShowWindow( hwnd, SW_RESTORE );
2179 break;
2181 case SC_CLOSE:
2182 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2184 case SC_VSCROLL:
2185 case SC_HSCROLL:
2187 POINT pt;
2188 pt.x = (short)LOWORD(lParam);
2189 pt.y = (short)HIWORD(lParam);
2190 NC_TrackScrollBar( hwnd, wParam, pt );
2192 break;
2194 case SC_MOUSEMENU:
2196 POINT pt;
2197 pt.x = (short)LOWORD(lParam);
2198 pt.y = (short)HIWORD(lParam);
2199 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2201 break;
2203 case SC_KEYMENU:
2204 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
2205 break;
2207 case SC_TASKLIST:
2208 WinExec( "taskman.exe", SW_SHOWNORMAL );
2209 break;
2211 case SC_SCREENSAVE:
2212 if (wParam == SC_ABOUTWINE)
2214 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2215 if (hmodule)
2217 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2218 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
2219 FreeLibrary( hmodule );
2222 else
2223 if (wParam == SC_PUTMARK)
2224 DPRINTF("Debug mark requested by user\n");
2225 break;
2227 case SC_HOTKEY:
2228 case SC_ARRANGE:
2229 case SC_NEXTWINDOW:
2230 case SC_PREVWINDOW:
2231 FIXME("unimplemented!\n");
2232 break;
2234 return 0;
2237 /*************************************************************
2238 * NC_DrawGrayButton
2240 * Stub for the grayed button of the caption
2242 *************************************************************/
2244 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2246 HBITMAP hMaskBmp;
2247 HDC hdcMask;
2248 HBRUSH hOldBrush;
2250 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2252 if(hMaskBmp == 0)
2253 return FALSE;
2255 hdcMask = CreateCompatibleDC (0);
2256 SelectObject (hdcMask, hMaskBmp);
2258 /* Draw the grayed bitmap using the mask */
2259 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
2260 BitBlt (hdc, x, y, 12, 10,
2261 hdcMask, 0, 0, 0xB8074A);
2263 /* Clean up */
2264 SelectObject (hdc, hOldBrush);
2265 DeleteObject(hMaskBmp);
2266 DeleteDC (hdcMask);
2268 return TRUE;
2271 /***********************************************************************
2272 * GetTitleBarInfo (USER32.@)
2273 * TODO: Handle STATE_SYSTEM_PRESSED
2275 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
2276 DWORD dwStyle;
2277 DWORD dwExStyle;
2278 RECT wndRect;
2280 TRACE("(%p %p)\n", hwnd, tbi);
2282 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
2283 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
2284 SetLastError(ERROR_INVALID_PARAMETER);
2285 return FALSE;
2287 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
2288 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
2289 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
2291 GetWindowRect(hwnd, &wndRect);
2293 tbi->rcTitleBar.top += wndRect.top;
2294 tbi->rcTitleBar.left += wndRect.left;
2295 tbi->rcTitleBar.right += wndRect.left;
2297 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
2298 if(dwExStyle & WS_EX_TOOLWINDOW)
2299 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
2300 else {
2301 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
2302 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
2305 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
2306 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
2307 * Under XP it seems to
2309 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
2310 if(dwStyle & WS_CAPTION) {
2311 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
2312 if(dwStyle & WS_SYSMENU) {
2313 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
2314 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
2315 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
2317 else {
2318 if(!(dwStyle & WS_MINIMIZEBOX))
2319 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
2320 if(!(dwStyle & WS_MAXIMIZEBOX))
2321 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
2323 if(!(dwExStyle & WS_EX_CONTEXTHELP))
2324 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
2325 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
2326 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
2328 else {
2329 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
2330 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
2331 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
2332 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
2335 else
2336 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
2337 return TRUE;