2017-03-17 8 views
0

winformsの透明度、グラデーション、テーマをサポートするために、複数のユーザーコントロールを含むプロジェクトを作成しました。 textboxの代替品を作成する方法を探していました。これは、winformsのテキストボックスが他のwinformsコントロールで使用されているOnPaintOnPaintBackgroundを使用していないためです。解決策 - 透明なリッチテキストボックスを自分のコントロール内にラップします。ユーザーコントロールとタブオーダーに関する問題

しかし、これは私が解決する方法を見つけることができないという新たな問題を提起しました - TabIndexプロパティは期待どおりに動作しません。

通常のテキストボックスでは、複数のテキストボックスがあり、それぞれに異なるタブインデックスがある場合、フォーカスはタブインデックスによって指定された順序で1つのテキストボックスから別のテキストボックスに移動します。私の場合は、そうではありません。代わりに、それは予測不可能です。 レイアウトやコントロールが異なる複数のフォームを試しましたが、問題を示唆するような予測可能なパターンを見つけることができませんでした。それが関連するかどう、

/// <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 
} 

とデザイナーコード:ここで

は、関連するコントロールのコード(親、それが重要な場合ZControlは、ユーザーコントロールを継承する)であるあなたが持っているので、おそらくです

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

いいえ、私は一度フォームの中に入れました。そこに他のコントロールはありません。タブインデックスは後方に働いているようです。私はそれらを別のコンテナ(ZControlも継承します)の中に入れました。タブはまったく動作していないようです。テーブルレイアウトパネルは私が避けようとしているものです。 –

+0

残念ながら、この作業をしたい場合は、テーブルレイアウトパネルを使用する必要があります。一度私はあなたと同じ問題をこのようにしていました。テーブルレイアウトパネルと同様に、応答性も実現できます –

答えて

3

スーは、次のコードによって引き起こされる:

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

あなたはUserControl(実際にはための任意の制御)のためにこれを行うべきではありません。 Control.TabIndex財産状態のドキュメント:

はそのコンテナ内のコントロールのタブオーダーを取得または設定します。

つまり、コントロールのTabIndexプロパティは、フォームではグローバルではなく、コントロールコンテナ(親)にスコープされています。

コントロールが存在するフォームデザイナーコードでは、シャドウTabOrderセッターが呼び出されますが、タブのナビゲーション処理では、単に基数Controlというプロパティが呼び出され、不確定な動作が発生します。

はまた、それがコンテナ(コントロール)内部の制御のみですので、インナーTextBoxTabIndexを設定することはありません任意の理にかなっていることに注意してください。本当に必要なのは、コンテナ内にコントロールのTabIndexを設定することです。

上記のコードを削除するだけで、すべてが期待通りに機能します。

+0

これは奇妙です。私がこれを追加した唯一の理由は、この奇妙な行動を最初に処理しようとすることでした。しかし、テスタープロジェクトではあなたの答えが正しいと思われますが、ライブプロジェクトではまだタブに問題があります...しかし、それは正しい方向への大きな一歩と思われ、おそらくこの特定の可能であれば、あなたは恩恵を得るでしょう。 (今から22時間後) –

0

あなたのテキストボックスを順番に追加していないか、またはそれらを追加している間に削除してしまったかもしれませんが、コントロールのプロパティでその順序を選択することができます=> TabIndex

+0

お返事ありがとうございますが、不幸にも間違っています。私はemtpy形式で3つのテキストボックスを追加するだけで、複数のシナリオを試しました。このポストのポイントは、TabIndexプロパティが期待どおりに動作しないということです。 –

関連する問題