Top / .NET備忘録 / 12.コンテナコントロール

コントロールが無効状態のときの背景色についてです。

これまで、コントロール側で完結しようとして四苦八苦していましたが、実は、コンテナコントロールで処理すると比較的簡単に実装できるんですね。(VisualStyle が無効な場合。)

コントロールを描画するタイミングで描画色を問い合わせるメッセージが、親コントロールに対して飛んできます。

すなわち

WM_CTLCOLOR0x0019
WM_CTLCOLORMSGBOX0x0132
WM_CTLCOLOREDIT0x0133
WM_CTLCOLORLISTBOX0x0134
WM_CTLCOLORBTN0x0135
WM_CTLCOLORDLG0x0136
WM_CTLCOLORSCROLLBAR0x0137
WM_CTLCOLORSTATIC0x0138

.NET の場合、これらに WM_REFLECT を加算した値のメッセージが、コントロール自身に再送信される場合があるようです。

なんだかとても意味不明な日本語ですが、以下に説明があります。

「情報: は、WM_CTLCOLOR メッセージを使用してください。」
http://support.microsoft.com/kb/32685/ja

どのメッセージも

WParam デバイスコンテキスト
LParam ウインドウハンドル
戻り値 背景を塗りつぶすブラシハンドル

になります。

Control.cs を覗いてみると、これらのメッセージをキャッチしたら、WmCtlColorControl を呼んでいます。

中身は、というと

 private void WmCtlColorControl(ref Message m) { 
     // We could simply reflect the message, but it's faster to handle it here if possible.
     Control control = Control.FromHandleInternal(m.LParam); 
     if (control != null) {
         m.Result = control.InitializeDCForWmCtlColor(m.WParam, m.Msg);
         if (m.Result != IntPtr.Zero) {
             return; 
         }
     } 
 
     DefWndProc(ref m);
 }

ウインドウハンドルから Control クラスのインスタンスを取得し、InitializeDCForWmCtlColor メソッドを呼んでいます。

InitializeDCForWmCtlColor を見てみましょう。

 internal virtual IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg) {
     if (!GetStyle(ControlStyles.UserPaint)) {
         SafeNativeMethods.SetTextColor(new HandleRef(null, dc), ColorTranslator.ToWin32(ForeColor));
         SafeNativeMethods.SetBkColor(new HandleRef(null, dc), ColorTranslator.ToWin32(BackColor)); 
         return BackColorBrush;
     } 
     else { 
         return UnsafeNativeMethods.GetStockObject(NativeMethods.HOLLOW_BRUSH);
     } 
 }

残念ですが、internal なメソッドなのですね(-"-)

ここが 上書き可能なメソッドなら、オーバーライドして、コントロール単体で完結できるのになぁ・・・

BackColorBrush も internal なプロパティです。

 internal IntPtr BackColorBrush {
     get { 
         object customBackBrush = Properties.GetObject(PropBackBrush); 
         if (customBackBrush != null) {
 
             // We already have a valid brush.  Unbox, and return.
             //
             return (IntPtr)customBackBrush;
         } 
 
         if (!Properties.ContainsObject(PropBackColor)) { 
 
             // No custom back color.  See if we can get to our parent.
             // The color check here is to account for parents and children who 
             // override the BackColor property.
             //
             if (parent != null && parent.BackColor == BackColor) {
                 return parent.BackColorBrush; 
             }
         } 
 
         // No parent, or we have a custom back color.  Either way, we need to
         // create our own. 
         //
         Color color = BackColor;
         IntPtr backBrush;
 
         if (ColorTranslator.ToOle(color) < 0) {
             backBrush = SafeNativeMethods.GetSysColorBrush(ColorTranslator.ToOle(color) & 0xFF); 
             SetState(STATE_OWNCTLBRUSH, false); 
         }
         else { 
             backBrush = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(color));
             SetState(STATE_OWNCTLBRUSH, true);
         }
 
         Debug.Assert(backBrush != IntPtr.Zero, "Failed to create brushHandle");
         Properties.SetObject(PropBackBrush, backBrush); 
 
         return backBrush;
     } 
 }



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-12-07 (土) 01:14:13 (1348d)