色選択ComboBox
設定ダイアログでの色選択部品はどういうインターフェースがいいのかなあと考えつつ、とりあえずComboBoxを作ってみることに。
KnownColorをアイテムに表示しつつ、"参照..."アイテムを選択するとColorDialogが出るというの感じ。
KnownColorはSystemColorを含んでいるため、同じ色がリストにでてしまう場合があります。
ちょっと邪魔なので今回は消えていただきます。
protected override void OnCreateControl() { foreach (KnownColor kc in Enum.GetValues(typeof(KnownColor))) { Color c = Color.FromKnownColor(kc); if (!c.IsSystemColor) { this.Items.Add(c); } } }
IsSystemColorで判別してアイテムに追加。
この追加処理ですが、最初コンストラクタでやったところ、フォームデザイナに置いたときに中身が全部.Designer.csに書き出されてしまいました。
起動するとコンストラクタでアイテムが追加され、さらにInitializeComponentでアイテムが追加されるという事態に。
ちょっとハマりましたが、それっぽいOnCreateControlをオーバーライドして解決。
ただ初期値の設定を配置したフォームのOnLoad以前にできないという縛り付きです。
他にそれらしきメソッドが見あたらなかったので初期値の設定処理側で対応しました。
しかしフォームに2,3個置くとちょっともっさり…
データソースを共通で持っておいたほうがいいのかもしれないですね。
アイテム描画は色々考えましたが、
□ #ffffff [あれば色の名前]
これくらいが落ち着いていていいかな…
protected override void OnDrawItem(DrawItemEventArgs e) { using (SolidBrush sb = new SolidBrush(e.BackColor)) { e.Graphics.FillRectangle(sb, e.Bounds); } Color c = (Color)this.Items[e.Index]; using (SolidBrush sbBack = new SolidBrush(c)) using (SolidBrush sbFore = new SolidBrush(e.ForeColor)) { Rectangle rcColor = new Rectangle(e.Bounds.Left + 2, e.Bounds.Top + 1, e.Bounds.Height - 3, e.Bounds.Height - 3); Rectangle rcText = new Rectangle(rcColor.Right + 2, e.Bounds.Top, e.Bounds.Width - rcColor.Width, e.Bounds.Height); e.Graphics.FillRectangle(sbBack, rcColor); e.Graphics.DrawRectangle(Pens.Black, rcColor); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Center; string text = string.Format("#{0:x2}{1:x2}{2:x2}", c.R, c.G, c.B); if (c.IsNamedColor) { text += " [" + c.Name + "]"; } e.Graphics.DrawString(text, e.Font, sbFore, rcText, sf); } }
ところで色々なサンプルを見ているとBrushとかPenをusingとかDispose()したりしていないんですが、これはするのとしないのどちらがいいんでしょう?
私はDispose()が実装されているものは全部usingで囲むようにしています。