如何解决.NET Core Windows Forms项目TextBox控件光标不闪烁问题
.NET Core 3.1/.NET 5 WinForms TextBox 光标不闪烁问题解决方案
问题根因
该问题为.NET Core 3.1、.NET 5版本Windows Forms运行时的已知底层bug,运行时对Win32原生光标消息的处理逻辑存在异常,默认拦截了系统的光标闪烁定时器触发逻辑,导致光标仅显示为固定实线,和.NET Framework的默认实现逻辑不一致。
修复方案
方案1:升级框架版本
直接升级项目到.NET 6及以上版本,微软已经在.NET 6的WinForms运行时中修复了该问题,升级后无需修改任何业务代码即可恢复TextBox光标默认闪烁效果。
方案2:自定义控件兼容(适用于必须保留在.NET Core 3.1/.NET 5的场景)
此前直接调用Win32 API无效的核心原因是调用时机错误,未避开.NET运行时的默认光标处理逻辑。可以通过继承TextBox重写窗口消息处理逻辑,接管光标生命周期实现闪烁效果,实现代码如下:
using System; using System.Runtime.InteropServices; using System.Windows.Forms; public class BlinkingTextBox : TextBox { [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool ShowCaret(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool DestroyCaret(); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern uint SetCaretBlinkTime(uint uMSeconds); protected override void WndProc(ref Message m) { const int WM_SETFOCUS = 0x0007; const int WM_KILLFOCUS = 0x0008; // 先执行基类逻辑,再接管光标处理 base.WndProc(ref m); switch (m.Msg) { case WM_SETFOCUS: // 销毁运行时创建的异常光标 DestroyCaret(); // 创建适配当前字体的光标,宽度可按需调整,此处用默认1px CreateCaret(Handle, IntPtr.Zero, 1, Font.Height); // 设置闪烁间隔,默认系统值为500毫秒,可自行调整 SetCaretBlinkTime(500); // 显示光标 ShowCaret(Handle); break; case WM_KILLFOCUS: // 失去焦点时销毁光标,避免资源泄漏 DestroyCaret(); break; } } }
使用方法
编译项目后,将窗体设计器中原本的TextBox控件替换为自定义的BlinkingTextBox控件即可,无需额外配置。
内容的提问来源于stack exchange,提问作者Dakusan
相关产品推荐
相关产品推荐

