エクスプローラのアイコンを管理している、システムイメージリストを作成し、アイコンを参照して利用するコードを紹介します。
概要
SHGetFileInfo() APIで第4引数に"SHGFI_SYSICONINDEX"を与えて呼び出すと、システムイメージリストのハンドルを取得できます。合わせて"SHGFI_LARGEICON"を指定すると大きいアイコンを取得できます。
プログラム
UI
下図のUIを作成します。
コード
以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ShellObjects
{
public class SystemImageList
{
public enum SystemIconSize {Small, Large};
// Used to store the handle of the system image list.
private static IntPtr m_pImgHandle = IntPtr.Zero;
// Flags whether we've already retrieved the image list handle or not.
private static Boolean m_bImgInit = false;
// TreeView message constants.
private const UInt32 TVSIL_NORMAL = 0x0000;
private const UInt32 TVSIL_STATE = 0x0002;
private const UInt32 TVM_SETIMAGELIST = 0x1109; //4361;
// ListView message constants.
private const UInt32 LVSIL_NORMAL = 0x0000;
private const UInt32 LVSIL_SMALL = 0x0001;
private const UInt32 LVSIL_STATE = 0x0002;
private const UInt32 LVSIL_GROUPHEADER = 0x0003;
private const UInt32 LVM_SETIMAGELIST = 0x1003;
public SystemImageList(bool SelectedImage, SystemIconSize iconSize)
{
InitImageList(SelectedImage, iconSize);
}
private void InitImageList(bool selected, SystemIconSize iconSize)
{
IntPtr ppidl = IntPtr.Zero;
ShellWindowsAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellWindowsAPI.CSIDL.CSIDL_DESKTOP, ref ppidl);
ShellWindowsAPI.SHFILEINFO shInfo = new ShellWindowsAPI.SHFILEINFO();
ShellWindowsAPI.SHGFI dwAttribs;
dwAttribs = ShellWindowsAPI.SHGFI.SHGFI_USEFILEATTRIBUTES | ShellWindowsAPI.SHGFI.SHGFI_SYSICONINDEX;
switch (iconSize) {
case SystemIconSize.Small:
dwAttribs = dwAttribs | ShellWindowsAPI.SHGFI.SHGFI_SMALLICON;
break;
case SystemIconSize.Large:
dwAttribs = dwAttribs | ShellWindowsAPI.SHGFI.SHGFI_LARGEICON;
break;
}
if (selected == true) {
dwAttribs = dwAttribs | ShellWindowsAPI.SHGFI.SHGFI_SELECTED;
}
m_pImgHandle = ShellWindowsAPI.SHGetFileInfo(ppidl, ShellWindowsAPI.FILE_ATTRIBUTE_NORMAL, out shInfo, (uint)Marshal.SizeOf(shInfo), dwAttribs);
}
/// <summary>
/// Sets the image list for the TreeView to the system image list.
/// </summary>
/// <param name="tvwHandle">The window handle of the TreeView control</param>
public void TreeViewSetImageList(TreeView targetTreeView)
{
//InitImageList();
Int32 hRes = ShellWindowsAPI.SendMessage(targetTreeView.Handle, TVM_SETIMAGELIST, TVSIL_NORMAL, m_pImgHandle);
if (hRes != 0)
Marshal.ThrowExceptionForHR(hRes);
}
/// <summary>
/// Sets the image list for the ListView to the system image list.
/// </summary>
/// <param name="tvwHandle">The window handle of the TreeView control</param>
public void ListViewSetImageList(ListView targetListView)
{
//InitImageList();
Int32 hRes = ShellWindowsAPI.SendMessage(targetListView.Handle, LVM_SETIMAGELIST, LVSIL_NORMAL, m_pImgHandle);
if (hRes != 0)
Marshal.ThrowExceptionForHR(hRes);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ShellObjects;
namespace SystemImageListDemo
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
SystemImageList sil1 = new SystemImageList(false, SystemImageList.SystemIconSize.Small);
sil1.TreeViewSetImageList(treeView1);
SystemImageList sil2 = new SystemImageList(false, SystemImageList.SystemIconSize.Large);
sil2.ListViewSetImageList(listView1);
}
private void button1_Click(object sender, EventArgs e)
{
for (int i=0; i < 100; i++) {
TreeNode tn = new TreeNode("test-"+i.ToString(), i, i);
treeView1.Nodes.Add(tn);
}
for (int i=0; i < 100; i++) {
ListViewItem lv = new ListViewItem("test-" + i.ToString());
lv.ImageIndex = i;
listView1.Items.Add(lv);
}
}
}
}
解説
プロジェクト配置
SystemImageList.csは別のクラスライブラリプロジェクト"ShellObjects"に配置しています。Windowsフォームアプリ側で参照設定にShellObjectsプロジェクトを追加して、uses ShellObjects を記述します。
システムイメージリスト
SHGetFileInfo() APIで第4引数に"SHGFI_SYSICONINDEX"を与えて呼び出すと、システムイメージリストのハンドルを取得できます。
リストビューでは大きい画像のシステムイメージリストを取得するため、第4引数に"SHGFI_LARGEICON"を加えて指定します。ツリービューでは、小さいアイコンを指定するため、第4引数に"SHGFI_SMALLICON"を加えて指定します。
コントロールへの設定
コントロールへの設定はWindowsメッセージの送信で設定します。ツリービューへイメージリストを設定する場合は、TVM_SETIMAGELISTメッセージをコントロールに送信します。リストビューの場合は、LVM_SETIMAGELISTメッセージを送信します。メッセージのwparamに設定したいイメージリストのハンドルを与えます。
実行結果
プロジェクトを実行します。下図のウィンドウが表示されます。
[button1]をクリックします。TreeViewとListViewに項目が追加され、システムイメージリストのアイコンが表示されます。エクスプローラのフォルダやディスクドライブ、ネットワークのアイコンが表示されることが確認できます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2020-03-21
作成日: 2015-05-27