【问题标题】:Removing (or updating) an image from RichTextBox从 RichTextBox 中删除(或更新)图像
【发布时间】:2009-07-17 11:05:07
【问题描述】:

我有一个关于在 RichTextBox 中管理 OLE 对象的问题。

到目前为止,我发现了很多信息,但并不完全是我所需要的,所以我先做一个简单的介绍(我也希望有人会觉得这很有帮助)。

1.到目前为止我所知道的

首先,我使用 OLE 将图像(或任何 ActiveX)插入到 RichTextBox 中。这应该是执行此操作的“正确方法”,因为不涉及剪贴板,并且您可以插入所需的任何 ActiveX 控件。 CodeProject (MyExtRichTextBox) 上有一篇文章解释了如何做到这一点(带有完整的源代码),但要简短:

使用 P/Invoke,从 ole32.dll 导入 OleCreateFromFile 函数,以从图像文件创建 OLE 对象。

int hresult = OleCreateFromFile(...);

函数返回一个IOleObject 实例,然后必须由REOBJECT 结构引用:

REOBJECT reoObject = new REOBJECT();

reoObject.cp = 0; // charated index for insertion
reoObject.clsid = guid; // iOleObject class guid
reoObject.poleobj = Marshal.GetIUnknownForObject(pOleObject); // actual object

// etc. (set other fields

// Then we set the flags. We can, for example, make the image resizable 
// by adding a flag. I found this question to be asked frequently
// (how to enable or disable image drag handles).
reoObject.dwFlags = (uint)
     (REOOBJECTFLAGS.REO_BELOWBASELINE | REOOBJECTFLAGS.REO_RESIZABLE);

// and I use the `dwUser` property to set the object's unique id 
// (it's a 32-bit word, and it will be sufficient to identify it)
reoObject.dwUser = id;

最后使用IRichEditOle.InsertObject 将结构传递给RichTextBox。 IRichEditOle 是一个 COM 接口,也是使用 P/Invoke 导入的。

对象的“id”使我能够遍历插入对象的列表,并“做一些事情”。使用IRichEditOle.GetObject,我可以获取每个插入的对象并检查dwUser 字段以查看id 是否匹配。

2。问题

现在问题来了:

a) 第一个问题是更新插入的图像。我希望能够按需“刷新”某些图像(或更改它们)。我现在的做法是这样的:

if (reoObject.dwUser == id)
{
    // get the char index for the "old" image
    oldImageIndex = reoObject.cp;

    // insert the new image (I added this overload for testing,
    // it does the thing described above)
    InsertImageFromFile(oldImageIndex, id, filename);

    // and now I select the old image (which has now moved by one "character"
    // position to the right), and delete it by setting the selection to ""
    _richEdit.SelectionStart = oldImageIndex + 1;
    _richEdit.SelectionLength = 1;
    _richEdit.SelectedText = "";
}

由于我是从 Gui 线程更新,我相信我不应该担心用户在此方法期间更改选择,因为 OLE 插入会阻塞线程,并且应用程序正在 STA 中运行。

但我不知何故觉得可能有更好/更安全的方法来做到这一点?这个方法看起来我应该用[DirtyHack] 属性标记它。

b) 另一个问题是,在插入 (IRichEditOle.InsertObject) 的那一刻,我得到一个未处理的异常(Paint Shop Pro 已停止工作)。尽管打开或编辑 shell 命令不存在文件关联,但插入 OLE 对象似乎会以某种方式启动此应用程序。

有谁知道这可能是什么原因以及如何预防?

[编辑]

我刚刚有了一个不同的想法——我可以创建我的自定义 ActiveX 控件来负责更新图像。在这种情况下,我只需要使 RichTextBox 的那部分无效(类似于 CodeProject 文章的作者所做的)。但这会使部署变得更加复杂(我需要向 COM 公开一个 .Net 类,然后在嵌入之前对其进行注册)。

【问题讨论】:

    标签: .net com pinvoke richtextbox ole


    【解决方案1】:

    我对 .NET/OLE/ActiveX 等了解不多,但在编写 GUI 时,应避免从线程修改/刷新窗口。

    我在 C++ 方面也有类似的经历。与其使用线程来修改窗口,不如使用计时器之类的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-28
      • 2013-08-12
      • 2016-07-13
      • 1970-01-01
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      • 2019-10-30
      相关资源
      最近更新 更多