コントロールの色を扱うときの注意
ここにはコントロールのBackColorなどを変更する際に陥りやすいミスについて書いてあります。 .NET Frameworkの”色”と従来のWindowsコントロールの”色”には微妙な差異が存在します。それを無視したまま コーディングを続けていくと、大変なことになってしまいます。
ビットの並びに注意!
Windows GDIにおいてはRGB色を指定するときCOLORREF値というDWORD型の値を設定します。 例えば、SetBkColor()やSetTextColor()関数などが挙げられます。 一方.NET Frameworkでは”色”を表すものとしてColor構造体があります。 これはRGB値ではなく、さらにアルファ値を加えたARGB値で色を表現します。 このRGB値とARGB値ですが、Aの有無以外に実は大きな違いが存在します。 それは、各ビットの並び方です。ビットの並びを16進数で表現すると以下のような構造をしています。
ARGB = 0xAARRGGBB
色指定にColorDialogを使用するときは要注意
Aはアルファ、Rはレッド、Gはグリーン、Bはブルーです。 この両者の違いが浮き彫りとなることは少ないのかもしれませんが、つぎのような場合が考えられます。 「ボタンコントロールの背景色をColorDialogで設定(取得)したい」この場合ColorDialogに既に存在する色ならば多くの場合問題ないのですが、 独自の色を設定するとなると、上記のことをしっかりと念頭においておかないとうまくいきません。 CustomColorsプロパティはInt32型のARGB値の配列を設定しなければなりません。ここで次のようなコードを書いたとします。
{
ColorDialog myDialog = new ColorDialog();
myDialog.AllowFullOpen = true;
myDialog.CustomColors = new int [] {button1.BackColor.ToArgb()};
myDialog.Color = button1.BackColor;
if(myDialog.ShowDialog() == DialogResult.OK)
button1.BackColor = myDialog.Color;
}
一見するとこれでうまくいきそうな気もしますが、さきほどのことを思い出してみると、 これではうまくいかないであろうことが予想されます。ToArgb()メソッドはAも含む値を返してくれるメソッドですが、 ボタンコントロールは通常アルファ値を使用することはないので、BackColor.Aの値は常に0xFFを指しています。 従って、ToArgb()によって返される値は上位8ビットが0xFFでRGBの順番に24ビットが並んだものとなります。 しかし、実際CustomColorsに設定できる値は0xA0000000より小さな値しか設定することができません。 しかもそのビット配列はWindowsカラーによる配列でなければいけないのです。従って、次のようなコードでないとうまくいきません。
{
ColorDialog myDialog = new ColorDialog();
myDialog.AllowFullOpen = true;
myDialog.CustomColors = new int [] {ColorTranslator.ToWin32(button1.BackColor)};
myDialog.Color = button1.BackColor;
if (myDialog.ShowDialog() == DialogResult.OK)
button1.BackColor = myDialog.Color;
}
今のところ、.NET Frameworkも所詮はWin32 APIのラッパーにすぎません。従って、コモンコントロールなどの 従来のWindowsコントロールをそのまま内部で使用している場合には、今回のようなことにも気を配る必要が でてくるということです。