WPF C# 提取并显示默认文件图标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13428580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:15:45  来源:igfitidea点击:

WPF C# Extract and Show Default File Icon

c#wpficons

提问by Amit Sharma

I am extracting system default icons (16 * 16 only) for some extensions like XLS, XLSX, PDF etc and trying to show that in Image Control. I am noticing that if I take dump of those icons on disk, they look sharp but the icons in my ListBox look somewhat blurred.

我正在为某些扩展程序(如 XLS、XLSX、PDF 等)提取系统默认图标(仅 16 * 16),并尝试在 Image Control 中显示它。我注意到如果我在磁盘上转储这些图标,它们看起来很清晰,但我的 ListBox 中的图标看起来有些模糊。

Any ideas what could be going on here ? I have tried a lot of suggestions from the posts I read from but couldn't make the problem go

有什么想法可能会在这里发生吗?我从我阅读的帖子中尝试了很多建议,但无法解决问题

Code Snippet:

代码片段:

Case1 - I am extracting the icon of file through Win32 Pinvoke - result -> blurrred icons

案例 1 - 我通过 Win32 Pinvoke 提取文件的图标 - 结果 -> 图标模糊

private const uint SHGFI_ICON = 0x100;
    private const uint SHGFI_LARGEICON = 0x0;
    private const uint SHGFI_SMALLICON = 0x1;
    private const int FILE_ATTRIBUTE_NORMAL = 0x80;
    private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
    [StructLayout(LayoutKind.Sequential)]
    private struct SHFILEINFO
    {
        public IntPtr hIcon;
        public IntPtr iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };
    [DllImport("shell32.dll")]
    private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes,   
   ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

private static Icon Extract(string fileName)
{
var shinfo = new SHFILEINFO();

IntPtr hIcon = SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SMALLICON);
//The icon is returned in the hIcon member of the shinfo struct
var icon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
DestroyIcon(shinfo.hIcon);
return icon;
}
[DllImport("User32.dll")]
public static extern int DestroyIcon(IntPtr hIcon);

Case2 - Dumping Icon objects created above to disk and viewing them in explorer -> the icons are of excellent quality

案例 2 - 将上面创建的图标对象转储到磁盘并在资源管理器中查看 -> 图标质量非常好

string filePath = string.Format("C:\temp\Icons\{0}.ico", iconName.Substring(1));
var stream = new FileStream(filePath, FileMode.OpenOrCreate);
iconObject.ExtensionSource.ToBitmap().Save(stream, ImageFormat.Bmp);
stream.Close();

ListBox xaml -

列表框 xaml -

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal"
                    Grid.Row="0"
                    Margin="10">
            <TextBox Text="{Binding ExtensionNames, Mode=TwoWay}"
                     ToolTip="Comma Separated List of Extensions, Tab out to persist changes.."
                     Margin="5"/>
            <Button Content="Dump All Icons" 
                    Click="Button_DumpAllIconsClick" 
                    Width="100"
                    ToolTip="Dump Path: C:\temp\Icons"
                    Margin="5"/>

        </StackPanel>
        <ListBox ItemsSource="{Binding Icons}"
                 Grid.Row="1"
                 Margin="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal"
                                HorizontalAlignment="Stretch"
                                Margin="5">
                        <TextBlock Text="{Binding ExtensionName}"
                                       FontWeight="Bold"
                                       FontSize="20"/>
                        <Image Source="{Binding Path=ExtensionSource,
                                                Converter={ExtractIconWPF:IconToImageSourceConverter}}"
                               Margin="5"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
</Grid>

How I am converting Icon to ImageSource object:

我如何将 Icon 转换为 ImageSource 对象:

var stream = GetIconStream(iconObject);
ImageSource source = GetBitMapImage(stream);

public static Stream GetIconStream(Icon icon)
{
var iconStream = new MemoryStream();

var bitmap = icon.ToBitmap();
bitmap.Save(iconStream, ImageFormat.Png);

return iconStream;
}

public static ImageSource GetBitMapImage(Stream iconStream)
{
var bi = new BitmapImage();

bi.BeginInit();
bi.StreamSource = iconStream;
bi.EndInit();

return bi;
}

Any pointers will be highly appreciated!

任何指针将不胜感激!

Thanks

谢谢

采纳答案by Amit Sharma

Sharing what helped in my case for others who face similar problem.

分享对我的情况有帮助的其他面临类似问题的人。

Setting this property on Image helped a ton in removing the blur:

在 Image 上设置此属性有助于消除模糊:

RenderOptions.BitmapScalingMode="NearestNeighbor"

In other case, we were showing the image in a grid cell which was 20 * 20, so we ended up removing the default Image stretch with below setting. That made a lot of diff too.

在其他情况下,我们在 20 * 20 的网格单元格中显示图像,因此我们最终使用以下设置删除了默认的图像拉伸。这也造成了很大的不同。

Stretch = Stretch.None

回答by Sebastien Lemichez

I know it's been a while this subject is resolved but I've seen a cool shortcut to win32 invoke :

我知道这个主题已经解决了一段时间,但我看到了一个很酷的 win32 invoke 快捷方式:

var sysicon = System.Drawing.Icon.ExtractAssociatedIcon(filePath);
var bmpSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
        sysicon.Handle,
        System.Windows.Int32Rect.Empty,
        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
sysicon.Dispose();

I think it could be better than all what you did.

我认为这可能比你所做的一切都好。

Source : Here

来源:这里

回答by Morten Frederiksen

Here is a solution to your question:

这是您问题的解决方案:

Get Registered File Types and Their Associated Icons in C#

在 C# 中获取注册的文件类型及其相关图标

made by Man Vuong.

Man Vuong 制作。