2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Miscellaneous User functions
5 * FILE: subsystems/win32/win32k/ntuser/defwnd.c
13 DBG_DEFAULT_CHANNEL(UserDefwnd
);
15 #define UserHasDlgFrameStyle(Style, ExStyle) \
16 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
17 (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
19 #define UserHasThickFrameStyle(Style, ExStyle) \
20 (((Style) & WS_THICKFRAME) && \
21 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
23 #define UserHasThinFrameStyle(Style, ExStyle) \
24 (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
26 #define ON_LEFT_BORDER(hit) \
27 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
28 #define ON_RIGHT_BORDER(hit) \
29 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
30 #define ON_TOP_BORDER(hit) \
31 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
32 #define ON_BOTTOM_BORDER(hit) \
33 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
35 // Client Shutdown messages
36 #define MCS_SHUTDOWNTIMERS 1
37 #define MCS_QUERYENDSESSION 2
38 // Client Shutdown returns
39 #define MCSR_GOODFORSHUTDOWN 1
40 #define MCSR_SHUTDOWNFINISHED 2
41 #define MCSR_DONOTSHUTDOWN 3
44 * Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth Edition".
45 * Apparently CSRSS sends out messages to do this w/o going into win32k internals.
58 LRESULT lResult
= MCSR_GOODFORSHUTDOWN
;
61 lParams
= wParam
& (ENDSESSION_LOGOFF
|ENDSESSION_CRITICAL
|ENDSESSION_CLOSEAPP
);
62 KillTimers
= wParam
& MCS_SHUTDOWNTIMERS
? TRUE
: FALSE
;
64 First, send end sessions to children.
66 List
= IntWinListChildren(pWindow
);
70 for (i
= 0; List
[i
]; i
++)
74 if (!(WndChild
= UserGetWindowObject(List
[i
])))
77 if (wParam
& MCS_QUERYENDSESSION
)
79 if (!co_IntSendMessage(WndChild
->head
.h
, WM_QUERYENDSESSION
, 0, lParams
))
81 lResult
= MCSR_DONOTSHUTDOWN
;
87 co_IntSendMessage(WndChild
->head
.h
, WM_ENDSESSION
, KillTimers
, lParams
);
90 DestroyTimersForWindow(WndChild
->head
.pti
, WndChild
);
92 lResult
= MCSR_SHUTDOWNFINISHED
;
95 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
97 if (List
&& (lResult
== MCSR_DONOTSHUTDOWN
)) return lResult
;
101 if (wParam
& MCS_QUERYENDSESSION
)
103 if (!co_IntSendMessage(pWindow
->head
.h
, WM_QUERYENDSESSION
, 0, lParams
))
105 lResult
= MCSR_DONOTSHUTDOWN
;
110 co_IntSendMessage(pWindow
->head
.h
, WM_ENDSESSION
, KillTimers
, lParams
);
113 DestroyTimersForWindow(pWindow
->head
.pti
, pWindow
);
115 lResult
= MCSR_SHUTDOWNFINISHED
;
121 DefWndControlColor(HDC hDC
, UINT ctlType
)
123 if (ctlType
== CTLCOLOR_SCROLLBAR
)
125 HBRUSH hb
= IntGetSysColorBrush(COLOR_SCROLLBAR
);
126 COLORREF bk
= IntGetSysColor(COLOR_3DHILIGHT
);
127 IntGdiSetTextColor(hDC
, IntGetSysColor(COLOR_3DFACE
));
128 IntGdiSetBkColor(hDC
, bk
);
130 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
131 * we better use 0x55aa bitmap brush to make scrollbar's background
132 * look different from the window background.
134 if ( bk
== IntGetSysColor(COLOR_WINDOW
))
135 return gpsi
->hbrGray
;
137 NtGdiUnrealizeObject( hb
);
141 IntGdiSetTextColor(hDC
, IntGetSysColor(COLOR_WINDOWTEXT
));
143 if ((ctlType
== CTLCOLOR_EDIT
) || (ctlType
== CTLCOLOR_LISTBOX
))
145 IntGdiSetBkColor(hDC
, IntGetSysColor(COLOR_WINDOW
));
149 IntGdiSetBkColor(hDC
, IntGetSysColor(COLOR_3DFACE
));
150 return IntGetSysColorBrush(COLOR_3DFACE
);
153 return IntGetSysColorBrush(COLOR_WINDOW
);
157 DefWndHandleWindowPosChanging(PWND pWnd
, WINDOWPOS
* Pos
)
159 POINT maxTrack
, minTrack
;
160 LONG style
= pWnd
->style
;
162 if (Pos
->flags
& SWP_NOSIZE
) return 0;
163 if ((style
& WS_THICKFRAME
) || ((style
& (WS_POPUP
| WS_CHILD
)) == 0))
165 co_WinPosGetMinMaxInfo(pWnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
166 Pos
->cx
= min(Pos
->cx
, maxTrack
.x
);
167 Pos
->cy
= min(Pos
->cy
, maxTrack
.y
);
168 if (!(style
& WS_MINIMIZE
))
170 if (Pos
->cx
< minTrack
.x
) Pos
->cx
= minTrack
.x
;
171 if (Pos
->cy
< minTrack
.y
) Pos
->cy
= minTrack
.y
;
176 Pos
->cx
= max(Pos
->cx
, 0);
177 Pos
->cy
= max(Pos
->cy
, 0);
183 DefWndHandleWindowPosChanged(PWND pWnd
, WINDOWPOS
* Pos
)
186 LONG style
= pWnd
->style
;
188 IntGetClientRect(pWnd
, &Rect
);
189 IntMapWindowPoints(pWnd
, (style
& WS_CHILD
? IntGetParent(pWnd
) : NULL
), (LPPOINT
) &Rect
, 2);
191 if (!(Pos
->flags
& SWP_NOCLIENTMOVE
))
193 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_MOVE
, 0, MAKELONG(Rect
.left
, Rect
.top
));
196 if (!(Pos
->flags
& SWP_NOCLIENTSIZE
) || (Pos
->flags
& SWP_STATECHANGED
))
198 if (style
& WS_MINIMIZE
) co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SIZE
, SIZE_MINIMIZED
, 0 );
201 WPARAM wp
= (style
& WS_MAXIMIZE
) ? SIZE_MAXIMIZED
: SIZE_RESTORED
;
202 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SIZE
, wp
, MAKELONG(Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
));
209 UserDrawWindowFrame(HDC hdc
,
214 HBRUSH hbrush
= NtGdiSelectBrush( hdc
, gpsi
->hbrGray
);
215 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
, rect
->right
- rect
->left
- width
, height
, PATINVERT
);
216 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
+ height
, width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
217 NtGdiPatBlt( hdc
, rect
->left
+ width
, rect
->bottom
- 1, rect
->right
- rect
->left
- width
, -height
, PATINVERT
);
218 NtGdiPatBlt( hdc
, rect
->right
- 1, rect
->top
, -width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
219 NtGdiSelectBrush( hdc
, hbrush
);
223 UserDrawMovingFrame(HDC hdc
,
227 if (thickframe
) UserDrawWindowFrame(hdc
, rect
, UserGetSystemMetrics(SM_CXFRAME
), UserGetSystemMetrics(SM_CYFRAME
));
228 else UserDrawWindowFrame(hdc
, rect
, 1, 1);
231 /***********************************************************************
234 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
235 * but without the borders (if any).
238 NC_GetInsideRect(PWND Wnd
, RECT
*rect
)
244 ExStyle
= Wnd
->ExStyle
;
246 rect
->top
= rect
->left
= 0;
247 rect
->right
= Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
;
248 rect
->bottom
= Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
;
250 if (Style
& WS_ICONIC
) return;
252 /* Remove frame from rectangle */
253 if (UserHasThickFrameStyle(Style
, ExStyle
))
255 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
));
259 if (UserHasDlgFrameStyle(Style
, ExStyle
))
261 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
262 /* FIXME: this isn't in NC_AdjustRect? why not? */
263 if (ExStyle
& WS_EX_DLGMODALFRAME
)
264 RECTL_vInflateRect( rect
, -1, 0 );
268 if (UserHasThinFrameStyle(Style
, ExStyle
))
270 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
274 /* We have additional border information if the window
275 * is a child (but not an MDI child) */
276 if ((Style
& WS_CHILD
) && !(ExStyle
& WS_EX_MDICHILD
))
278 if (ExStyle
& WS_EX_CLIENTEDGE
)
279 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
280 if (ExStyle
& WS_EX_STATICEDGE
)
281 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
286 DefWndStartSizeMove(PWND Wnd
, WPARAM wParam
, POINT
*capturePoint
)
292 ULONG Style
= Wnd
->style
;
293 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
295 rectWindow
= Wnd
->rcWindow
;
297 if ((wParam
& 0xfff0) == SC_MOVE
)
299 /* Move pointer at the center of the caption */
300 RECT rect
= rectWindow
;
301 /* Note: to be exactly centered we should take the different types
302 * of border into account, but it shouldn't make more than a few pixels
303 * of difference so let's not bother with that */
304 if (Style
& WS_SYSMENU
)
305 rect
.left
+= UserGetSystemMetrics(SM_CXSIZE
) + 1;
306 if (Style
& WS_MINIMIZEBOX
)
307 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
308 if (Style
& WS_MAXIMIZEBOX
)
309 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
310 pt
.x
= (rect
.right
+ rect
.left
) / 2;
311 pt
.y
= rect
.top
+ UserGetSystemMetrics(SM_CYSIZE
)/2;
320 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) return 0;
321 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
326 //// Clamp the mouse position to the window rectangle when starting a window resize.
327 pt
.x
= min( max( msg
.pt
.x
, rectWindow
.left
), rectWindow
.right
- 1 );
328 pt
.y
= min( max( msg
.pt
.y
, rectWindow
.top
), rectWindow
.bottom
- 1 );
329 hittest
= GetNCHitEx(Wnd
, pt
);
330 if ((hittest
< HTLEFT
) || (hittest
> HTBOTTOMRIGHT
)) hittest
= 0;
341 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
342 pt
.y
= rectWindow
.top
+ UserGetSystemMetrics(SM_CYFRAME
) / 2;
346 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
347 pt
.y
= rectWindow
.bottom
- UserGetSystemMetrics(SM_CYFRAME
) / 2;
351 pt
.x
= rectWindow
.left
+ UserGetSystemMetrics(SM_CXFRAME
) / 2;
352 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
356 pt
.x
= rectWindow
.right
- UserGetSystemMetrics(SM_CXFRAME
) / 2;
357 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
364 IntTranslateKbdMessage( &msg
, 0 );
365 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
366 IntDispatchMessage( &msg
);
367 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
373 UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
374 co_IntSendMessage(UserHMGetHandle(Wnd
), WM_SETCURSOR
, (WPARAM
)UserHMGetHandle(Wnd
), MAKELONG(hittest
, WM_MOUSEMOVE
));
379 // System Command Size and Move
381 // Perform SC_MOVE and SC_SIZE commands.
384 DefWndDoSizeMove(PWND pwnd
, WORD wParam
)
387 RECT sizingRect
, mouseRect
, origRect
, unmodRect
;
389 LONG hittest
= (LONG
)(wParam
& 0x0f);
390 HCURSOR hDragCursor
= 0, hOldCursor
= 0;
391 POINT minTrack
, maxTrack
;
392 POINT capturePoint
, pt
;
393 ULONG Style
, ExStyle
;
397 BOOL DragFullWindows
= FALSE
;
398 PWND pWndParent
= NULL
;
399 WPARAM syscommand
= (wParam
& 0xfff0);
400 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
401 //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
402 // The task bar can grow in size and can not reduce due to the change
406 ExStyle
= pwnd
->ExStyle
;
407 iconic
= (Style
& WS_MINIMIZE
) != 0;
409 if ((Style
& WS_MAXIMIZE
) || !IntIsWindowVisible(pwnd
)) return;
411 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !iconic
;
414 // Show window contents while dragging the window, get flag from registry data.
416 UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
418 pt
.x
= pti
->ptLast
.x
;
419 pt
.y
= pti
->ptLast
.y
;
421 UserClipCursor( NULL
);
423 TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
424 pwnd
, syscommand
, hittest
, pt
.x
, pt
.y
);
426 if (syscommand
== SC_MOVE
)
428 if (!hittest
) hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
429 if (!hittest
) return;
433 if (!thickframe
) return;
434 if (hittest
&& (syscommand
!= SC_MOUSEMENU
))
436 hittest
+= (HTLEFT
- WMSZ_LEFT
);
440 co_UserSetCapture(UserHMGetHandle(pwnd
));
441 hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
450 /* Get min/max info */
452 co_WinPosGetMinMaxInfo(pwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
453 sizingRect
= pwnd
->rcWindow
;
454 origRect
= sizingRect
;
455 if (Style
& WS_CHILD
)
457 pWndParent
= IntGetParent(pwnd
);
458 IntGetClientRect( pWndParent
, &mouseRect
);
459 IntMapWindowPoints( pWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
460 IntMapWindowPoints( 0, pWndParent
, (LPPOINT
)&sizingRect
, 2 );
461 unmodRect
= sizingRect
;
465 if (!(ExStyle
& WS_EX_TOPMOST
))
467 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
471 RECTL_vSetRect(&mouseRect
, 0, 0, UserGetSystemMetrics(SM_CXSCREEN
), UserGetSystemMetrics(SM_CYSCREEN
));
473 unmodRect
= sizingRect
;
476 if (ON_LEFT_BORDER(hittest
))
478 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
+capturePoint
.x
-sizingRect
.left
);
479 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
+capturePoint
.x
-sizingRect
.left
);
481 else if (ON_RIGHT_BORDER(hittest
))
483 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
+capturePoint
.x
-sizingRect
.right
);
484 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
+capturePoint
.x
-sizingRect
.right
);
486 if (ON_TOP_BORDER(hittest
))
488 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
+capturePoint
.y
-sizingRect
.top
);
489 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
+capturePoint
.y
-sizingRect
.top
);
491 else if (ON_BOTTOM_BORDER(hittest
))
493 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
494 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
497 hdc
= UserGetDCEx( pWndParent
, 0, DCX_CACHE
);
499 if ( iconic
) /* create a cursor for dragging */
501 hDragCursor
= pwnd
->pcls
->hIcon
;;
502 if ( !hDragCursor
) hDragCursor
= (HCURSOR
)co_IntSendMessage( UserHMGetHandle(pwnd
), WM_QUERYDRAGICON
, 0, 0 );
503 if ( !hDragCursor
) iconic
= FALSE
;
506 /* repaint the window before moving it around */
507 co_UserRedrawWindow( pwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
509 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
511 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_ENTERSIZEMOVE
, 0, 0 );
513 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, UserHMGetHandle(pwnd
));
515 if (IntGetCapture() != UserHMGetHandle(pwnd
)) co_UserSetCapture( UserHMGetHandle(pwnd
) );
517 pwnd
->head
.pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
523 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) break;
524 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
526 /* Exit on button-up, Return, or Esc */
527 if ((msg
.message
== WM_LBUTTONUP
) ||
528 ((msg
.message
== WM_KEYDOWN
) &&
529 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
531 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
533 IntTranslateKbdMessage( &msg
, 0 );
534 IntDispatchMessage( &msg
);
535 continue; /* We are not interested in other messages */
540 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
542 case VK_UP
: pt
.y
-= 8; break;
543 case VK_DOWN
: pt
.y
+= 8; break;
544 case VK_LEFT
: pt
.x
-= 8; break;
545 case VK_RIGHT
: pt
.x
+= 8; break;
548 pt
.x
= max( pt
.x
, mouseRect
.left
);
549 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
550 pt
.y
= max( pt
.y
, mouseRect
.top
);
551 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
553 dx
= pt
.x
- capturePoint
.x
;
554 dy
= pt
.y
- capturePoint
.y
;
562 if ( iconic
) /* ok, no system popup tracking */
564 hOldCursor
= IntSetCursor(hDragCursor
);
565 UserShowCursor( TRUE
);
567 else if(!DragFullWindows
)
568 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
571 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
574 RECT newRect
= unmodRect
;
576 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
577 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
578 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
579 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
580 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
581 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
585 // Save the new position to the unmodified rectangle. This allows explorer task bar
586 // sizing. Explorer will forces back the position unless a certain amount of sizing
591 /* determine the hit location */
592 if (syscommand
== SC_SIZE
)
594 WPARAM wpSizingHit
= 0;
596 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
597 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
598 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
601 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
605 if (!DragFullWindows
)
606 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
608 { // Moving the whole window now!
610 //// This causes the mdi child window to jump up when it is moved.
611 //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
612 co_WinPosSetWindowPos( pwnd
,
616 newRect
.right
- newRect
.left
,
617 newRect
.bottom
- newRect
.top
,
618 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
620 // Update all the windows after the move or size, including this window.
621 for ( pwndTemp
= pwnd
->head
.rpdesk
->pDeskInfo
->spwnd
->spwndChild
;
623 pwndTemp
= pwndTemp
->spwndNext
)
626 // Only the windows that overlap will be redrawn.
627 if (RECTL_bIntersectRect( &rect
, &pwnd
->rcWindow
, &pwndTemp
->rcWindow
))
629 co_UserRedrawWindow( pwndTemp
, NULL
, NULL
, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
634 sizingRect
= newRect
;
639 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
645 if ( moved
) /* restore cursors, show icon title later on */
647 UserShowCursor( FALSE
);
648 IntSetCursor( hOldCursor
);
650 IntDestroyCursor( hDragCursor
, FALSE
);
652 else if ( moved
&& !DragFullWindows
)
653 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
655 UserReleaseDC(NULL
, hdc
, FALSE
);
657 //// This causes the mdi child window to jump up when it is moved.
658 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
660 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
662 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
666 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
668 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
670 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
672 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
674 /* window moved or resized */
677 /* if the moving/resizing isn't canceled call SetWindowPos
678 * with the new position or the new size of the window
680 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
682 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
683 if (!DragFullWindows
|| iconic
)
685 co_WinPosSetWindowPos( pwnd
,
689 sizingRect
.right
- sizingRect
.left
,
690 sizingRect
.bottom
- sizingRect
.top
,
691 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
695 { /* restore previous size/position */
696 if ( DragFullWindows
)
698 co_WinPosSetWindowPos( pwnd
,
702 origRect
.right
- origRect
.left
,
703 origRect
.bottom
- origRect
.top
,
704 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
709 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
712 /* Single click brings up the system menu when iconized */
715 if( Style
& WS_SYSMENU
)
716 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
722 // Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
725 DefWndHandleSysCommand(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
730 if (ISITHOOKED(WH_CBT
) || (pWnd
->head
.rpdesk
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_CBT
)))
733 lResult
= co_HOOK_CallHooks(WH_CBT
, HCBT_SYSCOMMAND
, wParam
, lParam
);
735 if (lResult
) return lResult
;
738 switch (wParam
& 0xfff0)
742 DefWndDoSizeMove(pWnd
, wParam
);
746 if (UserHMGetHandle(pWnd
) == UserGetActiveWindow())
747 IntShowOwnedPopups(pWnd
,FALSE
); // This is done in ShowWindow! Need to retest!
748 co_WinPosShowWindow( pWnd
, SW_MINIMIZE
);
752 if (((pWnd
->style
& WS_MINIMIZE
) != 0) && UserHMGetHandle(pWnd
) == UserGetActiveWindow())
753 IntShowOwnedPopups(pWnd
,TRUE
);
754 co_WinPosShowWindow( pWnd
, SW_MAXIMIZE
);
758 if (((pWnd
->style
& WS_MINIMIZE
) != 0) && UserHMGetHandle(pWnd
) == UserGetActiveWindow())
759 IntShowOwnedPopups(pWnd
,TRUE
);
760 co_WinPosShowWindow( pWnd
, SW_RESTORE
);
764 return co_IntSendMessage(UserHMGetHandle(pWnd
), WM_CLOSE
, 0, 0);
767 ERR("Screensaver Called!\n");
768 UserPostMessage(hwndSAS
, WM_LOGONNOTIFY
, LN_START_SCREENSAVE
, 0); // always lParam 0 == not Secure
773 USER_REFERENCE_ENTRY Ref
;
775 pWnd
= ValidateHwndNoErr((HWND
)lParam
);
778 if (pWnd
->spwndLastActive
)
780 pWnd
= pWnd
->spwndLastActive
;
782 UserRefObjectCo(pWnd
, &Ref
);
783 co_IntSetForegroundWindow(pWnd
);
784 UserDerefObjectCo(pWnd
);
785 if (pWnd
->style
& WS_MINIMIZE
)
787 UserPostMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_RESTORE
, 0);
795 // We do not support anything else here so we should return normal even when sending a hook.
799 return(Hook
? 1 : 0); // Don't call us again from user space.
802 VOID FASTCALL
DefWndPrint( PWND pwnd
, HDC hdc
, ULONG uFlags
)
807 if ( (uFlags
& PRF_CHECKVISIBLE
) &&
808 !IntIsWindowVisible(pwnd
) )
812 * Unimplemented flags.
814 if ( (uFlags
& PRF_CHILDREN
) ||
815 (uFlags
& PRF_OWNED
) ||
816 (uFlags
& PRF_NONCLIENT
) )
818 FIXME("WM_PRINT message with unsupported flags\n");
824 if ( uFlags
& PRF_ERASEBKGND
)
825 co_IntSendMessage(UserHMGetHandle(pwnd
), WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
830 if ( uFlags
& PRF_CLIENT
)
831 co_IntSendMessage(UserHMGetHandle(pwnd
), WM_PRINTCLIENT
, (WPARAM
)hdc
, uFlags
);
836 Win32k counterpart of User DefWindowProc
847 USER_REFERENCE_ENTRY Ref
;
849 if (Msg
> WM_USER
) return 0;
855 ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd
->head
.h
, wParam
, lParam
);
856 lResult
= DefWndHandleSysCommand(Wnd
, wParam
, lParam
);
861 if ((Wnd
->style
& WS_VISIBLE
) && wParam
) break;
862 if (!(Wnd
->style
& WS_VISIBLE
) && !wParam
) break;
863 if (!Wnd
->spwndOwner
) break;
868 if (!(Wnd
->state
& WNDS_HIDDENPOPUP
)) break;
869 Wnd
->state
&= ~WNDS_HIDDENPOPUP
;
872 Wnd
->state
|= WNDS_HIDDENPOPUP
;
874 co_WinPosShowWindow(Wnd
, wParam
? SW_SHOWNOACTIVATE
: SW_HIDE
);
878 case WM_CLIENTSHUTDOWN
:
879 return IntClientShutdown(Wnd
, wParam
, lParam
);
882 ERR("WM_APPCOMMAND\n");
883 if ( (Wnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
884 Wnd
!= co_GetDesktopWindow(Wnd
) )
886 if (!co_HOOK_CallHooks(WH_SHELL
, HSHELL_APPCOMMAND
, wParam
, lParam
))
887 co_IntShellHookNotify(HSHELL_APPCOMMAND
, wParam
, lParam
);
890 UserRefObjectCo(Wnd
->spwndParent
, &Ref
);
891 lResult
= co_IntSendMessage(UserHMGetHandle(Wnd
->spwndParent
), WM_APPCOMMAND
, wParam
, lParam
);
892 UserDerefObjectCo(Wnd
->spwndParent
);
896 co_UserDestroyWindow(Wnd
);
899 case WM_CTLCOLORMSGBOX
:
900 case WM_CTLCOLOREDIT
:
901 case WM_CTLCOLORLISTBOX
:
904 case WM_CTLCOLORSTATIC
:
905 case WM_CTLCOLORSCROLLBAR
:
906 return (LRESULT
) DefWndControlColor((HDC
)wParam
, Msg
- WM_CTLCOLORMSGBOX
);
909 return (LRESULT
) DefWndControlColor((HDC
)wParam
, HIWORD(lParam
));
912 /* The default action in Windows is to set the keyboard focus to
913 * the window, if it's being activated and not minimized */
914 if (LOWORD(wParam
) != WA_INACTIVE
&&
915 !(Wnd
->style
& WS_MINIMIZE
))
917 //ERR("WM_ACTIVATE %p\n",hWnd);
918 co_UserSetFocus(Wnd
);
923 if (Wnd
->style
& WS_CHILD
)
926 PWND pwndParent
= IntGetParent(Wnd
);
927 hwndParent
= pwndParent
? UserHMGetHandle(pwndParent
) : NULL
;
928 return co_IntSendMessage( hwndParent
, WM_MOUSEWHEEL
, wParam
, lParam
);
933 case WM_ICONERASEBKGND
:
936 HBRUSH hBrush
= Wnd
->pcls
->hbrBackground
;
937 if (!hBrush
) return 0;
938 if (hBrush
<= (HBRUSH
)COLOR_MENUBAR
)
940 hBrush
= IntGetSysColorBrush((INT
)hBrush
);
942 if (Wnd
->pcls
->style
& CS_PARENTDC
)
944 /* can't use GetClipBox with a parent DC or we fill the whole parent */
945 IntGetClientRect(Wnd
, &Rect
);
946 GreDPtoLP((HDC
)wParam
, (LPPOINT
)&Rect
, 2);
950 GdiGetClipBox((HDC
)wParam
, &Rect
);
952 FillRect((HDC
)wParam
, &Rect
, hBrush
);
957 //ERR("WM_GETHOTKEY\n");
958 return DefWndGetHotKey(Wnd
);
960 //ERR("WM_SETHOTKEY\n");
961 return DefWndSetHotKey(Wnd
, wParam
);
966 Point
.x
= GET_X_LPARAM(lParam
);
967 Point
.y
= GET_Y_LPARAM(lParam
);
968 return GetNCHitEx(Wnd
, Point
);
973 DefWndPrint(Wnd
, (HDC
)wParam
, lParam
);
983 /* If already in Paint and Client area is not empty just return. */
984 if (Wnd
->state2
& WNDS2_STARTPAINT
&& !RECTL_bIsEmptyRect(&Wnd
->rcClient
))
986 ERR("In Paint and Client area is not empty!\n");
990 hDC
= IntBeginPaint(Wnd
, &Ps
);
994 if (((Wnd
->style
& WS_MINIMIZE
) != 0) && (hIcon
= Wnd
->pcls
->hIcon
))
998 PCURICON_OBJECT pIcon
;
999 if (!(pIcon
= UserGetCurIconObject(hIcon
))) return 0;
1000 ERR("Doing Paint and Client area is empty!\n");
1001 IntGetClientRect(Wnd
, &ClientRect
);
1002 x
= (ClientRect
.right
- ClientRect
.left
- UserGetSystemMetrics(SM_CXICON
)) / 2;
1003 y
= (ClientRect
.bottom
- ClientRect
.top
- UserGetSystemMetrics(SM_CYICON
)) / 2;
1004 UserDrawIconEx( hDC
, x
, y
, pIcon
, 0, 0, 0, 0, DI_NORMAL
| DI_COMPAT
| DI_DEFAULTSIZE
);
1006 IntEndPaint(Wnd
, &Ps
);
1014 Wnd
->state
&= ~WNDS_SYNCPAINTPENDING
;
1015 ERR("WM_SYNCPAINT\n");
1016 hRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
1017 if (co_UserGetUpdateRgn(Wnd
, hRgn
, FALSE
) != NULLREGION
)
1019 if (!wParam
) wParam
= (RDW_ERASENOW
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
1020 co_UserRedrawWindow(Wnd
, NULL
, hRgn
, wParam
);
1022 GreDeleteObject(hRgn
);
1027 ERR("WM_SETREDRAW\n");
1030 if (!(Wnd
->style
& WS_VISIBLE
))
1032 IntSetStyle( Wnd
, WS_VISIBLE
, 0 );
1033 Wnd
->state
|= WNDS_SENDNCPAINT
;
1038 if (Wnd
->style
& WS_VISIBLE
)
1040 co_UserRedrawWindow( Wnd
, NULL
, NULL
, RDW_ALLCHILDREN
| RDW_VALIDATE
);
1041 IntSetStyle( Wnd
, 0, WS_VISIBLE
);
1046 case WM_WINDOWPOSCHANGING
:
1048 return (DefWndHandleWindowPosChanging(Wnd
, (WINDOWPOS
*)lParam
));
1051 case WM_WINDOWPOSCHANGED
:
1053 return (DefWndHandleWindowPosChanged(Wnd
, (WINDOWPOS
*)lParam
));
1069 ProbeForRead((PVOID
)lParam
,
1077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1084 lResult
= co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)Wnd
->head
.h
, lParam
? (LPARAM
)&rt
: 0);
1095 HICON FASTCALL
NC_IconForWindow( PWND pWnd
)
1098 // First thing to do, init the Window Logo icons.
1099 if (!gpsi
->hIconSmWindows
) co_IntSetWndIcons();
1101 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
);
1102 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
);
1103 if (!hIcon
) hIcon
= pWnd
->pcls
->hIconSm
;
1104 if (!hIcon
) hIcon
= pWnd
->pcls
->hIcon
;
1106 if (!hIcon
&& pWnd
->style
& DS_MODALFRAME
)
1108 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
1109 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
1115 GetNCHitEx(PWND pWnd
, POINT pt
)
1117 RECT rcWindow
, rcClient
;
1118 DWORD Style
, ExStyle
;
1120 if (!pWnd
) return HTNOWHERE
;
1122 if (pWnd
== UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
1124 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
1125 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1126 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1127 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1128 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1132 rcClient
= pWnd
->rcClient
;
1133 rcWindow
= pWnd
->rcWindow
;
1136 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
1138 Style
= pWnd
->style
;
1139 ExStyle
= pWnd
->ExStyle
;
1141 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
1143 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
1146 if (HAS_THICKFRAME( Style
, ExStyle
))
1148 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1149 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
1151 /* Check top sizing border */
1152 if (pt
.y
< rcWindow
.top
)
1154 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
1155 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
1158 /* Check bottom sizing border */
1159 if (pt
.y
>= rcWindow
.bottom
)
1161 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
1162 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
1165 /* Check left sizing border */
1166 if (pt
.x
< rcWindow
.left
)
1168 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
1169 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
1172 /* Check right sizing border */
1173 if (pt
.x
>= rcWindow
.right
)
1175 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
1176 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
1181 else /* No thick frame */
1183 if (HAS_DLGFRAME( Style
, ExStyle
))
1184 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1185 else if (HAS_THINFRAME( Style
, ExStyle
))
1186 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1187 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1192 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1194 if (ExStyle
& WS_EX_TOOLWINDOW
)
1195 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1197 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1198 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1200 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1201 if (ExStyle
& WS_EX_LAYOUTRTL
)
1203 /* Check system menu */
1204 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1206 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1207 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
1210 /* Check close button */
1211 if (Style
& WS_SYSMENU
)
1213 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
1214 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
1217 /* Check maximize box */
1218 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1219 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1221 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1222 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
1225 /* Check minimize box */
1226 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1228 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1229 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
1234 /* Check system menu */
1235 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1237 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1238 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
1241 /* Check close button */
1242 if (Style
& WS_SYSMENU
)
1244 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
1245 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
1248 /* Check maximize box */
1249 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1250 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1252 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1253 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
1256 /* Check minimize box */
1257 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1259 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1260 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
1267 /* Check menu bar */
1269 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
1270 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
1273 /* Check vertical scroll bar */
1275 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
1276 if (Style
& WS_VSCROLL
)
1278 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1279 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1281 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1282 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
1285 /* Check horizontal scroll bar */
1287 if (Style
& WS_HSCROLL
)
1289 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
1290 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
1292 /* Check size box */
1293 if ((Style
& WS_VSCROLL
) &&
1294 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
1295 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
1301 /* Has to return HTNOWHERE if nothing was found
1302 Could happen when a window has a customized non client area */