きゃべログ

プログラミングや電子工作などについての記事がほとんどです

C#:CheckedListBoxのチェックされてる行の文字色を変更

0 件のコメント

文字色の変更方法はやや工夫が必要

ちょっと知り合いのフォームアプリケーションのプログラムの相談に乗ったところ,「CheckedListBoxの文字色を条件に応じて変更したい」とのことだった.色々ググってみたが,ListBoxにはデザインエディタのプロパティウィンドウから追加できるDrawItemというイベントを使用すれば上手くいくらしいが,CheckedListBoxにはそれが見当たらない.ふしぎ.オーナードローができないということらしいですが,よくわからない.ListBoxの描画設定を変更したいという方は以下を参照してください.
ListBoxの任意な行の色変え - 仕事に追われるプログラマーの日記
C#を攻略しよう、オーナードロー3

変更方法

さて,ここからが本題になるのですが,CheckedListBoxの特定の行だけ文字色を変更する方法を模索した.困ったときのstackoverflow,困っている人は多いらしくすぐ見つかった.
c# - How to dynamically change / set checkedListBox item fore colour - Stack Overflow
どうやらCheckedListBoxを継承したカスタムコントロールを作成し,描画に関わるOnDrawItemというメソッドをオーバーライドして解決するらしい.というわけでさっそく実装しようと思ったもののカスタムコントロールというものを作ったことがないのでこれにも悩むことに.

カスタムコントロールの作成

ここで第一の落とし穴にはまるわけですが,色々調べていたら公式にそれらしきことが書いていました.
方法 : 既存の Windows フォーム コントロールから継承する
でも画像付きで易しいサイトを見つけたので参照したのはこちら.
[C#]テキストボックスのカスタムコントロールを作成する : 忘れる前にメモ
プロジェクト → クラスの追加 からCustomCheckedListBox.csを作成し,ソースからCheckedListBoxを継承する.そしたらソースはこんな具合に.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication5.bin
{
    class CustomCheckedListBox : CheckedListBox
    {
    }
}

そしてビルド → ソリューションのビルドを実行する.そしてFormのデザインエディタのツールボックスを開くとCustomCheckedListBoxが追加されているのでそれをドラッグ&ドロップで配置する.綺麗に表示できました.これだけで嬉しい.

チェックのついている行の文字色赤色にしてみる

さて自分で作ったコントロールが表示できたところで,次は機能拡張させることにします.今回はサンプルとしてチェックのついている行の文字を赤色にしてみます.とりあえず先ほど調べたstackoverflowのこのAnswerを参考にし,クラス名を変更したりusing System.Drawingを追記したりして実装してみます.この例ではチェックの入った列の文字が緑色になってくれるはずです.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;


namespace WindowsFormsApplication5.bin
{
    class CustomCheckedListBox : CheckedListBox
    {
        public CustomCheckedListBox()
        {
            DoubleBuffered = true;
        }
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            Size checkSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, System.Windows.Forms.VisualStyles.CheckBoxState.MixedNormal);
            int dx = (e.Bounds.Height - checkSize.Width) / 2;
            e.DrawBackground();
            bool isChecked = GetItemChecked(e.Index);//For some reason e.State doesn't work so we have to do this instead.
            CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(dx, e.Bounds.Top + dx), isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
            using (StringFormat sf = new StringFormat { LineAlignment = StringAlignment.Center })
            {
                using (Brush brush = new SolidBrush(isChecked ? CheckedItemColor : ForeColor))
                {
                    e.Graphics.DrawString(Items[e.Index].ToString(), Font, brush, new Rectangle(e.Bounds.Height, e.Bounds.Top, e.Bounds.Width - e.Bounds.Height, e.Bounds.Height), sf);
                }
            }
        }
        Color checkedItemColor = Color.Green;
        public Color CheckedItemColor
        {
            get { return checkedItemColor; }
            set
            {
                checkedItemColor = value;
                Invalidate();
            }
        }
    }
}

いざ実行してみると何やらエラーが.フォームのコントロールの中にエラーの警告が出ていてなかなか迫力がある.「デザイナーでハンドルされていない例外をスローして、無効になりました。例外:'0'のInvalidArgument= Valueは'index'に対して有効ではありません。パラメーター名:index」とのこと.さっぱりわからんので検索して参考にしたのはこちら.
【C#.NET】ListViewの選択しているインデックスを取得する|ばちブロ
どうもindexが0のときにもe.Indexを呼び出しているのが悪さをしているらしいので,要素の個数が0の時には描画処理を行わないようにしてやりました.Items.Countが0でないときのみこの描画処理を行うようにします.ついでにcheckedItemColorの指定をGreenからRedに変えてやります.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;


namespace WindowsFormsApplication5.bin
{
    class CustomCheckedListBox : CheckedListBox
    {
        public CustomCheckedListBox()
        {
            DoubleBuffered = true;
        }
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (Items.Count != 0)
            {
                Size checkSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, System.Windows.Forms.VisualStyles.CheckBoxState.MixedNormal);
                int dx = (e.Bounds.Height - checkSize.Width) / 2;
                e.DrawBackground();
                bool isChecked = GetItemChecked(e.Index);//For some reason e.State doesn't work so we have to do this instead.
                CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(dx, e.Bounds.Top + dx), isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
                using (StringFormat sf = new StringFormat { LineAlignment = StringAlignment.Center })
                {
                    using (Brush brush = new SolidBrush(isChecked ? CheckedItemColor : ForeColor))
                    {
                        e.Graphics.DrawString(Items[e.Index].ToString(), Font, brush, new Rectangle(e.Bounds.Height, e.Bounds.Top, e.Bounds.Width - e.Bounds.Height, e.Bounds.Height), sf);
                    }
                }
            }
        }
        Color checkedItemColor = Color.Red;
        public Color CheckedItemColor
        {
            get { return checkedItemColor; }
            set
            {
                checkedItemColor = value;
                Invalidate();
            }
        }

    }
}

はいできあがり!

まとめ

  • CheckedListBoxの文字色指定は結構大変だった.
  • カスタムコントロールの作り方をお勉強しました.
  • stackoverflowの答えをコピペしたらエラーが出た.
  • if文一つで解決した.
  • オリジナルのコントロールができた.嬉しい.
スッキリわかるJava入門 第2版
中山 清喬 国本 大悟
インプレス
売り上げランキング: 798

0 件のコメント :

コメントを投稿

ニュースがよくわからないあなたに「日経新聞:超サクッ!ニュースまとめ」

0 件のコメント

教養をつけるために

最近,頻繁に自身の教養不足を感じます.ニュースを聞いても内容が入ってこなかったり,一般教養の話の引き合いに出されたときによくわからず話してしまったり.何とかしないといけないと考えてはいるのですが,なかなか時間がとれなかったり気持ちが前向きにならない.まずは簡単なところから始めようと思い,日経新聞のサイトを開いてみるのですが,難しい.色々見ていると面白いものを見つけました.

超サクッ!ニュースまとめ :特集 :日本経済新聞
最近読みだしたのですが,シンプルでわかりやすい.平日の18:00に定期更新されています.話題になっているあるトピックについて,新聞の記事から引用しつつ,要点をまとめてあります.ニュースのトピックの大切なところが書かれているというのももちろんなのですが,1日1度の更新に反映されるトピックの選定自体も,莫大な情報量から特に重要なものを見出す手助けになっているのではと感じています.新聞の見出しや必要なところをつまみ出して読むというのが苦手なので気に入りました.

これをヒントに通常の記事も難なく読めたら嬉しいですね.時事の話題だけでなく,各分野の教養を付けたいと最近思うようになりました.何か良い本はないでしょうか.社会,文学など科学分野とは異なる教養について広く簡単に書いてあるような本,あれば教えてくださいませ.

0 件のコメント :

コメントを投稿

高機能テキストエディタSublime Text3を使ってみた

0 件のコメント

言わずと知れた高機能エディタ,Sublime Text3 の紹介です.
Web系の開発をする人には特におすすめ. カスタムできる部分が多いので,エディタにこだわりがあるけど良いものがないという人は必見.

特徴

使った感じの特徴を挙げてみます.
まず動作が軽い.IDEと比べればそれはそうなんですが,他のテキストエディタと比較しても遅いと感じることはありません.あと,マウス操作が皆無で良いくらいコマンド操作が充実している.そしてパッケージと呼ばれる拡張機能が充実している.困ったことがあればだいたいこれで補完できます.あと,デザインがとっても好み.

環境構築

高機能と聞いてファイルサイズも大きいのかと思いきや,ほんの5MB強のインストールパッケージでした. インストールも難しいことはなく指示通りにするだけ,1分足らずで終了しました.
パッケージを管理するために少しやらないといけないことがあるのですが,以下のサイトを見てやれば簡単にできました.
Sublime Text 3をインストールしたらまずやること

おすすめ機能・パッケージ

コマンドパレット

コマンドパレットとは,パッケージとかコマンドをすぐ呼び出せる機能です. 驚くべきはサジェスト機能で,適当に入力してもかなり正確な候補が出てきます. 例えばテキストのモードをHTMLモードにしたいとき,Syntax: HTMLというものを呼び出す必要があるのですが,

こんなに適当でも呼び出せます.すげえ!

パッケージ「Emmet」

Zen Codingの次のバージョンにあたるのがEmmetらしいのですが,これは何かというとHTML,CSSなどのマークアップを効率化する機能です.具体的には短いコードとショートカットを組み合わせて爆速でコードを書けるというもの.Sublime TextにもSnippetという似たような機能が元々用意されているのですが,HTML,CSSに関してはこちらの方が豊富です.
まず,「!」だけ入力してTabキーを押すと......

一瞬で基本的な部分がコーディングできました.
続いてbodyタグの中に「ul>li.Example$*5」と入力してTabを押すと......

これはたまげた.
詳しい使い方は以下を参照.
Emmet/Zen-coding入門 -ドットインストール
Cheat Sheet

まとめ

Sublime Textは使い込めば使い込むほど病み付きになるテキストエディタです! 最初はよくわからないのですが,わかるにつれて面白くなってきます. なかなかわからないという方はこちらを参照されると良いと思います.旧バージョンなのですが,動画でわかりやすく解説されています.

0 件のコメント :

コメントを投稿