2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
11 #include "sysmetrics.h"
19 #include "nonclient.h"
21 #include "selectors.h"
23 /* #define DEBUG_NONCLIENT */
27 static HBITMAP hbitmapClose = 0;
28 static HBITMAP hbitmapMinimize = 0;
29 static HBITMAP hbitmapMinimizeD = 0;
30 static HBITMAP hbitmapMaximize = 0;
31 static HBITMAP hbitmapMaximizeD = 0;
32 static HBITMAP hbitmapRestore = 0;
33 static HBITMAP hbitmapRestoreD = 0;
35 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
36 extern BOOL AboutWine_Proc( HWND hDlg, WORD msg, WORD wParam, LONG lParam );
38 /* Some useful macros */
39 #define HAS_DLGFRAME(style,exStyle) \
40 (((exStyle) & WS_EX_DLGMODALFRAME) || \
41 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
43 #define HAS_THICKFRAME(style) \
44 (((style) & WS_THICKFRAME) && \
45 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
49 #define ON_LEFT_BORDER(hit) \
50 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
51 #define ON_RIGHT_BORDER(hit) \
52 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
53 #define ON_TOP_BORDER(hit) \
54 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
55 #define ON_BOTTOM_BORDER(hit) \
56 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
58 /***********************************************************************
61 * Compute the size of the window rectangle from the size of the
64 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
66 if (style & WS_ICONIC) return; /* Nothing to change for an icon */
67 if (HAS_DLGFRAME( style, exStyle ))
68 InflateRect( rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
71 if (HAS_THICKFRAME(style))
72 InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
73 if (style & WS_BORDER)
74 InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER );
77 if ((style & WS_CAPTION) == WS_CAPTION)
78 rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
79 if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
81 if (style & WS_VSCROLL) rect->right += SYSMETRICS_CXVSCROLL;
82 if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
86 /***********************************************************************
87 * AdjustWindowRect (USER.102)
89 void AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
91 AdjustWindowRectEx( rect, style, menu, 0 );
95 /***********************************************************************
96 * AdjustWindowRectEx (USER.454)
98 void AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
100 /* Correct the window style */
102 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
104 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
106 dprintf_nonclient(stddeb, "AdjustWindowRectEx: (%d,%d)-(%d,%d) %08lx %d %08lx\n",
107 rect->left, rect->top, rect->right, rect->bottom, style, menu, exStyle );
109 NC_AdjustRect( rect, style, menu, exStyle );
113 /*******************************************************************
116 * Get the minimized and maximized information for a window.
118 void NC_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
119 POINT *minTrack, POINT *maxTrack )
122 MINMAXINFO MinMax, *pMinMax;
124 WND *wndPtr = WIN_FindWndPtr( hwnd );
126 /* Compute default values */
128 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
129 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
130 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
131 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
132 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
133 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
135 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
137 xinc = SYSMETRICS_CXDLGFRAME;
138 yinc = SYSMETRICS_CYDLGFRAME;
143 if (HAS_THICKFRAME(wndPtr->dwStyle))
145 xinc += SYSMETRICS_CXFRAME;
146 yinc += SYSMETRICS_CYFRAME;
148 if (wndPtr->dwStyle & WS_BORDER)
150 xinc += SYSMETRICS_CXBORDER;
151 yinc += SYSMETRICS_CYBORDER;
154 MinMax.ptMaxSize.x += 2 * xinc;
155 MinMax.ptMaxSize.y += 2 * yinc;
157 if ((wndPtr->ptMaxPos.x != -1) || (wndPtr->ptMaxPos.y != -1))
158 MinMax.ptMaxPosition = wndPtr->ptMaxPos;
161 MinMax.ptMaxPosition.x = -xinc;
162 MinMax.ptMaxPosition.y = -yinc;
165 minmaxHandle = USER_HEAP_ALLOC( sizeof(MINMAXINFO) );
168 pMinMax = (MINMAXINFO *) USER_HEAP_LIN_ADDR( minmaxHandle );
169 memcpy( pMinMax, &MinMax, sizeof(MinMax) );
170 SendMessage( hwnd, WM_GETMINMAXINFO, 0,
171 USER_HEAP_SEG_ADDR(minmaxHandle) );
173 else pMinMax = &MinMax;
175 /* Some sanity checks */
177 pMinMax->ptMaxTrackSize.x = max( pMinMax->ptMaxTrackSize.x,
178 pMinMax->ptMinTrackSize.x );
179 pMinMax->ptMaxTrackSize.y = max( pMinMax->ptMaxTrackSize.y,
180 pMinMax->ptMinTrackSize.y );
182 if (maxSize) *maxSize = pMinMax->ptMaxSize;
183 if (maxPos) *maxPos = pMinMax->ptMaxPosition;
184 if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
185 if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
186 if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
190 /***********************************************************************
191 * NC_HandleNCCalcSize
193 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
195 LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params )
197 RECT tmpRect = { 0, 0, 0, 0 };
198 WND *wndPtr = WIN_FindWndPtr( hwnd );
200 if (!wndPtr) return 0;
201 NC_AdjustRect( &tmpRect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle );
202 params->rgrc[0].left -= tmpRect.left;
203 params->rgrc[0].top -= tmpRect.top;
204 params->rgrc[0].right -= tmpRect.right;
205 params->rgrc[0].bottom -= tmpRect.bottom;
207 if (HAS_MENU(wndPtr))
209 params->rgrc[0].top += MENU_GetMenuBarHeight( hwnd,
210 params->rgrc[0].right - params->rgrc[0].left,
211 -tmpRect.left, -tmpRect.top ) + 1;
217 /***********************************************************************
220 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
221 * but without the borders (if any).
222 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
224 void NC_GetInsideRect( HWND hwnd, RECT *rect )
226 WND * wndPtr = WIN_FindWndPtr( hwnd );
228 rect->top = rect->left = 0;
229 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
230 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
232 if (wndPtr->dwStyle & WS_ICONIC) return; /* No border to remove */
234 /* Remove frame from rectangle */
235 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
237 InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
238 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
242 if (HAS_THICKFRAME( wndPtr->dwStyle ))
243 InflateRect( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
244 if (wndPtr->dwStyle & WS_BORDER)
245 InflateRect( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
250 /***********************************************************************
253 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
255 LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
258 WND *wndPtr = WIN_FindWndPtr( hwnd );
259 if (!wndPtr) return HTERROR;
261 dprintf_nonclient(stddeb, "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n",
264 GetWindowRect( hwnd, &rect );
265 if (!PtInRect( &rect, pt )) return HTNOWHERE;
268 * if this is a iconic window, we don't care were the hit
269 * occured, only that it did occur, just return HTCAPTION
270 * so the caller knows the icon did get hit
274 return HTCAPTION; /* change this to something meaningful? */
278 if (HAS_THICKFRAME( wndPtr->dwStyle ))
280 InflateRect( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
281 if (wndPtr->dwStyle & WS_BORDER)
282 InflateRect( &rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
283 if (!PtInRect( &rect, pt ))
285 /* Check top sizing border */
288 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
289 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
292 /* Check bottom sizing border */
293 if (pt.y >= rect.bottom)
295 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
296 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
299 /* Check left sizing border */
300 if (pt.x < rect.left)
302 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
303 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
306 /* Check right sizing border */
307 if (pt.x >= rect.right)
309 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
310 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
315 else /* No thick frame */
317 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
318 InflateRect(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
319 else if (wndPtr->dwStyle & WS_BORDER)
320 InflateRect(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
321 if (!PtInRect( &rect, pt )) return HTBORDER;
326 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
328 rect.top += SYSMETRICS_CYCAPTION - 1;
329 if (!PtInRect( &rect, pt ))
331 /* Check system menu */
332 if (wndPtr->dwStyle & WS_SYSMENU)
333 rect.left += SYSMETRICS_CXSIZE;
334 if (pt.x <= rect.left) return HTSYSMENU;
335 /* Check maximize box */
336 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
337 rect.right -= SYSMETRICS_CXSIZE + 1;
338 if (pt.x >= rect.right) return HTMAXBUTTON;
339 /* Check minimize box */
340 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
341 rect.right -= SYSMETRICS_CXSIZE + 1;
342 if (pt.x >= rect.right) return HTMINBUTTON;
347 /* Check client area */
349 ScreenToClient( hwnd, &pt );
350 GetClientRect( hwnd, &rect );
351 if (PtInRect( &rect, pt )) return HTCLIENT;
353 /* Check vertical scroll bar */
355 if (wndPtr->dwStyle & WS_VSCROLL)
357 rect.right += SYSMETRICS_CXVSCROLL;
358 if (PtInRect( &rect, pt )) return HTVSCROLL;
361 /* Check horizontal scroll bar */
363 if (wndPtr->dwStyle & WS_HSCROLL)
365 rect.bottom += SYSMETRICS_CYHSCROLL;
366 if (PtInRect( &rect, pt ))
369 if ((wndPtr->dwStyle & WS_VSCROLL) &&
370 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
378 if (HAS_MENU(wndPtr))
380 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
384 /* Should never get here */
389 /***********************************************************************
392 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
397 WND *wndPtr = WIN_FindWndPtr( hwnd );
399 NC_GetInsideRect( hwnd, &rect );
400 hdcMem = CreateCompatibleDC( hdc );
401 hbitmap = SelectObject( hdcMem, hbitmapClose );
402 BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
403 hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
404 down ? NOTSRCCOPY : SRCCOPY );
405 SelectObject( hdcMem, hbitmap );
410 /***********************************************************************
413 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
416 NC_GetInsideRect( hwnd, &rect );
417 GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
418 (down ? hbitmapRestoreD : hbitmapRestore) :
419 (down ? hbitmapMaximizeD : hbitmapMaximize)),
420 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
421 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
425 /***********************************************************************
428 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
431 WND *wndPtr = WIN_FindWndPtr( hwnd );
432 NC_GetInsideRect( hwnd, &rect );
433 if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
434 GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
435 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
436 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
440 /***********************************************************************
443 * Draw a window frame inside the given rectangle, and update the rectangle.
444 * The correct pen for the frame must be selected in the DC.
446 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame, BOOL active )
448 short width, height, tmp;
452 width = SYSMETRICS_CXDLGFRAME - 1;
453 height = SYSMETRICS_CYDLGFRAME - 1;
454 SelectObject( hdc, active ? sysColorObjects.hbrushActiveCaption :
455 sysColorObjects.hbrushInactiveCaption );
459 width = SYSMETRICS_CXFRAME - 1;
460 height = SYSMETRICS_CYFRAME - 1;
461 SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
462 sysColorObjects.hbrushInactiveBorder );
466 PatBlt( hdc, rect->left, rect->top,
467 rect->right - rect->left, height, PATCOPY );
468 PatBlt( hdc, rect->left, rect->top,
469 width, rect->bottom - rect->top, PATCOPY );
470 PatBlt( hdc, rect->left, rect->bottom,
471 rect->right - rect->left, -height, PATCOPY );
472 PatBlt( hdc, rect->right, rect->top,
473 -width, rect->bottom - rect->top, PATCOPY );
477 InflateRect( rect, -width, -height );
481 /* Draw inner rectangle */
482 MoveTo( hdc, rect->left+width, rect->top+height );
483 LineTo( hdc, rect->right-width-1, rect->top+height );
484 LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
485 LineTo( hdc, rect->left+width, rect->bottom-height-1 );
486 LineTo( hdc, rect->left+width, rect->top+height );
488 /* Draw the decorations */
489 tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
490 MoveTo( hdc, rect->left, tmp);
491 LineTo( hdc, rect->left+width, tmp );
492 MoveTo( hdc, rect->right-width-1, tmp );
493 LineTo( hdc, rect->right-1, tmp );
495 tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
496 MoveTo( hdc, rect->left, tmp );
497 LineTo( hdc, rect->left+width, tmp );
498 MoveTo( hdc, rect->right-width-1, tmp );
499 LineTo( hdc, rect->right-1, tmp );
501 tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
502 MoveTo( hdc, tmp, rect->top );
503 LineTo( hdc, tmp, rect->top+height );
504 MoveTo( hdc, tmp, rect->bottom-height-1 );
505 LineTo( hdc, tmp, rect->bottom-1 );
507 tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
508 MoveTo( hdc, tmp, rect->top );
509 LineTo( hdc, tmp, rect->top+height );
510 MoveTo( hdc, tmp, rect->bottom-height-1 );
511 LineTo( hdc, tmp, rect->bottom-1 );
513 InflateRect( rect, -width-1, -height-1 );
517 /***********************************************************************
520 * Draw the frame used when moving or resizing window.
522 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
526 SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
527 PatBlt( hdc, rect->left, rect->top,
528 rect->right - rect->left - SYSMETRICS_CXFRAME,
529 SYSMETRICS_CYFRAME, PATINVERT );
530 PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
532 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
533 PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
534 rect->right - rect->left - SYSMETRICS_CXFRAME,
535 -SYSMETRICS_CYFRAME, PATINVERT );
536 PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME,
537 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
539 else DrawFocusRect( hdc, rect );
543 /***********************************************************************
546 * Draw the window caption.
547 * The correct pen for the window frame must be selected in the DC.
549 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
550 DWORD style, BOOL active )
553 WND * wndPtr = WIN_FindWndPtr( hwnd );
558 if (!(hbitmapClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
560 hbitmapMinimize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCE) );
561 hbitmapMinimizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCED) );
562 hbitmapMaximize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOM) );
563 hbitmapMaximizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
564 hbitmapRestore = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE) );
565 hbitmapRestoreD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
568 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
570 HBRUSH hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
571 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
572 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
573 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
576 SelectObject( hdc, hbrushOld );
579 MoveTo( hdc, r.left, r.bottom );
580 LineTo( hdc, r.right-1, r.bottom );
582 if (style & WS_SYSMENU)
584 NC_DrawSysButton( hwnd, hdc, FALSE );
585 r.left += SYSMETRICS_CXSIZE + 1;
586 MoveTo( hdc, r.left - 1, r.top );
587 LineTo( hdc, r.left - 1, r.bottom );
589 if (style & WS_MAXIMIZEBOX)
591 NC_DrawMaxButton( hwnd, hdc, FALSE );
592 r.right -= SYSMETRICS_CXSIZE + 1;
594 if (style & WS_MINIMIZEBOX)
596 NC_DrawMinButton( hwnd, hdc, FALSE );
597 r.right -= SYSMETRICS_CXSIZE + 1;
600 FillRect( hdc, &r, active ? sysColorObjects.hbrushActiveCaption :
601 sysColorObjects.hbrushInactiveCaption );
603 if (GetWindowText( hwnd, buffer, 256 ))
605 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
606 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
607 SetBkMode( hdc, TRANSPARENT );
608 DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
613 /***********************************************************************
616 * Paint the non-client area.
618 void NC_DoNCPaint( HWND hwnd, BOOL active, BOOL suppress_menupaint )
623 WND *wndPtr = WIN_FindWndPtr( hwnd );
625 dprintf_nonclient(stddeb, "NC_DoNCPaint: %x %d\n", hwnd, active );
626 if (!wndPtr || !(wndPtr->dwStyle & WS_VISIBLE)) return; /* Nothing to do */
628 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
631 * If this is an icon, we don't want to do any more nonclient painting
632 * of the window manager.
633 * If there is a class icon to draw, draw it
637 HICON hIcon = WIN_CLASS_INFO(wndPtr).hIcon;
640 SendMessage(hwnd, WM_ICONERASEBKGND, hdc, 0);
641 DrawIcon(hdc, 0, 0, hIcon);
643 ReleaseDC(hwnd, hdc);
647 if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
648 wndPtr->rectClient.top-wndPtr->rectWindow.top,
649 wndPtr->rectClient.right-wndPtr->rectWindow.left,
650 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
653 ReleaseDC( hwnd, hdc );
657 rect.top = rect.left = 0;
658 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
659 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
661 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
663 if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
664 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
667 LineTo( hdc, rect.right-1, 0 );
668 LineTo( hdc, rect.right-1, rect.bottom-1 );
669 LineTo( hdc, 0, rect.bottom-1 );
671 InflateRect( &rect, -1, -1 );
674 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
675 NC_DrawFrame( hdc, &rect, TRUE, active );
676 else if (wndPtr->dwStyle & WS_THICKFRAME)
677 NC_DrawFrame(hdc, &rect, FALSE, active );
679 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
682 r.bottom = rect.top + SYSMETRICS_CYSIZE;
683 rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
684 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
687 if (HAS_MENU(wndPtr))
690 r.bottom = rect.top + SYSMETRICS_CYMENU; /* default height */
691 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
694 /* Draw the scroll-bars */
696 if (wndPtr->dwStyle & WS_VSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_VERT);
697 if (wndPtr->dwStyle & WS_HSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_HORZ);
699 /* Draw the "size-box" */
701 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
704 r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
705 r.top = r.bottom - SYSMETRICS_CYHSCROLL + 1;
706 FillRect( hdc, &r, sysColorObjects.hbrushScrollbar );
709 ReleaseDC( hwnd, hdc );
714 /***********************************************************************
717 * Handle a WM_NCPAINT message. Called from DefWindowProc().
719 LONG NC_HandleNCPaint( HWND hwnd )
721 NC_DoNCPaint( hwnd, hwnd == GetActiveWindow(), FALSE );
726 /***********************************************************************
727 * NC_HandleNCActivate
729 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
731 LONG NC_HandleNCActivate( HWND hwnd, WORD wParam )
733 NC_DoNCPaint( hwnd, wParam, FALSE );
738 /***********************************************************************
741 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
743 LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam )
745 if (hwnd != wParam) return 0; /* Don't set the cursor for child windows */
747 switch(LOWORD(lParam))
751 WORD msg = HIWORD( lParam );
752 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
753 (msg == WM_RBUTTONDOWN))
762 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
763 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) break;
764 if (classPtr->wc.hCursor)
766 SetCursor( classPtr->wc.hCursor );
774 return SetCursor( LoadCursor( 0, IDC_SIZEWE ) );
778 return SetCursor( LoadCursor( 0, IDC_SIZENS ) );
782 return SetCursor( LoadCursor( 0, IDC_SIZENWSE ) );
786 return SetCursor( LoadCursor( 0, IDC_SIZENESW ) );
789 /* Default cursor: arrow */
790 return SetCursor( LoadCursor( 0, IDC_ARROW ) );
794 /***********************************************************************
797 * Initialisation of a move or resize, when initiatied from a menu choice.
798 * Return hit test code for caption or sizing border.
800 static LONG NC_StartSizeMove( HWND hwnd, WORD wParam, POINT *capturePoint )
805 WND * wndPtr = WIN_FindWndPtr( hwnd );
807 if ((wParam & 0xfff0) == SC_MOVE)
809 /* Move pointer at the center of the caption */
811 NC_GetInsideRect( hwnd, &rect );
812 if (wndPtr->dwStyle & WS_SYSMENU)
813 rect.left += SYSMETRICS_CXSIZE + 1;
814 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
815 rect.right -= SYSMETRICS_CXSIZE + 1;
816 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
817 rect.right -= SYSMETRICS_CXSIZE + 1;
818 pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
819 pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
820 if (wndPtr->dwStyle & WS_CHILD)
821 ClientToScreen( wndPtr->hwndParent, &pt );
829 MSG_GetHardwareMessage( &msg );
833 hittest = NC_HandleNCHitTest( hwnd, msg.pt );
835 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
847 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
848 pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
852 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
853 pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
857 pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
858 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
862 pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
863 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
866 case VK_ESCAPE: return 0;
872 SetCursorPos( capturePoint->x, capturePoint->y );
873 NC_HandleSetCursor( hwnd, hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
878 /***********************************************************************
881 * Perform SC_MOVE and SC_SIZE commands.
883 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
887 RECT sizingRect, mouseRect;
890 POINT minTrack, maxTrack, capturePoint = pt;
891 WND * wndPtr = WIN_FindWndPtr( hwnd );
893 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd)) return;
894 hittest = wParam & 0x0f;
895 thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
897 if ((wParam & 0xfff0) == SC_MOVE)
899 if (!(wndPtr->dwStyle & WS_CAPTION)) return;
900 if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
901 if (!hittest) return;
905 if (!thickframe) return;
906 if (hittest) hittest += HTLEFT-1;
910 hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
919 /* Get min/max info */
921 NC_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
922 sizingRect = wndPtr->rectWindow;
923 if (wndPtr->dwStyle & WS_CHILD)
924 GetClientRect( wndPtr->hwndParent, &mouseRect );
925 else SetRect( &mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN );
926 if (ON_LEFT_BORDER(hittest))
928 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
929 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
931 else if (ON_RIGHT_BORDER(hittest))
933 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
934 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
936 if (ON_TOP_BORDER(hittest))
938 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
939 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
941 else if (ON_BOTTOM_BORDER(hittest))
943 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
944 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
946 SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
948 if (GetCapture() != hwnd) SetCapture( hwnd );
950 if (wndPtr->dwStyle & WS_CHILD)
952 /* Retrieve a default cache DC (without using the window style) */
953 hdc = GetDCEx( wndPtr->hwndParent, 0, DCX_CACHE );
956 { /* Grab the server only when moving top-level windows without desktop */
958 if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
960 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
966 MSG_GetHardwareMessage( &msg );
968 /* Exit on button-up, Return, or Esc */
969 if ((msg.message == WM_LBUTTONUP) ||
970 ((msg.message == WM_KEYDOWN) &&
971 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
973 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
974 continue; /* We are not interested in other messages */
977 if (wndPtr->dwStyle & WS_CHILD)
978 ScreenToClient( wndPtr->hwndParent, &pt );
981 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
983 case VK_UP: pt.y -= 8; break;
984 case VK_DOWN: pt.y += 8; break;
985 case VK_LEFT: pt.x -= 8; break;
986 case VK_RIGHT: pt.x += 8; break;
989 pt.x = max( pt.x, mouseRect.left );
990 pt.x = min( pt.x, mouseRect.right );
991 pt.y = max( pt.y, mouseRect.top );
992 pt.y = min( pt.y, mouseRect.bottom );
994 dx = pt.x - capturePoint.x;
995 dy = pt.y - capturePoint.y;
999 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1002 RECT newRect = sizingRect;
1004 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
1005 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1006 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1007 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1008 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1009 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1010 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1012 sizingRect = newRect;
1017 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1019 if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
1022 ReleaseDC( 0, hdc );
1023 if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1025 SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1027 /* If Esc key, don't move the window */
1028 if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1030 if (hittest != HTCAPTION)
1031 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1032 sizingRect.right - sizingRect.left,
1033 sizingRect.bottom - sizingRect.top,
1034 SWP_NOACTIVATE | SWP_NOZORDER );
1035 else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1036 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1040 /***********************************************************************
1043 * Track a mouse button press on the minimize or maximize box.
1045 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1048 HDC hdc = GetWindowDC( hwnd );
1049 BOOL pressed = TRUE;
1052 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1053 else NC_DrawMaxButton( hwnd, hdc, TRUE );
1057 BOOL oldstate = pressed;
1058 MSG_GetHardwareMessage( &msg );
1060 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1061 if (pressed != oldstate)
1063 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1064 else NC_DrawMaxButton( hwnd, hdc, pressed );
1066 } while (msg.message != WM_LBUTTONUP);
1068 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1069 else NC_DrawMaxButton( hwnd, hdc, FALSE );
1072 ReleaseDC( hwnd, hdc );
1073 if (!pressed) return;
1075 if (wParam == HTMINBUTTON)
1076 SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1078 SendMessage( hwnd, WM_SYSCOMMAND,
1079 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1083 /***********************************************************************
1086 * Track a mouse button press on the horizontal or vertical scroll-bar.
1088 static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt )
1093 WND *wndPtr = WIN_FindWndPtr( hwnd );
1095 if ((wParam & 0xfff0) == SC_HSCROLL)
1097 if ((wParam & 0x0f) != HTHSCROLL) return;
1098 scrollbar = SB_HORZ;
1100 else /* SC_VSCROLL */
1102 if ((wParam & 0x0f) != HTVSCROLL) return;
1103 scrollbar = SB_VERT;
1106 hMsg = USER_HEAP_ALLOC( sizeof(MSG) );
1107 msg = (MSG *) USER_HEAP_LIN_ADDR( hMsg );
1108 pt.x -= wndPtr->rectWindow.left;
1109 pt.y -= wndPtr->rectWindow.top;
1111 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1115 GetMessage( USER_HEAP_SEG_ADDR(hMsg), 0, 0, 0 );
1116 switch(msg->message)
1121 pt = MAKEPOINT(msg->lParam);
1122 pt.x += wndPtr->rectClient.left - wndPtr->rectWindow.left;
1123 pt.y += wndPtr->rectClient.top - wndPtr->rectWindow.top;
1124 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
1127 TranslateMessage( msg );
1128 DispatchMessage( msg );
1131 if (!IsWindow( hwnd ))
1136 } while (msg->message != WM_LBUTTONUP);
1137 USER_HEAP_FREE( hMsg );
1140 /***********************************************************************
1143 * Track a mouse button press on the system menu.
1145 static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT pt )
1148 WND *wndPtr = WIN_FindWndPtr( hwnd );
1150 if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
1151 /* If window has a menu, track the menu bar normally */
1152 if (HAS_MENU(wndPtr)) MENU_TrackMouseMenuBar( hwnd, pt );
1155 /* Otherwise track the system menu like a normal popup menu */
1156 NC_GetInsideRect( hwnd, &rect );
1157 OffsetRect( &rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
1158 if (wndPtr->dwStyle & WS_CHILD)
1159 ClientToScreen( wndPtr->hwndParent, (POINT *)&rect );
1160 rect.right = rect.left + SYSMETRICS_CXSIZE;
1161 rect.bottom = rect.top + SYSMETRICS_CYSIZE;
1162 NC_DrawSysButton( hwnd, hdc, TRUE );
1163 TrackPopupMenu( wndPtr->hSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
1164 rect.left, rect.bottom, 0, hwnd, &rect );
1165 NC_DrawSysButton( hwnd, hdc, FALSE );
1170 /***********************************************************************
1171 * NC_HandleNCLButtonDown
1173 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1175 LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam )
1177 HDC hdc = GetWindowDC( hwnd );
1179 switch(wParam) /* Hit test */
1182 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1186 NC_TrackSysMenu( hwnd, hdc, MAKEPOINT(lParam) );
1190 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1194 SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1198 SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1203 NC_TrackMinMaxBox( hwnd, wParam );
1214 SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1221 ReleaseDC( hwnd, hdc );
1226 /***********************************************************************
1227 * NC_HandleNCLButtonDblClk
1229 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1231 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam )
1234 * if this is an icon, send a restore since we are handling
1239 SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam);
1243 switch(wParam) /* Hit test */
1246 SendMessage( hwnd, WM_SYSCOMMAND,
1247 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1251 SendMessage( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1258 /***********************************************************************
1259 * NC_HandleSysCommand
1261 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1263 LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
1265 WND *wndPtr = WIN_FindWndPtr( hwnd );
1267 dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n",
1268 wParam, pt.x, pt.y );
1270 if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
1272 switch (wParam & 0xfff0)
1276 NC_DoSizeMove( hwnd, wParam, pt );
1280 ShowWindow( hwnd, SW_MINIMIZE );
1284 ShowWindow( hwnd, SW_MAXIMIZE );
1288 ShowWindow( hwnd, SW_RESTORE );
1296 return SendMessage( hwnd, WM_CLOSE, 0, 0 );
1300 NC_TrackScrollBar( hwnd, wParam, pt );
1304 MENU_TrackMouseMenuBar( hwnd, pt );
1308 MENU_TrackKbdMenuBar( hwnd, wParam );
1315 /* WinExec( "taskman.exe", SW_SHOWNORMAL ); */
1322 if (wParam == SC_ABOUTWINE)
1323 { extern char sysres_DIALOG_2[];
1324 DialogBoxIndirectPtr( wndPtr->hInstance, sysres_DIALOG_2,
1325 hwnd, GetWndProcEntry16("AboutWine_Proc") );