📄 painting.c
字号:
}
UserRefObjectCo(Window, &Ref);
ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
UserDerefObjectCo(Window);
RETURN(ret);
CLEANUP:
DPRINT("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserGetUpdateRect
*
* Status
* @implemented
*/
BOOL STDCALL
NtUserGetUpdateRect(HWND hWnd, LPRECT UnsafeRect, BOOL bErase)
{
PWINDOW_OBJECT Window;
RECT Rect;
INT RegionType;
PROSRGNDATA RgnData;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserGetUpdateRect\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(FALSE);
}
if (Window->UpdateRegion == NULL)
{
Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
}
else
{
/* Get the update region bounding box. */
if (Window->UpdateRegion == (HRGN)1)
{
Rect = Window->ClientRect;
}
else
{
RgnData = RGNDATA_LockRgn(Window->UpdateRegion);
ASSERT(RgnData != NULL);
RegionType = UnsafeIntGetRgnBox(RgnData, &Rect);
RGNDATA_UnlockRgn(RgnData);
if (RegionType != ERROR && RegionType != NULLREGION)
IntGdiIntersectRect(&Rect, &Rect, &Window->ClientRect);
}
if (IntIntersectWithParents(Window, &Rect))
{
IntGdiOffsetRect(&Rect,
-Window->ClientRect.left,
-Window->ClientRect.top);
} else
{
Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
}
}
if (bErase && !IntGdiIsEmptyRect(&Rect))
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(Window, &Ref);
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
UserDerefObjectCo(Window);
}
if (UnsafeRect != NULL)
{
Status = MmCopyToCaller(UnsafeRect, &Rect, sizeof(RECT));
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN(FALSE);
}
}
RETURN(!IntGdiIsEmptyRect(&Rect));
CLEANUP:
DPRINT("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserRedrawWindow
*
* Status
* @implemented
*/
BOOL STDCALL
NtUserRedrawWindow(HWND hWnd, CONST RECT *lprcUpdate, HRGN hrgnUpdate,
UINT flags)
{
RECT SafeUpdateRect;
NTSTATUS Status;
PWINDOW_OBJECT Wnd;
DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserRedrawWindow\n");
UserEnterExclusive();
if (!(Wnd = UserGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
{
RETURN( FALSE);
}
if (lprcUpdate != NULL)
{
Status = MmCopyFromCaller(&SafeUpdateRect, (PRECT)lprcUpdate,
sizeof(RECT));
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
}
UserRefObjectCo(Wnd, &Ref);
Status = co_UserRedrawWindow(Wnd, NULL == lprcUpdate ? NULL : &SafeUpdateRect,
hrgnUpdate, flags);
UserDerefObjectCo(Wnd);
if (!NT_SUCCESS(Status))
{
/* IntRedrawWindow fails only in case that flags are invalid */
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
RETURN( TRUE);
CLEANUP:
DPRINT("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static
INT FASTCALL
UserScrollDC(HDC hDC, INT dx, INT dy, const RECT *prcScroll,
const RECT *prcClip, HRGN hrgnUpdate, LPRECT prcUpdate)
{
PDC pDC;
RECT rcScroll, rcSrc, rcDst;
INT Result;
IntGdiGetClipBox(hDC, &rcScroll);
if (prcScroll)
{
IntGdiIntersectRect(&rcScroll, &rcScroll, prcScroll);
}
if (prcClip)
{
IntGdiIntersectRect(&rcScroll, &rcScroll, prcClip);
}
rcDst = rcScroll;
IntGdiOffsetRect(&rcDst, dx, dy);
IntGdiIntersectRect(&rcDst, &rcDst, &rcScroll);
rcSrc = rcDst;
IntGdiOffsetRect(&rcSrc, -dx, -dy);
if (!NtGdiBitBlt(hDC, rcDst.left, rcDst.top,
rcDst.right - rcDst.left, rcDst.bottom - rcDst.top,
hDC, rcSrc.left, rcSrc.top, SRCCOPY, 0, 0))
{
return ERROR;
}
/* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */
if (hrgnUpdate || prcUpdate)
{
HRGN hrgnOwn, hrgnVisible, hrgnDst;
pDC = DC_LockDc(hDC);
if (!pDC)
{
return FALSE;
}
hrgnVisible = pDC->w.hVisRgn; // pDC->w.hGCClipRgn?
DC_UnlockDc(pDC);
if (hrgnUpdate)
{
hrgnOwn = hrgnUpdate;
if (!NtGdiSetRectRgn(hrgnOwn, rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom))
{
return ERROR;
}
}
else
{
hrgnOwn = UnsafeIntCreateRectRgnIndirect(&rcScroll);
}
hrgnDst = UnsafeIntCreateRectRgnIndirect(&rcSrc);
NtGdiCombineRgn(hrgnDst, hrgnDst, hrgnVisible, RGN_AND);
NtGdiOffsetRgn(hrgnDst, dx, dy);
Result = NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnDst, RGN_DIFF);
NtGdiDeleteObject(hrgnDst);
if (prcUpdate)
{
NtGdiGetRgnBox(hrgnOwn, prcUpdate);
}
if (!hrgnUpdate)
{
NtGdiDeleteObject(hrgnOwn);
}
}
else
Result = NULLREGION;
return Result;
}
/*
* NtUserScrollDC
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserScrollDC(HDC hDC, INT dx, INT dy, const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip, HRGN hrgnUpdate, LPRECT prcUnsafeUpdate)
{
DECLARE_RETURN(DWORD);
RECT rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Enter NtUserScrollDC\n");
UserEnterExclusive();
_SEH_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);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(FALSE);
}
if (UserScrollDC(hDC, dx, dy,
prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0, hrgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL) == ERROR)
{
/* FIXME: SetLastError? */
RETURN(FALSE);
}
if (prcUnsafeUpdate)
{
_SEH_TRY
{
*prcUnsafeUpdate = rcUpdate;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END
if (!NT_SUCCESS(Status))
{
/* FIXME: SetLastError? */
/* FIXME: correct? We have already scrolled! */
RETURN(FALSE);
}
}
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserScrollDC, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserScrollWindowEx
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserScrollWindowEx(HWND hWnd, INT dx, INT dy, const RECT *prcUnsafeScroll,
const RECT *prcUnsafeClip, HRGN hrgnUpdate, LPRECT prcUnsafeUpdate, UINT flags)
{
RECT rcScroll, rcClip, rcCaret, rcUpdate;
INT Result;
PWINDOW_OBJECT Window = NULL, CaretWnd;
HDC hDC;
HRGN hrgnOwn = NULL, hrgnTemp;
HWND hwndCaret;
NTSTATUS Status = STATUS_SUCCESS;
DECLARE_RETURN(DWORD);
USER_REFERENCE_ENTRY Ref, CaretRef;
DPRINT("Enter NtUserScrollWindowEx\n");
UserEnterExclusive();
Window = UserGetWindowObject(hWnd);
if (!Window || !IntIsWindowDrawable(Window))
{
Window = NULL; /* prevent deref at cleanup */
RETURN( ERROR);
}
UserRefObjectCo(Window, &Ref);
IntGetClientRect(Window, &rcScroll);
_SEH_TRY
{
if (prcUnsafeScroll)
{
ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
IntGdiIntersectRect(&rcScroll, &rcScroll, prcUnsafeScroll);
}
if (prcUnsafeClip)
{
ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
IntGdiIntersectRect(&rcClip, &rcScroll, prcUnsafeClip);
}
else
rcClip = rcScroll;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(ERROR);
}
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
(dx == 0 && dy == 0))
{
RETURN(NULLREGION);
}
if (hrgnUpdate)
hrgnOwn = hrgnUpdate;
else
hrgnOwn = NtGdiCreateRectRgn(0, 0, 0, 0);
hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE);
if (!hDC)
{
/* FIXME: SetLastError? */
RETURN(ERROR);
}
rcCaret = rcScroll;
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
Result = UserScrollDC(hDC, dx, dy, &rcScroll, &rcClip, hrgnOwn, prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE);
/*
* Take into account the fact that some damage may have occurred during
* the scroll.
*/
hrgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
if (co_UserGetUpdateRgn(Window, hrgnTemp, FALSE) != NULLREGION)
{
HRGN hrgnClip = UnsafeIntCreateRectRgnIndirect(&rcClip);
NtGdiOffsetRgn(hrgnTemp, dx, dy);
NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND);
co_UserRedrawWindow(Window, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE);
NtGdiDeleteObject(hrgnClip);
}
NtGdiDeleteObject(hrgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
PWINDOW_OBJECT Child;
RECT rcChild;
POINT ClientOrigin;
USER_REFERENCE_ENTRY WndRef;
RECT rcDummy;
IntGetClientOrigin(Window, &ClientOrigin);
for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
rcChild = Child->WindowRect;
rcChild.left -= ClientOrigin.x;
rcChild.top -= ClientOrigin.y;
rcChild.right -= ClientOrigin.x;
rcChild.bottom -= ClientOrigin.y;
if (! prcUnsafeScroll || IntGdiIntersectRect(&rcDummy, &rcChild, &rcScroll))
{
UserRefObjectCo(Child, &WndRef);
co_WinPosSetWindowPos(Child, 0, rcChild.left + dx, rcChild.top + dy, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
SWP_NOREDRAW);
UserDerefObjectCo(Child);
}
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
{
co_UserRedrawWindow(Window, NULL, hrgnOwn, RDW_INVALIDATE | RDW_ERASE |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
}
if ((CaretWnd = UserGetWindowObject(hwndCaret)))
{
UserRefObjectCo(CaretWnd, &CaretRef);
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
co_UserShowCaret(CaretWnd);
UserDerefObjectCo(CaretWnd);
}
if (prcUnsafeUpdate)
{
_SEH_TRY
{
/* Probe here, to not fail on invalid pointer before scrolling */
ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
*prcUnsafeUpdate = rcUpdate;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -