C# MetaFile类型的属性有缺陷,如何避免?

C# MetaFile类型的属性有缺陷,如何避免?,c#,winforms,visual-studio,properties,user-controls,C#,Winforms,Visual Studio,Properties,User Controls,我有一个名为BackImage的属性的UserControl: public Metafile BackImage { get; set; } 然后,我使用以下代码在Paint事件中的UserControl上绘制此图像作为背景: if (BackImage != null) e.Graphics.DrawImage(BackImage, this.ClientRectangle); 我使用.wmf图像,因为在调整UserControl的大小时需要矢量格式 在设计时将UserContr

我有一个名为BackImage的属性的UserControl:

public Metafile BackImage { get; set; }
然后,我使用以下代码在Paint事件中的UserControl上绘制此图像作为背景:

if (BackImage != null)
    e.Graphics.DrawImage(BackImage, this.ClientRectangle);
我使用.wmf图像,因为在调整UserControl的大小时需要矢量格式

在设计时将UserControl拖动到窗体并通过Visual Studio中的“属性”窗口设置此属性时,重新绘制时会正确显示图像

问题是,当运行程序时,Visual Studio在包含表单的设计器文件中抛出“InvalidCastException”错误。这是出现错误的行:

this.imageControl1.BackImage = ((System.Drawing.Imaging.Metafile)(resources.GetObject("imageControl1.BackImage")));
这是Visual Studio中一个众所周知的错误:

由于图像也必须在设计时显示,因此无法在运行时加载图像

问题:
是否可以使用一种原始格式,而不是元文件类型的属性,然后在代码中使用它时仅转换或类型转换它?

此问题是由于GDI+中不支持编码Emf/Wmf元文件造成的。它只能读它们。选择图元文件时获得的内置图像编辑器将其转换为PNG图像以绕过限制。您将看到它显示在设计器中,但它实际上不是图元文件。此PNG图像也是存储在.resx文件中的图像。Kaboom当您运行程序时,该PNG无法转换为图元文件

因此,解决方法不是将属性设置为图元文件,这就是无法工作的。我在寻找替代方法时遇到了相当大的困难,选择byte[]作为属性类型使代码序列化程序在尝试查找类型转换器时挂起。很奇怪,不知道为什么。我选择了
列表

    private List<byte> BackImageBytes;

    [Editor(typeof(MyMetafileEditor), typeof(UITypeEditor))]
    public List<byte> BackImage {
        get { return BackImageBytes; }
        set {
            BackImageBytes = value;
            if (value == null) base.BackgroundImage = null;
            else base.BackgroundImage = new Metafile(new System.IO.MemoryStream(value.ToArray()));
        }
    }
属性关联菜单中的“重置”命令已禁用,您需要添加以下命令:返回:

    private void ResetBackImage() {
        BackImage = null;
    }
最后,您需要替换默认属性编辑器,它需要加载图元文件并将其转换为列表:

    class MyMetafileEditor : UITypeEditor {
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
            using (var dlg = new OpenFileDialog()) {
                dlg.Filter = "Metafiles (*.wmf, *.emf)|*.wmf;*.emf";
                if (dlg.ShowDialog() == DialogResult.OK) {
                    value = new List<byte>(System.IO.File.ReadAllBytes(dlg.FileName));
                }
            }
            return value;                     
        }
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
            return UITypeEditorEditStyle.Modal;
        }
    }
类MyMetafileEditor:UITypeEditor{
公共重写对象EditValue(ITypeDescriptorContext上下文、IServiceProvider提供程序、对象值){
使用(var dlg=new OpenFileDialog()){
dlg.Filter=“图元文件(*.wmf,*.emf)|*.wmf;*.emf”;
if(dlg.ShowDialog()==DialogResult.OK){
value=新列表(System.IO.File.ReadAllBytes(dlg.FileName));
}
}
返回值;
}
公共重写UITypeEditorEditStyle GetEditStyle(ITTypeDescriptorContext上下文){
返回UITypeEditorEditStyle.Modal;
}
}

此问题是由于GDI+中缺少对Emf/Wmf元文件编码的支持造成的。它只能读它们。选择图元文件时获得的内置图像编辑器将其转换为PNG图像以绕过限制。您将看到它显示在设计器中,但它实际上不是图元文件。此PNG图像也是存储在.resx文件中的图像。Kaboom当您运行程序时,该PNG无法转换为图元文件

因此,解决方法不是将属性设置为图元文件,这就是无法工作的。我在寻找替代方法时遇到了相当大的困难,选择byte[]作为属性类型使代码序列化程序在尝试查找类型转换器时挂起。很奇怪,不知道为什么。我选择了
列表

    private List<byte> BackImageBytes;

    [Editor(typeof(MyMetafileEditor), typeof(UITypeEditor))]
    public List<byte> BackImage {
        get { return BackImageBytes; }
        set {
            BackImageBytes = value;
            if (value == null) base.BackgroundImage = null;
            else base.BackgroundImage = new Metafile(new System.IO.MemoryStream(value.ToArray()));
        }
    }
属性关联菜单中的“重置”命令已禁用,您需要添加以下命令:返回:

    private void ResetBackImage() {
        BackImage = null;
    }
最后,您需要替换默认属性编辑器,它需要加载图元文件并将其转换为列表:

    class MyMetafileEditor : UITypeEditor {
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
            using (var dlg = new OpenFileDialog()) {
                dlg.Filter = "Metafiles (*.wmf, *.emf)|*.wmf;*.emf";
                if (dlg.ShowDialog() == DialogResult.OK) {
                    value = new List<byte>(System.IO.File.ReadAllBytes(dlg.FileName));
                }
            }
            return value;                     
        }
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
            return UITypeEditorEditStyle.Modal;
        }
    }
类MyMetafileEditor:UITypeEditor{
公共重写对象EditValue(ITypeDescriptorContext上下文、IServiceProvider提供程序、对象值){
使用(var dlg=new OpenFileDialog()){
dlg.Filter=“图元文件(*.wmf,*.emf)|*.wmf;*.emf”;
if(dlg.ShowDialog()==DialogResult.OK){
value=新列表(System.IO.File.ReadAllBytes(dlg.FileName));
}
}
返回值;
}
公共重写UITypeEditorEditStyle GetEditStyle(ITTypeDescriptorContext上下文){
返回UITypeEditorEditStyle.Modal;
}
}

包含“Bug”的论坛链接给出了404。该线程表示castign to
System.Drawing.Image
有效,也许在参考资料中将它存储为byte[]而不是image,并显式加载它而不是强制转换是更安全的解决方案。我看到过System.Drawing.image的VB线程,问题是它被转换为位图,因此我失去了向量格式。我将如何将其作为字节[]存储在参考资料中?如果我只是以常规方式将其添加到资源中,我假设它是以文件的形式存储的?您可以假设,但事实并非如此。正如Hans所回答的,EMF在序列化后被转换为PNG。有趣的是吗?包含“Bug”的论坛链接给出了一个404。这个帖子说castign to
System.Drawing.Image
有效,也许在参考资料中将它存储为byte[]而不是image,并显式加载它而不是强制转换是更安全的解决方案。我看到过System.Drawing.image的VB线程,问题是它被转换为位图,因此我失去了向量格式。我将如何将其作为字节[]存储在参考资料中?如果我只是以常规方式将其添加到资源中,我假设它是以文件的形式存储的?您可以假设,但事实并非如此。正如Hans所回答的,EMF在序列化后被转换为PNG。好笑啊?你在这方面付出了多大的努力,非常感谢!现在是在欧洲下注的时候了,但我会看看,然后尽快回来!我对你的帮助感激不尽!我和它一起工作