【问题标题】:Using Custom Colored Cursors in a C# Windows Application [closed]在 C# Windows 应用程序中使用自定义彩色光标 [关闭]
【发布时间】:2010-11-29 16:33:21
【问题描述】:

我正在开发一个 SDG(单显示组件)应用程序,为此我需要多个光标(最简单的不同颜色)用于单个窗口。我知道使用 C# 可以只使用黑白光标,这并不能解决我的问题。

【问题讨论】:

  • 彩色光标工作正常。你是怎么发现只能使用黑白光标的?
  • Windows 会让你拥有超过 1 个光标吗?
  • 我曾经需要动态创建动态光标。事实证明这会带来奇怪的问题,特别是因为半透明会与黑色混合并使光标太暗。最后我在 SO 社区的帮助下解决了这个问题,整个解决方案显示在这里:https://stackoverflow.com/questions/1236473/windows-forms-making-a-cursor-bitmap-partially-transparent
  • @Tim - 我在一个 C# 论坛上读到,使用默认的 Cursor 类,您只能使用黑白光标(甚至不能使用灰度光标)。
  • @Henk - 我正在使用一个名为 SDGToolkit(来自卡尔加里大学)的 C# API,它完成了从键盘和鼠标甚至平板电脑获取多个输入的所有低级工作。

标签: c# custom-controls cursors


【解决方案1】:

Cursor 类做得很差。由于某种神秘的原因,它使用了旧的 COM 接口 (IPicture),该接口不支持彩色和动画光标。它可以用一些相当难看的肘部油脂修复:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;

static class NativeMethods {
    public static Cursor LoadCustomCursor(string path) {
        IntPtr hCurs = LoadCursorFromFile(path);
        if (hCurs == IntPtr.Zero) throw new Win32Exception();
        var curs = new Cursor(hCurs);
        // Note: force the cursor to own the handle so it gets released properly
        var fi = typeof(Cursor).GetField("ownHandle", BindingFlags.NonPublic | BindingFlags.Instance);
        fi.SetValue(curs, true);
        return curs;
    }
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr LoadCursorFromFile(string path);
}

示例用法:

this.Cursor = NativeMethods.LoadCustomCursor(@"c:\windows\cursors\aero_busy.ani");

【讨论】:

  • 感谢汉斯,你最近一直是我的英雄。我只想补充一点,如果有人从Control 构造函数内部加载它,其路径目录类似于"aero_busy.ani"(假设.ani 文件存在于根应用程序目录中),这将使Designer 变为停止工作,所以在我的情况下,我返回 nullptr 而不是抛出 Win32Exception 然后只更改 Cursor 如果它不同于 nullptr
【解决方案2】:

我也尝试了一些不同的方法,它似乎适用于不同颜色的光标,但这段代码的唯一问题是鼠标光标的热点坐标不准确,即略微向右移动。但这可以通过考虑代码中的偏移来解决。

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace MID
{    
    public partial class CustomCursor : Form
    {
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr LoadCursorFromFile(string filename);

        public CustomCursor()
        {
            InitializeComponent();

            Bitmap bmp = (Bitmap)Bitmap.FromFile("Path of the cursor file saved as .bmp");
            bmp.MakeTransparent(Color.Black);
            IntPtr ptr1 = blue.GetHicon();

            Cursor cur = new Cursor(ptr1);
            this.Cursor = cur;

        }
    }
}

【讨论】:

    【解决方案3】:

    这个帖子已经很老了,但它是 Google 上的第一个热门话题,所以这里是 VS 2019 的答案:

    someControl.Cursor = new Cursor(Properties.Resources.somePNG.GetHicon());
    

    您应该添加具有您喜欢的任何透明度的“somePNG.png”作为项目资源。

    希望它在 2020 年对某人有所帮助。

    【讨论】:

      【解决方案4】:

      您可以像这样从文件中动态加载游标:

      var myCursor = new Cursor("myCursor.cur");
      

      加载后,你可以像这样设置任何控件的光标:

      myControl.Cursor = myCursor;
      

      游标也接受流作为构造函数参数。这意味着您可以从应用程序中嵌入的资源加载,而不是从文件系统加载。

      Windows 不允许您拥有多个光标,但您可以在控件上绘制多个光标。您可以像这样使用光标对象的Draw 方法:

      myCursor.Draw(g, new Rectangle(...));
      

      如果您使用 TCP/IP 在客户端之间发送游标数据,那么这应该足够了。

      但是,有一些应用程序支持在单台 PC 上进行多输入。 (例如,Rag Doll Kung Fu)为此,您正在查看 .NET 框架不支持的内容。

      您可能需要研究 PInvoking 一些 USB 调用。 (我在这里没有太多经验,所以我无法详细说明。)

      【讨论】:

      • 谢谢约翰,但我实际上尝试过,但它对我不起作用,对于我的 Windows 应用程序上的多个鼠标控件,基本上我使用的是一个名为 SDGToolkit 的 C# API,它处理所有低级东西。
      【解决方案5】:

      唯一的问题是热点将位于文件的中心。所以要么:

      使文件宽两倍,高两倍,并将图标放在右下象限。

      或者

      使用这个复杂的代码来调整热点: Change Cursor HotSpot in WinForms / .NET

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-04
        • 2011-10-08
        • 2011-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多