⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 painting.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
   }

   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 + -