【发布时间】: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