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
943 PMENU menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)); // FIXME!
944 TempRect
= CurrentRect
;
945 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
946 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
949 if (ExStyle
& WS_EX_CLIENTEDGE
)
951 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
957 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
958 the call to GetDCEx implying that it is allowed not to use it either.
959 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
960 will cause clipRgn to be deleted after ReleaseDC().
961 Now, how is the "system" supposed to tell what happened?
965 * - Drawing of WS_BORDER after scrollbars
966 * - Correct drawing of size-box
969 NC_DoNCPaint(PWND pWnd
, HDC hDC
, INT Flags
)
971 DWORD Style
, ExStyle
;
973 RECT WindowRect
, CurrentRect
, TempRect
;
976 if (!IntIsWindowVisible(pWnd
) ||
977 (pWnd
->state
& WNDS_NONCPAINT
&& !(pWnd
->state
& WNDS_FORCEMENUDRAW
)) ||
978 IntEqualRect(&pWnd
->rcWindow
, &pWnd
->rcClient
) )
983 TRACE("DefWndNCPaint: pWnd %p, hDc %p, Active %s.\n", pWnd
, hDC
, Flags
& DC_ACTIVE
? "TRUE" : "FALSE");
985 Parent
= IntGetParent(pWnd
);
986 ExStyle
= pWnd
->ExStyle
;
988 if (Flags
== -1) // NC paint mode.
990 if (ExStyle
& WS_EX_MDICHILD
)
992 Active
= IntIsChildWindow(gpqForeground
->spwndActive
, pWnd
);
995 Active
= (UserHMGetHandle(pWnd
) == (HWND
)co_IntSendMessage(UserHMGetHandle(Parent
), WM_MDIGETACTIVE
, 0, 0));
999 Active
= (gpqForeground
== pWnd
->head
.pti
->MessageQueue
);
1001 Flags
= DC_NC
; // Redraw everything!
1007 IntGetWindowRect(pWnd
, &WindowRect
);
1009 CurrentRect
.top
= CurrentRect
.left
= 0;
1010 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
1011 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
1013 /* Draw outer edge */
1014 if (UserHasWindowEdge(pWnd
->style
, pWnd
->ExStyle
))
1016 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1018 else if (pWnd
->ExStyle
& WS_EX_STATICEDGE
)
1021 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
1023 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
1024 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1025 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1027 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
1028 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1029 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1031 RECTL_vInflateRect(&CurrentRect
, -1, -1);
1035 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, Active
? Active
: (Flags
& DC_ACTIVE
), Style
, ExStyle
);
1038 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1041 BOOL Gradient
= FALSE
;
1043 if (Flags
& DC_REDRAWHUNGWND
)
1045 Flags
&= ~DC_REDRAWHUNGWND
;
1046 Flags
|= DC_NOSENDMSG
;
1049 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
1051 Flags
|= DC_GRADIENT
;
1056 if (pWnd
->state
& WNDS_ACTIVEFRAME
)
1060 ERR("Wnd is active and not set active!\n");
1064 TempRect
= CurrentRect
;
1066 if (ExStyle
& WS_EX_TOOLWINDOW
)
1068 Flags
|= DC_SMALLCAP
;
1069 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1070 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1074 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1075 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1078 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, NULL
, NULL
, Flags
);
1081 if (Style
& WS_SYSMENU
)
1083 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
1084 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
1086 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
1087 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
1090 if (!(Style
& WS_MINIMIZE
))
1092 /* Line under caption */
1093 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
1095 IntSetDCPenColor( hDC
, IntGetSysColor(
1096 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
| WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
1097 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
1099 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
1101 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
1103 NtGdiSelectPen(hDC
, PreviousPen
);
1107 if (!(Style
& WS_MINIMIZE
))
1110 if (pWnd
->state
& WNDS_HASMENU
&& pWnd
->IDMenu
) // Should be pWnd->spmenu
1112 if (!(Flags
& DC_NOSENDMSG
))
1114 PMENU menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
)); // FIXME!
1115 TempRect
= CurrentRect
;
1116 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
; // Should be pWnd->spmenu->cyMenu;
1117 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
1121 if (ExStyle
& WS_EX_CLIENTEDGE
)
1123 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1126 /* Draw the scrollbars */
1127 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1128 IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1130 RECT ParentClientRect
;
1132 TempRect
= CurrentRect
;
1134 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
1135 TempRect
.right
= TempRect
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
);
1137 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXVSCROLL
);
1139 TempRect
.top
= TempRect
.bottom
- UserGetSystemMetrics(SM_CYHSCROLL
);
1141 FillRect(hDC
, &TempRect
, IntGetSysColorBrush(COLOR_BTNFACE
));
1144 IntGetClientRect(Parent
, &ParentClientRect
);
1146 if (HASSIZEGRIP(Style
, ExStyle
, Parent
->style
, WindowRect
, ParentClientRect
))
1148 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
1151 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1152 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1156 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
))
1158 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1160 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1162 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1166 return 0; // For WM_NCPAINT message, return 0.
1169 LRESULT
NC_HandleNCCalcSize( PWND Wnd
, WPARAM wparam
, RECTL
*Rect
, BOOL Suspended
)
1174 DWORD Style
= Wnd
->style
;
1182 Wnd
->state
&= ~WNDS_HASCAPTION
;
1186 if (Wnd
->pcls
->style
& CS_VREDRAW
)
1188 Result
|= WVR_VREDRAW
;
1190 if (Wnd
->pcls
->style
& CS_HREDRAW
)
1192 Result
|= WVR_HREDRAW
;
1194 Result
|= WVR_VALIDRECTS
;
1197 if (!(Wnd
->style
& WS_MINIMIZE
))
1199 if (UserHasWindowEdge(Wnd
->style
, Wnd
->ExStyle
))
1201 UserGetWindowBorders(Wnd
->style
, Wnd
->ExStyle
, &WindowBorders
, FALSE
);
1202 RECTL_vInflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1204 else if ((Wnd
->ExStyle
& WS_EX_STATICEDGE
) || (Wnd
->style
& WS_BORDER
))
1206 RECTL_vInflateRect(Rect
, -1, -1);
1209 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
1211 Wnd
->state
|= WNDS_HASCAPTION
;
1213 if (Wnd
->ExStyle
& WS_EX_TOOLWINDOW
)
1214 Rect
->top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1216 Rect
->top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1219 if (HAS_MENU(Wnd
, Style
))
1221 HDC hDC
= UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
1223 Wnd
->state
|= WNDS_HASMENU
;
1227 RECT CliRect
= *Rect
;
1228 CliRect
.bottom
-= OrigRect
.top
;
1229 CliRect
.right
-= OrigRect
.left
;
1230 CliRect
.left
-= OrigRect
.left
;
1231 CliRect
.top
-= OrigRect
.top
;
1232 if (!Suspended
) Rect
->top
+= MENU_DrawMenuBar(hDC
, &CliRect
, Wnd
, TRUE
);
1233 UserReleaseDC(Wnd
, hDC
, FALSE
);
1237 if (Wnd
->ExStyle
& WS_EX_CLIENTEDGE
)
1239 RECTL_vInflateRect(Rect
, -2 * UserGetSystemMetrics(SM_CXBORDER
), -2 * UserGetSystemMetrics(SM_CYBORDER
));
1242 if (Wnd
->style
& (WS_VSCROLL
| WS_HSCROLL
))
1245 SETSCROLLBARINFO ssbi
;
1247 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
1248 if ((Style
& WS_VSCROLL
) && co_IntGetScrollBarInfo(Wnd
, OBJID_VSCROLL
, &sbi
))
1251 LONG sx
= Rect
->right
;
1253 Wnd
->state
|= WNDS_HASVERTICALSCROOLLBAR
;
1255 sx
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1257 for (i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
1258 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
1260 if (sx
<= Rect
->left
)
1261 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
1263 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
1265 co_IntSetScrollBarInfo(Wnd
, OBJID_VSCROLL
, &ssbi
);
1267 if (ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
1268 Style
&= ~WS_VSCROLL
;
1271 Style
&= ~WS_VSCROLL
;
1273 if ((Style
& WS_HSCROLL
) && co_IntGetScrollBarInfo(Wnd
, OBJID_HSCROLL
, &sbi
))
1276 LONG sy
= Rect
->bottom
;
1278 Wnd
->state
|= WNDS_HASHORIZONTALSCROLLBAR
;
1280 sy
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1282 for (i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
1283 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
1285 if (sy
<= Rect
->top
)
1286 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
1288 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
1290 co_IntSetScrollBarInfo(Wnd
, OBJID_HSCROLL
, &ssbi
);
1292 if (ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
1293 Style
&= ~WS_HSCROLL
;
1296 Style
&= ~WS_HSCROLL
;
1299 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
1301 if ((Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1302 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1304 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1306 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1310 if (Style
& WS_VSCROLL
)
1312 if ((Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1313 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1315 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1317 else if (Style
& WS_HSCROLL
)
1318 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1321 if (Rect
->top
> Rect
->bottom
)
1322 Rect
->bottom
= Rect
->top
;
1324 if (Rect
->left
> Rect
->right
)
1325 Rect
->right
= Rect
->left
;
1329 Rect
->right
= Rect
->left
;
1330 Rect
->bottom
= Rect
->top
;
1337 INT
NC_DoNCActive(PWND Wnd
)
1341 if ( IntGetSysColor(COLOR_CAPTIONTEXT
) != IntGetSysColor(COLOR_INACTIVECAPTIONTEXT
) ||
1342 IntGetSysColor(COLOR_ACTIVECAPTION
) != IntGetSysColor(COLOR_INACTIVECAPTION
) )
1345 if (!(Wnd
->style
& WS_MINIMIZED
) && UserHasThickFrameStyle(Wnd
->style
, Wnd
->ExStyle
))
1347 //if (IntGetSysColor(COLOR_ACTIVEBORDER) != IntGetSysColor(COLOR_INACTIVEBORDER)) // Why are these the same?
1355 LRESULT
NC_HandleNCActivate( PWND Wnd
, WPARAM wParam
, LPARAM lParam
)
1358 /* Lotus Notes draws menu descriptions in the caption of its main
1359 * window. When it wants to restore original "system" view, it just
1360 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1361 * attempt to minimize redrawings lead to a not restored caption.
1363 if (wParam
& DC_ACTIVE
)
1365 Wnd
->state
|= WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
;
1366 wParam
= DC_CAPTION
|DC_ACTIVE
;
1370 Wnd
->state
&= ~WNDS_ACTIVEFRAME
;
1371 wParam
= DC_CAPTION
;
1374 if ((Wnd
->state
& WNDS_NONCPAINT
) || !(Wnd
->style
& WS_VISIBLE
))
1377 /* This isn't documented but is reproducible in at least XP SP2 and
1378 * Outlook 2007 depends on it
1381 // If this parameter is set to -1, DefWindowProc does not repaint the
1382 // nonclient area to reflect the state change.
1383 if ( lParam
!= -1 &&
1384 ( Flags
= NC_DoNCActive(Wnd
)) != 0 )
1387 HRGN hRgnTemp
= NULL
, hRgn
= (HRGN
)lParam
;
1389 if (GreIsHandleValid(hRgn
))
1391 hRgnTemp
= NtGdiCreateRectRgn(0, 0, 0, 0);
1392 if (NtGdiCombineRgn(hRgnTemp
, hRgn
, 0, RGN_COPY
) == ERROR
)
1394 GreDeleteObject(hRgnTemp
);
1399 if ((hDC
= UserGetDCEx(Wnd
, hRgnTemp
, DCX_WINDOW
|DCX_USESTYLE
)))
1401 NC_DoNCPaint(Wnd
, hDC
, wParam
| Flags
); // Redraw MENUs.
1402 UserReleaseDC(Wnd
, hDC
, FALSE
);
1405 GreDeleteObject(hRgnTemp
);
1412 NC_DoButton(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1416 BOOL Pressed
= TRUE
, OldState
;
1423 Style
= pWnd
->style
;
1427 SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1428 MenuState
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
1429 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (pWnd
->style
& CS_NOCLOSE
))
1431 ButtonType
= DFCS_CAPTIONCLOSE
;
1435 if (!(Style
& WS_MINIMIZEBOX
))
1437 ButtonType
= DFCS_CAPTIONMIN
;
1438 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
1441 if (!(Style
& WS_MAXIMIZEBOX
))
1443 ButtonType
= DFCS_CAPTIONMAX
;
1444 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
1453 * FIXME: Not sure where to do this, but we must flush the pending
1454 * window updates when someone clicks on the close button and at
1455 * the same time the window is overlapped with another one. This
1456 * looks like a good place for now...
1458 co_IntUpdateWindows(pWnd
, RDW_ALLCHILDREN
, FALSE
);
1460 WindowDC
= UserGetWindowDC(pWnd
);
1461 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, TRUE
, ButtonType
);
1463 co_UserSetCapture(UserHMGetHandle(pWnd
));
1467 if (!co_IntGetPeekMessage(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1468 if (IntCallMsgFilter( &Msg
, MSGF_MAX
)) continue;
1470 if (Msg
.message
== WM_LBUTTONUP
)
1473 if (Msg
.message
!= WM_MOUSEMOVE
)
1477 Pressed
= (GetNCHitEx(pWnd
, Msg
.pt
) == wParam
);
1478 if (Pressed
!= OldState
)
1479 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, Pressed
, ButtonType
);
1483 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, FALSE
, ButtonType
);
1484 IntReleaseCapture();
1485 UserReleaseDC(pWnd
, WindowDC
, FALSE
);
1487 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SCMsg
, SCMsg
== SC_CLOSE
? lParam
: MAKELONG(Msg
.pt
.x
,Msg
.pt
.y
));
1492 NC_HandleNCLButtonDown(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1498 PWND TopWnd
= pWnd
, parent
;
1501 if ((TopWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1503 parent
= UserGetAncestor( TopWnd
, GA_PARENT
);
1504 if (!parent
|| parent
== UserGetDesktopWindow()) break;
1508 if ( co_IntSetForegroundWindowMouse(TopWnd
) ||
1509 //NtUserCallHwndLock(hTopWnd, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE) ||
1510 UserGetActiveWindow() == UserHMGetHandle(TopWnd
))
1512 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1518 LONG style
= pWnd
->style
;
1519 if (style
& WS_SYSMENU
)
1521 if(!(style
& WS_MINIMIZE
) )
1524 HDC hDC
= UserGetWindowDC(pWnd
);
1525 NC_GetInsideRect(pWnd
, &rect
);
1526 UserDrawSysMenuButton(pWnd
, hDC
, &rect
, TRUE
);
1527 UserReleaseDC( pWnd
, hDC
, FALSE
);
1529 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1535 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
1540 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1545 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1552 NC_DoButton(pWnd
, wParam
, lParam
);
1565 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1566 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1568 /* But that is not what WinNT does. Instead it sends this. This
1569 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1570 * SC_MOUSEMENU into wParam.
1572 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1583 NC_HandleNCLButtonDblClk(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1587 Style
= pWnd
->style
;
1592 /* Maximize/Restore the window */
1593 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1595 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1601 PMENU SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1602 UINT state
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
);
1604 /* If the close item of the sysmenu is disabled or not present do nothing */
1605 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1608 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1612 return NC_HandleNCLButtonDown(pWnd
, wParam
, lParam
);
1617 /***********************************************************************
1618 * NC_HandleNCRButtonDown
1620 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1622 LRESULT
NC_HandleNCRButtonDown( PWND pwnd
, WPARAM wParam
, LPARAM lParam
)
1625 INT hittest
= wParam
;
1631 if (!IntGetSystemMenu( pwnd
, FALSE
)) break;
1633 co_UserSetCapture( UserHMGetHandle(pwnd
) );
1636 if (!co_IntGetPeekMessage(&msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1637 if (IntCallMsgFilter( &msg
, MSGF_MAX
)) continue;
1638 if (msg
.message
== WM_RBUTTONUP
)
1640 hittest
= GetNCHitEx( pwnd
, msg
.pt
);
1643 if (UserHMGetHandle(pwnd
) != IntGetCapture()) return 0;
1645 IntReleaseCapture();
1646 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
|| hittest
== HTHSCROLL
|| hittest
== HTVSCROLL
)
1648 TRACE("Msg pt %x and Msg.lParam %x and lParam %x\n",MAKELONG(msg
.pt
.x
,msg
.pt
.y
),msg
.lParam
,lParam
);
1649 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_CONTEXTMENU
, (WPARAM
)UserHMGetHandle(pwnd
), MAKELONG(msg
.pt
.x
,msg
.pt
.y
));
1657 #if 0 // Old version, kept there for reference, which is also used
1658 // almost unmodified in uxtheme.dll (in nonclient.c)
1661 * - Check the scrollbar handling
1664 DefWndNCHitTest(HWND hWnd
, POINT Point
)
1666 RECT WindowRect
, ClientRect
, OrigWndRect
;
1669 DWORD Style
= GetWindowLongPtrW(hWnd
, GWL_STYLE
);
1670 DWORD ExStyle
= GetWindowLongPtrW(hWnd
, GWL_EXSTYLE
);
1672 GetWindowRect(hWnd
, &WindowRect
);
1673 if (!PtInRect(&WindowRect
, Point
))
1677 OrigWndRect
= WindowRect
;
1679 if (UserHasWindowEdge(Style
, ExStyle
))
1683 UserGetWindowBorders(Style
, ExStyle
, &WindowBorders
, FALSE
);
1684 InflateRect(&WindowRect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1685 XSize
= GetSystemMetrics(SM_CXSIZE
) * GetSystemMetrics(SM_CXBORDER
);
1686 YSize
= GetSystemMetrics(SM_CYSIZE
) * GetSystemMetrics(SM_CYBORDER
);
1687 if (!PtInRect(&WindowRect
, Point
))
1691 ThickFrame
= (Style
& WS_THICKFRAME
);
1692 if (Point
.y
< WindowRect
.top
)
1694 if(Style
& WS_MINIMIZE
)
1698 if (Point
.x
< (WindowRect
.left
+ XSize
))
1700 if (Point
.x
>= (WindowRect
.right
- XSize
))
1704 if (Point
.y
>= WindowRect
.bottom
)
1706 if(Style
& WS_MINIMIZE
)
1710 if (Point
.x
< (WindowRect
.left
+ XSize
))
1711 return HTBOTTOMLEFT
;
1712 if (Point
.x
>= (WindowRect
.right
- XSize
))
1713 return HTBOTTOMRIGHT
;
1716 if (Point
.x
< WindowRect
.left
)
1718 if(Style
& WS_MINIMIZE
)
1722 if (Point
.y
< (WindowRect
.top
+ YSize
))
1724 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1725 return HTBOTTOMLEFT
;
1728 if (Point
.x
>= WindowRect
.right
)
1730 if(Style
& WS_MINIMIZE
)
1734 if (Point
.y
< (WindowRect
.top
+ YSize
))
1736 if (Point
.y
>= (WindowRect
.bottom
- YSize
))
1737 return HTBOTTOMRIGHT
;
1744 if (ExStyle
& WS_EX_STATICEDGE
)
1745 InflateRect(&WindowRect
,
1746 -GetSystemMetrics(SM_CXBORDER
),
1747 -GetSystemMetrics(SM_CYBORDER
));
1748 if (!PtInRect(&WindowRect
, Point
))
1752 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1754 if (ExStyle
& WS_EX_TOOLWINDOW
)
1755 WindowRect
.top
+= GetSystemMetrics(SM_CYSMCAPTION
);
1757 WindowRect
.top
+= GetSystemMetrics(SM_CYCAPTION
);
1758 if (!PtInRect(&WindowRect
, Point
))
1760 if (Style
& WS_SYSMENU
)
1762 if (ExStyle
& WS_EX_TOOLWINDOW
)
1764 WindowRect
.right
-= GetSystemMetrics(SM_CXSMSIZE
);
1768 // if(!(ExStyle & WS_EX_DLGMODALFRAME))
1769 // FIXME: The real test should check whether there is
1770 // an icon for the system window, and if so, do the
1771 // rect.left increase.
1772 // See dll/win32/uxtheme/nonclient.c!DefWndNCHitTest
1773 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does
1775 WindowRect
.left
+= GetSystemMetrics(SM_CXSIZE
);
1776 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1779 if (Point
.x
< WindowRect
.left
)
1781 if (WindowRect
.right
<= Point
.x
)
1783 if (Style
& WS_MAXIMIZEBOX
|| Style
& WS_MINIMIZEBOX
)
1784 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1785 if (Point
.x
>= WindowRect
.right
)
1787 if (Style
& WS_MINIMIZEBOX
)
1788 WindowRect
.right
-= GetSystemMetrics(SM_CXSIZE
);
1789 if (Point
.x
>= WindowRect
.right
)
1795 if(!(Style
& WS_MINIMIZE
))
1797 ClientPoint
= Point
;
1798 ScreenToClient(hWnd
, &ClientPoint
);
1799 GetClientRect(hWnd
, &ClientRect
);
1801 if (PtInRect(&ClientRect
, ClientPoint
))
1806 if (GetMenu(hWnd
) && !(Style
& WS_CHILD
))
1808 if (Point
.x
> 0 && Point
.x
< WindowRect
.right
&& ClientPoint
.y
< 0)
1812 if (ExStyle
& WS_EX_CLIENTEDGE
)
1814 InflateRect(&WindowRect
, -2 * GetSystemMetrics(SM_CXBORDER
),
1815 -2 * GetSystemMetrics(SM_CYBORDER
));
1818 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1819 (WindowRect
.bottom
- WindowRect
.top
) > GetSystemMetrics(SM_CYHSCROLL
))
1821 RECT ParentRect
, TempRect
= WindowRect
, TempRect2
= WindowRect
;
1822 HWND Parent
= GetParent(hWnd
);
1824 TempRect
.bottom
-= GetSystemMetrics(SM_CYHSCROLL
);
1825 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1826 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1828 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1829 if (PtInRect(&TempRect
, Point
))
1832 TempRect2
.top
= TempRect2
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1833 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1834 TempRect2
.left
+= GetSystemMetrics(SM_CXVSCROLL
);
1836 TempRect2
.right
-= GetSystemMetrics(SM_CXVSCROLL
);
1837 if (PtInRect(&TempRect2
, Point
))
1840 TempRect
.top
= TempRect2
.top
;
1841 TempRect
.bottom
= TempRect2
.bottom
;
1843 GetClientRect(Parent
, &ParentRect
);
1844 if (PtInRect(&TempRect
, Point
) && HASSIZEGRIP(Style
, ExStyle
,
1845 GetWindowLongPtrW(Parent
, GWL_STYLE
), OrigWndRect
, ParentRect
))
1847 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1848 return HTBOTTOMLEFT
;
1850 return HTBOTTOMRIGHT
;
1855 if (Style
& WS_VSCROLL
)
1857 RECT TempRect
= WindowRect
;
1859 if ((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1860 TempRect
.right
= TempRect
.left
+ GetSystemMetrics(SM_CXVSCROLL
);
1862 TempRect
.left
= TempRect
.right
- GetSystemMetrics(SM_CXVSCROLL
);
1863 if (PtInRect(&TempRect
, Point
))
1866 if (Style
& WS_HSCROLL
)
1868 RECT TempRect
= WindowRect
;
1869 TempRect
.top
= TempRect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
1870 if (PtInRect(&TempRect
, Point
))
1881 GetNCHitEx(PWND pWnd
, POINT pt
)
1883 RECT rcWindow
, rcClient
;
1884 DWORD Style
, ExStyle
;
1886 if (!pWnd
) return HTNOWHERE
;
1888 if (pWnd
== UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
1890 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
1891 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1892 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1893 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1894 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1898 rcClient
= pWnd
->rcClient
;
1899 rcWindow
= pWnd
->rcWindow
;
1902 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
1904 Style
= pWnd
->style
;
1905 ExStyle
= pWnd
->ExStyle
;
1907 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
1909 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
1912 if (HAS_THICKFRAME( Style
, ExStyle
))
1914 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1915 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
1917 /* Check top sizing border */
1918 if (pt
.y
< rcWindow
.top
)
1920 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
1921 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
1924 /* Check bottom sizing border */
1925 if (pt
.y
>= rcWindow
.bottom
)
1927 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
1928 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
1931 /* Check left sizing border */
1932 if (pt
.x
< rcWindow
.left
)
1934 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
1935 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
1938 /* Check right sizing border */
1939 if (pt
.x
>= rcWindow
.right
)
1941 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
1942 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
1947 else /* No thick frame */
1949 if (HAS_DLGFRAME( Style
, ExStyle
))
1950 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1951 else if (HAS_THINFRAME( Style
, ExStyle
))
1952 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1953 else if (HAS_CLIENTFRAME( Style
, ExStyle
))
1954 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
1955 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1960 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1962 if (ExStyle
& WS_EX_TOOLWINDOW
)
1963 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1965 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1966 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1968 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1969 if (ExStyle
& WS_EX_LAYOUTRTL
)
1971 /* Check system menu */
1972 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1974 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1975 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
1978 /* Check close button */
1979 if (Style
& WS_SYSMENU
)
1981 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
1982 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
1985 /* Check maximize box */
1986 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1987 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1989 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1990 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
1993 /* Check minimize box */
1994 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1996 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1997 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
2002 /* Check system menu */
2003 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
2005 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
2006 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
2009 /* Check close button */
2010 if (Style
& WS_SYSMENU
)
2012 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
2013 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
2016 /* Check maximize box */
2017 /* In Win95 there is automatically a Maximize button when there is a minimize one */
2018 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2020 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2021 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
2024 /* Check minimize box */
2025 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2027 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2028 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
2035 /* Check menu bar */
2037 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
2038 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
2041 /* Check vertical scroll bar */
2043 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
2044 if (Style
& WS_VSCROLL
)
2046 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
2047 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
2049 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
2050 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
2053 /* Check horizontal scroll bar */
2055 if (Style
& WS_HSCROLL
)
2057 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
2058 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
2060 /* Check size box */
2061 if ((Style
& WS_VSCROLL
) &&
2062 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
2063 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
2069 /* Has to return HTNOWHERE if nothing was found
2070 Could happen when a window has a customized non client area */