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;
218 IntTranslateKbdMessage( &msg
, 0 );
219 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
220 IntDispatchMessage( &msg
);
221 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
227 UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
228 co_IntSendMessage(UserHMGetHandle(Wnd
), WM_SETCURSOR
, (WPARAM
)UserHMGetHandle(Wnd
), MAKELONG(hittest
, WM_MOUSEMOVE
));
233 // System Command Size and Move
235 // Perform SC_MOVE and SC_SIZE commands.
238 DefWndDoSizeMove(PWND pwnd
, WORD wParam
)
241 RECT sizingRect
, mouseRect
, origRect
, unmodRect
;
243 LONG hittest
= (LONG
)(wParam
& 0x0f);
244 PCURICON_OBJECT DragCursor
= NULL
, OldCursor
= NULL
;
245 POINT minTrack
, maxTrack
;
246 POINT capturePoint
, pt
;
247 ULONG Style
, ExStyle
;
251 BOOL DragFullWindows
= FALSE
;
252 PWND pWndParent
= NULL
;
253 WPARAM syscommand
= (wParam
& 0xfff0);
254 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
255 //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
256 // The task bar can grow in size and can not reduce due to the change
260 ExStyle
= pwnd
->ExStyle
;
261 iconic
= (Style
& WS_MINIMIZE
) != 0;
263 if ((Style
& WS_MAXIMIZE
) || !IntIsWindowVisible(pwnd
)) return;
265 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !iconic
;
268 // Show window contents while dragging the window, get flag from registry data.
270 UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
272 pt
.x
= pti
->ptLast
.x
;
273 pt
.y
= pti
->ptLast
.y
;
275 UserClipCursor( NULL
);
277 TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
278 pwnd
, syscommand
, hittest
, pt
.x
, pt
.y
);
280 if (syscommand
== SC_MOVE
)
282 if (!hittest
) hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
283 if (!hittest
) return;
287 if (!thickframe
) return;
288 if (hittest
&& (syscommand
!= SC_MOUSEMENU
))
290 hittest
+= (HTLEFT
- WMSZ_LEFT
);
294 co_UserSetCapture(UserHMGetHandle(pwnd
));
295 hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
304 /* Get min/max info */
306 co_WinPosGetMinMaxInfo(pwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
307 sizingRect
= pwnd
->rcWindow
;
308 origRect
= sizingRect
;
309 if (Style
& WS_CHILD
)
311 pWndParent
= IntGetParent(pwnd
);
312 IntGetClientRect( pWndParent
, &mouseRect
);
313 IntMapWindowPoints( pWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
314 IntMapWindowPoints( 0, pWndParent
, (LPPOINT
)&sizingRect
, 2 );
315 unmodRect
= sizingRect
;
319 if (!(ExStyle
& WS_EX_TOPMOST
))
321 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
325 RECTL_vSetRect(&mouseRect
, 0, 0, UserGetSystemMetrics(SM_CXSCREEN
), UserGetSystemMetrics(SM_CYSCREEN
));
327 unmodRect
= sizingRect
;
330 if (ON_LEFT_BORDER(hittest
))
332 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
+capturePoint
.x
-sizingRect
.left
);
333 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
+capturePoint
.x
-sizingRect
.left
);
335 else if (ON_RIGHT_BORDER(hittest
))
337 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
+capturePoint
.x
-sizingRect
.right
);
338 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
+capturePoint
.x
-sizingRect
.right
);
340 if (ON_TOP_BORDER(hittest
))
342 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
+capturePoint
.y
-sizingRect
.top
);
343 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
+capturePoint
.y
-sizingRect
.top
);
345 else if (ON_BOTTOM_BORDER(hittest
))
347 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
348 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
351 hdc
= UserGetDCEx( pWndParent
, 0, DCX_CACHE
);
354 DragCursor
= pwnd
->pcls
->spicn
;
357 UserReferenceObject(DragCursor
);
361 HCURSOR CursorHandle
= (HCURSOR
)co_IntSendMessage( UserHMGetHandle(pwnd
), WM_QUERYDRAGICON
, 0, 0 );
364 DragCursor
= UserGetCurIconObject(CursorHandle
);
373 /* repaint the window before moving it around */
374 co_UserRedrawWindow( pwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
376 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
378 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_ENTERSIZEMOVE
, 0, 0 );
380 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, UserHMGetHandle(pwnd
));
382 if (IntGetCapture() != UserHMGetHandle(pwnd
)) co_UserSetCapture( UserHMGetHandle(pwnd
) );
384 pwnd
->head
.pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
390 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) break;
391 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
393 /* Exit on button-up, Return, or Esc */
394 if ((msg
.message
== WM_LBUTTONUP
) ||
395 ((msg
.message
== WM_KEYDOWN
) &&
396 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
398 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
400 IntTranslateKbdMessage( &msg
, 0 );
401 IntDispatchMessage( &msg
);
402 continue; /* We are not interested in other messages */
407 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
409 case VK_UP
: pt
.y
-= 8; break;
410 case VK_DOWN
: pt
.y
+= 8; break;
411 case VK_LEFT
: pt
.x
-= 8; break;
412 case VK_RIGHT
: pt
.x
+= 8; break;
415 pt
.x
= max( pt
.x
, mouseRect
.left
);
416 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
417 pt
.y
= max( pt
.y
, mouseRect
.top
);
418 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
420 dx
= pt
.x
- capturePoint
.x
;
421 dy
= pt
.y
- capturePoint
.y
;
428 if ( iconic
) /* ok, no system popup tracking */
430 OldCursor
= UserSetCursor(DragCursor
, FALSE
);
431 UserShowCursor( TRUE
);
433 else if(!DragFullWindows
)
434 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
437 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
440 RECT newRect
= unmodRect
;
442 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
443 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
444 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
445 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
446 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
447 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
451 // Save the new position to the unmodified rectangle. This allows explorer task bar
452 // sizing. Explorer will forces back the position unless a certain amount of sizing
457 /* determine the hit location */
458 if (syscommand
== SC_SIZE
)
460 WPARAM wpSizingHit
= 0;
462 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
463 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
464 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
467 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
471 if (!DragFullWindows
)
472 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
474 { // Moving the whole window now!
476 HRGN hrgnOrig
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
478 if (pwnd
->hrgnClip
!= NULL
)
479 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, pwnd
->hrgnClip
, RGN_AND
);
481 //// This causes the mdi child window to jump up when it is moved.
482 //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
483 co_WinPosSetWindowPos( pwnd
,
487 newRect
.right
- newRect
.left
,
488 newRect
.bottom
- newRect
.top
,
489 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
491 hrgnNew
= GreCreateRectRgnIndirect(&pwnd
->rcWindow
);
492 if (pwnd
->hrgnClip
!= NULL
)
493 NtGdiCombineRgn(hrgnNew
, hrgnNew
, pwnd
->hrgnClip
, RGN_AND
);
498 NtGdiCombineRgn(hrgnOrig
, hrgnOrig
, hrgnNew
, RGN_DIFF
);
504 GreDeleteObject(hrgnOrig
);
509 // Update all the windows after the move or size, including this window.
510 UpdateThreadWindows(UserGetDesktopWindow()->spwndChild
, pti
, hrgnOrig
);
512 if (hrgnOrig
) GreDeleteObject(hrgnOrig
);
513 if (hrgnNew
) GreDeleteObject(hrgnNew
);
516 sizingRect
= newRect
;
521 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
527 if ( moved
) /* restore cursors, show icon title later on */
529 UserShowCursor( FALSE
);
530 OldCursor
= UserSetCursor(OldCursor
, FALSE
);
533 /* It could be that the cursor was already changed while we were proceeding,
534 * so we must unreference whatever cursor was current at the time we restored the old one.
535 * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
537 if (OldCursor
) UserDereferenceObject(OldCursor
);
539 else if ( moved
&& !DragFullWindows
)
540 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
542 UserReleaseDC(NULL
, hdc
, FALSE
);
544 //// This causes the mdi child window to jump up when it is moved.
545 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
547 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
549 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
553 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
555 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
557 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
559 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
561 /* window moved or resized */
564 /* if the moving/resizing isn't canceled call SetWindowPos
565 * with the new position or the new size of the window
567 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
569 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
570 if (!DragFullWindows
|| iconic
)
572 co_WinPosSetWindowPos( pwnd
,
576 sizingRect
.right
- sizingRect
.left
,
577 sizingRect
.bottom
- sizingRect
.top
,
578 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
582 { /* restore previous size/position */
583 if ( DragFullWindows
)
585 co_WinPosSetWindowPos( pwnd
,
589 origRect
.right
- origRect
.left
,
590 origRect
.bottom
- origRect
.top
,
591 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
596 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
600 /* Single click brings up the system menu when iconized */
603 if( Style
& WS_SYSMENU
)
604 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
610 PCURICON_OBJECT FASTCALL
NC_IconForWindow( PWND pWnd
)
612 PCURICON_OBJECT pIcon
= NULL
;
615 //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
616 //FIXME: Hence we must return a pointer with no reference count.
617 //FIXME: This is bad and we should feel bad.
618 //FIXME: Stop whining over wine code.
620 hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
, TRUE
);
621 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
, TRUE
);
623 if (!hIcon
&& pWnd
->pcls
->spicnSm
)
624 return pWnd
->pcls
->spicnSm
;
625 if (!hIcon
&& pWnd
->pcls
->spicn
)
626 return pWnd
->pcls
->spicn
;
628 // WARNING: Wine code has this test completely wrong. The following is how
629 // Windows behaves for windows having the WS_EX_DLGMODALFRAME style set:
630 // it does not use the default icon! And it does not check for DS_MODALFRAME.
631 if (!hIcon
&& !(pWnd
->ExStyle
& WS_EX_DLGMODALFRAME
))
633 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
634 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
638 pIcon
= UserGetCurIconObject(hIcon
);
641 UserDereferenceObject(pIcon
);
648 UserDrawSysMenuButton(PWND pWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
650 PCURICON_OBJECT WindowIcon
;
653 if ((WindowIcon
= NC_IconForWindow(pWnd
)))
655 UserReferenceObject(WindowIcon
);
657 Ret
= UserDrawIconEx(hDC
,
661 UserGetSystemMetrics(SM_CXSMICON
),
662 UserGetSystemMetrics(SM_CYSMICON
),
665 UserDereferenceObject(WindowIcon
);
671 IntIsScrollBarVisible(PWND pWnd
, INT hBar
)
674 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
676 if(!co_IntGetScrollBarInfo(pWnd
, hBar
, &sbi
))
679 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
684 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
685 * wasting precious CPU cycles) every time
686 * - Center the buttons vertically in the rect
689 UserDrawCaptionButton(PWND pWnd
, LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
693 if (!(Style
& WS_SYSMENU
))
702 case DFCS_CAPTIONMIN
:
704 if (ExStyle
& WS_EX_TOOLWINDOW
)
705 return; /* ToolWindows don't have min/max buttons */
707 if (Style
& WS_SYSMENU
)
708 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
710 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
711 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) - 2;
713 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
714 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
718 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
719 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
720 (bDown
? DFCS_PUSHED
: 0) |
721 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
724 case DFCS_CAPTIONMAX
:
726 if (ExStyle
& WS_EX_TOOLWINDOW
)
727 return; /* ToolWindows don't have min/max buttons */
729 if (Style
& WS_SYSMENU
)
730 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
732 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
733 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
737 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
738 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
739 (bDown
? DFCS_PUSHED
: 0) |
740 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
743 case DFCS_CAPTIONCLOSE
:
745 PMENU pSysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
746 UINT MenuState
= IntGetMenuState(UserHMGetHandle(pSysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
748 /* A tool window has a smaller Close button */
749 if (ExStyle
& WS_EX_TOOLWINDOW
)
751 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSMSIZE
);
752 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMSIZE
) - 2;
756 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
);
757 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
762 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
763 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
764 ((!(MenuState
& (MF_GRAYED
|MF_DISABLED
)) && !(pWnd
->pcls
->style
& CS_NOCLOSE
)) ? 0 : DFCS_INACTIVE
)));
771 UserDrawCaptionButtonWnd(PWND pWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
776 IntGetWindowRect(pWnd
, &WindowRect
);
778 WindowRect
.right
-= WindowRect
.left
;
779 WindowRect
.bottom
-= WindowRect
.top
;
780 WindowRect
.left
= WindowRect
.top
= 0;
782 UserGetWindowBorders(pWnd
->style
, pWnd
->ExStyle
, &WindowBorder
, FALSE
);
784 RECTL_vInflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
786 UserDrawCaptionButton(pWnd
, &WindowRect
, pWnd
->style
, pWnd
->ExStyle
, hDC
, bDown
, Type
);
790 NC_DrawFrame( HDC hDC
, RECT
*CurrentRect
, BOOL Active
, DWORD Style
, DWORD ExStyle
)
792 /* Firstly the "thick" frame */
793 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
796 (UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
)) *
797 UserGetSystemMetrics(SM_CXBORDER
);
800 (UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
)) *
801 UserGetSystemMetrics(SM_CYBORDER
);
803 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
806 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
807 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
808 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
809 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
811 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
814 /* Now the other bit of the frame */
815 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
817 DWORD Width
= UserGetSystemMetrics(SM_CXBORDER
);
818 DWORD Height
= UserGetSystemMetrics(SM_CYBORDER
);
820 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(
821 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
822 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
823 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
827 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
828 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
829 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
830 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
832 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
836 VOID
UserDrawCaptionBar(
841 DWORD Style
, ExStyle
;
842 RECT WindowRect
, CurrentRect
, TempRect
;
844 BOOL Gradient
= FALSE
;
845 PCURICON_OBJECT pIcon
= NULL
;
847 if (!(Flags
& DC_NOVISIBLE
) && !IntIsWindowVisible(pWnd
)) return;
849 ERR("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd
, hDC
, Flags
);
852 ExStyle
= pWnd
->ExStyle
;
854 IntGetWindowRect(pWnd
, &WindowRect
);
856 CurrentRect
.top
= CurrentRect
.left
= 0;
857 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
858 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
860 /* Draw outer edge */
861 if (UserHasWindowEdge(Style
, ExStyle
))
863 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
865 else if (ExStyle
& WS_EX_STATICEDGE
)
868 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
870 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
871 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
872 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
874 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
875 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
876 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
878 RECTL_vInflateRect(&CurrentRect
, -1, -1);
882 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, (Flags
& DC_ACTIVE
), Style
, ExStyle
);
885 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
887 TempRect
= CurrentRect
;
889 Flags
|= DC_TEXT
|DC_BUTTONS
; // Icon will be checked if not already set.
891 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
893 Flags
|= DC_GRADIENT
;
896 if (ExStyle
& WS_EX_TOOLWINDOW
)
898 Flags
|= DC_SMALLCAP
;
899 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
900 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
904 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
905 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
908 if (!(Flags
& DC_ICON
) &&
909 !(Flags
& DC_SMALLCAP
) &&
910 (Style
& WS_SYSMENU
) &&
911 !(ExStyle
& WS_EX_TOOLWINDOW
) )
913 pIcon
= NC_IconForWindow(pWnd
); // Force redraw of caption with icon if DC_ICON not flaged....
915 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, pIcon
? UserHMGetHandle(pIcon
) : NULL
, NULL
, Flags
);
918 if (Style
& WS_SYSMENU
)
920 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
921 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
923 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
924 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
928 if (!(Style
& WS_MINIMIZE
))
930 /* Line under caption */
931 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
933 IntSetDCPenColor( hDC
, IntGetSysColor(((ExStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
934 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
936 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
938 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
940 NtGdiSelectPen(hDC
, PreviousPen
);
944 if (!(Style
& WS_MINIMIZE
))
947 if (HAS_MENU(pWnd
, Style
))
949 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &CurrentRect
, 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 (HAS_MENU(pWnd
, Style
))
1115 if (!(Flags
& DC_NOSENDMSG
))
1117 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &CurrentRect
, 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 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1958 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1960 if (ExStyle
& WS_EX_TOOLWINDOW
)
1961 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1963 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1964 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1966 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1967 if (ExStyle
& WS_EX_LAYOUTRTL
)
1969 /* Check system menu */
1970 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1972 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1973 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
1976 /* Check close button */
1977 if (Style
& WS_SYSMENU
)
1979 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
1980 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
1983 /* Check maximize box */
1984 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1985 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1987 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1988 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
1991 /* Check minimize box */
1992 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1994 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1995 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
2000 /* Check system menu */
2001 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
2003 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
2004 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
2007 /* Check close button */
2008 if (Style
& WS_SYSMENU
)
2010 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
2011 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
2014 /* Check maximize box */
2015 /* In Win95 there is automatically a Maximize button when there is a minimize one */
2016 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2018 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2019 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
2022 /* Check minimize box */
2023 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
2025 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
2026 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
2033 /* Check menu bar */
2035 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
2036 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
2039 /* Check vertical scroll bar */
2041 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
2042 if (Style
& WS_VSCROLL
)
2044 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
2045 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
2047 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
2048 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
2051 /* Check horizontal scroll bar */
2053 if (Style
& WS_HSCROLL
)
2055 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
2056 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
2058 /* Check size box */
2059 if ((Style
& WS_VSCROLL
) &&
2060 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
2061 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
2067 /* Has to return HTNOWHERE if nothing was found
2068 Could happen when a window has a customized non client area */