リストビューのLVS_SHAREIMAGELISTSフラグの問題

解決


Picard  2008-08-15 23:14:49  No: 68855  IP: [192.*.*.*]

はじめまして。VC初心者のPicardといいます。
 
現在仮想フォルダを表示するエクスプローラのようなソフトウェアを作成しようと思い、いくつかのサンプルコードを参考にしています。
リストビューの作成用に下記のたろさんのサンプルコードを参考にさせていただいています。
http://www5b.biglobe.ne.jp/~kouta_y/c/c07.html
 
サンプルコードのFileView.cの中で、リストビューのスタイルを指定する以下のフラグがあります。
 WS_CHILD | WS_VISIBLE | LVS_ICON | LVS_SHOWSELALWAYS | LVS_OWNERDATA,
 
これにLVS_SHAREIMAGELISTSを追加すると表示されるアイコンが、微妙におかしくなります。具体的に言いますとアイコンの背景がちゃんと透明になりません(中途半端)。これはなぜなのでしょうか?
 
 LVS_SHAREIMAGELISTSは、「コントロールが破棄されても関連付けられているイメージリストを破棄しない複数のリストビューでイメージリストを共有する時に指定する 」ということらしいです。
 
各仮想ファイル名で、
 SHGetFileInfo(file, 0, &info, sizeof(info), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES );
 のようにして、アイコンを取得したいのです。

その場合、LVS_SHAREIMAGELISTSを指定すると、前述したようにアイコンが変になってしまします。なにかアドバイスがあれば、ご教授お願いいたします。

なお、同様の質問をサンプルコードの作成者である「たろさんの掲示板」http://cgi.www5b.biglobe.ne.jp/~kouta_y/cgi-bin/cgi-bbs/s3mb/w_s3mbix.cgiにも書き込んだのですが、お返事がないようですので、こちらで質問させていただきました。よろしくお願いいたします。

編集 削除
シャノン  2008-08-18 12:07:07  No: 68856  IP: [192.*.*.*]

念のため、たろさんの方にも、こっちでも質問している旨、書いておいたほうがいいと思います。

ところで、OS と、利用している VC++ のバージョンは何でしょうか?

編集 削除
Picard  2008-08-18 22:24:13  No: 68857  IP: [192.*.*.*]

すみません。開発環境を明記するのを忘れていました。
Windows XP SP3 + VC++(VS2008)です。CV++6.0でも試してみましたが同じ現象です。

たろさんの掲示板にもこちらで質問していることを書いておきます。

よろしくお願いいたします。

編集 削除
subaru  2008-08-19 10:39:29  No: 68858  IP: [192.*.*.*]

エクスプローラー風のリストビューなら普通は
LVS_SHAREIMAGELISTSスタイルにして
イメージリストにシステムイメージリストを設定して
アイコンは参照のみにすると思います。

サンプルではシステムイメージリストを使用せず、
リストビューのイメージリストを動的に更新しているようですが
単純にサンプルの内容でLVS_SHAREIMAGELISTSを指定したとしたら
それはどのような意図なのでしょうか?

編集 削除
Picard  2008-08-19 12:57:35  No: 68859  IP: [192.*.*.*]

>それはどのような意図なのでしょうか?
サンプルの内容では、LVS_SHAREIMAGELISTSは必要ないと思います。
実際に私が実現したいのは、実際にはWindowsファイルシステムではない仮想フォルダや仮想ファイル(たとえばDBやテキストファイルに情報が保存されているもの)をエクスプローラ風に表示することです。実際には、シェルネームスペースエクステンションを使用して、ウインドウズエクスプローラ内に独自のシェルを表示したく思っています。
他のいろいろなサンプルコードを参考にして、何とかデータベースからのデータを元に独自のシェルをエクスプローラ内に表示できるようになったのですが、アイコンの表示だけがどうしてもうまくいかないのです。原因がLVS_SHAREIMAGELISTSだということまでは、何とか突き止めましたが、なぜそうなってしまうのかがわかりません。
ですのでLVS_SHAREIMAGELISTSした場合には、そのようなアイコン表示になるのが仕様だということであれば、違う方法を検討しなければならないのですが、もし、何かそれを回避できる方法があればと思い、質問させていただきました。単純にLVS_SHAREIMAGELISTSを指定した状態で、正常にファイルの拡張子からファイルアイコンを取得したいだけなのです。
どうかよろしくお願いいたします。

編集 削除
subaru  2008-08-19 13:33:04  No: 68860  IP: [192.*.*.*]

事情はよくわかりませんがLVS_SHAREIMAGELISTSスタイルで
イメージリストの動的な更新も行うということでしょうか?

とりあえずリンク先にあるサンプルにLVS_SHAREIMAGELISTSを
付加しただけでは、アイコンが変になったりしないようですが・・・

編集 削除
シャノン  2008-08-19 14:47:05  No: 68861  IP: [192.*.*.*]

シェル名前空間拡張を実装してるんですか。すげー。
で、Windows 組み込みの仮想アイコン(マイコンピュータとか)の背景もおかしくなっちゃうんでしょうか?
自分のシェル拡張のアイコンだけがおかしいなら、IExtractIcon の実装がマズいとか考えられそうですが。

編集 削除
シャノン  2008-08-19 14:48:48  No: 68862  IP: [192.*.*.*]

ん?

> 実際には、シェルネームスペースエクステンションを使用して、ウインドウズエクスプローラ内に独自のシェルを表示したく思っています。

だとすると、

> 現在仮想フォルダを表示するエクスプローラのようなソフトウェアを作成しようと思い、

というのは何なんです?
シェル名前空間拡張を作っているなら、エクスプローラ「のようなソフトウェア」は要らないのでは?

編集 削除
Picard  2008-08-19 15:08:03  No: 68863  IP: [192.*.*.*]

subaruさんへ
試していただけたようでありがとうございます。
>LVS_SHAREIMAGELISTSを付加しただけでは、アイコンが変になったりしないようですが・・・
あれ??そうですか?PDFやExcel、フォルダのアイコンなどの背景が微妙に違いませんか?もう一度別のパソコンで確認してみます。

他の方も表示はうまく行っているのでしょうか?結果を教えていただければ幸いです。

シャノンさんへ
>シェル名前空間拡張を実装してるんですか。すげー。
サンプルコードを改造しているだけです...。
最初に書いてあるとおりVC++初心者です。
サンプルを一生懸命読んで理解しながら(つもり)、改造しています。
http://www.codeproject.com/KB/shell/TipsInNSE_SubFld.aspxシリーズを利用させてもらっています。
このサンプルでLVS_SHAREIMAGELISTSが使用されています。
この方は独自のアイコンを使用されているのですが、私はウインドウズのシステムアイコンと独自のアイコンの両方を使用したいと考えています。

>シェル名前空間拡張を作っているなら、エクスプローラ「のようなソフトウェア」は要らないのでは?
おっしゃる通りです。ただ、LVS_SHAREIMAGELISTSを追加するとアイコンがうまく表示されない原因を知りたかったので、あまり考えずに質問してしまいました。惑わせるようなことを書いてしまいすみませんでした。

編集 削除
gak  2008-08-19 16:22:26  No: 68864  IP: [192.*.*.*]

> 他の方も表示はうまく行っているのでしょうか?
WinXPsp3 + VC6sp6 環境では症状が起きた。その他の環境はどうなるか知らない。

> LVS_SHAREIMAGELISTSを追加するとアイコンがうまく表示されない原因を知りたかったので
LVS_SHAREIMAGELISTS 無しだと問題無く、有りだと症状が起きる原因は知らない(仕様なんだろうか?)
けど、たろさんのサンプルコードにおいて症状を改善するには
・マニフェストを作成して ComCtl32.dll Ver.6 以降を使用するように設定
・イメージリスト作成時 ILC_COLOR32 を指定してアルファチャンネル領域を確保する
とすればいけるはず。

編集 削除
Picard  2008-08-19 22:29:16  No: 68865  IP: [192.*.*.*]

gakさんありがとうございます。
http://wind-master.dip.jp/soft-info/item/56
に説明されていたやり方で、とりあえずマニフェストファイルを作成することによって、
gakさんの言われるとおり、たろさんのサンプルで正常にアイコンが表示されました。
今度は、別ファイルではなくリソースに組み込んでみようと思います。
また、後で調査しようと思っていたビジュアルも良くなり一石二鳥です。

また、こちらのページにも同様の問題が指摘されているのを発見したのでリンクを張っておきます。
[BCB] ListViewに32bitアイコンを表示
http://kwikwi.cocolog-nifty.com/blog/tlistview/index.html

LVS_SHAREIMAGELISTSの問題自体は、真には解決ではないですが、
今回の私の問題はとりあえずこれで解決しましたので、解決とさせていただきます。

皆さんどうもお世話になりました。感謝します。

編集 削除
subaru  2008-08-19 22:48:51  No: 68866  IP: [192.*.*.*]

改めましてXPSP2でOK。XPSP3、VISTAでNGでした。

すでに解決されているようですが、イメージリストを作成後、
ImageList_SetBkColorでイメージリストの背景色を0xc0c0c0に
設定することでも正常にアイコンが表示されました。

#理由はよくわからないんですけどね。。。

編集 削除
Picard  2008-08-19 23:53:31  No: 68867  IP: [192.*.*.*]

subaruさん
ありがとうございます。subaruさんのやり方でもうまく行きました。
>背景色を0xc0c0c0に設定することでも...。
どうしてこのようなことが分かったのでしょうか?
私には見当もつきませんでした。さすがとしか言いようがありません。

現在DLLにどうやってmanifestを組み込むか調査中です。難儀してます。

編集 削除
subaru  2008-08-20 20:10:13  No: 68868  IP: [192.*.*.*]

システムイメージリストをImageList_Duplicateで複製したもの
を使うとうまくいったのと、以前アイコンを動的にビットマップに
変換したものからイメージリストを作成したときに背景の一部が透過された
ことがあり予測がつきました。

で、よく調べもせず0xc0c0c0と書いてしまいましたが
普通に0xffffffでよかったです。
(システムイメージリストにImageList_GetBkColorで確認)

編集 削除
subaru  2008-08-22 15:47:59  No: 68869  IP: [192.*.*.*]

たびたびすみません。

>普通に0xffffffでよかったです。
>(システムイメージリストにImageList_GetBkColorで確認)

これって単にリストビューの背景色のようですね。
GetSysColorかListView_GetBkColorで取得する必要があるのかも。
おかしくなるときはどうも常にイメージリストの背景色が
適用されているような感じなのかな?(背景がCLR_NONEでも)
WM_SYSCOLORCHANGEの対応の手間などもありそうなので
gakさんの方法をおすすめします。

編集 削除