简单的问题。 如果我在Winform项目中设置单选按钮为只读,它的外观(字体颜色)会变成浅灰色。当我将其启用属性设置为false时也是如此。
我该如何创建一个看起来像正常单选按钮的只读单选按钮? 因为这样你几乎看不到它。
谢谢
简单的问题。 如果我在Winform项目中设置单选按钮为只读,它的外观(字体颜色)会变成浅灰色。当我将其启用属性设置为false时也是如此。
我该如何创建一个看起来像正常单选按钮的只读单选按钮? 因为这样你几乎看不到它。
谢谢
ReadOnly
属性并重写OnClick
, 仅当!ReadOnly
时才调用base.OnClick(e)
:using System;
using System.Windows.Forms;
public class MyRadioButton : RadioButton
{
public bool ReadOnly { get; set; }
protected override void OnClick(EventArgs e)
{
if (!ReadOnly)
base.OnClick(e);
}
}
通过删除单选按钮的文本并在其旁边添加标签来管理它。
不是最好的解决方案,但起作用了...
Imports System
Imports System.Windows.Forms
Namespace RadioButtonControl
''' <summary>
'''
''' Enables the user to show radio buttons in readonly mode.
''' </summary>
''' <remarks>
''' When visualstyle is enabled there is minimal feedback to the user about 'Readonly=true' (e.g.: not changing when hoovering over).
'''
''' When visualstyle is not enabled there is no feedback to the user about 'Readonly=true'.
''' </remarks>
Public Class RadioButtonReadonly
Inherits RadioButton
Private _readonly As Boolean = False
Private _enabled As Boolean = True
''' <summary>
''' Radiobutton with Readonly attribute.
''' </summary>
Public Sub New()
Me.BaseEnabledCheck(Nothing, Nothing)
AddHandler MyBase.EnabledChanged, AddressOf Me.BaseEnabledCheck
End Sub
''' <summary>
''' Gets or sets a value indicating whether the control will respond to user interaction.
''' </summary>
Public Property [Readonly] As Boolean
Get
Return Me._readonly
End Get
Set(value As Boolean)
Dim flag As Boolean = Me._readonly <> value
If flag Then
Me._readonly = value
Me.BaseEnabledCheck(Nothing, Nothing)
End If
End Set
End Property
''' <summary>
''' Gets or sets a value indicating whether the control can respond to user interaction.
''' </summary>
''' <remarks>
''' Overruled to take away visualstyle behaviour.
''' </remarks>
Public Property Enabled As Boolean
Get
Return Me._enabled
End Get
Set(value As Boolean)
Dim flag As Boolean = Me._enabled <> value
If flag Then
Me._enabled = value
Me.BaseEnabledCheck(Nothing, Nothing)
End If
End Set
End Property
''' <summary>
''' Raises the System.Windows.Forms.Control.EnabledChanged event, force base.Enabled to always be true.
''' </summary>
''' <param name="sender"></param>
''' <param name="e">An System.EventArgs that contains the event data.</param>
Private Sub BaseEnabledCheck(sender As Object, e As EventArgs)
Dim [readonly] As Boolean = Me.[Readonly]
If [readonly] Then
Dim flag As Boolean = Not MyBase.Enabled
If flag Then
MyBase.Enabled = True
MyBase.Invalidate()
End If
Else
Dim flag2 As Boolean = Me.Enabled <> MyBase.Enabled
If flag2 Then
MyBase.Enabled = Me.Enabled
MyBase.Invalidate()
End If
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.Click event.
''' </summary>
''' <param name="e">An System.EventArgs that contains the event data.</param>
Protected Overrides Sub OnClick(e As EventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnClick(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.ButtonBase.OnKeyUp(System.Windows.Forms.KeyEventArgs) event.
''' </summary>
''' <param name="kevent">A System.Windows.Forms.KeyEventArgs that contains the event data.</param>
Protected Overrides Sub OnKeyDown(kevent As KeyEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnKeyDown(kevent)
End If
End Sub
''' <summary>
''' Occurs when a character. space or backspace key is pressed while the control has focus.
''' </summary>
''' <param name="e">A System.Windows.Forms.KeyPressEventArgs that contains the event data.</param>
Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnKeyPress(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.ButtonBase.OnKeyUp(System.Windows.Forms.KeyEventArgs) event.
''' </summary>
''' <param name="kevent">A System.Windows.Forms.KeyEventArgs that contains the event data.</param>
Protected Overrides Sub OnKeyUp(kevent As KeyEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnKeyUp(kevent)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.MouseUp event, draw the radio button in the checked or unchecked state.
''' </summary>
''' <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseDown(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.MouseUp event, draw the radio button in the hot state.
''' </summary>
''' <param name="e"></param>
Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseUp(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.MouseHover event, draw the radio button in the hot state.
''' </summary>
''' <param name="e">An System.EventArgs that contains the event data.</param>
Protected Overrides Sub OnMouseHover(e As EventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseHover(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.OnMouseEnter(System.EventArgs) event, draw the radio button in the hot state.
''' </summary>
''' <param name="eventargs"></param>
Protected Overrides Sub OnMouseEnter(eventargs As EventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseEnter(eventargs)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.OnMouseLeave(System.EventArgs) event, draw the radio button in the unpressed state.
''' </summary>
''' <param name="e">An System.EventArgs that contains the event data.</param>
Protected Overrides Sub OnMouseLeave(e As EventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseLeave(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.MouseWheel event.
''' </summary>
''' <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
Protected Overrides Sub OnMouseWheel(e As MouseEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnMouseWheel(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.DragDrop event.
''' </summary>
''' <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
Protected Overrides Sub OnDragDrop(drgevent As DragEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnDragDrop(drgevent)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.DragEnter event.
''' </summary>
''' <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
Protected Overrides Sub OnDragEnter(drgevent As DragEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnDragEnter(drgevent)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.DragLeave event.
''' </summary>
''' <param name="e">An System.EventArgs that contains the event data.</param>
Protected Overrides Sub OnDragLeave(e As EventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnDragLeave(e)
End If
End Sub
''' <summary>
''' Raises the System.Windows.Forms.Control.DragOver event.
''' </summary>
''' <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
Protected Overrides Sub OnDragOver(drgevent As DragEventArgs)
Dim flag As Boolean = Not Me.[Readonly]
If flag Then
MyBase.OnDragOver(drgevent)
End If
End Sub
End Class
End Namespace
旧问题使用旧代码,我知道。
最近我遇到了同样的问题。 原因:我想以一个漂亮可见的格式显示状态,但不允许用户更改该状态(故意或者意外)。 '禁用'格式不太易读或有吸引力。
我搜索了一些解决方案,这个线程排在首位。随着时间的推移,人们对这个主题进行了很多讨论,但仍然存在一些问题。
我为此创建了 RadioButtonReadonly
,其中只读状态使用与启用状态相同的格式,但不允许用户更改任何设置。
我的思路是保护 base.Enabled
并替换它。如果在只读
模式下,则拒绝来自用户的任何输入。
如果有人认为已启用
和未启用
之间有不同的格式,那么我完全同意。但是,在某些情况下没有只读
选项会导致令人烦恼的问题。
我找到了建议使用面板和覆盖层的方法,覆盖层是显示内容的图像。该图像显示所有面板成员处于启用模式,但该图像捕获所有单击事件。我尝试了这个方法,但得到的代码笨重且不灵活。
接下来,我尝试了RadioButtonReadonly
,它具有一个额外的属性ReadOnly
并覆盖了Enabled
。
当 ReadOnly=false
时,所有行为就像一般的Radiobutton
当 ReadOnly=true
时,显示布局与启用=false相同,但所有用户交互都会被静默忽略。
以下是我的 RadioButtonReadonly
代码和测试表格。
(注意:我从搜索中借用了一些代码和想法。不幸的是,我不记得在哪里看到的所有代码。使用覆盖层的最初想法来自 Hans Passant,他提出了一种静态解决方案,无法在运行时更改状态。我修改了它以跟踪更改。)
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace RadioButtonControl
{
class Form1 : Form
{
RadioButtonReadonly RadioButton1 = new RadioButtonReadonly();
RadioButtonReadonly RadioButton2 = new RadioButtonReadonly();
RadioButton RadioButton3 = new RadioButton();
RadioButton RadioButton4 = new RadioButton();
Button button1 = new Button();
Button button2 = new Button();
Button button3 = new Button();
public Form1() : base()
{
RadioButton1.Location = new Point(50, 50);
RadioButton1.Size = new Size(100, 23);
RadioButton1.Text = "Click 1ro";
RadioButton1.Font = SystemFonts.IconTitleFont;
Controls.Add(RadioButton1);
RadioButton2.Location = new Point(50, 75);
RadioButton2.Size = new Size(100, 23);
RadioButton2.Text = "Click 2ro";
RadioButton2.Font = SystemFonts.IconTitleFont;
Controls.Add(RadioButton2);
RadioButton3.Location = new Point(50, 100);
RadioButton3.Size = new Size(100, 23);
RadioButton3.Text = "Click 3";
RadioButton3.Font = SystemFonts.IconTitleFont;
Controls.Add(RadioButton3);
RadioButton4.Location = new Point(50, 125);
RadioButton4.Size = new Size(100, 23);
RadioButton4.Text = "Click 4";
RadioButton4.Font = SystemFonts.IconTitleFont;
Controls.Add(RadioButton4);
button1.Location = new Point(175, 231);
button1.Size = new Size(105, 23);
button1.Text = "Toggle Style";
button1.Click += new EventHandler(this.button1_Click);
Controls.Add(button1);
button2.Location = new Point(175, 200);
button2.Size = new Size(105, 23);
button2.Text = "Toggle Enabled";
button2.Click += new EventHandler(this.button2_Click);
Controls.Add(button2);
button3.Location = new Point(175, 169);
button3.Size = new Size(105, 23);
button3.Text = "Toggle Readonly";
button3.Click += new EventHandler(this.button3_Click);
Controls.Add(button3);
Text = (Application.RenderWithVisualStyles) ? "Visual Styles Enabled" : "Visual Styles Disabled";
}
[STAThread]
static void Main()
{
// If you do not call EnableVisualStyles below, then RadioButtonRenderer.DrawRadioButton automatically
// detects this and draws the radio button without visual styles.
Application.EnableVisualStyles();
Application.Run(new Form1());
}
private void button1_Click(object sender, EventArgs e)
{
Application.VisualStyleState =
Application.VisualStyleState ^
VisualStyleState.ClientAndNonClientAreasEnabled;
GroupBoxRenderer.RenderMatchingApplicationState = true;
Text = (Application.RenderWithVisualStyles) ? "Visual Styles Enabled" : "Visual Styles Disabled";
}
private void button2_Click(object sender, EventArgs e)
{
RadioButton1.Enabled = !RadioButton1.Enabled;
RadioButton2.Enabled = RadioButton1.Enabled;
RadioButton3.Enabled = RadioButton1.Enabled;
RadioButton4.Enabled = RadioButton1.Enabled;
}
private void button3_Click(object sender, EventArgs e)
{
RadioButton1.Readonly = !RadioButton1.Readonly;
RadioButton2.Readonly = RadioButton1.Readonly;
}
}
/// <summary>
/// Enables the user to show radio buttons in readonly mode.
/// </summary>
/// <remarks>
/// When visualstyle is enabled there is minimal feedback to the user about 'Readonly=true' (e.g.: not changing when hoovering over).
///
/// When visualstyle is not enabled there is no feedback to the user about 'Readonly=true'.
/// </remarks>
public class RadioButtonReadonly : RadioButton
{
/// <summary>
/// Radiobutton with Readonly attribute.
/// </summary>
public RadioButtonReadonly()
{
BaseEnabledCheck(null, null);
base.EnabledChanged += BaseEnabledCheck;
}
#region Readonly/Enabled
/// <summary>
/// Gets or sets a value indicating whether the control will respond to user interaction.
/// </summary>
public bool Readonly
{
get { return _readonly; }
set
{
if (_readonly != value)
{
_readonly = value;
BaseEnabledCheck(null, null);
}
}
}
bool _readonly = false;
/// <summary>
/// Gets or sets a value indicating whether the control can respond to user interaction.
/// </summary>
/// <remarks>
/// Overruled to take away visualstyle behaviour.
/// </remarks>
public new bool Enabled
{
get { return _enabled; }
set
{
if (_enabled != value)
{
_enabled = value;
BaseEnabledCheck(null, null);
}
}
}
bool _enabled = true;
/// <summary>
/// Raises the System.Windows.Forms.Control.EnabledChanged event, force base.Enabled to always be true.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">An System.EventArgs that contains the event data.</param>
private void BaseEnabledCheck(object sender, EventArgs e)
{
if (Readonly)
{
if (!base.Enabled)
{
base.Enabled = true;
Invalidate();
}
}
else
{
if (Enabled != base.Enabled)
{
base.Enabled = Enabled;
Invalidate();
}
}
}
#endregion Readonly/Enabled
#region User input handling
/// <summary>
/// Raises the System.Windows.Forms.Control.Click event.
/// </summary>
/// <param name="e">An System.EventArgs that contains the event data.</param>
protected override void OnClick(EventArgs e)
{
if (!Readonly) base.OnClick(e);
}
/// <summary>
/// Raises the System.Windows.Forms.ButtonBase.OnKeyUp(System.Windows.Forms.KeyEventArgs) event.
/// </summary>
/// <param name="kevent">A System.Windows.Forms.KeyEventArgs that contains the event data.</param>
protected override void OnKeyDown(KeyEventArgs kevent)
{
if (!Readonly) base.OnKeyDown(kevent);
}
/// <summary>
/// Occurs when a character. space or backspace key is pressed while the control has focus.
/// </summary>
/// <param name="e">A System.Windows.Forms.KeyPressEventArgs that contains the event data.</param>
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (!Readonly) base.OnKeyPress(e);
}
/// <summary>
/// Raises the System.Windows.Forms.ButtonBase.OnKeyUp(System.Windows.Forms.KeyEventArgs) event.
/// </summary>
/// <param name="kevent">A System.Windows.Forms.KeyEventArgs that contains the event data.</param>
protected override void OnKeyUp(KeyEventArgs kevent)
{
if (!Readonly) base.OnKeyUp(kevent);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.MouseUp event, draw the radio button in the checked or unchecked state.
/// </summary>
/// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
if (!Readonly) base.OnMouseDown(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.MouseUp event, draw the radio button in the hot state.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{
if (!Readonly) base.OnMouseUp(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.MouseHover event, draw the radio button in the hot state.
/// </summary>
/// <param name="e">An System.EventArgs that contains the event data.</param>
protected override void OnMouseHover(EventArgs e)
{
if (!Readonly) base.OnMouseHover(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.OnMouseEnter(System.EventArgs) event, draw the radio button in the hot state.
/// </summary>
/// <param name="eventargs"></param>
protected override void OnMouseEnter(EventArgs eventargs)
{
if (!Readonly) base.OnMouseEnter(eventargs);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.OnMouseLeave(System.EventArgs) event, draw the radio button in the unpressed state.
/// </summary>
/// <param name="e">An System.EventArgs that contains the event data.</param>
protected override void OnMouseLeave(EventArgs e)
{
if (!Readonly) base.OnMouseLeave(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.MouseWheel event.
/// </summary>
/// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
protected override void OnMouseWheel(MouseEventArgs e)
{
if (!Readonly) base.OnMouseWheel(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.DragDrop event.
/// </summary>
/// <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
protected override void OnDragDrop(DragEventArgs drgevent)
{
if (!Readonly) base.OnDragDrop(drgevent);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.DragEnter event.
/// </summary>
/// <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
protected override void OnDragEnter(DragEventArgs drgevent)
{
if (!Readonly) base.OnDragEnter(drgevent);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.DragLeave event.
/// </summary>
/// <param name="e">An System.EventArgs that contains the event data.</param>
protected override void OnDragLeave(EventArgs e)
{
if (!Readonly) base.OnDragLeave(e);
}
/// <summary>
/// Raises the System.Windows.Forms.Control.DragOver event.
/// </summary>
/// <param name="drgevent">A System.Windows.Forms.DragEventArgs that contains the event data.</param>
protected override void OnDragOver(DragEventArgs drgevent)
{
if (!Readonly) base.OnDragOver(drgevent);
}
#endregion User input handling
}
}