cursoricon.c

来自「一个类似windows」· C语言 代码 · 共 1,531 行 · 第 1/3 页

C
1,531
字号

   CurInfo = IntGetSysCursorInfo(WinSta);
   if(CurInfo->CursorClipInfo.IsClipped)
   {
      Rect.left = CurInfo->CursorClipInfo.Left;
      Rect.top = CurInfo->CursorClipInfo.Top;
      Rect.right = CurInfo->CursorClipInfo.Right;
      Rect.bottom = CurInfo->CursorClipInfo.Bottom;
   }
   else
   {
      Rect.left = 0;
      Rect.top = 0;
      Rect.right = UserGetSystemMetrics(SM_CXSCREEN);
      Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
   }

   Status = MmCopyToCaller((PRECT)lpRect, &Rect, sizeof(RECT));
   if(!NT_SUCCESS(Status))
   {
      ObDereferenceObject(WinSta);
      SetLastNtError(Status);
      RETURN( FALSE);
   }

   ObDereferenceObject(WinSta);

   RETURN( TRUE);

CLEANUP:
   DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}


/*
 * @implemented
 */
HCURSOR
STDCALL
NtUserSetCursor(
   HCURSOR hCursor)
{
   PCURICON_OBJECT CurIcon;
   HICON OldCursor;
   PWINSTATION_OBJECT WinSta;
   DECLARE_RETURN(HCURSOR);

   DPRINT("Enter NtUserSetCursor\n");
   UserEnterExclusive();

   WinSta = IntGetWinStaObj();
   if(WinSta == NULL)
   {
      RETURN(NULL);
   }
   
   if(!(CurIcon = UserGetCurIconObject(hCursor)))
   {
      ObDereferenceObject(WinSta);
      RETURN(NULL);
   }
   
   OldCursor = IntSetCursor(WinSta, CurIcon, FALSE);

   ObDereferenceObject(WinSta);
   
   RETURN(OldCursor);

CLEANUP:
   DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}


/*
 * @implemented
 */
BOOL
STDCALL
NtUserSetCursorIconContents(
   HANDLE hCurIcon,
   PICONINFO IconInfo)
{
   PCURICON_OBJECT CurIcon;
   PBITMAPOBJ bmp;
   PWINSTATION_OBJECT WinSta;
   NTSTATUS Status;
   BOOL Ret = FALSE;
   DECLARE_RETURN(BOOL);

   DPRINT("Enter NtUserSetCursorIconContents\n");
   UserEnterExclusive();

   WinSta = IntGetWinStaObj();
   if(WinSta == NULL)
   {
      RETURN( FALSE);
   }

   if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
   {
      ObDereferenceObject(WinSta);
      RETURN(FALSE);      
   }

   /* Copy fields */
   Status = MmCopyFromCaller(&CurIcon->IconInfo, IconInfo, sizeof(ICONINFO));
   if(!NT_SUCCESS(Status))
   {
      SetLastNtError(Status);
      goto done;
   }

   bmp = BITMAPOBJ_LockBitmap(CurIcon->IconInfo.hbmColor);
   if(bmp)
   {
      CurIcon->Size.cx = bmp->SurfObj.sizlBitmap.cx;
      CurIcon->Size.cy = bmp->SurfObj.sizlBitmap.cy;
      BITMAPOBJ_UnlockBitmap(bmp);
      GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmColor, NULL);
   }
   else
   {
      bmp = BITMAPOBJ_LockBitmap(CurIcon->IconInfo.hbmMask);
      if(!bmp)
         goto done;

      CurIcon->Size.cx = bmp->SurfObj.sizlBitmap.cx;
      CurIcon->Size.cy = bmp->SurfObj.sizlBitmap.cy / 2;

      BITMAPOBJ_UnlockBitmap(bmp);
      GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
   }

   Ret = TRUE;

done:

   ObDereferenceObject(WinSta);
   RETURN( Ret);

CLEANUP:
   DPRINT("Leave NtUserSetCursorIconContents, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}


/*
 * @implemented
 */
BOOL
STDCALL
NtUserSetCursorIconData(
   HANDLE hCurIcon,
   PBOOL fIcon,
   POINT *Hotspot,
   HMODULE hModule,
   HRSRC hRsrc,
   HRSRC hGroupRsrc)
{
   PCURICON_OBJECT CurIcon;
   PWINSTATION_OBJECT WinSta;
   NTSTATUS Status;
   POINT SafeHotspot;
   BOOL Ret = FALSE;
   DECLARE_RETURN(BOOL);

   DPRINT("Enter NtUserSetCursorIconData\n");
   UserEnterExclusive();

   WinSta = IntGetWinStaObj();
   if(WinSta == NULL)
   {
      RETURN( FALSE);
   }

   if(!(CurIcon = UserGetCurIconObject(hCurIcon)))
   {
      ObDereferenceObject(WinSta);
      RETURN(FALSE);
   }

   CurIcon->hModule = hModule;
   CurIcon->hRsrc = hRsrc;
   CurIcon->hGroupRsrc = hGroupRsrc;

   /* Copy fields */
   if(fIcon)
   {
      Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL));
      if(!NT_SUCCESS(Status))
      {
         SetLastNtError(Status);
         goto done;
      }
   }
   else
   {
      if(!Hotspot)
         Ret = TRUE;
   }

   if(Hotspot)
   {
      Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT));
      if(NT_SUCCESS(Status))
      {
         CurIcon->IconInfo.xHotspot = SafeHotspot.x;
         CurIcon->IconInfo.yHotspot = SafeHotspot.y;

         Ret = TRUE;
      }
      else
         SetLastNtError(Status);
   }

   if(!fIcon && !Hotspot)
   {
      Ret = TRUE;
   }

done:
   ObDereferenceObject(WinSta);
   RETURN( Ret);


CLEANUP:
   DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}


/*
 * @unimplemented
 */
BOOL
STDCALL
NtUserSetSystemCursor(
   HCURSOR hcur,
   DWORD id)
{
   return FALSE;
}


#define STRETCH_CAN_SRCCOPY_ONLY

#ifdef STRETCH_CAN_SRCCOPY_ONLY
void
FASTCALL
DoStretchBlt(HDC DcDest, int XDest, int YDest, int WidthDest, int HeightDest,
             HDC DcSrc, int XSrc, int YSrc, int WidthSrc, int HeightSrc,
             DWORD Rop3, BOOL Color)
{
   HDC DcStretched;
   HBITMAP BitmapStretched;
   HBITMAP OldBitmap;

   if (WidthDest == WidthSrc && HeightDest == HeightSrc)
   {
      NtGdiBitBlt(DcDest, XDest, YDest, WidthDest, HeightDest,
                  DcSrc, XSrc, YSrc, Rop3, 0, 0);
   }
   else if (SRCCOPY == Rop3)
   {
      NtGdiStretchBlt(DcDest, XDest, YDest, WidthDest, HeightDest,
                      DcSrc, XSrc, YSrc, WidthSrc, HeightSrc,
                      Rop3, 0);
   }
   else
   {
      DcStretched = NtGdiCreateCompatibleDC(DcSrc);
      if (NULL == DcStretched)
      {
         DPRINT1("Failed to create compatible DC\n");
         return;
      }
      if (Color)
      {
         BitmapStretched = NtGdiCreateCompatibleBitmap(DcDest, WidthDest,
                                                       HeightDest);
      }
      else
      {
         BitmapStretched = NtGdiCreateBitmap(WidthDest, HeightDest, 1, 1, NULL);
      }
      if (NULL == BitmapStretched)
      {
         NtGdiDeleteObjectApp(DcStretched);
         DPRINT1("Failed to create temporary bitmap\n");
         return;
      }
      OldBitmap = NtGdiSelectObject(DcStretched, BitmapStretched);
      if (NULL == OldBitmap)
      {
         NtGdiDeleteObject(BitmapStretched);
         NtGdiDeleteObjectApp(DcStretched);
         DPRINT1("Failed to create temporary bitmap\n");
         return;
      }
      if (! NtGdiStretchBlt(DcStretched, 0, 0, WidthDest, HeightDest,
                            DcSrc, XSrc, YSrc, WidthSrc, HeightSrc,
                            SRCCOPY, 0) ||
          ! NtGdiBitBlt(DcDest, XDest, YDest, WidthDest, HeightDest,
                        DcStretched, 0, 0, Rop3, 0, 0))
      {
         DPRINT1("Failed to blt\n");
      }
      NtGdiSelectObject(DcStretched, OldBitmap);
      NtGdiDeleteObject(BitmapStretched);
      NtGdiDeleteObjectApp(DcStretched);
   }
}
#else
#define DoStretchBlt(DcDest, XDest, YDest, WidthDest, HeightDest, \
                     DcSrc, XSrc, YSrc, WidthSrc, HeightSrc, Rop3, Color) \
        NtGdiStretchBlt((DcDest), (XDest), (YDest), (WidthDest), (HeightDest), \
                        (DcSrc), (XSrc), (YSrc), (WidthSrc), (HeightSrc), \
                        (Rop3), 0)
#endif /* STRETCH_CAN_SRCCOPY_ONLY */

/*
 * @implemented
 */
BOOL
STDCALL
NtUserDrawIconEx(
   HDC hdc,
   int xLeft,
   int yTop,
   HICON hIcon,
   int cxWidth,
   int cyHeight,
   UINT istepIfAniCur,
   HBRUSH hbrFlickerFreeDraw,
   UINT diFlags,
   DWORD Unknown0,
   DWORD Unknown1)
{
   PCURICON_OBJECT CurIcon;
   PWINSTATION_OBJECT WinSta;
   HBITMAP hbmMask, hbmColor;
   BITMAP bmpMask, bmpColor;
   BOOL DoFlickerFree;
   SIZE IconSize;
   COLORREF oldFg, oldBg;
   HDC hdcMem, hdcOff = (HDC)0;
   HBITMAP hbmOff = (HBITMAP)0;
   HGDIOBJ hOldOffBrush = 0, hOldOffBmp = 0, hOldMem;
   BOOL Ret = FALSE;
   INT nStretchMode;

   DECLARE_RETURN(BOOL);

   DPRINT("Enter NtUserDrawIconEx\n");
   UserEnterExclusive();

   WinSta = IntGetWinStaObj();
   if(WinSta == NULL)
   {
      RETURN( FALSE);
   }

   if (!(CurIcon = UserGetCurIconObject(hIcon)))
   {
      ObDereferenceObject(WinSta);
      RETURN(FALSE);
   }
   
   hbmMask = CurIcon->IconInfo.hbmMask;
   hbmColor = CurIcon->IconInfo.hbmColor;

   if(istepIfAniCur)
      DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");

   if(!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), &bmpMask))
      goto done;

   if(hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), &bmpColor))
      goto done;

   if(hbmColor)
   {
      IconSize.cx = bmpColor.bmWidth;
      IconSize.cy = bmpColor.bmHeight;
   }
   else
   {
      IconSize.cx = bmpMask.bmWidth;
      IconSize.cy = bmpMask.bmHeight / 2;
   }

   if(!diFlags)
      diFlags = DI_NORMAL;

   if(!cxWidth)
      cxWidth = ((diFlags & DI_DEFAULTSIZE) ? UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
   if(!cyHeight)
      cyHeight = ((diFlags & DI_DEFAULTSIZE) ? UserGetSystemMetrics(SM_CYICON) : IconSize.cy);

   DoFlickerFree = (hbrFlickerFreeDraw && (NtGdiGetObjectType(hbrFlickerFreeDraw) == OBJ_BRUSH));

   if(DoFlickerFree)
   {
      RECT r;
      r.right = cxWidth;
      r.bottom = cyHeight;

      hdcOff = NtGdiCreateCompatibleDC(hdc);
      if(!hdcOff)
         goto done;

      hbmOff = NtGdiCreateCompatibleBitmap(hdc, cxWidth, cyHeight);
      if(!hbmOff)
      {
         NtGdiDeleteObjectApp(hdcOff);
         goto done;
      }
      hOldOffBrush = NtGdiSelectObject(hdcOff, hbrFlickerFreeDraw);
      hOldOffBmp = NtGdiSelectObject(hdcOff, hbmOff);
      NtGdiPatBlt(hdcOff, 0, 0, r.right, r.bottom, PATCOPY);
      NtGdiSelectObject(hdcOff, hbmOff);
   }

   hdcMem = NtGdiCreateCompatibleDC(hdc);
   if(!hdcMem)
      goto cleanup;

   if(!DoFlickerFree)
      hdcOff = hdc;

   nStretchMode = NtGdiSetStretchBltMode(hdcOff, STRETCH_DELETESCANS);

   oldFg = NtGdiSetTextColor(hdcOff, RGB(0, 0, 0));
   oldBg = NtGdiSetBkColor(hdcOff, RGB(255, 255, 255));

   if(diFlags & DI_MASK)
   {
      hOldMem = NtGdiSelectObject(hdcMem, hbmMask);

      DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
                   (DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
                   0, 0, IconSize.cx, IconSize.cy,
                   ((diFlags & DI_IMAGE) ? SRCAND : SRCCOPY), FALSE);

      if(!hbmColor && (bmpMask.bmHeight == 2 * bmpMask.bmWidth) && (diFlags & DI_IMAGE))
      {
         DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
                      (DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
                      0, IconSize.cy, IconSize.cx, IconSize.cy, SRCINVERT,
                      FALSE);

         diFlags &= ~DI_IMAGE;
      }
      NtGdiSelectObject(hdcMem, hOldMem);
   }

   if(diFlags & DI_IMAGE)
   {
      hOldMem = NtGdiSelectObject(hdcMem, (hbmColor ? hbmColor : hbmMask));

      DoStretchBlt(hdcOff, (DoFlickerFree ? 0 : xLeft),
                   (DoFlickerFree ? 0 : yTop), cxWidth, cyHeight, hdcMem,
                   0, (hbmColor ? 0 : IconSize.cy), IconSize.cx, IconSize.cy,
                   ((diFlags & DI_MASK) ? SRCINVERT : SRCCOPY),
                   NULL != hbmColor);

      NtGdiSelectObject(hdcMem, hOldMem);
   }

   if(DoFlickerFree)
      NtGdiBitBlt(hdc, xLeft, yTop, cxWidth, cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0);

   NtGdiSetTextColor(hdcOff, oldFg);
   NtGdiSetBkColor(hdcOff, oldBg);

   NtGdiSetStretchBltMode(hdcOff, nStretchMode);

   Ret = TRUE;

cleanup:
   if(DoFlickerFree)
   {

      NtGdiSelectObject(hdcOff, hOldOffBmp);
      NtGdiSelectObject(hdcOff, hOldOffBrush);
      NtGdiDeleteObject(hbmOff);
      NtGdiDeleteObjectApp(hdcOff);
   }
   if(hdcMem)
      NtGdiDeleteObjectApp(hdcMem);

done:
   ObDereferenceObject(WinSta);

   RETURN( Ret);

CLEANUP:
   DPRINT("Leave NtUserDrawIconEx, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?