【问题标题】:Windows cursor visible part sizeWindows 光标可见部分尺寸
【发布时间】:2017-04-28 09:59:32
【问题描述】:

我想显示一些类似于 ToolTip 的信息 - 我不能使用 ToolTip 因为它没有提供足够的自定义,我需要在鼠标悬停在 @987654330 上的整个过程中显示它@.
问题是 Cursor.Size 设置为 32x32,但光标的可见部分只有 12x19 像素,因此光标的可见部分和我想要显示的信息之间存在很大的差距(20x13 像素)(它是在其他 Windows 版本或鼠标光标设置上可能会有所不同。

我知道不同类型的光标(带有时钟/问号的箭头,手,...)都有较大的尺寸,但是如何计算可见部分的尺寸?
应该有某种方式,因为ToolTips 显示在光标的正下方。

ToolTip 的显示方式如下:

这是我的信息的显示方式:

【问题讨论】:

  • 也许你可以检查Cursor.Current.Size而不是Cursor.Current.Size
  • @m.rogalski 它返回相同的结果。
  • 只是想确定一下。您可以检查this example,然后找到最右下角的像素偏移。现在只是一个快速的想法。编辑:错误的链接,已修复
  • @m.rogalski 感谢您的帮助。你的链接帮助了我。我创建了一个解决方案并将其作为答案发布。
  • "我需要在鼠标悬停在控件上的整个过程中显示它" 您可以使用 ToolTipService Attached Properties 调整很多设置(包括 ShowDuration):EDIT 没关系,我刚刚看到你正在使用 WinForms。请改用this

标签: c# winforms mouse-cursor


【解决方案1】:

感谢m.rogalski(指给我this question)和this answerthis answerthis article 我能够创建计算鼠标光标可见部分的代码。由于它使用非托管代码,最大的问题是内存管理,所以我希望最后释放所有内容。如果不是,请告诉我。
外部

using System;
using System.Runtime.InteropServices;

namespace MouseCursorHelper
{
    /// <summary>
    /// Source: https://www.codeproject.com/kb/cs/desktopcapturewithmouse.aspx
    /// + DestroyIcon, DeleteObject
    /// </summary>
    class ExternalDlls
    {
        #region Class Variables

        public const Int32 CURSOR_SHOWING = 0x00000001;

        [StructLayout(LayoutKind.Sequential)]
        public struct ICONINFO
        {
            public bool fIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
            public Int32 xHotspot;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
            public Int32 yHotspot;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
            public IntPtr hbmMask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
            public IntPtr hbmColor;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public Int32 x;
            public Int32 y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CURSORINFO
        {
            public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
            public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
            public IntPtr hCursor;          // Handle to the cursor. 
            public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
        }

        #endregion

        #region Class Functions

        [DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
        public static extern bool GetCursorInfo(out CURSORINFO pci);

        [DllImport("user32.dll", EntryPoint = "CopyIcon")]
        public static extern IntPtr CopyIcon(IntPtr hIcon);

        [DllImport("user32.dll", EntryPoint = "GetIconInfo")]
        public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);

        [DllImport("user32.dll", EntryPoint = "DestroyIcon")]
        public static extern bool DestroyIcon(IntPtr hIcon);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);

        #endregion
    }
}

尺寸计算

using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace MouseCursorHelper
{
    class CursorActualSize
    {
        public static Size GetActualSize()
        {
            Bitmap bmp;
            IntPtr hicon;
            ExternalDlls.CURSORINFO ci = new ExternalDlls.CURSORINFO();
            ExternalDlls.ICONINFO icInfo;
            ci.cbSize = Marshal.SizeOf(ci);
            if (ExternalDlls.GetCursorInfo(out ci))
            {
                if (ci.flags == ExternalDlls.CURSOR_SHOWING)
                {
                    hicon = ExternalDlls.CopyIcon(ci.hCursor);
                    if (ExternalDlls.GetIconInfo(hicon, out icInfo))
                    {
                        bmp = Bitmap.FromHbitmap(icInfo.hbmMask);

                        var x = 0;
                        var y = 0;

                        for (var i = 0; i < bmp.Width; i++)
                        {
                            for (var j = 0; j < bmp.Height; j++)
                            {
                                var a = bmp.GetPixel(i, j);

                                if (a.R == 0 && a.G == 0 && a.B == 0)
                                {
                                    if (i > x)
                                    {
                                        x = i;
                                    }

                                    if (j > y)
                                    {
                                        y = j;
                                    }
                                }
                            }
                        }

                        bmp.Dispose();
                        if (hicon != IntPtr.Zero)
                        {
                            ExternalDlls.DestroyIcon(hicon);
                        }
                        if (icInfo.hbmColor != IntPtr.Zero)
                        {
                            ExternalDlls.DeleteObject(icInfo.hbmColor);
                        }
                        if (icInfo.hbmMask != IntPtr.Zero)
                        {
                            ExternalDlls.DeleteObject(icInfo.hbmMask);
                        }
                        if (ci.hCursor != IntPtr.Zero)
                        {
                            ExternalDlls.DeleteObject(ci.hCursor);
                        }

                        return new Size(x, y);
                    }

                    if (hicon != IntPtr.Zero)
                    {
                        ExternalDlls.DestroyIcon(hicon);
                    }
                    if (icInfo.hbmColor != IntPtr.Zero)
                    {
                        ExternalDlls.DeleteObject(icInfo.hbmColor);
                    }
                    if (icInfo.hbmMask != IntPtr.Zero)
                    {
                        ExternalDlls.DeleteObject(icInfo.hbmMask);
                    }
                }
            }

            if (ci.hCursor != IntPtr.Zero)
            {
                ExternalDlls.DeleteObject(ci.hCursor);
            }

            return new Size(0, 0);
        }
    }
}

然后只需调用

Size cursorSize = CursorActualSize.GetActualSize();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2018-06-01
    • 2011-03-04
    相关资源
    最近更新 更多