リストボックスのリストを行ごとに色分けするには?

解決


VBちょっとかじってます  2004-05-22 14:17:35  No: 113432  IP: [192.*.*.*]

VB6.0で画面を開発しています。
リストボックスのリストを1行ずつ
異なる色で表示させたいのですが、
どなたか方法をご存知でしょうか?

現在行のForeColorは○○色みたいな
設定ってロジックでできますか?

編集 削除
魔界の仮面弁士  2004-05-22 14:31:51  No: 113433  IP: [192.*.*.*]

ListBoxの場合、APIを使って文字列を「描画」する必要があります。
行単位で色を変えたいのであれば、ListBoxの替わりに
・TreeViewコントロール
・ListViewコントロール
・MSHFlexGridコントロール
などを使う事ができます。

編集 削除
VBちょっとかじってます  2004-05-22 15:15:39  No: 113434  IP: [192.*.*.*]

レスいただきましてありがとうございます。

「APIを使って文字列を「描画」する」
とのことですが、具体的に
どのAPI関数を使えばよろしいですか?

編集 削除
魔界の仮面弁士  2004-05-22 19:01:41  No: 113435  IP: [192.*.*.*]

項目単位での色指定機能を持たないコントロールで、無理矢理APIを使って
実現させるなどという面倒な手順を踏むよりも、最初から色を指定可能な
コントロールを選択した方が、手軽だと思いますけれども……。(^^;)

例えば、TreeViewで実現するなら、こんな感じで済みますよ。
http://madia.world.coocan.jp/vb/vb_bbs/200311_03110023.html


> 「APIを使って文字列を「描画」する」
一言で「描画」と書きましたが、そのための処理はかなり面倒です。

VB.NETなら、描画すべきタイミングがイベントで通達されますし、
APIも不要なので、実装も簡単ですが……VB6だと厄介な作業が待っています。
http://dobon.net/vb/dotnet/control/lbownerdraw.html
http://santamartadotnet.hp.infoseek.co.jp/documents/vbdotnet/ownerdraw.html


> どのAPI関数を使えばよろしいですか?
オーナードロー方式とサブクラス方式があります。

オーナードロー方式では、LBS_OWNERDRAWFIXED または LBS_OWNERDRAWVARIABLE という
スタイルを指定したListBoxを作る事になります(後者は、各項目の高さが一定では
ない時に使い、前者は全て同じ高さの時に使います)。VB6の「オブジェクトブラウザ」で
利用されているのが、この LBS_OWNERDRAWFIXED スタイルのListBoxです。

このスタイルを指定すると、項目を描画する必要がある時に、OSから
WM_DRAWITEMというメッセージが送られてきます。この時、一緒に
DRAWITEMSTRUCT構造体が渡されてきますので、それを利用します。

DRAWITEMSTRUCT構造体のitemIDメンバは、項目の番号を示します。
itemActionメンバは、選択状態やフォーカスの有無などを示します。
そして、hDCメンバはデバイスコンテキストハンドルを示しています。
ここに、TextOut API等を使って、描画処理を行うことができます。
(描画する座標位置は、rcItemメンバから得る事になります)

…しかし、VB6のListBoxには、LBS_OWNERDRAWFIXED を指定するための機能が
用意されていません。なので、ListBox自体を CreateWindowEx API等で
作成する必要があります。(これはつまり、ListBoxのあらゆる操作に、VB標準の
プロパティやメソッドが使えず、すべてAPIだけで記述する必要があるという事です)


一方、サブクラス化方式の場合は、LBS_OWNERDRAWFIXED は利用しません。
VB6のAddressOf演算子と、SetWindowLong API を使って、ListBox が OS と
通信しているメッセージを横取りしてしまい、OSがやるはずだった
項目の描画処理を、VB6で肩代わりするという手法です。

ListBoxをサブクラス化して項目を描画するVB向けサンプルは、
Microsoftのサイト(オーナーエリア)で公開されていた
DbgWproc.exe 内の Drawitemフォルダに含まれています。

下記に、その紹介があります。
http://www.galliver.co.jp/writing/susume_vb/tre908/

ただし、上記のページからリンクされたページに行っても、肝心の DbgWproc が
見つからないかも知れません。その場合は、下記URLから直接入手してください。
http://download.microsoft.com/download/vb60pro/update/6.0/w9x2k/en-us/dbgwproc.exe


上記をexeを展開すると、DrawItemというフォルダに、Group1.vbg という
ファイルがあります。それをダブルクリックして開いて見てください。

このサンプル自体は、ListBoxにアイコンを表示するためのものであって、
項目の色を変えるという物ではありません。そこで、ソースに少々手を加えます。

サンプル中の OwnerDrawListBox を開き、そのコード中にある
  Private Sub DrawItemText(pDIS As DRAWITEMSTRUCT)
というプロシージャから、以下の行を修正します。

修正前:
  SetTextColor hdc,  m_Colors(clrText)

修正後:
  SetTextColor hdc, QBColor(pDIS.itemID And 15)


元のコードでは、各項目の状態にあわせて
 ・標準的な文字色(黒など)
 ・選択時の文字色(白など)
を切り替えていたのですが、今回、QBColor関数を使って
修正したコードでは、選択状態に関係なく、
黒, 紺, 緑, 青緑, 茶, 暗紫, 黄土色, 薄灰,
濃灰, 青, 黄緑, 水色, 赤, 桃色, 黄色, 白 の
繰り返しで表示されるようになります。
QBColorの替わりにRGB関数を使えば、より細かい色も指定できます。

# 実際の処理では、単に1行ごとに色を変化させるのではなく、
# 項目番号(つまり、.itemID)に応じて、指定する事になるでしょう。

編集 削除
VBちょっとかじってます  2004-05-24 11:03:57  No: 113436  IP: [192.*.*.*]

>これはつまり、ListBoxのあらゆる操作に、
>VB標準のプロパティやメソッドが使えず、
>すべてAPIだけで記述する必要があるという事です

やはりご指摘のとおり、
「色を指定可能なコントロールを選択した方が、手軽」
だと思います。
それを承知な上でAPI関数での実装方法を
ご質問させていただきましたが、
これほど大変とは・・・

勉強になりました。
丁寧にご教授いただき、ありがとうございました。

編集 削除