Store window icons in the window structure so that WM_SETICON can do
[wine/multimedia.git] / windows / nonclient.c
blobbfd1340634eede3e30db8431ebb3e903a0a8d00a
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 "bitmap.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
42 WINE_DECLARE_DEBUG_CHANNEL(shell);
44 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
46 static HBITMAP hbitmapClose;
48 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
49 0x55, 0x50,
50 0xAA, 0xA0,
51 0x55, 0x50,
52 0xAA, 0xA0,
53 0x55, 0x50,
54 0xAA, 0xA0,
55 0x55, 0x50,
56 0xAA, 0xA0,
57 0x55, 0x50};
59 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
60 #define SC_PUTMARK (SC_SCREENSAVE+2)
62 /* Some useful macros */
63 #define HAS_DLGFRAME(style,exStyle) \
64 (((exStyle) & WS_EX_DLGMODALFRAME) || \
65 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
67 #define HAS_THICKFRAME(style,exStyle) \
68 (((style) & WS_THICKFRAME) && \
69 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
71 #define HAS_THINFRAME(style) \
72 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
74 #define HAS_BIGFRAME(style,exStyle) \
75 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
76 ((exStyle) & WS_EX_DLGMODALFRAME))
78 #define HAS_STATICOUTERFRAME(style,exStyle) \
79 (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
80 WS_EX_STATICEDGE)
82 #define HAS_ANYFRAME(style,exStyle) \
83 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
84 ((exStyle) & WS_EX_DLGMODALFRAME) || \
85 !((style) & (WS_CHILD | WS_POPUP)))
87 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
90 /***********************************************************************
91 * NC_AdjustRect
93 * Compute the size of the window rectangle from the size of the
94 * client rectangle.
96 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
98 if (TWEAK_WineLook > WIN31_LOOK)
99 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
101 if(style & WS_ICONIC) return;
103 if (HAS_THICKFRAME( style, exStyle ))
104 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
105 else if (HAS_DLGFRAME( style, exStyle ))
106 InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
107 else if (HAS_THINFRAME( style ))
108 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
110 if ((style & WS_CAPTION) == WS_CAPTION)
111 rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
113 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
115 if (style & WS_VSCROLL) {
116 rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
117 if(!HAS_ANYFRAME( style, exStyle ))
118 rect->right++;
121 if (style & WS_HSCROLL) {
122 rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
123 if(!HAS_ANYFRAME( style, exStyle ))
124 rect->bottom++;
129 /******************************************************************************
130 * NC_AdjustRectOuter95
132 * Computes the size of the "outside" parts of the window based on the
133 * parameters of the client area.
135 + PARAMS
136 * LPRECT16 rect
137 * DWORD style
138 * BOOL menu
139 * DWORD exStyle
141 * NOTES
142 * "Outer" parts of a window means the whole window frame, caption and
143 * menu bar. It does not include "inner" parts of the frame like client
144 * edge, static edge or scroll bars.
146 * Revision history
147 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
148 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
150 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
151 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
152 * NC_AdjustRectInner95 and added handling of Win95 styles.
154 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
155 * Streamlined window style checks.
157 *****************************************************************************/
159 static void
160 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
162 int adjust;
163 if(style & WS_ICONIC) return;
165 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
166 WS_EX_STATICEDGE)
168 adjust = 1; /* for the outer frame always present */
170 else
172 adjust = 0;
173 if ((exStyle & WS_EX_DLGMODALFRAME) ||
174 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
176 if (style & WS_THICKFRAME)
177 adjust += ( GetSystemMetrics (SM_CXFRAME)
178 - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
179 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
180 (exStyle & WS_EX_DLGMODALFRAME))
181 adjust++; /* The other border */
183 InflateRect (rect, adjust, adjust);
185 if ((style & WS_CAPTION) == WS_CAPTION)
187 if (exStyle & WS_EX_TOOLWINDOW)
188 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
189 else
190 rect->top -= GetSystemMetrics(SM_CYCAPTION);
192 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
196 /******************************************************************************
197 * NC_AdjustRectInner95
199 * Computes the size of the "inside" part of the window based on the
200 * parameters of the client area.
202 + PARAMS
203 * LPRECT16 rect
204 * DWORD style
205 * DWORD exStyle
207 * NOTES
208 * "Inner" part of a window means the window frame inside of the flat
209 * window frame. It includes the client edge, the static edge and the
210 * scroll bars.
212 * Revision history
213 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
214 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
216 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
217 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
218 * NC_AdjustRectInner95 and added handling of Win95 styles.
220 *****************************************************************************/
222 static void
223 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
225 if(style & WS_ICONIC) return;
227 if (exStyle & WS_EX_CLIENTEDGE)
228 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
230 if (style & WS_VSCROLL)
232 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
233 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
234 else
235 rect->right += GetSystemMetrics(SM_CXVSCROLL);
237 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
242 static HICON NC_IconForWindow( HWND hwnd )
244 HICON hIcon = 0;
245 WND *wndPtr = WIN_GetPtr( hwnd );
247 if (wndPtr && wndPtr != WND_OTHER_PROCESS)
249 hIcon = wndPtr->hIconSmall;
250 if (!hIcon) hIcon = wndPtr->hIcon;
251 WIN_ReleasePtr( wndPtr );
253 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
254 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
256 /* If there is no hIcon specified and this is a modal dialog,
257 * get the default one.
259 if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
260 hIcon = LoadImageA(0, (LPSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
261 return hIcon;
264 /***********************************************************************
265 * DrawCaption (USER32.@) Draws a caption bar
267 * PARAMS
268 * hwnd [I]
269 * hdc [I]
270 * lpRect [I]
271 * uFlags [I]
273 * RETURNS
274 * Success:
275 * Failure:
278 BOOL WINAPI
279 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
281 return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
285 /***********************************************************************
286 * DrawCaptionTempA (USER32.@)
288 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
289 HICON hIcon, LPCSTR str, UINT uFlags)
291 LPWSTR strW;
292 INT len;
293 BOOL ret = FALSE;
295 if (!(uFlags & DC_TEXT) || !str)
296 return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
298 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
299 if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
301 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
302 ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
303 HeapFree( GetProcessHeap (), 0, strW );
305 return ret;
309 /***********************************************************************
310 * DrawCaptionTempW (USER32.@)
312 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
313 HICON hIcon, LPCWSTR str, UINT uFlags)
315 RECT rc = *rect;
317 TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
318 hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
320 /* drawing background */
321 if (uFlags & DC_INBUTTON) {
322 FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
324 if (uFlags & DC_ACTIVE) {
325 HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
326 PatBlt (hdc, rc.left, rc.top,
327 rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
328 SelectObject (hdc, hbr);
331 else {
332 FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
333 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
337 /* drawing icon */
338 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
339 POINT pt;
341 pt.x = rc.left + 2;
342 pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
344 if (!hIcon) hIcon = NC_IconForWindow(hwnd);
345 DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
346 GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
347 rc.left += (rc.bottom - rc.top);
350 /* drawing text */
351 if (uFlags & DC_TEXT) {
352 HFONT hOldFont;
354 if (uFlags & DC_INBUTTON)
355 SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
356 else if (uFlags & DC_ACTIVE)
357 SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
358 else
359 SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
361 SetBkMode (hdc, TRANSPARENT);
363 if (hFont)
364 hOldFont = SelectObject (hdc, hFont);
365 else {
366 NONCLIENTMETRICSW nclm;
367 HFONT hNewFont;
368 nclm.cbSize = sizeof(NONCLIENTMETRICSW);
369 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
370 hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
371 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
372 hOldFont = SelectObject (hdc, hNewFont);
375 if (str)
376 DrawTextW (hdc, str, -1, &rc,
377 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
378 else {
379 WCHAR szText[128];
380 INT nLen;
381 nLen = GetWindowTextW (hwnd, szText, 128);
382 DrawTextW (hdc, szText, nLen, &rc,
383 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
386 if (hFont)
387 SelectObject (hdc, hOldFont);
388 else
389 DeleteObject (SelectObject (hdc, hOldFont));
392 /* drawing focus ??? */
393 if (uFlags & 0x2000)
394 FIXME("undocumented flag (0x2000)!\n");
396 return 0;
400 /***********************************************************************
401 * AdjustWindowRect (USER.102)
403 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
405 return AdjustWindowRectEx16( rect, style, menu, 0 );
409 /***********************************************************************
410 * AdjustWindowRect (USER32.@)
412 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
414 return AdjustWindowRectEx( rect, style, menu, 0 );
418 /***********************************************************************
419 * AdjustWindowRectEx (USER.454)
421 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
422 BOOL16 menu, DWORD exStyle )
424 RECT rect32;
425 BOOL ret;
427 CONV_RECT16TO32( rect, &rect32 );
428 ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
429 CONV_RECT32TO16( &rect32, rect );
430 return ret;
434 /***********************************************************************
435 * AdjustWindowRectEx (USER32.@)
437 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
439 /* Correct the window style */
440 style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
441 exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
442 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
443 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
445 TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
446 rect->left, rect->top, rect->right, rect->bottom,
447 style, menu, exStyle );
449 if (TWEAK_WineLook == WIN31_LOOK)
450 NC_AdjustRect( rect, style, menu, exStyle );
451 else
453 NC_AdjustRectOuter95( rect, style, menu, exStyle );
454 NC_AdjustRectInner95( rect, style, exStyle );
456 return TRUE;
460 /***********************************************************************
461 * NC_HandleNCCalcSize
463 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
465 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
467 RECT tmpRect = { 0, 0, 0, 0 };
468 LONG result = 0;
469 LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
470 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
471 LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
473 if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
474 if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
476 if (!IsIconic(hwnd))
478 if (TWEAK_WineLook == WIN31_LOOK)
479 NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
480 else
481 NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
483 winRect->left -= tmpRect.left;
484 winRect->top -= tmpRect.top;
485 winRect->right -= tmpRect.right;
486 winRect->bottom -= tmpRect.bottom;
488 if (!(style & WS_CHILD) && GetMenu(hwnd))
490 TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
491 hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
493 winRect->top +=
494 MENU_GetMenuBarHeight( hwnd,
495 winRect->right - winRect->left,
496 -tmpRect.left, -tmpRect.top ) + 1;
499 if (TWEAK_WineLook > WIN31_LOOK) {
500 SetRect(&tmpRect, 0, 0, 0, 0);
501 NC_AdjustRectInner95 (&tmpRect, style, exStyle);
502 winRect->left -= tmpRect.left;
503 winRect->top -= tmpRect.top;
504 winRect->right -= tmpRect.right;
505 winRect->bottom -= tmpRect.bottom;
508 if (winRect->top > winRect->bottom)
509 winRect->bottom = winRect->top;
511 if (winRect->left > winRect->right)
512 winRect->right = winRect->left;
514 return result;
518 /***********************************************************************
519 * NC_GetInsideRect
521 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
522 * but without the borders (if any).
523 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
525 void NC_GetInsideRect( HWND hwnd, RECT *rect )
527 WND * wndPtr = WIN_FindWndPtr( hwnd );
529 rect->top = rect->left = 0;
530 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
531 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
533 if (wndPtr->dwStyle & WS_ICONIC) goto END;
535 /* Remove frame from rectangle */
536 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
538 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
540 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
542 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
543 /* FIXME: this isn't in NC_AdjustRect? why not? */
544 if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
545 InflateRect( rect, -1, 0 );
547 else if (HAS_THINFRAME( wndPtr->dwStyle ))
549 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
552 /* We have additional border information if the window
553 * is a child (but not an MDI child) */
554 if (TWEAK_WineLook != WIN31_LOOK)
556 if ( (wndPtr->dwStyle & WS_CHILD) &&
557 ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
559 if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
560 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
561 if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
562 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
566 END:
567 WIN_ReleaseWndPtr(wndPtr);
568 return;
572 /***********************************************************************
573 * NC_DoNCHitTest
575 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
578 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
580 RECT rect;
582 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
584 GetWindowRect(wndPtr->hwndSelf, &rect );
585 if (!PtInRect( &rect, pt )) return HTNOWHERE;
587 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
589 /* Check borders */
590 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
592 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
593 if (!PtInRect( &rect, pt ))
595 /* Check top sizing border */
596 if (pt.y < rect.top)
598 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
599 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
600 return HTTOP;
602 /* Check bottom sizing border */
603 if (pt.y >= rect.bottom)
605 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
606 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
607 return HTBOTTOM;
609 /* Check left sizing border */
610 if (pt.x < rect.left)
612 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
613 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
614 return HTLEFT;
616 /* Check right sizing border */
617 if (pt.x >= rect.right)
619 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
620 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
621 return HTRIGHT;
625 else /* No thick frame */
627 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
628 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
629 else if (HAS_THINFRAME( wndPtr->dwStyle ))
630 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
631 if (!PtInRect( &rect, pt )) return HTBORDER;
634 /* Check caption */
636 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
638 rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
639 if (!PtInRect( &rect, pt ))
641 /* Check system menu */
642 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
643 rect.left += GetSystemMetrics(SM_CXSIZE);
644 if (pt.x <= rect.left) return HTSYSMENU;
646 /* Check maximize box */
647 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
648 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
650 if (pt.x >= rect.right) return HTMAXBUTTON;
651 /* Check minimize box */
652 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
653 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
654 if (pt.x >= rect.right) return HTMINBUTTON;
655 return HTCAPTION;
659 /* Check client area */
661 ScreenToClient( wndPtr->hwndSelf, &pt );
662 GetClientRect( wndPtr->hwndSelf, &rect );
663 if (PtInRect( &rect, pt )) return HTCLIENT;
665 /* Check vertical scroll bar */
667 if (wndPtr->dwStyle & WS_VSCROLL)
669 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
670 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
671 else
672 rect.right += GetSystemMetrics(SM_CXVSCROLL);
673 if (PtInRect( &rect, pt )) return HTVSCROLL;
676 /* Check horizontal scroll bar */
678 if (wndPtr->dwStyle & WS_HSCROLL)
680 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
681 if (PtInRect( &rect, pt ))
683 /* Check size box */
684 if ((wndPtr->dwStyle & WS_VSCROLL) &&
685 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
686 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
687 return HTSIZE;
688 return HTHSCROLL;
692 /* Check menu bar */
694 if (HAS_MENU(wndPtr))
696 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
697 return HTMENU;
700 /* Has to return HTNOWHERE if nothing was found
701 Could happen when a window has a customized non client area */
702 return HTNOWHERE;
706 /***********************************************************************
707 * NC_DoNCHitTest95
709 * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
711 * FIXME: Just a modified copy of the Win 3.1 version.
714 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
716 RECT rect;
718 TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
720 GetWindowRect(wndPtr->hwndSelf, &rect );
721 if (!PtInRect( &rect, pt )) return HTNOWHERE;
723 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
725 /* Check borders */
726 if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
728 InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
729 if (!PtInRect( &rect, pt ))
731 /* Check top sizing border */
732 if (pt.y < rect.top)
734 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
735 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
736 return HTTOP;
738 /* Check bottom sizing border */
739 if (pt.y >= rect.bottom)
741 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
742 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
743 return HTBOTTOM;
745 /* Check left sizing border */
746 if (pt.x < rect.left)
748 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
749 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
750 return HTLEFT;
752 /* Check right sizing border */
753 if (pt.x >= rect.right)
755 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
756 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
757 return HTRIGHT;
761 else /* No thick frame */
763 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
764 InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
765 else if (HAS_THINFRAME( wndPtr->dwStyle ))
766 InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
767 if (!PtInRect( &rect, pt )) return HTBORDER;
770 /* Check caption */
772 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
774 if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
775 rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
776 else
777 rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
778 if (!PtInRect( &rect, pt ))
780 /* Check system menu */
781 if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
783 if (NC_IconForWindow(wndPtr->hwndSelf))
784 rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
786 if (pt.x < rect.left) return HTSYSMENU;
788 /* Check close button */
789 if (wndPtr->dwStyle & WS_SYSMENU)
790 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
791 if (pt.x > rect.right) return HTCLOSE;
793 /* Check maximize box */
794 /* In win95 there is automatically a Maximize button when there is a minimize one*/
795 if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
796 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
797 if (pt.x > rect.right) return HTMAXBUTTON;
799 /* Check minimize box */
800 /* In win95 there is automatically a Maximize button when there is a Maximize one*/
801 if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
802 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
804 if (pt.x > rect.right) return HTMINBUTTON;
805 return HTCAPTION;
809 /* Check client area */
811 ScreenToClient( wndPtr->hwndSelf, &pt );
812 GetClientRect( wndPtr->hwndSelf, &rect );
813 if (PtInRect( &rect, pt )) return HTCLIENT;
815 /* Check vertical scroll bar */
817 if (wndPtr->dwStyle & WS_VSCROLL)
819 if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
820 rect.left -= GetSystemMetrics(SM_CXVSCROLL);
821 else
822 rect.right += GetSystemMetrics(SM_CXVSCROLL);
823 if (PtInRect( &rect, pt )) return HTVSCROLL;
826 /* Check horizontal scroll bar */
828 if (wndPtr->dwStyle & WS_HSCROLL)
830 rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
831 if (PtInRect( &rect, pt ))
833 /* Check size box */
834 if ((wndPtr->dwStyle & WS_VSCROLL) &&
835 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rect.left + GetSystemMetrics(SM_CXVSCROLL))) ||
836 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))))
837 return HTSIZE;
838 return HTHSCROLL;
842 /* Check menu bar */
844 if (HAS_MENU(wndPtr))
846 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
847 return HTMENU;
850 /* Has to return HTNOWHERE if nothing was found
851 Could happen when a window has a customized non client area */
852 return HTNOWHERE;
856 /***********************************************************************
857 * NC_HandleNCHitTest
859 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
861 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
863 LONG retvalue;
864 WND *wndPtr = WIN_FindWndPtr (hwnd);
866 if (!wndPtr)
867 return HTERROR;
869 if (TWEAK_WineLook == WIN31_LOOK)
870 retvalue = NC_DoNCHitTest (wndPtr, pt);
871 else
872 retvalue = NC_DoNCHitTest95 (wndPtr, pt);
873 WIN_ReleaseWndPtr(wndPtr);
874 return retvalue;
878 /***********************************************************************
879 * NC_DrawSysButton
881 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
883 RECT rect;
884 HDC hdcMem;
885 HBITMAP hbitmap;
887 NC_GetInsideRect( hwnd, &rect );
888 hdcMem = CreateCompatibleDC( hdc );
889 hbitmap = SelectObject( hdcMem, hbitmapClose );
890 BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
891 hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
892 down ? NOTSRCCOPY : SRCCOPY );
893 SelectObject( hdcMem, hbitmap );
894 DeleteDC( hdcMem );
898 /***********************************************************************
899 * NC_DrawMaxButton
901 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
903 RECT rect;
904 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
906 NC_GetInsideRect( hwnd, &rect );
907 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
908 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
909 rect.top += 1;
910 rect.right -= 1;
911 if (down) flags |= DFCS_PUSHED;
912 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
916 /***********************************************************************
917 * NC_DrawMinButton
919 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
921 RECT rect;
922 UINT flags = DFCS_CAPTIONMIN;
923 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
925 NC_GetInsideRect( hwnd, &rect );
926 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
927 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
928 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
929 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
930 rect.top += 1;
931 rect.right -= 1;
932 if (down) flags |= DFCS_PUSHED;
933 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
937 /******************************************************************************
939 * void NC_DrawSysButton95(
940 * HWND hwnd,
941 * HDC hdc,
942 * BOOL down )
944 * Draws the Win95 system icon.
946 * Revision history
947 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
948 * Original implementation from NC_DrawSysButton source.
949 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
950 * Fixed most bugs.
952 *****************************************************************************/
954 BOOL
955 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
957 HICON hIcon = NC_IconForWindow( hwnd );
959 if (hIcon)
961 RECT rect;
962 NC_GetInsideRect( hwnd, &rect );
963 DrawIconEx (hdc, rect.left + 1, rect.top + 1, hIcon,
964 GetSystemMetrics(SM_CXSIZE) - 1,
965 GetSystemMetrics(SM_CYSIZE) - 1, 0, 0, DI_NORMAL);
967 return (hIcon != 0);
971 /******************************************************************************
973 * void NC_DrawCloseButton95(
974 * HWND hwnd,
975 * HDC hdc,
976 * BOOL down,
977 * BOOL bGrayed )
979 * Draws the Win95 close button.
981 * If bGrayed is true, then draw a disabled Close button
983 * Revision history
984 * 11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
985 * Original implementation from NC_DrawSysButton95 source.
987 *****************************************************************************/
989 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
991 RECT rect;
993 NC_GetInsideRect( hwnd, &rect );
995 /* A tool window has a smaller Close button */
996 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
998 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
999 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
1000 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
1002 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
1003 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
1004 rect.bottom = rect.top + iBmpHeight;
1005 rect.right = rect.left + iBmpWidth;
1007 else
1009 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
1010 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1011 rect.top += 2;
1012 rect.right -= 2;
1014 DrawFrameControl( hdc, &rect, DFC_CAPTION,
1015 (DFCS_CAPTIONCLOSE |
1016 (down ? DFCS_PUSHED : 0) |
1017 (bGrayed ? DFCS_INACTIVE : 0)) );
1020 /******************************************************************************
1021 * NC_DrawMaxButton95
1023 * Draws the maximize button for Win95 style windows.
1024 * If bGrayed is true, then draw a disabled Maximize button
1026 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1028 RECT rect;
1029 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1031 NC_GetInsideRect( hwnd, &rect );
1032 if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1033 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1034 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1035 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1036 rect.top += 2;
1037 rect.right -= 2;
1038 if (down) flags |= DFCS_PUSHED;
1039 if (bGrayed) flags |= DFCS_INACTIVE;
1040 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1043 /******************************************************************************
1044 * NC_DrawMinButton95
1046 * Draws the minimize button for Win95 style windows.
1047 * If bGrayed is true, then draw a disabled Minimize button
1049 static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
1051 RECT rect;
1052 UINT flags = DFCS_CAPTIONMIN;
1053 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1055 NC_GetInsideRect( hwnd, &rect );
1056 if (style & WS_SYSMENU)
1057 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1058 if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1059 rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1060 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1061 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1062 rect.top += 2;
1063 rect.right -= 2;
1064 if (down) flags |= DFCS_PUSHED;
1065 if (bGrayed) flags |= DFCS_INACTIVE;
1066 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1069 /***********************************************************************
1070 * NC_DrawFrame
1072 * Draw a window frame inside the given rectangle, and update the rectangle.
1073 * The correct pen for the frame must be selected in the DC.
1075 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1076 BOOL active )
1078 INT width, height;
1080 if (TWEAK_WineLook != WIN31_LOOK)
1081 ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1083 if (dlgFrame)
1085 width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1086 height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1087 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1088 COLOR_INACTIVECAPTION) );
1090 else
1092 width = GetSystemMetrics(SM_CXFRAME) - 2;
1093 height = GetSystemMetrics(SM_CYFRAME) - 2;
1094 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1095 COLOR_INACTIVEBORDER) );
1098 /* Draw frame */
1099 PatBlt( hdc, rect->left, rect->top,
1100 rect->right - rect->left, height, PATCOPY );
1101 PatBlt( hdc, rect->left, rect->top,
1102 width, rect->bottom - rect->top, PATCOPY );
1103 PatBlt( hdc, rect->left, rect->bottom - 1,
1104 rect->right - rect->left, -height, PATCOPY );
1105 PatBlt( hdc, rect->right - 1, rect->top,
1106 -width, rect->bottom - rect->top, PATCOPY );
1108 if (dlgFrame)
1110 InflateRect( rect, -width, -height );
1112 else
1114 INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1115 INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1117 /* Draw inner rectangle */
1119 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1120 Rectangle( hdc, rect->left + width, rect->top + height,
1121 rect->right - width , rect->bottom - height );
1123 /* Draw the decorations */
1125 MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1126 LineTo( hdc, rect->left + width, rect->top + decYOff );
1127 MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1128 LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1129 MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1130 LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1131 MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1132 LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1134 MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1135 LineTo( hdc, rect->left + decXOff, rect->top + height);
1136 MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1137 LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1138 MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1139 LineTo( hdc, rect->right - decXOff, rect->top + height );
1140 MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1141 LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1143 InflateRect( rect, -width - 1, -height - 1 );
1148 /******************************************************************************
1150 * void NC_DrawFrame95(
1151 * HDC hdc,
1152 * RECT *rect,
1153 * BOOL active,
1154 * DWORD style,
1155 * DWORD exStyle )
1157 * Draw a window frame inside the given rectangle, and update the rectangle.
1159 * Bugs
1160 * Many. First, just what IS a frame in Win95? Note that the 3D look
1161 * on the outer edge is handled by NC_DoNCPaint95. As is the inner
1162 * edge. The inner rectangle just inside the frame is handled by the
1163 * Caption code.
1165 * In short, for most people, this function should be a nop (unless
1166 * you LIKE thick borders in Win95/NT4.0 -- I've been working with
1167 * them lately, but just to get this code right). Even so, it doesn't
1168 * appear to be so. It's being worked on...
1170 * Revision history
1171 * 06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1172 * Original implementation (based on NC_DrawFrame)
1173 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1174 * Some minor fixes.
1175 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1176 * Fixed a fix or something.
1178 *****************************************************************************/
1180 static void NC_DrawFrame95(
1181 HDC hdc,
1182 RECT *rect,
1183 BOOL active,
1184 DWORD style,
1185 DWORD exStyle)
1187 INT width, height;
1189 /* Firstly the "thick" frame */
1190 if (style & WS_THICKFRAME)
1192 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1193 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1195 SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1196 COLOR_INACTIVEBORDER) );
1197 /* Draw frame */
1198 PatBlt( hdc, rect->left, rect->top,
1199 rect->right - rect->left, height, PATCOPY );
1200 PatBlt( hdc, rect->left, rect->top,
1201 width, rect->bottom - rect->top, PATCOPY );
1202 PatBlt( hdc, rect->left, rect->bottom - 1,
1203 rect->right - rect->left, -height, PATCOPY );
1204 PatBlt( hdc, rect->right - 1, rect->top,
1205 -width, rect->bottom - rect->top, PATCOPY );
1207 InflateRect( rect, -width, -height );
1210 /* Now the other bit of the frame */
1211 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1212 (exStyle & WS_EX_DLGMODALFRAME))
1214 width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1215 height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1216 /* This should give a value of 1 that should also work for a border */
1218 SelectObject( hdc, GetSysColorBrush(
1219 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1220 COLOR_3DFACE :
1221 (exStyle & WS_EX_STATICEDGE) ?
1222 COLOR_WINDOWFRAME :
1223 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1224 COLOR_3DFACE :
1225 /* else */
1226 COLOR_WINDOWFRAME));
1228 /* Draw frame */
1229 PatBlt( hdc, rect->left, rect->top,
1230 rect->right - rect->left, height, PATCOPY );
1231 PatBlt( hdc, rect->left, rect->top,
1232 width, rect->bottom - rect->top, PATCOPY );
1233 PatBlt( hdc, rect->left, rect->bottom - 1,
1234 rect->right - rect->left, -height, PATCOPY );
1235 PatBlt( hdc, rect->right - 1, rect->top,
1236 -width, rect->bottom - rect->top, PATCOPY );
1238 InflateRect( rect, -width, -height );
1243 /***********************************************************************
1244 * NC_DrawCaption
1246 * Draw the window caption.
1247 * The correct pen for the window frame must be selected in the DC.
1249 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1250 DWORD style, BOOL active )
1252 RECT r = *rect;
1253 char buffer[256];
1255 if (!hbitmapClose)
1257 if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1260 if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1262 HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1263 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1264 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1265 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1266 r.left++;
1267 r.right--;
1268 SelectObject( hdc, hbrushOld );
1270 MoveToEx( hdc, r.left, r.bottom, NULL );
1271 LineTo( hdc, r.right, r.bottom );
1273 if (style & WS_SYSMENU)
1275 NC_DrawSysButton( hwnd, hdc, FALSE );
1276 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1277 MoveToEx( hdc, r.left - 1, r.top, NULL );
1278 LineTo( hdc, r.left - 1, r.bottom );
1280 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1281 if (style & WS_MAXIMIZEBOX)
1283 NC_DrawMaxButton( hwnd, hdc, FALSE );
1284 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1286 if (style & WS_MINIMIZEBOX)
1288 NC_DrawMinButton( hwnd, hdc, FALSE );
1289 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1292 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1294 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1295 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1296 SetBkMode( hdc, TRANSPARENT );
1297 DrawTextA( hdc, buffer, -1, &r,
1298 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1303 /******************************************************************************
1305 * NC_DrawCaption95(
1306 * HDC hdc,
1307 * RECT *rect,
1308 * HWND hwnd,
1309 * DWORD style,
1310 * BOOL active )
1312 * Draw the window caption for Win95 style windows.
1313 * The correct pen for the window frame must be selected in the DC.
1315 * Bugs
1316 * Hey, a function that finally works! Well, almost.
1317 * It's being worked on.
1319 * Revision history
1320 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1321 * Original implementation.
1322 * 02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1323 * Some minor fixes.
1325 *****************************************************************************/
1327 static void NC_DrawCaption95(
1328 HDC hdc,
1329 RECT *rect,
1330 HWND hwnd,
1331 DWORD style,
1332 DWORD exStyle,
1333 BOOL active )
1335 RECT r = *rect;
1336 char buffer[256];
1337 HPEN hPrevPen;
1338 HMENU hSysMenu;
1340 hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
1341 ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1342 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1343 COLOR_WINDOWFRAME : COLOR_3DFACE) );
1344 MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1345 LineTo( hdc, r.right, r.bottom - 1 );
1346 SelectObject( hdc, hPrevPen );
1347 r.bottom--;
1349 FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1350 COLOR_INACTIVECAPTION) );
1352 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1353 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1354 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1357 if (style & WS_SYSMENU)
1359 UINT state;
1361 /* Go get the sysmenu */
1362 hSysMenu = GetSystemMenu(hwnd, FALSE);
1363 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1365 /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1366 NC_DrawCloseButton95 (hwnd, hdc, FALSE,
1367 ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1368 r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1370 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1372 /* In win95 the two buttons are always there */
1373 /* But if the menu item is not in the menu they're disabled*/
1375 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1376 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1378 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
1379 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1383 if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1384 NONCLIENTMETRICSA nclm;
1385 HFONT hFont, hOldFont;
1386 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1387 SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1388 if (exStyle & WS_EX_TOOLWINDOW)
1389 hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1390 else
1391 hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1392 hOldFont = SelectObject (hdc, hFont);
1393 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1394 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1395 SetBkMode( hdc, TRANSPARENT );
1396 r.left += 2;
1397 DrawTextA( hdc, buffer, -1, &r,
1398 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1399 DeleteObject (SelectObject (hdc, hOldFont));
1405 /***********************************************************************
1406 * NC_DoNCPaint
1408 * Paint the non-client area. clip is currently unused.
1410 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1412 HDC hdc;
1413 RECT rect;
1414 BOOL active;
1415 WND *wndPtr;
1416 DWORD dwStyle, dwExStyle;
1417 WORD flags;
1418 RECT rectClient, rectWindow;
1419 int has_menu;
1421 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1422 has_menu = HAS_MENU(wndPtr);
1423 dwStyle = wndPtr->dwStyle;
1424 dwExStyle = wndPtr->dwExStyle;
1425 flags = wndPtr->flags;
1426 rectClient = wndPtr->rectClient;
1427 rectWindow = wndPtr->rectWindow;
1428 WIN_ReleasePtr( wndPtr );
1430 if ( dwStyle & WS_MINIMIZE ||
1431 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1433 active = flags & WIN_NCACTIVATED;
1435 TRACE("%p %d\n", hwnd, active );
1437 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1438 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1440 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1441 rectClient.top-rectWindow.top,
1442 rectClient.right-rectWindow.left,
1443 rectClient.bottom-rectWindow.top )
1444 == NULLREGION)
1446 ReleaseDC( hwnd, hdc );
1447 return;
1450 rect.top = rect.left = 0;
1451 rect.right = rectWindow.right - rectWindow.left;
1452 rect.bottom = rectWindow.bottom - rectWindow.top;
1454 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1456 if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1458 SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1459 Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1460 InflateRect( &rect, -1, -1 );
1463 if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1464 NC_DrawFrame(hdc, &rect, FALSE, active );
1465 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1466 NC_DrawFrame( hdc, &rect, TRUE, active );
1468 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1470 RECT r = rect;
1471 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1472 rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1473 NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1476 if (has_menu)
1478 RECT r = rect;
1479 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); /* default height */
1480 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1483 /* Draw the scroll-bars */
1485 if (dwStyle & WS_VSCROLL)
1486 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1487 if (dwStyle & WS_HSCROLL)
1488 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1490 /* Draw the "size-box" */
1492 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1494 RECT r = rect;
1495 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1496 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1497 else
1498 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1499 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1500 if(wndPtr->dwStyle & WS_BORDER) {
1501 r.left++;
1502 r.top++;
1504 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1507 ReleaseDC( hwnd, hdc );
1511 /******************************************************************************
1513 * void NC_DoNCPaint95(
1514 * HWND hwnd,
1515 * HRGN clip,
1516 * BOOL suppress_menupaint )
1518 * Paint the non-client area for Win95 windows. The clip region is
1519 * currently ignored.
1521 * Bugs
1522 * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1523 * misc/tweak.c controls/menu.c # :-)
1525 * Revision history
1526 * 03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1527 * Original implementation
1528 * 10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1529 * Fixed some bugs.
1530 * 29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1531 * Streamlined window style checks.
1533 *****************************************************************************/
1535 static void NC_DoNCPaint95(
1536 HWND hwnd,
1537 HRGN clip,
1538 BOOL suppress_menupaint )
1540 HDC hdc;
1541 RECT rfuzz, rect, rectClip;
1542 BOOL active;
1543 WND *wndPtr;
1544 DWORD dwStyle, dwExStyle;
1545 WORD flags;
1546 RECT rectClient, rectWindow;
1547 int has_menu;
1549 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1550 has_menu = HAS_MENU(wndPtr);
1551 dwStyle = wndPtr->dwStyle;
1552 dwExStyle = wndPtr->dwExStyle;
1553 flags = wndPtr->flags;
1554 rectClient = wndPtr->rectClient;
1555 rectWindow = wndPtr->rectWindow;
1556 WIN_ReleasePtr( wndPtr );
1558 if ( dwStyle & WS_MINIMIZE ||
1559 !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1561 active = flags & WIN_NCACTIVATED;
1563 TRACE("%p %d\n", hwnd, active );
1565 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1566 the call to GetDCEx implying that it is allowed not to use it either.
1567 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1568 will cause clipRgn to be deleted after ReleaseDC().
1569 Now, how is the "system" supposed to tell what happened?
1572 if (!(hdc = GetDCEx( hwnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1573 ((clip > (HRGN)1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1576 if (ExcludeVisRect16( HDC_16(hdc), rectClient.left-rectWindow.left,
1577 rectClient.top-rectWindow.top,
1578 rectClient.right-rectWindow.left,
1579 rectClient.bottom-rectWindow.top )
1580 == NULLREGION)
1582 ReleaseDC( hwnd, hdc );
1583 return;
1586 rect.top = rect.left = 0;
1587 rect.right = rectWindow.right - rectWindow.left;
1588 rect.bottom = rectWindow.bottom - rectWindow.top;
1590 if( clip > (HRGN)1 )
1591 GetRgnBox( clip, &rectClip );
1592 else
1594 clip = 0;
1595 rectClip = rect;
1598 SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1600 if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1601 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1603 else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1604 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1607 NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1609 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1611 RECT r = rect;
1612 if (dwExStyle & WS_EX_TOOLWINDOW) {
1613 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1614 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1616 else {
1617 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1618 rect.top += GetSystemMetrics(SM_CYCAPTION);
1620 if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1621 NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1622 dwExStyle, active);
1625 if (has_menu)
1627 RECT r = rect;
1628 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1630 TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
1631 r.left, r.top, r.right, r.bottom);
1633 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1636 TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
1637 rect.left, rect.top, rect.right, rect.bottom );
1639 if (dwExStyle & WS_EX_CLIENTEDGE)
1640 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1642 /* Draw the scroll-bars */
1644 if (dwStyle & WS_VSCROLL)
1645 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1646 if (dwStyle & WS_HSCROLL)
1647 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1649 /* Draw the "size-box" */
1650 if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1652 RECT r = rect;
1653 if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1654 r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1655 else
1656 r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1657 r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1658 FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1661 ReleaseDC( hwnd, hdc );
1667 /***********************************************************************
1668 * NC_HandleNCPaint
1670 * Handle a WM_NCPAINT message. Called from DefWindowProc().
1672 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1674 DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1676 if( dwStyle & WS_VISIBLE )
1678 if( dwStyle & WS_MINIMIZE )
1679 WINPOS_RedrawIconTitle( hwnd );
1680 else if (TWEAK_WineLook == WIN31_LOOK)
1681 NC_DoNCPaint( hwnd, clip, FALSE );
1682 else
1683 NC_DoNCPaint95( hwnd, clip, FALSE );
1685 return 0;
1689 /***********************************************************************
1690 * NC_HandleNCActivate
1692 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1694 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1696 WND* wndPtr = WIN_FindWndPtr( hwnd );
1698 /* Lotus Notes draws menu descriptions in the caption of its main
1699 * window. When it wants to restore original "system" view, it just
1700 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1701 * attempt to minimize redrawings lead to a not restored caption.
1703 if (wndPtr)
1705 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1706 else wndPtr->flags &= ~WIN_NCACTIVATED;
1707 WIN_ReleaseWndPtr(wndPtr);
1709 if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1710 else if (TWEAK_WineLook == WIN31_LOOK)
1711 NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1712 else
1713 NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1715 return TRUE;
1719 /***********************************************************************
1720 * NC_HandleSetCursor
1722 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1724 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1726 hwnd = WIN_GetFullHandle( (HWND)wParam );
1728 switch(LOWORD(lParam))
1730 case HTERROR:
1732 WORD msg = HIWORD( lParam );
1733 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1734 (msg == WM_RBUTTONDOWN))
1735 MessageBeep(0);
1737 break;
1739 case HTCLIENT:
1741 HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
1742 if(hCursor) {
1743 SetCursor(hCursor);
1744 return TRUE;
1746 return FALSE;
1749 case HTLEFT:
1750 case HTRIGHT:
1751 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1753 case HTTOP:
1754 case HTBOTTOM:
1755 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1757 case HTTOPLEFT:
1758 case HTBOTTOMRIGHT:
1759 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1761 case HTTOPRIGHT:
1762 case HTBOTTOMLEFT:
1763 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1766 /* Default cursor: arrow */
1767 return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1770 /***********************************************************************
1771 * NC_GetSysPopupPos
1773 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1775 if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1776 else
1778 WND *wndPtr = WIN_FindWndPtr( hwnd );
1779 if (!wndPtr) return;
1781 NC_GetInsideRect( hwnd, rect );
1782 OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1783 if (wndPtr->dwStyle & WS_CHILD)
1784 ClientToScreen( GetParent(hwnd), (POINT *)rect );
1785 if (TWEAK_WineLook == WIN31_LOOK) {
1786 rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1787 rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1789 else {
1790 rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1791 rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1793 WIN_ReleaseWndPtr( wndPtr );
1797 /***********************************************************************
1798 * NC_TrackMinMaxBox95
1800 * Track a mouse button press on the minimize or maximize box.
1802 * The big difference between 3.1 and 95 is the disabled button state.
1803 * In win95 the system button can be disabled, so it can ignore the mouse
1804 * event.
1807 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1809 MSG msg;
1810 HDC hdc = GetWindowDC( hwnd );
1811 BOOL pressed = TRUE;
1812 UINT state;
1813 DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1814 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1816 void (*paintButton)(HWND, HDC, BOOL, BOOL);
1818 if (wParam == HTMINBUTTON)
1820 /* If the style is not present, do nothing */
1821 if (!(wndStyle & WS_MINIMIZEBOX))
1822 return;
1824 /* Check if the sysmenu item for minimize is there */
1825 state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1827 paintButton = &NC_DrawMinButton95;
1829 else
1831 /* If the style is not present, do nothing */
1832 if (!(wndStyle & WS_MAXIMIZEBOX))
1833 return;
1835 /* Check if the sysmenu item for maximize is there */
1836 state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1838 paintButton = &NC_DrawMaxButton95;
1841 SetCapture( hwnd );
1843 (*paintButton)( hwnd, hdc, TRUE, FALSE);
1845 while(1)
1847 BOOL oldstate = pressed;
1849 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1850 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1852 if(msg.message == WM_LBUTTONUP)
1853 break;
1855 if(msg.message != WM_MOUSEMOVE)
1856 continue;
1858 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1859 if (pressed != oldstate)
1860 (*paintButton)( hwnd, hdc, pressed, FALSE);
1863 if(pressed)
1864 (*paintButton)(hwnd, hdc, FALSE, FALSE);
1866 ReleaseCapture();
1867 ReleaseDC( hwnd, hdc );
1869 /* If the item minimize or maximize of the sysmenu are not there */
1870 /* or if the style is not present, do nothing */
1871 if ((!pressed) || (state == 0xFFFFFFFF))
1872 return;
1874 if (wParam == HTMINBUTTON)
1875 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1876 else
1877 SendMessageA( hwnd, WM_SYSCOMMAND,
1878 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1881 /***********************************************************************
1882 * NC_TrackMinMaxBox
1884 * Track a mouse button press on the minimize or maximize box.
1886 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1888 MSG msg;
1889 HDC hdc = GetWindowDC( hwnd );
1890 BOOL pressed = TRUE;
1891 void (*paintButton)(HWND, HDC, BOOL);
1893 SetCapture( hwnd );
1895 if (wParam == HTMINBUTTON)
1896 paintButton = &NC_DrawMinButton;
1897 else
1898 paintButton = &NC_DrawMaxButton;
1900 (*paintButton)( hwnd, hdc, TRUE);
1902 while(1)
1904 BOOL oldstate = pressed;
1906 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1907 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1909 if(msg.message == WM_LBUTTONUP)
1910 break;
1912 if(msg.message != WM_MOUSEMOVE)
1913 continue;
1915 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1916 if (pressed != oldstate)
1917 (*paintButton)( hwnd, hdc, pressed);
1920 if(pressed)
1921 (*paintButton)( hwnd, hdc, FALSE);
1923 ReleaseCapture();
1924 ReleaseDC( hwnd, hdc );
1926 if (!pressed) return;
1928 if (wParam == HTMINBUTTON)
1929 SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1930 else
1931 SendMessageA( hwnd, WM_SYSCOMMAND,
1932 IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1936 /***********************************************************************
1937 * NC_TrackCloseButton95
1939 * Track a mouse button press on the Win95 close button.
1941 static void
1942 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1944 MSG msg;
1945 HDC hdc;
1946 BOOL pressed = TRUE;
1947 HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1948 UINT state;
1950 if(hSysMenu == 0)
1951 return;
1953 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1955 /* If the item close of the sysmenu is disabled or not there do nothing */
1956 if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1957 return;
1959 hdc = GetWindowDC( hwnd );
1961 SetCapture( hwnd );
1963 NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1965 while(1)
1967 BOOL oldstate = pressed;
1969 if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1970 if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1972 if(msg.message == WM_LBUTTONUP)
1973 break;
1975 if(msg.message != WM_MOUSEMOVE)
1976 continue;
1978 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1979 if (pressed != oldstate)
1980 NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1983 if(pressed)
1984 NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1986 ReleaseCapture();
1987 ReleaseDC( hwnd, hdc );
1988 if (!pressed) return;
1990 SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1994 /***********************************************************************
1995 * NC_TrackScrollBar
1997 * Track a mouse button press on the horizontal or vertical scroll-bar.
1999 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2001 INT scrollbar;
2003 if ((wParam & 0xfff0) == SC_HSCROLL)
2005 if ((wParam & 0x0f) != HTHSCROLL) return;
2006 scrollbar = SB_HORZ;
2008 else /* SC_VSCROLL */
2010 if ((wParam & 0x0f) != HTVSCROLL) return;
2011 scrollbar = SB_VERT;
2013 SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
2017 /***********************************************************************
2018 * NC_HandleNCLButtonDown
2020 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2022 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
2024 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
2026 switch(wParam) /* Hit test */
2028 case HTCAPTION:
2030 HWND top = GetAncestor( hwnd, GA_ROOT );
2032 if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
2033 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2034 break;
2037 case HTSYSMENU:
2038 if( style & WS_SYSMENU )
2040 if( !(style & WS_MINIMIZE) )
2042 HDC hDC = GetWindowDC(hwnd);
2043 if (TWEAK_WineLook == WIN31_LOOK)
2044 NC_DrawSysButton( hwnd, hDC, TRUE );
2045 else
2046 NC_DrawSysButton95( hwnd, hDC, TRUE );
2047 ReleaseDC( hwnd, hDC );
2049 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2051 break;
2053 case HTMENU:
2054 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2055 break;
2057 case HTHSCROLL:
2058 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2059 break;
2061 case HTVSCROLL:
2062 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2063 break;
2065 case HTMINBUTTON:
2066 case HTMAXBUTTON:
2067 if (TWEAK_WineLook == WIN31_LOOK)
2068 NC_TrackMinMaxBox( hwnd, wParam );
2069 else
2070 NC_TrackMinMaxBox95( hwnd, wParam );
2071 break;
2073 case HTCLOSE:
2074 if (TWEAK_WineLook >= WIN95_LOOK)
2075 NC_TrackCloseButton95 (hwnd, wParam);
2076 break;
2078 case HTLEFT:
2079 case HTRIGHT:
2080 case HTTOP:
2081 case HTTOPLEFT:
2082 case HTTOPRIGHT:
2083 case HTBOTTOM:
2084 case HTBOTTOMLEFT:
2085 case HTBOTTOMRIGHT:
2086 /* Old comment:
2087 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
2088 * This was previously done by setting wParam=SC_SIZE + wParam - 2
2090 /* But that is not what WinNT does. Instead it sends this. This
2091 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
2092 * SC_MOUSEMENU into wParam.
2094 SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
2095 break;
2097 case HTBORDER:
2098 break;
2100 return 0;
2104 /***********************************************************************
2105 * NC_HandleNCLButtonDblClk
2107 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2109 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2112 * if this is an icon, send a restore since we are handling
2113 * a double click
2115 if (IsIconic(hwnd))
2117 SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2118 return 0;
2121 switch(wParam) /* Hit test */
2123 case HTCAPTION:
2124 /* stop processing if WS_MAXIMIZEBOX is missing */
2125 if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2126 SendMessageW( hwnd, WM_SYSCOMMAND,
2127 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2128 break;
2130 case HTSYSMENU:
2131 if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2132 SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2133 break;
2135 case HTHSCROLL:
2136 SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2137 break;
2139 case HTVSCROLL:
2140 SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2141 break;
2143 return 0;
2147 /***********************************************************************
2148 * NC_HandleSysCommand
2150 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2152 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2154 TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2156 switch (wParam & 0xfff0)
2158 case SC_SIZE:
2159 case SC_MOVE:
2160 if (USER_Driver.pSysCommandSizeMove)
2161 USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2162 break;
2164 case SC_MINIMIZE:
2165 if (hwnd == GetForegroundWindow())
2166 ShowOwnedPopups(hwnd,FALSE);
2167 ShowWindow( hwnd, SW_MINIMIZE );
2168 break;
2170 case SC_MAXIMIZE:
2171 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2172 ShowOwnedPopups(hwnd,TRUE);
2173 ShowWindow( hwnd, SW_MAXIMIZE );
2174 break;
2176 case SC_RESTORE:
2177 if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2178 ShowOwnedPopups(hwnd,TRUE);
2179 ShowWindow( hwnd, SW_RESTORE );
2180 break;
2182 case SC_CLOSE:
2183 return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2185 case SC_VSCROLL:
2186 case SC_HSCROLL:
2188 POINT pt;
2189 pt.x = (short)LOWORD(lParam);
2190 pt.y = (short)HIWORD(lParam);
2191 NC_TrackScrollBar( hwnd, wParam, pt );
2193 break;
2195 case SC_MOUSEMENU:
2197 POINT pt;
2198 pt.x = (short)LOWORD(lParam);
2199 pt.y = (short)HIWORD(lParam);
2200 MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2202 break;
2204 case SC_KEYMENU:
2205 MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
2206 break;
2208 case SC_TASKLIST:
2209 WinExec( "taskman.exe", SW_SHOWNORMAL );
2210 break;
2212 case SC_SCREENSAVE:
2213 if (wParam == SC_ABOUTWINE)
2215 HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2216 if (hmodule)
2218 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2219 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
2220 FreeLibrary( hmodule );
2223 else
2224 if (wParam == SC_PUTMARK)
2225 TRACE_(shell)("Mark requested by user\n");
2226 break;
2228 case SC_HOTKEY:
2229 case SC_ARRANGE:
2230 case SC_NEXTWINDOW:
2231 case SC_PREVWINDOW:
2232 FIXME("unimplemented!\n");
2233 break;
2235 return 0;
2238 /*************************************************************
2239 * NC_DrawGrayButton
2241 * Stub for the grayed button of the caption
2243 *************************************************************/
2245 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2247 HBITMAP hMaskBmp;
2248 HDC hdcMask;
2249 HBRUSH hOldBrush;
2251 hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2253 if(hMaskBmp == 0)
2254 return FALSE;
2256 hdcMask = CreateCompatibleDC (0);
2257 SelectObject (hdcMask, hMaskBmp);
2259 /* Draw the grayed bitmap using the mask */
2260 hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
2261 BitBlt (hdc, x, y, 12, 10,
2262 hdcMask, 0, 0, 0xB8074A);
2264 /* Clean up */
2265 SelectObject (hdc, hOldBrush);
2266 DeleteObject(hMaskBmp);
2267 DeleteDC (hdcMask);
2269 return TRUE;
2272 /***********************************************************************
2273 * GetTitleBarInfo (USER32.@)
2274 * TODO: Handle STATE_SYSTEM_PRESSED
2276 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
2277 DWORD dwStyle;
2278 DWORD dwExStyle;
2279 RECT wndRect;
2281 TRACE("(%p %p)\n", hwnd, tbi);
2283 if(tbi->cbSize != sizeof(TITLEBARINFO)) {
2284 TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
2285 SetLastError(ERROR_INVALID_PARAMETER);
2286 return FALSE;
2288 dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
2289 dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
2290 NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
2292 GetWindowRect(hwnd, &wndRect);
2294 tbi->rcTitleBar.top += wndRect.top;
2295 tbi->rcTitleBar.left += wndRect.left;
2296 tbi->rcTitleBar.right += wndRect.left;
2298 tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
2299 if(dwExStyle & WS_EX_TOOLWINDOW)
2300 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
2301 else {
2302 tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
2303 tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
2306 ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
2307 /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
2308 * Under XP it seems to
2310 tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
2311 if(dwStyle & WS_CAPTION) {
2312 tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
2313 if(dwStyle & WS_SYSMENU) {
2314 if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
2315 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
2316 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
2318 else {
2319 if(!(dwStyle & WS_MINIMIZEBOX))
2320 tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
2321 if(!(dwStyle & WS_MAXIMIZEBOX))
2322 tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
2324 if(!(dwExStyle & WS_EX_CONTEXTHELP))
2325 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
2326 if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
2327 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
2329 else {
2330 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
2331 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
2332 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
2333 tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
2336 else
2337 tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
2338 return TRUE;