【C#】TreeViewとListViewにシステムイメージ(アイコン)を表示する
おはようございます。
昨日に引き続き、Windows Forms で、エクスプローラーのような表示をするために、
今回はファイル・フォルダの横にアイコンを表示してみます。
プログラムは前回のものを流用します。
【C#】TreeView と ListView でエクスプローラーのような画面を作成してみた
スポンサーリンク
プログラムの修正
DLL関数の呼び出し宣言を追加
システムイメージを利用するには「Shll32.dll」、「user32.dll」の関数を呼び出す必要があるため、関数呼び出しの宣言を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // DllImportに必要 usingSystem.Runtime.InteropServices; /// <summary> /// ファイル情報を取得 /// </summary> /// <param name="pszPath"></param> /// <param name="dwFileAttributes"></param> /// <param name="psfi"></param> /// <param name="cbFileInfo"></param> /// <param name="uFlags"></param> /// <returns></returns> [DllImport("shell32.dll",CharSet=CharSet.Auto)] privatestaticexternIntPtr SHGetFileInfo(stringpszPath,uintdwFileAttributes,outSHFILEINFO psfi,uintcbFileInfo,uintuFlags); /// <summary> /// イメージリストを登録 /// </summary> /// <param name="hWnd"></param> /// <param name="Msg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> [DllImport("user32.dll",CharSet=CharSet.Auto)] privatestaticexternIntPtr SendMessage(IntPtr hWnd,uintMsg,IntPtr wParam,IntPtr lParam); |
構造体や定数の定義
DLL関数で利用する構造体や定数の定義を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /// <summary> /// SHGetFileInfo関数で使用する構造体 /// </summary> [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] privatestructSHFILEINFO { publicIntPtr hIcon; publicintiIcon; publicuintdwAttributes; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=260)] publicstringszDisplayName; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=80)] publicstringszTypeName; }; // ファイル情報用 privateconstintSHGFI_LARGEICON=0x00000000; privateconstintSHGFI_SMALLICON=0x00000001; privateconstintSHGFI_USEFILEATTRIBUTES=0x00000010; privateconstintSHGFI_OVERLAYINDEX=0x00000040; privateconstintSHGFI_ICON=0x00000100; privateconstintSHGFI_SYSICONINDEX=0x00004000; privateconstintSHGFI_TYPENAME=0x000000400; // TreeView用 privateconstintTVSIL_NORMAL=0x0000; privateconstintTVSIL_STATE=0x0002; privateconstintTVM_SETIMAGELIST=0x1109; // ListView用 privateconstintLVSIL_NORMAL=0; privateconstintLVSIL_SMALL=1; privateconstintLVM_SETIMAGELIST=0x1003; // 選択された項目を保持 privateStringselectedItem=""; |
起動時にシステムイメージを登録
起動時の処理で、TreeView、ListViewにイメージのリストを登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /// <summary> /// 起動時の処理 /// </summary> publicForm1() { InitializeComponent(); // イメージリストの設定 SHFILEINFO shFileInfo=newSHFILEINFO(); IntPtr imageListHandle=SHGetFileInfo(String.Empty,0,outshFileInfo,(uint)Marshal.SizeOf(shFileInfo),SHGFI_SMALLICON|SHGFI_SYSICONINDEX); // TreeView SendMessage(treeView1.Handle,TVM_SETIMAGELIST,newIntPtr(TVSIL_NORMAL),imageListHandle); // ListView SendMessage(listView1.Handle,LVM_SETIMAGELIST,newIntPtr(LVSIL_SMALL),imageListHandle); // ドライブ一覧を走査してツリーに追加 foreach(Stringdrive inEnvironment.GetLogicalDrives()) { // アイコンの取得 inticonIndex=0; IntPtr hSuccess=SHGetFileInfo(drive,0,outshFileInfo,(uint)Marshal.SizeOf(shFileInfo),SHGFI_SYSICONINDEX); if(hSuccess!=IntPtr.Zero) { iconIndex=shFileInfo.iIcon; } // 新規ノード作成 // プラスボタンを表示するため空のノードを追加しておく TreeNode node=newTreeNode(drive,iconIndex,iconIndex); node.Nodes.Add(newTreeNode()); treeView1.Nodes.Add(node); } // 初期選択ドライブの内容を表示 setListItem(Environment.GetLogicalDrives().First()); } |
ListViewの内容更新時の処理を修正
TreeViewが選択された際にListViewの内容を更新する処理で、
表示するファイル、フォルダ―のイメージを取得して設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | /// <summary> /// リストビューの項目を設定します. /// </summary> privatevoidsetListItem(StringfilePath) { // リストビューのヘッダーを設定 listView1.View=View.Details; listView1.Clear(); listView1.Columns.Add("名前"); listView1.Columns.Add("種類"); listView1.Columns.Add("更新日時"); listView1.Columns.Add("サイズ"); try { // フォルダ一覧 DirectoryInfo dirList=newDirectoryInfo(filePath); foreach(DirectoryInfo di indirList.GetDirectories()) { ListViewItem item=newListViewItem(di.Name); // フォルダ種類、アイコンの取得 Stringtype=""; inticonIndex=0; SHFILEINFO shFileInfo=newSHFILEINFO(); IntPtr hSuccess=SHGetFileInfo(di.FullName,0,outshFileInfo,(uint)Marshal.SizeOf(shFileInfo),SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_TYPENAME); if(hSuccess!=IntPtr.Zero) { type=shFileInfo.szTypeName; iconIndex=shFileInfo.iIcon; } // 各列の内容を設定 item.ImageIndex=iconIndex; item.SubItems.Add(type); item.SubItems.Add(String.Format("{0:yyyy/MM/dd HH:mm:ss}",di.LastAccessTime)); item.SubItems.Add(""); // リストに追加 listView1.Items.Add(item); } // ファイル一覧 List<String>files=Directory.GetFiles(filePath).ToList<String>(); foreach(Stringfile infiles) { FileInfo info=newFileInfo(file); ListViewItem item=newListViewItem(info.Name); // ファイル種類、アイコンの取得 Stringtype=""; inticonIndex=0; SHFILEINFO shinfo=newSHFILEINFO(); IntPtr hSuccess=SHGetFileInfo(info.FullName,0,outshinfo,(uint)Marshal.SizeOf(shinfo),SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_TYPENAME); if(hSuccess!=IntPtr.Zero) { type=shinfo.szTypeName; iconIndex=shinfo.iIcon; } // 各列の内容を設定 item.ImageIndex=iconIndex; item.SubItems.Add(type); item.SubItems.Add(String.Format("{0:yyyy/MM/dd HH:mm:ss}",info.LastAccessTime)); item.SubItems.Add(getFileSize(info.Length)); listView1.Items.Add(item); } } catch(IOException ie) { MessageBox.Show(ie.Message,"選択エラー"); } // 列幅を自動調整 listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); } |
TreeView展開時の処理を修正
同様に TreeView を展開する際の処理で、
フォルダ―のアイコンを取得して設定するように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /// <summary> /// ツリービュー項目展開時(前)のイベントハンドラ. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> privatevoidtreeView1_BeforeExpand(objectsender,TreeViewCancelEventArgse) { TreeNode node=e.Node; node.Nodes.Clear(); try { DirectoryInfo dirList=newDirectoryInfo(node.FullPath); foreach(DirectoryInfo di indirList.GetDirectories()) { // フォルダのアイコンを取得 SHFILEINFO shinfo=newSHFILEINFO(); inticonIndex=0; IntPtr hSuccess=SHGetFileInfo(di.FullName,0,outshinfo,(uint)Marshal.SizeOf(shinfo),SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_TYPENAME); if(hSuccess!=IntPtr.Zero) { iconIndex=shinfo.iIcon; } // 子を追加してノードを展開 TreeNode child=newTreeNode(di.Name,shinfo.iIcon,shinfo.iIcon); child.ImageIndex=iconIndex; child.Nodes.Add(newTreeNode()); node.Nodes.Add(child); } } catch(IOException ie) { MessageBox.Show(ie.Message,"選択エラー"); } } |
起動してみる
無事に TreeView、ListViewにアイコンを表示することができ、
更にエクスプローラーのようなUIになりました。
まとめ
プログラムについては共通化したり、別クラスに処理をまとめたりできるので整理が必要ですが、
ひとまずアイコンを表示する方法を試してみました。
ディスカッション
コメント一覧
お初にお目にかかります.
上記のコードを実装したところ,treeViewの方にはアイコンが表示されたのですが,
listViewの方にはアイコンが表示されませんでした.
item.ImageIndex=iconIndex;
のタイミングでitem.ImageIndexにはー1でない値が入っているのですが,GUI上に反映がされませんでした.
何か記述しなければならないことがあるのでしょうか…?
初歩的なこととは思いますが,ご回答いただけると幸いです.
いしづか様
いつもブログを見ていただきありがとうございます。
ご質問の件、
結構前の記事なので少々お時間をいただければお調べします。
ちなみに環境についてもう少し詳しく教えていただけますか?
よろしくお願いします。
I don’t know how to speak Japanese but I came across your blog and it helped me the most.
I have two questions and it will be a great help if you can answer me.
1. How do I make the Desktop to be the first node of Tree View?
2. Can you show me how to list files in list view when you double click the folder/item?
Thank you very much!
(Google 翻訳)
日本語が話せませんが、あなたのブログに出会い、一番役に立ちました。
2つ質問があるのですが、お答えいただけると大変助かります。
1. デスクトップをツリー ビューの最初のノードにする方法を教えてください。
2. フォルダー/アイテムをダブルクリックしたときにリスト ビューでファイルを一覧表示する方法を教えてください。
どうもありがとうございました!
justWonderWoman 様
ブログを見ていただきありがとうございます。
ご質問の回答ですが、
1の回答は
ドライブを走査する箇所を変更し、
“System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)”
でデスクトップのパスを取得、起点とすればいいと思います。
2の回答は
ダブルクリックイベントを追加し、選択されたファイルを”setListItem” メソッドに渡すことで出来ませんか?
よろしくお願いします。
(Google 翻訳)
justWonderWoman
Thank you for visiting our blog.
The answer to your question,
Answer 1 is
Change where the drive is scanned,
“System.Environment.GetFolderPath (Environment.SpecialFolder.DesktopDirectory)”
Get the desktop path with and use it as the starting point.
Answer 2 is
Is it possible to add a double click event and pass the selected file to the “setListItem” method?
Thank you.