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).
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
));
92 if (UserHasDlgFrameStyle(Style
, ExStyle
))
94 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
95 /* FIXME: this isn't in NC_AdjustRect? why not? */
96 if (ExStyle
& WS_EX_DLGMODALFRAME
)
97 RECTL_vInflateRect( rect
, -1, 0 );
101 if (UserHasThinFrameStyle(Style
, ExStyle
))
103 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
107 /* We have additional border information if the window
108 * is a child (but not an MDI child) */
109 if ((Style
& WS_CHILD
) && !(ExStyle
& WS_EX_MDICHILD
))
111 if (ExStyle
& WS_EX_CLIENTEDGE
)
112 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
113 if (ExStyle
& WS_EX_STATICEDGE
)
114 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
118 /***********************************************************************
122 NC_GetSysPopupPos(PWND Wnd
, RECT
*Rect
)
126 if ((Wnd
->style
& WS_MINIMIZE
) != 0)
128 IntGetWindowRect(Wnd
, Rect
);
132 NC_GetInsideRect(Wnd
, Rect
);
133 IntGetWindowRect(Wnd
, &WindowRect
);
134 RECTL_vOffsetRect(Rect
, WindowRect
.left
, WindowRect
.top
);
135 if (Wnd
->style
& WS_CHILD
)
137 IntClientToScreen(IntGetParent(Wnd
), (POINT
*) Rect
);
139 Rect
->right
= Rect
->left
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
140 Rect
->bottom
= Rect
->top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
145 DefWndStartSizeMove(PWND Wnd
, WPARAM wParam
, POINT
*capturePoint
)
151 ULONG Style
= Wnd
->style
;
152 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
154 rectWindow
= Wnd
->rcWindow
;
156 if ((wParam
& 0xfff0) == SC_MOVE
)
158 /* Move pointer at the center of the caption */
159 RECT rect
= rectWindow
;
160 /* Note: to be exactly centered we should take the different types
161 * of border into account, but it shouldn't make more than a few pixels
162 * of difference so let's not bother with that */
163 if (Style
& WS_SYSMENU
)
164 rect
.left
+= UserGetSystemMetrics(SM_CXSIZE
) + 1;
165 if (Style
& WS_MINIMIZEBOX
)
166 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
167 if (Style
& WS_MAXIMIZEBOX
)
168 rect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
169 pt
.x
= (rect
.right
+ rect
.left
) / 2;
170 pt
.y
= rect
.top
+ UserGetSystemMetrics(SM_CYSIZE
)/2;
179 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) return 0;
180 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
185 //// Clamp the mouse position to the window rectangle when starting a window resize.
186 pt
.x
= min( max( msg
.pt
.x
, rectWindow
.left
), rectWindow
.right
- 1 );
187 pt
.y
= min( max( msg
.pt
.y
, rectWindow
.top
), rectWindow
.bottom
- 1 );
188 hittest
= GetNCHitEx(Wnd
, pt
);
189 if ((hittest
< HTLEFT
) || (hittest
> HTBOTTOMRIGHT
)) hittest
= 0;
200 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
201 pt
.y
= rectWindow
.top
+ UserGetSystemMetrics(SM_CYFRAME
) / 2;
205 pt
.x
= (rectWindow
.left
+rectWindow
.right
)/2;
206 pt
.y
= rectWindow
.bottom
- UserGetSystemMetrics(SM_CYFRAME
) / 2;
210 pt
.x
= rectWindow
.left
+ UserGetSystemMetrics(SM_CXFRAME
) / 2;
211 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
215 pt
.x
= rectWindow
.right
- UserGetSystemMetrics(SM_CXFRAME
) / 2;
216 pt
.y
= (rectWindow
.top
+rectWindow
.bottom
)/2;
223 IntTranslateKbdMessage( &msg
, 0 );
224 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
225 IntDispatchMessage( &msg
);
226 pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
232 UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
233 co_IntSendMessage(UserHMGetHandle(Wnd
), WM_SETCURSOR
, (WPARAM
)UserHMGetHandle(Wnd
), MAKELONG(hittest
, WM_MOUSEMOVE
));
238 // System Command Size and Move
240 // Perform SC_MOVE and SC_SIZE commands.
243 DefWndDoSizeMove(PWND pwnd
, WORD wParam
)
246 RECT sizingRect
, mouseRect
, origRect
, unmodRect
;
248 LONG hittest
= (LONG
)(wParam
& 0x0f);
249 PCURICON_OBJECT DragCursor
= NULL
, OldCursor
= NULL
;
250 POINT minTrack
, maxTrack
;
251 POINT capturePoint
, pt
;
252 ULONG Style
, ExStyle
;
256 BOOL DragFullWindows
= FALSE
;
257 PWND pWndParent
= NULL
;
258 WPARAM syscommand
= (wParam
& 0xfff0);
259 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
260 //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
261 // The task bar can grow in size and can not reduce due to the change
265 ExStyle
= pwnd
->ExStyle
;
266 iconic
= (Style
& WS_MINIMIZE
) != 0;
268 if ((Style
& WS_MAXIMIZE
) || !IntIsWindowVisible(pwnd
)) return;
270 thickframe
= UserHasThickFrameStyle(Style
, ExStyle
) && !iconic
;
273 // Show window contents while dragging the window, get flag from registry data.
275 UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &DragFullWindows
, 0);
277 pt
.x
= pti
->ptLast
.x
;
278 pt
.y
= pti
->ptLast
.y
;
280 UserClipCursor( NULL
);
282 TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
283 pwnd
, syscommand
, hittest
, pt
.x
, pt
.y
);
285 if (syscommand
== SC_MOVE
)
287 if (!hittest
) hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
288 if (!hittest
) return;
292 if (!thickframe
) return;
293 if (hittest
&& (syscommand
!= SC_MOUSEMENU
))
295 hittest
+= (HTLEFT
- WMSZ_LEFT
);
299 co_UserSetCapture(UserHMGetHandle(pwnd
));
300 hittest
= DefWndStartSizeMove(pwnd
, wParam
, &capturePoint
);
309 /* Get min/max info */
311 co_WinPosGetMinMaxInfo(pwnd
, NULL
, NULL
, &minTrack
, &maxTrack
);
312 sizingRect
= pwnd
->rcWindow
;
313 origRect
= sizingRect
;
314 if (Style
& WS_CHILD
)
316 pWndParent
= IntGetParent(pwnd
);
317 IntGetClientRect( pWndParent
, &mouseRect
);
318 IntMapWindowPoints( pWndParent
, 0, (LPPOINT
)&mouseRect
, 2 );
319 IntMapWindowPoints( 0, pWndParent
, (LPPOINT
)&sizingRect
, 2 );
320 unmodRect
= sizingRect
;
324 if (!(ExStyle
& WS_EX_TOPMOST
))
326 UserSystemParametersInfo(SPI_GETWORKAREA
, 0, &mouseRect
, 0);
330 RECTL_vSetRect(&mouseRect
, 0, 0, UserGetSystemMetrics(SM_CXSCREEN
), UserGetSystemMetrics(SM_CYSCREEN
));
332 unmodRect
= sizingRect
;
335 if (ON_LEFT_BORDER(hittest
))
337 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.right
-maxTrack
.x
+capturePoint
.x
-sizingRect
.left
);
338 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.right
-minTrack
.x
+capturePoint
.x
-sizingRect
.left
);
340 else if (ON_RIGHT_BORDER(hittest
))
342 mouseRect
.left
= max( mouseRect
.left
, sizingRect
.left
+minTrack
.x
+capturePoint
.x
-sizingRect
.right
);
343 mouseRect
.right
= min( mouseRect
.right
, sizingRect
.left
+maxTrack
.x
+capturePoint
.x
-sizingRect
.right
);
345 if (ON_TOP_BORDER(hittest
))
347 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.bottom
-maxTrack
.y
+capturePoint
.y
-sizingRect
.top
);
348 mouseRect
.bottom
= min( mouseRect
.bottom
,sizingRect
.bottom
-minTrack
.y
+capturePoint
.y
-sizingRect
.top
);
350 else if (ON_BOTTOM_BORDER(hittest
))
352 mouseRect
.top
= max( mouseRect
.top
, sizingRect
.top
+minTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
353 mouseRect
.bottom
= min( mouseRect
.bottom
, sizingRect
.top
+maxTrack
.y
+capturePoint
.y
-sizingRect
.bottom
);
356 hdc
= UserGetDCEx( pWndParent
, 0, DCX_CACHE
);
359 DragCursor
= pwnd
->pcls
->spicn
;
362 UserReferenceObject(DragCursor
);
366 HCURSOR CursorHandle
= (HCURSOR
)co_IntSendMessage( UserHMGetHandle(pwnd
), WM_QUERYDRAGICON
, 0, 0 );
369 DragCursor
= UserGetCurIconObject(CursorHandle
);
378 /* repaint the window before moving it around */
379 co_UserRedrawWindow( pwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
381 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
383 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_ENTERSIZEMOVE
, 0, 0 );
385 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, UserHMGetHandle(pwnd
));
387 if (IntGetCapture() != UserHMGetHandle(pwnd
)) co_UserSetCapture( UserHMGetHandle(pwnd
) );
389 pwnd
->head
.pti
->TIF_flags
|= TIF_MOVESIZETRACKING
;
395 if (!co_IntGetPeekMessage(&msg
, 0, 0, 0, PM_REMOVE
, TRUE
)) break;
396 if (IntCallMsgFilter( &msg
, MSGF_SIZE
)) continue;
398 /* Exit on button-up, Return, or Esc */
399 if ((msg
.message
== WM_LBUTTONUP
) ||
400 ((msg
.message
== WM_KEYDOWN
) &&
401 ((msg
.wParam
== VK_RETURN
) || (msg
.wParam
== VK_ESCAPE
)))) break;
403 if ((msg
.message
!= WM_KEYDOWN
) && (msg
.message
!= WM_MOUSEMOVE
))
405 IntTranslateKbdMessage( &msg
, 0 );
406 IntDispatchMessage( &msg
);
407 continue; /* We are not interested in other messages */
412 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
414 case VK_UP
: pt
.y
-= 8; break;
415 case VK_DOWN
: pt
.y
+= 8; break;
416 case VK_LEFT
: pt
.x
-= 8; break;
417 case VK_RIGHT
: pt
.x
+= 8; break;
420 pt
.x
= max( pt
.x
, mouseRect
.left
);
421 pt
.x
= min( pt
.x
, mouseRect
.right
- 1 );
422 pt
.y
= max( pt
.y
, mouseRect
.top
);
423 pt
.y
= min( pt
.y
, mouseRect
.bottom
- 1 );
425 dx
= pt
.x
- capturePoint
.x
;
426 dy
= pt
.y
- capturePoint
.y
;
433 if ( iconic
) /* ok, no system popup tracking */
435 OldCursor
= UserSetCursor(DragCursor
, FALSE
);
436 UserShowCursor( TRUE
);
438 else if(!DragFullWindows
)
439 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
442 if (msg
.message
== WM_KEYDOWN
) UserSetCursorPos(pt
.x
, pt
.y
, 0, 0, FALSE
);
445 RECT newRect
= unmodRect
;
447 if (!iconic
&& !DragFullWindows
) UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
448 if (hittest
== HTCAPTION
) RECTL_vOffsetRect( &newRect
, dx
, dy
);
449 if (ON_LEFT_BORDER(hittest
)) newRect
.left
+= dx
;
450 else if (ON_RIGHT_BORDER(hittest
)) newRect
.right
+= dx
;
451 if (ON_TOP_BORDER(hittest
)) newRect
.top
+= dy
;
452 else if (ON_BOTTOM_BORDER(hittest
)) newRect
.bottom
+= dy
;
456 // Save the new position to the unmodified rectangle. This allows explorer task bar
457 // sizing. Explorer will forces back the position unless a certain amount of sizing
462 /* determine the hit location */
463 if (syscommand
== SC_SIZE
)
465 WPARAM wpSizingHit
= 0;
467 if (hittest
>= HTLEFT
&& hittest
<= HTBOTTOMRIGHT
)
468 wpSizingHit
= WMSZ_LEFT
+ (hittest
- HTLEFT
);
469 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SIZING
, wpSizingHit
, (LPARAM
)&newRect
);
472 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_MOVING
, 0, (LPARAM
)&newRect
);
476 if (!DragFullWindows
)
477 UserDrawMovingFrame( hdc
, &newRect
, thickframe
);
479 { // Moving the whole window now!
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 // Update all the windows after the move or size, including this window.
492 for ( pwndTemp
= pwnd
->head
.rpdesk
->pDeskInfo
->spwnd
->spwndChild
;
494 pwndTemp
= pwndTemp
->spwndNext
)
497 // Only the windows that overlap will be redrawn.
498 if (RECTL_bIntersectRect( &rect
, &pwnd
->rcWindow
, &pwndTemp
->rcWindow
))
500 co_UserRedrawWindow( pwndTemp
, NULL
, NULL
, RDW_UPDATENOW
| RDW_NOCHILDREN
);
505 sizingRect
= newRect
;
510 pwnd
->head
.pti
->TIF_flags
&= ~TIF_MOVESIZETRACKING
;
516 if ( moved
) /* restore cursors, show icon title later on */
518 UserShowCursor( FALSE
);
519 OldCursor
= UserSetCursor(OldCursor
, FALSE
);
522 /* It could be that the cursor was already changed while we were proceeding,
523 * so we must unreference whatever cursor was current at the time we restored the old one.
524 * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
526 if (OldCursor
) UserDereferenceObject(OldCursor
);
528 else if ( moved
&& !DragFullWindows
)
529 UserDrawMovingFrame( hdc
, &sizingRect
, thickframe
);
531 UserReleaseDC(NULL
, hdc
, FALSE
);
533 //// This causes the mdi child window to jump up when it is moved.
534 //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
536 if (co_HOOK_CallHooks(WH_CBT
, HCBT_MOVESIZE
, (WPARAM
)UserHMGetHandle(pwnd
), (LPARAM
)&sizingRect
))
538 ERR("DoSizeMove : WH_CBT Call Hook return!\n");
542 IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND
, pwnd
, OBJID_WINDOW
, CHILDID_SELF
, 0);
544 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
546 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_EXITSIZEMOVE
, 0, 0 );
548 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SETVISIBLE
, !!(pwnd
->style
& WS_MINIMIZE
), 0L);
550 /* window moved or resized */
553 /* if the moving/resizing isn't canceled call SetWindowPos
554 * with the new position or the new size of the window
556 if (!((msg
.message
== WM_KEYDOWN
) && (msg
.wParam
== VK_ESCAPE
)) )
558 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
559 if (!DragFullWindows
|| iconic
)
561 co_WinPosSetWindowPos( pwnd
,
565 sizingRect
.right
- sizingRect
.left
,
566 sizingRect
.bottom
- sizingRect
.top
,
567 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
571 { /* restore previous size/position */
572 if ( DragFullWindows
)
574 co_WinPosSetWindowPos( pwnd
,
578 origRect
.right
- origRect
.left
,
579 origRect
.bottom
- origRect
.top
,
580 ( hittest
== HTCAPTION
) ? SWP_NOSIZE
: 0 );
585 if ( IntIsWindow(UserHMGetHandle(pwnd
)) )
589 /* Single click brings up the system menu when iconized */
592 if( Style
& WS_SYSMENU
)
593 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, MAKELONG(pt
.x
,pt
.y
));
599 PCURICON_OBJECT FASTCALL
NC_IconForWindow( PWND pWnd
)
601 PCURICON_OBJECT pIcon
= NULL
;
604 //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
605 //FIXME: Hence we must return a pointer with no reference count.
606 //FIXME: This is bad and we should feel bad.
607 //FIXME: Stop whining over wine code.
609 hIcon
= UserGetProp(pWnd
, gpsi
->atomIconSmProp
);
610 if (!hIcon
) hIcon
= UserGetProp(pWnd
, gpsi
->atomIconProp
);
612 if (!hIcon
&& pWnd
->pcls
->spicnSm
)
613 return pWnd
->pcls
->spicnSm
;
614 if (!hIcon
&& pWnd
->pcls
->spicn
)
615 return pWnd
->pcls
->spicn
;
617 if (!hIcon
&& (pWnd
->style
& DS_MODALFRAME
))
619 if (!hIcon
) hIcon
= gpsi
->hIconSmWindows
; // Both are IDI_WINLOGO Small
620 if (!hIcon
) hIcon
= gpsi
->hIconWindows
; // Reg size.
624 pIcon
= UserGetCurIconObject(hIcon
);
627 UserDereferenceObject(pIcon
);
634 UserDrawSysMenuButton(PWND pWnd
, HDC hDC
, LPRECT Rect
, BOOL Down
)
636 PCURICON_OBJECT WindowIcon
;
639 if ((WindowIcon
= NC_IconForWindow(pWnd
)))
641 UserReferenceObject(WindowIcon
);
643 Ret
= UserDrawIconEx( hDC
,
647 UserGetSystemMetrics(SM_CXSMICON
),
648 UserGetSystemMetrics(SM_CYSMICON
),
651 UserDereferenceObject(WindowIcon
);
657 UserGetInsideRectNC(PWND Wnd
, RECT
*rect
)
663 ExStyle
= Wnd
->ExStyle
;
665 rect
->top
= rect
->left
= 0;
666 rect
->right
= Wnd
->rcWindow
.right
- Wnd
->rcWindow
.left
;
667 rect
->bottom
= Wnd
->rcWindow
.bottom
- Wnd
->rcWindow
.top
;
669 if (Style
& WS_ICONIC
)
674 /* Remove frame from rectangle */
675 if (UserHasThickFrameStyle(Style
, ExStyle
))
677 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
));
681 if (UserHasDlgFrameStyle(Style
, ExStyle
))
683 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
684 /* FIXME: this isn't in NC_AdjustRect? why not? */
685 if (ExStyle
& WS_EX_DLGMODALFRAME
)
686 RECTL_vInflateRect( rect
, -1, 0 );
690 if (UserHasThinFrameStyle(Style
, ExStyle
))
692 RECTL_vInflateRect(rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
696 /* We have additional border information if the window
697 * is a child (but not an MDI child) */
698 if ((Style
& WS_CHILD
) && !(ExStyle
& WS_EX_MDICHILD
))
700 if (ExStyle
& WS_EX_CLIENTEDGE
)
701 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXEDGE
), -UserGetSystemMetrics(SM_CYEDGE
));
702 if (ExStyle
& WS_EX_STATICEDGE
)
703 RECTL_vInflateRect (rect
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
708 IntIsScrollBarVisible(PWND pWnd
, INT hBar
)
711 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
713 if(!co_IntGetScrollBarInfo(pWnd
, hBar
, &sbi
))
716 return !(sbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
);
720 UserHasMenu(PWND pWnd
, ULONG Style
)
722 return (!(Style
& WS_CHILD
) && UlongToHandle(pWnd
->IDMenu
) != 0);
727 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
728 * wasting precious CPU cycles) every time
729 * - Center the buttons verticaly in the rect
732 UserDrawCaptionButton(PWND pWnd
, LPRECT Rect
, DWORD Style
, DWORD ExStyle
, HDC hDC
, BOOL bDown
, ULONG Type
)
736 if (!(Style
& WS_SYSMENU
))
745 case DFCS_CAPTIONMIN
:
747 if (ExStyle
& WS_EX_TOOLWINDOW
)
748 return; /* ToolWindows don't have min/max buttons */
750 if (Style
& WS_SYSMENU
)
751 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
753 if (Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
))
754 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) - 2;
756 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
757 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
761 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
762 ((Style
& WS_MINIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMIN
) |
763 (bDown
? DFCS_PUSHED
: 0) |
764 ((Style
& WS_MINIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
767 case DFCS_CAPTIONMAX
:
769 if (ExStyle
& WS_EX_TOOLWINDOW
)
770 return; /* ToolWindows don't have min/max buttons */
772 if (Style
& WS_SYSMENU
)
773 TempRect
.right
-= UserGetSystemMetrics(SM_CXSIZE
) + 1;
775 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
) + 1;
776 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
780 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
781 ((Style
& WS_MAXIMIZE
) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX
) |
782 (bDown
? DFCS_PUSHED
: 0) |
783 ((Style
& WS_MAXIMIZEBOX
) ? 0 : DFCS_INACTIVE
));
786 case DFCS_CAPTIONCLOSE
:
788 PMENU pSysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
789 UINT MenuState
= IntGetMenuState(UserHMGetHandle(pSysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
791 /* FIXME: A tool window has a smaller Close button */
793 if (ExStyle
& WS_EX_TOOLWINDOW
)
795 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSMSIZE
);
796 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMSIZE
) - 2;
800 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXSIZE
);
801 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSIZE
) - 2;
806 DrawFrameControl(hDC
, &TempRect
, DFC_CAPTION
,
807 (DFCS_CAPTIONCLOSE
| (bDown
? DFCS_PUSHED
: 0) |
808 ((!(MenuState
& (MF_GRAYED
|MF_DISABLED
)) && !(pWnd
->pcls
->style
& CS_NOCLOSE
)) ? 0 : DFCS_INACTIVE
)));
815 UserDrawCaptionButtonWnd(PWND pWnd
, HDC hDC
, BOOL bDown
, ULONG Type
)
820 IntGetWindowRect(pWnd
, &WindowRect
);
822 WindowRect
.right
-= WindowRect
.left
;
823 WindowRect
.bottom
-= WindowRect
.top
;
824 WindowRect
.left
= WindowRect
.top
= 0;
826 UserGetWindowBorders(pWnd
->style
, pWnd
->ExStyle
, &WindowBorder
, FALSE
);
828 RECTL_vInflateRect(&WindowRect
, -WindowBorder
.cx
, -WindowBorder
.cy
);
830 UserDrawCaptionButton(pWnd
, &WindowRect
, pWnd
->style
, pWnd
->ExStyle
, hDC
, bDown
, Type
);
834 NC_DrawFrame( HDC hDC
, RECT
*CurrentRect
, BOOL Active
, DWORD Style
, DWORD ExStyle
)
836 /* Firstly the "thick" frame */
837 if ((Style
& WS_THICKFRAME
) && !(Style
& WS_MINIMIZE
))
840 (UserGetSystemMetrics(SM_CXFRAME
) - UserGetSystemMetrics(SM_CXDLGFRAME
)) *
841 UserGetSystemMetrics(SM_CXBORDER
);
844 (UserGetSystemMetrics(SM_CYFRAME
) - UserGetSystemMetrics(SM_CYDLGFRAME
)) *
845 UserGetSystemMetrics(SM_CYBORDER
);
847 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(Active
? COLOR_ACTIVEBORDER
: COLOR_INACTIVEBORDER
));
850 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
851 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
852 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
853 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
855 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
858 /* Now the other bit of the frame */
859 if (Style
& (WS_DLGFRAME
| WS_BORDER
) || ExStyle
& WS_EX_DLGMODALFRAME
)
861 DWORD Width
= UserGetSystemMetrics(SM_CXBORDER
);
862 DWORD Height
= UserGetSystemMetrics(SM_CYBORDER
);
864 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(
865 (ExStyle
& (WS_EX_DLGMODALFRAME
| WS_EX_CLIENTEDGE
)) ? COLOR_3DFACE
:
866 (ExStyle
& WS_EX_STATICEDGE
) ? COLOR_WINDOWFRAME
:
867 (Style
& (WS_DLGFRAME
| WS_THICKFRAME
)) ? COLOR_3DFACE
:
871 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, CurrentRect
->right
- CurrentRect
->left
, Height
, PATCOPY
);
872 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->top
, Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
873 NtGdiPatBlt(hDC
, CurrentRect
->left
, CurrentRect
->bottom
- 1, CurrentRect
->right
- CurrentRect
->left
, -Height
, PATCOPY
);
874 NtGdiPatBlt(hDC
, CurrentRect
->right
- 1, CurrentRect
->top
, -Width
, CurrentRect
->bottom
- CurrentRect
->top
, PATCOPY
);
876 RECTL_vInflateRect(CurrentRect
, -Width
, -Height
);
880 VOID
UserDrawCaptionBar(
885 DWORD Style
, ExStyle
;
886 RECT WindowRect
, CurrentRect
, TempRect
;
888 BOOL Gradient
= FALSE
;
889 PCURICON_OBJECT pIcon
= NULL
;
891 if (!(Flags
& DC_NOVISIBLE
) && !IntIsWindowVisible(pWnd
)) return;
893 ERR("UserDrawCaptionBar: pWnd %p, hDc %p, Flags 0x%x.\n", pWnd
, hDC
, Flags
);
896 ExStyle
= pWnd
->ExStyle
;
898 IntGetWindowRect(pWnd
, &WindowRect
);
900 CurrentRect
.top
= CurrentRect
.left
= 0;
901 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
902 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
904 /* Draw outer edge */
905 if (UserHasWindowEdge(Style
, ExStyle
))
907 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
909 else if (ExStyle
& WS_EX_STATICEDGE
)
912 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
914 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
915 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
916 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
918 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
919 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
920 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
922 RECTL_vInflateRect(&CurrentRect
, -1, -1);
926 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, (Flags
& DC_ACTIVE
), Style
, ExStyle
);
929 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
931 TempRect
= CurrentRect
;
933 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
935 Flags
|= DC_GRADIENT
;
938 if (ExStyle
& WS_EX_TOOLWINDOW
)
940 Flags
|= DC_SMALLCAP
;
941 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
942 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
946 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
947 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
950 if (!(Flags
& DC_ICON
) &&
951 (Style
& WS_SYSMENU
) &&
952 !(Flags
& DC_SMALLCAP
) &&
953 !(ExStyle
& WS_EX_DLGMODALFRAME
) &&
954 !(ExStyle
& WS_EX_TOOLWINDOW
) )
956 pIcon
= NC_IconForWindow(pWnd
); // Force redraw of caption with icon if DC_ICON not flaged....
958 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, pIcon
? UserHMGetHandle(pIcon
) : NULL
, NULL
, Flags
);
961 if (Style
& WS_SYSMENU
)
963 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
964 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
966 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
967 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
971 if (!(Style
& WS_MINIMIZE
))
973 /* Line under caption */
974 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
976 IntSetDCPenColor( hDC
, IntGetSysColor(((ExStyle
& (WS_EX_STATICEDGE
|WS_EX_CLIENTEDGE
|WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
977 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
979 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
981 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
983 NtGdiSelectPen(hDC
, PreviousPen
);
987 if (!(Style
& WS_MINIMIZE
))
989 if (ExStyle
& WS_EX_CLIENTEDGE
)
991 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
997 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
998 the call to GetDCEx implying that it is allowed not to use it either.
999 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
1000 will cause clipRgn to be deleted after ReleaseDC().
1001 Now, how is the "system" supposed to tell what happened?
1005 * - Drawing of WS_BORDER after scrollbars
1006 * - Correct drawing of size-box
1009 NC_DoNCPaint(PWND pWnd
, HDC hDC
, INT Flags
)
1011 DWORD Style
, ExStyle
;
1013 RECT WindowRect
, CurrentRect
, TempRect
;
1014 BOOL Active
= FALSE
;
1015 PCURICON_OBJECT pIcon
= NULL
;
1017 if (!IntIsWindowVisible(pWnd
) ||
1018 (pWnd
->state
& WNDS_NONCPAINT
&& !(pWnd
->state
& WNDS_FORCEMENUDRAW
)) ||
1019 IntEqualRect(&pWnd
->rcWindow
, &pWnd
->rcClient
) )
1022 Style
= pWnd
->style
;
1024 TRACE("DefWndNCPaint: pWnd %p, hDc %p, Active %s.\n", pWnd
, hDC
, Flags
& DC_ACTIVE
? "TRUE" : "FALSE");
1026 Parent
= IntGetParent(pWnd
);
1027 ExStyle
= pWnd
->ExStyle
;
1029 if (Flags
== -1) // NC paint mode.
1031 if (ExStyle
& WS_EX_MDICHILD
)
1033 Active
= IntIsChildWindow(gpqForeground
->spwndActive
, pWnd
);
1036 Active
= (UserHMGetHandle(pWnd
) == (HWND
)co_IntSendMessage(UserHMGetHandle(Parent
), WM_MDIGETACTIVE
, 0, 0));
1040 Active
= (gpqForeground
== pWnd
->head
.pti
->MessageQueue
);
1045 IntGetWindowRect(pWnd
, &WindowRect
);
1047 CurrentRect
.top
= CurrentRect
.left
= 0;
1048 CurrentRect
.right
= WindowRect
.right
- WindowRect
.left
;
1049 CurrentRect
.bottom
= WindowRect
.bottom
- WindowRect
.top
;
1051 /* Draw outer edge */
1052 if (UserHasWindowEdge(pWnd
->style
, pWnd
->ExStyle
))
1054 DrawEdge(hDC
, &CurrentRect
, EDGE_RAISED
, BF_RECT
| BF_ADJUST
);
1056 else if (pWnd
->ExStyle
& WS_EX_STATICEDGE
)
1059 DrawEdge(hDC
, &CurrentRect
, BDR_SUNKENINNER
, BF_RECT
| BF_ADJUST
| BF_FLAT
);
1061 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNSHADOW
));
1062 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1063 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1065 NtGdiSelectBrush(hDC
, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT
));
1066 NtGdiPatBlt(hDC
, CurrentRect
.left
, CurrentRect
.bottom
- 1, CurrentRect
.right
- CurrentRect
.left
, 1, PATCOPY
);
1067 NtGdiPatBlt(hDC
, CurrentRect
.right
- 1, CurrentRect
.top
, 1, CurrentRect
.bottom
- CurrentRect
.top
, PATCOPY
);
1069 RECTL_vInflateRect(&CurrentRect
, -1, -1);
1073 if (Flags
& DC_FRAME
) NC_DrawFrame(hDC
, &CurrentRect
, Active
? Active
: (Flags
& DC_ACTIVE
), Style
, ExStyle
);
1076 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1079 BOOL Gradient
= FALSE
;
1081 if (Flags
& DC_REDRAWHUNGWND
)
1083 Flags
&= ~DC_REDRAWHUNGWND
;
1084 Flags
|= DC_NOSENDMSG
;
1087 if (UserSystemParametersInfo(SPI_GETGRADIENTCAPTIONS
, 0, &Gradient
, 0) && Gradient
)
1089 Flags
|= DC_GRADIENT
;
1094 if (!(pWnd
->state
& WNDS_ACTIVEFRAME
))
1096 ERR("Wnd is active and not set active!\n");
1101 TempRect
= CurrentRect
;
1103 if (ExStyle
& WS_EX_TOOLWINDOW
)
1105 Flags
|= DC_SMALLCAP
;
1106 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1107 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1111 TempRect
.bottom
= TempRect
.top
+ UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1112 CurrentRect
.top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1115 if (!(Flags
& DC_ICON
) &&
1116 (Style
& WS_SYSMENU
) &&
1117 !(Flags
& DC_SMALLCAP
) &&
1118 !(ExStyle
& WS_EX_DLGMODALFRAME
) &&
1119 !(ExStyle
& WS_EX_TOOLWINDOW
) )
1121 pIcon
= NC_IconForWindow(pWnd
); // Force redraw of caption with icon if DC_ICON not flaged....
1123 UserDrawCaption(pWnd
, hDC
, &TempRect
, NULL
, pIcon
? UserHMGetHandle(pIcon
) : NULL
, NULL
, Flags
);
1126 if (Style
& WS_SYSMENU
)
1128 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONCLOSE
);
1129 if ((Style
& (WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
)) && !(ExStyle
& WS_EX_TOOLWINDOW
))
1131 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMIN
);
1132 UserDrawCaptionButton(pWnd
, &TempRect
, Style
, ExStyle
, hDC
, FALSE
, DFCS_CAPTIONMAX
);
1135 if (!(Style
& WS_MINIMIZE
))
1137 /* Line under caption */
1138 PreviousPen
= NtGdiSelectPen(hDC
, NtGdiGetStockObject(DC_PEN
));
1140 IntSetDCPenColor( hDC
, IntGetSysColor(
1141 ((ExStyle
& (WS_EX_STATICEDGE
| WS_EX_CLIENTEDGE
| WS_EX_DLGMODALFRAME
)) == WS_EX_STATICEDGE
) ?
1142 COLOR_WINDOWFRAME
: COLOR_3DFACE
));
1144 GreMoveTo(hDC
, TempRect
.left
, TempRect
.bottom
, NULL
);
1146 NtGdiLineTo(hDC
, TempRect
.right
, TempRect
.bottom
);
1148 NtGdiSelectPen(hDC
, PreviousPen
);
1152 if (!(Style
& WS_MINIMIZE
))
1154 PMENU menu
= UserGetMenuObject(UlongToHandle(pWnd
->IDMenu
));
1156 if (menu
&& !(Style
& WS_CHILD
))
1158 TempRect
= CurrentRect
;
1159 TempRect
.bottom
= TempRect
.top
+ menu
->cyMenu
;
1160 CurrentRect
.top
+= MENU_DrawMenuBar(hDC
, &TempRect
, pWnd
, FALSE
);
1163 if (ExStyle
& WS_EX_CLIENTEDGE
)
1165 DrawEdge(hDC
, &CurrentRect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1168 /* Draw the scrollbars */
1169 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
) &&
1170 IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
) && IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1172 RECT ParentClientRect
;
1174 TempRect
= CurrentRect
;
1176 if (ExStyle
& WS_EX_LEFTSCROLLBAR
)
1177 TempRect
.right
= TempRect
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
);
1179 TempRect
.left
= TempRect
.right
- UserGetSystemMetrics(SM_CXVSCROLL
);
1181 TempRect
.top
= TempRect
.bottom
- UserGetSystemMetrics(SM_CYHSCROLL
);
1183 FillRect(hDC
, &TempRect
, IntGetSysColorBrush(COLOR_BTNFACE
));
1186 IntGetClientRect(Parent
, &ParentClientRect
);
1188 if (HASSIZEGRIP(Style
, ExStyle
, Parent
->style
, WindowRect
, ParentClientRect
))
1190 DrawFrameControl(hDC
, &TempRect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
1193 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1194 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1198 if (Style
& WS_VSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_VSCROLL
))
1200 IntDrawScrollBar(pWnd
, hDC
, SB_VERT
);
1202 else if (Style
& WS_HSCROLL
&& IntIsScrollBarVisible(pWnd
, OBJID_HSCROLL
))
1204 IntDrawScrollBar(pWnd
, hDC
, SB_HORZ
);
1208 return 0; // For WM_NCPAINT message, return 0.
1211 LRESULT
NC_HandleNCCalcSize( PWND Wnd
, WPARAM wparam
, RECTL
*Rect
)
1216 DWORD Style
= Wnd
->style
;
1224 Wnd
->state
&= ~WNDS_HASCAPTION
;
1228 if (Wnd
->pcls
->style
& CS_VREDRAW
)
1230 Result
|= WVR_VREDRAW
;
1232 if (Wnd
->pcls
->style
& CS_HREDRAW
)
1234 Result
|= WVR_HREDRAW
;
1236 Result
|= WVR_VALIDRECTS
;
1239 if (!(Wnd
->style
& WS_MINIMIZE
))
1241 if (UserHasWindowEdge(Wnd
->style
, Wnd
->ExStyle
))
1243 UserGetWindowBorders(Wnd
->style
, Wnd
->ExStyle
, &WindowBorders
, FALSE
);
1244 RECTL_vInflateRect(Rect
, -WindowBorders
.cx
, -WindowBorders
.cy
);
1246 else if ((Wnd
->ExStyle
& WS_EX_STATICEDGE
) || (Wnd
->style
& WS_BORDER
))
1248 RECTL_vInflateRect(Rect
, -1, -1);
1251 if ((Wnd
->style
& WS_CAPTION
) == WS_CAPTION
)
1253 Wnd
->state
|= WNDS_HASCAPTION
;
1255 if (Wnd
->ExStyle
& WS_EX_TOOLWINDOW
)
1256 Rect
->top
+= UserGetSystemMetrics(SM_CYSMCAPTION
);
1258 Rect
->top
+= UserGetSystemMetrics(SM_CYCAPTION
);
1261 if (Wnd
->IDMenu
&& ((Wnd
->style
& (WS_CHILD
| WS_POPUP
)) != WS_CHILD
))
1263 HDC hDC
= UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
1265 Wnd
->state
|= WNDS_HASMENU
;
1269 RECT CliRect
= *Rect
;
1270 CliRect
.bottom
-= OrigRect
.top
;
1271 CliRect
.right
-= OrigRect
.left
;
1272 CliRect
.left
-= OrigRect
.left
;
1273 CliRect
.top
-= OrigRect
.top
;
1274 Rect
->top
+= MENU_DrawMenuBar(hDC
, &CliRect
, Wnd
, TRUE
);
1275 UserReleaseDC(Wnd
, hDC
, FALSE
);
1279 if (Wnd
->ExStyle
& WS_EX_CLIENTEDGE
)
1281 RECTL_vInflateRect(Rect
, -2 * UserGetSystemMetrics(SM_CXBORDER
), -2 * UserGetSystemMetrics(SM_CYBORDER
));
1284 if (Wnd
->style
& (WS_VSCROLL
| WS_HSCROLL
))
1287 SETSCROLLBARINFO ssbi
;
1289 sbi
.cbSize
= sizeof(SCROLLBARINFO
);
1290 if ((Style
& WS_VSCROLL
) && co_IntGetScrollBarInfo(Wnd
, OBJID_VSCROLL
, &sbi
))
1293 LONG sx
= Rect
->right
;
1295 Wnd
->state
|= WNDS_HASVERTICALSCROOLLBAR
;
1297 sx
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1299 for (i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
1300 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
1302 if (sx
<= Rect
->left
)
1303 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
1305 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
1307 co_IntSetScrollBarInfo(Wnd
, OBJID_VSCROLL
, &ssbi
);
1309 if (ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
1310 Style
&= ~WS_VSCROLL
;
1313 Style
&= ~WS_VSCROLL
;
1315 if ((Style
& WS_HSCROLL
) && co_IntGetScrollBarInfo(Wnd
, OBJID_HSCROLL
, &sbi
))
1318 LONG sy
= Rect
->bottom
;
1320 Wnd
->state
|= WNDS_HASHORIZONTALSCROLLBAR
;
1322 sy
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1324 for (i
= 0; i
<= CCHILDREN_SCROLLBAR
; i
++)
1325 ssbi
.rgstate
[i
] = sbi
.rgstate
[i
];
1327 if (sy
<= Rect
->top
)
1328 ssbi
.rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
1330 ssbi
.rgstate
[0] &= ~STATE_SYSTEM_OFFSCREEN
;
1332 co_IntSetScrollBarInfo(Wnd
, OBJID_HSCROLL
, &ssbi
);
1334 if (ssbi
.rgstate
[0] & STATE_SYSTEM_OFFSCREEN
)
1335 Style
&= ~WS_HSCROLL
;
1338 Style
&= ~WS_HSCROLL
;
1341 if ((Style
& WS_VSCROLL
) && (Style
& WS_HSCROLL
))
1343 if ((Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1344 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1346 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1348 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1352 if (Style
& WS_VSCROLL
)
1354 if ((Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1355 Rect
->left
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1357 Rect
->right
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1359 else if (Style
& WS_HSCROLL
)
1360 Rect
->bottom
-= UserGetSystemMetrics(SM_CYHSCROLL
);
1363 if (Rect
->top
> Rect
->bottom
)
1364 Rect
->bottom
= Rect
->top
;
1366 if (Rect
->left
> Rect
->right
)
1367 Rect
->right
= Rect
->left
;
1371 Rect
->right
= Rect
->left
;
1372 Rect
->bottom
= Rect
->top
;
1379 INT
NC_DoNCActive(PWND Wnd
)
1383 if ( IntGetSysColor(COLOR_CAPTIONTEXT
) != IntGetSysColor(COLOR_INACTIVECAPTIONTEXT
) ||
1384 IntGetSysColor(COLOR_ACTIVECAPTION
) != IntGetSysColor(COLOR_INACTIVECAPTION
) )
1387 if (!(Wnd
->style
& WS_MINIMIZED
) && UserHasThickFrameStyle(Wnd
->style
, Wnd
->ExStyle
))
1389 //if (IntGetSysColor(COLOR_ACTIVEBORDER) != IntGetSysColor(COLOR_INACTIVEBORDER)) // Why are these the same?
1397 LRESULT
NC_HandleNCActivate( PWND Wnd
, WPARAM wParam
, LPARAM lParam
)
1400 /* Lotus Notes draws menu descriptions in the caption of its main
1401 * window. When it wants to restore original "system" view, it just
1402 * sends WM_NCACTIVATE message to itself. Any optimizations here in
1403 * attempt to minimize redrawings lead to a not restored caption.
1405 if (wParam
& DC_ACTIVE
)
1407 Wnd
->state
|= WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
;
1408 wParam
= DC_CAPTION
|DC_ACTIVE
;
1412 Wnd
->state
&= ~(WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
);
1413 wParam
= DC_CAPTION
;
1416 if (Wnd
->state
& WNDS_NONCPAINT
|| !(Wnd
->style
& WS_VISIBLE
))
1419 /* This isn't documented but is reproducible in at least XP SP2 and
1420 * Outlook 2007 depends on it
1423 // If this parameter is set to -1, DefWindowProc does not repaint the
1424 // nonclient area to reflect the state change.
1425 if ( lParam
!= -1 &&
1426 ( Flags
= NC_DoNCActive(Wnd
)) != 0 )
1429 HRGN hRgnTemp
= NULL
, hRgn
= (HRGN
)lParam
;
1431 if (GreIsHandleValid(hRgn
))
1433 hRgnTemp
= NtGdiCreateRectRgn(0, 0, 0, 0);
1434 if (NtGdiCombineRgn(hRgnTemp
, hRgn
, 0, RGN_COPY
) == ERROR
)
1436 GreDeleteObject(hRgnTemp
);
1441 if ((hDC
= UserGetDCEx(Wnd
, hRgnTemp
, DCX_WINDOW
|DCX_USESTYLE
)))
1443 NC_DoNCPaint(Wnd
, hDC
, wParam
| Flags
); // Redraw MENUs.
1444 UserReleaseDC(Wnd
, hDC
, FALSE
);
1447 GreDeleteObject(hRgnTemp
);
1454 NC_DoButton(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1458 BOOL Pressed
= TRUE
, OldState
;
1465 Style
= pWnd
->style
;
1469 SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1470 MenuState
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
); /* in case of error MenuState==0xFFFFFFFF */
1471 if (!(Style
& WS_SYSMENU
) || (MenuState
& (MF_GRAYED
|MF_DISABLED
)) || (pWnd
->style
& CS_NOCLOSE
))
1473 ButtonType
= DFCS_CAPTIONCLOSE
;
1477 if (!(Style
& WS_MINIMIZEBOX
))
1479 ButtonType
= DFCS_CAPTIONMIN
;
1480 SCMsg
= ((Style
& WS_MINIMIZE
) ? SC_RESTORE
: SC_MINIMIZE
);
1483 if (!(Style
& WS_MAXIMIZEBOX
))
1485 ButtonType
= DFCS_CAPTIONMAX
;
1486 SCMsg
= ((Style
& WS_MAXIMIZE
) ? SC_RESTORE
: SC_MAXIMIZE
);
1495 * FIXME: Not sure where to do this, but we must flush the pending
1496 * window updates when someone clicks on the close button and at
1497 * the same time the window is overlapped with another one. This
1498 * looks like a good place for now...
1500 co_IntUpdateWindows(pWnd
, RDW_ALLCHILDREN
, FALSE
);
1502 WindowDC
= UserGetWindowDC(pWnd
);
1503 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, TRUE
, ButtonType
);
1505 co_UserSetCapture(UserHMGetHandle(pWnd
));
1509 if (!co_IntGetPeekMessage(&Msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1510 if (IntCallMsgFilter( &Msg
, MSGF_MAX
)) continue;
1512 if (Msg
.message
== WM_LBUTTONUP
)
1515 if (Msg
.message
!= WM_MOUSEMOVE
)
1519 Pressed
= (GetNCHitEx(pWnd
, Msg
.pt
) == wParam
);
1520 if (Pressed
!= OldState
)
1521 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, Pressed
, ButtonType
);
1525 UserDrawCaptionButtonWnd(pWnd
, WindowDC
, FALSE
, ButtonType
);
1526 IntReleaseCapture();
1527 UserReleaseDC(pWnd
, WindowDC
, FALSE
);
1529 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SCMsg
, SCMsg
== SC_CLOSE
? lParam
: MAKELONG(Msg
.pt
.x
,Msg
.pt
.y
));
1534 NC_HandleNCLButtonDown(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1540 PWND TopWnd
= pWnd
, parent
;
1543 if ((TopWnd
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
)
1545 parent
= UserGetAncestor( TopWnd
, GA_PARENT
);
1546 if (!parent
|| parent
== UserGetDesktopWindow()) break;
1550 if ( co_IntSetForegroundWindowMouse(TopWnd
) ||
1551 //NtUserCallHwndLock(hTopWnd, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE) ||
1552 UserGetActiveWindow() == UserHMGetHandle(TopWnd
))
1554 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOVE
+ HTCAPTION
, lParam
);
1560 LONG style
= pWnd
->style
;
1561 if (style
& WS_SYSMENU
)
1563 if(!(style
& WS_MINIMIZE
) )
1566 HDC hDC
= UserGetWindowDC(pWnd
);
1567 UserGetInsideRectNC(pWnd
, &rect
);
1568 UserDrawSysMenuButton(pWnd
, hDC
, &rect
, TRUE
);
1569 UserReleaseDC( pWnd
, hDC
, FALSE
);
1571 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTSYSMENU
, lParam
);
1577 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_MOUSEMENU
+ HTMENU
, lParam
);
1582 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_HSCROLL
+ HTHSCROLL
, lParam
);
1587 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_VSCROLL
+ HTVSCROLL
, lParam
);
1594 NC_DoButton(pWnd
, wParam
, lParam
);
1607 * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1608 * This was previously done by setting wParam=SC_SIZE + wParam - 2
1610 /* But that is not what WinNT does. Instead it sends this. This
1611 * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1612 * SC_MOUSEMENU into wParam.
1614 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_SIZE
+ wParam
- (HTLEFT
- WMSZ_LEFT
), lParam
);
1625 NC_HandleNCLButtonDblClk(PWND pWnd
, WPARAM wParam
, LPARAM lParam
)
1629 Style
= pWnd
->style
;
1634 /* Maximize/Restore the window */
1635 if((Style
& WS_CAPTION
) == WS_CAPTION
&& (Style
& WS_MAXIMIZEBOX
))
1637 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, ((Style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) ? SC_RESTORE
: SC_MAXIMIZE
), 0);
1643 PMENU SysMenu
= IntGetSystemMenu(pWnd
, FALSE
);
1644 UINT state
= IntGetMenuState(UserHMGetHandle(SysMenu
), SC_CLOSE
, MF_BYCOMMAND
);
1646 /* If the close item of the sysmenu is disabled or not present do nothing */
1647 if ((state
& (MF_DISABLED
| MF_GRAYED
)) || (state
== 0xFFFFFFFF))
1650 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SYSCOMMAND
, SC_CLOSE
, lParam
);
1654 return NC_HandleNCLButtonDown(pWnd
, wParam
, lParam
);
1659 /***********************************************************************
1660 * NC_HandleNCRButtonDown
1662 * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
1664 LRESULT
NC_HandleNCRButtonDown( PWND pwnd
, WPARAM wParam
, LPARAM lParam
)
1667 INT hittest
= wParam
;
1673 if (!IntGetSystemMenu( pwnd
, FALSE
)) break;
1675 co_UserSetCapture( UserHMGetHandle(pwnd
) );
1678 if (!co_IntGetPeekMessage(&msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, TRUE
)) break;
1679 if (IntCallMsgFilter( &msg
, MSGF_MAX
)) continue;
1680 if (msg
.message
== WM_RBUTTONUP
)
1682 hittest
= GetNCHitEx( pwnd
, msg
.pt
);
1685 if (UserHMGetHandle(pwnd
) != IntGetCapture()) return 0;
1687 IntReleaseCapture();
1688 if (hittest
== HTCAPTION
|| hittest
== HTSYSMENU
|| hittest
== HTHSCROLL
|| hittest
== HTVSCROLL
)
1690 TRACE("Msg pt %x and Msg.lParam %x and lParam %x\n",MAKELONG(msg
.pt
.x
,msg
.pt
.y
),msg
.lParam
,lParam
);
1691 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_CONTEXTMENU
, (WPARAM
)UserHMGetHandle(pwnd
), MAKELONG(msg
.pt
.x
,msg
.pt
.y
));
1700 GetNCHitEx(PWND pWnd
, POINT pt
)
1702 RECT rcWindow
, rcClient
;
1703 DWORD Style
, ExStyle
;
1705 if (!pWnd
) return HTNOWHERE
;
1707 if (pWnd
== UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
1709 rcClient
.left
= rcClient
.top
= rcWindow
.left
= rcWindow
.top
= 0;
1710 rcWindow
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1711 rcWindow
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1712 rcClient
.right
= UserGetSystemMetrics(SM_CXSCREEN
);
1713 rcClient
.bottom
= UserGetSystemMetrics(SM_CYSCREEN
);
1717 rcClient
= pWnd
->rcClient
;
1718 rcWindow
= pWnd
->rcWindow
;
1721 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
)) return HTNOWHERE
;
1723 Style
= pWnd
->style
;
1724 ExStyle
= pWnd
->ExStyle
;
1726 if (Style
& WS_MINIMIZE
) return HTCAPTION
;
1728 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTCLIENT
;
1731 if (HAS_THICKFRAME( Style
, ExStyle
))
1733 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXFRAME
), -UserGetSystemMetrics(SM_CYFRAME
) );
1734 if (!RECTL_bPointInRect(&rcWindow
, pt
.x
, pt
.y
))
1736 /* Check top sizing border */
1737 if (pt
.y
< rcWindow
.top
)
1739 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPLEFT
;
1740 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTTOPRIGHT
;
1743 /* Check bottom sizing border */
1744 if (pt
.y
>= rcWindow
.bottom
)
1746 if (pt
.x
< rcWindow
.left
+UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMLEFT
;
1747 if (pt
.x
>= rcWindow
.right
-UserGetSystemMetrics(SM_CXSIZE
)) return HTBOTTOMRIGHT
;
1750 /* Check left sizing border */
1751 if (pt
.x
< rcWindow
.left
)
1753 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPLEFT
;
1754 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMLEFT
;
1757 /* Check right sizing border */
1758 if (pt
.x
>= rcWindow
.right
)
1760 if (pt
.y
< rcWindow
.top
+UserGetSystemMetrics(SM_CYSIZE
)) return HTTOPRIGHT
;
1761 if (pt
.y
>= rcWindow
.bottom
-UserGetSystemMetrics(SM_CYSIZE
)) return HTBOTTOMRIGHT
;
1766 else /* No thick frame */
1768 if (HAS_DLGFRAME( Style
, ExStyle
))
1769 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXDLGFRAME
), -UserGetSystemMetrics(SM_CYDLGFRAME
));
1770 else if (HAS_THINFRAME( Style
, ExStyle
))
1771 RECTL_vInflateRect(&rcWindow
, -UserGetSystemMetrics(SM_CXBORDER
), -UserGetSystemMetrics(SM_CYBORDER
));
1772 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
)) return HTBORDER
;
1777 if ((Style
& WS_CAPTION
) == WS_CAPTION
)
1779 if (ExStyle
& WS_EX_TOOLWINDOW
)
1780 rcWindow
.top
+= UserGetSystemMetrics(SM_CYSMCAPTION
) - 1;
1782 rcWindow
.top
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1783 if (!RECTL_bPointInRect( &rcWindow
, pt
.x
, pt
.y
))
1785 BOOL min_or_max_box
= (Style
& WS_SYSMENU
) && (Style
& (WS_MINIMIZEBOX
|WS_MAXIMIZEBOX
));
1786 if (ExStyle
& WS_EX_LAYOUTRTL
)
1788 /* Check system menu */
1789 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1791 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1792 if (pt
.x
> rcWindow
.right
) return HTSYSMENU
;
1795 /* Check close button */
1796 if (Style
& WS_SYSMENU
)
1798 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
);
1799 if (pt
.x
< rcWindow
.left
) return HTCLOSE
;
1802 /* Check maximize box */
1803 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1804 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1806 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1807 if (pt
.x
< rcWindow
.left
) return HTMAXBUTTON
;
1810 /* Check minimize box */
1811 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1813 rcWindow
.left
+= UserGetSystemMetrics(SM_CXSIZE
);
1814 if (pt
.x
< rcWindow
.left
) return HTMINBUTTON
;
1819 /* Check system menu */
1820 if ((Style
& WS_SYSMENU
) && !(ExStyle
& WS_EX_TOOLWINDOW
) && NC_IconForWindow(pWnd
))
1822 rcWindow
.left
+= UserGetSystemMetrics(SM_CYCAPTION
) - 1;
1823 if (pt
.x
< rcWindow
.left
) return HTSYSMENU
;
1826 /* Check close button */
1827 if (Style
& WS_SYSMENU
)
1829 rcWindow
.right
-= UserGetSystemMetrics(SM_CYCAPTION
);
1830 if (pt
.x
> rcWindow
.right
) return HTCLOSE
;
1833 /* Check maximize box */
1834 /* In Win95 there is automatically a Maximize button when there is a minimize one */
1835 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1837 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1838 if (pt
.x
> rcWindow
.right
) return HTMAXBUTTON
;
1841 /* Check minimize box */
1842 if (min_or_max_box
&& !(ExStyle
& WS_EX_TOOLWINDOW
))
1844 rcWindow
.right
-= UserGetSystemMetrics(SM_CXSIZE
);
1845 if (pt
.x
> rcWindow
.right
) return HTMINBUTTON
;
1852 /* Check menu bar */
1854 if (HAS_MENU( pWnd
, Style
) && (pt
.y
< rcClient
.top
) &&
1855 (pt
.x
>= rcClient
.left
) && (pt
.x
< rcClient
.right
))
1858 /* Check vertical scroll bar */
1860 if (ExStyle
& WS_EX_LAYOUTRTL
) ExStyle
^= WS_EX_LEFTSCROLLBAR
;
1861 if (Style
& WS_VSCROLL
)
1863 if((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0)
1864 rcClient
.left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
1866 rcClient
.right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
1867 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
)) return HTVSCROLL
;
1870 /* Check horizontal scroll bar */
1872 if (Style
& WS_HSCROLL
)
1874 rcClient
.bottom
+= UserGetSystemMetrics(SM_CYHSCROLL
);
1875 if (RECTL_bPointInRect( &rcClient
, pt
.x
, pt
.y
))
1877 /* Check size box */
1878 if ((Style
& WS_VSCROLL
) &&
1879 ((((ExStyle
& WS_EX_LEFTSCROLLBAR
) != 0) && (pt
.x
<= rcClient
.left
+ UserGetSystemMetrics(SM_CXVSCROLL
))) ||
1880 (((ExStyle
& WS_EX_LEFTSCROLLBAR
) == 0) && (pt
.x
>= rcClient
.right
- UserGetSystemMetrics(SM_CXVSCROLL
)))))
1886 /* Has to return HTNOWHERE if nothing was found
1887 Could happen when a window has a customized non client area */