VB6には、Frameコントロールというのがあり、そのコントロール(てかコンテナ)に
コントロールを載せたりします。windows formsではGroupBoxと同じ使い方を
したりします。
で、このFrameコントロールですが、こいつのEnabledをfalseにするとFrameコントロール自身は
グレーになるのですが内部に乗っている各コントロールは入力が出来ない状態なのに前景色と背景色が
変わりません。つまり、背景がグレーになったりしないのです。
これと同じ事をwindows formsでやろうとするとちょっと大変です。
なぜなら、GroupBox, Panelなどのコンテナ系のコントロールのEnabledをfalseにすると
下位のコントロールもfalseになります。その際に、下位のコントロールはちゃんとdisable状態
(つまり背景がグレーになり、文字色も変わります。)になります。(こっちが本来のあるべき動作だと
思いますが・・)
んで、やろうとすると以下の方法などになります。
- カスタムコントロールを作成
- PanelなどでEnabled=falseとするのではなく、各コントロールを一つ一つReadOnlyにしていく
今回は、カスタムコントロールの方向でやってみます。
このサンプルを作成するのに、いろいろリソースを参照しましたが、URLを失念しました。すみません・・。
とりあえず、以下サンプルです。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace CustomControls { public partial class CustomEnabledStateTextBox : TextBox { public CustomEnabledStateTextBox() { InitializeComponent(); } protected override void OnEnabledChanged(EventArgs e) { // // Enabledの値から、自前で描画するのかシステムにまかせるのかを決定. // this.SetStyle(ControlStyles.UserPaint, !this.Enabled); this.Invalidate(); base.OnEnabledChanged(e); } protected override void OnPaint(PaintEventArgs e) { // // 基底の描画処理をまず行う。 // base.OnPaint(e); // // 文字の描画は、自前で行う。 // using(StringFormat sf = new StringFormat()) { if(this.TextAlign == HorizontalAlignment.Center) { sf.Alignment = StringAlignment.Center; } else if(this.TextAlign == HorizontalAlignment.Left) { sf.Alignment = StringAlignment.Near; } else { sf.Alignment = StringAlignment.Far; } using(SolidBrush brush = new SolidBrush(ForeColor)) { e.Graphics.DrawString( base.Text, base.Font, brush, new Rectangle(-1, 2, base.Width, base.Height), sf); } if(this.BorderStyle == BorderStyle.FixedSingle) { e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.Width - 1, this.Height - 1); } } } } }
ちなみに、Enabled=falseにするのではなく、ReadOnlyプロパティを操作していくやり方では
// // 配下のテキストボックスの状態を一気に変更する // foreach(Control c in Controls){ if(c is TextBoxBase){ TextBoxBase t = c as TextBoxBase; t.ReadOnly = true; t.TabStop = false; t.BackColor = SystemColors.Window; } }
としても同じ状態になるはずです。