.NET カスタムコントロール - GuideTextBox
2008/06/21 00:00
目次
サンプルダウンロード
概要
Internet Explorer 7.0やFirefoxには、検索エンジンを呼ぶためのTextBoxがあります。
IEの検索欄

このTextBoxは以下のような動作をします。 こんなコントロールを、カスタムコントロールで作成してみました。
詳細
  1. Visual Studio 2005を起動し、[ファイル]→[新規作成]→[プロジェクト]→[Windowsコントロールライブラリ]を選択します。
  2. ソリューション エクスプローラからUserControl1.csを削除します。
  3. ソリューション エクスプローラに新しい項目を追加します。テンプレートから「カスタムコントロール」を選択し、ファイル名を「GuideTextBox.cs」にします。
  4. GuideTextBoxクラスはTextBoxクラスと似た機能を持ちます。GuideTextBoxの継承元クラスをSystem.Windows.Forms.TextBoxに変更します。
  5.     public partial class GuideTextBox : System.Windows.Forms.TextBox
        {
            public GuideTextBox()
            {
                InitializeComponent();
            }
    
            protected override void OnPaint(PaintEventArgs pe)
            {
                // TODO: カスタム ペイント コードをここに追加します
    
                // 基本クラス OnPaint を呼び出しています
                base.OnPaint(pe);
            }
        }
            
  6. GuideTextBoxクラスにプロパティを追加します。今回は以下のプロパティを追加します。
    • Guide : 未入力、非フォーカス状態のときにTextBox内に表示する文字列
    • GuideColor : GuideTextの描画色
    また、Guideプロパティ/GuideColorプロパティが変更されたとき、その内容がすぐ反映されるようにInvalidateメソッドを呼び出すようにします。
  7.     public partial class GuideTextBox : System.Windows.Forms.TextBox
        {
            /// 
            /// Guide
            /// 
            private string _guide = "";
            [
            Category("表示")
            ]
            public string Guide
            {
                get
                {
                    return _guide;
                }
    
                set
                {
                    _guide = value;
                    Invalidate();
                }
            }
    
            /// 
            /// GuideColor
            /// 
            private Color _guideColor = Color.Gray;
            [
            Category("表示")
            ]
            public Color GuideColor
            {
                get
                {
                    return _guideColor;
                }
                set
                {
                    _guideColor = value;
                    Invalidate();
                }
            }
            
  8. 次にGuide文字列を描画する処理を追加します。OnPaintイベントをoverrideしてその中で・・・と実装しても何故かうまくいきません。そこでWndProcをoverrideして、その中でWM_PAINTメッセージをDispatchするようにします。
  9.         private const int WM_PAINT = 0x000F;
    
            protected override void WndProc(ref Message m)
            {
                base.WndProc(ref m);
                switch (m.Msg)
                {
                    case WM_PAINT:
                        if (!this.Focused && string.IsNullOrEmpty(this.Text))
                        {
                            DrawGuide(); // Guideプロパティの文字列を描画
                        }
                        break;
                    default:
                        break;
                }
            }
    
            private void DrawGuide()
            {
                using (Graphics g = CreateGraphics())
                using (SolidBrush activeBrush = new SolidBrush(this.BackColor))
                {
                    // GuideTextBoxコントロールが無効 もしくは親コントロールが無効のときは、背景をグレーで描画する
                    if (this.Enabled == false || (this.Parent != null && this.Parent.Enabled == false))
                    {
                        g.FillRectangle(SystemBrushes.Control, this.ClientRectangle);
                    }
                    // GuideTextBoxコントロールが有効なとき
                    else
                    {
                        g.FillRectangle(activeBrush, this.ClientRectangle);
                    }
                    // 文字描画位置は、垂直方向は中央、水平方向は左寄せで
                    TextFormatFlags tff = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
                    TextRenderer.DrawText(g, this._guide, this.Font, this.ClientRectangle, this._guideColor, tff);
                }
            }
            
  10. 最後に、protected override void OnPaint(PaintEventArgs pe) を削除します。
  11. using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    namespace GuideTextBox
    {
        public partial class GuideTextBox : System.Windows.Forms.TextBox
        {
            /// 
            /// Guide
            /// 
            private string _guide = "";
            [
            Category("表示")
            ]
            public string Guide
            {
                get
                {
                    return _guide;
                }
    
                set
                {
                    _guide = value;
                    Invalidate();
                }
            }
    
            /// 
            /// GuideColor
            /// 
            private Color _guideColor = Color.Gray;
            [
            Category("表示")
            ]
            public Color GuideColor
            {
                get
                {
                    return _guideColor;
                }
                set
                {
                    _guideColor = value;
                    Invalidate();
                }
            }
    
    
    
            public GuideTextBox()
            {
                InitializeComponent();
            }
    
            private const int WM_PAINT = 0x000F;
    
            protected override void WndProc(ref Message m)
            {
                base.WndProc(ref m);
                switch (m.Msg)
                {
                    case WM_PAINT:
                        if (!this.Focused && string.IsNullOrEmpty(this.Text))
                        {
                            DrawGuide(); // Guideプロパティの文字列を描画
                        }
                        break;
                    default:
                        break;
                }
            }
    
            private void DrawGuide()
            {
                using (Graphics g = CreateGraphics())
                using (SolidBrush activeBrush = new SolidBrush(this.BackColor))
                {
                    // GuideTextBoxコントロールが無効 もしくは親コントロールが無効のときは、背景をグレーで描画する
                    if (this.Enabled == false || (this.Parent != null && this.Parent.Enabled == false))
                    {
                        g.FillRectangle(SystemBrushes.Control, this.ClientRectangle);
                    }
                    // GuideTextBoxコントロールが有効なとき
                    else
                    {
                        g.FillRectangle(activeBrush, this.ClientRectangle);
                    }
                    // 文字描画位置は、垂直方向は中央、水平方向は左寄せで
                    TextFormatFlags tff = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
                    TextRenderer.DrawText(g, this._guide, this.Font, this.ClientRectangle, this._guideColor, tff);
                }
            }
        }
    }
            
  12. 以上で完成です。
    このコントロールは「Grab!」のダイアログ画面でも使っていたりします。
参考文献
更新履歴