Release 960928
[wine/multimedia.git] / windows / nonclient.c
blobfe3148d64298c3c9e1e8d14a4a005f152e9d2622
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 */
8 #include "win.h"
9 #include "message.h"
10 #include "sysmetrics.h"
11 #include "user.h"
12 #include "heap.h"
13 #include "shell.h"
14 #include "dialog.h"
15 #include "syscolor.h"
16 #include "menu.h"
17 #include "winpos.h"
18 #include "hook.h"
19 #include "scroll.h"
20 #include "nonclient.h"
21 #include "graphics.h"
22 #include "queue.h"
23 #include "selectors.h"
24 #include "stddebug.h"
25 #include "debug.h"
26 #include "options.h"
29 static HBITMAP hbitmapClose = 0;
30 static HBITMAP hbitmapMinimize = 0;
31 static HBITMAP hbitmapMinimizeD = 0;
32 static HBITMAP hbitmapMaximize = 0;
33 static HBITMAP hbitmapMaximizeD = 0;
34 static HBITMAP hbitmapRestore = 0;
35 static HBITMAP hbitmapRestoreD = 0;
37 #define SC_ABOUTWINE (SC_SCREENSAVE+1)
39 /* Some useful macros */
40 #define HAS_DLGFRAME(style,exStyle) \
41 (((exStyle) & WS_EX_DLGMODALFRAME) || \
42 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
44 #define HAS_THICKFRAME(style) \
45 (((style) & WS_THICKFRAME) && \
46 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
48 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
50 #define ON_LEFT_BORDER(hit) \
51 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
52 #define ON_RIGHT_BORDER(hit) \
53 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
54 #define ON_TOP_BORDER(hit) \
55 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
56 #define ON_BOTTOM_BORDER(hit) \
57 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
59 /***********************************************************************
60 * NC_AdjustRect
62 * Compute the size of the window rectangle from the size of the
63 * client rectangle.
65 static void NC_AdjustRect(LPRECT16 rect, DWORD style, BOOL menu, DWORD exStyle)
67 /* Decide if the window will be managed (see CreateWindowEx) */
68 if (!(Options.managed && !(style & WS_CHILD) &&
69 ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
70 (exStyle & WS_EX_DLGMODALFRAME))))
72 if (HAS_DLGFRAME( style, exStyle ))
73 InflateRect16(rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
74 else
76 if (HAS_THICKFRAME(style))
77 InflateRect16( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
78 if (style & WS_BORDER)
79 InflateRect16( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
82 if ((style & WS_CAPTION) == WS_CAPTION)
83 rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
85 if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
87 if (style & WS_VSCROLL) rect->right += SYSMETRICS_CXVSCROLL;
88 if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
92 /***********************************************************************
93 * AdjustWindowRect16 (USER.102)
95 BOOL16 AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
97 return AdjustWindowRectEx16( rect, style, menu, 0 );
101 /***********************************************************************
102 * AdjustWindowRect32 (USER32.)
104 BOOL32 AdjustWindowRect32( LPRECT32 rect, DWORD style, BOOL32 menu )
106 return AdjustWindowRectEx32( rect, style, menu, 0 );
110 /***********************************************************************
111 * AdjustWindowRectEx16 (USER.454)
113 BOOL16 AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
114 BOOL16 menu, DWORD exStyle )
116 /* Correct the window style */
118 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
119 style |= WS_CAPTION;
120 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
122 dprintf_nonclient(stddeb, "AdjustWindowRectEx: (%d,%d)-(%d,%d) %08lx %d %08lx\n",
123 rect->left, rect->top, rect->right, rect->bottom,
124 style, menu, exStyle );
126 NC_AdjustRect( rect, style, menu, exStyle );
127 return TRUE;
131 /***********************************************************************
132 * AdjustWindowRectEx32 (USER32.)
134 BOOL32 AdjustWindowRectEx32( LPRECT32 rect, DWORD style,
135 BOOL32 menu, DWORD exStyle )
137 RECT16 rect16;
138 BOOL32 ret;
140 CONV_RECT32TO16( rect, &rect16 );
141 ret = AdjustWindowRectEx16( &rect16, style, (BOOL16)menu, exStyle );
142 CONV_RECT16TO32( &rect16, rect );
143 return ret;
147 /*******************************************************************
148 * NC_GetMinMaxInfo
150 * Get the minimized and maximized information for a window.
152 void NC_GetMinMaxInfo( HWND hwnd, POINT16 *maxSize, POINT16 *maxPos,
153 POINT16 *minTrack, POINT16 *maxTrack )
155 MINMAXINFO16 *MinMax;
156 short xinc, yinc;
157 WND *wndPtr = WIN_FindWndPtr( hwnd );
159 if (!(MinMax = SEGPTR_NEW(MINMAXINFO16))) return;
161 /* Compute default values */
163 MinMax->ptMaxSize.x = SYSMETRICS_CXSCREEN;
164 MinMax->ptMaxSize.y = SYSMETRICS_CYSCREEN;
165 MinMax->ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
166 MinMax->ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
167 MinMax->ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
168 MinMax->ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
170 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
171 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
173 xinc = SYSMETRICS_CXDLGFRAME;
174 yinc = SYSMETRICS_CYDLGFRAME;
176 else
178 xinc = yinc = 0;
179 if (HAS_THICKFRAME(wndPtr->dwStyle))
181 xinc += SYSMETRICS_CXFRAME;
182 yinc += SYSMETRICS_CYFRAME;
184 if (wndPtr->dwStyle & WS_BORDER)
186 xinc += SYSMETRICS_CXBORDER;
187 yinc += SYSMETRICS_CYBORDER;
190 MinMax->ptMaxSize.x += 2 * xinc;
191 MinMax->ptMaxSize.y += 2 * yinc;
193 /* Note: The '+' in the following test should really be a ||, but
194 * that would cause gcc-2.7.0 to generate incorrect code.
196 if ((wndPtr->ptMaxPos.x != -1) + (wndPtr->ptMaxPos.y != -1))
197 MinMax->ptMaxPosition = wndPtr->ptMaxPos;
198 else
200 MinMax->ptMaxPosition.x = -xinc;
201 MinMax->ptMaxPosition.y = -yinc;
204 SendMessage16( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)SEGPTR_GET(MinMax) );
206 /* Some sanity checks */
208 dprintf_nonclient(stddeb,
209 "NC_GetMinMaxInfo: %d %d / %d %d / %d %d / %d %d\n",
210 MinMax->ptMaxSize.x, MinMax->ptMaxSize.y,
211 MinMax->ptMaxPosition.x, MinMax->ptMaxPosition.y,
212 MinMax->ptMaxTrackSize.x, MinMax->ptMaxTrackSize.y,
213 MinMax->ptMinTrackSize.x, MinMax->ptMinTrackSize.y);
214 MinMax->ptMaxTrackSize.x = MAX( MinMax->ptMaxTrackSize.x,
215 MinMax->ptMinTrackSize.x );
216 MinMax->ptMaxTrackSize.y = MAX( MinMax->ptMaxTrackSize.y,
217 MinMax->ptMinTrackSize.y );
219 if (maxSize) *maxSize = MinMax->ptMaxSize;
220 if (maxPos) *maxPos = MinMax->ptMaxPosition;
221 if (minTrack) *minTrack = MinMax->ptMinTrackSize;
222 if (maxTrack) *maxTrack = MinMax->ptMaxTrackSize;
223 SEGPTR_FREE(MinMax);
227 /***********************************************************************
228 * NC_HandleNCCalcSize
230 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
232 LONG NC_HandleNCCalcSize( WND *pWnd, RECT16 *winRect )
234 RECT16 tmpRect = { 0, 0, 0, 0 };
235 LONG result = 0;
237 if (pWnd->class->style & CS_VREDRAW) result |= WVR_VREDRAW;
238 if (pWnd->class->style & CS_HREDRAW) result |= WVR_HREDRAW;
240 if( !( pWnd->dwStyle & WS_MINIMIZE ) )
242 NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
243 winRect->left -= tmpRect.left;
244 winRect->top -= tmpRect.top;
245 winRect->right -= tmpRect.right;
246 winRect->bottom -= tmpRect.bottom;
248 if (HAS_MENU(pWnd))
250 winRect->top += MENU_GetMenuBarHeight( pWnd->hwndSelf,
251 winRect->right - winRect->left,
252 -tmpRect.left, -tmpRect.top ) + 1;
255 return result;
259 /***********************************************************************
260 * NC_GetInsideRect
262 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
263 * but without the borders (if any).
264 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
266 static void NC_GetInsideRect( HWND hwnd, RECT16 *rect )
268 WND * wndPtr = WIN_FindWndPtr( hwnd );
270 rect->top = rect->left = 0;
271 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
272 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
274 if (wndPtr->dwStyle & WS_ICONIC) return; /* No border to remove */
275 if (wndPtr->flags & WIN_MANAGED) return;
277 /* Remove frame from rectangle */
278 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
280 InflateRect16( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
281 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
282 InflateRect16( rect, -1, 0 );
284 else
286 if (HAS_THICKFRAME( wndPtr->dwStyle ))
287 InflateRect16( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
288 if (wndPtr->dwStyle & WS_BORDER)
289 InflateRect16( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
294 /***********************************************************************
295 * NC_HandleNCHitTest
297 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
299 LONG NC_HandleNCHitTest( HWND hwnd, POINT16 pt )
301 RECT16 rect;
302 WND *wndPtr = WIN_FindWndPtr( hwnd );
303 if (!wndPtr) return HTERROR;
305 dprintf_nonclient(stddeb, "NC_HandleNCHitTest: hwnd=%04x pt=%d,%d\n",
306 hwnd, pt.x, pt.y );
308 GetWindowRect16( hwnd, &rect );
309 if (!PtInRect16( &rect, pt )) return HTNOWHERE;
311 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
313 if (!(wndPtr->flags & WIN_MANAGED))
315 /* Check borders */
316 if (HAS_THICKFRAME( wndPtr->dwStyle ))
318 InflateRect16( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
319 if (wndPtr->dwStyle & WS_BORDER)
320 InflateRect16(&rect,-SYSMETRICS_CXBORDER,-SYSMETRICS_CYBORDER);
321 if (!PtInRect16( &rect, pt ))
323 /* Check top sizing border */
324 if (pt.y < rect.top)
326 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
327 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
328 return HTTOP;
330 /* Check bottom sizing border */
331 if (pt.y >= rect.bottom)
333 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
334 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
335 return HTBOTTOM;
337 /* Check left sizing border */
338 if (pt.x < rect.left)
340 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
341 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
342 return HTLEFT;
344 /* Check right sizing border */
345 if (pt.x >= rect.right)
347 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
348 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
349 return HTRIGHT;
353 else /* No thick frame */
355 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
356 InflateRect16(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
357 else if (wndPtr->dwStyle & WS_BORDER)
358 InflateRect16(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
359 if (!PtInRect16( &rect, pt )) return HTBORDER;
362 /* Check caption */
364 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
366 rect.top += SYSMETRICS_CYCAPTION - 1;
367 if (!PtInRect16( &rect, pt ))
369 /* Check system menu */
370 if (wndPtr->dwStyle & WS_SYSMENU)
371 rect.left += SYSMETRICS_CXSIZE;
372 if (pt.x <= rect.left) return HTSYSMENU;
373 /* Check maximize box */
374 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
375 rect.right -= SYSMETRICS_CXSIZE + 1;
376 if (pt.x >= rect.right) return HTMAXBUTTON;
377 /* Check minimize box */
378 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
379 rect.right -= SYSMETRICS_CXSIZE + 1;
380 if (pt.x >= rect.right) return HTMINBUTTON;
381 return HTCAPTION;
386 /* Check client area */
388 ScreenToClient16( hwnd, &pt );
389 GetClientRect16( hwnd, &rect );
390 if (PtInRect16( &rect, pt )) return HTCLIENT;
392 /* Check vertical scroll bar */
394 if (wndPtr->dwStyle & WS_VSCROLL)
396 rect.right += SYSMETRICS_CXVSCROLL;
397 if (PtInRect16( &rect, pt )) return HTVSCROLL;
400 /* Check horizontal scroll bar */
402 if (wndPtr->dwStyle & WS_HSCROLL)
404 rect.bottom += SYSMETRICS_CYHSCROLL;
405 if (PtInRect16( &rect, pt ))
407 /* Check size box */
408 if ((wndPtr->dwStyle & WS_VSCROLL) &&
409 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
410 return HTSIZE;
411 return HTHSCROLL;
415 /* Check menu bar */
417 if (HAS_MENU(wndPtr))
419 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
420 return HTMENU;
423 /* Should never get here */
424 return HTERROR;
428 /***********************************************************************
429 * NC_DrawSysButton
431 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
433 RECT16 rect;
434 HDC hdcMem;
435 HBITMAP hbitmap;
436 WND *wndPtr = WIN_FindWndPtr( hwnd );
438 if( !(wndPtr->flags & WIN_MANAGED) )
440 NC_GetInsideRect( hwnd, &rect );
441 hdcMem = CreateCompatibleDC( hdc );
442 hbitmap = SelectObject( hdcMem, hbitmapClose );
443 BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
444 hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
445 down ? NOTSRCCOPY : SRCCOPY );
446 SelectObject( hdcMem, hbitmap );
447 DeleteDC( hdcMem );
452 /***********************************************************************
453 * NC_DrawMaxButton
455 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
457 RECT16 rect;
458 WND *wndPtr = WIN_FindWndPtr( hwnd );
460 if( !(wndPtr->flags & WIN_MANAGED) )
462 NC_GetInsideRect( hwnd, &rect );
463 GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
464 (down ? hbitmapRestoreD : hbitmapRestore) :
465 (down ? hbitmapMaximizeD : hbitmapMaximize)),
466 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
467 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
472 /***********************************************************************
473 * NC_DrawMinButton
475 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
477 RECT16 rect;
478 WND *wndPtr = WIN_FindWndPtr( hwnd );
480 if( !(wndPtr->flags & WIN_MANAGED) )
482 NC_GetInsideRect( hwnd, &rect );
483 if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
484 GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
485 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
486 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
491 /***********************************************************************
492 * NC_DrawFrame
494 * Draw a window frame inside the given rectangle, and update the rectangle.
495 * The correct pen for the frame must be selected in the DC.
497 static void NC_DrawFrame( HDC hdc, RECT16 *rect, BOOL dlgFrame, BOOL active )
499 short width, height, tmp;
501 if (dlgFrame)
503 width = SYSMETRICS_CXDLGFRAME - 1;
504 height = SYSMETRICS_CYDLGFRAME - 1;
505 SelectObject( hdc, active ? sysColorObjects.hbrushActiveCaption :
506 sysColorObjects.hbrushInactiveCaption );
508 else
510 width = SYSMETRICS_CXFRAME - 1;
511 height = SYSMETRICS_CYFRAME - 1;
512 SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
513 sysColorObjects.hbrushInactiveBorder );
516 /* Draw frame */
517 PatBlt( hdc, rect->left, rect->top,
518 rect->right - rect->left, height, PATCOPY );
519 PatBlt( hdc, rect->left, rect->top,
520 width, rect->bottom - rect->top, PATCOPY );
521 PatBlt( hdc, rect->left, rect->bottom,
522 rect->right - rect->left, -height, PATCOPY );
523 PatBlt( hdc, rect->right, rect->top,
524 -width, rect->bottom - rect->top, PATCOPY );
526 if (dlgFrame)
528 InflateRect16( rect, -width, -height );
529 return;
532 /* Draw inner rectangle */
533 MoveTo( hdc, rect->left+width, rect->top+height );
534 LineTo( hdc, rect->right-width-1, rect->top+height );
535 LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
536 LineTo( hdc, rect->left+width, rect->bottom-height-1 );
537 LineTo( hdc, rect->left+width, rect->top+height );
539 /* Draw the decorations */
540 tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
541 MoveTo( hdc, rect->left, tmp);
542 LineTo( hdc, rect->left+width, tmp );
543 MoveTo( hdc, rect->right-width-1, tmp );
544 LineTo( hdc, rect->right-1, tmp );
546 tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
547 MoveTo( hdc, rect->left, tmp );
548 LineTo( hdc, rect->left+width, tmp );
549 MoveTo( hdc, rect->right-width-1, tmp );
550 LineTo( hdc, rect->right-1, tmp );
552 tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
553 MoveTo( hdc, tmp, rect->top );
554 LineTo( hdc, tmp, rect->top+height );
555 MoveTo( hdc, tmp, rect->bottom-height-1 );
556 LineTo( hdc, tmp, rect->bottom-1 );
558 tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
559 MoveTo( hdc, tmp, rect->top );
560 LineTo( hdc, tmp, rect->top+height );
561 MoveTo( hdc, tmp, rect->bottom-height-1 );
562 LineTo( hdc, tmp, rect->bottom-1 );
564 InflateRect16( rect, -width-1, -height-1 );
568 /***********************************************************************
569 * NC_DrawMovingFrame
571 * Draw the frame used when moving or resizing window.
573 static void NC_DrawMovingFrame( HDC hdc, RECT16 *rect, BOOL thickframe )
575 if (thickframe)
577 SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
578 PatBlt( hdc, rect->left, rect->top,
579 rect->right - rect->left - SYSMETRICS_CXFRAME,
580 SYSMETRICS_CYFRAME, PATINVERT );
581 PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
582 SYSMETRICS_CXFRAME,
583 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
584 PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
585 rect->right - rect->left - SYSMETRICS_CXFRAME,
586 -SYSMETRICS_CYFRAME, PATINVERT );
587 PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME,
588 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
590 else DrawFocusRect16( hdc, rect );
594 /***********************************************************************
595 * NC_DrawCaption
597 * Draw the window caption.
598 * The correct pen for the window frame must be selected in the DC.
600 static void NC_DrawCaption( HDC hdc, RECT16 *rect, HWND hwnd,
601 DWORD style, BOOL active )
603 RECT16 r = *rect;
604 WND * wndPtr = WIN_FindWndPtr( hwnd );
605 char buffer[256];
607 if (wndPtr->flags & WIN_MANAGED) return;
609 if (!hbitmapClose)
611 if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
612 return;
613 hbitmapMinimize = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_REDUCE) );
614 hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_REDUCED) );
615 hbitmapMaximize = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_ZOOM) );
616 hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
617 hbitmapRestore = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORE) );
618 hbitmapRestoreD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORED) );
621 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
623 HBRUSH hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
624 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
625 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
626 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
627 r.left++;
628 r.right--;
629 SelectObject( hdc, hbrushOld );
632 MoveTo( hdc, r.left, r.bottom );
633 LineTo( hdc, r.right-1, r.bottom );
635 if (style & WS_SYSMENU)
637 NC_DrawSysButton( hwnd, hdc, FALSE );
638 r.left += SYSMETRICS_CXSIZE + 1;
639 MoveTo( hdc, r.left - 1, r.top );
640 LineTo( hdc, r.left - 1, r.bottom );
642 if (style & WS_MAXIMIZEBOX)
644 NC_DrawMaxButton( hwnd, hdc, FALSE );
645 r.right -= SYSMETRICS_CXSIZE + 1;
647 if (style & WS_MINIMIZEBOX)
649 NC_DrawMinButton( hwnd, hdc, FALSE );
650 r.right -= SYSMETRICS_CXSIZE + 1;
653 FillRect16( hdc, &r, active ? sysColorObjects.hbrushActiveCaption :
654 sysColorObjects.hbrushInactiveCaption );
656 if (GetWindowText32A( hwnd, buffer, sizeof(buffer) ))
658 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
659 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
660 SetBkMode( hdc, TRANSPARENT );
661 DrawText16( hdc, buffer, -1, &r,
662 DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
667 /***********************************************************************
668 * NC_DoNCPaint
670 * Paint the non-client area. clip is currently unused.
672 void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
674 HDC32 hdc;
675 RECT16 rect;
676 BOOL active;
678 WND *wndPtr = WIN_FindWndPtr( hwnd );
680 if (!wndPtr || wndPtr->dwStyle & WS_MINIMIZE ||
681 !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
683 active = wndPtr->flags & WIN_NCACTIVATED;
685 dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
687 if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
689 if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
690 wndPtr->rectClient.top-wndPtr->rectWindow.top,
691 wndPtr->rectClient.right-wndPtr->rectWindow.left,
692 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
693 == NULLREGION)
695 ReleaseDC32( hwnd, hdc );
696 return;
699 rect.top = rect.left = 0;
700 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
701 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
703 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
705 if (!(wndPtr->flags & WIN_MANAGED))
707 if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
708 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
710 MoveTo( hdc, 0, 0 );
711 LineTo( hdc, rect.right-1, 0 );
712 LineTo( hdc, rect.right-1, rect.bottom-1 );
713 LineTo( hdc, 0, rect.bottom-1 );
714 LineTo( hdc, 0, 0 );
715 InflateRect16( &rect, -1, -1 );
718 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
719 NC_DrawFrame( hdc, &rect, TRUE, active );
720 else if (wndPtr->dwStyle & WS_THICKFRAME)
721 NC_DrawFrame(hdc, &rect, FALSE, active );
723 if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
725 RECT16 r = rect;
726 r.bottom = rect.top + SYSMETRICS_CYSIZE;
727 rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
728 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
732 if (HAS_MENU(wndPtr))
734 RECT16 r = rect;
735 r.bottom = rect.top + SYSMETRICS_CYMENU; /* default height */
736 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
739 /* Draw the scroll-bars */
741 if (wndPtr->dwStyle & WS_VSCROLL)
742 SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE );
743 if (wndPtr->dwStyle & WS_HSCROLL)
744 SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE );
746 /* Draw the "size-box" */
748 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
750 RECT16 r = rect;
751 r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
752 r.top = r.bottom - SYSMETRICS_CYHSCROLL + 1;
753 FillRect16( hdc, &r, sysColorObjects.hbrushScrollbar );
756 ReleaseDC32( hwnd, hdc );
761 /***********************************************************************
762 * NC_HandleNCPaint
764 * Handle a WM_NCPAINT message. Called from DefWindowProc().
766 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
768 NC_DoNCPaint( hwnd, clip, FALSE );
769 return 0;
773 /***********************************************************************
774 * NC_HandleNCActivate
776 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
778 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM wParam )
780 WORD wStateChange;
782 if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
783 else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
785 if( wStateChange )
787 if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
788 else wndPtr->flags &= ~WIN_NCACTIVATED;
790 if( wndPtr->dwStyle & WS_MINIMIZE )
791 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, 0 );
792 else
793 NC_DoNCPaint( wndPtr->hwndSelf, (HRGN)1, FALSE );
795 return TRUE;
799 /***********************************************************************
800 * NC_HandleSetCursor
802 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
804 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
806 if (hwnd != (HWND)wParam) return 0; /* Don't set the cursor for child windows */
808 switch(LOWORD(lParam))
810 case HTERROR:
812 WORD msg = HIWORD( lParam );
813 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
814 (msg == WM_RBUTTONDOWN))
815 MessageBeep(0);
817 break;
819 case HTCLIENT:
821 WND *wndPtr;
822 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
823 if (wndPtr->class->hCursor)
825 SetCursor( wndPtr->class->hCursor );
826 return TRUE;
828 else return FALSE;
831 case HTLEFT:
832 case HTRIGHT:
833 return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZEWE ) );
835 case HTTOP:
836 case HTBOTTOM:
837 return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENS ) );
839 case HTTOPLEFT:
840 case HTBOTTOMRIGHT:
841 return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENWSE ) );
843 case HTTOPRIGHT:
844 case HTBOTTOMLEFT:
845 return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENESW ) );
848 /* Default cursor: arrow */
849 return (LONG)SetCursor( LoadCursor16( 0, IDC_ARROW ) );
852 /***********************************************************************
853 * NC_GetSysPopupPos
855 BOOL NC_GetSysPopupPos( WND* wndPtr, RECT16* rect )
857 if( !wndPtr->hSysMenu ) return FALSE;
859 NC_GetInsideRect( wndPtr->hwndSelf, rect );
860 OffsetRect16( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
861 if (wndPtr->dwStyle & WS_CHILD)
862 ClientToScreen16( wndPtr->parent->hwndSelf, (POINT16 *)rect );
863 rect->right = rect->left + SYSMETRICS_CXSIZE;
864 rect->bottom = rect->top + SYSMETRICS_CYSIZE;
865 return TRUE;
868 /***********************************************************************
869 * NC_TrackSysMenu
871 * Track a mouse button press on the system menu.
873 static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT16 pt )
875 RECT16 rect;
876 WND *wndPtr = WIN_FindWndPtr( hwnd );
877 int iconic = wndPtr->dwStyle & WS_MINIMIZE;
878 HMENU hmenu;
880 if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
882 /* If window has a menu, track the menu bar normally if it not minimized */
883 if (HAS_MENU(wndPtr) && !iconic) MENU_TrackMouseMenuBar( hwnd, pt );
884 else
886 /* Otherwise track the system menu like a normal popup menu */
888 NC_GetSysPopupPos( wndPtr, &rect );
889 if (!iconic) NC_DrawSysButton( hwnd, hdc, TRUE );
890 hmenu = GetSystemMenu(hwnd, 0);
891 MENU_InitSysMenuPopup(hmenu, wndPtr->dwStyle,
892 wndPtr->class->style);
893 TrackPopupMenu16( hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
894 rect.left, rect.bottom, 0, hwnd, &rect );
895 if (!iconic) NC_DrawSysButton( hwnd, hdc, FALSE );
900 /***********************************************************************
901 * NC_StartSizeMove
903 * Initialisation of a move or resize, when initiatied from a menu choice.
904 * Return hit test code for caption or sizing border.
906 static LONG NC_StartSizeMove( HWND hwnd, WPARAM wParam, POINT16 *capturePoint )
908 LONG hittest = 0;
909 POINT16 pt;
910 MSG16 msg;
911 WND * wndPtr = WIN_FindWndPtr( hwnd );
913 if ((wParam & 0xfff0) == SC_MOVE)
915 /* Move pointer at the center of the caption */
916 RECT16 rect;
917 NC_GetInsideRect( hwnd, &rect );
918 if (wndPtr->dwStyle & WS_SYSMENU)
919 rect.left += SYSMETRICS_CXSIZE + 1;
920 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
921 rect.right -= SYSMETRICS_CXSIZE + 1;
922 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
923 rect.right -= SYSMETRICS_CXSIZE + 1;
924 pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
925 pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
926 if (wndPtr->dwStyle & WS_CHILD)
927 ClientToScreen16( wndPtr->parent->hwndSelf, &pt );
928 hittest = HTCAPTION;
930 else /* SC_SIZE */
932 SetCapture32(hwnd);
933 while(!hittest)
935 MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
936 switch(msg.message)
938 case WM_MOUSEMOVE:
939 hittest = NC_HandleNCHitTest( hwnd, msg.pt );
940 pt = msg.pt;
941 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
942 hittest = 0;
943 break;
945 case WM_LBUTTONUP:
946 return 0;
948 case WM_KEYDOWN:
949 switch(msg.wParam)
951 case VK_UP:
952 hittest = HTTOP;
953 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
954 pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
955 break;
956 case VK_DOWN:
957 hittest = HTBOTTOM;
958 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
959 pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
960 break;
961 case VK_LEFT:
962 hittest = HTLEFT;
963 pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
964 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
965 break;
966 case VK_RIGHT:
967 hittest = HTRIGHT;
968 pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
969 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
970 break;
971 case VK_RETURN:
972 case VK_ESCAPE: return 0;
977 *capturePoint = pt;
978 SetCursorPos( capturePoint->x, capturePoint->y );
979 NC_HandleSetCursor( hwnd, (WPARAM)hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
980 return hittest;
984 /***********************************************************************
985 * NC_DoSizeMove
987 * Perform SC_MOVE and SC_SIZE commands.
989 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT16 pt )
991 MSG16 msg;
992 LONG hittest;
993 RECT16 sizingRect, mouseRect;
994 HDC32 hdc;
995 BOOL thickframe;
996 POINT16 minTrack, maxTrack, capturePoint = pt;
997 WND * wndPtr = WIN_FindWndPtr( hwnd );
998 int moved = 0;
1000 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) ||
1001 (wndPtr->flags & WIN_MANAGED)) return;
1002 hittest = wParam & 0x0f;
1003 thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
1005 if ((wParam & 0xfff0) == SC_MOVE)
1007 if (!(wndPtr->dwStyle & WS_CAPTION)) return;
1008 if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
1009 if (!hittest) return;
1011 else /* SC_SIZE */
1013 if (!thickframe) return;
1014 if (hittest) hittest += HTLEFT-1;
1015 else
1017 SetCapture32(hwnd);
1018 hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
1019 if (!hittest)
1021 ReleaseCapture();
1022 return;
1027 /* Get min/max info */
1029 NC_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1030 sizingRect = wndPtr->rectWindow;
1031 if (wndPtr->dwStyle & WS_CHILD)
1032 GetClientRect16( wndPtr->parent->hwndSelf, &mouseRect );
1033 else SetRect16(&mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN);
1034 if (ON_LEFT_BORDER(hittest))
1036 mouseRect.left = MAX( mouseRect.left, sizingRect.right-maxTrack.x );
1037 mouseRect.right = MIN( mouseRect.right, sizingRect.right-minTrack.x );
1039 else if (ON_RIGHT_BORDER(hittest))
1041 mouseRect.left = MAX( mouseRect.left, sizingRect.left+minTrack.x );
1042 mouseRect.right = MIN( mouseRect.right, sizingRect.left+maxTrack.x );
1044 if (ON_TOP_BORDER(hittest))
1046 mouseRect.top = MAX( mouseRect.top, sizingRect.bottom-maxTrack.y );
1047 mouseRect.bottom = MIN( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1049 else if (ON_BOTTOM_BORDER(hittest))
1051 mouseRect.top = MAX( mouseRect.top, sizingRect.top+minTrack.y );
1052 mouseRect.bottom = MIN( mouseRect.bottom, sizingRect.top+maxTrack.y );
1054 SendMessage16( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1056 if (GetCapture32() != hwnd) SetCapture32( hwnd );
1058 if (wndPtr->dwStyle & WS_CHILD)
1060 /* Retrieve a default cache DC (without using the window style) */
1061 hdc = GetDCEx32( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
1063 else
1064 { /* Grab the server only when moving top-level windows without desktop */
1065 hdc = GetDC32( 0 );
1066 if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
1068 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1070 while(1)
1072 int dx = 0, dy = 0;
1074 MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
1076 /* Exit on button-up, Return, or Esc */
1077 if ((msg.message == WM_LBUTTONUP) ||
1078 ((msg.message == WM_KEYDOWN) &&
1079 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1081 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1082 continue; /* We are not interested in other messages */
1084 pt = msg.pt;
1085 if (wndPtr->dwStyle & WS_CHILD)
1086 ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1088 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1090 case VK_UP: pt.y -= 8; break;
1091 case VK_DOWN: pt.y += 8; break;
1092 case VK_LEFT: pt.x -= 8; break;
1093 case VK_RIGHT: pt.x += 8; break;
1096 pt.x = MAX( pt.x, mouseRect.left );
1097 pt.x = MIN( pt.x, mouseRect.right );
1098 pt.y = MAX( pt.y, mouseRect.top );
1099 pt.y = MIN( pt.y, mouseRect.bottom );
1101 dx = pt.x - capturePoint.x;
1102 dy = pt.y - capturePoint.y;
1104 if (dx || dy)
1106 moved = 1;
1107 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1108 else
1110 RECT16 newRect = sizingRect;
1112 if (hittest == HTCAPTION) OffsetRect16( &newRect, dx, dy );
1113 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1114 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1115 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1116 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1117 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1118 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1119 capturePoint = pt;
1120 sizingRect = newRect;
1125 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1126 ReleaseCapture();
1128 if (wndPtr->dwStyle & WS_CHILD)
1129 ReleaseDC32( wndPtr->parent->hwndSelf, hdc );
1130 else
1132 ReleaseDC32( 0, hdc );
1133 if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1136 if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
1138 RECT16* pr = SEGPTR_NEW(RECT16);
1139 if( pr )
1141 *pr = sizingRect;
1142 if( HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, hwnd,
1143 (LPARAM)SEGPTR_GET(pr)) )
1144 sizingRect = wndPtr->rectWindow;
1145 else
1146 sizingRect = *pr;
1147 SEGPTR_FREE(pr);
1150 SendMessage16( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1151 SendMessage16( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1153 /* Single click brings up the system menu when iconized */
1155 if (!moved && (wndPtr->dwStyle & WS_MINIMIZE))
1157 NC_TrackSysMenu( hwnd, hdc, pt );
1158 return;
1161 /* If Esc key, don't move the window */
1162 if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1164 if (hittest != HTCAPTION)
1165 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1166 sizingRect.right - sizingRect.left,
1167 sizingRect.bottom - sizingRect.top,
1168 SWP_NOACTIVATE | SWP_NOZORDER );
1169 else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1170 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1174 /***********************************************************************
1175 * NC_TrackMinMaxBox
1177 * Track a mouse button press on the minimize or maximize box.
1179 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1181 MSG16 msg;
1182 HDC32 hdc = GetWindowDC32( hwnd );
1183 BOOL pressed = TRUE;
1185 SetCapture32( hwnd );
1186 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1187 else NC_DrawMaxButton( hwnd, hdc, TRUE );
1191 BOOL oldstate = pressed;
1192 MSG_InternalGetMessage( &msg, 0, 0, 0, PM_REMOVE, FALSE );
1194 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1195 if (pressed != oldstate)
1197 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1198 else NC_DrawMaxButton( hwnd, hdc, pressed );
1200 } while (msg.message != WM_LBUTTONUP);
1202 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1203 else NC_DrawMaxButton( hwnd, hdc, FALSE );
1205 ReleaseCapture();
1206 ReleaseDC32( hwnd, hdc );
1207 if (!pressed) return;
1209 if (wParam == HTMINBUTTON)
1210 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1211 else
1212 SendMessage16( hwnd, WM_SYSCOMMAND,
1213 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1217 /***********************************************************************
1218 * NC_TrackScrollBar
1220 * Track a mouse button press on the horizontal or vertical scroll-bar.
1222 static void NC_TrackScrollBar( HWND32 hwnd, WPARAM32 wParam, POINT32 pt )
1224 MSG16 *msg;
1225 INT32 scrollbar;
1226 WND *wndPtr = WIN_FindWndPtr( hwnd );
1228 if ((wParam & 0xfff0) == SC_HSCROLL)
1230 if ((wParam & 0x0f) != HTHSCROLL) return;
1231 scrollbar = SB_HORZ;
1233 else /* SC_VSCROLL */
1235 if ((wParam & 0x0f) != HTVSCROLL) return;
1236 scrollbar = SB_VERT;
1239 if (!(msg = SEGPTR_NEW(MSG16))) return;
1240 pt.x -= wndPtr->rectWindow.left;
1241 pt.y -= wndPtr->rectWindow.top;
1242 SetCapture32( hwnd );
1243 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1247 GetMessage( SEGPTR_GET(msg), 0, 0, 0 );
1248 switch(msg->message)
1250 case WM_LBUTTONUP:
1251 case WM_MOUSEMOVE:
1252 case WM_SYSTIMER:
1253 pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left -
1254 wndPtr->rectWindow.left;
1255 pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top -
1256 wndPtr->rectWindow.top;
1257 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
1258 break;
1259 default:
1260 TranslateMessage( msg );
1261 DispatchMessage( msg );
1262 break;
1264 if (!IsWindow( hwnd ))
1266 ReleaseCapture();
1267 break;
1269 } while (msg->message != WM_LBUTTONUP);
1270 SEGPTR_FREE(msg);
1273 /***********************************************************************
1274 * NC_HandleNCLButtonDown
1276 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1278 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1280 HDC32 hdc;
1282 switch(wParam) /* Hit test */
1284 case HTCAPTION:
1285 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1286 break;
1288 case HTSYSMENU:
1289 hdc = GetWindowDC32( hwnd );
1290 NC_TrackSysMenu( hwnd, hdc, MAKEPOINT16(lParam) );
1291 ReleaseDC32( hwnd, hdc );
1292 break;
1294 case HTMENU:
1295 SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1296 break;
1298 case HTHSCROLL:
1299 SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1300 break;
1302 case HTVSCROLL:
1303 SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1304 break;
1306 case HTMINBUTTON:
1307 case HTMAXBUTTON:
1308 NC_TrackMinMaxBox( hwnd, wParam );
1309 break;
1311 case HTLEFT:
1312 case HTRIGHT:
1313 case HTTOP:
1314 case HTTOPLEFT:
1315 case HTTOPRIGHT:
1316 case HTBOTTOM:
1317 case HTBOTTOMLEFT:
1318 case HTBOTTOMRIGHT:
1319 SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1320 break;
1322 case HTBORDER:
1323 break;
1325 return 0;
1329 /***********************************************************************
1330 * NC_HandleNCLButtonDblClk
1332 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1334 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM wParam, LPARAM lParam )
1337 * if this is an icon, send a restore since we are handling
1338 * a double click
1340 if (pWnd->dwStyle & WS_MINIMIZE)
1342 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
1343 return 0;
1346 switch(wParam) /* Hit test */
1348 case HTCAPTION:
1349 /* stop processing if WS_MAXIMIZEBOX is missing */
1350 if (pWnd->dwStyle & WS_MAXIMIZEBOX)
1351 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
1352 (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
1353 lParam );
1354 break;
1356 case HTSYSMENU:
1357 if (!(pWnd->class->style & CS_NOCLOSE))
1358 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
1359 break;
1361 return 0;
1365 /***********************************************************************
1366 * NC_HandleSysCommand
1368 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1370 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT16 pt )
1372 WND *wndPtr = WIN_FindWndPtr( hwnd );
1373 POINT32 pt32;
1375 dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n",
1376 wParam, pt.x, pt.y );
1378 if (wndPtr->dwStyle & WS_CHILD && wParam != SC_KEYMENU )
1379 ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1381 switch (wParam & 0xfff0)
1383 case SC_SIZE:
1384 case SC_MOVE:
1385 NC_DoSizeMove( hwnd, wParam, pt );
1386 break;
1388 case SC_MINIMIZE:
1389 ShowWindow( hwnd, SW_MINIMIZE );
1390 break;
1392 case SC_MAXIMIZE:
1393 ShowWindow( hwnd, SW_MAXIMIZE );
1394 break;
1396 case SC_RESTORE:
1397 ShowWindow( hwnd, SW_RESTORE );
1398 break;
1400 case SC_NEXTWINDOW:
1401 case SC_PREVWINDOW:
1402 break;
1404 case SC_CLOSE:
1405 return SendMessage16( hwnd, WM_CLOSE, 0, 0 );
1407 case SC_VSCROLL:
1408 case SC_HSCROLL:
1409 CONV_POINT16TO32( &pt, &pt32 );
1410 NC_TrackScrollBar( hwnd, wParam, pt32 );
1411 break;
1413 case SC_MOUSEMENU:
1414 MENU_TrackMouseMenuBar( hwnd, pt );
1415 break;
1417 case SC_KEYMENU:
1418 MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
1419 break;
1421 case SC_ARRANGE:
1422 break;
1424 case SC_TASKLIST:
1425 WinExec( "taskman.exe", SW_SHOWNORMAL );
1426 break;
1428 case SC_HOTKEY:
1429 break;
1431 case SC_SCREENSAVE:
1432 if (wParam == SC_ABOUTWINE)
1434 extern const char people[];
1435 ShellAbout(hwnd,"WINE",people,0);
1437 break;
1439 return 0;