[Win32SS]

- Start ordering functions into separate files.

svn path=/trunk/; revision=68582
This commit is contained in:
James Tabor 2015-07-30 07:49:09 +00:00
parent bfb9c92b07
commit 6fe69964e1
7 changed files with 1412 additions and 1375 deletions

View file

@ -129,11 +129,13 @@ list(APPEND SOURCE
user/ntuser/monitor.c
user/ntuser/mouse.c
user/ntuser/msgqueue.c
user/ntuser/nonclient.c
user/ntuser/ntstubs.c
user/ntuser/ntuser.c
user/ntuser/painting.c
user/ntuser/prop.c
user/ntuser/scrollbar.c
user/ntuser/scrollex.c
user/ntuser/session.c
user/ntuser/shutdown.c
user/ntuser/simplecall.c

View file

@ -11,25 +11,6 @@
DBG_DEFAULT_CHANNEL(UserDefwnd);
#define UserHasDlgFrameStyle(Style, ExStyle) \
(((ExStyle) & WS_EX_DLGMODALFRAME) || \
(((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
#define UserHasThickFrameStyle(Style, ExStyle) \
(((Style) & WS_THICKFRAME) && \
(!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
#define UserHasThinFrameStyle(Style, ExStyle) \
(((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
#define ON_LEFT_BORDER(hit) \
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
#define ON_RIGHT_BORDER(hit) \
(((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
#define ON_TOP_BORDER(hit) \
(((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
#define ON_BOTTOM_BORDER(hit) \
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
HBRUSH FASTCALL
DefWndControlColor(HDC hDC, UINT ctlType)
@ -119,538 +100,6 @@ DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
return 0;
}
VOID FASTCALL
UserDrawWindowFrame(HDC hdc,
RECTL *rect,
ULONG width,
ULONG height)
{
HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
NtGdiSelectBrush( hdc, hbrush );
}
VOID FASTCALL
UserDrawMovingFrame(HDC hdc,
RECTL *rect,
BOOL thickframe)
{
if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
else UserDrawWindowFrame(hdc, rect, 1, 1);
}
/***********************************************************************
* NC_GetInsideRect
*
* Get the 'inside' rectangle of a window, i.e. the whole window rectangle
* but without the borders (if any).
*/
void FASTCALL
NC_GetInsideRect(PWND Wnd, RECT *rect)
{
ULONG Style;
ULONG ExStyle;
Style = Wnd->style;
ExStyle = Wnd->ExStyle;
rect->top = rect->left = 0;
rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
if (Style & WS_ICONIC) return;
/* Remove frame from rectangle */
if (UserHasThickFrameStyle(Style, ExStyle ))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
}
else
{
if (UserHasDlgFrameStyle(Style, ExStyle ))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
/* FIXME: this isn't in NC_AdjustRect? why not? */
if (ExStyle & WS_EX_DLGMODALFRAME)
RECTL_vInflateRect( rect, -1, 0 );
}
else
{
if (UserHasThinFrameStyle(Style, ExStyle))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
}
}
}
/* We have additional border information if the window
* is a child (but not an MDI child) */
if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
{
if (ExStyle & WS_EX_CLIENTEDGE)
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
if (ExStyle & WS_EX_STATICEDGE)
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
}
}
LONG FASTCALL
DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
{
LONG hittest = 0;
POINT pt;
MSG msg;
RECT rectWindow;
ULONG Style = Wnd->style;
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
rectWindow = Wnd->rcWindow;
if ((wParam & 0xfff0) == SC_MOVE)
{
/* Move pointer at the center of the caption */
RECT rect = rectWindow;
/* Note: to be exactly centered we should take the different types
* of border into account, but it shouldn't make more than a few pixels
* of difference so let's not bother with that */
if (Style & WS_SYSMENU)
rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MINIMIZEBOX)
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MAXIMIZEBOX)
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
pt.x = (rect.right + rect.left) / 2;
pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
hittest = HTCAPTION;
*capturePoint = pt;
}
else /* SC_SIZE */
{
pt.x = pt.y = 0;
while (!hittest)
{
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
switch(msg.message)
{
case WM_MOUSEMOVE:
//// Clamp the mouse position to the window rectangle when starting a window resize.
pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
hittest = GetNCHitEx(Wnd, pt);
if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
break;
case WM_LBUTTONUP:
return 0;
case WM_KEYDOWN:
switch (msg.wParam)
{
case VK_UP:
hittest = HTTOP;
pt.x = (rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_DOWN:
hittest = HTBOTTOM;
pt.x = (rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_LEFT:
hittest = HTLEFT;
pt.x = rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
pt.y = (rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RIGHT:
hittest = HTRIGHT;
pt.x = rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
pt.y = (rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RETURN:
case VK_ESCAPE:
return 0;
}
default:
IntTranslateKbdMessage( &msg, 0 );
pti->TIF_flags |= TIF_MOVESIZETRACKING;
IntDispatchMessage( &msg );
pti->TIF_flags |= TIF_MOVESIZETRACKING;
break;
}
}
*capturePoint = pt;
}
UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
return hittest;
}
//
// System Command Size and Move
//
// Perform SC_MOVE and SC_SIZE commands.
//
VOID FASTCALL
DefWndDoSizeMove(PWND pwnd, WORD wParam)
{
MSG msg;
RECT sizingRect, mouseRect, origRect, unmodRect;
HDC hdc;
LONG hittest = (LONG)(wParam & 0x0f);
PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
POINT minTrack, maxTrack;
POINT capturePoint, pt;
ULONG Style, ExStyle;
BOOL thickframe;
BOOL iconic;
BOOL moved = FALSE;
BOOL DragFullWindows = FALSE;
PWND pWndParent = NULL;
WPARAM syscommand = (wParam & 0xfff0);
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
//PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
// The task bar can grow in size and can not reduce due to the change
// in the work area.
Style = pwnd->style;
ExStyle = pwnd->ExStyle;
iconic = (Style & WS_MINIMIZE) != 0;
if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
//
// Show window contents while dragging the window, get flag from registry data.
//
UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
pt.x = pti->ptLast.x;
pt.y = pti->ptLast.y;
capturePoint = pt;
UserClipCursor( NULL );
TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
pwnd, syscommand, hittest, pt.x, pt.y);
if (syscommand == SC_MOVE)
{
if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
if (!hittest) return;
}
else /* SC_SIZE */
{
if (!thickframe) return;
if (hittest && (syscommand != SC_MOUSEMENU))
{
hittest += (HTLEFT - WMSZ_LEFT);
}
else
{
co_UserSetCapture(UserHMGetHandle(pwnd));
hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
if (!hittest)
{
IntReleaseCapture();
return;
}
}
}
/* Get min/max info */
co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
sizingRect = pwnd->rcWindow;
origRect = sizingRect;
if (Style & WS_CHILD)
{
pWndParent = IntGetParent(pwnd);
IntGetClientRect( pWndParent, &mouseRect );
IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
unmodRect = sizingRect;
}
else
{
if (!(ExStyle & WS_EX_TOPMOST))
{
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
}
else
{
RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
}
unmodRect = sizingRect;
}
if (ON_LEFT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
}
else if (ON_RIGHT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
}
if (ON_TOP_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
}
else if (ON_BOTTOM_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
}
hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
if (iconic)
{
DragCursor = pwnd->pcls->spicn;
if (DragCursor)
{
UserReferenceObject(DragCursor);
}
else
{
HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
if (CursorHandle)
{
DragCursor = UserGetCurIconObject(CursorHandle);
}
else
{
iconic = FALSE;
}
}
}
/* repaint the window before moving it around */
co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
for(;;)
{
int dx = 0, dy = 0;
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
/* Exit on button-up, Return, or Esc */
if ((msg.message == WM_LBUTTONUP) ||
((msg.message == WM_KEYDOWN) &&
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
{
IntTranslateKbdMessage( &msg , 0 );
IntDispatchMessage( &msg );
continue; /* We are not interested in other messages */
}
pt = msg.pt;
if (msg.message == WM_KEYDOWN) switch(msg.wParam)
{
case VK_UP: pt.y -= 8; break;
case VK_DOWN: pt.y += 8; break;
case VK_LEFT: pt.x -= 8; break;
case VK_RIGHT: pt.x += 8; break;
}
pt.x = max( pt.x, mouseRect.left );
pt.x = min( pt.x, mouseRect.right - 1 );
pt.y = max( pt.y, mouseRect.top );
pt.y = min( pt.y, mouseRect.bottom - 1 );
dx = pt.x - capturePoint.x;
dy = pt.y - capturePoint.y;
if (dx || dy)
{
if ( !moved )
{
moved = TRUE;
if ( iconic ) /* ok, no system popup tracking */
{
OldCursor = UserSetCursor(DragCursor, FALSE);
UserShowCursor( TRUE );
}
else if(!DragFullWindows)
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
}
if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
else
{
RECT newRect = unmodRect;
if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
if (ON_TOP_BORDER(hittest)) newRect.top += dy;
else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
capturePoint = pt;
//
// Save the new position to the unmodified rectangle. This allows explorer task bar
// sizing. Explorer will forces back the position unless a certain amount of sizing
// has occurred.
//
unmodRect = newRect;
/* determine the hit location */
if (syscommand == SC_SIZE)
{
WPARAM wpSizingHit = 0;
if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
}
else
co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
if (!iconic)
{
if (!DragFullWindows)
UserDrawMovingFrame( hdc, &newRect, thickframe );
else
{ // Moving the whole window now!
PWND pwndTemp;
//// This causes the mdi child window to jump up when it is moved.
//IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
co_WinPosSetWindowPos( pwnd,
0,
newRect.left,
newRect.top,
newRect.right - newRect.left,
newRect.bottom - newRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
// Update all the windows after the move or size, including this window.
for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
pwndTemp;
pwndTemp = pwndTemp->spwndNext )
{
RECTL rect;
// Only the windows that overlap will be redrawn.
if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
{
co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}
}
}
sizingRect = newRect;
}
}
}
pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
IntReleaseCapture();
if ( iconic )
{
if ( moved ) /* restore cursors, show icon title later on */
{
UserShowCursor( FALSE );
OldCursor = UserSetCursor(OldCursor, FALSE);
}
/* It could be that the cursor was already changed while we were proceeding,
* so we must unreference whatever cursor was current at the time we restored the old one.
* Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
*/
if (OldCursor) UserDereferenceObject(OldCursor);
}
else if ( moved && !DragFullWindows )
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
UserReleaseDC(NULL, hdc, FALSE);
//// This causes the mdi child window to jump up when it is moved.
//if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
{
ERR("DoSizeMove : WH_CBT Call Hook return!\n");
moved = FALSE;
}
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
//// wine mdi hack
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
////
/* window moved or resized */
if (moved)
{
/* if the moving/resizing isn't canceled call SetWindowPos
* with the new position or the new size of the window
*/
if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
{
/* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
if (!DragFullWindows || iconic )
{
co_WinPosSetWindowPos( pwnd,
0,
sizingRect.left,
sizingRect.top,
sizingRect.right - sizingRect.left,
sizingRect.bottom - sizingRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
else
{ /* restore previous size/position */
if ( DragFullWindows )
{
co_WinPosSetWindowPos( pwnd,
0,
origRect.left,
origRect.top,
origRect.right - origRect.left,
origRect.bottom - origRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
}
if ( IntIsWindow(UserHMGetHandle(pwnd)) )
{
if ( iconic )
{
/* Single click brings up the system menu when iconized */
if ( !moved )
{
if( Style & WS_SYSMENU )
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
}
}
}
}
//
// Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
//
@ -1197,230 +646,4 @@ IntDefWindowProc(
return lResult;
}
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
{
PCURICON_OBJECT pIcon = NULL;
HICON hIcon;
//FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
//FIXME: Hence we must return a pointer with no reference count.
//FIXME: This is bad and we should feel bad.
//FIXME: Stop whining over wine code.
hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
if (!hIcon && pWnd->pcls->spicnSm)
return pWnd->pcls->spicnSm;
if (!hIcon && pWnd->pcls->spicn)
return pWnd->pcls->spicn;
if (!hIcon && (pWnd->style & DS_MODALFRAME))
{
if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
}
if (hIcon)
{
pIcon = UserGetCurIconObject(hIcon);
if (pIcon)
{
UserDereferenceObject(pIcon);
}
}
return pIcon;
}
DWORD FASTCALL
GetNCHitEx(PWND pWnd, POINT pt)
{
RECT rcWindow, rcClient;
DWORD Style, ExStyle;
if (!pWnd) return HTNOWHERE;
if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
{
rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
}
else
{
rcClient = pWnd->rcClient;
rcWindow = pWnd->rcWindow;
}
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
Style = pWnd->style;
ExStyle = pWnd->ExStyle;
if (Style & WS_MINIMIZE) return HTCAPTION;
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
/* Check borders */
if (HAS_THICKFRAME( Style, ExStyle ))
{
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
{
/* Check top sizing border */
if (pt.y < rcWindow.top)
{
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rcWindow.bottom)
{
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rcWindow.left)
{
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rcWindow.right)
{
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( Style, ExStyle ))
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( Style, ExStyle ))
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
}
/* Check caption */
if ((Style & WS_CAPTION) == WS_CAPTION)
{
if (ExStyle & WS_EX_TOOLWINDOW)
rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
else
rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
{
BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
if (ExStyle & WS_EX_LAYOUTRTL)
{
/* Check system menu */
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
{
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x > rcWindow.right) return HTSYSMENU;
}
/* Check close button */
if (Style & WS_SYSMENU)
{
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
if (pt.x < rcWindow.left) return HTCLOSE;
}
/* Check maximize box */
/* In Win95 there is automatically a Maximize button when there is a minimize one */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
if (pt.x < rcWindow.left) return HTMAXBUTTON;
}
/* Check minimize box */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
if (pt.x < rcWindow.left) return HTMINBUTTON;
}
}
else
{
/* Check system menu */
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
{
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x < rcWindow.left) return HTSYSMENU;
}
/* Check close button */
if (Style & WS_SYSMENU)
{
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
if (pt.x > rcWindow.right) return HTCLOSE;
}
/* Check maximize box */
/* In Win95 there is automatically a Maximize button when there is a minimize one */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
if (pt.x > rcWindow.right) return HTMAXBUTTON;
}
/* Check minimize box */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
if (pt.x > rcWindow.right) return HTMINBUTTON;
}
}
return HTCAPTION;
}
}
/* Check menu bar */
if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
(pt.x >= rcClient.left) && (pt.x < rcClient.right))
return HTMENU;
/* Check vertical scroll bar */
if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
if (Style & WS_VSCROLL)
{
if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
else
rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
}
/* Check horizontal scroll bar */
if (Style & WS_HSCROLL)
{
rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
{
/* Check size box */
if ((Style & WS_VSCROLL) &&
((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
(((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
return HTSIZE;
return HTHSCROLL;
}
}
/* Has to return HTNOWHERE if nothing was found
Could happen when a window has a customized non client area */
return HTNOWHERE;
}
/* EOF */

View file

@ -0,0 +1,793 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Miscellaneous User functions
* FILE: win32ss/user/ntuser/nonclient.c
* PROGRAMER:
*/
#include <win32k.h>
#include <windowsx.h>
DBG_DEFAULT_CHANNEL(UserDefwnd);
#define UserHasDlgFrameStyle(Style, ExStyle) \
(((ExStyle) & WS_EX_DLGMODALFRAME) || \
(((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
#define UserHasThickFrameStyle(Style, ExStyle) \
(((Style) & WS_THICKFRAME) && \
(!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
#define UserHasThinFrameStyle(Style, ExStyle) \
(((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
#define ON_LEFT_BORDER(hit) \
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
#define ON_RIGHT_BORDER(hit) \
(((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
#define ON_TOP_BORDER(hit) \
(((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
#define ON_BOTTOM_BORDER(hit) \
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
VOID FASTCALL
UserDrawWindowFrame(HDC hdc,
RECTL *rect,
ULONG width,
ULONG height)
{
HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
NtGdiSelectBrush( hdc, hbrush );
}
VOID FASTCALL
UserDrawMovingFrame(HDC hdc,
RECTL *rect,
BOOL thickframe)
{
if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
else UserDrawWindowFrame(hdc, rect, 1, 1);
}
/***********************************************************************
* NC_GetInsideRect
*
* Get the 'inside' rectangle of a window, i.e. the whole window rectangle
* but without the borders (if any).
*/
void FASTCALL
NC_GetInsideRect(PWND Wnd, RECT *rect)
{
ULONG Style;
ULONG ExStyle;
Style = Wnd->style;
ExStyle = Wnd->ExStyle;
rect->top = rect->left = 0;
rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
if (Style & WS_ICONIC) return;
/* Remove frame from rectangle */
if (UserHasThickFrameStyle(Style, ExStyle ))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
}
else
{
if (UserHasDlgFrameStyle(Style, ExStyle ))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
/* FIXME: this isn't in NC_AdjustRect? why not? */
if (ExStyle & WS_EX_DLGMODALFRAME)
RECTL_vInflateRect( rect, -1, 0 );
}
else
{
if (UserHasThinFrameStyle(Style, ExStyle))
{
RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
}
}
}
/* We have additional border information if the window
* is a child (but not an MDI child) */
if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
{
if (ExStyle & WS_EX_CLIENTEDGE)
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
if (ExStyle & WS_EX_STATICEDGE)
RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
}
}
LONG FASTCALL
DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
{
LONG hittest = 0;
POINT pt;
MSG msg;
RECT rectWindow;
ULONG Style = Wnd->style;
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
rectWindow = Wnd->rcWindow;
if ((wParam & 0xfff0) == SC_MOVE)
{
/* Move pointer at the center of the caption */
RECT rect = rectWindow;
/* Note: to be exactly centered we should take the different types
* of border into account, but it shouldn't make more than a few pixels
* of difference so let's not bother with that */
if (Style & WS_SYSMENU)
rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MINIMIZEBOX)
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MAXIMIZEBOX)
rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
pt.x = (rect.right + rect.left) / 2;
pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
hittest = HTCAPTION;
*capturePoint = pt;
}
else /* SC_SIZE */
{
pt.x = pt.y = 0;
while (!hittest)
{
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
switch(msg.message)
{
case WM_MOUSEMOVE:
//// Clamp the mouse position to the window rectangle when starting a window resize.
pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
hittest = GetNCHitEx(Wnd, pt);
if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
break;
case WM_LBUTTONUP:
return 0;
case WM_KEYDOWN:
switch (msg.wParam)
{
case VK_UP:
hittest = HTTOP;
pt.x = (rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_DOWN:
hittest = HTBOTTOM;
pt.x = (rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_LEFT:
hittest = HTLEFT;
pt.x = rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
pt.y = (rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RIGHT:
hittest = HTRIGHT;
pt.x = rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
pt.y = (rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RETURN:
case VK_ESCAPE:
return 0;
}
default:
IntTranslateKbdMessage( &msg, 0 );
pti->TIF_flags |= TIF_MOVESIZETRACKING;
IntDispatchMessage( &msg );
pti->TIF_flags |= TIF_MOVESIZETRACKING;
break;
}
}
*capturePoint = pt;
}
UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
return hittest;
}
//
// System Command Size and Move
//
// Perform SC_MOVE and SC_SIZE commands.
//
VOID FASTCALL
DefWndDoSizeMove(PWND pwnd, WORD wParam)
{
MSG msg;
RECT sizingRect, mouseRect, origRect, unmodRect;
HDC hdc;
LONG hittest = (LONG)(wParam & 0x0f);
PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
POINT minTrack, maxTrack;
POINT capturePoint, pt;
ULONG Style, ExStyle;
BOOL thickframe;
BOOL iconic;
BOOL moved = FALSE;
BOOL DragFullWindows = FALSE;
PWND pWndParent = NULL;
WPARAM syscommand = (wParam & 0xfff0);
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
//PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
// The task bar can grow in size and can not reduce due to the change
// in the work area.
Style = pwnd->style;
ExStyle = pwnd->ExStyle;
iconic = (Style & WS_MINIMIZE) != 0;
if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
//
// Show window contents while dragging the window, get flag from registry data.
//
UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
pt.x = pti->ptLast.x;
pt.y = pti->ptLast.y;
capturePoint = pt;
UserClipCursor( NULL );
TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
pwnd, syscommand, hittest, pt.x, pt.y);
if (syscommand == SC_MOVE)
{
if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
if (!hittest) return;
}
else /* SC_SIZE */
{
if (!thickframe) return;
if (hittest && (syscommand != SC_MOUSEMENU))
{
hittest += (HTLEFT - WMSZ_LEFT);
}
else
{
co_UserSetCapture(UserHMGetHandle(pwnd));
hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
if (!hittest)
{
IntReleaseCapture();
return;
}
}
}
/* Get min/max info */
co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
sizingRect = pwnd->rcWindow;
origRect = sizingRect;
if (Style & WS_CHILD)
{
pWndParent = IntGetParent(pwnd);
IntGetClientRect( pWndParent, &mouseRect );
IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
unmodRect = sizingRect;
}
else
{
if (!(ExStyle & WS_EX_TOPMOST))
{
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
}
else
{
RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
}
unmodRect = sizingRect;
}
if (ON_LEFT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
}
else if (ON_RIGHT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
}
if (ON_TOP_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
}
else if (ON_BOTTOM_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
}
hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
if (iconic)
{
DragCursor = pwnd->pcls->spicn;
if (DragCursor)
{
UserReferenceObject(DragCursor);
}
else
{
HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
if (CursorHandle)
{
DragCursor = UserGetCurIconObject(CursorHandle);
}
else
{
iconic = FALSE;
}
}
}
/* repaint the window before moving it around */
co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
for(;;)
{
int dx = 0, dy = 0;
if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
/* Exit on button-up, Return, or Esc */
if ((msg.message == WM_LBUTTONUP) ||
((msg.message == WM_KEYDOWN) &&
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
{
IntTranslateKbdMessage( &msg , 0 );
IntDispatchMessage( &msg );
continue; /* We are not interested in other messages */
}
pt = msg.pt;
if (msg.message == WM_KEYDOWN) switch(msg.wParam)
{
case VK_UP: pt.y -= 8; break;
case VK_DOWN: pt.y += 8; break;
case VK_LEFT: pt.x -= 8; break;
case VK_RIGHT: pt.x += 8; break;
}
pt.x = max( pt.x, mouseRect.left );
pt.x = min( pt.x, mouseRect.right - 1 );
pt.y = max( pt.y, mouseRect.top );
pt.y = min( pt.y, mouseRect.bottom - 1 );
dx = pt.x - capturePoint.x;
dy = pt.y - capturePoint.y;
if (dx || dy)
{
if ( !moved )
{
moved = TRUE;
if ( iconic ) /* ok, no system popup tracking */
{
OldCursor = UserSetCursor(DragCursor, FALSE);
UserShowCursor( TRUE );
}
else if(!DragFullWindows)
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
}
if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
else
{
RECT newRect = unmodRect;
if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
if (ON_TOP_BORDER(hittest)) newRect.top += dy;
else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
capturePoint = pt;
//
// Save the new position to the unmodified rectangle. This allows explorer task bar
// sizing. Explorer will forces back the position unless a certain amount of sizing
// has occurred.
//
unmodRect = newRect;
/* determine the hit location */
if (syscommand == SC_SIZE)
{
WPARAM wpSizingHit = 0;
if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
}
else
co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
if (!iconic)
{
if (!DragFullWindows)
UserDrawMovingFrame( hdc, &newRect, thickframe );
else
{ // Moving the whole window now!
PWND pwndTemp;
//// This causes the mdi child window to jump up when it is moved.
//IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
co_WinPosSetWindowPos( pwnd,
0,
newRect.left,
newRect.top,
newRect.right - newRect.left,
newRect.bottom - newRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
// Update all the windows after the move or size, including this window.
for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
pwndTemp;
pwndTemp = pwndTemp->spwndNext )
{
RECTL rect;
// Only the windows that overlap will be redrawn.
if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
{
co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}
}
}
sizingRect = newRect;
}
}
}
pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
IntReleaseCapture();
if ( iconic )
{
if ( moved ) /* restore cursors, show icon title later on */
{
UserShowCursor( FALSE );
OldCursor = UserSetCursor(OldCursor, FALSE);
}
/* It could be that the cursor was already changed while we were proceeding,
* so we must unreference whatever cursor was current at the time we restored the old one.
* Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
*/
if (OldCursor) UserDereferenceObject(OldCursor);
}
else if ( moved && !DragFullWindows )
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
UserReleaseDC(NULL, hdc, FALSE);
//// This causes the mdi child window to jump up when it is moved.
//if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
{
ERR("DoSizeMove : WH_CBT Call Hook return!\n");
moved = FALSE;
}
IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
//// wine mdi hack
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
////
/* window moved or resized */
if (moved)
{
/* if the moving/resizing isn't canceled call SetWindowPos
* with the new position or the new size of the window
*/
if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
{
/* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
if (!DragFullWindows || iconic )
{
co_WinPosSetWindowPos( pwnd,
0,
sizingRect.left,
sizingRect.top,
sizingRect.right - sizingRect.left,
sizingRect.bottom - sizingRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
else
{ /* restore previous size/position */
if ( DragFullWindows )
{
co_WinPosSetWindowPos( pwnd,
0,
origRect.left,
origRect.top,
origRect.right - origRect.left,
origRect.bottom - origRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
}
if ( IntIsWindow(UserHMGetHandle(pwnd)) )
{
if ( iconic )
{
/* Single click brings up the system menu when iconized */
if ( !moved )
{
if( Style & WS_SYSMENU )
co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
}
}
}
}
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
{
PCURICON_OBJECT pIcon = NULL;
HICON hIcon;
//FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
//FIXME: Hence we must return a pointer with no reference count.
//FIXME: This is bad and we should feel bad.
//FIXME: Stop whining over wine code.
hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
if (!hIcon && pWnd->pcls->spicnSm)
return pWnd->pcls->spicnSm;
if (!hIcon && pWnd->pcls->spicn)
return pWnd->pcls->spicn;
if (!hIcon && (pWnd->style & DS_MODALFRAME))
{
if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
}
if (hIcon)
{
pIcon = UserGetCurIconObject(hIcon);
if (pIcon)
{
UserDereferenceObject(pIcon);
}
}
return pIcon;
}
DWORD FASTCALL
GetNCHitEx(PWND pWnd, POINT pt)
{
RECT rcWindow, rcClient;
DWORD Style, ExStyle;
if (!pWnd) return HTNOWHERE;
if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
{
rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
}
else
{
rcClient = pWnd->rcClient;
rcWindow = pWnd->rcWindow;
}
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
Style = pWnd->style;
ExStyle = pWnd->ExStyle;
if (Style & WS_MINIMIZE) return HTCAPTION;
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
/* Check borders */
if (HAS_THICKFRAME( Style, ExStyle ))
{
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
{
/* Check top sizing border */
if (pt.y < rcWindow.top)
{
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rcWindow.bottom)
{
if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rcWindow.left)
{
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rcWindow.right)
{
if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( Style, ExStyle ))
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( Style, ExStyle ))
RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
}
/* Check caption */
if ((Style & WS_CAPTION) == WS_CAPTION)
{
if (ExStyle & WS_EX_TOOLWINDOW)
rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
else
rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
{
BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
if (ExStyle & WS_EX_LAYOUTRTL)
{
/* Check system menu */
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
{
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x > rcWindow.right) return HTSYSMENU;
}
/* Check close button */
if (Style & WS_SYSMENU)
{
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
if (pt.x < rcWindow.left) return HTCLOSE;
}
/* Check maximize box */
/* In Win95 there is automatically a Maximize button when there is a minimize one */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
if (pt.x < rcWindow.left) return HTMAXBUTTON;
}
/* Check minimize box */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
if (pt.x < rcWindow.left) return HTMINBUTTON;
}
}
else
{
/* Check system menu */
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
{
rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x < rcWindow.left) return HTSYSMENU;
}
/* Check close button */
if (Style & WS_SYSMENU)
{
rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
if (pt.x > rcWindow.right) return HTCLOSE;
}
/* Check maximize box */
/* In Win95 there is automatically a Maximize button when there is a minimize one */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
if (pt.x > rcWindow.right) return HTMAXBUTTON;
}
/* Check minimize box */
if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
{
rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
if (pt.x > rcWindow.right) return HTMINBUTTON;
}
}
return HTCAPTION;
}
}
/* Check menu bar */
if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
(pt.x >= rcClient.left) && (pt.x < rcClient.right))
return HTMENU;
/* Check vertical scroll bar */
if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
if (Style & WS_VSCROLL)
{
if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
else
rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
}
/* Check horizontal scroll bar */
if (Style & WS_HSCROLL)
{
rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
{
/* Check size box */
if ((Style & WS_VSCROLL) &&
((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
(((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
return HTSIZE;
return HTHSCROLL;
}
}
/* Has to return HTNOWHERE if nothing was found
Could happen when a window has a customized non client area */
return HTNOWHERE;
}
/* EOF */

View file

@ -1127,55 +1127,6 @@ IntGetPaintMessage(
return TRUE;
}
static
HWND FASTCALL
co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
{
PDESKTOP Desktop;
PTHRDCARETINFO CaretInfo;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ActiveMessageQueue;
HWND hWndCaret;
PWND WndCaret;
ASSERT_REFS_CO(Window);
pti = PsGetCurrentThreadWin32Thread();
Desktop = pti->rpdesk;
ActiveMessageQueue = Desktop->ActiveMessageQueue;
if (!ActiveMessageQueue) return 0;
CaretInfo = ActiveMessageQueue->CaretInfo;
hWndCaret = CaretInfo->hWnd;
WndCaret = ValidateHwndNoErr(hWndCaret);
// FIXME: Check for WndCaret can be NULL
if (WndCaret == Window ||
((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
{
POINT pt, FromOffset, ToOffset;
RECTL rcCaret;
pt.x = CaretInfo->Pos.x;
pt.y = CaretInfo->Pos.y;
IntGetClientOrigin(WndCaret, &FromOffset);
IntGetClientOrigin(Window, &ToOffset);
rcCaret.left = pt.x;
rcCaret.top = pt.y;
rcCaret.right = pt.x + CaretInfo->Size.cx;
rcCaret.bottom = pt.y + CaretInfo->Size.cy;
if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
{
co_UserHideCaret(0);
lprc->left = pt.x;
lprc->top = pt.y;
return hWndCaret;
}
}
return 0;
}
BOOL
FASTCALL
IntPrintWindow(
@ -1914,553 +1865,6 @@ CLEANUP:
END_CLEANUP;
}
/*
Old GetUpdateRgn, for scrolls, see above note.
*/
INT FASTCALL
co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
{
int RegionType;
RECTL Rect;
PREGION UpdateRgn;
ASSERT_REFS_CO(Window);
if (bErase)
{
co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
}
Window->state &= ~WNDS_UPDATEDIRTY;
if (Window->hrgnUpdate == NULL)
{
REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
return NULLREGION;
}
UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
if (!UpdateRgn)
return ERROR;
Rect = Window->rcClient;
IntIntersectWithParents(Window, &Rect);
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
REGION_UnlockRgn(UpdateRgn);
return RegionType;
}
static
INT FASTCALL
UserScrollDC(
HDC hDC,
INT dx,
INT dy,
const RECTL *prcScroll,
const RECTL *prcClip,
HRGN hrgnUpdate,
PREGION RgnUpdate,
RECTL *prcUpdate)
{
PDC pDC;
RECTL rcScroll, rcClip, rcSrc, rcDst;
INT Result;
if (GdiGetClipBox(hDC, &rcClip) == ERROR)
{
ERR("GdiGetClipBox failed for HDC %p\n", hDC);
return ERROR;
}
rcScroll = rcClip;
if (prcClip)
{
RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
}
if (prcScroll)
{
rcScroll = *prcScroll;
RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
}
else
{
rcSrc = rcClip;
}
rcDst = rcSrc;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (!NtGdiBitBlt( hDC,
rcDst.left,
rcDst.top,
rcDst.right - rcDst.left,
rcDst.bottom - rcDst.top,
hDC,
rcDst.left - dx,
rcDst.top - dy,
SRCCOPY,
0,
0))
{
return ERROR;
}
/* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */
if (RgnUpdate || hrgnUpdate || prcUpdate)
{
PREGION RgnOwn, RgnTmp;
pDC = DC_LockDc(hDC);
if (!pDC)
{
return ERROR;
}
if (hrgnUpdate)
{
NT_ASSERT(RgnUpdate == NULL);
RgnUpdate = REGION_LockRgn(hrgnUpdate);
if (!RgnUpdate)
{
DC_UnlockDc(pDC);
return ERROR;
}
}
/* Begin with the shifted and then clipped scroll rect */
rcDst = rcScroll;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (RgnUpdate)
{
RgnOwn = RgnUpdate;
REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
}
else
{
RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
}
/* Add the source rect */
RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
/* Substract the part of the dest that was visible in source */
IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
REGION_bOffsetRgn(RgnTmp, dx, dy);
Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
/* DO NOT Unlock DC while messing with prgnVis! */
DC_UnlockDc(pDC);
REGION_Delete(RgnTmp);
if (prcUpdate)
{
REGION_GetRgnBox(RgnOwn, prcUpdate);
}
if (hrgnUpdate)
{
REGION_UnlockRgn(RgnUpdate);
}
else if (!RgnUpdate)
{
REGION_Delete(RgnOwn);
}
}
else
Result = NULLREGION;
return Result;
}
/*
* NtUserScrollDC
*
* Status
* @implemented
*/
BOOL APIENTRY
NtUserScrollDC(
HDC hDC,
INT dx,
INT dy,
const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip,
HRGN hrgnUpdate,
LPRECT prcUnsafeUpdate)
{
DECLARE_RETURN(DWORD);
RECTL rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS;
DWORD Result;
TRACE("Enter NtUserScrollDC\n");
UserEnterExclusive();
_SEH2_TRY
{
if (prcUnsafeScroll)
{
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
rcScroll = *prcUnsafeScroll;
}
if (prcUnsafeClip)
{
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
rcClip = *prcUnsafeClip;
}
if (prcUnsafeUpdate)
{
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(FALSE);
}
Result = UserScrollDC( hDC,
dx,
dy,
prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0,
hrgnUpdate,
NULL,
prcUnsafeUpdate? &rcUpdate : NULL);
if(Result == ERROR)
{
/* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
RETURN(FALSE);
}
if (prcUnsafeUpdate)
{
_SEH2_TRY
{
*prcUnsafeUpdate = rcUpdate;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
/* FIXME: SetLastError? */
/* FIXME: correct? We have already scrolled! */
RETURN(FALSE);
}
}
RETURN(TRUE);
CLEANUP:
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserScrollWindowEx
*
* Status
* @implemented
*/
DWORD APIENTRY
NtUserScrollWindowEx(
HWND hWnd,
INT dx,
INT dy,
const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip,
HRGN hrgnUpdate,
LPRECT prcUnsafeUpdate,
UINT flags)
{
RECTL rcScroll, rcClip, rcCaret, rcUpdate;
INT Result;
PWND Window = NULL, CaretWnd;
HDC hDC;
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret;
DWORD dcxflags = 0;
int rdw_flags;
NTSTATUS Status = STATUS_SUCCESS;
DECLARE_RETURN(DWORD);
USER_REFERENCE_ENTRY Ref, CaretRef;
TRACE("Enter NtUserScrollWindowEx\n");
UserEnterExclusive();
Window = UserGetWindowObject(hWnd);
if (!Window || !IntIsWindowDrawable(Window))
{
Window = NULL; /* prevent deref at cleanup */
RETURN( ERROR);
}
UserRefObjectCo(Window, &Ref);
IntGetClientRect(Window, &rcClip);
_SEH2_TRY
{
if (prcUnsafeScroll)
{
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
}
else
rcScroll = rcClip;
if (prcUnsafeClip)
{
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(ERROR);
}
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
(dx == 0 && dy == 0))
{
RETURN(NULLREGION);
}
/* We must use a copy of the region, as we can't hold an exclusive lock
* on it while doing callouts to user-mode */
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
if(!RgnUpdate)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(ERROR);
}
if (hrgnUpdate)
{
RgnTemp = REGION_LockRgn(hrgnUpdate);
if (!RgnTemp)
{
EngSetLastError(ERROR_INVALID_HANDLE);
RETURN(ERROR);
}
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
if (flags & SW_SCROLLWNDDCE)
{
dcxflags = DCX_USESTYLE;
if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
}
else
{
/* So in this case ScrollWindowEx uses Cache DC. */
dcxflags = DCX_CACHE|DCX_USESTYLE;
if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
}
hDC = UserGetDCEx(Window, 0, dcxflags);
if (!hDC)
{
/* FIXME: SetLastError? */
RETURN(ERROR);
}
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
rcCaret = rcScroll;
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
Result = UserScrollDC( hDC,
dx,
dy,
&rcScroll,
&rcClip,
NULL,
RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE);
/*
* Take into account the fact that some damage may have occurred during
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!RgnTemp)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(ERROR);
}
if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
{
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
if (RgnClip)
{
if (hrgnUpdate)
{
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
}
REGION_bOffsetRgn(RgnTemp, dx, dy);
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
if (hrgnUpdate)
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
REGION_Delete(RgnClip);
}
}
REGION_Delete(RgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
PWND Child;
RECTL rcChild;
POINT ClientOrigin;
USER_REFERENCE_ENTRY WndRef;
RECTL rcDummy;
LPARAM lParam;
IntGetClientOrigin(Window, &ClientOrigin);
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
rcChild = Child->rcWindow;
rcChild.left -= ClientOrigin.x;
rcChild.top -= ClientOrigin.y;
rcChild.right -= ClientOrigin.x;
rcChild.bottom -= ClientOrigin.y;
if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
{
UserRefObjectCo(Child, &WndRef);
if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
else
lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
/* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
/* windows sometimes a WM_MOVE */
co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
UserDerefObjectCo(Child);
}
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
{
co_UserRedrawWindow( Window,
NULL,
RgnUpdate,
rdw_flags | /* HACK */
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
}
if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
{
UserRefObjectCo(CaretWnd, &CaretRef);
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
co_UserShowCaret(CaretWnd);
UserDerefObjectCo(CaretWnd);
}
if (prcUnsafeUpdate)
{
_SEH2_TRY
{
/* Probe here, to not fail on invalid pointer before scrolling */
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
*prcUnsafeUpdate = rcUpdate;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(ERROR);
}
}
RETURN(Result);
CLEANUP:
if (hrgnUpdate && (_ret_ != ERROR))
{
/* Give everything back to the caller */
RgnTemp = REGION_LockRgn(hrgnUpdate);
/* The handle should still be valid */
ASSERT(RgnTemp);
if (RgnWinupd)
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
else
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
if (RgnWinupd)
{
REGION_Delete(RgnWinupd);
}
if (RgnUpdate)
{
REGION_Delete(RgnUpdate);
}
if (Window)
UserDerefObjectCo(Window);
TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
BOOL

View file

@ -32,3 +32,5 @@ BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
BOOL FASTCALL IntFlashWindowEx(PWND,PFLASHWINFO);
BOOL FASTCALL IntIntersectWithParents(PWND, RECTL *);
BOOL FASTCALL IntIsWindowDrawable(PWND);

View file

@ -0,0 +1,610 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Window scrolling function
* FILE: win32ss/user/ntuser/scrollex.c
* PROGRAMER: Filip Navara (xnavara@volny.cz)
*/
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserPainting);
static
HWND FASTCALL
co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
{
PDESKTOP Desktop;
PTHRDCARETINFO CaretInfo;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ActiveMessageQueue;
HWND hWndCaret;
PWND WndCaret;
ASSERT_REFS_CO(Window);
pti = PsGetCurrentThreadWin32Thread();
Desktop = pti->rpdesk;
ActiveMessageQueue = Desktop->ActiveMessageQueue;
if (!ActiveMessageQueue) return 0;
CaretInfo = ActiveMessageQueue->CaretInfo;
hWndCaret = CaretInfo->hWnd;
WndCaret = ValidateHwndNoErr(hWndCaret);
// FIXME: Check for WndCaret can be NULL
if (WndCaret == Window ||
((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
{
POINT pt, FromOffset, ToOffset;
RECTL rcCaret;
pt.x = CaretInfo->Pos.x;
pt.y = CaretInfo->Pos.y;
IntGetClientOrigin(WndCaret, &FromOffset);
IntGetClientOrigin(Window, &ToOffset);
rcCaret.left = pt.x;
rcCaret.top = pt.y;
rcCaret.right = pt.x + CaretInfo->Size.cx;
rcCaret.bottom = pt.y + CaretInfo->Size.cy;
if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
{
co_UserHideCaret(0);
lprc->left = pt.x;
lprc->top = pt.y;
return hWndCaret;
}
}
return 0;
}
/*
Old GetUpdateRgn, for scrolls, see above note.
*/
INT FASTCALL
co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
{
int RegionType;
RECTL Rect;
PREGION UpdateRgn;
ASSERT_REFS_CO(Window);
if (bErase)
{
co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
}
Window->state &= ~WNDS_UPDATEDIRTY;
if (Window->hrgnUpdate == NULL)
{
REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
return NULLREGION;
}
UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
if (!UpdateRgn)
return ERROR;
Rect = Window->rcClient;
IntIntersectWithParents(Window, &Rect);
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
REGION_UnlockRgn(UpdateRgn);
return RegionType;
}
static
INT FASTCALL
UserScrollDC(
HDC hDC,
INT dx,
INT dy,
const RECTL *prcScroll,
const RECTL *prcClip,
HRGN hrgnUpdate,
PREGION RgnUpdate,
RECTL *prcUpdate)
{
PDC pDC;
RECTL rcScroll, rcClip, rcSrc, rcDst;
INT Result;
if (GdiGetClipBox(hDC, &rcClip) == ERROR)
{
ERR("GdiGetClipBox failed for HDC %p\n", hDC);
return ERROR;
}
rcScroll = rcClip;
if (prcClip)
{
RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
}
if (prcScroll)
{
rcScroll = *prcScroll;
RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
}
else
{
rcSrc = rcClip;
}
rcDst = rcSrc;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (!NtGdiBitBlt( hDC,
rcDst.left,
rcDst.top,
rcDst.right - rcDst.left,
rcDst.bottom - rcDst.top,
hDC,
rcDst.left - dx,
rcDst.top - dy,
SRCCOPY,
0,
0))
{
return ERROR;
}
/* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */
if (RgnUpdate || hrgnUpdate || prcUpdate)
{
PREGION RgnOwn, RgnTmp;
pDC = DC_LockDc(hDC);
if (!pDC)
{
return ERROR;
}
if (hrgnUpdate)
{
NT_ASSERT(RgnUpdate == NULL);
RgnUpdate = REGION_LockRgn(hrgnUpdate);
if (!RgnUpdate)
{
DC_UnlockDc(pDC);
return ERROR;
}
}
/* Begin with the shifted and then clipped scroll rect */
rcDst = rcScroll;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (RgnUpdate)
{
RgnOwn = RgnUpdate;
REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
}
else
{
RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
}
/* Add the source rect */
RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
/* Substract the part of the dest that was visible in source */
IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
REGION_bOffsetRgn(RgnTmp, dx, dy);
Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
/* DO NOT Unlock DC while messing with prgnVis! */
DC_UnlockDc(pDC);
REGION_Delete(RgnTmp);
if (prcUpdate)
{
REGION_GetRgnBox(RgnOwn, prcUpdate);
}
if (hrgnUpdate)
{
REGION_UnlockRgn(RgnUpdate);
}
else if (!RgnUpdate)
{
REGION_Delete(RgnOwn);
}
}
else
Result = NULLREGION;
return Result;
}
/*
* NtUserScrollDC
*
* Status
* @implemented
*/
BOOL APIENTRY
NtUserScrollDC(
HDC hDC,
INT dx,
INT dy,
const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip,
HRGN hrgnUpdate,
LPRECT prcUnsafeUpdate)
{
DECLARE_RETURN(DWORD);
RECTL rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS;
DWORD Result;
TRACE("Enter NtUserScrollDC\n");
UserEnterExclusive();
_SEH2_TRY
{
if (prcUnsafeScroll)
{
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
rcScroll = *prcUnsafeScroll;
}
if (prcUnsafeClip)
{
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
rcClip = *prcUnsafeClip;
}
if (prcUnsafeUpdate)
{
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(FALSE);
}
Result = UserScrollDC( hDC,
dx,
dy,
prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0,
hrgnUpdate,
NULL,
prcUnsafeUpdate? &rcUpdate : NULL);
if(Result == ERROR)
{
/* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
RETURN(FALSE);
}
if (prcUnsafeUpdate)
{
_SEH2_TRY
{
*prcUnsafeUpdate = rcUpdate;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
/* FIXME: SetLastError? */
/* FIXME: correct? We have already scrolled! */
RETURN(FALSE);
}
}
RETURN(TRUE);
CLEANUP:
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserScrollWindowEx
*
* Status
* @implemented
*/
DWORD APIENTRY
NtUserScrollWindowEx(
HWND hWnd,
INT dx,
INT dy,
const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip,
HRGN hrgnUpdate,
LPRECT prcUnsafeUpdate,
UINT flags)
{
RECTL rcScroll, rcClip, rcCaret, rcUpdate;
INT Result;
PWND Window = NULL, CaretWnd;
HDC hDC;
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret;
DWORD dcxflags = 0;
int rdw_flags;
NTSTATUS Status = STATUS_SUCCESS;
DECLARE_RETURN(DWORD);
USER_REFERENCE_ENTRY Ref, CaretRef;
TRACE("Enter NtUserScrollWindowEx\n");
UserEnterExclusive();
Window = UserGetWindowObject(hWnd);
if (!Window || !IntIsWindowDrawable(Window))
{
Window = NULL; /* prevent deref at cleanup */
RETURN( ERROR);
}
UserRefObjectCo(Window, &Ref);
IntGetClientRect(Window, &rcClip);
_SEH2_TRY
{
if (prcUnsafeScroll)
{
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
}
else
rcScroll = rcClip;
if (prcUnsafeClip)
{
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(ERROR);
}
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
(dx == 0 && dy == 0))
{
RETURN(NULLREGION);
}
/* We must use a copy of the region, as we can't hold an exclusive lock
* on it while doing callouts to user-mode */
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
if(!RgnUpdate)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(ERROR);
}
if (hrgnUpdate)
{
RgnTemp = REGION_LockRgn(hrgnUpdate);
if (!RgnTemp)
{
EngSetLastError(ERROR_INVALID_HANDLE);
RETURN(ERROR);
}
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
if (flags & SW_SCROLLWNDDCE)
{
dcxflags = DCX_USESTYLE;
if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
}
else
{
/* So in this case ScrollWindowEx uses Cache DC. */
dcxflags = DCX_CACHE|DCX_USESTYLE;
if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
}
hDC = UserGetDCEx(Window, 0, dcxflags);
if (!hDC)
{
/* FIXME: SetLastError? */
RETURN(ERROR);
}
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
rcCaret = rcScroll;
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
Result = UserScrollDC( hDC,
dx,
dy,
&rcScroll,
&rcClip,
NULL,
RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE);
/*
* Take into account the fact that some damage may have occurred during
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!RgnTemp)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(ERROR);
}
if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
{
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
if (RgnClip)
{
if (hrgnUpdate)
{
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
}
REGION_bOffsetRgn(RgnTemp, dx, dy);
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
if (hrgnUpdate)
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
REGION_Delete(RgnClip);
}
}
REGION_Delete(RgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
PWND Child;
RECTL rcChild;
POINT ClientOrigin;
USER_REFERENCE_ENTRY WndRef;
RECTL rcDummy;
LPARAM lParam;
IntGetClientOrigin(Window, &ClientOrigin);
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
rcChild = Child->rcWindow;
rcChild.left -= ClientOrigin.x;
rcChild.top -= ClientOrigin.y;
rcChild.right -= ClientOrigin.x;
rcChild.bottom -= ClientOrigin.y;
if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
{
UserRefObjectCo(Child, &WndRef);
if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
else
lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
/* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
/* windows sometimes a WM_MOVE */
co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
UserDerefObjectCo(Child);
}
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
{
co_UserRedrawWindow( Window,
NULL,
RgnUpdate,
rdw_flags | /* HACK */
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
}
if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
{
UserRefObjectCo(CaretWnd, &CaretRef);
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
co_UserShowCaret(CaretWnd);
UserDerefObjectCo(CaretWnd);
}
if (prcUnsafeUpdate)
{
_SEH2_TRY
{
/* Probe here, to not fail on invalid pointer before scrolling */
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
*prcUnsafeUpdate = rcUpdate;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(ERROR);
}
}
RETURN(Result);
CLEANUP:
if (hrgnUpdate && (_ret_ != ERROR))
{
/* Give everything back to the caller */
RgnTemp = REGION_LockRgn(hrgnUpdate);
/* The handle should still be valid */
ASSERT(RgnTemp);
if (RgnWinupd)
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
else
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
if (RgnWinupd)
{
REGION_Delete(RgnWinupd);
}
if (RgnUpdate)
{
REGION_Delete(RgnUpdate);
}
if (Window)
UserDerefObjectCo(Window);
TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
/* EOF */

View file

@ -123,7 +123,10 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu);
/*************** SCROLLBAR.C ***************/
DWORD FASTCALL
co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
DWORD FASTCALL co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
/************** NONCLIENT **************/
VOID FASTCALL DefWndDoSizeMove(PWND pwnd, WORD wParam);
/* EOF */