여러 가지 방법이 있습니다. 한 가지 방법은 ImageList를 만들고 ListView에 링크 한 다음 각 개별 파일의 아이콘을 가져 와서 ImageList에 추가하고 ImageList의 적절한 인덱스에 아이콘을 표시하도록 ListViewItem을 설정하는 것입니다.
또 다른 방법은 쉘이 유지 관리하는 시스템 이미지 목록을 활용하는 것입니다. 이렇게하면 아이콘의 중복 사본을 직접 관리하지 않아도됩니다. ListView에 여러 개의 폴더가 있다고 상상해보십시오. 그들 모두는 동일한 아이콘을 갖지만, 특별한주의를 기울이지 않고도 폴더 아이콘을 사용하는 항목을 표시 할 때 그 폴더 아이콘의 사본을 여러 개 저장할 수 있습니다. 쉘 구현은이 모든 중복 추적을 처리합니다. 시스템 이미지 목록에는 필요한 아이콘 (명시 적으로 요청한 아이콘) 만 포함 된 다음 각각의 단일 복사본 만 포함됩니다. 저는 이것이 더 깔끔하고 우아한 디자인이라고 생각합니다. 그래서 그것을 구현합시다. P/Invoke 코드가 필요합니다.
internal static class NativeMethods
{
public const uint LVM_FIRST = 0x1000;
public const uint LVM_GETIMAGELIST = (LVM_FIRST + 2);
public const uint LVM_SETIMAGELIST = (LVM_FIRST + 3);
public const uint LVSIL_NORMAL = 0;
public const uint LVSIL_SMALL = 1;
public const uint LVSIL_STATE = 2;
public const uint LVSIL_GROUPHEADER = 3;
[DllImport("user32")]
public static extern IntPtr SendMessage(IntPtr hWnd,
uint msg,
uint wParam,
IntPtr lParam);
[DllImport("comctl32")]
public static extern bool ImageList_Destroy(IntPtr hImageList);
public const uint SHGFI_DISPLAYNAME = 0x200;
public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0;
public const uint SHGFI_SMALLICON = 0x1;
public const uint SHGFI_SYSICONINDEX = 0x4000;
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260 /* MAX_PATH */)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[DllImport("shell32")]
public static extern IntPtr SHGetFileInfo(string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbSizeFileInfo,
uint uFlags);
[DllImport("uxtheme", CharSet = CharSet.Unicode)]
public static extern int SetWindowTheme(IntPtr hWnd,
string pszSubAppName,
string pszSubIdList);
}
이제 사용해 보도록하겠습니다. 데모 목적을 위해, 나는 listView1
이름, 폼에 ListView 컨트롤을 추가 그것에서 "세부 사항"모드를 표시하도록 설정하고 폼의 Load 이벤트 처리기에 다음 코드를 덤프 :
private void Form1_Load(object sender, EventArgs e)
{
// Obtain a handle to the system image list.
NativeMethods.SHFILEINFO shfi = new NativeMethods.SHFILEINFO();
IntPtr hSysImgList = NativeMethods.SHGetFileInfo("",
0,
ref shfi,
(uint)Marshal.SizeOf(shfi),
NativeMethods.SHGFI_SYSICONINDEX
| NativeMethods.SHGFI_SMALLICON);
Debug.Assert(hSysImgList != IntPtr.Zero); // cross our fingers and hope to succeed!
// Set the ListView control to use that image list.
IntPtr hOldImgList = NativeMethods.SendMessage(listView1.Handle,
NativeMethods.LVM_SETIMAGELIST,
NativeMethods.LVSIL_SMALL,
hSysImgList);
// If the ListView control already had an image list, delete the old one.
if (hOldImgList != IntPtr.Zero)
{
NativeMethods.ImageList_Destroy(hOldImgList);
}
// Set up the ListView control's basic properties.
// Put it in "Details" mode, create a column so that "Details" mode will work,
// and set its theme so it will look like the one used by Explorer.
listView1.View = View.Details;
listView1.Columns.Add("Name", 500);
NativeMethods.SetWindowTheme(listView1.Handle, "Explorer", null);
// Get the items from the file system, and add each of them to the ListView,
// complete with their corresponding name and icon indices.
string[] s = Directory.GetFileSystemEntries(@"C:\...");
foreach (string file in s)
{
IntPtr himl = NativeMethods.SHGetFileInfo(file,
0,
ref shfi,
(uint)Marshal.SizeOf(shfi),
NativeMethods.SHGFI_DISPLAYNAME
| NativeMethods.SHGFI_SYSICONINDEX
| NativeMethods.SHGFI_SMALLICON);
Debug.Assert(himl == hSysImgList); // should be the same imagelist as the one we set
listView1.Items.Add(shfi.szDisplayName, shfi.iIcon);
}
}
참고하는 등의 간단한 샘플 프로그램으로 오류 검사를 거의하지 않습니다. 나는 Debug.Assert 온건주의 검사를 던졌다.
또한 완벽을 기하기 위해 Explorer에서 사용하는 것처럼 ListView 모양을 만들기 위해 코드를 던졌습니다. 그 주소는 SetWindowTheme function입니다.
쉘이하는 것을 다른 일이 있습니다하지만 당신은 여기에 누락 될 것이다. 예를 들어 셸 오버레이 - 소스 제어 시스템에 체크인 된 아이콘과 같은 특정 아이콘에 표시되는 작은 뱃지입니다. 그것은 독자를위한 운동으로 남겨 두었습니다. (힌트 : LVSIL_STATE
플래그는 ListView 컨트롤의 "상태"이미지 목록을 설정하는 데 사용됩니다.) 그들은 당일 Explorer를 작성하지 않았습니다.
https://msdn.microsoft.com/en-us/library/ms404308(v=vs.110).aspx? – BugFinder
* 매우 * 광범위한 질문. LIstView에서 항목의 아이콘을 설정하는 방법을 알려주시겠습니까? 시스템 이미지 목록을 검색하는 방법을 알려주시겠습니까? 또는 각 개별 파일의 아이콘을 검색 하시겠습니까? 크거나 작은 어떤 크기의 아이콘을 원하십니까? –
@CodyGray, 각 아이콘 및 폴더를 적절한 아이콘, 작은 아이콘으로 나타내려고합니다. 감사. – user3165438