【问题标题】:How do I determine if the current mouse cursor is animated?如何确定当前鼠标光标是否为动画?
【发布时间】:2011-10-21 15:19:53
【问题描述】:

有没有办法确定当前鼠标光标是否动画?

前段时间我正在寻找一种方法how to save the current cursor。我发现 DrawIconEx 函数非常适合我的目的。不幸的是,我不知道如何确定当前光标是否为动画。我希望如果我将 istepIfAniCur 参数设置为 1 以防静态游标 DrawIconEx 返回 False 但它确实忽略了该参数并返回 True 什么不允许我在循环中使用它来获取静态游标以及所有从动画的帧。如果动画按预期工作,那么当您使用 istepIfAniCur 超出范围时,它会返回 False。

那么我如何确定 HICON (HCURSOR) 是动画光标? DrawIconEx 如何确定光标是动画的?

非常感谢

【问题讨论】:

  • 听起来你在写远程桌面软件。如果是这样,你不应该使用本地机器的光标吗?
  • @David - 是的,类似的东西。但我最后两个问题的提出主要是因为我的好奇心。当然,我必须显示在查看器一侧的光标集,我不能让用户摸索他身边的跳跃兔子光标到底是什么。我只停留在这个原始的东西上,想知道DrawIconEx 是如何识别你正在向它传递动画光标句柄的,在我的情况下它没有实际用途。
  • @David - 现在我正在考虑它;自定义光标的情况如何?在这种情况下,如果另一侧的用户正在绘图,让观众看到例如刷子会很好。如果是 OEM 光标,我当然会使用查看器的设置。
  • 也许您可以使用GetIconInfo 来检索与光标关联的位图的尺寸(使用GetObject)并得到numFrames = width_of_bitmap / height_of_bitmap`,假设所有光标都是方形的。
  • @user786653 - 我试过了,但它总是返回一帧的宽度。请参阅下面的 Delphi 示例的临时答案。

标签: c++ delphi winapi animated mouse-cursor


【解决方案1】:

我找到了一种解决方法 - 传递给 DrawIconEx 函数最大值 UINT 的 istepIfAniCur 参数。不可能有人会创建具有 4,294,967,295 帧的动画光标(可能用于某些光标电影:)

有了这个事实,您可以将此值传递给DrawIconEx 函数,如果光标处于动画状态(因为超出帧范围),该函数将返回 False,在静态光标的情况下返回 True,因为它忽略了 istepIfAniCur 参数.您应该将 0 传递给 diFlags 参数,因为不需要绘制任何东西。

这是 Delphi 示例:

if not DrawIconEx(Canvas.Handle, 0, 0, hCursor, 0, 0, High(Cardinal), 0, 0) then
  Caption := 'Cursor is animated ...'
else
  Caption := 'Cursor is not animated ...';

因为我答应了 C++ 标签,这是我的翻译尝试

if (!DrawIconEx(this->Canvas->Handle, 0, 0, hCursor, 0, 0, UINT_MAX, NULL, 0))
  this->Caption = "Cursor is animated ...";
else
  this->Caption = "Cursor is not animated ...";


操作系统错误ERROR_INVALID_PARAMETER 也指示超出帧范围,当DrawIconEx 失败时,您可以使用GetLastError 函数进行检查。

【讨论】:

    【解决方案2】:

    最好的方法:

          typedef HCURSOR(WINAPI* GET_CURSOR_FRAME_INFO)(HCURSOR, LPCWSTR, DWORD, DWORD*, DWORD*);
          GET_CURSOR_FRAME_INFO fnGetCursorFrameInfo = 0;
    
          HMODULE libUser32 = LoadLibraryA("user32.dll");
          if (!libUser32)
          {
            return false;
          }
    
          fnGetCursorFrameInfo = reinterpret_cast<GET_CURSOR_FRAME_INFO>(GetProcAddress(libUser32, "GetCursorFrameInfo"));
          if (!fnGetCursorFrameInfo)
          {
            return false;
          }
    
          DWORD displayRate, totalFrames;
          fnGetCursorFrameInfo(hcursor, L"", 0, &displayRate, &totalFrames);
    

    【讨论】:

    • 这是整个代码吗?最后感觉有些东西不见了
    • 据我所知,GetCursorFrameInfo 是一个未记录的 API,但我相信它应该为您提供显示速率和总帧数的信息。如果光标是静态的,我希望总帧数为 1(或可能为 0)。如果是动画,它应该告诉你动画一个周期有多少帧。
    【解决方案3】:

    这是 Delphi 中的示例(并尝试转换为 C++)我如何尝试使用 GetIconInfo 函数获取光标尺寸,但它并没有像我预期的那样工作。在动画光标的情况下,它总是返回一帧的宽度,因此GetIconInfo 似乎根本不关心帧。还是我错了?

    procedure TForm1.Timer1Timer(Sender: TObject);
    var
      IconInfo: TIconInfo;
      CursorInfo: TCursorInfo;
      Bitmap: Windows.TBitmap;
    begin
      CursorInfo.cbSize := SizeOf(CursorInfo);
      GetCursorInfo(CursorInfo);
      GetIconInfo(CursorInfo.hCursor, IconInfo);
    
      if GetObject(IconInfo.hbmColor, SizeOf(Bitmap), @Bitmap) <> 0 then
      begin
        Caption := 'Cursor size: ' +
                   IntToStr(Bitmap.bmWidth) + ' x ' +
                   IntToStr(Bitmap.bmHeight) + ' px';
      end;
    
      DeleteObject(IconInfo.hbmColor);
      DeleteObject(IconInfo.hbmMask);
    end;
    

    我的 Visual C++ 尝试(请注意,我不懂 C++,也没有编译器 :)

    CString txt;
    ICONINFO ii;
    CURSORINFO ci;
    BITMAP bitmap;
    
    ci.cbSize = SizeOf(CURSORINFO);
    GetCursorInfo(ci);
    GetIconInfo(ci.hCursor, ii);
    GetObject(ii.hbmColor, sizeof(BITMAP), &bitmap);
    txt.Format("Cursor width: %d px", bitmap.bmWidth);
    MessageBox(txt);
    

    【讨论】:

    • BitmapbmWidthBytes 成员怎么样?它可能具有“真实”宽度。
    • 返回 128,但我认为这不是我们需要的:The number of bytes in each scan line. This value must be divisible by 2, because the system assumes that the bit values of a bitmap form an array that is word aligned. 所以我想说,如果我们知道 B/px 我假设另一个函数调用是什么,这可能会起作用。跨度>
    • 假设您的光标是 32 位和 32x32,那么这也不好。这只是在黑暗中拍摄,希望它能返回动画光标帧的组合宽度。
    • @user786653 - 我也希望如此。这么简单的事情,做起来这么复杂。如果 MS 不忽略 istepIfAniCur 参数,那么我们将能够在一个循环中绘制静态光标或动画的所有帧。
    • 一张 32x32px、每像素 1 位的图像将使用 128 字节。
    猜你喜欢
    • 1970-01-01
    • 2014-02-23
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多