3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/window.c
6 * PURPOSE: Window management
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 06-06-2001 CSH Created
12 /* INCLUDES ******************************************************************/
16 #include <wine/debug.h>
19 #define WM_SETVISIBLE 9
21 #ifndef WM_QUERYDROPOBJECT
22 #define WM_QUERYDROPOBJECT 0x022B
25 LRESULT
DefWndNCPaint(HWND hWnd
, HRGN hRgn
, BOOL Active
);
26 LRESULT
DefWndNCCalcSize(HWND hWnd
, BOOL CalcSizeStruct
, RECT
*Rect
);
27 LRESULT
DefWndNCActivate(HWND hWnd
, WPARAM wParam
);
28 LRESULT
DefWndNCHitTest(HWND hWnd
, POINT Point
);
29 LRESULT
DefWndNCLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
30 LRESULT
DefWndNCLButtonDblClk(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
31 void FASTCALL
MenuInitSysMenuPopup(HMENU Menu
, DWORD Style
, DWORD ClsStyle
, LONG HitTest
);
33 /* GLOBALS *******************************************************************/
35 COLORREF SysColors
[NUM_SYSCOLORS
] = {0};
36 HPEN SysPens
[NUM_SYSCOLORS
] = {0};
37 HBRUSH SysBrushes
[NUM_SYSCOLORS
] = {0};
39 /* Bits in the dwKeyData */
40 #define KEYDATA_ALT 0x2000
41 #define KEYDATA_PREVSTATE 0x4000
43 static short iF10Key
= 0;
44 static short iMenuSysKey
= 0;
46 /* FUNCTIONS *****************************************************************/
49 InitStockObjects(void)
51 /* FIXME - Instead of copying the stuff to usermode we should map the tables to
52 userland. The current implementation has one big flaw: the system color
53 table doesn't get updated when another process changes them. That's why
54 we should rather map the table into usermode. But it only affects the
55 SysColors table - the pens, brushes and stock objects are not affected
56 as their handles never change. But it'd be faster to map them, too. */
57 if(SysBrushes
[0] == NULL
)
59 /* only initialize once */
60 (void)NtUserGetSysColors(SysColors
, NUM_SYSCOLORS
);
61 (void)NtUserGetSysColorPens(SysPens
, NUM_SYSCOLORS
);
62 (void)NtUserGetSysColorBrushes(SysBrushes
, NUM_SYSCOLORS
);
70 GetSysColor(int nIndex
)
72 if(nIndex
>= 0 && nIndex
<= NUM_SYSCOLORS
)
74 return SysColors
[nIndex
];
77 SetLastError(ERROR_INVALID_PARAMETER
);
85 GetSysColorPen(int nIndex
)
87 if(nIndex
>= 0 && nIndex
<= NUM_SYSCOLORS
)
89 return SysPens
[nIndex
];
92 SetLastError(ERROR_INVALID_PARAMETER
);
100 GetSysColorBrush(int nIndex
)
102 if(nIndex
>= 0 && nIndex
<= NUM_SYSCOLORS
)
104 return SysBrushes
[nIndex
];
107 SetLastError(ERROR_INVALID_PARAMETER
);
118 CONST INT
*lpaElements
,
119 CONST COLORREF
*lpaRgbValues
)
128 ChangeSysColors
.Elements
= (INT
*)lpaElements
;
129 ChangeSysColors
.Colors
= (COLORREF
*)lpaRgbValues
;
133 Ret
= NtUserSetSysColors(&ChangeSysColors
, cElements
);
136 /* FIXME - just change it in the usermode structure, too, instead of asking win32k again */
137 (void)NtUserGetSysColors(SysColors
, NUM_SYSCOLORS
);
142 SetLastError(ERROR_INVALID_PARAMETER
);
150 UserGetInsideRectNC(HWND hWnd
, RECT
*rect
)
156 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
157 ExStyle
= GetWindowLongW(hWnd
, GWL_EXSTYLE
);
158 GetWindowRect(hWnd
, &WindowRect
);
159 rect
->top
= rect
->left
= 0;
160 rect
->right
= WindowRect
.right
- WindowRect
.left
;
161 rect
->bottom
= WindowRect
.bottom
- WindowRect
.top
;
163 if (Style
& WS_ICONIC
)
168 /* Remove frame from rectangle */
169 if (UserHasThickFrameStyle(Style
, ExStyle
))
171 InflateRect(rect
, -GetSystemMetrics(SM_CXFRAME
),
172 -GetSystemMetrics(SM_CYFRAME
));
176 if (UserHasDlgFrameStyle(Style
, ExStyle
))
178 InflateRect(rect
, -GetSystemMetrics(SM_CXDLGFRAME
),
179 -GetSystemMetrics(SM_CYDLGFRAME
));
180 /* FIXME: this isn't in NC_AdjustRect? why not? */
181 if (ExStyle
& WS_EX_DLGMODALFRAME
)
182 InflateRect( rect
, -1, 0 );
186 if (UserHasThinFrameStyle(Style
, ExStyle
))
188 InflateRect(rect
, -GetSystemMetrics(SM_CXBORDER
),
189 -GetSystemMetrics(SM_CYBORDER
));
197 DefWndSetRedraw(HWND hWnd
, WPARAM wParam
)
199 LONG Style
= GetWindowLong(hWnd
, GWL_STYLE
);
200 /* Content can be redrawn after a change. */
203 if (!(Style
& WS_VISIBLE
)) /* Not Visible */
205 SetWindowLong(hWnd
, GWL_STYLE
, WS_VISIBLE
);
208 else /* Content cannot be redrawn after a change. */
210 if (Style
& WS_VISIBLE
) /* Visible */
212 RedrawWindow( hWnd
, NULL
, 0, RDW_ALLCHILDREN
| RDW_VALIDATE
);
213 Style
&= ~WS_VISIBLE
;
214 SetWindowLong(hWnd
, GWL_STYLE
, Style
); /* clear bits */
222 DefWndHandleSetCursor(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, ULONG Style
)
224 /* Not for child windows. */
225 if (hWnd
!= (HWND
)wParam
)
230 switch((INT_PTR
) LOWORD(lParam
))
234 WORD Msg
= HIWORD(lParam
);
235 if (Msg
== WM_LBUTTONDOWN
|| Msg
== WM_MBUTTONDOWN
||
236 Msg
== WM_RBUTTONDOWN
|| Msg
== WM_XBUTTONDOWN
)
245 HICON hCursor
= (HICON
)GetClassLongW(hWnd
, GCL_HCURSOR
);
257 if (Style
& WS_MAXIMIZE
)
261 return((LRESULT
)SetCursor(LoadCursorW(0, IDC_SIZEWE
)));
267 if (Style
& WS_MAXIMIZE
)
271 return((LRESULT
)SetCursor(LoadCursorW(0, IDC_SIZENS
)));
277 if (Style
& WS_MAXIMIZE
)
281 return((LRESULT
)SetCursor(LoadCursorW(0, IDC_SIZENWSE
)));
287 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_MAXIMIZE
)
291 return((LRESULT
)SetCursor(LoadCursorW(0, IDC_SIZENESW
)));
294 return((LRESULT
)SetCursor(LoadCursorW(0, IDC_ARROW
)));
298 DefWndStartSizeMove(HWND hWnd
, WPARAM wParam
, POINT
*capturePoint
)
304 ULONG Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
306 GetWindowRect(hWnd
, &rectWindow
);
308 if ((wParam
& 0xfff0) == SC_MOVE
)
310 /* Move pointer at the center of the caption */
312 UserGetInsideRectNC(hWnd
, &rect
);
313 if (Style
& WS_SYSMENU
)
314 rect
.left
+= GetSystemMetrics(SM_CXSIZE
) + 1;
315 if (Style
& WS_MINIMIZEBOX
)
316 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
317 if (Style
& WS_MAXIMIZEBOX
)
318 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
319 pt
.x
= rectWindow
.left
+ (rect
.right
- rect
.left
) / 2;
320 pt
.y
= rectWindow
.top
+ rect
.top
+ GetSystemMetrics(SM_CYSIZE
)/2;
329 if (GetMessageW(&msg
, NULL
, 0, 0) <= 0)
334 hittest
= DefWndNCHitTest(hWnd
, msg
.pt
);
335 if ((hittest
< HTLEFT
) || (hittest
> HTBOTTOMRIGHT
))
347 pt
.x
=(rectWindow
.left
+rectWindow
.right
)/2;
348 pt
.y
= rectWindow
.top
+ GetSystemMetrics(SM_CYFRAME
) / 2;
352 pt
.x
=(rectWindow
.left
+rectWindow
.right
)/2;
353 pt
.y
= rectWindow
.bottom
- GetSystemMetrics(SM_CYFRAME
) / 2;
357 pt
.x
= rectWindow
.left
+ GetSystemMetrics(SM_CXFRAME
) / 2;
358 pt
.y
=(rectWindow
.top
+rectWindow
.bottom
)/2;
362 pt
.x
= rectWindow
.right
- GetSystemMetrics(SM_CXFRAME
) / 2;
363 pt
.y
=(rectWindow
.top
+rectWindow
.bottom
)/2;
366 case VK_ESCAPE
: return 0;
372 SetCursorPos( pt
.x
, pt
.y
);
373 DefWndHandleSetCursor(hWnd
, (WPARAM
)hWnd
, MAKELONG(hittest
, WM_MOUSEMOVE
), Style
);
377 #define ON_LEFT_BORDER(hit) \
378 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
379 #define ON_RIGHT_BORDER(hit) \
380 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
381 #define ON_TOP_BORDER(hit) \
382 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
383 #define ON_BOTTOM_BORDER(hit) \
384 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
387 UserDrawWindowFrame(HDC hdc
, const RECT
*rect
,
388 ULONG width
, ULONG height
)
390 static HBRUSH hDraggingRectBrush
= NULL
;
393 if(!hDraggingRectBrush
)
395 static HBITMAP hDraggingPattern
= NULL
;
396 const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
398 hDraggingPattern
= CreateBitmap(8, 8, 1, 1, Pattern
);
399 hDraggingRectBrush
= CreatePatternBrush(hDraggingPattern
);
402 hbrush
= SelectObject( hdc
, hDraggingRectBrush
);
403 PatBlt( hdc
, rect
->left
, rect
->top
,
404 rect
->right
- rect
->left
- width
, height
, PATINVERT
);
405 PatBlt( hdc
, rect
->left
, rect
->top
+ height
, width
,
406 rect
->bottom
- rect
->top
- height
, PATINVERT
);
407 PatBlt( hdc
, rect
->left
+ width
, rect
->bottom
- 1,
408 rect
->right
- rect
->left
- width
, -height
, PATINVERT
);
409 PatBlt( hdc
, rect
->right
- 1, rect
->top
, -width
,
410 rect
->bottom
- rect
->top
- height
, PATINVERT
);
411 SelectObject( hdc
, hbrush
);
415 UserDrawMovingFrame(HDC hdc
, RECT
*rect
, BOOL thickframe
)
419 UserDrawWindowFrame(hdc
, rect
, GetSystemMetrics(SM_CXFRAME
), GetSystemMetrics(SM_CYFRAME
));
423 UserDrawWindowFrame(hdc
, rect
, 1, 1);
428 DefWndDoSizeMove(HWND hwnd
, WORD wParam
)
432 RECT sizingRect
, mouseRect
, origRect
, clipRect
, unmodRect
;
434 LONG hittest
= (LONG
)(wParam
& 0x0f);
435 HCURSOR hDragCursor
= 0, hOldCursor
= 0;
436 POINT minTrack
, maxTrack
;
437 POINT capturePoint
, pt
;
438 ULONG Style
= GetWindowLongW(hwnd
, GWL_STYLE
);
439 ULONG ExStyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
441 BOOL iconic
= Style
& WS_MINIMIZE
;
443 DWORD dwPoint
= GetMessagePos();
444 BOOL DragFullWindows
= FALSE
;
445 HWND hWndParent
= NULL
;
447 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
449 pt
.x
= GET_X_LPARAM(dwPoint
);
450 pt
.y
= GET_Y_LPARAM(dwPoint
);
453 if (IsZoomed(hwnd
) || !IsWindowVisible(hwnd
))
458 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !(Style
& WS_MINIMIZE
);
459 if ((wParam
& 0xfff0) == SC_MOVE
)
463 hittest
= DefWndStartSizeMove(hwnd
, wParam
, &capturePoint
);
476 if (hittest
&& ((wParam
& 0xfff0) != SC_MOUSEMENU
))
478 hittest
+= (HTLEFT
- WMSZ_LEFT
);
483 hittest
= DefWndStartSizeMove(hwnd
, wParam
, &capturePoint
);
492 /* Get min/max info */
494 WinPosGetMinMaxInfo(hwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
495 GetWindowRect(hwnd
, &sizingRect
);
496 if (Style
& WS_CHILD
)
498 hWndParent
= GetParent(hwnd
);
499 MapWindowPoints( 0, hWndParent
, (LPPOINT
)&sizingRect
, 2 );
500 unmodRect
= sizingRect
;
501 GetClientRect(hWndParent
, &mouseRect
);
502 clipRect
= mouseRect
;
503 MapWindowPoints(hWndParent
, HWND_DESKTOP
, (LPPOINT
)&clipRect
, 2);
507 if(!(ExStyle
& WS_EX_TOPMOST
))
509 SystemParametersInfoW(SPI_GETWORKAREA
, 0, &clipRect
, 0);
510 mouseRect
= clipRect
;
514 SetRect(&mouseRect
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
515 clipRect
= mouseRect
;
517 unmodRect
= sizingRect
;
519 ClipCursor(&clipRect
);
521 origRect
= sizingRect
;
522 if (ON_LEFT_BORDER(hittest
))
524 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
);
525 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
);
527 else if (ON_RIGHT_BORDER(hittest
))
529 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
);
530 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
);
532 if (ON_TOP_BORDER(hittest
))
534 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
);
535 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
);
537 else if (ON_BOTTOM_BORDER(hittest
))
539 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
);
540 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
);
542 if (Style
& WS_CHILD
)
544 MapWindowPoints( hWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
547 SendMessageA( hwnd
, WM_ENTERSIZEMOVE
, 0, 0 );
548 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE
, hwnd
);
549 if (GetCapture() != hwnd
) SetCapture( hwnd
);
551 if (Style
& WS_CHILD
)
553 /* Retrieve a default cache DC (without using the window style) */
554 hdc
= GetDCEx(hWndParent
, 0, DCX_CACHE
);
560 DesktopRgn
= CreateRectRgnIndirect(&clipRect
);
563 SelectObject(hdc
, DesktopRgn
);
565 if( iconic
) /* create a cursor for dragging */
567 HICON hIcon
= (HICON
)GetClassLongW(hwnd
, GCL_HICON
);
568 if(!hIcon
) hIcon
= (HICON
)SendMessageW( hwnd
, WM_QUERYDRAGICON
, 0, 0L);
569 if( hIcon
) hDragCursor
= CursorIconToCursor( hIcon
, TRUE
);
570 if( !hDragCursor
) iconic
= FALSE
;
573 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
574 if( !iconic
&& !DragFullWindows
)
576 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
583 if (GetMessageW(&msg
, 0, 0, 0) <= 0)
586 /* Exit on button-up, Return, or Esc */
587 if ((msg
.message
== WM_LBUTTONUP
) ||
588 ((msg
.message
== WM_KEYDOWN
) &&
589 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
591 if (msg
.message
== WM_PAINT
)
593 if(!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
594 UpdateWindow( msg
.hwnd
);
595 if(!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
599 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
600 continue; /* We are not interested in other messages */
604 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
606 case VK_UP
: pt
.y
-= 8; break;
607 case VK_DOWN
: pt
.y
+= 8; break;
608 case VK_LEFT
: pt
.x
-= 8; break;
609 case VK_RIGHT
: pt
.x
+= 8; break;
612 pt
.x
= max( pt
.x
, mouseRect
.left
);
613 pt
.x
= min( pt
.x
, mouseRect
.right
);
614 pt
.y
= max( pt
.y
, mouseRect
.top
);
615 pt
.y
= min( pt
.y
, mouseRect
.bottom
);
617 dx
= pt
.x
- capturePoint
.x
;
618 dy
= pt
.y
- capturePoint
.y
;
626 if( iconic
) /* ok, no system popup tracking */
628 hOldCursor
= SetCursor(hDragCursor
);
633 if (msg
.message
== WM_KEYDOWN
) SetCursorPos( pt
.x
, pt
.y
);
636 RECT newRect
= unmodRect
;
637 WPARAM wpSizingHit
= 0;
639 if (hittest
== HTCAPTION
) OffsetRect( &newRect
, dx
, dy
);
640 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
641 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
642 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
643 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
644 if(!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
647 /* determine the hit location */
648 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
649 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
651 SendMessageA( hwnd
, WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
656 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
658 /* To avoid any deadlocks, all the locks on the windows
659 structures must be suspended before the SetWindowPos */
660 SetWindowPos( hwnd
, 0, newRect
.left
, newRect
.top
,
661 newRect
.right
- newRect
.left
,
662 newRect
.bottom
- newRect
.top
,
663 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
666 sizingRect
= newRect
;
675 if( moved
) /* restore cursors, show icon title later on */
678 SetCursor( hOldCursor
);
680 DestroyCursor( hDragCursor
);
682 else if(!DragFullWindows
)
683 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
685 if (Style
& WS_CHILD
)
686 ReleaseDC( hWndParent
, hdc
);
692 DeleteObject(DesktopRgn
);
695 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE
, NULL
);
696 SendMessageA( hwnd
, WM_EXITSIZEMOVE
, 0, 0 );
697 SendMessageA( hwnd
, WM_SETVISIBLE
, !IsIconic(hwnd
), 0L);
699 /* window moved or resized */
702 /* if the moving/resizing isn't canceled call SetWindowPos
703 * with the new position or the new size of the window
705 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
707 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
709 SetWindowPos( hwnd
, 0, sizingRect
.left
, sizingRect
.top
,
710 sizingRect
.right
- sizingRect
.left
,
711 sizingRect
.bottom
- sizingRect
.top
,
712 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
714 else { /* restore previous size/position */
716 SetWindowPos( hwnd
, 0, origRect
.left
, origRect
.top
,
717 origRect
.right
- origRect
.left
,
718 origRect
.bottom
- origRect
.top
,
719 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
724 if( Style
& WS_MINIMIZE
)
726 /* Single click brings up the system menu when iconized */
730 if( Style
& WS_SYSMENU
)
731 SendMessageA( hwnd
, WM_SYSCOMMAND
,
732 SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
738 /***********************************************************************
739 * DefWndTrackScrollBar
741 * Track a mouse button press on the horizontal or vertical scroll-bar.
744 DefWndTrackScrollBar(HWND Wnd
, WPARAM wParam
, POINT Pt
)
748 if (SC_HSCROLL
== (wParam
& 0xfff0))
750 if (HTHSCROLL
!= (wParam
& 0x0f))
756 else /* SC_VSCROLL */
758 if (HTVSCROLL
!= (wParam
& 0x0f))
764 ScrollTrackScrollBar(Wnd
, ScrollBar
, Pt
);
769 DefWndHandleSysCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
774 switch (wParam
& 0xfff0)
778 DefWndDoSizeMove(hWnd
, wParam
);
781 wp
.length
= sizeof(WINDOWPLACEMENT
);
782 if(GetWindowPlacement(hWnd
, &wp
))
784 wp
.showCmd
= SW_MINIMIZE
;
785 SetWindowPlacement(hWnd
, &wp
);
789 wp
.length
= sizeof(WINDOWPLACEMENT
);
790 if(GetWindowPlacement(hWnd
, &wp
))
792 wp
.showCmd
= SW_MAXIMIZE
;
793 SetWindowPlacement(hWnd
, &wp
);
797 wp
.length
= sizeof(WINDOWPLACEMENT
);
798 if(GetWindowPlacement(hWnd
, &wp
))
800 wp
.showCmd
= SW_RESTORE
;
801 SetWindowPlacement(hWnd
, &wp
);
805 SendMessageA(hWnd
, WM_CLOSE
, 0, 0);
809 Pt
.x
= (short)LOWORD(lParam
);
810 Pt
.y
= (short)HIWORD(lParam
);
811 MenuTrackMouseMenuBar(hWnd
, wParam
& 0x000f, Pt
);
815 MenuTrackKbdMenuBar(hWnd
, wParam
, (WCHAR
)lParam
);
820 Pt
.x
= (short)LOWORD(lParam
);
821 Pt
.y
= (short)HIWORD(lParam
);
822 DefWndTrackScrollBar(hWnd
, wParam
, Pt
);
827 /* FIXME: Implement */
836 DefWndHandleWindowPosChanging(HWND hWnd
, WINDOWPOS
* Pos
)
838 POINT maxTrack
, minTrack
;
839 LONG style
= GetWindowLongA(hWnd
, GWL_STYLE
);
841 if (Pos
->flags
& SWP_NOSIZE
) return 0;
842 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
844 WinPosGetMinMaxInfo(hWnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
845 Pos
->cx
= min(Pos
->cx
, maxTrack
.x
);
846 Pos
->cy
= min(Pos
->cy
, maxTrack
.y
);
847 if (!(style
& WS_MINIMIZE
))
849 if (Pos
->cx
< minTrack
.x
) Pos
->cx
= minTrack
.x
;
850 if (Pos
->cy
< minTrack
.y
) Pos
->cy
= minTrack
.y
;
855 Pos
->cx
= max(Pos
->cx
, 0);
856 Pos
->cy
= max(Pos
->cy
, 0);
861 /* Undocumented flags. */
862 #define SWP_NOCLIENTMOVE 0x0800
863 #define SWP_NOCLIENTSIZE 0x1000
866 DefWndHandleWindowPosChanged(HWND hWnd
, WINDOWPOS
* Pos
)
870 GetClientRect(hWnd
, &Rect
);
871 MapWindowPoints(hWnd
, (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
?
872 GetParent(hWnd
) : NULL
), (LPPOINT
) &Rect
, 2);
874 if (! (Pos
->flags
& SWP_NOCLIENTMOVE
))
876 SendMessageW(hWnd
, WM_MOVE
, 0, MAKELONG(Rect
.left
, Rect
.top
));
879 if (! (Pos
->flags
& SWP_NOCLIENTSIZE
))
881 WPARAM wp
= SIZE_RESTORED
;
886 else if (IsIconic(hWnd
))
890 SendMessageW(hWnd
, WM_SIZE
, wp
,
891 MAKELONG(Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
));
897 /***********************************************************************
900 * Default colors for control painting.
903 DefWndControlColor(HDC hDC
, UINT ctlType
)
905 if (CTLCOLOR_SCROLLBAR
== ctlType
)
907 HBRUSH hb
= GetSysColorBrush(COLOR_SCROLLBAR
);
908 COLORREF bk
= GetSysColor(COLOR_3DHILIGHT
);
909 SetTextColor(hDC
, GetSysColor(COLOR_3DFACE
));
912 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
913 * we better use 0x55aa bitmap brush to make scrollbar's background
914 * look different from the window background.
916 if (bk
== GetSysColor(COLOR_WINDOW
))
918 static const WORD wPattern55AA
[] =
920 0x5555, 0xaaaa, 0x5555, 0xaaaa,
921 0x5555, 0xaaaa, 0x5555, 0xaaaa
923 static HBITMAP hPattern55AABitmap
= NULL
;
924 static HBRUSH hPattern55AABrush
= NULL
;
925 if (hPattern55AABrush
== NULL
)
927 hPattern55AABitmap
= CreateBitmap(8, 8, 1, 1, wPattern55AA
);
928 hPattern55AABrush
= CreatePatternBrush(hPattern55AABitmap
);
930 return hPattern55AABrush
;
936 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
938 if ((CTLCOLOR_EDIT
== ctlType
) || (CTLCOLOR_LISTBOX
== ctlType
))
940 SetBkColor(hDC
, GetSysColor(COLOR_WINDOW
));
944 SetBkColor(hDC
, GetSysColor(COLOR_3DFACE
));
945 return GetSysColorBrush(COLOR_3DFACE
);
948 return GetSysColorBrush(COLOR_WINDOW
);
951 static void DefWndPrint( HWND hwnd
, HDC hdc
, ULONG uFlags
)
956 if ( (uFlags
& PRF_CHECKVISIBLE
) &&
957 !IsWindowVisible(hwnd
) )
961 * Unimplemented flags.
963 if ( (uFlags
& PRF_CHILDREN
) ||
964 (uFlags
& PRF_OWNED
) ||
965 (uFlags
& PRF_NONCLIENT
) )
967 DPRINT1("WM_PRINT message with unsupported flags\n");
973 if ( uFlags
& PRF_ERASEBKGND
)
974 SendMessageW(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
979 if ( uFlags
& PRF_CLIENT
)
980 SendMessageW(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, PRF_CLIENT
);
985 DefWndScreenshot(HWND hWnd
)
991 User32DefWindowProc(HWND hWnd
,
1001 return DefWndNCPaint(hWnd
, (HRGN
)wParam
, -1);
1006 return DefWndNCCalcSize(hWnd
, (BOOL
)wParam
, (RECT
*)lParam
);
1011 return DefWndNCActivate(hWnd
, wParam
);
1017 Point
.x
= GET_X_LPARAM(lParam
);
1018 Point
.y
= GET_Y_LPARAM(lParam
);
1019 return (DefWndNCHitTest(hWnd
, Point
));
1022 case WM_LBUTTONDOWN
:
1023 case WM_RBUTTONDOWN
:
1024 case WM_MBUTTONDOWN
:
1025 iF10Key
= iMenuSysKey
= 0;
1028 case WM_NCLBUTTONDOWN
:
1030 return (DefWndNCLButtonDown(hWnd
, wParam
, lParam
));
1033 case WM_LBUTTONDBLCLK
:
1034 case WM_NCLBUTTONDBLCLK
:
1036 return (DefWndNCLButtonDblClk(hWnd
, wParam
, lParam
));
1039 case WM_WINDOWPOSCHANGING
:
1041 return (DefWndHandleWindowPosChanging(hWnd
, (WINDOWPOS
*)lParam
));
1044 case WM_WINDOWPOSCHANGED
:
1046 return (DefWndHandleWindowPosChanged(hWnd
, (WINDOWPOS
*)lParam
));
1049 case WM_NCRBUTTONDOWN
:
1051 /* in Windows, capture is taken when right-clicking on the caption bar */
1052 if (wParam
== HTCAPTION
)
1062 if (hWnd
== GetCapture())
1066 Pt
.x
= GET_X_LPARAM(lParam
);
1067 Pt
.y
= GET_Y_LPARAM(lParam
);
1068 ClientToScreen(hWnd
, &Pt
);
1069 lParam
= MAKELPARAM(Pt
.x
, Pt
.y
);
1072 SendMessageW(hWnd
, WM_CONTEXTMENU
, (WPARAM
)hWnd
, lParam
);
1076 SendMessageA(hWnd
, WM_CONTEXTMENU
, (WPARAM
)hWnd
, lParam
);
1081 case WM_NCRBUTTONUP
:
1083 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1084 * in Windows), but what _should_ we do? According to MSDN :
1085 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1086 * message to the window". When is it appropriate?
1090 case WM_CONTEXTMENU
:
1092 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
)
1096 SendMessageW(GetParent(hWnd
), Msg
, wParam
, lParam
);
1100 SendMessageA(GetParent(hWnd
), WM_CONTEXTMENU
, wParam
, lParam
);
1109 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
1111 Pt
.x
= GET_X_LPARAM(lParam
);
1112 Pt
.y
= GET_Y_LPARAM(lParam
);
1113 if (Style
& WS_CHILD
)
1115 ScreenToClient(GetParent(hWnd
), &Pt
);
1118 HitCode
= DefWndNCHitTest(hWnd
, Pt
);
1120 if (HitCode
== HTCAPTION
|| HitCode
== HTSYSMENU
)
1125 if((SystemMenu
= GetSystemMenu(hWnd
, FALSE
)))
1127 MenuInitSysMenuPopup(SystemMenu
, GetWindowLongW(hWnd
, GWL_STYLE
),
1128 GetClassLongW(hWnd
, GCL_STYLE
), HitCode
);
1130 if(HitCode
== HTCAPTION
)
1131 Flags
= TPM_LEFTBUTTON
| TPM_RIGHTBUTTON
;
1133 Flags
= TPM_LEFTBUTTON
;
1135 TrackPopupMenu(SystemMenu
, Flags
,
1136 Pt
.x
, Pt
.y
, 0, hWnd
, NULL
);
1145 DefWndPrint(hWnd
, (HDC
)wParam
, lParam
);
1153 HDC hDC
= BeginPaint(hWnd
, &Ps
);
1157 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_MINIMIZE
&&
1158 (hIcon
= (HICON
)GetClassLongW(hWnd
, GCL_HICON
)) != NULL
)
1162 GetClientRect(hWnd
, &ClientRect
);
1163 x
= (ClientRect
.right
- ClientRect
.left
-
1164 GetSystemMetrics(SM_CXICON
)) / 2;
1165 y
= (ClientRect
.bottom
- ClientRect
.top
-
1166 GetSystemMetrics(SM_CYICON
)) / 2;
1167 DrawIcon(hDC
, x
, y
, hIcon
);
1169 EndPaint(hWnd
, &Ps
);
1177 hRgn
= CreateRectRgn(0, 0, 0, 0);
1178 if (GetUpdateRgn(hWnd
, hRgn
, FALSE
) != NULLREGION
)
1180 RedrawWindow(hWnd
, NULL
, hRgn
,
1181 RDW_ERASENOW
| RDW_ERASE
| RDW_FRAME
|
1190 DefWndSetRedraw(hWnd
, wParam
);
1196 DestroyWindow(hWnd
);
1200 case WM_MOUSEACTIVATE
:
1202 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
)
1207 Ret
= SendMessageW(GetParent(hWnd
), WM_MOUSEACTIVATE
,
1212 Ret
= SendMessageA(GetParent(hWnd
), WM_MOUSEACTIVATE
,
1220 return ((LOWORD(lParam
) >= HTCLIENT
) ? MA_ACTIVATE
: MA_NOACTIVATE
);
1225 /* Check if the window is minimized. */
1226 if (LOWORD(wParam
) != WA_INACTIVE
&&
1227 !(GetWindowLongW(hWnd
, GWL_STYLE
) & WS_MINIMIZE
))
1236 if (GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CHILD
)
1240 return (SendMessageW(GetParent(hWnd
), WM_MOUSEWHEEL
,
1245 return (SendMessageA(GetParent(hWnd
), WM_MOUSEWHEEL
,
1253 case WM_ICONERASEBKGND
:
1256 HBRUSH hBrush
= (HBRUSH
)GetClassLongW(hWnd
, GCL_HBRBACKGROUND
);
1262 if (GetClassLongW(hWnd
, GCL_STYLE
) & CS_PARENTDC
)
1264 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1265 GetClientRect(hWnd
, &Rect
);
1266 DPtoLP((HDC
)wParam
, (LPPOINT
)&Rect
, 2);
1270 GetClipBox((HDC
)wParam
, &Rect
);
1272 FillRect((HDC
)wParam
, &Rect
, hBrush
);
1276 case WM_CTLCOLORMSGBOX
:
1277 case WM_CTLCOLOREDIT
:
1278 case WM_CTLCOLORLISTBOX
:
1279 case WM_CTLCOLORBTN
:
1280 case WM_CTLCOLORDLG
:
1281 case WM_CTLCOLORSTATIC
:
1282 case WM_CTLCOLORSCROLLBAR
:
1283 return (LRESULT
) DefWndControlColor((HDC
)wParam
, Msg
- WM_CTLCOLORMSGBOX
);
1286 return (LRESULT
) DefWndControlColor((HDC
)wParam
, HIWORD(lParam
));
1290 ULONG Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
1292 if (Style
& WS_CHILD
)
1294 if (LOWORD(lParam
) < HTLEFT
|| LOWORD(lParam
) > HTBOTTOMRIGHT
)
1299 bResult
= SendMessageW(GetParent(hWnd
), WM_SETCURSOR
,
1304 bResult
= SendMessageA(GetParent(hWnd
), WM_SETCURSOR
,
1313 return (DefWndHandleSetCursor(hWnd
, wParam
, lParam
, Style
));
1317 return (DefWndHandleSysCommand(hWnd
, wParam
, lParam
));
1320 if(wParam
== VK_F10
) iF10Key
= VK_F10
;
1323 /* FIXME: This is also incomplete. */
1326 if (HIWORD(lParam
) & KEYDATA_ALT
)
1328 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1329 if ( (wParam
== VK_MENU
|| wParam
== VK_LMENU
1330 || wParam
== VK_RMENU
) && !iMenuSysKey
)
1337 if (wParam
== VK_F4
) /* Try to close the window */
1339 HWND top
= GetAncestor(hWnd
, GA_ROOT
);
1340 if (!(GetClassLongW(top
, GCL_STYLE
) & CS_NOCLOSE
))
1343 PostMessageW(top
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1345 PostMessageA(top
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1348 else if (wParam
== VK_SNAPSHOT
)
1350 DefWndScreenshot(hWnd
);
1353 else if( wParam
== VK_F10
)
1355 else if( wParam
== VK_ESCAPE
&& (GetKeyState(VK_SHIFT
) & 0x8000))
1356 SendMessageW( hWnd
, WM_SYSCOMMAND
, SC_KEYMENU
, ' ' );
1363 /* Press and release F10 or ALT */
1364 if (((wParam
== VK_MENU
|| wParam
== VK_LMENU
|| wParam
== VK_RMENU
)
1365 && iMenuSysKey
) || ((wParam
== VK_F10
) && iF10Key
))
1366 SendMessageW( GetAncestor( hWnd
, GA_ROOT
), WM_SYSCOMMAND
, SC_KEYMENU
, 0L );
1367 iMenuSysKey
= iF10Key
= 0;
1374 if (wParam
== '\r' && IsIconic(hWnd
))
1376 PostMessageW( hWnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0L );
1379 if ((HIWORD(lParam
) & KEYDATA_ALT
) && wParam
)
1381 if (wParam
== '\t' || wParam
== '\x1b') break;
1382 if (wParam
== ' ' && (GetWindowLongW( hWnd
, GWL_STYLE
) & WS_CHILD
))
1383 SendMessageW( GetParent(hWnd
), Msg
, wParam
, lParam
);
1385 SendMessageW( hWnd
, WM_SYSCOMMAND
, SC_KEYMENU
, wParam
);
1387 else /* check for Ctrl-Esc */
1388 if (wParam
!= '\x1b') MessageBeep(0);
1397 if (!lParam
) return 0;
1398 Style
= GetWindowLongW(hWnd
, GWL_STYLE
);
1399 if ((Style
& WS_VISIBLE
) && wParam
) return 0;
1400 if (!(Style
& WS_VISIBLE
) && !wParam
) return 0;
1401 if (!GetWindow(hWnd
, GW_OWNER
)) return 0;
1402 Ret
= NtUserCallTwoParam((DWORD
) hWnd
, (DWORD
) wParam
, TWOPARAM_ROUTINE_ROS_SHOWWINDOW
);
1405 if( Ret
== -1) return 0;
1408 ShowWindow(hWnd
, wParam
? SW_SHOWNOACTIVATE
: SW_HIDE
);
1415 /* FIXME: Check for a desktop. */
1416 if (!(GetWindowLongW( hWnd
, GWL_STYLE
) & WS_CHILD
)) EndMenu();
1417 if (GetCapture() == hWnd
)
1431 case WM_QUERYDROPOBJECT
:
1433 if (GetWindowLongW(hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)
1440 case WM_QUERYDRAGICON
:
1445 hIcon
= (HICON
)GetClassLongW(hWnd
, GCL_HICON
);
1448 return ((LRESULT
)hIcon
);
1450 for (Len
= 1; Len
< 64; Len
++)
1452 if ((hIcon
= LoadIconW(NULL
, MAKEINTRESOURCEW(Len
))) != NULL
)
1454 return((LRESULT
)hIcon
);
1457 return ((LRESULT
)LoadIconW(0, IDI_APPLICATION
));
1460 /* FIXME: WM_ISACTIVEICON */
1462 case WM_NOTIFYFORMAT
:
1464 if (IsWindowUnicode(hWnd
))
1466 return(NFR_UNICODE
);
1476 INT Index
= (wParam
!= 0) ? GCL_HICON
: GCL_HICONSM
;
1477 HICON hOldIcon
= (HICON
)GetClassLongW(hWnd
, Index
);
1478 SetClassLongW(hWnd
, Index
, lParam
);
1479 SetWindowPos(hWnd
, 0, 0, 0, 0, 0,
1480 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1481 SWP_NOACTIVATE
| SWP_NOZORDER
);
1482 return ((LRESULT
)hOldIcon
);
1487 INT Index
= (wParam
== ICON_BIG
) ? GCL_HICON
: GCL_HICONSM
;
1488 return (GetClassLongW(hWnd
, Index
));
1495 SendMessageW(GetParent(hWnd
), Msg
, wParam
, lParam
);
1499 SendMessageA(GetParent(hWnd
), Msg
, wParam
, lParam
);
1506 THRDCARETINFO CaretInfo
;
1509 case 0xffff: /* Caret timer */
1510 /* switch showing byte in win32k and get information about the caret */
1511 if(NtUserSwitchCaretShowing(&CaretInfo
) && (CaretInfo
.hWnd
== hWnd
))
1513 DrawCaret(hWnd
, &CaretInfo
);
1521 case WM_QUERYENDSESSION
:
1527 if (wParam
) PostQuitMessage(0);
1536 DefWindowProcA(HWND hWnd
,
1543 SPY_EnterMessage(SPY_DEFWNDPROC
, hWnd
, Msg
, wParam
, lParam
);
1548 ANSI_STRING AnsiString
;
1549 UNICODE_STRING UnicodeString
;
1550 LPCREATESTRUCTA cs
= (LPCREATESTRUCTA
)lParam
;
1551 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1552 * may have child window IDs instead of window name */
1556 RtlInitAnsiString(&AnsiString
, (LPSTR
)cs
->lpszName
);
1557 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
1558 NtUserDefSetText(hWnd
, &UnicodeString
);
1559 RtlFreeUnicodeString(&UnicodeString
);
1562 NtUserDefSetText(hWnd
, NULL
);
1568 case WM_GETTEXTLENGTH
:
1570 Result
= (LRESULT
)NtUserInternalGetWindowText(hWnd
, NULL
, 0);
1577 LPSTR AnsiBuffer
= (LPSTR
)lParam
;
1580 Buffer
= HeapAlloc(GetProcessHeap(), 0, wParam
* sizeof(WCHAR
));
1586 Length
= NtUserInternalGetWindowText(hWnd
, Buffer
, wParam
);
1587 if (Length
> 0 && wParam
> 0 &&
1588 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
1589 AnsiBuffer
, wParam
, NULL
, NULL
))
1591 AnsiBuffer
[0] = '\0';
1594 HeapFree(GetProcessHeap(), 0, Buffer
);
1596 Result
= (LRESULT
)Length
;
1602 ANSI_STRING AnsiString
;
1603 UNICODE_STRING UnicodeString
;
1607 RtlInitAnsiString(&AnsiString
, (LPSTR
)lParam
);
1608 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
1609 NtUserDefSetText(hWnd
, &UnicodeString
);
1610 RtlFreeUnicodeString(&UnicodeString
);
1613 NtUserDefSetText(hWnd
, NULL
);
1615 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) == WS_CAPTION
)
1617 DefWndNCPaint(hWnd
, (HRGN
)1, -1);
1624 /* FIXME: Implement these. */
1626 case WM_IME_KEYDOWN
:
1628 case WM_IME_STARTCOMPOSITION
:
1629 case WM_IME_COMPOSITION
:
1630 case WM_IME_ENDCOMPOSITION
:
1632 case WM_IME_SETCONTEXT
:
1633 DPRINT1("FIXME: WM_IME_* conversion isn't implemented yet!");
1636 Result
= User32DefWindowProc(hWnd
, Msg
, wParam
, lParam
, FALSE
);
1639 SPY_ExitMessage(SPY_RESULT_DEFWND
, hWnd
, Msg
, Result
, wParam
, lParam
);
1645 DefWindowProcW(HWND hWnd
,
1652 SPY_EnterMessage(SPY_DEFWNDPROC
, hWnd
, Msg
, wParam
, lParam
);
1657 UNICODE_STRING UnicodeString
;
1658 LPCREATESTRUCTW cs
= (LPCREATESTRUCTW
)lParam
;
1659 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1660 * may have child window IDs instead of window name */
1663 RtlInitUnicodeString(&UnicodeString
, (LPWSTR
)cs
->lpszName
);
1665 NtUserDefSetText( hWnd
, (cs
->lpszName
? &UnicodeString
: NULL
));
1670 case WM_GETTEXTLENGTH
:
1672 Result
= (LRESULT
)NtUserInternalGetWindowText(hWnd
, NULL
, 0);
1678 Result
= (LRESULT
)NtUserInternalGetWindowText(hWnd
, (PWSTR
)lParam
, wParam
);
1684 UNICODE_STRING UnicodeString
;
1687 RtlInitUnicodeString(&UnicodeString
, (LPWSTR
)lParam
);
1689 NtUserDefSetText(hWnd
, (lParam
? &UnicodeString
: NULL
));
1691 if ((GetWindowLongW(hWnd
, GWL_STYLE
) & WS_CAPTION
) == WS_CAPTION
)
1693 DefWndNCPaint(hWnd
, (HRGN
)1, -1);
1701 SendMessageW(hWnd
, WM_CHAR
, wParam
, lParam
);
1706 case WM_IME_SETCONTEXT
:
1709 DPRINT1("FIXME: WM_IME_SETCONTEXT is not implemented!");
1715 Result
= User32DefWindowProc(hWnd
, Msg
, wParam
, lParam
, TRUE
);
1717 SPY_ExitMessage(SPY_RESULT_DEFWND
, hWnd
, Msg
, Result
, wParam
, lParam
);