2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1994";
12 #include "sysmetrics.h"
18 static HBITMAP hbitmapClose = 0;
19 static HBITMAP hbitmapMDIClose = 0;
20 static HBITMAP hbitmapMinimize = 0;
21 static HBITMAP hbitmapMinimizeD = 0;
22 static HBITMAP hbitmapMaximize = 0;
23 static HBITMAP hbitmapMaximizeD = 0;
24 static HBITMAP hbitmapRestore = 0;
25 static HBITMAP hbitmapRestoreD = 0;
27 extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
28 POINT *minTrack, POINT *maxTrack ); /* winpos.c */
29 extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor ); /* cursor.c */
30 extern WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth,
31 int orgX, int orgY ); /* menu.c */
34 /* Some useful macros */
35 #define HAS_DLGFRAME(style,exStyle) \
36 (((style) & WS_DLGFRAME) && \
37 (((exStyle) & WS_EX_DLGMODALFRAME) || !((style) & WS_BORDER)))
39 #define HAS_THICKFRAME(style) \
40 (((style) & WS_THICKFRAME) && \
41 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
43 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
45 #define ON_LEFT_BORDER(hit) \
46 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
47 #define ON_RIGHT_BORDER(hit) \
48 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
49 #define ON_TOP_BORDER(hit) \
50 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
51 #define ON_BOTTOM_BORDER(hit) \
52 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
54 /***********************************************************************
57 * Compute the size of the window rectangle from the size of the
60 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
62 if (HAS_DLGFRAME( style, exStyle ))
63 InflateRect( rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
66 if (HAS_THICKFRAME(style))
67 InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
68 if (style & WS_BORDER)
69 InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER );
72 if ((style & WS_CAPTION) == WS_CAPTION)
73 rect->top -= SYSMETRICS_CYCAPTION - 1;
74 if (menu) rect->top -= SYSMETRICS_CYMENU + 1;
76 if (style & WS_VSCROLL) rect->right += SYSMETRICS_CXVSCROLL;
77 if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
81 /***********************************************************************
82 * AdjustWindowRect (USER.102)
84 void AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
86 AdjustWindowRectEx( rect, style, menu, 0 );
90 /***********************************************************************
91 * AdjustWindowRectEx (USER.454)
93 void AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
95 /* Correct the window style */
97 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
99 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
101 #ifdef DEBUG_NONCLIENT
102 printf( "AdjustWindowRectEx: (%d,%d)-(%d,%d) %08x %d %08x\n",
103 rect->left, rect->top, rect->right, rect->bottom, style, menu, exStyle );
106 NC_AdjustRect( rect, style, menu, exStyle );
110 /***********************************************************************
111 * NC_HandleNCCalcSize
113 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
115 LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params )
117 RECT tmpRect = { 0, 0, 0, 0 };
118 WND *wndPtr = WIN_FindWndPtr( hwnd );
120 if (!wndPtr) return 0;
122 NC_AdjustRect( &tmpRect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle );
123 params->rgrc[0].left -= tmpRect.left;
124 params->rgrc[0].top -= tmpRect.top;
125 params->rgrc[0].right -= tmpRect.right;
126 params->rgrc[0].bottom -= tmpRect.bottom;
128 if (HAS_MENU(wndPtr))
130 params->rgrc[0].top += MENU_GetMenuBarHeight( hwnd,
131 params->rgrc[0].right - params->rgrc[0].left,
132 -tmpRect.left, -tmpRect.top ) + 1;
138 /***********************************************************************
141 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
142 * but without the borders (if any).
143 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
145 void NC_GetInsideRect( HWND hwnd, RECT *rect )
147 WND * wndPtr = WIN_FindWndPtr( hwnd );
149 rect->top = rect->left = 0;
150 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
151 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
153 /* Remove frame from rectangle */
154 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
156 InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
157 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
161 if (HAS_THICKFRAME( wndPtr->dwStyle ))
162 InflateRect( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
163 if (wndPtr->dwStyle & WS_BORDER)
164 InflateRect( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
169 /***********************************************************************
170 * NC_InternalNCHitTest
172 * Perform the hit test calculation, but whithout testing the capture
175 static LONG NC_InternalNCHitTest( HWND hwnd, POINT pt )
178 WND *wndPtr = WIN_FindWndPtr( hwnd );
179 if (!wndPtr) return HTERROR;
181 GetWindowRect( hwnd, &rect );
182 if (!PtInRect( &rect, pt )) return HTNOWHERE;
186 if (HAS_THICKFRAME( wndPtr->dwStyle ))
188 InflateRect( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
189 if (wndPtr->dwStyle & WS_BORDER)
190 InflateRect( &rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
191 if (!PtInRect( &rect, pt ))
193 /* Check top sizing border */
196 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
197 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
200 /* Check bottom sizing border */
201 if (pt.y >= rect.bottom)
203 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
204 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
207 /* Check left sizing border */
208 if (pt.x < rect.left)
210 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
211 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
214 /* Check right sizing border */
215 if (pt.x >= rect.right)
217 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
218 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
223 else /* No thick frame */
225 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
226 InflateRect(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
227 else if (wndPtr->dwStyle & WS_BORDER)
228 InflateRect(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
229 if (!PtInRect( &rect, pt )) return HTBORDER;
234 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
236 rect.top += SYSMETRICS_CYCAPTION - 1;
237 if (!PtInRect( &rect, pt ))
239 /* Check system menu */
240 if ((wndPtr->dwStyle & WS_SYSMENU) && (pt.x <= SYSMETRICS_CXSIZE))
242 /* Check maximize box */
243 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
244 rect.right -= SYSMETRICS_CXSIZE + 1;
245 if (pt.x >= rect.right) return HTMAXBUTTON;
246 /* Check minimize box */
247 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
248 rect.right -= SYSMETRICS_CXSIZE + 1;
249 if (pt.x >= rect.right) return HTMINBUTTON;
254 /* Check client area */
256 ScreenToClient( hwnd, &pt );
257 GetClientRect( hwnd, &rect );
258 if (PtInRect( &rect, pt )) return HTCLIENT;
260 /* Check vertical scroll bar */
262 if (wndPtr->dwStyle & WS_VSCROLL)
264 rect.right += SYSMETRICS_CXVSCROLL;
265 if (PtInRect( &rect, pt )) return HTVSCROLL;
268 /* Check horizontal scroll bar */
270 if (wndPtr->dwStyle & WS_HSCROLL)
272 rect.bottom += SYSMETRICS_CYHSCROLL;
273 if (PtInRect( &rect, pt ))
276 if ((wndPtr->dwStyle & WS_VSCROLL) &&
277 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
285 if (HAS_MENU(wndPtr))
287 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
291 /* Should never get here */
296 /***********************************************************************
299 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
301 LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
303 #ifdef DEBUG_NONCLIENT
304 printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
306 if (hwnd == GetCapture()) return HTCLIENT;
307 return NC_InternalNCHitTest( hwnd, pt );
311 /***********************************************************************
314 static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
317 WND *wndPtr = WIN_FindWndPtr( hwnd );
318 HDC hdcMem = CreateCompatibleDC( hdc );
321 NC_GetInsideRect( hwnd, &rect );
322 if (wndPtr->dwStyle & WS_CHILD)
323 SelectObject( hdcMem, hbitmapMDIClose );
325 SelectObject( hdcMem, hbitmapClose );
326 BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE,
327 SYSMETRICS_CYSIZE, hdcMem, 1, 1, down ? NOTSRCCOPY : SRCCOPY );
333 /***********************************************************************
336 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
339 HDC hdcMem = CreateCompatibleDC( hdc );
342 NC_GetInsideRect( hwnd, &rect );
344 SelectObject( hdcMem, down ? hbitmapRestoreD : hbitmapRestore );
345 else SelectObject( hdcMem, down ? hbitmapMaximizeD : hbitmapMaximize );
346 BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
347 SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
353 /***********************************************************************
356 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
359 WND *wndPtr = WIN_FindWndPtr( hwnd );
360 HDC hdcMem = CreateCompatibleDC( hdc );
363 NC_GetInsideRect( hwnd, &rect );
364 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
365 rect.right -= SYSMETRICS_CXSIZE + 1;
366 if (down) SelectObject( hdcMem, hbitmapMinimizeD );
367 else SelectObject( hdcMem, hbitmapMinimize );
368 BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
369 SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
375 /***********************************************************************
378 * Draw a window frame inside the given rectangle, and update the rectangle.
379 * The correct pen and brush must be selected in the DC.
381 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame )
383 short width, height, tmp;
387 width = SYSMETRICS_CXDLGFRAME - 1;
388 height = SYSMETRICS_CYDLGFRAME - 1;
392 width = SYSMETRICS_CXFRAME - 1;
393 height = SYSMETRICS_CYFRAME - 1;
397 PatBlt( hdc, rect->left, rect->top,
398 rect->right - rect->left, height, PATCOPY );
399 PatBlt( hdc, rect->left, rect->top,
400 width, rect->bottom - rect->top, PATCOPY );
401 PatBlt( hdc, rect->left, rect->bottom,
402 rect->right - rect->left, -height, PATCOPY );
403 PatBlt( hdc, rect->right, rect->top,
404 -width, rect->bottom - rect->top, PATCOPY );
408 InflateRect( rect, -width, -height );
412 /* Draw inner rectangle */
413 MoveTo( hdc, rect->left+width, rect->top+height );
414 LineTo( hdc, rect->right-width-1, rect->top+height );
415 LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
416 LineTo( hdc, rect->left+width, rect->bottom-height-1 );
417 LineTo( hdc, rect->left+width, rect->top+height );
419 /* Draw the decorations */
420 tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
421 MoveTo( hdc, rect->left, tmp);
422 LineTo( hdc, rect->left+width, tmp );
423 MoveTo( hdc, rect->right-width-1, tmp );
424 LineTo( hdc, rect->right-1, tmp );
426 tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
427 MoveTo( hdc, rect->left, tmp );
428 LineTo( hdc, rect->left+width, tmp );
429 MoveTo( hdc, rect->right-width-1, tmp );
430 LineTo( hdc, rect->right-1, tmp );
432 tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
433 MoveTo( hdc, tmp, rect->top );
434 LineTo( hdc, tmp, rect->top+height );
435 MoveTo( hdc, tmp, rect->bottom-height-1 );
436 LineTo( hdc, tmp, rect->bottom-1 );
438 tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
439 MoveTo( hdc, tmp, rect->top );
440 LineTo( hdc, tmp, rect->top+height );
441 MoveTo( hdc, tmp, rect->bottom-height-1 );
442 LineTo( hdc, tmp, rect->bottom-1 );
444 InflateRect( rect, -width-1, -height-1 );
448 /***********************************************************************
451 * Draw the frame used when moving or resizing window.
453 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
457 SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
458 PatBlt( hdc, rect->left, rect->top,
459 rect->right - rect->left - SYSMETRICS_CXFRAME,
460 SYSMETRICS_CYFRAME, PATINVERT );
461 PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
463 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
464 PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
465 rect->right - rect->left - SYSMETRICS_CXFRAME,
466 -SYSMETRICS_CYFRAME, PATINVERT );
467 PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME,
468 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
470 else DrawFocusRect( hdc, rect );
474 /***********************************************************************
477 * Draw the window caption.
478 * The correct pen for the window frame must be selected in the DC.
480 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
481 DWORD style, BOOL active )
484 WND * wndPtr = WIN_FindWndPtr( hwnd );
489 if (!(hbitmapClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
491 if (!(hbitmapMDIClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_OLD_CLOSE) )))
493 hbitmapMinimize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCE) );
494 hbitmapMinimizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCED) );
495 hbitmapMaximize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOM) );
496 hbitmapMaximizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
497 hbitmapRestore = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE) );
498 hbitmapRestoreD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
501 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
503 HBRUSH hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
504 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
505 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
506 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
509 SelectObject( hdc, hbrushOld );
512 MoveTo( hdc, r.left, r.bottom );
513 LineTo( hdc, r.right-1, r.bottom );
515 if (style & WS_SYSMENU)
517 NC_DrawSysButton( hwnd, hdc, FALSE );
518 r.left += SYSMETRICS_CXSIZE + 1;
519 MoveTo( hdc, r.left - 1, r.top );
520 LineTo( hdc, r.left - 1, r.bottom );
522 if (style & WS_MAXIMIZEBOX)
524 NC_DrawMaxButton( hwnd, hdc, FALSE );
525 r.right -= SYSMETRICS_CXSIZE + 1;
527 if (style & WS_MINIMIZEBOX)
529 NC_DrawMinButton( hwnd, hdc, FALSE );
530 r.right -= SYSMETRICS_CXSIZE + 1;
533 FillRect( hdc, &r, active ? sysColorObjects.hbrushActiveCaption :
534 sysColorObjects.hbrushInactiveCaption );
536 if (GetWindowText( hwnd, buffer, 256 ))
538 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
539 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
540 SetBkMode( hdc, TRANSPARENT );
541 DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
546 /***********************************************************************
549 * Paint the non-client area.
550 * 'hrgn' is the update rgn to use (in client coords) or 1 if no update rgn.
552 void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active, BOOL suppress_menupaint )
557 WND *wndPtr = WIN_FindWndPtr( hwnd );
559 #ifdef DEBUG_NONCLIENT
560 printf( "NC_DoNCPaint: %d %d\n", hwnd, hrgn );
562 if (!wndPtr || !hrgn) return;
563 if ((!(wndPtr->dwStyle & (WS_BORDER | WS_DLGFRAME | WS_THICKFRAME))) ||
564 (!(wndPtr->dwStyle & WS_VISIBLE)))
565 return; /* Nothing to do! */
567 if (hrgn == 1) hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
570 /* Make region relative to window area */
571 int xoffset = wndPtr->rectWindow.left - wndPtr->rectClient.left;
572 int yoffset = wndPtr->rectWindow.top - wndPtr->rectClient.top;
573 OffsetRgn( hrgn, -xoffset, -yoffset );
574 hdc = GetDCEx( hwnd, hrgn, DCX_CACHE | DCX_WINDOW | DCX_INTERSECTRGN);
575 OffsetRgn( hrgn, xoffset, yoffset ); /* Restore region */
578 if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
579 wndPtr->rectClient.top-wndPtr->rectWindow.top,
580 wndPtr->rectClient.right-wndPtr->rectWindow.left,
581 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
584 ReleaseDC( hwnd, hdc );
588 rect.top = rect.left = 0;
589 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
590 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
592 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
593 SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
594 sysColorObjects.hbrushInactiveBorder );
596 if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME))
599 LineTo( hdc, rect.right-1, 0 );
600 LineTo( hdc, rect.right-1, rect.bottom-1 );
601 LineTo( hdc, 0, rect.bottom-1 );
603 InflateRect( &rect, -1, -1 );
606 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
607 NC_DrawFrame( hdc, &rect, TRUE );
608 else if (wndPtr->dwStyle & WS_THICKFRAME)
609 NC_DrawFrame(hdc, &rect, FALSE);
611 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
614 rect.top += SYSMETRICS_CYSIZE + 1;
615 r.bottom = rect.top - 1;
616 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
619 if (HAS_MENU(wndPtr))
621 LPPOPUPMENU lpMenu = (LPPOPUPMENU) GlobalLock( wndPtr->wIDmenu );
623 r.bottom = rect.top + lpMenu->Height;
624 rect.top += lpMenu->Height;
625 StdDrawMenuBar( hdc, &r, lpMenu, suppress_menupaint );
626 GlobalUnlock( wndPtr->wIDmenu );
629 if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL)) {
630 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->VScroll != NULL) &&
631 (wndPtr->scroll_flags & 0x0001)) {
632 int bottom = rect.bottom;
633 if ((wndPtr->dwStyle & WS_HSCROLL) && (wndPtr->scroll_flags & 0x0001))
634 bottom -= SYSMETRICS_CYHSCROLL;
635 SetRect(&rect2, rect.right - SYSMETRICS_CXVSCROLL,
636 rect.top, rect.right, bottom);
637 StdDrawScrollBar(hwnd, hdc, SB_VERT, &rect2, (LPHEADSCROLL)wndPtr->VScroll);
639 if ((wndPtr->dwStyle & WS_HSCROLL) && wndPtr->HScroll != NULL &&
640 (wndPtr->scroll_flags & 0x0002)) {
641 int right = rect.right;
642 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->scroll_flags & 0x0001))
643 right -= SYSMETRICS_CYVSCROLL;
644 SetRect(&rect2, rect.left, rect.bottom - SYSMETRICS_CYHSCROLL,
646 StdDrawScrollBar(hwnd, hdc, SB_HORZ, &rect2, (LPHEADSCROLL)wndPtr->HScroll);
649 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL) &&
650 (wndPtr->scroll_flags & 0x0003) == 0x0003) {
652 r.left = r.right - SYSMETRICS_CXVSCROLL;
653 r.top = r.bottom - SYSMETRICS_CYHSCROLL;
654 FillRect( hdc, &r, sysColorObjects.hbrushScrollbar );
658 ReleaseDC( hwnd, hdc );
662 NC_DoNCPaintIcon(HWND hwnd)
664 WND *wndPtr = WIN_FindWndPtr(hwnd);
673 printf("painting icon\n");
674 if (wndPtr == NULL) {
675 printf("argh, can't find an icon to draw\n");
678 hdc = BeginPaint(hwnd, &ps);
680 ret = DrawIcon(hdc, 100/2 - 16, 0, wndPtr->hIcon);
681 printf("ret is %d\n", ret);
683 if (s=GetWindowText(hwnd, buffer, 256))
685 /*SetBkColor(hdc, TRANSPARENT); */
686 TextOut(hdc, 0, 32, buffer, s);
690 printf("done painting icon\n");
695 LONG NC_HandleNCPaintIcon( HWND hwnd )
697 NC_DoNCPaintIcon(hwnd);
703 /***********************************************************************
706 * Handle a WM_NCPAINT message. Called from DefWindowProc().
708 LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
710 NC_DoNCPaint( hwnd, hrgn, hwnd == GetActiveWindow(), FALSE );
715 /***********************************************************************
716 * NC_HandleNCActivate
718 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
720 LONG NC_HandleNCActivate( HWND hwnd, WORD wParam )
722 NC_DoNCPaint( hwnd, (HRGN)1, wParam, FALSE );
727 /***********************************************************************
730 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
732 LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam )
734 if (hwnd != wParam) return 0; /* Don't set the cursor for child windows */
736 switch(LOWORD(lParam))
740 WORD msg = HIWORD( lParam );
741 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
742 (msg == WM_RBUTTONDOWN))
751 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
752 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) break;
753 if (classPtr->wc.hCursor)
755 CURSOR_SetWinCursor( hwnd, classPtr->wc.hCursor );
763 CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZEWE ) );
768 CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENS ) );
773 CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENWSE ) );
778 CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENESW ) );
782 /* Default cursor: arrow */
783 CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_ARROW ) );
788 /***********************************************************************
791 * Initialisation of a move or resize, when initiatied from a menu choice.
792 * Return hit test code for caption or sizing border.
794 static LONG NC_StartSizeMove( HWND hwnd, WORD wParam, POINT *capturePoint )
799 WND * wndPtr = WIN_FindWndPtr( hwnd );
801 if ((wParam & 0xfff0) == SC_MOVE)
803 /* Move pointer at the center of the caption */
805 NC_GetInsideRect( hwnd, &rect );
806 if (wndPtr->dwStyle & WS_SYSMENU)
807 rect.left += SYSMETRICS_CXSIZE + 1;
808 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
809 rect.right -= SYSMETRICS_CXSIZE + 1;
810 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
811 rect.right -= SYSMETRICS_CXSIZE + 1;
812 pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
813 pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
814 if (wndPtr->dwStyle & WS_CHILD)
815 ClientToScreen( wndPtr->hwndParent, &pt );
823 MSG_GetHardwareMessage( &msg );
827 hittest = NC_InternalNCHitTest( hwnd, msg.pt );
829 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
841 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
842 pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
846 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
847 pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
851 pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
852 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
856 pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
857 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
860 case VK_ESCAPE: return 0;
866 SetCursorPos( capturePoint->x, capturePoint->y );
867 NC_HandleSetCursor( hwnd, hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
872 /***********************************************************************
875 * Perform SC_MOVE and SC_SIZE commands.
877 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
881 RECT sizingRect, mouseRect;
884 POINT minTrack, maxTrack, capturePoint = pt;
885 WND * wndPtr = WIN_FindWndPtr( hwnd );
887 if (IsZoomed(hwnd) || IsIconic(hwnd) || !IsWindowVisible(hwnd)) return;
888 hittest = wParam & 0x0f;
889 thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
891 if ((wParam & 0xfff0) == SC_MOVE)
893 if (!(wndPtr->dwStyle & WS_CAPTION)) return;
894 if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
895 if (!hittest) return;
899 if (!thickframe) return;
900 if (hittest) hittest += HTLEFT-1;
904 hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
913 /* Get min/max info */
915 WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
916 sizingRect = wndPtr->rectWindow;
917 if (wndPtr->dwStyle & WS_CHILD)
918 GetClientRect( wndPtr->hwndParent, &mouseRect );
919 else SetRect( &mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN );
920 if (ON_LEFT_BORDER(hittest))
922 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
923 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
925 else if (ON_RIGHT_BORDER(hittest))
927 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
928 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
930 if (ON_TOP_BORDER(hittest))
932 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
933 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
935 else if (ON_BOTTOM_BORDER(hittest))
937 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
938 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
940 SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
942 if (GetCapture() != hwnd) SetCapture( hwnd );
944 if (wndPtr->dwStyle & WS_CHILD) hdc = GetDC( wndPtr->hwndParent );
946 { /* Grab the server only when moving top-level windows without desktop */
948 if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
950 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
956 MSG_GetHardwareMessage( &msg );
958 /* Exit on button-up, Return, or Esc */
959 if ((msg.message == WM_LBUTTONUP) ||
960 ((msg.message == WM_KEYDOWN) &&
961 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
963 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
964 continue; /* We are not interested in other messages */
967 if (wndPtr->dwStyle & WS_CHILD)
968 ScreenToClient( wndPtr->hwndParent, &pt );
971 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
973 case VK_UP: pt.y -= 8; break;
974 case VK_DOWN: pt.y += 8; break;
975 case VK_LEFT: pt.x -= 8; break;
976 case VK_RIGHT: pt.x += 8; break;
979 pt.x = max( pt.x, mouseRect.left );
980 pt.x = min( pt.x, mouseRect.right );
981 pt.y = max( pt.y, mouseRect.top );
982 pt.y = min( pt.y, mouseRect.bottom );
984 dx = pt.x - capturePoint.x;
985 dy = pt.y - capturePoint.y;
989 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
992 RECT newRect = sizingRect;
994 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
995 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
996 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
997 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
998 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
999 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1000 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1002 sizingRect = newRect;
1007 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1009 if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
1012 ReleaseDC( 0, hdc );
1013 if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1015 SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1017 /* If Esc key, don't move the window */
1018 if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1020 if (hittest != HTCAPTION)
1021 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1022 sizingRect.right - sizingRect.left,
1023 sizingRect.bottom - sizingRect.top,
1024 SWP_NOACTIVATE | SWP_NOZORDER );
1025 else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1026 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1030 /***********************************************************************
1033 * Track a mouse button press on the minimize or maximize box.
1035 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1038 HDC hdc = GetWindowDC( hwnd );
1039 BOOL pressed = TRUE;
1042 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1043 else NC_DrawMaxButton( hwnd, hdc, TRUE );
1047 BOOL oldstate = pressed;
1048 MSG_GetHardwareMessage( &msg );
1050 pressed = (NC_InternalNCHitTest( hwnd, msg.pt ) == wParam);
1051 if (pressed != oldstate)
1053 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1054 else NC_DrawMaxButton( hwnd, hdc, pressed );
1056 } while (msg.message != WM_LBUTTONUP);
1058 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1059 else NC_DrawMaxButton( hwnd, hdc, FALSE );
1062 ReleaseDC( hwnd, hdc );
1063 if (!pressed) return;
1065 if (wParam == HTMINBUTTON)
1066 SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1068 SendMessage( hwnd, WM_SYSCOMMAND,
1069 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1073 /***********************************************************************
1076 * Track a mouse button press on the horizontal or vertical scroll-bar.
1078 static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt )
1082 if ((wParam & 0xfff0) == SC_HSCROLL)
1084 if ((wParam & 0x0f) != HTHSCROLL) return;
1085 scrollbar = SB_HORZ;
1087 else /* SC_VSCROLL */
1089 if ((wParam & 0x0f) != HTVSCROLL) return;
1090 scrollbar = SB_VERT;
1093 ScreenToClient( hwnd, &pt );
1094 ScrollBarButtonDown( hwnd, scrollbar, pt.x, pt.y );
1099 MSG_GetHardwareMessage( &msg );
1100 ScreenToClient( msg.hwnd, &msg.pt );
1104 ScrollBarButtonUp( hwnd, scrollbar, msg.pt.x, msg.pt.y );
1107 ScrollBarMouseMove(hwnd, scrollbar, msg.wParam, msg.pt.x,msg.pt.y);
1110 } while (msg.message != WM_LBUTTONUP);
1115 /***********************************************************************
1116 * NC_TrackMouseMenuBar
1118 * Track a mouse events for the MenuBar.
1120 static void NC_TrackMouseMenuBar( HWND hwnd, WORD wParam, POINT pt )
1125 wndPtr = WIN_FindWndPtr(hwnd);
1126 lppop = (LPPOPUPMENU)GlobalLock(wndPtr->wIDmenu);
1128 printf("NC_TrackMouseMenuBar // wndPtr=%08X lppop=%08X !\n", wndPtr, lppop);
1130 ScreenToClient(hwnd, &pt);
1131 pt.y += lppop->rect.bottom;
1133 MenuButtonDown(hwnd, lppop, pt.x, pt.y);
1134 GlobalUnlock(wndPtr->wIDmenu);
1138 /***********************************************************************
1139 * NC_HandleNCLButtonDown
1141 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1143 LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam )
1145 HDC hdc = GetWindowDC( hwnd );
1147 switch(wParam) /* Hit test */
1150 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1154 NC_DrawSysButton( hwnd, hdc, TRUE );
1155 NC_TrackSysMenu(hwnd);
1159 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1163 SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1167 SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1172 NC_TrackMinMaxBox( hwnd, wParam );
1183 SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1190 ReleaseDC( hwnd, hdc );
1195 /***********************************************************************
1196 * NC_HandleNCLButtonDblClk
1198 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1200 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam )
1202 switch(wParam) /* Hit test */
1205 SendMessage( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
1209 SendMessage( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1216 /***********************************************************************
1217 * NC_HandleSysCommand
1219 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1221 LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
1223 WND *wndPtr = WIN_FindWndPtr( hwnd );
1225 #ifdef DEBUG_NONCLIENT
1226 printf( "Handling WM_SYSCOMMAND %x %d,%d\n", wParam, pt.x, pt.y );
1229 if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
1231 switch (wParam & 0xfff0)
1235 NC_DoSizeMove( hwnd, wParam, pt );
1239 ICON_Iconify( hwnd );
1240 /*ShowWindow( hwnd, SW_MINIMIZE );*/
1244 ShowWindow( hwnd, SW_MAXIMIZE );
1248 ICON_Deiconify(hwnd);
1249 ShowWindow( hwnd, SW_RESTORE );
1257 return SendMessage( hwnd, WM_CLOSE, 0, 0 );
1261 if (wndPtr->dwStyle & WS_CHILD) ClientToScreen(wndPtr->hwndParent, &pt);
1262 NC_TrackScrollBar( hwnd, wParam, pt );
1266 NC_TrackMouseMenuBar( hwnd, wParam, pt );
1270 /* NC_KeyMenuBar( hwnd, wParam, pt ); */