C# 获取特殊文件夹(如“我的电脑”和“库”)的图标
我一直在尝试构造一个类来简单地获取特殊文件夹的当前图标,例如“我的电脑”、“计算机”、“库”,等等。我目前正在尝试使用SHGetFileInfo()API来实现这一点 Microsoft页面上的原始SHGetFileInfo函数 #1代码块C# 获取特殊文件夹(如“我的电脑”和“库”)的图标,c#,winapi,icons,special-folders,C#,Winapi,Icons,Special Folders,我一直在尝试构造一个类来简单地获取特殊文件夹的当前图标,例如“我的电脑”、“计算机”、“库”,等等。我目前正在尝试使用SHGetFileInfo()API来实现这一点 Microsoft页面上的原始SHGetFileInfo函数 #1代码块 DWORD_PTR SHGetFileInfo( _In_ LPCTSTR pszPath, DWORD dwFileAttributes, _Inout_ SHFILEINFO *psfi, UINT cbFileInfo,
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
(以上引用自:)
在另一个问题上,我发现这是一个例子
#2代码块
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
(以上引用自:)
它描述了以要求第一个参数为IntPtr的方式使用SHGetFileInfo。我的印象是,第一个参数必须是基于此的字符串
#3代码块
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
(以上引用自:)
此外,环顾四周,我也找到了这个答案
#4代码块
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
(以上引用自:)
在上面的回答中,用户告诉原始海报使用
#5代码块
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
映射到
#6代码块
DWORD_PTR SHGetFileInfo(
_In_ LPCTSTR pszPath,
DWORD dwFileAttributes,
_Inout_ SHFILEINFO *psfi,
UINT cbFileInfo,
UINT uFlags
);
IntPtr pidl;
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[MarshalAs(UnmanagedType.LPWStr)] string
"_In_ LPCTSTR pszPath,"
帕拉姆。在顶部的MSDN C++构造函数中找到。这对我来说比任何一个都更有意义。但我无法理解的是上面的答案(#2代码块),当pinvoke.net网站说将IntPtr定义为字符串时,它告诉原始海报使用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);
如何获取图标示例:
[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
SHGetFileInfo
相当时髦。第一个参数是指向以null结尾的字符数组的指针或PIDL。在非托管代码中,参数声明为以null结尾的字符数组。如果您希望通过PIDL,则需要执行强制转换
在p/invoke调用中,不能使用强制转换。因此,您需要声明两个重载的p/invoke导入。一个使用
string
作为第一个参数,另一个使用IntPtr
SHGetFileInfo
根据是否设置了SHGFI_PIDL
标志来获取字符串或PIDL。文档非常清楚。我看不到任何证据表明您确实试图调用该函数。@JonathanPotter,即使我设置了该标志,该函数的第一个参数需要一个字符串(我定义它的方式)。因此,如果我设置该标志,然后尝试调用该函数,我会得到我刚刚更新的示例(上面)中引用的错误。我是否应该以不同的方式定义DllImport?如果是,请提供建议。谢谢@DavidHeffernan:我真的不明白你的评论到底要说什么,但只是为了好玩,我用一个例子更新了我的问题,我试着使用它……所以,什么是oTarget
?SHGetFileInfo
根据是否设置了SHGFI_-PIDL
标志来获取字符串或PIDL。文档非常清晰。我看不到任何证据表明您确实试图调用该函数。@JonathanPotter,即使我设置了该标志,该函数的第一个参数需要一个字符串(我定义它的方式)。因此,如果我设置该标志,然后尝试调用该函数,我会得到我刚刚更新的示例(上面)中引用的错误。我是否应该以不同的方式定义DllImport?如果是,请提供建议。谢谢@DavidHeffernan:我真的不明白你的评论到底想说什么,但只是为了好玩,我用了一个例子更新了我的问题,我试着使用它……那么,oTarget
?我以为你想通过一个PIDLI考试,你的答案是100%正确的!:/我很难决定答案应该是什么。我只是想建议对另一个答案进行编辑,同时添加另一个DllImport。。。你能在你的答案中加上一个例子吗?;)所以你-1我的问题是我的错误,嗯不,不是我。我不确定我们还需要另一个p/invoke声明。你显然相当熟练,我认为你需要的不仅仅是高水平。我以为你想通过皮德利考试,你的答案是100%正确的!:/我很难决定答案应该是什么。我只是想建议对另一个答案进行编辑,同时添加另一个DllImport。。。你能在你的答案中加上一个例子吗?;)所以你-1我的问题是我的错误,嗯不,不是我。我不确定我们还需要另一个p/invoke声明。你显然相当精通,我认为你需要的不仅仅是高水平。我只是想接受这个作为例子的答案。我很难决定答案应该是什么。但是+1作为示例,只是没有按照我的要求使用正确的DLLImport。;)我将接受这一点作为答案,只是为了举例。我很难决定答案应该是什么。但是+1作为示例,只是没有按照我的要求使用正确的DLLImport。;)