首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MetaFile类型的属性是有缺陷的,如何绕过它?

MetaFile类型的属性是有缺陷的,如何绕过它?
EN

Stack Overflow用户
提问于 2014-05-17 13:46:12
回答 1查看 256关注 0票数 0

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

代码语言:javascript
复制
public Metafile BackImage { get; set; }

然后,我用以下代码在UserControl事件中将此图像绘制为背景:

代码语言:javascript
复制
if (BackImage != null)
    e.Graphics.DrawImage(BackImage, this.ClientRectangle);

我使用.wmf图像,因为在调整UserControl大小时需要向量格式。

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

问题是,当运行程序时,Visual会在包含窗体的设计器文件中抛出"InvalidCastException“错误。这是带有错误的一行:

代码语言:javascript
复制
this.imageControl1.BackImage = ((System.Drawing.Imaging.Metafile)(resources.GetObject("imageControl1.BackImage")));

这是Visual中一个众所周知的bug:http://www.tek-tips.com/viewthread.cfm?qid=425541

由于映像也必须在设计时显示,所以不能只在运行时加载它。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-17 18:01:15

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

因此,解决办法并不是使属性成为元文件,而只是无法工作。我在寻找替代方案时遇到了不少麻烦,显然,byte[]作为属性类型的选择使得代码序列化程序在试图找到类型转换器时挂起。很奇怪,不知道为什么。我选择了一个List<byte>

代码语言:javascript
复制
    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()));
        }
    }

您需要覆盖BackgroundImage属性,这样它就不会被序列化:

代码语言:javascript
复制
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override Image BackgroundImage {
        get { return base.BackgroundImage; }
        set { base.BackgroundImage = value; }
    }

属性的“上下文”菜单中的“重置”命令被禁用,您需要添加以下内容:

代码语言:javascript
复制
    private void ResetBackImage() {
        BackImage = null;
    }

最后,您需要替换默认的属性编辑器,它需要加载一个元文件并将其转换为一个列表:

代码语言:javascript
复制
    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;
        }
    }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23712063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档