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))
36 UserDrawWindowFrame(HDC hdc
,
41 HBRUSH hbrush
= NtGdiSelectBrush( hdc
, gpsi
->hbrGray
);
42 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
, rect
->right
- rect
->left
- width
, height
, PATINVERT
);
43 NtGdiPatBlt( hdc
, rect
->left
, rect
->top
+ height
, width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
44 NtGdiPatBlt( hdc
, rect
->left
+ width
, rect
->bottom
- 1, rect
->right
- rect
->left
- width
, -(LONG
)height
, PATINVERT
);
45 NtGdiPatBlt( hdc
, rect
->right
- 1, rect
->top
, -(LONG
)width
, rect
->bottom
- rect
->top
- height
, PATINVERT
);
46 NtGdiSelectBrush( hdc
, hbrush
);
50 UserDrawMovingFrame(HDC hdc
,
54 if (thickframe
) UserDrawWindowFrame(hdc
, rect
, UserGetSystemMetrics(SM_CXFRAME
), UserGetSystemMetrics(SM_CYFRAME
));
55 else UserDrawWindowFrame(hdc
, rect
, 1, 1);
58 /***********************************************************************
61 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
62 * but without the borders (if any).
65 NC_GetInsideRect(PWND Wnd
, RECT
*rect
)
71 ExStyle
= Wnd
->ExStyle
;
73 rect
->top
= rect
->left
= 0;
74 rect
->right
= Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
;
75 rect
->bottom
= Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
;
77 if (Style
& WS_ICONIC
) return;
79 /* Remove frame from rectangle */
80 if (UserHasThickFrameStyle(Style
, ExStyle
))
82 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
));
86 if (UserHasDlgFrameStyle(Style
, ExStyle
))
88 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
89 /* FIXME: this isn't in NC_AdjustRect? why not? */
90 if (ExStyle
& WS_EX_DLGMODALFRAME
)
91 RECTL_vInflateRect( rect
, -1, 0 );
95 if (UserHasThinFrameStyle(Style
, ExStyle
))
97 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
101 /* We have additional border information if the window
102 * is a child (but not an MDI child) */
103 if ((Style
& WS_CHILD
) && !(ExStyle
& WS_EX_MDICHILD
))
105 if (ExStyle
& WS_EX_CLIENTEDGE
)
106 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
107 if (ExStyle
& WS_EX_STATICEDGE
)
108 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
113 DefWndStartSizeMove(PWND Wnd
, WPARAM wParam
, POINT
*capturePoint
)
119 ULONG Style
= Wnd
->style
;
120 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
122 rectWindow
= Wnd
->rcWindow
;
124 if ((wParam
& 0xfff0) == SC_MOVE
)
126 /* Move pointer at the center of the caption */
127 RECT rect
= rectWindow
;
128 /* Note: to be exactly centered we should take the different types
129 * of border into account, but it shouldn't make more than a few pixels
130 * of difference so let's not bother with that */
131 if (Style
& WS_SYSMENU
)
132 rect
.left
+= UserGetSystemMetrics(SM_CXSIZE
) + 1;
133 if (Style
& WS_MINIMIZEBOX
)
134 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
135 if (Style
& WS_MAXIMIZEBOX
)
136 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
137 pt
.x
= (rect
.right
+ rect
.left
) / 2;
138 pt
.y
= rect
.top
+ UserGetSystemMetrics(SM_CYSIZE
)/2;
147 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) return 0;
148 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
153 //// Clamp the mouse position to the window rectangle when starting a window resize.
154 pt
.x
= min( max( msg
.pt
.x
, rectWindow
.left
), rectWindow
.right
- 1 );
155 pt
.y
= min( max( msg
.pt
.y
, rectWindow
.top
), rectWindow
.bottom
- 1 );
156 hittest
= GetNCHitEx(Wnd
, pt
);
157 if ((hittest
< HTLEFT
) || (hittest
> HTBOTTOMRIGHT
)) hittest
= 0;
168 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
169 pt
.y
= rectWindow
.top
+ UserGetSystemMetrics(SM_CYFRAME
) / 2;
173 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
174 pt
.y
= rectWindow
.bottom
- UserGetSystemMetrics(SM_CYFRAME
) / 2;
178 pt
.x
= rectWindow
.left
+ UserGetSystemMetrics(SM_CXFRAME
) / 2;
179 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
183 pt
.x
= rectWindow
.right
- UserGetSystemMetrics(SM_CXFRAME
) / 2;
184 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
191 IntTranslateKbdMessage( &msg
, 0 );
192 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
193 IntDispatchMessage( &msg
);
194 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
200 UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
201 co_IntSendMessage(UserHMGetHandle(Wnd
), WM_SETCURSOR
, (WPARAM
)UserHMGetHandle(Wnd
), MAKELONG(hittest
, WM_MOUSEMOVE
));
206 // System Command Size and Move
208 // Perform SC_MOVE and SC_SIZE commands.
211 DefWndDoSizeMove(PWND pwnd
, WORD wParam
)
214 RECT sizingRect
, mouseRect
, origRect
, unmodRect
;
216 LONG hittest
= (LONG
)(wParam
& 0x0f);
217 PCURICON_OBJECT DragCursor
= NULL
, OldCursor
= NULL
;
218 POINT minTrack
, maxTrack
;
219 POINT capturePoint
, pt
;
220 ULONG Style
, ExStyle
;
224 BOOL DragFullWindows
= FALSE
;
225 PWND pWndParent
= NULL
;
226 WPARAM syscommand
= (wParam
& 0xfff0);
227 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
228 //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
229 // The task bar can grow in size and can not reduce due to the change
233 ExStyle
= pwnd
->ExStyle
;
234 iconic
= (Style
& WS_MINIMIZE
) != 0;
236 if ((Style
& WS_MAXIMIZE
) || !IntIsWindowVisible(pwnd
)) return;
238 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !iconic
;
241 // Show window contents while dragging the window, get flag from registry data.
243 UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
245 pt
.x
= pti
->ptLast
.x
;
246 pt
.y
= pti
->ptLast
.y
;
248 UserClipCursor( NULL
);
250 TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
251 pwnd
, syscommand
, hittest
, pt
.x
, pt
.y
);
253 if (syscommand
== SC_MOVE
)
255 if (!hittest
) hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
256 if (!hittest
) return;
260 if (!thickframe
) return;
261 if (hittest
&& (syscommand
!= SC_MOUSEMENU
))
263 hittest
+= (HTLEFT
- WMSZ_LEFT
);
267 co_UserSetCapture(UserHMGetHandle(pwnd
));
268 hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
277 /* Get min/max info */
279 co_WinPosGetMinMaxInfo(pwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
280 sizingRect
= pwnd
->rcWindow
;
281 origRect
= sizingRect
;
282 if (Style
& WS_CHILD
)
284 pWndParent
= IntGetParent(pwnd
);
285 IntGetClientRect( pWndParent
, &mouseRect
);
286 IntMapWindowPoints( pWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
287 IntMapWindowPoints( 0, pWndParent
, (LPPOINT
)&sizingRect
, 2 );
288 unmodRect
= sizingRect
;
292 if (!(ExStyle
& WS_EX_TOPMOST
))
294 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
298 RECTL_vSetRect(&mouseRect
, 0, 0, UserGetSystemMetrics(SM_CXSCREEN
), UserGetSystemMetrics(SM_CYSCREEN
));
300 unmodRect
= sizingRect
;
303 if (ON_LEFT_BORDER(hittest
))
305 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
+capturePoint
.x
-sizingRect
.left
);
306 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
+capturePoint
.x
-sizingRect
.left
);
308 else if (ON_RIGHT_BORDER(hittest
))
310 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
+capturePoint
.x
-sizingRect
.right
);
311 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
+capturePoint
.x
-sizingRect
.right
);
313 if (ON_TOP_BORDER(hittest
))
315 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
+capturePoint
.y
-sizingRect
.top
);
316 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
+capturePoint
.y
-sizingRect
.top
);
318 else if (ON_BOTTOM_BORDER(hittest
))
320 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
321 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
324 hdc
= UserGetDCEx( pWndParent
, 0, DCX_CACHE
);
327 DragCursor
= pwnd
->pcls
->spicn
;
330 UserReferenceObject(DragCursor
);
334 HCURSOR CursorHandle
= (HCURSOR
)co_IntSendMessage( UserHMGetHandle(pwnd
), WM_QUERYDRAGICON
, 0, 0 );
337 DragCursor
= UserGetCurIconObject(CursorHandle
);
346 /* repaint the window before moving it around */
347 co_UserRedrawWindow( pwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
349 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
351 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_ENTERSIZEMOVE
, 0, 0 );
353 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, UserHMGetHandle(pwnd
));
355 if (IntGetCapture() != UserHMGetHandle(pwnd
)) co_UserSetCapture( UserHMGetHandle(pwnd
) );
357 pwnd
->head
.pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
363 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) break;
364 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
366 /* Exit on button-up, Return, or Esc */
367 if ((msg
.message
== WM_LBUTTONUP
) ||
368 ((msg
.message
== WM_KEYDOWN
) &&
369 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
371 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
373 IntTranslateKbdMessage( &msg
, 0 );
374 IntDispatchMessage( &msg
);
375 continue; /* We are not interested in other messages */
380 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
382 case VK_UP
: pt
.y
-= 8; break;
383 case VK_DOWN
: pt
.y
+= 8; break;
384 case VK_LEFT
: pt
.x
-= 8; break;
385 case VK_RIGHT
: pt
.x
+= 8; break;
388 pt
.x
= max( pt
.x
, mouseRect
.left
);
389 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
390 pt
.y
= max( pt
.y
, mouseRect
.top
);
391 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
393 dx
= pt
.x
- capturePoint
.x
;
394 dy
= pt
.y
- capturePoint
.y
;
401 if ( iconic
) /* ok, no system popup tracking */
403 OldCursor
= UserSetCursor(DragCursor
, FALSE
);
404 UserShowCursor( TRUE
);
406 else if(!DragFullWindows
)
407 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
410 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
413 RECT newRect
= unmodRect
;
415 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
416 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
417 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
418 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
419 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
420 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
424 // Save the new position to the unmodified rectangle. This allows explorer task bar
425 // sizing. Explorer will forces back the position unless a certain amount of sizing
430 /* determine the hit location */
431 if (syscommand
== SC_SIZE
)
433 WPARAM wpSizingHit
= 0;
435 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
436 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
437 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
440 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
444 if (!DragFullWindows
)
445 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
447 { // Moving the whole window now!
449 //// This causes the mdi child window to jump up when it is moved.
450 //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
451 co_WinPosSetWindowPos( pwnd
,
455 newRect
.right
- newRect
.left
,
456 newRect
.bottom
- newRect
.top
,
457 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
459 // Update all the windows after the move or size, including this window.
460 for ( pwndTemp
= pwnd
->head
.rpdesk
->pDeskInfo
->spwnd
->spwndChild
;
462 pwndTemp
= pwndTemp
->spwndNext
)
465 // Only the windows that overlap will be redrawn.
466 if (RECTL_bIntersectRect( &rect
, &pwnd
->rcWindow
, &pwndTemp
->rcWindow
))
468 co_UserRedrawWindow( pwndTemp
, NULL
, NULL
, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
473 sizingRect
= newRect
;
478 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
484 if ( moved
) /* restore cursors, show icon title later on */
486 UserShowCursor( FALSE
);
487 OldCursor
= UserSetCursor(OldCursor
, FALSE
);
490 /* It could be that the cursor was already changed while we were proceeding,
491 * so we must unreference whatever cursor was current at the time we restored the old one.
492 * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
494 if (OldCursor
) UserDereferenceObject(OldCursor
);
496 else if ( moved
&& !DragFullWindows
)
497 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
499 UserReleaseDC(NULL
, hdc
, FALSE
);
501 //// This causes the mdi child window to jump up when it is moved.
502 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
504 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
506 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
510 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
512 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
514 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
516 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
518 /* window moved or resized */
521 /* if the moving/resizing isn't canceled call SetWindowPos
522 * with the new position or the new size of the window
524 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
526 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
527 if (!DragFullWindows
|| iconic
)
529 co_WinPosSetWindowPos( pwnd
,
533 sizingRect
.right
- sizingRect
.left
,
534 sizingRect
.bottom
- sizingRect
.top
,
535 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
539 { /* restore previous size/position */
540 if ( DragFullWindows
)
542 co_WinPosSetWindowPos( pwnd
,
546 origRect
.right
- origRect
.left
,
547 origRect
.bottom
- origRect
.top
,
548 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
553 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
557 /* Single click brings up the system menu when iconized */
560 if( Style
& WS_SYSMENU
)
561 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
567 PCURICON_OBJECT FASTCALL
NC_IconForWindow( PWND pWnd
)
569 PCURICON_OBJECT pIcon
= NULL
;
572 //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
573 //FIXME: Hence we must return a pointer with no reference count.
574 //FIXME: This is bad and we should feel bad.
575 //FIXME: Stop whining over wine code.
577 hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
);
578 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
);
580 if (!hIcon
&& pWnd
->pcls
->spicnSm
)
581 return pWnd
->pcls
->spicnSm
;
582 if (!hIcon
&& pWnd
->pcls
->spicn
)
583 return pWnd
->pcls
->spicn
;
585 if (!hIcon
&& (pWnd
->style
& DS_MODALFRAME
))
587 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
588 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
592 pIcon
= UserGetCurIconObject(hIcon
);
595 UserDereferenceObject(pIcon
);
602 GetNCHitEx(PWND pWnd
, POINT pt
)
604 RECT rcWindow
, rcClient
;
605 DWORD Style
, ExStyle
;
607 if (!pWnd
) return HTNOWHERE
;
609 if (pWnd
== UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
611 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
612 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
613 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
614 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
615 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
619 rcClient
= pWnd
->rcClient
;
620 rcWindow
= pWnd
->rcWindow
;
623 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
626 ExStyle
= pWnd
->ExStyle
;
628 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
630 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
633 if (HAS_THICKFRAME( Style
, ExStyle
))
635 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
636 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
638 /* Check top sizing border */
639 if (pt
.y
< rcWindow
.top
)
641 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
642 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
645 /* Check bottom sizing border */
646 if (pt
.y
>= rcWindow
.bottom
)
648 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
649 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
652 /* Check left sizing border */
653 if (pt
.x
< rcWindow
.left
)
655 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
656 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
659 /* Check right sizing border */
660 if (pt
.x
>= rcWindow
.right
)
662 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
663 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
668 else /* No thick frame */
670 if (HAS_DLGFRAME( Style
, ExStyle
))
671 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
672 else if (HAS_THINFRAME( Style
, ExStyle
))
673 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
674 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
679 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
681 if (ExStyle
& WS_EX_TOOLWINDOW
)
682 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
684 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
685 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
687 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
688 if (ExStyle
& WS_EX_LAYOUTRTL
)
690 /* Check system menu */
691 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
693 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
694 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
697 /* Check close button */
698 if (Style
& WS_SYSMENU
)
700 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
701 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
704 /* Check maximize box */
705 /* In Win95 there is automatically a Maximize button when there is a minimize one */
706 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
708 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
709 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
712 /* Check minimize box */
713 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
715 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
716 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
721 /* Check system menu */
722 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
724 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
725 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
728 /* Check close button */
729 if (Style
& WS_SYSMENU
)
731 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
732 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
735 /* Check maximize box */
736 /* In Win95 there is automatically a Maximize button when there is a minimize one */
737 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
739 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
740 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
743 /* Check minimize box */
744 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
746 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
747 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
756 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
757 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
760 /* Check vertical scroll bar */
762 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
763 if (Style
& WS_VSCROLL
)
765 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
766 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
768 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
769 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
772 /* Check horizontal scroll bar */
774 if (Style
& WS_HSCROLL
)
776 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
777 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
780 if ((Style
& WS_VSCROLL
) &&
781 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
782 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
788 /* Has to return HTNOWHERE if nothing was found
789 Could happen when a window has a customized non client area */