Reputation: 951
Simple question. If I set a radiobutton in a winform project read only it's appearance (font color) changes to light grey. Same when I set it's enabled property to false,
How can I manage to create a read only radiobutton looking like a normal one ? Cause like that you can barely see it.
Thanks
Upvotes: 3
Views: 2774
Reputation: 7586
Thanks to PapaAtHome for sharing his RadioButtonReadonly code.
Here is the same code, but converted to VB.Net:
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
Upvotes: 1
Reputation: 604
Old question using old code, I know.
I ran into the same problem recently. Reason: I want to show a state (in a nice visible format) but now allow the user to change that state (on purpose or by accident). The 'disabled' format is not very readable or attractive.
I searched for posibilities and this thread came on top. Over time there has been a lot of discussing about this toppic and somehow it still raises questions now.
I createded RadioButtonReadonly
for this purpose where the readonly state uses the same format as the enabled case but does not allow the user to change any settings.
The idea is to shield base.Enabled
and to replace it. Then to deny any input form the user if in Readonly
mode.
If anyone argues that Enabled
and !Enabled
have different formats for a reason then I agree totally. But not having an option Readonly
is in some cases an iritating problem.
I have found suggestions to use a pannel with an overlay, the overlay being an image of what is on display. This image shows all pannel members in Enabled
mode but the image is catching all click events. Tried that and got it going but the resulting code is cumbersome and cludgy.
Next try, RadioButtonReadonly
, it has an extra attribute Readonly and overrides Enabled.
When Readonly=false then all behaviour is like Radiobutton
When Readonly=true then the layout on display is the same as with Enabled=false but all user interaction is silently ignored.
Here is the code for my RadioButtonReadonly
. It comes in its own test form.
(Note: I borrowed some code and idea's for the things I found while seaching. Unfortunately, I do not remember where I saw all code. The initial idea of using an overlay came from Hans Passant as a static solution, not able to change states durin runtime. I modified it to be able to track changes.)
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
}
}
Upvotes: 1
Reputation: 125187
As an option you can add a ReadOnly
property and override OnClick
and call base.OnClick(e)
only if !ReadOnly
:
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);
}
}
Upvotes: 3
Reputation: 951
Managed it by removing the text of the radiobutton and added a label next to it.
Not the greatest solution but working...
Upvotes: 1