2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Miscellaneous User functions
5 * FILE: win32ss/user/ntuser/nonclient.c
12 DBG_DEFAULT_CHANNEL(UserDefwnd
);
14 #define UserHasDlgFrameStyle(Style, ExStyle) \
15 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
16 (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
18 #define UserHasThickFrameStyle(Style, ExStyle) \
19 (((Style) & WS_THICKFRAME) && \
20 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
22 #define UserHasThinFrameStyle(Style, ExStyle) \
23 (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
25 #define ON_LEFT_BORDER(hit) \
26 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
27 #define ON_RIGHT_BORDER(hit) \
28 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
29 #define ON_TOP_BORDER(hit) \
30 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
31 #define ON_BOTTOM_BORDER(hit) \
32 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
34 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
35 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
36 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
37 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
38 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
42 UserDrawWindowFrame(HDC hdc
,
47 HBRUSH hbrush
= NtGdiSelectBrush( hdc
, gpsi
->hbrGray
);
48 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
, rect
->right
- rect
->left
- width
, height
, PATINVERT
);
49 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
+ height
, width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
50 NtGdiPatBlt( hdc
, rect
->left
+ width
, rect
->bottom
- 1, rect
->right
- rect
->left
- width
, -(LONG
)height
, PATINVERT
);
51 NtGdiPatBlt( hdc
, rect
->right
- 1, rect
->top
, -(LONG
)width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
52 NtGdiSelectBrush( hdc
, hbrush
);
56 UserDrawMovingFrame(HDC hdc
,
60 if (thickframe
) UserDrawWindowFrame(hdc
, rect
, UserGetSystemMetrics(SM_CXFRAME
), UserGetSystemMetrics(SM_CYFRAME
));
61 else UserDrawWindowFrame(hdc
, rect
, 1, 1);
64 /***********************************************************************
67 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
68 * but without the borders (if any).
70 void FASTCALL
// Previously known as "UserGetInsideRectNC"
71 NC_GetInsideRect(PWND Wnd
, RECT
*rect
)
77 ExStyle
= Wnd
->ExStyle
;
79 rect
->top
= rect
->left
= 0;
80 rect
->right
= Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
;
81 rect
->bottom
= Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
;
83 if (Style
& WS_ICONIC
) return;
85 /* Remove frame from rectangle */
86 if (UserHasThickFrameStyle(Style
, ExStyle
))
88 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
));
90 else if (UserHasDlgFrameStyle(Style
, ExStyle
))
92 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
93 /* FIXME: this isn't in NC_AdjustRect? why not? */
94 if (ExStyle
& WS_EX_DLGMODALFRAME
)
95 RECTL_vInflateRect( rect
, -1, 0 );
97 else if (UserHasThinFrameStyle(Style
, ExStyle
))
99 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
102 /* We have additional border information if the window
103 * is a child (but not an MDI child) */
104 if ((Style
& WS_CHILD
) && !(ExStyle
& WS_EX_MDICHILD
))
106 if (ExStyle
& WS_EX_CLIENTEDGE
)
107 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
108 if (ExStyle
& WS_EX_STATICEDGE
)
109 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
113 /***********************************************************************
117 NC_GetSysPopupPos(PWND Wnd
, RECT
*Rect
)
121 if ((Wnd
->style
& WS_MINIMIZE
) != 0)
123 IntGetWindowRect(Wnd
, Rect
);
127 NC_GetInsideRect(Wnd
, Rect
);
128 IntGetWindowRect(Wnd
, &WindowRect
);
129 RECTL_vOffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
130 if (Wnd
->style
& WS_CHILD
)
132 IntClientToScreen(IntGetParent(Wnd
), (POINT
*) Rect
);
134 Rect
->right
= Rect
->left
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
135 Rect
->bottom
= Rect
->top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
140 DefWndStartSizeMove(PWND Wnd
, WPARAM wParam
, POINT
*capturePoint
)
146 ULONG Style
= Wnd
->style
;
147 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
149 rectWindow
= Wnd
->rcWindow
;
151 if ((wParam
& 0xfff0) == SC_MOVE
)
153 /* Move pointer at the center of the caption */
154 RECT rect
= rectWindow
;
155 /* Note: to be exactly centered we should take the different types
156 * of border into account, but it shouldn't make more than a few pixels
157 * of difference so let's not bother with that */
158 if (Style
& WS_SYSMENU
)
159 rect
.left
+= UserGetSystemMetrics(SM_CXSIZE
) + 1;
160 if (Style
& WS_MINIMIZEBOX
)
161 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
162 if (Style
& WS_MAXIMIZEBOX
)
163 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
164 pt
.x
= (rect
.right
+ rect
.left
) / 2;
165 pt
.y
= rect
.top
+ UserGetSystemMetrics(SM_CYSIZE
)/2;
174 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) return 0;
175 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
180 //// Clamp the mouse position to the window rectangle when starting a window resize.
181 pt
.x
= min( max( msg
.pt
.x
, rectWindow
.left
), rectWindow
.right
- 1 );
182 pt
.y
= min( max( msg
.pt
.y
, rectWindow
.top
), rectWindow
.bottom
- 1 );
183 hittest
= GetNCHitEx(Wnd
, pt
);
184 if ((hittest
< HTLEFT
) || (hittest
> HTBOTTOMRIGHT
)) hittest
= 0;
195 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
196 pt
.y
= rectWindow
.top
+ UserGetSystemMetrics(SM_CYFRAME
) / 2;
200 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
201 pt
.y
= rectWindow
.bottom
- UserGetSystemMetrics(SM_CYFRAME
) / 2;
205 pt
.x
= rectWindow
.left
+ UserGetSystemMetrics(SM_CXFRAME
) / 2;
206 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
210 pt
.x
= rectWindow
.right
- UserGetSystemMetrics(SM_CXFRAME
) / 2;
211 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
219 IntTranslateKbdMessage( &msg
, 0 );
220 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
221 IntDispatchMessage( &msg
);
222 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
228 UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
229 co_IntSendMessage(UserHMGetHandle(Wnd
), WM_SETCURSOR
, (WPARAM
)UserHMGetHandle(Wnd
), MAKELONG(hittest
, WM_MOUSEMOVE
));
234 // System Command Size and Move
236 // Perform SC_MOVE and SC_SIZE commands.
239 DefWndDoSizeMove(PWND pwnd
, WORD wParam
)
242 RECT sizingRect
, mouseRect
, origRect
, unmodRect
;
244 LONG hittest
= (LONG
)(wParam
& 0x0f);
245 PCURICON_OBJECT DragCursor
= NULL
, OldCursor
= NULL
;
246 POINT minTrack
, maxTrack
;
247 POINT capturePoint
, pt
;
248 ULONG Style
, ExStyle
;
252 BOOL DragFullWindows
= FALSE
;
253 PWND pWndParent
= NULL
;
254 WPARAM syscommand
= (wParam
& 0xfff0);
255 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
256 //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
257 // The task bar can grow in size and can not reduce due to the change
261 ExStyle
= pwnd
->ExStyle
;
262 iconic
= (Style
& WS_MINIMIZE
) != 0;
264 if ((Style
& WS_MAXIMIZE
) || !IntIsWindowVisible(pwnd
)) return;
266 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !iconic
;
269 // Show window contents while dragging the window, get flag from registry data.
271 UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
273 pt
.x
= pti
->ptLast
.x
;
274 pt
.y
= pti
->ptLast
.y
;
276 UserClipCursor( NULL
);
278 TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
279 pwnd
, syscommand
, hittest
, pt
.x
, pt
.y
);
281 if (syscommand
== SC_MOVE
)
283 if (!hittest
) hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
284 if (!hittest
) return;
288 if (!thickframe
) return;
289 if (hittest
&& (syscommand
!= SC_MOUSEMENU
))
291 hittest
+= (HTLEFT
- WMSZ_LEFT
);
295 co_UserSetCapture(UserHMGetHandle(pwnd
));
296 hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
305 /* Get min/max info */
307 co_WinPosGetMinMaxInfo(pwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
308 sizingRect
= pwnd
->rcWindow
;
309 origRect
= sizingRect
;
310 if (Style
& WS_CHILD
)
312 pWndParent
= IntGetParent(pwnd
);
313 IntGetClientRect( pWndParent
, &mouseRect
);
314 IntMapWindowPoints( pWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
315 IntMapWindowPoints( 0, pWndParent
, (LPPOINT
)&sizingRect
, 2 );
316 unmodRect
= sizingRect
;
320 if (!(ExStyle
& WS_EX_TOPMOST
))
322 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
326 RECTL_vSetRect(&mouseRect
, 0, 0, UserGetSystemMetrics(SM_CXSCREEN
), UserGetSystemMetrics(SM_CYSCREEN
));
328 unmodRect
= sizingRect
;
331 if (ON_LEFT_BORDER(hittest
))
333 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
+capturePoint
.x
-sizingRect
.left
);
334 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
+capturePoint
.x
-sizingRect
.left
);
336 else if (ON_RIGHT_BORDER(hittest
))
338 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
+capturePoint
.x
-sizingRect
.right
);
339 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
+capturePoint
.x
-sizingRect
.right
);
341 if (ON_TOP_BORDER(hittest
))
343 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
+capturePoint
.y
-sizingRect
.top
);
344 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
+capturePoint
.y
-sizingRect
.top
);
346 else if (ON_BOTTOM_BORDER(hittest
))
348 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
349 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
352 hdc
= UserGetDCEx( pWndParent
, 0, DCX_CACHE
);
355 DragCursor
= pwnd
->pcls
->spicn
;
358 UserReferenceObject(DragCursor
);
362 HCURSOR CursorHandle
= (HCURSOR
)co_IntSendMessage( UserHMGetHandle(pwnd
), WM_QUERYDRAGICON
, 0, 0 );
365 DragCursor
= UserGetCurIconObject(CursorHandle
);
374 /* repaint the window before moving it around */
375 co_UserRedrawWindow( pwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
377 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
379 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_ENTERSIZEMOVE
, 0, 0 );
381 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, UserHMGetHandle(pwnd
));
383 if (IntGetCapture() != UserHMGetHandle(pwnd
)) co_UserSetCapture( UserHMGetHandle(pwnd
) );
385 pwnd
->head
.pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
391 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) break;
392 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
394 /* Exit on button-up */
395 if (msg
.message
== WM_LBUTTONUP
)
397 // check for snapping if was moved by caption
398 if (hittest
== HTCAPTION
&& thickframe
&& (ExStyle
& WS_EX_MDICHILD
) == 0)
401 BOOL doSideSnap
= FALSE
;
402 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &snapRect
, 0);
405 if (pt
.x
<= snapRect
.left
)
407 snapRect
.right
= (snapRect
.right
- snapRect
.left
) / 2 + snapRect
.left
;
411 if (pt
.x
>= snapRect
.right
-1)
413 snapRect
.left
= (snapRect
.right
- snapRect
.left
) / 2 + snapRect
.left
;
419 co_WinPosSetWindowPos(pwnd
,
423 snapRect
.right
- snapRect
.left
,
424 snapRect
.bottom
- snapRect
.top
,
426 pwnd
->InternalPos
.NormalRect
= origRect
;
430 // maximize if on dragged to top
431 if (pt
.y
<= snapRect
.top
)
433 co_IntSendMessage(UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MAXIMIZE
, 0);
434 pwnd
->InternalPos
.NormalRect
= origRect
;
441 /* Exit on Return or Esc */
442 if (msg
.message
== WM_KEYDOWN
&&
443 (msg
.wParam
== VK_RETURN
|| msg
.wParam
== VK_ESCAPE
))
448 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
450 IntTranslateKbdMessage( &msg
, 0 );
451 IntDispatchMessage( &msg
);
452 continue; /* We are not interested in other messages */
457 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
459 case VK_UP
: pt
.y
-= 8; break;
460 case VK_DOWN
: pt
.y
+= 8; break;
461 case VK_LEFT
: pt
.x
-= 8; break;
462 case VK_RIGHT
: pt
.x
+= 8; break;
465 pt
.x
= max( pt
.x
, mouseRect
.left
);
466 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
467 pt
.y
= max( pt
.y
, mouseRect
.top
);
468 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
470 dx
= pt
.x
- capturePoint
.x
;
471 dy
= pt
.y
- capturePoint
.y
;
478 if ( iconic
) /* ok, no system popup tracking */
480 OldCursor
= UserSetCursor(DragCursor
, FALSE
);
481 UserShowCursor( TRUE
);
483 else if(!DragFullWindows
)
484 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
487 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
490 RECT newRect
= unmodRect
;
492 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
493 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
494 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
495 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
496 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
497 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
501 // Save the new position to the unmodified rectangle. This allows explorer task bar
502 // sizing. Explorer will forces back the position unless a certain amount of sizing
507 /* determine the hit location */
508 if (syscommand
== SC_SIZE
)
510 WPARAM wpSizingHit
= 0;
512 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
513 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
514 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
517 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
521 if (!DragFullWindows
)
522 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
524 { // Moving the whole window now!
526 HRGN hrgnOrig
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
528 if (pwnd
->hrgnClip
!= NULL
)
529 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, pwnd
->hrgnClip
, RGN_AND
);
531 //// This causes the mdi child window to jump up when it is moved.
532 //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
533 co_WinPosSetWindowPos( pwnd
,
537 newRect
.right
- newRect
.left
,
538 newRect
.bottom
- newRect
.top
,
539 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
541 hrgnNew
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
542 if (pwnd
->hrgnClip
!= NULL
)
543 NtGdiCombineRgn(hrgnNew
, hrgnNew
, pwnd
->hrgnClip
, RGN_AND
);
548 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, hrgnNew
, RGN_DIFF
);
554 GreDeleteObject(hrgnOrig
);
559 // Update all the windows after the move or size, including this window.
560 UpdateThreadWindows(UserGetDesktopWindow()->spwndChild
, pti
, hrgnOrig
);
562 if (hrgnOrig
) GreDeleteObject(hrgnOrig
);
563 if (hrgnNew
) GreDeleteObject(hrgnNew
);
566 sizingRect
= newRect
;
571 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
577 if ( moved
) /* restore cursors, show icon title later on */
579 UserShowCursor( FALSE
);
580 OldCursor
= UserSetCursor(OldCursor
, FALSE
);
583 /* It could be that the cursor was already changed while we were proceeding,
584 * so we must unreference whatever cursor was current at the time we restored the old one.
585 * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
587 if (OldCursor
) UserDereferenceObject(OldCursor
);
589 else if ( moved
&& !DragFullWindows
)
590 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
592 UserReleaseDC(NULL
, hdc
, FALSE
);
594 //// This causes the mdi child window to jump up when it is moved.
595 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
597 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
599 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
603 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
605 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
607 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
609 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
611 /* window moved or resized */
614 /* if the moving/resizing isn't canceled call SetWindowPos
615 * with the new position or the new size of the window
617 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
619 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
620 if (!DragFullWindows
|| iconic
)
622 co_WinPosSetWindowPos( pwnd
,
626 sizingRect
.right
- sizingRect
.left
,
627 sizingRect
.bottom
- sizingRect
.top
,
628 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
632 { /* restore previous size/position */
633 if ( DragFullWindows
)
635 co_WinPosSetWindowPos( pwnd
,
639 origRect
.right
- origRect
.left
,
640 origRect
.bottom
- origRect
.top
,
641 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
646 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
650 /* Single click brings up the system menu when iconized */
653 if( Style
& WS_SYSMENU
)
654 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
660 PCURICON_OBJECT FASTCALL
NC_IconForWindow( PWND pWnd
)
662 PCURICON_OBJECT pIcon
= NULL
;
665 hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
, TRUE
);
666 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
, TRUE
);
668 if (!hIcon
&& pWnd
->pcls
->spicnSm
)
669 return pWnd
->pcls
->spicnSm
;
670 if (!hIcon
&& pWnd
->pcls
->spicn
)
671 return pWnd
->pcls
->spicn
;
673 // WARNING: Wine code has this test completely wrong. The following is how
674 // Windows behaves for windows having the WS_EX_DLGMODALFRAME style set:
675 // it does not use the default icon! And it does not check for DS_MODALFRAME.
676 if (!hIcon
&& !(pWnd
->ExStyle
& WS_EX_DLGMODALFRAME
))
678 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
679 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
683 pIcon
= (PCURICON_OBJECT
)UserGetObjectNoErr(gHandleTable
,
691 UserDrawSysMenuButton(PWND pWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
693 PCURICON_OBJECT WindowIcon
;
696 if ((WindowIcon
= NC_IconForWindow(pWnd
)))
698 UserReferenceObject(WindowIcon
);
700 Ret
= UserDrawIconEx(hDC
,
704 UserGetSystemMetrics(SM_CXSMICON
),
705 UserGetSystemMetrics(SM_CYSMICON
),
708 UserDereferenceObject(WindowIcon
);
714 IntIsScrollBarVisible(PWND pWnd
, INT hBar
)
717 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
719 if(!co_IntGetScrollBarInfo(pWnd
, hBar
, &sbi
))
722 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
727 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
728 * wasting precious CPU cycles) every time
729 * - Center the buttons vertically in the rect
732 UserDrawCaptionButton(PWND pWnd
, LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
736 if (!(Style
& WS_SYSMENU
))
745 case DFCS_CAPTIONMIN
:
747 if (ExStyle
& WS_EX_TOOLWINDOW
)
748 return; /* ToolWindows don't have min/max buttons */
750 if (Style
& WS_SYSMENU
)
751 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
753 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
754 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) - 2;
756 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
757 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
761 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
762 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
763 (bDown
? DFCS_PUSHED
: 0) |
764 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
767 case DFCS_CAPTIONMAX
:
769 if (ExStyle
& WS_EX_TOOLWINDOW
)
770 return; /* ToolWindows don't have min/max buttons */
772 if (Style
& WS_SYSMENU
)
773 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
775 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
776 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
780 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
781 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
782 (bDown
? DFCS_PUSHED
: 0) |
783 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
786 case DFCS_CAPTIONCLOSE
:
788 PMENU pSysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
789 UINT MenuState
= IntGetMenuState(pSysMenu
? UserHMGetHandle(pSysMenu
) : NULL
, SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
791 /* A tool window has a smaller Close button */
792 if (ExStyle
& WS_EX_TOOLWINDOW
)
794 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSMSIZE
);
795 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMSIZE
) - 2;
799 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
);
800 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
805 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
806 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
807 ((!(MenuState
& (MF_GRAYED
|MF_DISABLED
)) && !(pWnd
->pcls
->style
& CS_NOCLOSE
)) ? 0 : DFCS_INACTIVE
)));
814 UserDrawCaptionButtonWnd(PWND pWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
819 IntGetWindowRect(pWnd
, &WindowRect
);
821 WindowRect
.right
-= WindowRect
.left
;
822 WindowRect
.bottom
-= WindowRect
.top
;
823 WindowRect
.left
= WindowRect
.top
= 0;
825 UserGetWindowBorders(pWnd
->style
, pWnd
->ExStyle
, &WindowBorder
, FALSE
);
827 RECTL_vInflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
829 UserDrawCaptionButton(pWnd
, &WindowRect
, pWnd
->style
, pWnd
->ExStyle
, hDC
, bDown
, Type
);
833 NC_DrawFrame( HDC hDC
, RECT
*CurrentRect
, BOOL Active
, DWORD Style
, DWORD ExStyle
)
835 /* Firstly the "thick" frame */
836 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
839 (UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
)) *
840 UserGetSystemMetrics(SM_CXBORDER
);
843 (UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
)) *
844 UserGetSystemMetrics(SM_CYBORDER
);
846 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
849 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
850 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
851 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
852 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
854 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
857 /* Now the other bit of the frame */
858 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
860 LONG Width
= UserGetSystemMetrics(SM_CXBORDER
);
861 LONG Height
= UserGetSystemMetrics(SM_CYBORDER
);
863 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(
864 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
865 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
866 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
870 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
871 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
872 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
873 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
875 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
879 VOID
UserDrawCaptionBar(
884 DWORD Style
, ExStyle
;
885 RECT WindowRect
, CurrentRect
, TempRect
;
887 BOOL Gradient
= FALSE
;
888 PCURICON_OBJECT pIcon
= NULL
;
890 if (!(Flags
& DC_NOVISIBLE
) && !IntIsWindowVisible(pWnd
)) return;
892 TRACE("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd
, hDC
, Flags
);
895 ExStyle
= pWnd
->ExStyle
;
897 IntGetWindowRect(pWnd
, &WindowRect
);
899 CurrentRect
.top
= CurrentRect
.left
= 0;
900 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
901 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
903 /* Draw outer edge */
904 if (UserHasWindowEdge(Style
, ExStyle
))
906 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
908 else if (ExStyle
& WS_EX_STATICEDGE
)
911 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
913 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
914 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
915 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
917 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
918 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
919 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
921 RECTL_vInflateRect(&CurrentRect
, -1, -1);
925 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, (Flags
& DC_ACTIVE
), Style
, ExStyle
);
928 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
930 TempRect
= CurrentRect
;
932 Flags
|= DC_TEXT
|DC_BUTTONS
; // Icon will be checked if not already set.
934 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
936 Flags
|= DC_GRADIENT
;
939 if (ExStyle
& WS_EX_TOOLWINDOW
)
941 Flags
|= DC_SMALLCAP
;
942 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
943 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
947 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
948 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
951 if (!(Flags
& DC_ICON
) &&
952 !(Flags
& DC_SMALLCAP
) &&
953 (Style
& WS_SYSMENU
) &&
954 !(ExStyle
& WS_EX_TOOLWINDOW
) )
956 pIcon
= NC_IconForWindow(pWnd
); // Force redraw of caption with icon if DC_ICON not flaged....
958 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, pIcon
? UserHMGetHandle(pIcon
) : NULL
, NULL
, Flags
);
961 if (Style
& WS_SYSMENU
)
963 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
964 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
966 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
967 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
971 if (!(Style
& WS_MINIMIZE
))
973 /* Line under caption */
974 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
976 IntSetDCPenColor( hDC
, IntGetSysColor(((ExStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
977 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
979 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
981 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
983 NtGdiSelectPen(hDC
, PreviousPen
);
987 if (!(Style
& WS_MINIMIZE
))
990 if (pWnd
->state
& WNDS_HASMENU
&& pWnd
->IDMenu
) // Should be pWnd->spmenu
993 if ((menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)))) // FIXME! Use pWnd->spmenu,
995 TempRect
= CurrentRect
;
996 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
997 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
1001 if (ExStyle
& WS_EX_CLIENTEDGE
)
1003 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1009 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1010 the call to GetDCEx implying that it is allowed not to use it either.
1011 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1012 will cause clipRgn to be deleted after ReleaseDC().
1013 Now, how is the "system" supposed to tell what happened?
1017 * - Drawing of WS_BORDER after scrollbars
1018 * - Correct drawing of size-box
1021 NC_DoNCPaint(PWND pWnd
, HDC hDC
, INT Flags
)
1023 DWORD Style
, ExStyle
;
1025 RECT WindowRect
, CurrentRect
, TempRect
;
1026 BOOL Active
= FALSE
;
1028 if (!IntIsWindowVisible(pWnd
) ||
1029 (pWnd
->state
& WNDS_NONCPAINT
&& !(pWnd
->state
& WNDS_FORCEMENUDRAW
)) ||
1030 IntEqualRect(&pWnd
->rcWindow
, &pWnd
->rcClient
) )
1033 Style
= pWnd
->style
;
1035 TRACE("DefWndNCPaint: pWnd %p, hDc %p, Active %s.\n", pWnd
, hDC
, Flags
& DC_ACTIVE
? "TRUE" : "FALSE");
1037 Parent
= IntGetParent(pWnd
);
1038 ExStyle
= pWnd
->ExStyle
;
1040 if (Flags
== -1) // NC paint mode.
1042 if (ExStyle
& WS_EX_MDICHILD
)
1044 Active
= IntIsChildWindow(gpqForeground
->spwndActive
, pWnd
);
1047 Active
= (UserHMGetHandle(pWnd
) == (HWND
)co_IntSendMessage(UserHMGetHandle(Parent
), WM_MDIGETACTIVE
, 0, 0));
1051 Active
= (gpqForeground
== pWnd
->head
.pti
->MessageQueue
);
1053 Flags
= DC_NC
; // Redraw everything!
1059 IntGetWindowRect(pWnd
, &WindowRect
);
1061 CurrentRect
.top
= CurrentRect
.left
= 0;
1062 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
1063 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
1065 /* Draw outer edge */
1066 if (UserHasWindowEdge(pWnd
->style
, pWnd
->ExStyle
))
1068 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1070 else if (pWnd
->ExStyle
& WS_EX_STATICEDGE
)
1073 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
1075 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
1076 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1077 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1079 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
1080 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1081 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1083 RECTL_vInflateRect(&CurrentRect
, -1, -1);
1087 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, Active
? Active
: (Flags
& DC_ACTIVE
), Style
, ExStyle
);
1090 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1093 BOOL Gradient
= FALSE
;
1095 if (Flags
& DC_REDRAWHUNGWND
)
1097 Flags
&= ~DC_REDRAWHUNGWND
;
1098 Flags
|= DC_NOSENDMSG
;
1101 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
1103 Flags
|= DC_GRADIENT
;
1108 if (pWnd
->state
& WNDS_ACTIVEFRAME
)
1112 ERR("Wnd is active and not set active!\n");
1116 TempRect
= CurrentRect
;
1118 if (ExStyle
& WS_EX_TOOLWINDOW
)
1120 Flags
|= DC_SMALLCAP
;
1121 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1122 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1126 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1127 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1130 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, NULL
, NULL
, Flags
);
1133 if (Style
& WS_SYSMENU
)
1135 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
1136 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
1138 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
1139 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
1142 if (!(Style
& WS_MINIMIZE
))
1144 /* Line under caption */
1145 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
1147 IntSetDCPenColor( hDC
, IntGetSysColor(
1148 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
| WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
1149 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
1151 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
1153 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
1155 NtGdiSelectPen(hDC
, PreviousPen
);
1159 if (!(Style
& WS_MINIMIZE
))
1162 if (pWnd
->state
& WNDS_HASMENU
&& pWnd
->IDMenu
) // Should be pWnd->spmenu
1164 if (!(Flags
& DC_NOSENDMSG
))
1167 // Fix crash in test_menu_locked_by_window, should use pWnd->spmenu....
1168 if ((menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)))) // FIXME! Use pWnd->spmenu,
1170 TempRect
= CurrentRect
;
1171 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
1172 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
1177 if (ExStyle
& WS_EX_CLIENTEDGE
)
1179 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1182 /* Draw the scrollbars */
1183 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1184 IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1186 RECT ParentClientRect
;
1188 TempRect
= CurrentRect
;
1190 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
1191 TempRect
.right
= TempRect
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
);
1193 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXVSCROLL
);
1195 TempRect
.top
= TempRect
.bottom
- UserGetSystemMetrics(SM_CYHSCROLL
);
1197 FillRect(hDC
, &TempRect
, IntGetSysColorBrush(COLOR_BTNFACE
));
1201 IntGetClientRect(Parent
, &ParentClientRect
);
1203 if (HASSIZEGRIP(Style
, ExStyle
, Parent
->style
, WindowRect
, ParentClientRect
))
1205 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
1209 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1210 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1214 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
))
1216 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1218 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1220 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1224 return 0; // For WM_NCPAINT message, return 0.
1227 LRESULT
NC_HandleNCCalcSize( PWND Wnd
, WPARAM wparam
, RECTL
*Rect
, BOOL Suspended
)
1232 LONG Style
= Wnd
->style
;
1233 LONG exStyle
= Wnd
->ExStyle
;
1241 Wnd
->state
&= ~WNDS_HASCAPTION
;
1245 if (Wnd
->pcls
->style
& CS_VREDRAW
)
1247 Result
|= WVR_VREDRAW
;
1249 if (Wnd
->pcls
->style
& CS_HREDRAW
)
1251 Result
|= WVR_HREDRAW
;
1253 Result
|= WVR_VALIDRECTS
;
1256 if (!(Wnd
->style
& WS_MINIMIZE
))
1258 if (UserHasWindowEdge(Wnd
->style
, Wnd
->ExStyle
))
1260 UserGetWindowBorders(Wnd
->style
, Wnd
->ExStyle
, &WindowBorders
, FALSE
);
1261 RECTL_vInflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1263 else if ((Wnd
->ExStyle
& WS_EX_STATICEDGE
) || (Wnd
->style
& WS_BORDER
))
1265 RECTL_vInflateRect(Rect
, -1, -1);
1268 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
1270 Wnd
->state
|= WNDS_HASCAPTION
;
1272 if (Wnd
->ExStyle
& WS_EX_TOOLWINDOW
)
1273 Rect
->top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1275 Rect
->top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1278 if (HAS_MENU(Wnd
, Style
))
1280 HDC hDC
= UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
1282 Wnd
->state
|= WNDS_HASMENU
;
1286 RECT CliRect
= *Rect
;
1287 CliRect
.bottom
-= OrigRect
.top
;
1288 CliRect
.right
-= OrigRect
.left
;
1289 CliRect
.left
-= OrigRect
.left
;
1290 CliRect
.top
-= OrigRect
.top
;
1291 if (!Suspended
) Rect
->top
+= MENU_DrawMenuBar(hDC
, &CliRect
, Wnd
, TRUE
);
1292 UserReleaseDC(Wnd
, hDC
, FALSE
);
1296 if (Wnd
->ExStyle
& WS_EX_CLIENTEDGE
)
1298 RECTL_vInflateRect(Rect
, -2 * UserGetSystemMetrics(SM_CXBORDER
), -2 * UserGetSystemMetrics(SM_CYBORDER
));
1301 if (Style
& WS_VSCROLL
)
1303 if (Rect
->right
- Rect
->left
>= UserGetSystemMetrics(SM_CXVSCROLL
))
1305 Wnd
->state
|= WNDS_HASVERTICALSCROOLLBAR
;
1307 /* rectangle is in screen coords when wparam is false */
1308 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
1310 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1311 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1313 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1317 if (Style
& WS_HSCROLL
)
1319 if( Rect
->bottom
- Rect
->top
> UserGetSystemMetrics(SM_CYHSCROLL
))
1321 Wnd
->state
|= WNDS_HASHORIZONTALSCROLLBAR
;
1323 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1327 if (Rect
->top
> Rect
->bottom
)
1328 Rect
->bottom
= Rect
->top
;
1330 if (Rect
->left
> Rect
->right
)
1331 Rect
->right
= Rect
->left
;
1335 Rect
->right
= Rect
->left
;
1336 Rect
->bottom
= Rect
->top
;
1343 INT
NC_DoNCActive(PWND Wnd
)
1347 if ( IntGetSysColor(COLOR_CAPTIONTEXT
) != IntGetSysColor(COLOR_INACTIVECAPTIONTEXT
) ||
1348 IntGetSysColor(COLOR_ACTIVECAPTION
) != IntGetSysColor(COLOR_INACTIVECAPTION
) )
1351 if (!(Wnd
->style
& WS_MINIMIZED
) && UserHasThickFrameStyle(Wnd
->style
, Wnd
->ExStyle
))
1353 //if (IntGetSysColor(COLOR_ACTIVEBORDER) != IntGetSysColor(COLOR_INACTIVEBORDER)) // Why are these the same?
1361 LRESULT
NC_HandleNCActivate( PWND Wnd
, WPARAM wParam
, LPARAM lParam
)
1364 /* Lotus Notes draws menu descriptions in the caption of its main
1365 * window. When it wants to restore original "system" view, it just
1366 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1367 * attempt to minimize redrawings lead to a not restored caption.
1369 if (wParam
& DC_ACTIVE
)
1371 Wnd
->state
|= WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
;
1372 wParam
= DC_CAPTION
|DC_ACTIVE
;
1376 Wnd
->state
&= ~WNDS_ACTIVEFRAME
;
1377 wParam
= DC_CAPTION
;
1380 if ((Wnd
->state
& WNDS_NONCPAINT
) || !(Wnd
->style
& WS_VISIBLE
))
1383 /* This isn't documented but is reproducible in at least XP SP2 and
1384 * Outlook 2007 depends on it
1387 // If this parameter is set to -1, DefWindowProc does not repaint the
1388 // nonclient area to reflect the state change.
1389 if ( lParam
!= -1 &&
1390 ( Flags
= NC_DoNCActive(Wnd
)) != 0 )
1393 HRGN hRgnTemp
= NULL
, hRgn
= (HRGN
)lParam
;
1395 if (GreIsHandleValid(hRgn
))
1397 hRgnTemp
= NtGdiCreateRectRgn(0, 0, 0, 0);
1398 if (NtGdiCombineRgn(hRgnTemp
, hRgn
, 0, RGN_COPY
) == ERROR
)
1400 GreDeleteObject(hRgnTemp
);
1405 if ((hDC
= UserGetDCEx(Wnd
, hRgnTemp
, DCX_WINDOW
|DCX_USESTYLE
)))
1407 NC_DoNCPaint(Wnd
, hDC
, wParam
| Flags
); // Redraw MENUs.
1408 UserReleaseDC(Wnd
, hDC
, FALSE
);
1411 GreDeleteObject(hRgnTemp
);
1418 NC_DoButton(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1422 BOOL Pressed
= TRUE
, OldState
;
1429 Style
= pWnd
->style
;
1433 SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1434 MenuState
= IntGetMenuState(SysMenu
? UserHMGetHandle(SysMenu
) : NULL
, SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
1435 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (pWnd
->style
& CS_NOCLOSE
))
1437 ButtonType
= DFCS_CAPTIONCLOSE
;
1441 if (!(Style
& WS_MINIMIZEBOX
))
1443 ButtonType
= DFCS_CAPTIONMIN
;
1444 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
1447 if (!(Style
& WS_MAXIMIZEBOX
))
1449 ButtonType
= DFCS_CAPTIONMAX
;
1450 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
1459 * FIXME: Not sure where to do this, but we must flush the pending
1460 * window updates when someone clicks on the close button and at
1461 * the same time the window is overlapped with another one. This
1462 * looks like a good place for now...
1464 co_IntUpdateWindows(pWnd
, RDW_ALLCHILDREN
, FALSE
);
1466 WindowDC
= UserGetWindowDC(pWnd
);
1467 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, TRUE
, ButtonType
);
1469 co_UserSetCapture(UserHMGetHandle(pWnd
));
1473 if (!co_IntGetPeekMessage(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1474 if (IntCallMsgFilter( &Msg
, MSGF_MAX
)) continue;
1476 if (Msg
.message
== WM_LBUTTONUP
)
1479 if (Msg
.message
!= WM_MOUSEMOVE
)
1483 Pressed
= (GetNCHitEx(pWnd
, Msg
.pt
) == wParam
);
1484 if (Pressed
!= OldState
)
1485 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, Pressed
, ButtonType
);
1489 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, FALSE
, ButtonType
);
1490 IntReleaseCapture();
1491 UserReleaseDC(pWnd
, WindowDC
, FALSE
);
1493 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SCMsg
, SCMsg
== SC_CLOSE
? lParam
: MAKELONG(Msg
.pt
.x
,Msg
.pt
.y
));
1498 NC_HandleNCLButtonDown(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1504 PWND TopWnd
= pWnd
, parent
;
1507 if ((TopWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1509 parent
= UserGetAncestor( TopWnd
, GA_PARENT
);
1510 if (!parent
|| UserIsDesktopWindow(parent
)) break;
1514 if ( co_IntSetForegroundWindowMouse(TopWnd
) ||
1515 //NtUserCallHwndLock(hTopWnd, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE) ||
1516 UserGetActiveWindow() == UserHMGetHandle(TopWnd
))
1518 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1524 LONG style
= pWnd
->style
;
1525 if (style
& WS_SYSMENU
)
1527 if(!(style
& WS_MINIMIZE
) )
1530 HDC hDC
= UserGetWindowDC(pWnd
);
1531 NC_GetInsideRect(pWnd
, &rect
);
1532 UserDrawSysMenuButton(pWnd
, hDC
, &rect
, TRUE
);
1533 UserReleaseDC( pWnd
, hDC
, FALSE
);
1535 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1541 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
1546 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1551 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1558 NC_DoButton(pWnd
, wParam
, lParam
);
1571 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1572 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1574 /* But that is not what WinNT does. Instead it sends this. This
1575 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1576 * SC_MOUSEMENU into wParam.
1578 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1589 NC_HandleNCLButtonDblClk(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1593 Style
= pWnd
->style
;
1598 /* Maximize/Restore the window */
1599 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1601 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1607 PMENU SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1608 UINT state
= IntGetMenuState(SysMenu
? UserHMGetHandle(SysMenu
) : NULL
, SC_CLOSE
, MF_BYCOMMAND
);
1610 /* If the close item of the sysmenu is disabled or not present do nothing */
1611 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1614 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1620 RECT sizingRect
= pWnd
->rcWindow
, mouseRect
;
1622 if (pWnd
->ExStyle
& WS_EX_MDICHILD
)
1625 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
1627 co_WinPosSetWindowPos(pWnd
,
1631 sizingRect
.right
- sizingRect
.left
,
1632 mouseRect
.bottom
- mouseRect
.top
,
1637 return NC_HandleNCLButtonDown(pWnd
, wParam
, lParam
);
1642 /***********************************************************************
1643 * NC_HandleNCRButtonDown
1645 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1647 LRESULT
NC_HandleNCRButtonDown( PWND pwnd
, WPARAM wParam
, LPARAM lParam
)
1650 INT hittest
= wParam
;
1656 if (!IntGetSystemMenu( pwnd
, FALSE
)) break;
1658 co_UserSetCapture( UserHMGetHandle(pwnd
) );
1661 if (!co_IntGetPeekMessage(&msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1662 if (IntCallMsgFilter( &msg
, MSGF_MAX
)) continue;
1663 if (msg
.message
== WM_RBUTTONUP
)
1665 hittest
= GetNCHitEx( pwnd
, msg
.pt
);
1668 if (UserHMGetHandle(pwnd
) != IntGetCapture()) return 0;
1670 IntReleaseCapture();
1671 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
|| hittest
== HTHSCROLL
|| hittest
== HTVSCROLL
)
1673 TRACE("Msg pt %x and Msg.lParam %x and lParam %x\n",MAKELONG(msg
.pt
.x
,msg
.pt
.y
),msg
.lParam
,lParam
);
1674 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_CONTEXTMENU
, (WPARAM
)UserHMGetHandle(pwnd
), MAKELONG(msg
.pt
.x
,msg
.pt
.y
));
1682 #if 0 // Old version, kept there for reference, which is also used
1683 // almost unmodified in uxtheme.dll (in nonclient.c)
1686 * - Check the scrollbar handling
1689 DefWndNCHitTest(HWND hWnd
, POINT Point
)
1691 RECT WindowRect
, ClientRect
, OrigWndRect
;
1694 DWORD Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1695 DWORD ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
1697 GetWindowRect(hWnd
, &WindowRect
);
1698 if (!PtInRect(&WindowRect
, Point
))
1702 OrigWndRect
= WindowRect
;
1704 if (UserHasWindowEdge(Style
, ExStyle
))
1708 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
1709 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1710 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
1711 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
1712 if (!PtInRect(&WindowRect
, Point
))
1716 ThickFrame
= (Style
& WS_THICKFRAME
);
1717 if (Point
.y
< WindowRect
.top
)
1719 if(Style
& WS_MINIMIZE
)
1723 if (Point
.x
< (WindowRect
.left
+ XSize
))
1725 if (Point
.x
>= (WindowRect
.right
- XSize
))
1729 if (Point
.y
>= WindowRect
.bottom
)
1731 if(Style
& WS_MINIMIZE
)
1735 if (Point
.x
< (WindowRect
.left
+ XSize
))
1736 return HTBOTTOMLEFT
;
1737 if (Point
.x
>= (WindowRect
.right
- XSize
))
1738 return HTBOTTOMRIGHT
;
1741 if (Point
.x
< WindowRect
.left
)
1743 if(Style
& WS_MINIMIZE
)
1747 if (Point
.y
< (WindowRect
.top
+ YSize
))
1749 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1750 return HTBOTTOMLEFT
;
1753 if (Point
.x
>= WindowRect
.right
)
1755 if(Style
& WS_MINIMIZE
)
1759 if (Point
.y
< (WindowRect
.top
+ YSize
))
1761 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1762 return HTBOTTOMRIGHT
;
1769 if (ExStyle
& WS_EX_STATICEDGE
)
1770 InflateRect(&WindowRect
,
1771 -GetSystemMetrics(SM_CXBORDER
),
1772 -GetSystemMetrics(SM_CYBORDER
));
1773 if (!PtInRect(&WindowRect
, Point
))
1777 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1779 if (ExStyle
& WS_EX_TOOLWINDOW
)
1780 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1782 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1783 if (!PtInRect(&WindowRect
, Point
))
1785 if (Style
& WS_SYSMENU
)
1787 if (ExStyle
& WS_EX_TOOLWINDOW
)
1789 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
1793 // if(!(ExStyle & WS_EX_DLGMODALFRAME))
1794 // FIXME: The real test should check whether there is
1795 // an icon for the system window, and if so, do the
1796 // rect.left increase.
1797 // See dll/win32/uxtheme/nonclient.c!DefWndNCHitTest
1798 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
1800 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
1801 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1804 if (Point
.x
< WindowRect
.left
)
1806 if (WindowRect
.right
<= Point
.x
)
1808 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
1809 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1810 if (Point
.x
>= WindowRect
.right
)
1812 if (Style
& WS_MINIMIZEBOX
)
1813 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1814 if (Point
.x
>= WindowRect
.right
)
1820 if(!(Style
& WS_MINIMIZE
))
1822 ClientPoint
= Point
;
1823 ScreenToClient(hWnd
, &ClientPoint
);
1824 GetClientRect(hWnd
, &ClientRect
);
1826 if (PtInRect(&ClientRect
, ClientPoint
))
1831 if (GetMenu(hWnd
) && !(Style
& WS_CHILD
))
1833 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
1837 if (ExStyle
& WS_EX_CLIENTEDGE
)
1839 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
1840 -2 * GetSystemMetrics(SM_CYBORDER
));
1843 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1844 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
1846 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
1847 HWND Parent
= GetParent(hWnd
);
1849 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
1850 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1851 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1853 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1854 if (PtInRect(&TempRect
, Point
))
1857 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1858 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1859 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
1861 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
1862 if (PtInRect(&TempRect2
, Point
))
1865 TempRect
.top
= TempRect2
.top
;
1866 TempRect
.bottom
= TempRect2
.bottom
;
1868 GetClientRect(Parent
, &ParentRect
);
1869 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
1870 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
1872 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1873 return HTBOTTOMLEFT
;
1875 return HTBOTTOMRIGHT
;
1880 if (Style
& WS_VSCROLL
)
1882 RECT TempRect
= WindowRect
;
1884 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1885 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1887 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1888 if (PtInRect(&TempRect
, Point
))
1891 if (Style
& WS_HSCROLL
)
1893 RECT TempRect
= WindowRect
;
1894 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1895 if (PtInRect(&TempRect
, Point
))
1906 GetNCHitEx(PWND pWnd
, POINT pt
)
1908 RECT rcWindow
, rcClient
;
1909 DWORD Style
, ExStyle
;
1911 if (!pWnd
) return HTNOWHERE
;
1913 if (UserIsDesktopWindow(pWnd
))
1915 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
1916 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1917 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1918 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1919 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1923 rcClient
= pWnd
->rcClient
;
1924 rcWindow
= pWnd
->rcWindow
;
1927 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
1929 Style
= pWnd
->style
;
1930 ExStyle
= pWnd
->ExStyle
;
1932 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
1934 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
1937 if (HAS_THICKFRAME( Style
, ExStyle
))
1939 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1940 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
1942 /* Check top sizing border */
1943 if (pt
.y
< rcWindow
.top
)
1945 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
1946 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
1949 /* Check bottom sizing border */
1950 if (pt
.y
>= rcWindow
.bottom
)
1952 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
1953 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
1956 /* Check left sizing border */
1957 if (pt
.x
< rcWindow
.left
)
1959 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
1960 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
1963 /* Check right sizing border */
1964 if (pt
.x
>= rcWindow
.right
)
1966 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
1967 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
1972 else /* No thick frame */
1974 if (HAS_DLGFRAME( Style
, ExStyle
))
1975 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1976 else if (HAS_THINFRAME( Style
, ExStyle
))
1977 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1978 else if (HAS_CLIENTFRAME( Style
, ExStyle
))
1979 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1980 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1985 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1987 if (ExStyle
& WS_EX_TOOLWINDOW
)
1988 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1990 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1991 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1993 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1994 if (ExStyle
& WS_EX_LAYOUTRTL
)
1996 /* Check system menu */
1997 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1999 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
2000 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
2003 /* Check close button */
2004 if (Style
& WS_SYSMENU
)
2006 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
2007 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
2010 /* Check maximize box */
2011 /* In Win95 there is automatically a Maximize button when there is a minimize one */
2012 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2014 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
2015 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
2018 /* Check minimize box */
2019 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2021 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
2022 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
2027 /* Check system menu */
2028 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
2030 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
2031 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
2034 /* Check close button */
2035 if (Style
& WS_SYSMENU
)
2037 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
2038 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
2041 /* Check maximize box */
2042 /* In Win95 there is automatically a Maximize button when there is a minimize one */
2043 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2045 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2046 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
2049 /* Check minimize box */
2050 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2052 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2053 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
2060 /* Check menu bar */
2062 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
2063 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
2066 /* Check vertical scroll bar */
2068 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
2069 if (Style
& WS_VSCROLL
)
2071 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
2072 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
2074 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
2075 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
2078 /* Check horizontal scroll bar */
2080 if (Style
& WS_HSCROLL
)
2082 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
2083 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
2085 /* Check size box */
2086 if ((Style
& WS_VSCROLL
) &&
2087 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
2088 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
2094 /* Has to return HTNOWHERE if nothing was found
2095 Could happen when a window has a customized non client area */