平面按钮样式 - 当按钮处于活动状态时隐藏边框和焦点提示
Flat Button Style - Hide border and Focus Cue when the Button is active
我创建了一个带有透明边框的平面按钮,还设置了 FlatAppearance.BorderSize = 0
。
单击鼠标时边框隐藏,按下鼠标按钮时按钮背景使用自定义颜色。
我的问题是无法移除当 Button 激活时绘制的边框,例如按 Tab 键。
我不能使用 TabStop
属性(将其设置为 false),因为我想要我设计的功能。
我只想绘制背景颜色并隐藏边框(与鼠标单击颜色相同)。
窗体设计器中的按钮属性:
this.importBtn.BackgroundImage = global::CompetitionManager.Properties.Resources.Open;
this.importBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.importBtn.Cursor = System.Windows.Forms.Cursors.Hand;
this.importBtn.Delta = 5;
this.importBtn.Dock = System.Windows.Forms.DockStyle.Fill;
this.importBtn.FlatAppearance.BorderSize = 0;
this.importBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.SteelBlue;
this.importBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
this.importBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.importBtn.ForeColor = System.Drawing.Color.Transparent;
this.importBtn.Location = new System.Drawing.Point(3, 50);
this.importBtn.MoveXDirection = false;
this.importBtn.MoveYDirection = true;
this.importBtn.Name = "importBtn";
this.importBtn.Size = new System.Drawing.Size(183, 162);
this.importBtn.TabIndex = 0;
this.ToolTip.SetToolTip(this.importBtn, "Import Competitors (Excel/XML)");
this.importBtn.UseMargin = true;
this.importBtn.UseVisualStyleBackColor = true;
this.importBtn.Click += new System.EventHandler(this.ImportFile_Click);
如问题中所述,自定义控件 - 此处为按钮 - 在变为 ActiveControl 时显示其标准焦点提示。默认渲染似乎不适合,因为背景颜色在特定上下文中呈现透明,导致标准 Focus Cue 变得令人讨厌。
▶ 禁用标准 Focus Cue 渲染,覆盖 Control.ShowFocusCues 始终 return false
(尚未创建句柄时除外)。
▶ NotifyDefault 方法也被覆盖,以避免在 Button 用于打开变为活动状态的 Windows 时出现类似的 效果 :在在这种情况下,Button 呈现为带有边框,这意味着它是 Window.
的 ActiveControl 的视觉线索
▶ 一些定义 Button specialization 的属性已使用自定义 ControlDesigner 从 PropertyGrid 中删除,以避免对特定 defining[ 进行不必要的篡改=34=]属性。
最后,在自定义控件的 ClientRectangle 底部绘制一个自定义焦点提示,以提供一些反馈,否则用户将不知道当前Button/Control是。
鼠标悬停或单击按钮时不显示自定义提示。
这是一个可能的自定义渲染示例。当然,您现在可以随心所欲地绘制:不同的 边框 、背景、半透明叠加等
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[ToolboxItem(true)]
[DesignerCategory("code")]
[Designer(typeof(CustomDesigner))]
public class ImportButton : Button
{
private Color m_FocusColor = Color.LightBlue;
private bool m_DrawFocusCue = false;
public ImportButton() {
this.Cursor = Cursors.Hand;
this.Image = new Bitmap(Properties.Resources.[SomeImage]);
this.FlatAppearance.BorderSize = 0;
this.FlatAppearance.MouseDownBackColor = Color.SteelBlue;
this.FlatAppearance.MouseOverBackColor = Color.Transparent;
this.FlatStyle = FlatStyle.Flat;
}
protected override bool ShowFocusCues {
get {
m_DrawFocusCue = !ClientRectangle.Contains(PointToClient(MousePosition));
return !IsHandleCreated;
}
}
public override void NotifyDefault(bool value) => base.NotifyDefault(false);
// Make it public if this value should be customizable
private int FocusBorderSize { get; set; } = 2;
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
if (Focused && m_DrawFocusCue) {
var rect = ClientRectangle;
rect.Inflate(-FocusBorderSize, -FocusBorderSize);
using (var pen = new Pen(FlatAppearance.MouseDownBackColor, FocusBorderSize)) {
e.Graphics.DrawLine(pen, 0, rect.Bottom, rect.Right, rect.Bottom);
}
}
}
protected override void Dispose(bool disposing) {
if (disposing) {
this.Image?.Dispose();
}
base.Dispose(disposing);
}
public class CustomDesigner : ControlDesigner
{
private static string[] RemovedProperties = new[] {
"AutoEllipsis", "AutoSize", "AutoSizeMode",
"BackColor", "Cursor", "FlatAppearance", "FlatStyle",
"ForeColor", "Text", "TextAlign", "TextImageRelation"
};
public CustomDesigner() { }
protected override void PreFilterProperties(IDictionary properties) {
foreach (string prop in RemovedProperties) {
properties.Remove(prop);
}
base.PreFilterProperties(properties);
}
}
}
我创建了一个带有透明边框的平面按钮,还设置了 FlatAppearance.BorderSize = 0
。
单击鼠标时边框隐藏,按下鼠标按钮时按钮背景使用自定义颜色。
我的问题是无法移除当 Button 激活时绘制的边框,例如按 Tab 键。
我不能使用 TabStop
属性(将其设置为 false),因为我想要我设计的功能。
我只想绘制背景颜色并隐藏边框(与鼠标单击颜色相同)。
窗体设计器中的按钮属性:
this.importBtn.BackgroundImage = global::CompetitionManager.Properties.Resources.Open;
this.importBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.importBtn.Cursor = System.Windows.Forms.Cursors.Hand;
this.importBtn.Delta = 5;
this.importBtn.Dock = System.Windows.Forms.DockStyle.Fill;
this.importBtn.FlatAppearance.BorderSize = 0;
this.importBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.SteelBlue;
this.importBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
this.importBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.importBtn.ForeColor = System.Drawing.Color.Transparent;
this.importBtn.Location = new System.Drawing.Point(3, 50);
this.importBtn.MoveXDirection = false;
this.importBtn.MoveYDirection = true;
this.importBtn.Name = "importBtn";
this.importBtn.Size = new System.Drawing.Size(183, 162);
this.importBtn.TabIndex = 0;
this.ToolTip.SetToolTip(this.importBtn, "Import Competitors (Excel/XML)");
this.importBtn.UseMargin = true;
this.importBtn.UseVisualStyleBackColor = true;
this.importBtn.Click += new System.EventHandler(this.ImportFile_Click);
如问题中所述,自定义控件 - 此处为按钮 - 在变为 ActiveControl 时显示其标准焦点提示。默认渲染似乎不适合,因为背景颜色在特定上下文中呈现透明,导致标准 Focus Cue 变得令人讨厌。
▶ 禁用标准 Focus Cue 渲染,覆盖 Control.ShowFocusCues 始终 return false
(尚未创建句柄时除外)。
▶ NotifyDefault 方法也被覆盖,以避免在 Button 用于打开变为活动状态的 Windows 时出现类似的 效果 :在在这种情况下,Button 呈现为带有边框,这意味着它是 Window.
的 ActiveControl 的视觉线索▶ 一些定义 Button specialization 的属性已使用自定义 ControlDesigner 从 PropertyGrid 中删除,以避免对特定 defining[ 进行不必要的篡改=34=]属性。
最后,在自定义控件的 ClientRectangle 底部绘制一个自定义焦点提示,以提供一些反馈,否则用户将不知道当前Button/Control是。
鼠标悬停或单击按钮时不显示自定义提示。
这是一个可能的自定义渲染示例。当然,您现在可以随心所欲地绘制:不同的 边框 、背景、半透明叠加等
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[ToolboxItem(true)]
[DesignerCategory("code")]
[Designer(typeof(CustomDesigner))]
public class ImportButton : Button
{
private Color m_FocusColor = Color.LightBlue;
private bool m_DrawFocusCue = false;
public ImportButton() {
this.Cursor = Cursors.Hand;
this.Image = new Bitmap(Properties.Resources.[SomeImage]);
this.FlatAppearance.BorderSize = 0;
this.FlatAppearance.MouseDownBackColor = Color.SteelBlue;
this.FlatAppearance.MouseOverBackColor = Color.Transparent;
this.FlatStyle = FlatStyle.Flat;
}
protected override bool ShowFocusCues {
get {
m_DrawFocusCue = !ClientRectangle.Contains(PointToClient(MousePosition));
return !IsHandleCreated;
}
}
public override void NotifyDefault(bool value) => base.NotifyDefault(false);
// Make it public if this value should be customizable
private int FocusBorderSize { get; set; } = 2;
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
if (Focused && m_DrawFocusCue) {
var rect = ClientRectangle;
rect.Inflate(-FocusBorderSize, -FocusBorderSize);
using (var pen = new Pen(FlatAppearance.MouseDownBackColor, FocusBorderSize)) {
e.Graphics.DrawLine(pen, 0, rect.Bottom, rect.Right, rect.Bottom);
}
}
}
protected override void Dispose(bool disposing) {
if (disposing) {
this.Image?.Dispose();
}
base.Dispose(disposing);
}
public class CustomDesigner : ControlDesigner
{
private static string[] RemovedProperties = new[] {
"AutoEllipsis", "AutoSize", "AutoSizeMode",
"BackColor", "Cursor", "FlatAppearance", "FlatStyle",
"ForeColor", "Text", "TextAlign", "TextImageRelation"
};
public CustomDesigner() { }
protected override void PreFilterProperties(IDictionary properties) {
foreach (string prop in RemovedProperties) {
properties.Remove(prop);
}
base.PreFilterProperties(properties);
}
}
}