只读(可视)复选框 [英] Read-only (visually) CheckBox

查看:68
本文介绍了只读(可视)复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在屏幕上具有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 disabled CheckBox 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 only ReadOnly 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆