c# - 是否可以使用 Windows 图标选择器对话框?

标签 c# wpf dialog

在我的代码中,我希望我的用户能够从计算机上的任何位置选择一个图标。该图标可以是独立的 .ico,也可以是 .exe.dll 中的图标 - 不仅如此.exe/dll 的默认显示图标,以及其中包含的任何其他图标。

在理想的情况下,我希望能够使用这个 native Windows 图标选择器对话框:

Windows Icon Picker Dialog

但我不知道如何使用它 - 有可能吗? 此对话框对我来说非常理想,因为它似乎只允许用户浏览到图标或 .exe.dll 作为标准。

如果我的用户只能使用独立的 .ico 文件,那么我将采用在 Microsoft.WindowsAPICodePack- 中找到的 CommonOpenFileDialog 类。适用于 Windows Visa+ 的 Shell nuget 包和适用于旧系统的 System.Windows.Forms.FolderBrowserDialog - 如下所示:

private string SelectWinXPIcon()
{
    using (WinForms.OpenFileDialog ofd = new WinForms.OpenFileDialog()
    {
        Filter = "Icon files (*.ico)|*.ico",
    })
    {
        WinForms.DialogResult result = ofd.ShowDialog();
        switch (result)
        {
            case WinForms.DialogResult.OK:
            case WinForms.DialogResult.Yes:
                return ofd.FileName;

            default:
                return null;
        }
    }
}

private string SelectWinVistaIcon()
{
    using (CommonOpenFileDialog dialog = new CommonOpenFileDialog
    {
        DefaultDirectory = @"C:\",
        AllowNonFileSystemItems = false,
        EnsurePathExists = true,
        Multiselect = false,
        NavigateToShortcut = true
    })
    {
        dialog.Filters.Add(new CommonFileDialogFilter("Icon Files (*.ico)", ".ico"));
        CommonFileDialogResult result = dialog.ShowDialog();

        switch (result)
        {
            case CommonFileDialogResult.Ok:
                return dialog.FileName;

            default:
                return null;
        }
    }
}

但据我所知,这条路线不允许我的用户从 .exe/dll 中选择图标?

如果无法使用图标选择器对话框,是否有另一种方法可以从 .exe/dll 中提取图标,同时也允许独立的 .ico 要选择的文件?

最佳答案

这是通过 shell32 PickIconDlg 函数完成的,您可以使用 pinvoke site 轻松调用该函数。以供引用。该函数将返回文件名和索引,然后您可以使用the shell32 ExtractIconEx function提取图标句柄。 。然后,您可以将图标句柄转换为 GDI 图标或 WPF ImageSource。

作为示例,在 XAML 中声明一个图像以显示用户选择的图标:

<Image x:Name="myImage" Stretch="None" />

然后在窗口加载处理程序中使用此代码来显示对话框,加载它,将其转换为 ImageSource 并显示它:

[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int PickIconDlg(IntPtr hwndOwner, System.Text.StringBuilder lpstrFile, int nMaxFile, ref int lpdwIconIndex);

[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern uint ExtractIconEx(string szFileName, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons);

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

private const int MAX_PATH = 0x00000104;

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    // show the Pick Icon Dialog
    int index = 0;
    int retval;
    var handle = new WindowInteropHelper(this).Handle;
    var iconfile = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\shell32.dll";
    var sb = new System.Text.StringBuilder(iconfile, MAX_PATH);
    retval = PickIconDlg(handle, sb, sb.MaxCapacity, ref index);

    if (retval != 0)
    {
        // extract the icon
        var largeIcons = new IntPtr[1];
        var smallIcons = new IntPtr[1];
        ExtractIconEx(sb.ToString(), index, largeIcons, smallIcons, 1);

        // convert icon handle to ImageSource
        this.myImage.Source = Imaging.CreateBitmapSourceFromHIcon(largeIcons[0],
            Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

        // clean up
        DestroyIcon(largeIcons[0]);
        DestroyIcon(smallIcons[0]);
    }
}

它将与 DLL/EXE 等以及独立的 .ICO 文件一起使用。

关于c# - 是否可以使用 Windows 图标选择器对话框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55995052/

相关文章:

android - 使用主题完全透明的 ActionBarSherlock

c# - 系统资源不足,无法完成请求的服务

c# - 如何知道 System.Window.Forms.Help.ShowHelp 的结果

c# - 从 CSProj 列表生成解决方案文件

c# - WPF MVVM ObservableCollection/DataGrid 多个 Sql 表

c# - 在默认 AppDomain 中托管在 Winforms 中的 WPF 用户控件在弹出窗口中损坏的选项卡导航

.net - 从 UserControl 的子控件传递事件 - 最直接的方法?

Jquery,从点击中获取url并传递给对话框中的确认按钮

delphi - Windows 8 中的对话框向左上方移动

c# - LINQ - 返回非空对象的属性值