Sharpshell IconHandler не работает с динамически созданными значками
Справочная информация и цель:
Здравствуйте, я разрабатываю приложение, которое создает пользовательские расширения (.myextension) типов файлов. Любой файл может стать файлом.myextension после его взаимодействия с нашим приложением. Наше приложение просто действует как оболочка и оборачивает исходный файл некоторыми метаданными, чтобы преобразовать его в файл.myextension. Поэтому я бы хотел, чтобы значок файла был исходным значком файла (например, логотип Word для файлов Microsoft Word и т. Д.) С нашим логотипом.myextension в углу. Поэтому, если бы вы использовали наше приложение для упаковки документа Microsoft Word, оно превратилось бы в файл.myextension, но значок файла все равно был бы логотипом Microsoft Word только с нашим маленьким логотипом.myextension в углу.
Как я пытаюсь сделать это:
Я использую SharpShell для создания обработчика иконок оболочки для нашего типа файлов.myextension. Затем я пытаюсь динамически генерировать нужные мне значки, используя этот проект WPF FileName To Icon Converter, который я нашел в CodeProject. У меня обе части работают независимо: с SharpShell я могу выбрать пользовательский значок для наших типов файлов.myExtension, и они отображаются правильно. Я протестировал скачок Icon Converter, используя простое приложение WPF для Windows Classic Desktop, которое правильно отображает значок для любого типа файла и преобразует его в тип System.Drawing.Icon, который мне нужен для обработчика иконок SharpShell.
Проблема:
Когда я соединяю эти две части и пытаюсь динамически создавать нужные мне значки в SharpShell Icon Handler, он не работает, и все файлы просто украшены стандартным значком неизвестного типа файлов Windows. Я верю, что где-то в процессе происходит исключение, но я не могу понять, где и почему. Я еще не нашел хороший способ отладки этих расширений SharpShell, поэтому у меня не так много жизнеспособности. Если у кого-то есть идея, почему это может происходить или как отлаживать расширения SharpShell, я был бы очень признателен.
Код:
WPF приложение, которое Spike тестирует файл в Icon Converter:
using QuickZip.Tools;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.IO;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
FileToIconConverter converter = new FileToIconConverter();
//this can be changed to any icon sized value
int size = 40;
//for testing I am trying to load a powerpoint icon
//this can be changed to any file type
//get icon in form of ImageSource using FileToIconConverter
ImageSource originalImageSource = converter.GetImage(@"C:\Users\alech\Desktop\powerpoint.pptx", size);
//Convert file to System.Drawing.Icon type that SharpShell needs
Icon icon = BytesToIcon(ImageSourceToBytes(new PngBitmapEncoder(), originalImageSource));
//Convert back to imageSource to display in WPF window
ImageSource imageSourceFromIcon;
using (Bitmap bmp = icon.ToBitmap())
{
var stream = new MemoryStream();
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
imageSourceFromIcon = BitmapFrame.Create(stream);
}
iconImage.BeginInit();
iconImage.Source = imageSourceFromIcon;
iconImage.Height = size;
iconImage.Width = size;
iconImage.EndInit();
}
private byte[] ImageSourceToBytes(BitmapEncoder encoder, ImageSource imageSource)
{
byte[] bytes = null;
var bitmapSource = imageSource as BitmapSource;
if (bitmapSource != null)
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
bytes = stream.ToArray();
}
}
return bytes;
}
private static Icon BytesToIcon(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
Bitmap bm = new Bitmap(ms);
return System.Drawing.Icon.FromHandle(bm.GetHicon());
}
}
}
}
Обработчик иконок SharpShell, использующий описанный выше метод для динамического создания иконок (это не работает, но я не могу понять, почему):
using QuickZip.Tools;
using SharpShell.Attributes;
using SharpShell.SharpIconHandler;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
namespace SecondIconHandlerTest
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".myextension")]
public class SecondIconHandler : SharpIconHandler
{
protected override Icon GetIcon(bool smallIcon, uint iconSize)
{
//just get the powerpoint icon and use that as an easy test
FileToIconConverter converter = new FileToIconConverter();
ImageSource originalImageSource = converter.GetImage(@"C:\Users\alech\Desktop\powerpoint.pptx", (int)iconSize);
return BytesToIcon(ImageSourceToBytes(new PngBitmapEncoder(), originalImageSource));
}
private byte[] ImageSourceToBytes(BitmapEncoder encoder, ImageSource imageSource)
{
byte[] bytes = null;
var bitmapSource = imageSource as BitmapSource;
if (bitmapSource != null)
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
bytes = stream.ToArray();
}
}
return bytes;
}
private static Icon BytesToIcon(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
Bitmap bm = new Bitmap(ms);
return System.Drawing.Icon.FromHandle(bm.GetHicon());
}
}
}
}