You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cursor应用开发问题:C:\Windows\Cursors光标无法在flowLayoutPanel1显示

问题诊断与解决方案

核心问题分析

  1. 图像对象被提前释放:你在using (Image img = Image.FromFile(jpegFile))块内给btn.Image赋值,块结束后img会被自动Dispose,导致Button无法显示已释放的图像资源。
  2. 冗余的JPEG文件生成:没必要将.cur转成JPEG文件再读取,直接转换为内存中的Bitmap即可,既节省IO开销又避免文件权限问题。
  3. Button的图像布局未配置:默认Button的Image不会自适应按钮大小,需要设置ImageLayout属性让图像填满按钮区域。
  4. 点击事件中Tag的获取错误:你把光标路径存在btn.Tag上,但点击事件里却去取btn.Image.Tag,这会导致filePath为null,无法正确应用光标。

修改后的完整代码

using Microsoft.Win32;
using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;
using ImageMagick;

namespace CrossHare
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr LoadCursorFromFile(string lpFileName);

        private const int SPI_SETCURSORS = 0x0057;
        private const int SPIF_UPDATEINIFILE = 0x01;
        private const int SPIF_SENDCHANGE = 0x02;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 直接过滤.cur文件,避免后续判断
            string[] files = Directory.GetFiles(@"C:\Windows\Cursors", "*.cur"); 

            foreach (string file in files)
            {
                try
                {
                    Button btn = new Button();
                    btn.Size = new Size(100, 100);
                    btn.ImageAlign = ContentAlignment.MiddleCenter;
                    btn.ImageLayout = ImageLayout.Stretch; // 让图像自适应按钮大小
                    btn.Tag = file;
                    btn.Click += Button_Click;

                    // 直接将.cur转换为Bitmap,无需生成临时文件
                    using (MagickImage magickImg = new MagickImage(file))
                    {
                        btn.Image = magickImg.ToBitmap();
                    }

                    flowLayoutPanel1.Controls.Add(btn);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"加载光标失败:{ex.Message}");
                }
            }
        }

        private void Button_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            if (btn == null) return;

            string filePath = btn.Tag as string;
            if (string.IsNullOrEmpty(filePath)) return;

            // 更新注册表并应用光标
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Cursors", true))
            {
                key.SetValue("Arrow", filePath);
            }

            IntPtr hCursor = LoadCursorFromFile(filePath);
            if (hCursor != IntPtr.Zero)
            {
                SystemParametersInfo(SPI_SETCURSORS, 0, hCursor, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
                MessageBox.Show("光标已成功应用!");
            }
            else
            {
                MessageBox.Show("加载光标文件失败!");
            }
        }

        private void UploadButton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "Cursor files (*.cur)|*.cur|All files (*.*)|*.*";
                openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string filePath = openFileDialog.FileName;
                    string destinationPath = @"C:\Windows\Cursors";
                    string destinationFilePath = Path.Combine(destinationPath, Path.GetFileName(filePath));

                    if (File.Exists(destinationFilePath))
                    {
                        if (MessageBox.Show("文件已存在,是否覆盖?", "文件存在", MessageBoxButtons.YesNo) == DialogResult.No)
                        {
                            return;
                        }
                    }

                    try
                    {
                        File.Copy(filePath, destinationFilePath, true);
                        MessageBox.Show("文件上传成功!");
                        // 可选:上传后刷新光标列表
                        flowLayoutPanel1.Controls.Clear();
                        Form1_Load(sender, e);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"文件复制失败:{ex.Message}");
                    }
                }
            }
        }
    }
}

关键修改点说明

  • 移除临时文件操作:使用MagickImage.ToBitmap()直接将光标转换为内存Bitmap,避免文件IO和资源释放问题。
  • 优化图像显示:设置ImageLayout = ImageLayout.Stretch确保光标图像填满按钮,提升可见性。
  • 修复路径获取逻辑:直接从Button的Tag属性读取光标路径,解决点击事件中路径为空的问题。
  • 增强资源管理:用using块管理RegistryKey和OpenFileDialog,确保资源正确释放。
  • 完善错误处理:对LoadCursorFromFile的返回值做有效性判断,避免无效句柄引发异常。

内容的提问来源于stack exchange,提问作者Big Man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:50:24