只读(可视)复选框 [英] Read-only (visually) CheckBox
问题描述
我需要在屏幕上具有2组控件:输入和输出(因此它们具有2种状态: On 或关闭)。因此, CheckBox
似乎是一个不错的选择。检查任何输出都会对其进行设置。
I need to have 2 groups of controls on the screen: inputs and outputs (so they have 2 states: On or Off). Thus CheckBox
seems to be a good choice. Checking any output will set it.
但是,当显示输入时,不会有用户与之交互。
However, when displaying inputs there will be no user interaction with it. User is only allowed to see its value, not to change it.
可以考虑可能的解决方案:
Could think about possible solutions:
- 制作
CheckBox
已禁用。坏:不会有工具提示(可能会解决吗?是在顶部的假面板上吗?),并且在视觉上禁用CheckBox
是不好的(而且我不想让用户认为它已禁用)。 - 使用其他控件。哪一个?
标签
的On / Off值占位符不好。RadioButton
的外观不同,但是它们通常意味着只有一个选择,而 inputs 的值是独立的。 - 制作自己的组件。绘制整个
CheckBox
有点矫kill过正(老实说,我不知道如何使它具有Win7外观)。是否可以轻松地将ReadOnly
外观仅添加到框部分?
- Make
CheckBox
disabled. Bad: there will be no tooltip (possible to solve it? by fake panel on top?) and visually disabledCheckBox
is not nice (and I don't want to make user think it is disabled). - Use different control. Which one?
Label
doesn't have nice placeholder for the On/Off value.RadioButton
look differently, but they usually means there is a single choice out of many, while values of inputs are independent. - Making own component. Drawing the whole
CheckBox
is a bit overkill (and honestly, I don't know how to do it to have Win7 appearance). Would it be possible to add onlyReadOnly
appearance to the box part easily?
你们怎么想?
推荐答案
您必须自己绘制所有内容。我认为您应该使用一些布局正确的控件来模仿它。这是给您的演示代码,请注意,它不正确支持 AutoSize
。因为绘制的内容总是比默认的内容( AutoSize
可以使用的内容)宽,所以实现 AutoSize
并不是容易,如果您对 AutoSize
不太在意,这将是您的理想选择:
You have to draw everything yourself. I think you should use some controls with correct layout to mimic it. Here is the demo code for you, note that it does not support AutoSize
correctly. Because the drawn stuff is always wider than the default stuff (which the AutoSize
works with), implementing the AutoSize
is not easy, If you don't care too much about AutoSize
, this would be the great control for you:
public class XCheckBox : CheckBox
{
public XCheckBox()
{
SetStyle(ControlStyles.Opaque, false);
ReadOnlyCheckedColor = Color.Green;
ReadOnlyUncheckedColor = Color.Gray;
}
public bool ReadOnly { get; set; }
public bool AlwaysShowCheck { get; set; }
public Color ReadOnlyCheckedColor { get; set; }
public Color ReadOnlyUncheckedColor { get; set; }
protected override void OnPaint(PaintEventArgs pevent)
{
if (ReadOnly)
{
pevent.Graphics.SmoothingMode = SmoothingMode.HighQuality;
pevent.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
if (AlwaysShowCheck || Checked)
{
RenderCheck(pevent.Graphics);
}
RenderText(pevent.Graphics);
}
else base.OnPaint(pevent);
}
private void RenderCheck(Graphics g)
{
float fontScale = Font.Size / 8.25f;
Size glyphSize = CheckBoxRenderer.GetGlyphSize(g, System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
glyphSize.Width = (int) (glyphSize.Width * fontScale);
glyphSize.Height = (int)(glyphSize.Height * fontScale);
string checkAlign = CheckAlign.ToString();
using (GraphicsPath gp = new GraphicsPath())
using (Pen pen = new Pen(Checked ? ReadOnlyCheckedColor : ReadOnlyUncheckedColor, 1.5f)
{
LineJoin = LineJoin.Round,
EndCap = LineCap.Round,
StartCap = LineCap.Round
})
{
gp.AddLine(new Point(3, 7), new Point(5, 10));
gp.AddLine(new Point(5, 10), new Point(8, 3));
float dx = checkAlign.EndsWith("Right") ? Math.Max(-4*fontScale, ClientSize.Width - glyphSize.Width - 4 * fontScale) :
checkAlign.EndsWith("Center") ? Math.Max(-4*fontScale, (ClientSize.Width - glyphSize.Width) / 2 - 4 * fontScale) : -4;
float dy = checkAlign.StartsWith("Bottom") ? Math.Max(-4*fontScale, ClientSize.Height - glyphSize.Height - 4*fontScale) :
checkAlign.StartsWith("Middle") ? Math.Max(-4*fontScale, (ClientSize.Height - glyphSize.Height) / 2 - 4*fontScale) : 0;
g.TranslateTransform(dx, dy);
g.ScaleTransform(1.5f*fontScale, 1.5f*fontScale);
g.DrawPath(pen, gp);
g.ResetTransform();
}
}
private void RenderText(Graphics g)
{
Size glyphSize = CheckBoxRenderer.GetGlyphSize(g, System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
float fontScale = Font.Size / 8.25f;
glyphSize.Width = (int)(glyphSize.Width * fontScale);
glyphSize.Height = (int)(glyphSize.Height * fontScale);
string checkAlign = CheckAlign.ToString();
using (StringFormat sf = new StringFormat())
{
string alignment = TextAlign.ToString();
sf.LineAlignment = alignment.StartsWith("Top") ? StringAlignment.Near :
alignment.StartsWith("Middle") ? StringAlignment.Center : StringAlignment.Far;
sf.Alignment = alignment.EndsWith("Left") ? StringAlignment.Near :
alignment.EndsWith("Center") ? StringAlignment.Center : StringAlignment.Far;
sf.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
Rectangle textRectangle = ClientRectangle;
if (checkAlign.EndsWith("Left"))
{
textRectangle.Width -= glyphSize.Width;
textRectangle.Offset(glyphSize.Width, 0);
}
else if (checkAlign.EndsWith("Right"))
{
textRectangle.Width -= glyphSize.Width;
textRectangle.X = 0;
}
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRectangle, sf);
}
}
bool suppressCheckedChanged;
protected override void OnClick(EventArgs e)
{
if (ReadOnly) {
suppressCheckedChanged = true;
Checked = !Checked;
suppressCheckedChanged = false;
}
base.OnClick(e);
}
protected override void OnCheckedChanged(EventArgs e)
{
if (suppressCheckedChanged) return;
base.OnCheckedChanged(e);
}
}
注意:代码没有完全实现,一切都保持尽可能简单。您可以更改 AlwaysShowCheck
属性以选择 ReadOnly
未选中状态,它可以是灰色刻度线或什么都没有。您可以将 ReadOnly
设置为 true
使其成为只读视觉对象。
NOTE: The code is not fully implemented, everything is kept as simple as possible. You can change the AlwaysShowCheck
property to choose the ReadOnly
unchecked state, it can be a gray tick mark or nothing. You can set the ReadOnly
to true
to make it Read-only visual.
AlwaysShowCheck
设置为 true
(未选中ReadOnly状态为
AlwaysShowCheck
is set to true
(the ReadOnly unchecked state is indicated by a gray tick mark)
AlwaysShowCheck
设置为 false
(只读的未检查状态不显示任何内容)
AlwaysShowCheck
is set to false
(the ReadOnly unchecked state is indicated by nothing)
这篇关于只读(可视)复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!