您的位置:首页 > 其它

Windows注册文件类型信息的学习心得

2008-10-20 15:54 239 查看
前一阵做系统注册文件类型图标的提取工具,本来以为使用SHGetFileInfo()函数只能获取指定文件名的图标,没想到还能获取指定扩展名关联的图标,因此绕了一个大弯路去研究注册表。虽然花费了很多时间,但我也并非一无所获,至少现在对于Windows中文件类型相关的注册表信息有了一定的了解了。

先说说最简单的根据文件扩展名获取类型图标的方法吧。

定义如下结构和类,用于进行Windows API调用:

/// <summary>
/// 定义文件信息存储结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct SHFILEINFO
{
internal IntPtr hIcon;
internal IntPtr iIcon;
internal uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
internal string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
internal string szTypeName;
};

/// <summary>
/// Windows Shell的常数定义和调用的API方法定义
/// </summary>
internal class WinShell
{
#region Const
internal const uint SHGFI_ICON = 0x100;
internal const uint SHGFI_LARGEICON = 0x0; // 'Large icon
internal const uint SHGFI_SMALLICON = 0x1; // 'Small icon
internal static uint SHGFI_SYSICONINDEX = 0x4000;
internal static uint SHGFI_USEFILEATTRIBUTES = 0x10;
#endregion

#region API
/// <summary>
/// 定义调用的API方法
/// </summary>
[DllImport("shell32.dll")]
internal static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

[DllImport("shell32.dll")]
internal static extern uint ExtractIconEx(string lpszFile, int nIconIndex, int[] phiconLarge, int[] phiconSmall, uint nIcons);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal extern static bool DestroyIcon(IntPtr handle);

#endregion
}
实现按扩展名进行图标提取的方法:

///<summary>
/// 给出文件扩展名(.*),返回相应图标
/// 若不以"."开头则返回文件夹的图标。
/// 若无法获取任何有效图标,则返回未知类型图标。
/// </summary>
/// <param name="extension">文件扩展名</param>
/// <param name="isLarge">是否为大图标(32×32)</param>
/// <returns>图标数据</returns>
public static Icon GetIconByExtension(string extension, bool isLarge)
{
if (!extension.StartsWith("."))
{
return GetFolderIcon(isLarge);
}

SHFILEINFO shfileinfo = new SHFILEINFO();

WinShell.SHGetFileInfo(extension, 0, ref shfileinfo, (uint) Marshal.SizeOf(shfileinfo),
WinShell.SHGFI_ICON | WinShell.SHGFI_USEFILEATTRIBUTES |
((isLarge) ? WinShell.SHGFI_LARGEICON : WinShell.SHGFI_SMALLICON));

return Icon.FromHandle(shfileinfo.hIcon);
}
上述代码只是简化后的实现,在实际应用中还应对获取到的图标数据进行处理,获取其托管图标类型的数据,并对获取图标失败的情况进行处理(如返回未知文件类型图标)。为了节省篇幅,具体实现方法在此就不写出来了,网上很多相关资料。提示:获取托管图标要用到的API函数为DestroyIcon();获取未知文件类型的图标将用到API函数ExtractIcon()或ExtractIconEx(),该图标为下Shell32.dll文件里的第一个图标(索引为0)。

接下来我们来看看注册表中系统注册文件类型的相关信息。

打开注册表的HKEY_CLASS_ROOT主键,会看到满眼的以“.”开头的字符串作为名称的子键,系统中注册的扩展名就存储在这里。但子键光是名称以“.”开头还不足以让它成为系统中注册的扩展名——要想成为扩展名,子键必须满足另外一个条件,即子键的默认键值不能为空。子键的默认键值指向该扩展名所对应的文件类型信息。文件类型信息中通常包含着该文件类型所对应的默认图标(在DefaultIcon子键下),还有该文件类型的默认操作处理方式(shell子键下,每一个下级子键对应一个谓语)。有些文件类型信息子键下还会包含ShellEx子键,这些子键用于处理Shell扩展,例如ShellEx\IconHandler对应的是用于图标处理的Shell扩展,通过IconHandler子键的默认键值,在HKEY_CLASS_ROOT\CLSID子键下寻找相应的子键,可以得到该IconHandler所对应的注册表信息。对于Shell扩展和扩展名子键下的其他子键,我还没有进行全面研究,还请Windows注册表的高手们指教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: