Windows Forms 控件的 Cursor 屬性僅支持靜態 .cur 文件,不支持動畫光標 .ani。需調用 Win32 API:LoadCursorFromFile 加載光標文件,SetSystemCursor 設置系統類光標。
using System.Runtime.InteropServices;
public static class NativeMethods {
// 從文件加載光標(支持 .cur 和 .ani)
[DllImport("user32.dll", EntryPoint = "LoadCursorFromFileW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadCursorFromFile(string lpFileName);
// 設置系統光標
[DllImport("user32.dll", EntryPoint = "SetSystemCursor", SetLastError = true)]
public static extern bool SetSystemCursor(IntPtr hcur, uint id);
// 系統光標 ID 常量
public const uint OCR_NORMAL = 32512; // 普通箭頭
public const uint OCR_IBEAM = 32513; // 文本輸入
public const uint OCR_WAIT = 32514; // 等待(沙漏)
public const uint OCR_CROSS = 32515; // 十字
public const uint OCR_UP = 32516; // 向上箭頭
public const uint OCR_SIZENWSE = 32517; // 雙向調整大小
public const uint OCR_SIZENESW = 32518;
public const uint OCR_SIZEWE = 32519;
public const uint OCR_SIZENS = 32520;
public const uint OCR_SIZEALL = 32521;
public const uint OCR_NO = 32648; // 禁止
public const uint OCR_HAND = 32649; // 手形
public const uint OCR_APPSTARTING = 32650; // 應用啟動中
}
public partial class MainForm : Form {
private IntPtr _customCursor = IntPtr.Zero;
private IntPtr _originalCursor = IntPtr.Zero;
private const string CursorFileName = "custom_cursor.ani"; // 放在輸出目錄
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
string path = Path.Combine(Application.StartupPath, CursorFileName);
if (File.Exists(path)) {
// 保存原始系統光標(可選,這裡演示加載默認箭頭作為恢復)
_originalCursor = NativeMethods.LoadCursorFromFile(@"C:\Windows\Cursors\arrow.cur");
// 加載自定義動畫光標
_customCursor = NativeMethods.LoadCursorFromFile(path);
if (_customCursor != IntPtr.Zero) {
NativeMethods.SetSystemCursor(_customCursor, NativeMethods.OCR_NORMAL);
}
}
}
protected override void OnFormClosing(FormClosingEventArgs e) {
// 恢復系統默認光標
if (_originalCursor != IntPtr.Zero) {
NativeMethods.SetSystemCursor(_originalCursor, NativeMethods.OCR_NORMAL);
}
base.OnFormClosing(e);
}
}
SetSystemCursor 修改的是**系統級**光標,影響所有應用程序。僅在窗體激活時設置,關閉時恢復,否則用戶離開程序後光標仍為動畫。.ani 文件需設置「複製到輸出目錄」為「較新時複製」或「始終複製」。Marshal.GetLastWin32Error() 為 5/ERROR_ACCESS_DENIED)。MouseEnter 設置 this.Cursor = new Cursor(cursorStream)(僅支持靜態 .cur),或用 SetClassLongPtr 修改窗體類光標(僅影響該窗體類實例)。LoadCursorFromFile 返回的句柄由系統管理,無需手動 DestroyCursor,但最好在應用退出時恢復原狀。[DllImport("user32.dll", EntryPoint = "SetClassLongPtr", SetLastError = true)]
private static extern IntPtr SetClassLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr", SetLastError = true)]
private static extern IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex);
private const int GCLP_HCURSOR = -12;
public void SetFormCursor(string aniPath) {
IntPtr hCursor = NativeMethods.LoadCursorFromFile(aniPath);
if (hCursor != IntPtr.Zero) {
// 修改窗體類光標,僅影響該窗體實例
SetClassLongPtr(this.Handle, GCLP_HCURSOR, hCursor);
// 強制重繪
this.Invalidate();
}
}
此法無需管理員權限,僅影響當前窗體類的所有實例,體驗更好。