在我的代码中,我希望我的用户能够从计算机上的任何位置选择一个图标。该图标可以是独立的 .ico
,也可以是 .exe
或 .dll
中的图标 - 不仅如此.exe/dll
的默认显示图标,以及其中包含的任何其他图标。
在理想的情况下,我希望能够使用这个 native Windows 图标选择器对话框:
但我不知道如何使用它 - 有可能吗?
此对话框对我来说非常理想,因为它似乎只允许用户浏览到图标或 .exe
和 .dll
作为标准。
如果我的用户只能使用独立的 .ico
文件,那么我将采用在 Microsoft.WindowsAPICodePack- 中找到的
nuget 包和适用于旧系统的 CommonOpenFileDialog
类。适用于 Windows Visa+ 的 ShellSystem.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/