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, Return, or Esc */
395 if ((msg
.message
== WM_LBUTTONUP
) ||
396 ((msg
.message
== WM_KEYDOWN
) &&
397 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
399 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
401 IntTranslateKbdMessage( &msg
, 0 );
402 IntDispatchMessage( &msg
);
403 continue; /* We are not interested in other messages */
408 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
410 case VK_UP
: pt
.y
-= 8; break;
411 case VK_DOWN
: pt
.y
+= 8; break;
412 case VK_LEFT
: pt
.x
-= 8; break;
413 case VK_RIGHT
: pt
.x
+= 8; break;
416 pt
.x
= max( pt
.x
, mouseRect
.left
);
417 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
418 pt
.y
= max( pt
.y
, mouseRect
.top
);
419 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
421 dx
= pt
.x
- capturePoint
.x
;
422 dy
= pt
.y
- capturePoint
.y
;
429 if ( iconic
) /* ok, no system popup tracking */
431 OldCursor
= UserSetCursor(DragCursor
, FALSE
);
432 UserShowCursor( TRUE
);
434 else if(!DragFullWindows
)
435 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
438 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
441 RECT newRect
= unmodRect
;
443 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
444 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
445 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
446 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
447 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
448 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
452 // Save the new position to the unmodified rectangle. This allows explorer task bar
453 // sizing. Explorer will forces back the position unless a certain amount of sizing
458 /* determine the hit location */
459 if (syscommand
== SC_SIZE
)
461 WPARAM wpSizingHit
= 0;
463 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
464 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
465 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
468 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
472 if (!DragFullWindows
)
473 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
475 { // Moving the whole window now!
477 HRGN hrgnOrig
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
479 if (pwnd
->hrgnClip
!= NULL
)
480 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, pwnd
->hrgnClip
, RGN_AND
);
482 //// This causes the mdi child window to jump up when it is moved.
483 //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
484 co_WinPosSetWindowPos( pwnd
,
488 newRect
.right
- newRect
.left
,
489 newRect
.bottom
- newRect
.top
,
490 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
492 hrgnNew
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
493 if (pwnd
->hrgnClip
!= NULL
)
494 NtGdiCombineRgn(hrgnNew
, hrgnNew
, pwnd
->hrgnClip
, RGN_AND
);
499 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, hrgnNew
, RGN_DIFF
);
505 GreDeleteObject(hrgnOrig
);
510 // Update all the windows after the move or size, including this window.
511 UpdateThreadWindows(UserGetDesktopWindow()->spwndChild
, pti
, hrgnOrig
);
513 if (hrgnOrig
) GreDeleteObject(hrgnOrig
);
514 if (hrgnNew
) GreDeleteObject(hrgnNew
);
517 sizingRect
= newRect
;
522 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
528 if ( moved
) /* restore cursors, show icon title later on */
530 UserShowCursor( FALSE
);
531 OldCursor
= UserSetCursor(OldCursor
, FALSE
);
534 /* It could be that the cursor was already changed while we were proceeding,
535 * so we must unreference whatever cursor was current at the time we restored the old one.
536 * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
538 if (OldCursor
) UserDereferenceObject(OldCursor
);
540 else if ( moved
&& !DragFullWindows
)
541 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
543 UserReleaseDC(NULL
, hdc
, FALSE
);
545 //// This causes the mdi child window to jump up when it is moved.
546 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
548 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
550 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
554 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
556 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
558 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
560 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
562 /* window moved or resized */
565 /* if the moving/resizing isn't canceled call SetWindowPos
566 * with the new position or the new size of the window
568 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
570 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
571 if (!DragFullWindows
|| iconic
)
573 co_WinPosSetWindowPos( pwnd
,
577 sizingRect
.right
- sizingRect
.left
,
578 sizingRect
.bottom
- sizingRect
.top
,
579 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
583 { /* restore previous size/position */
584 if ( DragFullWindows
)
586 co_WinPosSetWindowPos( pwnd
,
590 origRect
.right
- origRect
.left
,
591 origRect
.bottom
- origRect
.top
,
592 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
597 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
601 /* Single click brings up the system menu when iconized */
604 if( Style
& WS_SYSMENU
)
605 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
611 PCURICON_OBJECT FASTCALL
NC_IconForWindow( PWND pWnd
)
613 PCURICON_OBJECT pIcon
= NULL
;
616 hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
, TRUE
);
617 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
, TRUE
);
619 if (!hIcon
&& pWnd
->pcls
->spicnSm
)
620 return pWnd
->pcls
->spicnSm
;
621 if (!hIcon
&& pWnd
->pcls
->spicn
)
622 return pWnd
->pcls
->spicn
;
624 // WARNING: Wine code has this test completely wrong. The following is how
625 // Windows behaves for windows having the WS_EX_DLGMODALFRAME style set:
626 // it does not use the default icon! And it does not check for DS_MODALFRAME.
627 if (!hIcon
&& !(pWnd
->ExStyle
& WS_EX_DLGMODALFRAME
))
629 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
630 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
634 pIcon
= (PCURICON_OBJECT
)UserGetObjectNoErr(gHandleTable
,
642 UserDrawSysMenuButton(PWND pWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
644 PCURICON_OBJECT WindowIcon
;
647 if ((WindowIcon
= NC_IconForWindow(pWnd
)))
649 UserReferenceObject(WindowIcon
);
651 Ret
= UserDrawIconEx(hDC
,
655 UserGetSystemMetrics(SM_CXSMICON
),
656 UserGetSystemMetrics(SM_CYSMICON
),
659 UserDereferenceObject(WindowIcon
);
665 IntIsScrollBarVisible(PWND pWnd
, INT hBar
)
668 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
670 if(!co_IntGetScrollBarInfo(pWnd
, hBar
, &sbi
))
673 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
678 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
679 * wasting precious CPU cycles) every time
680 * - Center the buttons vertically in the rect
683 UserDrawCaptionButton(PWND pWnd
, LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
687 if (!(Style
& WS_SYSMENU
))
696 case DFCS_CAPTIONMIN
:
698 if (ExStyle
& WS_EX_TOOLWINDOW
)
699 return; /* ToolWindows don't have min/max buttons */
701 if (Style
& WS_SYSMENU
)
702 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
704 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
705 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) - 2;
707 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
708 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
712 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
713 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
714 (bDown
? DFCS_PUSHED
: 0) |
715 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
718 case DFCS_CAPTIONMAX
:
720 if (ExStyle
& WS_EX_TOOLWINDOW
)
721 return; /* ToolWindows don't have min/max buttons */
723 if (Style
& WS_SYSMENU
)
724 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
726 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
727 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
731 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
732 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
733 (bDown
? DFCS_PUSHED
: 0) |
734 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
737 case DFCS_CAPTIONCLOSE
:
739 PMENU pSysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
740 UINT MenuState
= IntGetMenuState(UserHMGetHandle(pSysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
742 /* A tool window has a smaller Close button */
743 if (ExStyle
& WS_EX_TOOLWINDOW
)
745 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSMSIZE
);
746 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMSIZE
) - 2;
750 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
);
751 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
756 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
757 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
758 ((!(MenuState
& (MF_GRAYED
|MF_DISABLED
)) && !(pWnd
->pcls
->style
& CS_NOCLOSE
)) ? 0 : DFCS_INACTIVE
)));
765 UserDrawCaptionButtonWnd(PWND pWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
770 IntGetWindowRect(pWnd
, &WindowRect
);
772 WindowRect
.right
-= WindowRect
.left
;
773 WindowRect
.bottom
-= WindowRect
.top
;
774 WindowRect
.left
= WindowRect
.top
= 0;
776 UserGetWindowBorders(pWnd
->style
, pWnd
->ExStyle
, &WindowBorder
, FALSE
);
778 RECTL_vInflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
780 UserDrawCaptionButton(pWnd
, &WindowRect
, pWnd
->style
, pWnd
->ExStyle
, hDC
, bDown
, Type
);
784 NC_DrawFrame( HDC hDC
, RECT
*CurrentRect
, BOOL Active
, DWORD Style
, DWORD ExStyle
)
786 /* Firstly the "thick" frame */
787 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
790 (UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
)) *
791 UserGetSystemMetrics(SM_CXBORDER
);
794 (UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
)) *
795 UserGetSystemMetrics(SM_CYBORDER
);
797 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
800 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
801 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
802 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
803 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
805 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
808 /* Now the other bit of the frame */
809 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
811 DWORD Width
= UserGetSystemMetrics(SM_CXBORDER
);
812 DWORD Height
= UserGetSystemMetrics(SM_CYBORDER
);
814 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(
815 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
816 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
817 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
821 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
822 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
823 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
824 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
826 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
830 VOID
UserDrawCaptionBar(
835 DWORD Style
, ExStyle
;
836 RECT WindowRect
, CurrentRect
, TempRect
;
838 BOOL Gradient
= FALSE
;
839 PCURICON_OBJECT pIcon
= NULL
;
841 if (!(Flags
& DC_NOVISIBLE
) && !IntIsWindowVisible(pWnd
)) return;
843 TRACE("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd
, hDC
, Flags
);
846 ExStyle
= pWnd
->ExStyle
;
848 IntGetWindowRect(pWnd
, &WindowRect
);
850 CurrentRect
.top
= CurrentRect
.left
= 0;
851 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
852 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
854 /* Draw outer edge */
855 if (UserHasWindowEdge(Style
, ExStyle
))
857 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
859 else if (ExStyle
& WS_EX_STATICEDGE
)
862 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
864 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
865 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
866 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
868 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
869 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
870 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
872 RECTL_vInflateRect(&CurrentRect
, -1, -1);
876 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, (Flags
& DC_ACTIVE
), Style
, ExStyle
);
879 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
881 TempRect
= CurrentRect
;
883 Flags
|= DC_TEXT
|DC_BUTTONS
; // Icon will be checked if not already set.
885 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
887 Flags
|= DC_GRADIENT
;
890 if (ExStyle
& WS_EX_TOOLWINDOW
)
892 Flags
|= DC_SMALLCAP
;
893 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
894 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
898 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
899 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
902 if (!(Flags
& DC_ICON
) &&
903 !(Flags
& DC_SMALLCAP
) &&
904 (Style
& WS_SYSMENU
) &&
905 !(ExStyle
& WS_EX_TOOLWINDOW
) )
907 pIcon
= NC_IconForWindow(pWnd
); // Force redraw of caption with icon if DC_ICON not flaged....
909 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, pIcon
? UserHMGetHandle(pIcon
) : NULL
, NULL
, Flags
);
912 if (Style
& WS_SYSMENU
)
914 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
915 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
917 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
918 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
922 if (!(Style
& WS_MINIMIZE
))
924 /* Line under caption */
925 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
927 IntSetDCPenColor( hDC
, IntGetSysColor(((ExStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
928 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
930 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
932 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
934 NtGdiSelectPen(hDC
, PreviousPen
);
938 if (!(Style
& WS_MINIMIZE
))
941 if (pWnd
->state
& WNDS_HASMENU
&& pWnd
->IDMenu
) // Should be pWnd->spmenu
944 if ((menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)))) // FIXME! Use pWnd->spmenu,
946 TempRect
= CurrentRect
;
947 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
948 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
952 if (ExStyle
& WS_EX_CLIENTEDGE
)
954 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
960 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
961 the call to GetDCEx implying that it is allowed not to use it either.
962 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
963 will cause clipRgn to be deleted after ReleaseDC().
964 Now, how is the "system" supposed to tell what happened?
968 * - Drawing of WS_BORDER after scrollbars
969 * - Correct drawing of size-box
972 NC_DoNCPaint(PWND pWnd
, HDC hDC
, INT Flags
)
974 DWORD Style
, ExStyle
;
976 RECT WindowRect
, CurrentRect
, TempRect
;
979 if (!IntIsWindowVisible(pWnd
) ||
980 (pWnd
->state
& WNDS_NONCPAINT
&& !(pWnd
->state
& WNDS_FORCEMENUDRAW
)) ||
981 IntEqualRect(&pWnd
->rcWindow
, &pWnd
->rcClient
) )
986 TRACE("DefWndNCPaint: pWnd %p, hDc %p, Active %s.\n", pWnd
, hDC
, Flags
& DC_ACTIVE
? "TRUE" : "FALSE");
988 Parent
= IntGetParent(pWnd
);
989 ExStyle
= pWnd
->ExStyle
;
991 if (Flags
== -1) // NC paint mode.
993 if (ExStyle
& WS_EX_MDICHILD
)
995 Active
= IntIsChildWindow(gpqForeground
->spwndActive
, pWnd
);
998 Active
= (UserHMGetHandle(pWnd
) == (HWND
)co_IntSendMessage(UserHMGetHandle(Parent
), WM_MDIGETACTIVE
, 0, 0));
1002 Active
= (gpqForeground
== pWnd
->head
.pti
->MessageQueue
);
1004 Flags
= DC_NC
; // Redraw everything!
1010 IntGetWindowRect(pWnd
, &WindowRect
);
1012 CurrentRect
.top
= CurrentRect
.left
= 0;
1013 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
1014 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
1016 /* Draw outer edge */
1017 if (UserHasWindowEdge(pWnd
->style
, pWnd
->ExStyle
))
1019 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1021 else if (pWnd
->ExStyle
& WS_EX_STATICEDGE
)
1024 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
1026 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
1027 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1028 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1030 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
1031 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1032 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1034 RECTL_vInflateRect(&CurrentRect
, -1, -1);
1038 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, Active
? Active
: (Flags
& DC_ACTIVE
), Style
, ExStyle
);
1041 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1044 BOOL Gradient
= FALSE
;
1046 if (Flags
& DC_REDRAWHUNGWND
)
1048 Flags
&= ~DC_REDRAWHUNGWND
;
1049 Flags
|= DC_NOSENDMSG
;
1052 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
1054 Flags
|= DC_GRADIENT
;
1059 if (pWnd
->state
& WNDS_ACTIVEFRAME
)
1063 ERR("Wnd is active and not set active!\n");
1067 TempRect
= CurrentRect
;
1069 if (ExStyle
& WS_EX_TOOLWINDOW
)
1071 Flags
|= DC_SMALLCAP
;
1072 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1073 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1077 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1078 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1081 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, NULL
, NULL
, Flags
);
1084 if (Style
& WS_SYSMENU
)
1086 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
1087 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
1089 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
1090 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
1093 if (!(Style
& WS_MINIMIZE
))
1095 /* Line under caption */
1096 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
1098 IntSetDCPenColor( hDC
, IntGetSysColor(
1099 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
| WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
1100 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
1102 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
1104 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
1106 NtGdiSelectPen(hDC
, PreviousPen
);
1110 if (!(Style
& WS_MINIMIZE
))
1113 if (pWnd
->state
& WNDS_HASMENU
&& pWnd
->IDMenu
) // Should be pWnd->spmenu
1115 if (!(Flags
& DC_NOSENDMSG
))
1118 // Fix crash in test_menu_locked_by_window, should use pWnd->spmenu....
1119 if ((menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)))) // FIXME! Use pWnd->spmenu,
1121 TempRect
= CurrentRect
;
1122 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
1123 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
1128 if (ExStyle
& WS_EX_CLIENTEDGE
)
1130 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1133 /* Draw the scrollbars */
1134 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1135 IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1137 RECT ParentClientRect
;
1139 TempRect
= CurrentRect
;
1141 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
1142 TempRect
.right
= TempRect
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
);
1144 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXVSCROLL
);
1146 TempRect
.top
= TempRect
.bottom
- UserGetSystemMetrics(SM_CYHSCROLL
);
1148 FillRect(hDC
, &TempRect
, IntGetSysColorBrush(COLOR_BTNFACE
));
1151 IntGetClientRect(Parent
, &ParentClientRect
);
1153 if (HASSIZEGRIP(Style
, ExStyle
, Parent
->style
, WindowRect
, ParentClientRect
))
1155 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
1158 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1159 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1163 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
))
1165 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1167 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1169 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1173 return 0; // For WM_NCPAINT message, return 0.
1176 LRESULT
NC_HandleNCCalcSize( PWND Wnd
, WPARAM wparam
, RECTL
*Rect
, BOOL Suspended
)
1181 LONG Style
= Wnd
->style
;
1182 LONG exStyle
= Wnd
->ExStyle
;
1190 Wnd
->state
&= ~WNDS_HASCAPTION
;
1194 if (Wnd
->pcls
->style
& CS_VREDRAW
)
1196 Result
|= WVR_VREDRAW
;
1198 if (Wnd
->pcls
->style
& CS_HREDRAW
)
1200 Result
|= WVR_HREDRAW
;
1202 Result
|= WVR_VALIDRECTS
;
1205 if (!(Wnd
->style
& WS_MINIMIZE
))
1207 if (UserHasWindowEdge(Wnd
->style
, Wnd
->ExStyle
))
1209 UserGetWindowBorders(Wnd
->style
, Wnd
->ExStyle
, &WindowBorders
, FALSE
);
1210 RECTL_vInflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1212 else if ((Wnd
->ExStyle
& WS_EX_STATICEDGE
) || (Wnd
->style
& WS_BORDER
))
1214 RECTL_vInflateRect(Rect
, -1, -1);
1217 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
1219 Wnd
->state
|= WNDS_HASCAPTION
;
1221 if (Wnd
->ExStyle
& WS_EX_TOOLWINDOW
)
1222 Rect
->top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1224 Rect
->top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1227 if (HAS_MENU(Wnd
, Style
))
1229 HDC hDC
= UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
1231 Wnd
->state
|= WNDS_HASMENU
;
1235 RECT CliRect
= *Rect
;
1236 CliRect
.bottom
-= OrigRect
.top
;
1237 CliRect
.right
-= OrigRect
.left
;
1238 CliRect
.left
-= OrigRect
.left
;
1239 CliRect
.top
-= OrigRect
.top
;
1240 if (!Suspended
) Rect
->top
+= MENU_DrawMenuBar(hDC
, &CliRect
, Wnd
, TRUE
);
1241 UserReleaseDC(Wnd
, hDC
, FALSE
);
1245 if (Wnd
->ExStyle
& WS_EX_CLIENTEDGE
)
1247 RECTL_vInflateRect(Rect
, -2 * UserGetSystemMetrics(SM_CXBORDER
), -2 * UserGetSystemMetrics(SM_CYBORDER
));
1250 if (Style
& WS_VSCROLL
)
1252 if (Rect
->right
- Rect
->left
>= UserGetSystemMetrics(SM_CXVSCROLL
))
1254 Wnd
->state
|= WNDS_HASVERTICALSCROOLLBAR
;
1256 /* rectangle is in screen coords when wparam is false */
1257 if (!wparam
&& (exStyle
& WS_EX_LAYOUTRTL
)) exStyle
^= WS_EX_LEFTSCROLLBAR
;
1259 if((exStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1260 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1262 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1266 if (Style
& WS_HSCROLL
)
1268 if( Rect
->bottom
- Rect
->top
> UserGetSystemMetrics(SM_CYHSCROLL
))
1270 Wnd
->state
|= WNDS_HASHORIZONTALSCROLLBAR
;
1272 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1276 if (Rect
->top
> Rect
->bottom
)
1277 Rect
->bottom
= Rect
->top
;
1279 if (Rect
->left
> Rect
->right
)
1280 Rect
->right
= Rect
->left
;
1284 Rect
->right
= Rect
->left
;
1285 Rect
->bottom
= Rect
->top
;
1292 INT
NC_DoNCActive(PWND Wnd
)
1296 if ( IntGetSysColor(COLOR_CAPTIONTEXT
) != IntGetSysColor(COLOR_INACTIVECAPTIONTEXT
) ||
1297 IntGetSysColor(COLOR_ACTIVECAPTION
) != IntGetSysColor(COLOR_INACTIVECAPTION
) )
1300 if (!(Wnd
->style
& WS_MINIMIZED
) && UserHasThickFrameStyle(Wnd
->style
, Wnd
->ExStyle
))
1302 //if (IntGetSysColor(COLOR_ACTIVEBORDER) != IntGetSysColor(COLOR_INACTIVEBORDER)) // Why are these the same?
1310 LRESULT
NC_HandleNCActivate( PWND Wnd
, WPARAM wParam
, LPARAM lParam
)
1313 /* Lotus Notes draws menu descriptions in the caption of its main
1314 * window. When it wants to restore original "system" view, it just
1315 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1316 * attempt to minimize redrawings lead to a not restored caption.
1318 if (wParam
& DC_ACTIVE
)
1320 Wnd
->state
|= WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
;
1321 wParam
= DC_CAPTION
|DC_ACTIVE
;
1325 Wnd
->state
&= ~WNDS_ACTIVEFRAME
;
1326 wParam
= DC_CAPTION
;
1329 if ((Wnd
->state
& WNDS_NONCPAINT
) || !(Wnd
->style
& WS_VISIBLE
))
1332 /* This isn't documented but is reproducible in at least XP SP2 and
1333 * Outlook 2007 depends on it
1336 // If this parameter is set to -1, DefWindowProc does not repaint the
1337 // nonclient area to reflect the state change.
1338 if ( lParam
!= -1 &&
1339 ( Flags
= NC_DoNCActive(Wnd
)) != 0 )
1342 HRGN hRgnTemp
= NULL
, hRgn
= (HRGN
)lParam
;
1344 if (GreIsHandleValid(hRgn
))
1346 hRgnTemp
= NtGdiCreateRectRgn(0, 0, 0, 0);
1347 if (NtGdiCombineRgn(hRgnTemp
, hRgn
, 0, RGN_COPY
) == ERROR
)
1349 GreDeleteObject(hRgnTemp
);
1354 if ((hDC
= UserGetDCEx(Wnd
, hRgnTemp
, DCX_WINDOW
|DCX_USESTYLE
)))
1356 NC_DoNCPaint(Wnd
, hDC
, wParam
| Flags
); // Redraw MENUs.
1357 UserReleaseDC(Wnd
, hDC
, FALSE
);
1360 GreDeleteObject(hRgnTemp
);
1367 NC_DoButton(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1371 BOOL Pressed
= TRUE
, OldState
;
1378 Style
= pWnd
->style
;
1382 SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1383 MenuState
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
1384 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (pWnd
->style
& CS_NOCLOSE
))
1386 ButtonType
= DFCS_CAPTIONCLOSE
;
1390 if (!(Style
& WS_MINIMIZEBOX
))
1392 ButtonType
= DFCS_CAPTIONMIN
;
1393 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
1396 if (!(Style
& WS_MAXIMIZEBOX
))
1398 ButtonType
= DFCS_CAPTIONMAX
;
1399 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
1408 * FIXME: Not sure where to do this, but we must flush the pending
1409 * window updates when someone clicks on the close button and at
1410 * the same time the window is overlapped with another one. This
1411 * looks like a good place for now...
1413 co_IntUpdateWindows(pWnd
, RDW_ALLCHILDREN
, FALSE
);
1415 WindowDC
= UserGetWindowDC(pWnd
);
1416 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, TRUE
, ButtonType
);
1418 co_UserSetCapture(UserHMGetHandle(pWnd
));
1422 if (!co_IntGetPeekMessage(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1423 if (IntCallMsgFilter( &Msg
, MSGF_MAX
)) continue;
1425 if (Msg
.message
== WM_LBUTTONUP
)
1428 if (Msg
.message
!= WM_MOUSEMOVE
)
1432 Pressed
= (GetNCHitEx(pWnd
, Msg
.pt
) == wParam
);
1433 if (Pressed
!= OldState
)
1434 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, Pressed
, ButtonType
);
1438 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, FALSE
, ButtonType
);
1439 IntReleaseCapture();
1440 UserReleaseDC(pWnd
, WindowDC
, FALSE
);
1442 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SCMsg
, SCMsg
== SC_CLOSE
? lParam
: MAKELONG(Msg
.pt
.x
,Msg
.pt
.y
));
1447 NC_HandleNCLButtonDown(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1453 PWND TopWnd
= pWnd
, parent
;
1456 if ((TopWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1458 parent
= UserGetAncestor( TopWnd
, GA_PARENT
);
1459 if (!parent
|| UserIsDesktopWindow(parent
)) break;
1463 if ( co_IntSetForegroundWindowMouse(TopWnd
) ||
1464 //NtUserCallHwndLock(hTopWnd, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE) ||
1465 UserGetActiveWindow() == UserHMGetHandle(TopWnd
))
1467 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1473 LONG style
= pWnd
->style
;
1474 if (style
& WS_SYSMENU
)
1476 if(!(style
& WS_MINIMIZE
) )
1479 HDC hDC
= UserGetWindowDC(pWnd
);
1480 NC_GetInsideRect(pWnd
, &rect
);
1481 UserDrawSysMenuButton(pWnd
, hDC
, &rect
, TRUE
);
1482 UserReleaseDC( pWnd
, hDC
, FALSE
);
1484 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1490 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
1495 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1500 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1507 NC_DoButton(pWnd
, wParam
, lParam
);
1520 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1521 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1523 /* But that is not what WinNT does. Instead it sends this. This
1524 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1525 * SC_MOUSEMENU into wParam.
1527 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1538 NC_HandleNCLButtonDblClk(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1542 Style
= pWnd
->style
;
1547 /* Maximize/Restore the window */
1548 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1550 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1556 PMENU SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1557 UINT state
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
);
1559 /* If the close item of the sysmenu is disabled or not present do nothing */
1560 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1563 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1567 return NC_HandleNCLButtonDown(pWnd
, wParam
, lParam
);
1572 /***********************************************************************
1573 * NC_HandleNCRButtonDown
1575 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1577 LRESULT
NC_HandleNCRButtonDown( PWND pwnd
, WPARAM wParam
, LPARAM lParam
)
1580 INT hittest
= wParam
;
1586 if (!IntGetSystemMenu( pwnd
, FALSE
)) break;
1588 co_UserSetCapture( UserHMGetHandle(pwnd
) );
1591 if (!co_IntGetPeekMessage(&msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1592 if (IntCallMsgFilter( &msg
, MSGF_MAX
)) continue;
1593 if (msg
.message
== WM_RBUTTONUP
)
1595 hittest
= GetNCHitEx( pwnd
, msg
.pt
);
1598 if (UserHMGetHandle(pwnd
) != IntGetCapture()) return 0;
1600 IntReleaseCapture();
1601 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
|| hittest
== HTHSCROLL
|| hittest
== HTVSCROLL
)
1603 TRACE("Msg pt %x and Msg.lParam %x and lParam %x\n",MAKELONG(msg
.pt
.x
,msg
.pt
.y
),msg
.lParam
,lParam
);
1604 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_CONTEXTMENU
, (WPARAM
)UserHMGetHandle(pwnd
), MAKELONG(msg
.pt
.x
,msg
.pt
.y
));
1612 #if 0 // Old version, kept there for reference, which is also used
1613 // almost unmodified in uxtheme.dll (in nonclient.c)
1616 * - Check the scrollbar handling
1619 DefWndNCHitTest(HWND hWnd
, POINT Point
)
1621 RECT WindowRect
, ClientRect
, OrigWndRect
;
1624 DWORD Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1625 DWORD ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
1627 GetWindowRect(hWnd
, &WindowRect
);
1628 if (!PtInRect(&WindowRect
, Point
))
1632 OrigWndRect
= WindowRect
;
1634 if (UserHasWindowEdge(Style
, ExStyle
))
1638 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
1639 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1640 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
1641 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
1642 if (!PtInRect(&WindowRect
, Point
))
1646 ThickFrame
= (Style
& WS_THICKFRAME
);
1647 if (Point
.y
< WindowRect
.top
)
1649 if(Style
& WS_MINIMIZE
)
1653 if (Point
.x
< (WindowRect
.left
+ XSize
))
1655 if (Point
.x
>= (WindowRect
.right
- XSize
))
1659 if (Point
.y
>= WindowRect
.bottom
)
1661 if(Style
& WS_MINIMIZE
)
1665 if (Point
.x
< (WindowRect
.left
+ XSize
))
1666 return HTBOTTOMLEFT
;
1667 if (Point
.x
>= (WindowRect
.right
- XSize
))
1668 return HTBOTTOMRIGHT
;
1671 if (Point
.x
< WindowRect
.left
)
1673 if(Style
& WS_MINIMIZE
)
1677 if (Point
.y
< (WindowRect
.top
+ YSize
))
1679 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1680 return HTBOTTOMLEFT
;
1683 if (Point
.x
>= WindowRect
.right
)
1685 if(Style
& WS_MINIMIZE
)
1689 if (Point
.y
< (WindowRect
.top
+ YSize
))
1691 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1692 return HTBOTTOMRIGHT
;
1699 if (ExStyle
& WS_EX_STATICEDGE
)
1700 InflateRect(&WindowRect
,
1701 -GetSystemMetrics(SM_CXBORDER
),
1702 -GetSystemMetrics(SM_CYBORDER
));
1703 if (!PtInRect(&WindowRect
, Point
))
1707 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1709 if (ExStyle
& WS_EX_TOOLWINDOW
)
1710 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1712 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1713 if (!PtInRect(&WindowRect
, Point
))
1715 if (Style
& WS_SYSMENU
)
1717 if (ExStyle
& WS_EX_TOOLWINDOW
)
1719 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
1723 // if(!(ExStyle & WS_EX_DLGMODALFRAME))
1724 // FIXME: The real test should check whether there is
1725 // an icon for the system window, and if so, do the
1726 // rect.left increase.
1727 // See dll/win32/uxtheme/nonclient.c!DefWndNCHitTest
1728 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
1730 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
1731 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1734 if (Point
.x
< WindowRect
.left
)
1736 if (WindowRect
.right
<= Point
.x
)
1738 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
1739 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1740 if (Point
.x
>= WindowRect
.right
)
1742 if (Style
& WS_MINIMIZEBOX
)
1743 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1744 if (Point
.x
>= WindowRect
.right
)
1750 if(!(Style
& WS_MINIMIZE
))
1752 ClientPoint
= Point
;
1753 ScreenToClient(hWnd
, &ClientPoint
);
1754 GetClientRect(hWnd
, &ClientRect
);
1756 if (PtInRect(&ClientRect
, ClientPoint
))
1761 if (GetMenu(hWnd
) && !(Style
& WS_CHILD
))
1763 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
1767 if (ExStyle
& WS_EX_CLIENTEDGE
)
1769 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
1770 -2 * GetSystemMetrics(SM_CYBORDER
));
1773 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1774 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
1776 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
1777 HWND Parent
= GetParent(hWnd
);
1779 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
1780 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1781 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1783 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1784 if (PtInRect(&TempRect
, Point
))
1787 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1788 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1789 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
1791 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
1792 if (PtInRect(&TempRect2
, Point
))
1795 TempRect
.top
= TempRect2
.top
;
1796 TempRect
.bottom
= TempRect2
.bottom
;
1798 GetClientRect(Parent
, &ParentRect
);
1799 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
1800 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
1802 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1803 return HTBOTTOMLEFT
;
1805 return HTBOTTOMRIGHT
;
1810 if (Style
& WS_VSCROLL
)
1812 RECT TempRect
= WindowRect
;
1814 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1815 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1817 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1818 if (PtInRect(&TempRect
, Point
))
1821 if (Style
& WS_HSCROLL
)
1823 RECT TempRect
= WindowRect
;
1824 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1825 if (PtInRect(&TempRect
, Point
))
1836 GetNCHitEx(PWND pWnd
, POINT pt
)
1838 RECT rcWindow
, rcClient
;
1839 DWORD Style
, ExStyle
;
1841 if (!pWnd
) return HTNOWHERE
;
1843 if (UserIsDesktopWindow(pWnd
))
1845 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
1846 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1847 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1848 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1849 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1853 rcClient
= pWnd
->rcClient
;
1854 rcWindow
= pWnd
->rcWindow
;
1857 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
1859 Style
= pWnd
->style
;
1860 ExStyle
= pWnd
->ExStyle
;
1862 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
1864 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
1867 if (HAS_THICKFRAME( Style
, ExStyle
))
1869 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1870 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
1872 /* Check top sizing border */
1873 if (pt
.y
< rcWindow
.top
)
1875 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
1876 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
1879 /* Check bottom sizing border */
1880 if (pt
.y
>= rcWindow
.bottom
)
1882 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
1883 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
1886 /* Check left sizing border */
1887 if (pt
.x
< rcWindow
.left
)
1889 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
1890 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
1893 /* Check right sizing border */
1894 if (pt
.x
>= rcWindow
.right
)
1896 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
1897 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
1902 else /* No thick frame */
1904 if (HAS_DLGFRAME( Style
, ExStyle
))
1905 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1906 else if (HAS_THINFRAME( Style
, ExStyle
))
1907 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1908 else if (HAS_CLIENTFRAME( Style
, ExStyle
))
1909 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1910 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1915 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1917 if (ExStyle
& WS_EX_TOOLWINDOW
)
1918 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1920 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1921 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1923 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1924 if (ExStyle
& WS_EX_LAYOUTRTL
)
1926 /* Check system menu */
1927 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1929 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1930 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
1933 /* Check close button */
1934 if (Style
& WS_SYSMENU
)
1936 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
1937 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
1940 /* Check maximize box */
1941 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1942 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1944 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1945 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
1948 /* Check minimize box */
1949 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1951 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1952 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
1957 /* Check system menu */
1958 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1960 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1961 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
1964 /* Check close button */
1965 if (Style
& WS_SYSMENU
)
1967 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
1968 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
1971 /* Check maximize box */
1972 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1973 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1975 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1976 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
1979 /* Check minimize box */
1980 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1982 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1983 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
1990 /* Check menu bar */
1992 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
1993 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
1996 /* Check vertical scroll bar */
1998 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
1999 if (Style
& WS_VSCROLL
)
2001 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
2002 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
2004 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
2005 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
2008 /* Check horizontal scroll bar */
2010 if (Style
& WS_HSCROLL
)
2012 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
2013 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
2015 /* Check size box */
2016 if ((Style
& WS_VSCROLL
) &&
2017 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
2018 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
2024 /* Has to return HTNOWHERE if nothing was found
2025 Could happen when a window has a customized non client area */