Windows光标可见部件大小

时间:2016-12-13 10:59:49

标签: c# winforms mouse-cursor

我希望显示一些与ToolTip类似的信息 - 我无法使用ToolTip,因为它没有提供足够的自定义,我需要将其展示给整个鼠标时间超过Control 问题是Cursor.Size设置为32x32,但光标的可见部分只有12x19像素,因此光标的可见部分和我想要显示的信息之间存在很大的间隙(20x13像素)(在其他Windows版本或鼠标光标设置上可能会有所不同。)

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

这就是显示ToolTip的方式:
standard tooltip
这就是我的信息显示方式:
my tooltip

1 个答案:

答案 0 :(得分:1)

感谢m.rogalski(指向我this question)和this answer以及this 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();