2017-03-17 61 views
0

我创建了一个项目,其中包含多个用户控件以支持winforms的透明度,渐变和主题。 我正在寻找一种方法来创建textbox的替代品,因为WinForms文本框没有使用其他winforms控件使用的常规OnPaintOnPaintBackground,果然,我找到了一些可以使用的东西right here on stackoverflow. Brian的评论给了我解决方案 - 在我自己的控件中包装一个透明的RichTextBox。用户控件和Tab顺序的问题

但是,这提出了一个新问题,我不知道如何解决 - TabIndex属性dosn't不按预期方式运作。

对于普通的文本框,当您有多个文本框并且每个文本框都有不同的选项卡索引时,焦点将按照选项卡索引指定的顺序从一个文本框转到另一个文本框。在我的情况下,它没有。相反,这是不可预测的。 我试过不同的布局和控制他们的多个表单,但我似乎无法找到任何可预测的行为模式,将建议的问题。

下面是相关控件的代码(父,ZControl继承用户控件,如果该事项):

/// <summary> 
/// A stylable textbox. 
/// <Remarks> 
/// The solution for writing a stylable textbox was inspired by this SO post and Brian's comment: 
/// https://stackoverflow.com/a/4360341/3094533 
/// </Remarks> 
/// </summary> 
[DefaultEvent("TextChanged")] 
public partial class ZTextBox : ZControl 
{ 
    #region ctor 

    public ZTextBox() 
    { 
     TextBox = new TransparentRichTextBox(); 
     TextBox.BackColor = Color.Transparent; 
     TextBox.BorderStyle = BorderStyle.None; 
     TextBox.Multiline = false; 
     TextBox.TextChanged += TextBox_TextChanged; 
     TextBox.TabStop = true; 
     TextBox.AcceptsTab = false; 
     InitializeComponent(); 
     AdjustTextBoxRectangle(); 
     this.Controls.Add(TextBox); 
     this.RoundedCorners.PropertyChanged += RoundedCorners_PropertyChanged; 
    } 

    #endregion ctor 

    #region properties 

    private TransparentRichTextBox TextBox { get; } 

    public override string Text 
    { 
     get 
     { 
      return TextBox.Text; 
     } 

     set 
     { 
      TextBox.Text = value; 
     } 
    } 

    [DefaultValue(false)] 
    public bool Multiline 
    { 
     get 
     { 
      return this.TextBox.Multiline; 
     } 
     set 
     { 
      this.TextBox.Multiline = value; 
     } 
    } 

    public override Font Font 
    { 
     get 
     { 
      return base.Font; 
     } 

     set 
     { 
      if (base.Font != value) 
      { 
       base.Font = value; 
       if (TextBox != null) 
       { 
        TextBox.Font = value; 
       } 
      } 
     } 
    } 

    public new int TabIndex 
    { 
     get 
     { 
      return this.TextBox.TabIndex; 
     } 
     set 
     { 
      this.TextBox.TabIndex = value; 
     } 
    } 

    #region hidden properties 

    [ 
     DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
     Browsable(false), 
     EditorBrowsable(EditorBrowsableState.Never) 
    ] 
    public override Color ForeColor 
    { 
     get 
     { 
      return TextBox.ForeColor; 
     } 

     set 
     { 
      TextBox.ForeColor = value; 
     } 
    } 

    [ 
     DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
     Browsable(false), 
     EditorBrowsable(EditorBrowsableState.Never) 
    ] 
    public override ContentAlignment TextAlign 
    { 
     get 
     { 
      return base.TextAlign; 
     } 

     set 
     { 
      base.TextAlign = value; 
     } 
    } 

    [ 
     DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
     Browsable(false), 
     EditorBrowsable(EditorBrowsableState.Never) 
    ] 
    public override Point TextLocationOffset 
    { 
     get 
     { 
      return base.TextLocationOffset; 
     } 

     set 
     { 
      base.TextLocationOffset = value; 
     } 
    } 

    #endregion hidden properties 

    #endregion properties 

    #region methods 

    protected override void OnGotFocus(EventArgs e) 
    { 
     base.OnGotFocus(e); 
     TextBox.Focus(); 
    } 

    protected override void DrawText(Graphics graphics, string text, ContentAlignment textAlign, Point locationOffset, Size stringSize) 
    { 
     // Do nothing - The transparent rich textbox is responsible for drawing the text... 
    } 

    protected override void OnResize(EventArgs e) 
    { 
     base.OnResize(e); 
     AdjustTextBoxRectangle(); 
    } 

    private void AdjustTextBoxRectangle() 
    { 
     var corners = this.RoundedCorners.Corners; 
     var leftAdjustment = ((corners & RoundedEdges.TopLeft) == RoundedEdges.TopLeft || (corners & RoundedEdges.BottomLeft) == RoundedEdges.BottomLeft) ? this.RoundedCorners.ArcSize/2 : 0; 
     var rightAdjustment = ((corners & RoundedEdges.TopRight) == RoundedEdges.TopRight || (corners & RoundedEdges.BottomRight) == RoundedEdges.BottomRight) ? this.RoundedCorners.ArcSize/2 : 0; 

     TextBox.Top = 0; 
     TextBox.Left = leftAdjustment; 
     TextBox.Width = this.Width - leftAdjustment - rightAdjustment; 
     TextBox.Height = this.Height; 
    } 

    #endregion methods 

    #region event handlers 

    private void RoundedCorners_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     AdjustTextBoxRectangle(); 
    } 

    private void TextBox_TextChanged(object sender, EventArgs e) 
    { 
     OnTextChanged(e); 
    } 

    #endregion event handlers 

    #region private classes 

    private class TransparentRichTextBox : RichTextBox 
    { 
     public TransparentRichTextBox() 
     { 
      this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 
      this.SetStyle(ControlStyles.Opaque, true); 
      this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false); 
     } 

     protected override CreateParams CreateParams 
     { 
      get 
      { 
       CreateParams parms = base.CreateParams; 
       parms.ExStyle |= 0x20; // Turn on WS_EX_TRANSPARENT 
       return parms; 
      } 
     } 
    } 

    #endregion private classes 
} 

而设计的代码,如果是相关的:

partial class ZTextBox 
{ 
    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    #region Component Designer generated code 

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() 
    { 
     this.SuspendLayout(); 
     // 
     // ZTextBox 
     // 
     this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 
     this.Name = "ZTextBox"; 
     this.RoundedCorners.ArcSize = 50; 
     this.RoundedCorners.Corners = Zohar.UserControls.RoundedEdges.None; 
     this.Size = new System.Drawing.Size(100, 20); 
     this.Style.DisabledStyle.BackColor = System.Drawing.Color.Empty; 
     this.Style.DisabledStyle.BackgroundImage = null; 
     this.Style.DisabledStyle.BorderColor = System.Drawing.Color.Empty; 
     this.Style.DisabledStyle.ForeColor = System.Drawing.Color.Empty; 
     this.Style.DisabledStyle.Gradient.Angle = 0F; 
     this.Style.DisabledStyle.Gradient.BackColor = System.Drawing.Color.Empty; 
     this.Style.DisabledStyle.Image = null; 
     this.Style.DisabledStyle.Name = null; 
     this.Style.EnabledStyle.BackColor = System.Drawing.Color.Empty; 
     this.Style.EnabledStyle.BackgroundImage = null; 
     this.Style.EnabledStyle.BorderColor = System.Drawing.Color.Empty; 
     this.Style.EnabledStyle.ForeColor = System.Drawing.Color.Empty; 
     this.Style.EnabledStyle.Gradient.Angle = 0F; 
     this.Style.EnabledStyle.Gradient.BackColor = System.Drawing.Color.Empty; 
     this.Style.EnabledStyle.Image = null; 
     this.Style.EnabledStyle.Name = null; 
     this.Style.HoverStyle.BackColor = System.Drawing.Color.Empty; 
     this.Style.HoverStyle.BackgroundImage = null; 
     this.Style.HoverStyle.BorderColor = System.Drawing.Color.Empty; 
     this.Style.HoverStyle.ForeColor = System.Drawing.Color.Empty; 
     this.Style.HoverStyle.Gradient.Angle = 0F; 
     this.Style.HoverStyle.Gradient.BackColor = System.Drawing.Color.Empty; 
     this.Style.HoverStyle.Image = null; 
     this.Style.HoverStyle.Name = null; 
     this.ResumeLayout(false); 

    } 

    #endregion 
} 
+0

您是否将控件放置在表格布局面板中? –

+0

不,我把它们放在表单里面,没有其他控制 - tabindex似乎在倒退。我将它们放在另一个容器(也继承了ZControl)中,该选项卡似乎根本不起作用。表格布局面板是我尽量避免的。 –

+0

不幸的是,如果你想使这个工作,你将不得不使用表格布局面板。卡兹一旦我遇到同样的问题,你以我这样固定。与表格布局面板一样,您也可以实现响应能力 –

回答

3

这是Sue是由下面的代码引起的:

public new int TabIndex 
{ 
    get 
    { 
     return this.TextBox.TabIndex; 
    } 
    set 
    { 
     this.TextBox.TabIndex = value; 
    } 
} 

你不应该为UserControl(实际上是任何控制)做到这一点。为Control.TabIndex财产状态的文档:

获取或设置在容器内控制的Tab键顺序。

换句话说,控件TabIndex属性不是表单的全局属性,而是作用于控件容器(父级)的范围。

效果是,控件所在的表单设计器代码将调用影子TabOrder setter,但标签导航处理将简单地调用基础Control属性,从而导致未确定的行为。

另外请注意,设置内部TextBoxTabIndex是没有任何意义,因为它是容器(控件)里面的唯一控制。而你真正需要的是将你的控件的TabIndex设置在其容器中。

就这么说,只需删除上面的代码,一切都会按预期工作。

+0

好吧,这很奇怪。我添加这个的唯一原因就是首先尝试并处理这种奇怪的行为。然而,在一个测试项目中,似乎你的答案是正确的,而在实时项目中,我仍然遇到标签问题......但是,它似乎是向正确方向迈出的重要一步,可能是这个特定的正确答案问题,所以你会尽可能得到赏金。 (从现在起22小时) –

0

这可能是因为你有没有添加您的文本框的顺序,或者可能删除其中的一些,而添加它们,无论如何,您可以选择控件属性的顺序=> TabIndex

+0

谢谢你的回答,但不幸的是这是错误的。我已经尝试了多种场景,包括在一个静态表单上添加3个文本框。这篇文章的要点是,TabIndex属性不能按预期工作...... –