获取特殊文件夹的图标,例如我的电脑和图书馆

Getting Icon Of Special Folders Such As My Computer And Libraries

我一直在尝试构建一个 class 来简单地获取特殊文件夹的当前图标,例如 "My Computer" AKA "Computer"、"Libraries" 等。我'我目前正在尝试使用 SHGetFileInfo() API 来实现此目的。

微软页面上的原始SHGetFileInfo函数...

#1 代码块

DWORD_PTR SHGetFileInfo(
  _In_     LPCTSTR pszPath,
  DWORD dwFileAttributes,
  _Inout_  SHFILEINFO *psfi,
  UINT cbFileInfo,
  UINT uFlags
);

(以上引用自:http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179%28v=vs.85%29.aspx

在另一个 SO 问题上,我发现这是一个例子...

#2 代码块

IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));

(以上引用自:)

描述了以需要第一个参数为 IntPtr 的方式使用 SHGetFileInfo。我的印象是第一个参数需要是基于此的字符串...

#3 代码块

[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);

(以上引用自:http://pinvoke.net/default.aspx/shell32.SHGetFileInfo

此外,环顾四周,我也找到了这个答案...

#4 代码块

[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
    [MarshalAs(UnmanagedType.LPWStr)] string szDataSource, 
    UIntPtr dwUserData,
    out IntPtr phQuery);

(以上引用自:)

在上面的回答中,用户告诉原始发布者使用...

#5 代码块

[MarshalAs(UnmanagedType.LPWStr)] string

映射到

#6 代码块

"_In_     LPCTSTR pszPath,"

参数。在顶部的 MSDN c++ 构造函数中找到。这对我来说比任何一个都更有意义。但是我无法理解的是上面的答案(#2 代码块)告诉原始发布者在 pinvoke.net 网站说将其定义为字符串时使用 IntPtr。

知道如何让 SHGetFileInfo() 工作以获得该图标吗?谢谢!


更新

这是我尝试使用它的示例...

[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(
  string pszPath,
  uint dwFileAttributes,
  ref SHFILEINFO psfi,
  uint cbFileInfo,
  uint uFlags
);

SHGetFileInfo((IntPtr)oTarget, 0, ref shfi, (uint)Marshal.SizeOf(shfi), flags);

然后我得到两个错误...

Error   1   The best overloaded method match for 'SHGetFileInfo(string, uint, ref SHFILEINFO, uint, uint)' has some invalid arguments   C:\FakePath\ImageWorker.cs  67  25  ImageWorker

Error   2   Argument 1: cannot convert from 'System.IntPtr' to 'string' C:\FakePath\ImageTool.cs    67  47  ImageWorker

如何获取图标示例:

 [DllImport("shell32.dll", CharSet = CharSet.Auto)]
 public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
 public struct SHFILEINFO
 {
     public IntPtr hIcon;
     public int iIcon;
     public uint dwAttributes;
     public string szDisplayName;
     public string szTypeName;
 };

SHFILEINFO shinfo= new SHFILEINFO();
SHGetFileInfo(@"...", 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), 0x000000100); //SHGFI_ICON

Icon icon = (Icon)Icon.FromHandle(shinfo.hIcon);

//use the icon and finally destroy it with:

DestroyIcon(shinfo.hIcon); 

SHGetFileInfo 相当时髦。第一个参数是指向以 null 结尾的字符数组的指针,或者是 PIDL。在非托管代码中,参数被声明为以 null 结尾的字符数组。如果您想通过 PIDL,那么您需要进行演员表。

在 p/invoke 调用中,您不能使用转换。因此,您需要声明两个重载的 p/invoke 导入。一个以 string 作为第一个参数,另一个以 IntPtr 作为第一个参数。