我有一个与管理 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 类,然后在嵌入之前对其进行注册)。