C# WinForms:动态重写ToolStripProfessionalRenderer设置菜单项文本颜色
解决C# WinForms动态设置菜单项文本颜色的问题
先解释构造函数的作用
你的SkinRenderer构造函数是调用父类ToolStripProfessionalRenderer的构造方法,传入自定义MenuColorTable——父类会基于这个颜色表渲染菜单的背景、边框、分隔线等基础样式;你额外加的Console.WriteLine("test")只是构造实例时的测试输出。
动态设置文本颜色的两种实现方法
因为SkinRenderer是Form1的嵌套类,可以通过以下方式访问Form的变量,实现条件化颜色设置:
方法1:用委托回调解耦(推荐)
给SkinRenderer添加一个委托属性,用来动态获取文本颜色,避免直接依赖Form实例:
private class SkinRenderer : ToolStripProfessionalRenderer { // 定义回调委托,用于动态获取文本颜色 public Func<Color> TextColorProvider { get; set; } public SkinRenderer(MenuColorTable colorTable) : base(colorTable) { } protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { // 优先使用回调返回的颜色,无回调则用默认值 e.TextColor = TextColorProvider?.Invoke() ?? Color.FromArgb(220, 220, 220); // 调用父类方法完成文本渲染,不要自己调用TextRenderer.DrawText,避免样式冲突 base.OnRenderItemText(e); } }
在Form1的加载事件中初始化渲染器,并绑定回调:
// Form1的字段,示例条件变量 private int intVariable = 12; private void Form1_Load(object sender, EventArgs e) { var skinRenderer = new SkinRenderer(new MenuColorTable()); // 绑定颜色逻辑:根据intVariable的值返回对应颜色 skinRenderer.TextColorProvider = () => { return intVariable > 10 ? Color.Red : Color.FromArgb(220, 220, 220); }; menu.Renderer = skinRenderer; }
当intVariable变化时,调用menu.Invalidate()触发菜单重绘,颜色会自动更新:
// 比如修改变量后触发重绘 intVariable = 8; menu.Invalidate();
方法2:直接引用Form实例(简单直接)
利用嵌套类可访问外部类私有成员的特性,在SkinRenderer中持有Form1的引用:
private class SkinRenderer : ToolStripProfessionalRenderer { private readonly Form1 _form; public SkinRenderer(MenuColorTable colorTable, Form1 form) : base(colorTable) { _form = form; } protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { // 直接访问Form的变量判断条件 e.TextColor = _form.intVariable > 10 ? Color.Red : Color.FromArgb(220, 220, 220); base.OnRenderItemText(e); } }
Form1加载时初始化:
menu.Renderer = new SkinRenderer(new MenuColorTable(), this);
同样,变量变化后调用menu.Invalidate()更新渲染。
内容的提问来源于stack exchange,提问作者Roberto D V Leonardo
相关产品推荐
相关产品推荐

