📄 painting.c
字号:
RECT Rect;
ASSERT_REFS_CO(Window);
if (Window->UpdateRegion == NULL)
{
RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
}
else
{
Rect = Window->ClientRect;
IntIntersectWithParents(Window, &Rect);
NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->UpdateRegion, RGN_AND);
NtGdiOffsetRgn(hRgn, -Window->ClientRect.left, -Window->ClientRect.top);
}
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
{
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
}
return RegionType;
}
/*
* NtUserGetUpdateRgn
*
* Status
* @implemented
*/
INT STDCALL
NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
{
DECLARE_RETURN(INT);
PWINDOW_OBJECT Window;
INT ret;
USER_REFERENCE_ENTRY Ref;
DPRINT("Enter NtUserGetUpdateRgn\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(ERROR);
}
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
DWORD FASTCALL
UserScrollDC(HDC hDC, INT dx, INT dy, const RECT *lprcScroll,
const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
{
RECT rSrc, rClipped_src, rClip, rDst, offset;
PDC DC;
/*
* Compute device clipping region (in device coordinates).
*/
DC = DC_LockDc(hDC);
if (NULL == DC)
{
return FALSE;
}
if (lprcScroll)
rSrc = *lprcScroll;
else
IntGdiGetClipBox(hDC, &rSrc);
IntLPtoDP(DC, (LPPOINT)&rSrc, 2);
if (lprcClip)
rClip = *lprcClip;
else
IntGdiGetClipBox(hDC, &rClip);
IntLPtoDP(DC, (LPPOINT)&rClip, 2);
IntGdiIntersectRect(&rClipped_src, &rSrc, &rClip);
rDst = rClipped_src;
IntGdiSetRect(&offset, 0, 0, dx, dy);
IntLPtoDP(DC, (LPPOINT)&offset, 2);
IntGdiOffsetRect(&rDst, offset.right - offset.left, offset.bottom - offset.top);
IntGdiIntersectRect(&rDst, &rDst, &rClip);
/*
* Copy bits, if possible.
*/
if (rDst.bottom > rDst.top && rDst.right > rDst.left)
{
RECT rDst_lp = rDst, rSrc_lp = rDst;
IntGdiOffsetRect(&rSrc_lp, offset.left - offset.right, offset.top - offset.bottom);
IntDPtoLP(DC, (LPPOINT)&rDst_lp, 2);
IntDPtoLP(DC, (LPPOINT)&rSrc_lp, 2);
DC_UnlockDc(DC);
if (!NtGdiBitBlt(hDC, rDst_lp.left, rDst_lp.top, rDst_lp.right - rDst_lp.left,
rDst_lp.bottom - rDst_lp.top, hDC, rSrc_lp.left, rSrc_lp.top,
SRCCOPY, 0, 0))
return FALSE;
}
else
{
DC_UnlockDc(DC);
}
/*
* Compute update areas. This is the clipped source or'ed with the
* unclipped source translated minus the clipped src translated (rDst)
* all clipped to rClip.
*/
if (hrgnUpdate || lprcUpdate)
{
HRGN hRgn = hrgnUpdate, hRgn2;
if (hRgn)
NtGdiSetRectRgn(hRgn, rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom);
else
hRgn = NtGdiCreateRectRgn(rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom);
hRgn2 = UnsafeIntCreateRectRgnIndirect(&rSrc);
NtGdiOffsetRgn(hRgn2, offset.right - offset.left, offset.bottom - offset.top);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_OR);
NtGdiSetRectRgn(hRgn2, rDst.left, rDst.top, rDst.right, rDst.bottom);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_DIFF);
NtGdiSetRectRgn(hRgn2, rClip.left, rClip.top, rClip.right, rClip.bottom);
NtGdiCombineRgn(hRgn, hRgn, hRgn2, RGN_AND);
if (lprcUpdate)
{
NtGdiGetRgnBox(hRgn, lprcUpdate);
/* Put the lprcUpdate in logical coordinate */
NtGdiDPtoLP(hDC, (LPPOINT)lprcUpdate, 2);
}
if (!hrgnUpdate)
NtGdiDeleteObject(hRgn);
NtGdiDeleteObject(hRgn2);
}
return TRUE;
}
/*
* NtUserScrollDC
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserScrollDC(HDC hDC, INT dx, INT dy, const RECT *lprcScroll,
const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
{
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserScrollDC\n");
UserEnterExclusive();
RETURN( UserScrollDC(hDC, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate));
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 *UnsafeRect,
const RECT *UnsafeClipRect, HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags)
{
RECT rc, cliprc, caretrc, rect, clipRect;
INT Result;
PWINDOW_OBJECT Window = NULL, CaretWnd;
HDC hDC;
HRGN hrgnTemp;
HWND hwndCaret;
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
BOOL bOwnRgn = TRUE;
NTSTATUS Status;
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, &rc);
if (NULL != UnsafeRect)
{
Status = MmCopyFromCaller(&rect, UnsafeRect, sizeof(RECT));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( ERROR);
}
IntGdiIntersectRect(&rc, &rc, &rect);
}
if (NULL != UnsafeClipRect)
{
Status = MmCopyFromCaller(&clipRect, UnsafeClipRect, sizeof(RECT));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( ERROR);
}
IntGdiIntersectRect(&cliprc, &rc, &clipRect);
}
else
cliprc = rc;
if (cliprc.right <= cliprc.left || cliprc.bottom <= cliprc.top ||
(dx == 0 && dy == 0))
{
RETURN( NULLREGION);
}
caretrc = rc;
hwndCaret = co_IntFixCaret(Window, &caretrc, flags);
if (hrgnUpdate)
bOwnRgn = FALSE;
else if (bUpdate)
hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE);
if (hDC)
{
UserScrollDC(hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
UserReleaseDC(Window, hDC, FALSE);
}
/*
* Take into account the fact that some damage may have occurred during
* the scroll.
*/
hrgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
Result = co_UserGetUpdateRgn(Window, hrgnTemp, FALSE);
if (Result != NULLREGION)
{
HRGN hrgnClip = UnsafeIntCreateRectRgnIndirect(&cliprc);
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)
{
HWND *List = IntWinListChildren(Window);
if (List)
{
int i;
RECT r, dummy;
POINT ClientOrigin;
PWINDOW_OBJECT Wnd;
USER_REFERENCE_ENTRY WndRef;
IntGetClientOrigin(Window, &ClientOrigin);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -