如何在Delphi中获取鼠标光标的尺寸?

3

我使用 Toolbar2000 组件。当系统缩放比例 > 100% 时,它会在正确的位置下方显示按钮提示。因此,我需要手动设置 HintPos。我有Mouse.CursorPos。但提示应该显示在鼠标光标图像下方。

如何获取鼠标光标的尺寸?


也许这个链接 http://msdn.microsoft.com/en-us/library/windows/desktop/ms648387(v=vs.85).aspx 是你正在寻找的内容? - user497849
1
@ComputerSaysNo,你的链接声称:“如果光标未限制在矩形内,则该结构接收屏幕的尺寸”。你真的认为整个桌面可能是光标的大小吗?那是完全不同的事情——那是一个光标无法移动到外面的窗口。 - Arioch 'The
3个回答

1
您可以创建一个图标,使用GetCursor设置句柄,可以使用GetIconInfo检索附加信息。即使显示用户定义的光标,这也将起作用,这些光标可能具有任何大小。
var
  ico: TIcon;
  IcoInfo: TIconInfo;
begin
  ico := TIcon.Create;
  try
    ico.Handle := GetCursor;
    try
      GetIconInfo(ico.Handle, IcoInfo);
      Caption := Format('Width %d, Height %d HotSpotX %d, HotSpotY %d',
        [ico.Width, ico.Height, IcoInfo.xHotspot, IcoInfo.yHotspot]);
    finally
      ico.ReleaseHandle;
    end;
  finally
    ico.Free;
  end;
end;


// Just as example for an very unusual cursor
procedure TForm1.Button1Click(Sender: TObject);
var
  IconInfo: TIconInfo;
  AndMask, Bmp: TBitmap;
  w, h: Integer;
begin
  w := Screen.Width * 2;
  h := Screen.Height * 2;

  // Creation And Mask
  AndMask := TBitmap.Create;
  AndMask.Monochrome := True;
  AndMask.Height := h;
  AndMask.Width := w;

  // Draw on And Mask
  AndMask.Canvas.Brush.Color := clWhite;
  AndMask.Canvas.FillRect(AndMask.Canvas.ClipRect);

  AndMask.Canvas.Pen.Color := clwhite;
  AndMask.Canvas.Pen.Width := 5;
  AndMask.Canvas.MoveTo(w div 2, 0);
  AndMask.Canvas.LineTo(w div 2, h);
  AndMask.Canvas.MoveTo(0, h div 2);
  AndMask.Canvas.LineTo(w, h div 2);

  {Create the "XOr" mask}
  Bmp := TBitmap.Create;

  Bmp.Width := w;
  Bmp.Height := h;

  {Draw on the "XOr" mask}
  Bmp.Canvas.Brush.Color := clblack;
  Bmp.Canvas.FillRect(Rect(0, 0, w, h));
  Bmp.Canvas.Pen.Color := clwhite;
  Bmp.Canvas.Pen.Width := 5;
  Bmp.Canvas.MoveTo(w div 2, 0);
  Bmp.Canvas.LineTo(w div 2, h);
  Bmp.Canvas.MoveTo(0, h div 2);
  Bmp.Canvas.LineTo(w, h div 2);


  IconInfo.fIcon := true;
  IconInfo.xHotspot := w div 2;
  IconInfo.yHotspot := h div 2;
  IconInfo.hbmMask := AndMask.Handle;
  IconInfo.hbmColor :=  Bmp.Handle;

  Screen.Cursors[1]:= CreateIconIndirect(IconInfo);
  Screen.Cursor:=1;

end;

寻找像素的问题(包括调整热点)在于鼠标指针由于内部或外部事件而可能在任何时刻发生变化... - Arioch 'The
我的重点不在于热点,尽管使用奇特的用户设计光标(例如提示光标)可能很有趣。我只是想展示一种获取所需数据的方法。 - bummi
上面的代码是否提供了一个带有大透明背景和光标指向(xHotspot,yHotspot)位置的图标?除了透明背景之外,是否有任何简单的方法来计算它的高度? - Dmitry
ico.Height 返回与 GetSystemMetrics(SM_CYCURSOR) 相同的错误值。我认为这是光标背景的大小,而不是光标本身的大小。 - Dmitry
@Altaveron 检索此信息需要逐行扫描位图,例如绘制在IcoInfo.hbmMask/hbmColor上的图标(光标)或从中生成的图像。 - bummi
2
@Altaveron,如果你想计算一个紧密的矩形,可以看一下这篇文章。但是你需要将光标图像与其掩码结合起来。</自我推广> :-) - TLama

1

您应该向Windows询问系统度量 - 参见http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385.aspx

然而,如果用户安装了诸如Stardock CursorFX之类的内容,这些值将不匹配用户实际看到的内容和他对程序的期望行为。

这似乎是Win32 API的限制之一,即该值不能被更改,除了来自旧批准集合中的一些相对较小的标准值。


@TLama,即使如此,它仍无法解决第三方Windows扩展的问题。还要考虑到光标可能每秒钟都会改变,由于任何Windows事件,例如插入新磁盘或其他事件。因此,如果您要进行像素寻找,您是否会每秒重复20次以在光标形状更改后移动提示窗口? - Arioch 'The
你在说什么?我们正在谈论光标,而不是第三方的东西。你至少应该提到SM_CXCURSORSM_CYCURSOR常量,而不仅仅是询问一个可能在今年失效的外部链接后面的内容。我不会投反对票,但你的回答有时确实值得这样做。我没有更多要说的了... - TLama
该链接是官方文档。SO不应成为其替代品。SO的链接可能会失效、不正确,或被编辑成不正确的内容。MSDN是这个问题的主要数据来源。此外,我无法理解为什么将链接到一个非官方博客与黑客式代码视为好事,而将链接到官方文档视为坏事。这看起来不一致。 - Arioch 'The
我已经尝试过这种方法,但是在视网膜显示器上,即使系统缩放为200%,GetSystemMetrics(SM_CYCURSOR)的值也比正确大小大5-10倍。 - Dmitry
1
光标是一张图片 - 这张图片有像物品一样的透明像素。它可以全部是透明像素或全部是不透明像素,但通常情况下,就像图标一样,它是两者的混合。系统度量是该图片的大小,但其中哪些像素是透明的或不透明的 - 系统度量无法知道。毕竟,光标可能每秒钟变化几次。 - Arioch 'The
显示剩余4条评论

0

这是Windows 7的问题,目前没有合适的解决方案。GetSystemMetrics(SM_CYCURSOR)返回带有背景的光标图像大小。而且似乎在系统缩放>100%时,这个值更加不正确。Delphi XE2也显示了位置不正确的提示。但有趣的是,资源管理器显示了正确位置的提示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接