Release 951212
[wine/multimedia.git] / windows / nonclient.c
blob9df7ae5e45fa249477d74059049465186b91b79d
1 /*
2 * Non-client area window functions
4 * Copyright 1994 Alexandre Julliard
6 */
8 #include "win.h"
9 #include "class.h"
10 #include "message.h"
11 #include "sysmetrics.h"
12 #include "user.h"
13 #include "shell.h"
14 #include "dialog.h"
15 #include "syscolor.h"
16 #include "menu.h"
17 #include "winpos.h"
18 #include "scroll.h"
19 #include "nonclient.h"
20 #include "graphics.h"
21 #include "selectors.h"
22 #include "stackframe.h"
23 #include "stddebug.h"
24 /* #define DEBUG_NONCLIENT */
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 IS_MANAGED(style) \
41 (Options.managed && !((style) & WS_CHILD))
43 #define HAS_DLGFRAME(style,exStyle) \
44 (!(IS_MANAGED(style)) && \
45 (((exStyle) & WS_EX_DLGMODALFRAME) || \
46 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER))))
48 #define HAS_THICKFRAME(style) \
49 (!(IS_MANAGED(style)) && \
50 ((style) & WS_THICKFRAME) && \
51 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
53 #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
55 #define ON_LEFT_BORDER(hit) \
56 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
57 #define ON_RIGHT_BORDER(hit) \
58 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
59 #define ON_TOP_BORDER(hit) \
60 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
61 #define ON_BOTTOM_BORDER(hit) \
62 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
64 /***********************************************************************
65 * NC_AdjustRect
67 * Compute the size of the window rectangle from the size of the
68 * client rectangle.
70 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
72 if (style & WS_ICONIC) return; /* Nothing to change for an icon */
73 if (IS_MANAGED(style)) return;
74 if (HAS_DLGFRAME( style, exStyle ))
75 InflateRect( rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
76 else
78 if (HAS_THICKFRAME(style))
79 InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
80 if (style & WS_BORDER)
81 InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER );
84 if ((style & WS_CAPTION) == WS_CAPTION)
85 rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
86 if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
88 if (style & WS_VSCROLL) rect->right += SYSMETRICS_CXVSCROLL;
89 if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
93 /***********************************************************************
94 * AdjustWindowRect (USER.102)
96 void AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
98 AdjustWindowRectEx( rect, style, menu, 0 );
102 /***********************************************************************
103 * AdjustWindowRectEx (USER.454)
105 void AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
107 /* Correct the window style */
109 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
110 style |= WS_CAPTION;
111 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
113 dprintf_nonclient(stddeb, "AdjustWindowRectEx: (%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
114 (LONG)rect->left, (LONG)rect->top, (LONG)rect->right, (LONG)rect->bottom,
115 style, menu, exStyle );
117 NC_AdjustRect( rect, style, menu, exStyle );
121 /*******************************************************************
122 * NC_GetMinMaxInfo
124 * Get the minimized and maximized information for a window.
126 void NC_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
127 POINT *minTrack, POINT *maxTrack )
129 MINMAXINFO MinMax;
130 short xinc, yinc;
131 WND *wndPtr = WIN_FindWndPtr( hwnd );
133 /* Compute default values */
135 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
136 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
137 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
138 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
139 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
140 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
142 if (IS_MANAGED(wndPtr->dwStyle))
143 xinc = yinc = 0;
144 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
146 xinc = SYSMETRICS_CXDLGFRAME;
147 yinc = SYSMETRICS_CYDLGFRAME;
149 else
151 xinc = yinc = 0;
152 if (HAS_THICKFRAME(wndPtr->dwStyle))
154 xinc += SYSMETRICS_CXFRAME;
155 yinc += SYSMETRICS_CYFRAME;
157 if (wndPtr->dwStyle & WS_BORDER)
159 xinc += SYSMETRICS_CXBORDER;
160 yinc += SYSMETRICS_CYBORDER;
163 MinMax.ptMaxSize.x += 2 * xinc;
164 MinMax.ptMaxSize.y += 2 * yinc;
166 /* Note: The '+' in the following test should really be a ||, but
167 * that would cause gcc-2.7.0 to generate incorrect code.
169 if ((wndPtr->ptMaxPos.x != -1) + (wndPtr->ptMaxPos.y != -1))
170 MinMax.ptMaxPosition = wndPtr->ptMaxPos;
171 else
173 MinMax.ptMaxPosition.x = -xinc;
174 MinMax.ptMaxPosition.y = -yinc;
177 SendMessage( hwnd, WM_GETMINMAXINFO, 0, MAKE_SEGPTR(&MinMax) );
179 /* Some sanity checks */
181 dprintf_nonclient(stddeb,
182 "NC_GetMinMaxInfo: %d %d / %d %d / %d %d / %d %d\n",
183 MinMax.ptMaxSize.x,MinMax.ptMaxSize.y,
184 MinMax.ptMaxPosition.x,MinMax.ptMaxPosition.y,
185 MinMax.ptMaxTrackSize.x,MinMax.ptMaxTrackSize.y,
186 MinMax.ptMinTrackSize.x,MinMax.ptMinTrackSize.y);
187 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
188 MinMax.ptMinTrackSize.x );
189 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
190 MinMax.ptMinTrackSize.y );
192 if (maxSize) *maxSize = MinMax.ptMaxSize;
193 if (maxPos) *maxPos = MinMax.ptMaxPosition;
194 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
195 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
199 /***********************************************************************
200 * NC_HandleNCCalcSize
202 * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
204 LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params )
206 RECT tmpRect = { 0, 0, 0, 0 };
207 WND *wndPtr = WIN_FindWndPtr( hwnd );
209 if (!wndPtr) return 0;
210 NC_AdjustRect( &tmpRect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle );
211 params->rgrc[0].left -= tmpRect.left;
212 params->rgrc[0].top -= tmpRect.top;
213 params->rgrc[0].right -= tmpRect.right;
214 params->rgrc[0].bottom -= tmpRect.bottom;
216 if (HAS_MENU(wndPtr))
218 params->rgrc[0].top += MENU_GetMenuBarHeight( hwnd,
219 params->rgrc[0].right - params->rgrc[0].left,
220 -tmpRect.left, -tmpRect.top ) + 1;
222 return 0;
226 /***********************************************************************
227 * NC_GetInsideRect
229 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
230 * but without the borders (if any).
231 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
233 void NC_GetInsideRect( HWND hwnd, RECT *rect )
235 WND * wndPtr = WIN_FindWndPtr( hwnd );
237 rect->top = rect->left = 0;
238 rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
239 rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
241 if (wndPtr->dwStyle & WS_ICONIC) return; /* No border to remove */
242 if (IS_MANAGED(wndPtr->dwStyle)) return;
244 /* Remove frame from rectangle */
245 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
247 InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
248 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
250 else
252 if (HAS_THICKFRAME( wndPtr->dwStyle ))
253 InflateRect( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
254 if (wndPtr->dwStyle & WS_BORDER)
255 InflateRect( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
260 /***********************************************************************
261 * NC_HandleNCHitTest
263 * Handle a WM_NCHITTEST message. Called from DefWindowProc().
265 LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
267 RECT rect;
268 WND *wndPtr = WIN_FindWndPtr( hwnd );
269 if (!wndPtr) return HTERROR;
271 dprintf_nonclient(stddeb, "NC_HandleNCHitTest: hwnd="NPFMT" pt=%ld,%ld\n",
272 hwnd, (LONG)pt.x, (LONG)pt.y );
274 GetWindowRect( hwnd, &rect );
275 if (!PtInRect( &rect, pt )) return HTNOWHERE;
278 * if this is a iconic window, we don't care were the hit
279 * occured, only that it did occur, just return HTCAPTION
280 * so the caller knows the icon did get hit
282 if (IsIconic(hwnd))
284 return HTCAPTION; /* change this to something meaningful? */
287 /* Check borders */
288 if (HAS_THICKFRAME( wndPtr->dwStyle ))
290 InflateRect( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
291 if (wndPtr->dwStyle & WS_BORDER)
292 InflateRect( &rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
293 if (!PtInRect( &rect, pt ))
295 /* Check top sizing border */
296 if (pt.y < rect.top)
298 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
299 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
300 return HTTOP;
302 /* Check bottom sizing border */
303 if (pt.y >= rect.bottom)
305 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
306 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
307 return HTBOTTOM;
309 /* Check left sizing border */
310 if (pt.x < rect.left)
312 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
313 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
314 return HTLEFT;
316 /* Check right sizing border */
317 if (pt.x >= rect.right)
319 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
320 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
321 return HTRIGHT;
325 else /* No thick frame */
327 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
328 InflateRect(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
329 else if (!(IS_MANAGED(wndPtr->dwStyle)) &&
330 (wndPtr->dwStyle & WS_BORDER))
331 InflateRect(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
332 if (!PtInRect( &rect, pt )) return HTBORDER;
335 /* Check caption */
337 if (!(IS_MANAGED(wndPtr->dwStyle)) &&
338 ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION))
340 rect.top += SYSMETRICS_CYCAPTION - 1;
341 if (!PtInRect( &rect, pt ))
343 /* Check system menu */
344 if (wndPtr->dwStyle & WS_SYSMENU)
345 rect.left += SYSMETRICS_CXSIZE;
346 if (pt.x <= rect.left) return HTSYSMENU;
347 /* Check maximize box */
348 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
349 rect.right -= SYSMETRICS_CXSIZE + 1;
350 if (pt.x >= rect.right) return HTMAXBUTTON;
351 /* Check minimize box */
352 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
353 rect.right -= SYSMETRICS_CXSIZE + 1;
354 if (pt.x >= rect.right) return HTMINBUTTON;
355 return HTCAPTION;
359 /* Check client area */
361 ScreenToClient( hwnd, &pt );
362 GetClientRect( hwnd, &rect );
363 if (PtInRect( &rect, pt )) return HTCLIENT;
365 /* Check vertical scroll bar */
367 if (wndPtr->dwStyle & WS_VSCROLL)
369 rect.right += SYSMETRICS_CXVSCROLL;
370 if (PtInRect( &rect, pt )) return HTVSCROLL;
373 /* Check horizontal scroll bar */
375 if (wndPtr->dwStyle & WS_HSCROLL)
377 rect.bottom += SYSMETRICS_CYHSCROLL;
378 if (PtInRect( &rect, pt ))
380 /* Check size box */
381 if ((wndPtr->dwStyle & WS_VSCROLL) &&
382 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
383 return HTSIZE;
384 return HTHSCROLL;
388 /* Check menu bar */
390 if (HAS_MENU(wndPtr))
392 if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
393 return HTMENU;
396 /* Should never get here */
397 return HTERROR;
401 /***********************************************************************
402 * NC_DrawSysButton
404 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
406 RECT rect;
407 HDC hdcMem;
408 HBITMAP hbitmap;
409 WND *wndPtr = WIN_FindWndPtr( hwnd );
411 NC_GetInsideRect( hwnd, &rect );
412 hdcMem = CreateCompatibleDC( hdc );
413 hbitmap = SelectObject( hdcMem, hbitmapClose );
414 BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
415 hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
416 down ? NOTSRCCOPY : SRCCOPY );
417 SelectObject( hdcMem, hbitmap );
418 DeleteDC( hdcMem );
422 /***********************************************************************
423 * NC_DrawMaxButton
425 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
427 RECT rect;
428 NC_GetInsideRect( hwnd, &rect );
429 GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
430 (down ? hbitmapRestoreD : hbitmapRestore) :
431 (down ? hbitmapMaximizeD : hbitmapMaximize)),
432 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
433 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
437 /***********************************************************************
438 * NC_DrawMinButton
440 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
442 RECT rect;
443 WND *wndPtr = WIN_FindWndPtr( hwnd );
444 NC_GetInsideRect( hwnd, &rect );
445 if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
446 GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
447 rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
448 0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
452 /***********************************************************************
453 * NC_DrawFrame
455 * Draw a window frame inside the given rectangle, and update the rectangle.
456 * The correct pen for the frame must be selected in the DC.
458 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame, BOOL active )
460 short width, height, tmp;
462 if (dlgFrame)
464 width = SYSMETRICS_CXDLGFRAME - 1;
465 height = SYSMETRICS_CYDLGFRAME - 1;
466 SelectObject( hdc, active ? sysColorObjects.hbrushActiveCaption :
467 sysColorObjects.hbrushInactiveCaption );
469 else
471 width = SYSMETRICS_CXFRAME - 1;
472 height = SYSMETRICS_CYFRAME - 1;
473 SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
474 sysColorObjects.hbrushInactiveBorder );
477 /* Draw frame */
478 PatBlt( hdc, rect->left, rect->top,
479 rect->right - rect->left, height, PATCOPY );
480 PatBlt( hdc, rect->left, rect->top,
481 width, rect->bottom - rect->top, PATCOPY );
482 PatBlt( hdc, rect->left, rect->bottom,
483 rect->right - rect->left, -height, PATCOPY );
484 PatBlt( hdc, rect->right, rect->top,
485 -width, rect->bottom - rect->top, PATCOPY );
487 if (dlgFrame)
489 InflateRect( rect, -width, -height );
490 return;
493 /* Draw inner rectangle */
494 MoveTo( hdc, rect->left+width, rect->top+height );
495 LineTo( hdc, rect->right-width-1, rect->top+height );
496 LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
497 LineTo( hdc, rect->left+width, rect->bottom-height-1 );
498 LineTo( hdc, rect->left+width, rect->top+height );
500 /* Draw the decorations */
501 tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
502 MoveTo( hdc, rect->left, tmp);
503 LineTo( hdc, rect->left+width, tmp );
504 MoveTo( hdc, rect->right-width-1, tmp );
505 LineTo( hdc, rect->right-1, tmp );
507 tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
508 MoveTo( hdc, rect->left, tmp );
509 LineTo( hdc, rect->left+width, tmp );
510 MoveTo( hdc, rect->right-width-1, tmp );
511 LineTo( hdc, rect->right-1, tmp );
513 tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
514 MoveTo( hdc, tmp, rect->top );
515 LineTo( hdc, tmp, rect->top+height );
516 MoveTo( hdc, tmp, rect->bottom-height-1 );
517 LineTo( hdc, tmp, rect->bottom-1 );
519 tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
520 MoveTo( hdc, tmp, rect->top );
521 LineTo( hdc, tmp, rect->top+height );
522 MoveTo( hdc, tmp, rect->bottom-height-1 );
523 LineTo( hdc, tmp, rect->bottom-1 );
525 InflateRect( rect, -width-1, -height-1 );
529 /***********************************************************************
530 * NC_DrawMovingFrame
532 * Draw the frame used when moving or resizing window.
534 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
536 if (thickframe)
538 SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
539 PatBlt( hdc, rect->left, rect->top,
540 rect->right - rect->left - SYSMETRICS_CXFRAME,
541 SYSMETRICS_CYFRAME, PATINVERT );
542 PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
543 SYSMETRICS_CXFRAME,
544 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
545 PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
546 rect->right - rect->left - SYSMETRICS_CXFRAME,
547 -SYSMETRICS_CYFRAME, PATINVERT );
548 PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME,
549 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
551 else DrawFocusRect( hdc, rect );
555 /***********************************************************************
556 * NC_DrawCaption
558 * Draw the window caption.
559 * The correct pen for the window frame must be selected in the DC.
561 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
562 DWORD style, BOOL active )
564 RECT r = *rect;
565 WND * wndPtr = WIN_FindWndPtr( hwnd );
566 char buffer[256];
568 if (!hbitmapClose)
570 if (!(hbitmapClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
571 return;
572 hbitmapMinimize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCE) );
573 hbitmapMinimizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCED) );
574 hbitmapMaximize = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOM) );
575 hbitmapMaximizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
576 hbitmapRestore = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE) );
577 hbitmapRestoreD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
580 if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
582 HBRUSH hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
583 PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
584 PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
585 PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
586 r.left++;
587 r.right--;
588 SelectObject( hdc, hbrushOld );
591 MoveTo( hdc, r.left, r.bottom );
592 LineTo( hdc, r.right-1, r.bottom );
594 if (style & WS_SYSMENU)
596 NC_DrawSysButton( hwnd, hdc, FALSE );
597 r.left += SYSMETRICS_CXSIZE + 1;
598 MoveTo( hdc, r.left - 1, r.top );
599 LineTo( hdc, r.left - 1, r.bottom );
601 if (style & WS_MAXIMIZEBOX)
603 NC_DrawMaxButton( hwnd, hdc, FALSE );
604 r.right -= SYSMETRICS_CXSIZE + 1;
606 if (style & WS_MINIMIZEBOX)
608 NC_DrawMinButton( hwnd, hdc, FALSE );
609 r.right -= SYSMETRICS_CXSIZE + 1;
612 FillRect( hdc, &r, active ? sysColorObjects.hbrushActiveCaption :
613 sysColorObjects.hbrushInactiveCaption );
615 if (GetWindowText( hwnd, buffer, 256 ))
617 if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
618 else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
619 SetBkMode( hdc, TRANSPARENT );
620 DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
625 /***********************************************************************
626 * NC_DoNCPaint
628 * Paint the non-client area.
630 void NC_DoNCPaint( HWND hwnd, BOOL active, BOOL suppress_menupaint )
632 HDC hdc;
633 RECT rect;
635 WND *wndPtr = WIN_FindWndPtr( hwnd );
637 dprintf_nonclient(stddeb, "NC_DoNCPaint: "NPFMT" %d\n", hwnd, active );
638 if (!wndPtr || !(wndPtr->dwStyle & WS_VISIBLE)) return; /* Nothing to do */
640 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
643 * If this is an icon, we don't want to do any more nonclient painting
644 * of the window manager.
645 * If there is a class icon to draw, draw it
647 if (IsIconic(hwnd))
649 HICON hIcon = WIN_CLASS_INFO(wndPtr).hIcon;
650 if (hIcon)
652 SendMessage(hwnd, WM_ICONERASEBKGND, (WPARAM)hdc, 0);
653 DrawIcon(hdc, 0, 0, hIcon);
655 ReleaseDC(hwnd, hdc);
656 return;
659 if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
660 wndPtr->rectClient.top-wndPtr->rectWindow.top,
661 wndPtr->rectClient.right-wndPtr->rectWindow.left,
662 wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
663 == NULLREGION)
665 ReleaseDC( hwnd, hdc );
666 return;
669 rect.top = rect.left = 0;
670 rect.right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
671 rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
673 SelectObject( hdc, sysColorObjects.hpenWindowFrame );
675 if (((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
676 (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)) &&
677 !(IS_MANAGED(wndPtr->dwStyle)))
679 MoveTo( hdc, 0, 0 );
680 LineTo( hdc, rect.right-1, 0 );
681 LineTo( hdc, rect.right-1, rect.bottom-1 );
682 LineTo( hdc, 0, rect.bottom-1 );
683 LineTo( hdc, 0, 0 );
684 InflateRect( &rect, -1, -1 );
687 if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
688 NC_DrawFrame( hdc, &rect, TRUE, active );
689 else if ((wndPtr->dwStyle & WS_THICKFRAME) &&
690 !(IS_MANAGED(wndPtr->dwStyle)))
691 NC_DrawFrame(hdc, &rect, FALSE, active );
693 if (((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION) &&
694 !(IS_MANAGED(wndPtr->dwStyle)))
696 RECT r = rect;
697 r.bottom = rect.top + SYSMETRICS_CYSIZE;
698 rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
699 NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
702 if (HAS_MENU(wndPtr))
704 RECT r = rect;
705 r.bottom = rect.top + SYSMETRICS_CYMENU; /* default height */
706 rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
709 /* Draw the scroll-bars */
711 if (wndPtr->dwStyle & WS_VSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_VERT);
712 if (wndPtr->dwStyle & WS_HSCROLL) SCROLL_DrawScrollBar(hwnd, hdc, SB_HORZ);
714 /* Draw the "size-box" */
716 if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
718 RECT r = rect;
719 r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
720 r.top = r.bottom - SYSMETRICS_CYHSCROLL + 1;
721 FillRect( hdc, &r, sysColorObjects.hbrushScrollbar );
724 ReleaseDC( hwnd, hdc );
729 /***********************************************************************
730 * NC_HandleNCPaint
732 * Handle a WM_NCPAINT message. Called from DefWindowProc().
734 LONG NC_HandleNCPaint( HWND hwnd )
736 WND *wndPtr = WIN_FindWndPtr(hwnd);
738 NC_DoNCPaint( hwnd, wndPtr->flags & WIN_NCACTIVATED, FALSE );
739 return 0;
743 /***********************************************************************
744 * NC_HandleNCActivate
746 * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
748 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
750 WND *wndPtr = WIN_FindWndPtr(hwnd);
752 if (wParam != 0) wndPtr->flags |= WIN_NCACTIVATED;
753 else wndPtr->flags &= ~WIN_NCACTIVATED;
755 NC_DoNCPaint( hwnd, (wParam != 0), FALSE );
756 return TRUE;
760 /***********************************************************************
761 * NC_HandleSetCursor
763 * Handle a WM_SETCURSOR message. Called from DefWindowProc().
765 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
767 if (hwnd != (HWND)wParam) return 0; /* Don't set the cursor for child windows */
769 switch(LOWORD(lParam))
771 case HTERROR:
773 WORD msg = HIWORD( lParam );
774 if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
775 (msg == WM_RBUTTONDOWN))
776 MessageBeep(0);
778 break;
780 case HTCLIENT:
782 WND *wndPtr;
783 CLASS *classPtr;
784 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
785 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) break;
786 if (classPtr->wc.hCursor)
788 SetCursor( classPtr->wc.hCursor );
789 return TRUE;
791 else return FALSE;
794 case HTLEFT:
795 case HTRIGHT:
796 return (LONG)SetCursor( LoadCursor( 0, IDC_SIZEWE ) );
798 case HTTOP:
799 case HTBOTTOM:
800 return (LONG)SetCursor( LoadCursor( 0, IDC_SIZENS ) );
802 case HTTOPLEFT:
803 case HTBOTTOMRIGHT:
804 return (LONG)SetCursor( LoadCursor( 0, IDC_SIZENWSE ) );
806 case HTTOPRIGHT:
807 case HTBOTTOMLEFT:
808 return (LONG)SetCursor( LoadCursor( 0, IDC_SIZENESW ) );
811 /* Default cursor: arrow */
812 return (LONG)SetCursor( LoadCursor( 0, IDC_ARROW ) );
816 /***********************************************************************
817 * NC_StartSizeMove
819 * Initialisation of a move or resize, when initiatied from a menu choice.
820 * Return hit test code for caption or sizing border.
822 static LONG NC_StartSizeMove( HWND hwnd, WPARAM wParam, POINT *capturePoint )
824 LONG hittest = 0;
825 POINT pt;
826 MSG msg;
827 WND * wndPtr = WIN_FindWndPtr( hwnd );
829 if ((wParam & 0xfff0) == SC_MOVE)
831 /* Move pointer at the center of the caption */
832 RECT rect;
833 NC_GetInsideRect( hwnd, &rect );
834 if (wndPtr->dwStyle & WS_SYSMENU)
835 rect.left += SYSMETRICS_CXSIZE + 1;
836 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
837 rect.right -= SYSMETRICS_CXSIZE + 1;
838 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
839 rect.right -= SYSMETRICS_CXSIZE + 1;
840 pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
841 pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
842 if (wndPtr->dwStyle & WS_CHILD)
843 ClientToScreen( wndPtr->hwndParent, &pt );
844 hittest = HTCAPTION;
846 else /* SC_SIZE */
848 SetCapture(hwnd);
849 while(!hittest)
851 MSG_GetHardwareMessage( &msg );
852 switch(msg.message)
854 case WM_MOUSEMOVE:
855 hittest = NC_HandleNCHitTest( hwnd, msg.pt );
856 pt = msg.pt;
857 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
858 hittest = 0;
859 break;
861 case WM_LBUTTONUP:
862 return 0;
864 case WM_KEYDOWN:
865 switch(msg.wParam)
867 case VK_UP:
868 hittest = HTTOP;
869 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
870 pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
871 break;
872 case VK_DOWN:
873 hittest = HTBOTTOM;
874 pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
875 pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
876 break;
877 case VK_LEFT:
878 hittest = HTLEFT;
879 pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
880 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
881 break;
882 case VK_RIGHT:
883 hittest = HTRIGHT;
884 pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
885 pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
886 break;
887 case VK_RETURN:
888 case VK_ESCAPE: return 0;
893 *capturePoint = pt;
894 SetCursorPos( capturePoint->x, capturePoint->y );
895 NC_HandleSetCursor( hwnd, hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
896 return hittest;
900 /***********************************************************************
901 * NC_DoSizeMove
903 * Perform SC_MOVE and SC_SIZE commands.
905 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
907 MSG msg;
908 LONG hittest;
909 RECT sizingRect, mouseRect;
910 HDC hdc;
911 BOOL thickframe;
912 POINT minTrack, maxTrack, capturePoint = pt;
913 WND * wndPtr = WIN_FindWndPtr( hwnd );
915 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd)) return;
916 hittest = wParam & 0x0f;
917 thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
919 if ((wParam & 0xfff0) == SC_MOVE)
921 if (!(wndPtr->dwStyle & WS_CAPTION)) return;
922 if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
923 if (!hittest) return;
925 else /* SC_SIZE */
927 if (!thickframe) return;
928 if (hittest) hittest += HTLEFT-1;
929 else
931 SetCapture(hwnd);
932 hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
933 if (!hittest)
935 ReleaseCapture();
936 return;
941 /* Get min/max info */
943 NC_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
944 sizingRect = wndPtr->rectWindow;
945 if (wndPtr->dwStyle & WS_CHILD)
946 GetClientRect( wndPtr->hwndParent, &mouseRect );
947 else SetRect( &mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN );
948 if (ON_LEFT_BORDER(hittest))
950 mouseRect.left = MAX( mouseRect.left, sizingRect.right-maxTrack.x );
951 mouseRect.right = MIN( mouseRect.right, sizingRect.right-minTrack.x );
953 else if (ON_RIGHT_BORDER(hittest))
955 mouseRect.left = MAX( mouseRect.left, sizingRect.left+minTrack.x );
956 mouseRect.right = MIN( mouseRect.right, sizingRect.left+maxTrack.x );
958 if (ON_TOP_BORDER(hittest))
960 mouseRect.top = MAX( mouseRect.top, sizingRect.bottom-maxTrack.y );
961 mouseRect.bottom = MIN( mouseRect.bottom,sizingRect.bottom-minTrack.y);
963 else if (ON_BOTTOM_BORDER(hittest))
965 mouseRect.top = MAX( mouseRect.top, sizingRect.top+minTrack.y );
966 mouseRect.bottom = MIN( mouseRect.bottom, sizingRect.top+maxTrack.y );
968 SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
970 if (GetCapture() != hwnd) SetCapture( hwnd );
972 if (wndPtr->dwStyle & WS_CHILD)
974 /* Retrieve a default cache DC (without using the window style) */
975 hdc = GetDCEx( wndPtr->hwndParent, 0, DCX_CACHE );
977 else
978 { /* Grab the server only when moving top-level windows without desktop */
979 hdc = GetDC( 0 );
980 if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
982 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
984 while(1)
986 int dx = 0, dy = 0;
988 MSG_GetHardwareMessage( &msg );
990 /* Exit on button-up, Return, or Esc */
991 if ((msg.message == WM_LBUTTONUP) ||
992 ((msg.message == WM_KEYDOWN) &&
993 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
995 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
996 continue; /* We are not interested in other messages */
998 pt = msg.pt;
999 if (wndPtr->dwStyle & WS_CHILD)
1000 ScreenToClient( wndPtr->hwndParent, &pt );
1003 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1005 case VK_UP: pt.y -= 8; break;
1006 case VK_DOWN: pt.y += 8; break;
1007 case VK_LEFT: pt.x -= 8; break;
1008 case VK_RIGHT: pt.x += 8; break;
1011 pt.x = MAX( pt.x, mouseRect.left );
1012 pt.x = MIN( pt.x, mouseRect.right );
1013 pt.y = MAX( pt.y, mouseRect.top );
1014 pt.y = MIN( pt.y, mouseRect.bottom );
1016 dx = pt.x - capturePoint.x;
1017 dy = pt.y - capturePoint.y;
1019 if (dx || dy)
1021 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1022 else
1024 RECT newRect = sizingRect;
1026 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
1027 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1028 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1029 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1030 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1031 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1032 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1033 capturePoint = pt;
1034 sizingRect = newRect;
1039 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1040 ReleaseCapture();
1041 if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
1042 else
1044 ReleaseDC( 0, hdc );
1045 if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1047 SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1048 SendMessage( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1050 /* If Esc key, don't move the window */
1051 if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1053 if (hittest != HTCAPTION)
1054 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1055 sizingRect.right - sizingRect.left,
1056 sizingRect.bottom - sizingRect.top,
1057 SWP_NOACTIVATE | SWP_NOZORDER );
1058 else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1059 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1063 /***********************************************************************
1064 * NC_TrackMinMaxBox
1066 * Track a mouse button press on the minimize or maximize box.
1068 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1070 MSG msg;
1071 HDC hdc = GetWindowDC( hwnd );
1072 BOOL pressed = TRUE;
1074 SetCapture( hwnd );
1075 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1076 else NC_DrawMaxButton( hwnd, hdc, TRUE );
1080 BOOL oldstate = pressed;
1081 MSG_GetHardwareMessage( &msg );
1083 pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1084 if (pressed != oldstate)
1086 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1087 else NC_DrawMaxButton( hwnd, hdc, pressed );
1089 } while (msg.message != WM_LBUTTONUP);
1091 if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1092 else NC_DrawMaxButton( hwnd, hdc, FALSE );
1094 ReleaseCapture();
1095 ReleaseDC( hwnd, hdc );
1096 if (!pressed) return;
1098 if (wParam == HTMINBUTTON)
1099 SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1100 else
1101 SendMessage( hwnd, WM_SYSCOMMAND,
1102 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1106 /***********************************************************************
1107 * NC_TrackScrollBar
1109 * Track a mouse button press on the horizontal or vertical scroll-bar.
1111 static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt )
1113 MSG msg;
1114 WORD scrollbar;
1115 WND *wndPtr = WIN_FindWndPtr( hwnd );
1117 if ((wParam & 0xfff0) == SC_HSCROLL)
1119 if ((wParam & 0x0f) != HTHSCROLL) return;
1120 scrollbar = SB_HORZ;
1122 else /* SC_VSCROLL */
1124 if ((wParam & 0x0f) != HTVSCROLL) return;
1125 scrollbar = SB_VERT;
1128 pt.x -= wndPtr->rectWindow.left;
1129 pt.y -= wndPtr->rectWindow.top;
1130 SetCapture( hwnd );
1131 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1135 GetMessage( MAKE_SEGPTR(&msg), 0, 0, 0 );
1136 switch(msg.message)
1138 case WM_LBUTTONUP:
1139 case WM_MOUSEMOVE:
1140 case WM_SYSTIMER:
1141 pt.x = LOWORD(msg.lParam) + wndPtr->rectClient.left -
1142 wndPtr->rectWindow.left;
1143 pt.y = HIWORD(msg.lParam) + wndPtr->rectClient.top -
1144 wndPtr->rectWindow.top;
1145 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
1146 break;
1147 default:
1148 TranslateMessage( &msg );
1149 DispatchMessage( &msg );
1150 break;
1152 if (!IsWindow( hwnd ))
1154 ReleaseCapture();
1155 break;
1157 } while (msg.message != WM_LBUTTONUP);
1160 /***********************************************************************
1161 * NC_TrackSysMenu
1163 * Track a mouse button press on the system menu.
1165 static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT pt )
1167 RECT rect;
1168 WND *wndPtr = WIN_FindWndPtr( hwnd );
1170 if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
1171 /* If window has a menu, track the menu bar normally */
1172 if (HAS_MENU(wndPtr)) MENU_TrackMouseMenuBar( hwnd, pt );
1173 else
1175 /* Otherwise track the system menu like a normal popup menu */
1176 NC_GetInsideRect( hwnd, &rect );
1177 OffsetRect( &rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
1178 if (wndPtr->dwStyle & WS_CHILD)
1179 ClientToScreen( wndPtr->hwndParent, (POINT *)&rect );
1180 rect.right = rect.left + SYSMETRICS_CXSIZE;
1181 rect.bottom = rect.top + SYSMETRICS_CYSIZE;
1182 NC_DrawSysButton( hwnd, hdc, TRUE );
1183 TrackPopupMenu( wndPtr->hSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
1184 rect.left, rect.bottom, 0, hwnd, &rect );
1185 NC_DrawSysButton( hwnd, hdc, FALSE );
1190 /***********************************************************************
1191 * NC_HandleNCLButtonDown
1193 * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1195 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1197 HDC hdc = GetWindowDC( hwnd );
1198 POINT pt = { LOWORD(lParam), HIWORD(lParam) };
1200 switch(wParam) /* Hit test */
1202 case HTCAPTION:
1203 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1204 break;
1206 case HTSYSMENU:
1207 NC_TrackSysMenu( hwnd, hdc, pt );
1208 break;
1210 case HTMENU:
1211 SendMessage( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1212 break;
1214 case HTHSCROLL:
1215 SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1216 break;
1218 case HTVSCROLL:
1219 SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1220 break;
1222 case HTMINBUTTON:
1223 case HTMAXBUTTON:
1224 NC_TrackMinMaxBox( hwnd, wParam );
1225 break;
1227 case HTLEFT:
1228 case HTRIGHT:
1229 case HTTOP:
1230 case HTTOPLEFT:
1231 case HTTOPRIGHT:
1232 case HTBOTTOM:
1233 case HTBOTTOMLEFT:
1234 case HTBOTTOMRIGHT:
1235 SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1236 break;
1238 case HTBORDER:
1239 break;
1242 ReleaseDC( hwnd, hdc );
1243 return 0;
1247 /***********************************************************************
1248 * NC_HandleNCLButtonDblClk
1250 * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1252 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1255 * if this is an icon, send a restore since we are handling
1256 * a double click
1258 if (IsIconic(hwnd))
1260 SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam);
1261 return 0;
1264 switch(wParam) /* Hit test */
1266 case HTCAPTION:
1267 /* stop processing if WS_MAXIMIZEBOX is missing */
1269 if( GetWindowLong( hwnd , GWL_STYLE) & WS_MAXIMIZEBOX )
1270 SendMessage( hwnd, WM_SYSCOMMAND,
1271 IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1272 break;
1274 case HTSYSMENU:
1275 SendMessage( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1276 break;
1278 return 0;
1282 /***********************************************************************
1283 * NC_HandleSysCommand
1285 * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1287 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
1289 WND *wndPtr = WIN_FindWndPtr( hwnd );
1291 dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %lx %ld,%ld\n",
1292 (DWORD)wParam, (LONG)pt.x, (LONG)pt.y );
1294 if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
1296 switch (wParam & 0xfff0)
1298 case SC_SIZE:
1299 case SC_MOVE:
1300 NC_DoSizeMove( hwnd, wParam, pt );
1301 break;
1303 case SC_MINIMIZE:
1304 ShowWindow( hwnd, SW_MINIMIZE );
1305 break;
1307 case SC_MAXIMIZE:
1308 ShowWindow( hwnd, SW_MAXIMIZE );
1309 break;
1311 case SC_RESTORE:
1312 ShowWindow( hwnd, SW_RESTORE );
1313 break;
1315 case SC_NEXTWINDOW:
1316 case SC_PREVWINDOW:
1317 break;
1319 case SC_CLOSE:
1320 return SendMessage( hwnd, WM_CLOSE, 0, 0 );
1322 case SC_VSCROLL:
1323 case SC_HSCROLL:
1324 NC_TrackScrollBar( hwnd, wParam, pt );
1325 break;
1327 case SC_MOUSEMENU:
1328 MENU_TrackMouseMenuBar( hwnd, pt );
1329 break;
1331 case SC_KEYMENU:
1332 MENU_TrackKbdMenuBar( hwnd, wParam );
1333 break;
1335 case SC_ARRANGE:
1336 break;
1338 case SC_TASKLIST:
1339 WinExec( "taskman.exe", SW_SHOWNORMAL );
1340 break;
1342 case SC_HOTKEY:
1343 break;
1345 case SC_SCREENSAVE:
1346 if (wParam == SC_ABOUTWINE)
1348 extern const char people[];
1349 ShellAbout(hwnd,"WINE",people,0);
1351 break;
1353 return 0;