1

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

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

1.我目前所知道的

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

使用 P/Invoke,OleCreateFromFile从 ole32.dll 导入该函数以从图像文件创建 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;

最后将结构传递给 RichTextBox,使用IRichEditOle.InsertObject. 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 类,然后在嵌入之前对其进行注册)。

4

1 回答 1

0

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

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

于 2009-07-17T11:19:29.293 回答