いつもお世話になってます。
リストビューにコンピューターのアイコンを表示させたいと思ってます。
イメージリストのプロパティで表示したいアイコンを挿入して、
リストビューのプロパティの欄でイメージリストを指定すればいいのだと
思ったですが、うまくいきません。
やはりコードを書く必要があるのでしょうか?
ご存知の方、ご指導お願いいたします。
Add メソッド (ListItems コレクション)
の引数を調べてみてください。
http://www.takeittechies.com/vbtomo/boards/vbchoshoqa.php?do=spread&num=1023
編集 削除どのようにうまくいっていないのかはわかりませんが、
前回のスレッドとほぼ同じ内容ですよね。
サンプルを作ってみましたので試してみてください。
Option Explicit
Private Type IconType
cbSize As Long
picType As PictureTypeConstants
hIcon As Long
End Type
Private Type SHFILEINFO
hIcon As Long
iIcon As Long
dwAttributes As Long
szDisplayName As String * 260
szTypeName As String * 80
End Type
Private Type CLSIdType
id(16) As Byte
End Type
Private Declare Function SHGetSpecialFolderLocation Lib "shell32" (ByVal hwndOwner As Long, ByVal nFolder As Long, pidl As Long) As Long
Private Declare Function SHGetFileInfo Lib "shell32.dll" Alias "SHGetFileInfoA" (ByVal pszPath As Any, ByVal dwFileAttributes As Long, psfi As SHFILEINFO, ByVal cbFileInfo As Long, ByVal uFlags As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "oleaut32.dll" _
(pDicDesc As IconType, riid As CLSIdType, ByVal fown As Long, _
lpUnk As Object) As Long
'スペシャル(システム)なフォルダを取得するための定数
'なのだがサンプルでは未使用
Private Const CSIDL_DESKTOP = &H0
Private Const CSIDL_INTERNET = &H1
Private Const CSIDL_PROGRAMS = &H2
Private Const CSIDL_CONTROLS = &H3
Private Const CSIDL_PRINTERS = &H4
Private Const CSIDL_PERSONAL = &H5
Private Const CSIDL_FAVORITES = &H6
Private Const CSIDL_STARTUP = &H7
Private Const CSIDL_RECENT = &H8
Private Const CSIDL_SENDTO = &H9
Private Const CSIDL_BITBUCKET = &HA
Private Const CSIDL_STARTMENU = &HB
Private Const CSIDL_MYDOCUMENTS = &HC
Private Const CSIDL_MYMUSIC = &HD
Private Const CSIDL_MYVIDEO = &HE
Private Const CSIDL_DESKTOPDIRECTORY = &H10
Private Const CSIDL_DRIVES = &H11
Private Const CSIDL_NETWORK = &H12
Private Const CSIDL_NETHOOD = &H13
Private Const CSIDL_FONTS = &H14
Private Const CSIDL_TEMPLATES = &H15
'Private Const CSIDL_COMMON_STARTMENU = &H16
'Private Const CSIDL_COMMON_PROGRAMS = &H17
'Private Const CSIDL_COMMON_STARTUP = &H18
'Private Const CSIDL_COMMON_DESKTOPDIRECTORY = &H19
Private Const CSIDL_APPDATA = &H1A
Private Const CSIDL_PRINTHOOD = &H1B
Private Const CSIDL_LOCAL_APPDATA = &H1C
Private Const CSIDL_ALTSTARTUP = &H1D
Private Const CSIDL_COMMON_ALTSTARTUP = &H1E
Private Const CSIDL_COMMON_FAVORITES = &H1F
Private Const CSIDL_INTERNET_CACHE = &H20
Private Const CSIDL_COOKIES = &H21
Private Const CSIDL_HISTORY = &H22
Private Const SHGFI_ICON = &H100
Private Const SHGFI_LARGEICON = &H0
Private Const SHGFI_SMALLICON = &H1
Private Const SHGFI_PIDL = &H8
Private Const SHGFI_DISPLAYNAME = &H200&
Private ret As Long
Private Sub Form_Load()
Dim DispName As String
Dim IPic As IPictureDisp
Dim CSIDL As Long
Dim ImgCnt As Long
Dim SHFI As SHFILEINFO
Dim pid As Long
ListView1.Arrange = lvwAutoTop
'CSIDL_XXXXという定数を使用して行うのだが、めんどいのでFor文でループ
For CSIDL = 0 To &H22
Select Case CSIDL
Case &HF, &H16 To &H19
Case Else
'スペシャルフォルダのPIDLを取得
ret = SHGetSpecialFolderLocation(Me.hWnd, CSIDL, pid)
'スペシャルフォルダの小さいアイコンのハンドル取得
ret = SHGetFileInfo(pid, 0, SHFI, Len(SHFI), SHGFI_PIDL Or SHGFI_ICON Or SHGFI_SMALLICON)
Set IPic = IconToIPicture(SHFI.hIcon)
If Not (IPic Is Nothing) Then
ImgCnt = ImgCnt + 1
ImageList1.ListImages.Add , , IPic
'スペシャルフォルダの表示文字列及び大きいアイコンのハンドル取得
ret = SHGetFileInfo(pid, 0, SHFI, Len(SHFI), SHGFI_PIDL Or SHGFI_ICON Or SHGFI_LARGEICON Or SHGFI_DISPLAYNAME)
Set IPic = IconToIPicture(SHFI.hIcon)
ImageList2.ListImages.Add , , IPic
If ImgCnt = 1 Then
ListView1.SmallIcons = ImageList1
ListView1.Icons = ImageList2
End If
ListView1.ListItems.Add , , SHFI.szDisplayName, ImgCnt
End If
End Select
Next
End Sub
Private Sub Form_Resize()
If Me.ScaleWidth <= 0 Then Exit Sub
With ListView1
.Left = 0
.Top = 0
.Width = Me.ScaleWidth
.Height = Me.ScaleHeight
End With
End Sub
Private Function IconToIPicture(hIcon As Long) As IPictureDisp
Dim pic As IconType
Dim IPic As IPictureDisp
Dim IID_IDispatch As CLSIdType
Dim ret As Long
IID_IDispatch.id(8) = &HC0
IID_IDispatch.id(15) = &H46
With pic
.cbSize = Len(pic)
.picType = vbPicTypeIcon
.hIcon = hIcon
End With
ret = OleCreatePictureIndirect(pic, IID_IDispatch, 1, IPic)
Set IconToIPicture = IPic
End Function
返信が遅れて申し訳ありません。
りっとっとさんご丁寧にありがとうございます。
現在別の業務と平行して進めているので、
時間がかかると思いますが、試してみます。
まだVBを初めて間もないので、サンプルのコードを
理解できるかわかりませんが、自分なりに調べながら
やってみます。
また報告いたしますのでよろしくお願いいたします。
りっとっとさん提示のサンプルコードをためさせていただいたのですが、
WinXpならいいのですが、Win2000ですと、マイドキュメントアイコンがうまく取得できないようです。
うまく取得できる方法は、あるのでしょうか?
たいへん申し訳ないんですが、まだVBを始めたばかりで
りっとっとさんのサンプルコードを全く理解できませんでした。
コピー&ペーストすると確かにアイコンを表示できるのですが・・・
ごめんなさい
もっと詳しく解説をしていただけるとうれしいのですが
わがまま言ってすいません。
回答ではありません。
> りっとっとさんのサンプルコードを全く理解できませんでした。
> もっと詳しく解説をしていただけるとうれしいのですが
その前に、他の板で質問した件は解決したんですか?
http://www.takeittechies.com/vbtomo/boards/vbchoshoqa.php?do=spread&num=1023
サンプルコード全般の解説を求めるのではなく、解からない部分に絞って、
質問すべきでしょう?
>その前に、他の板で質問した件は解決したんですか?
申し訳ございません。同じ件を二つの板で書いてしまいました。
せっかくお答え頂いたので違う方法も覚えられたらと
思ったのですが。
>サンプルコード全般の解説を求めるのではなく、解からない部分に絞って、
質問すべきでしょう?
おっしゃるとおりです。私も自分で調べたりしてから、
できるだけ絞って質問しようと思ったのですが、調べ方も
ままならない状況レベルなんです。
自分でもう少し努力してみます。
サンプルプログラムの説明。
・SHGetSpecialFolderLocation関数
特殊フォルダのITEMIDLIST構造体へのポインタを取得します。
第1引数は、この関数を実行するアプリケーションのウィンドウハンドルを設定します。フォームのウィンドウハンドルでかまいません。
第2引数には、特殊フォルダを示す定数(CSIDL_XXXX)を設定します。
第3引数には、取得するためのLong型変数を設定します。
SHGetSpecialFolderLocation関数を実行すると、第3引数に設定した変数にポインタが取得されます。
ITEMIDLIST構造体は、ITEMIDLISTでグーグルなどで検索すると詳しい情報が得られます。
つまりは、指定した特殊フォルダが、ITEMIDLISTのどの位置なのかをポインタ(pIDL)で取得する関数です。
・SHGetFileInfo関数
ファイルまたはフォルダに関する情報を取得します。
取得できる情報は、SHFILEINFO構造体の定義を見るとわかるとおり
Private Type SHFILEINFO
hIcon As Long '関連付けされているアイコンのハンドル
iIcon As Long '関連付けされているアイコンのシステムイメージリストでのインデックス値
dwAttributes As Long '属性
szDisplayName As String * 260 '表示名
'フォルダのみ、フォルダ名と表示名が違う場合設定されている。
'たとえば、"マイドキュメント"というフォルダは、実際のフォルダ名は"My Document"である。
'この"マイドキュメント"という文字列がここに入る。
szTypeName As String * 80 'タイプ
End Type
です。
第一引数は、情報を取得したいファイルまたはフォルダのフルパス(String型)を本来設定するのですが、
今回は、特殊フォルダの情報を取得するため、SHGetSpecialFolderLocationで取得したITEMIDLISTへのポインタ(Long型)を
設定しています。
第2引数は取得するファイルの属性のマスク値を設定します。第5引数にSHGFI_USEFILEATTRIBUTESが含まれているときのみ有効です。
第3引数は取得するSHFILEINFO構造体の変数を設定します。関数を実行するとこの変数に情報が取得されます。
第4引数はSHFILEINFO構造体(変数)のバイト数を設定します。
第5引数は取得したい情報のフラグを設定します。フラグはビットデータですので複数設定する場合は Or 演算子を使用します。
SHGFI_ICON '関連付けされているアイコンのハンドルを取得
SHGFI_SYSICONINDEX '関連付けされているアイコンのシステムイメージリストでのインデックスを取得
SHGFI_LARGEICON '関連付けされているアイコンの情報を取得時に大きいアイコンの情報を取得する。(SHGFI_ICONまたはSHGFI_SYSICONINDEXと組み合わせて使用)
SHGFI_SMALLICON '同じく小さいアイコンの情報を取得
SHGFI_SHELLICONSIZE '(Shell(システム)での)規定サイズのアイコンの情報を取得
SHGFI_PIDL 'ITEMIDLISTへのポインタを使用して情報を取得
SHGFI_DISPLAYNAME '表示文字列を取得
SHGFI_USEFILEATTRIBUTES'ファイル属性を取得
SHGFI_TYPENAME 'タイプを取得("システム フォルダ"・"ファイル フォルダ"といったタイプ名が取得される)
SHGFI_EXETYPE '実行ファイルの種類を取得
'(SHGetFileInfo関数の戻り値(Long型)として取得。値によってWindowsアプリ・MS-DOSアプリ・Win32コンソールアプリかを判断できる)
・OleCreatePictureIndirect関数
PICDESC構造体(サンプルプログラムではIconType構造体)に設定した情報を元にピクチャーオブジェクトを作成。
第1引数は情報を設定したPICDESC構造体を設定します。
第2引数はIDispatchインタフェースのGUIDを設定します。
第3引数は取得するピクチャーオブジェクトのインタフェース変数を設定します。(サンプルではピクチャーオブジェクトのクラスにあわせてIpictureDispとしている)
これらの関数を使用してアイコンを取得しています。
サンプルプログラムの流れは、
SHGetSpecialFolderLocation関数にて特殊フォルダのITEMIDLISTへのポインタを取得。
SHGetFileInfo関数でポインタを元に関連付けられているアイコンのハンドルを取得。
OleCreatePictureIndirect関数で取得したアイコンハンドルを元にピクチャーオブジェクトを作成して、
作成したピクチャーオブジェクトをリストビューに関連付けしているイメージリストに追加。
追加後、リストビューにアイテムを追加。
という流れです。
リストビューにイメージリストを設定する場合、何もイメージ(画像)ないイメージリストを設定しようとすると
初期化されていないというエラーが発生しますので、イメージリストに1つ追加したとき(ImgCnt = 1)に設定しています。
りっとっとさんのサンプルコードで、
PIDLとアイコンハンドルの後始末を忘れている様な?
おかげさまでリストビューにアイコンを表示することが
できました。みなさん何度もご指導くださって
ありがとうございました。