我有一个与在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已经停止工作)。似乎插入OLE对象以某种方式启动此应用程序,尽管Open或Edit shell命令不存在文件关联。
有人知道可能导致这种情况的原因以及如何预防吗?
[编辑]
我有一个不同的想法 - 我可以创建我的自定义ActiveX控件,它将负责更新图像。在这种情况下,我只需要使RichTextBox的那部分无效(类似于CodeProject文章的作者所做的那样)。但这会使部署更加复杂(我需要将.Net类暴露给COM,然后在嵌入之前注册它)。
答案 0 :(得分:0)
我对.NET / OLE / ActiveX等知之甚少,但在编程GUI时,应避免从线程修改/刷新窗口。
我有类似的C ++经验。而不是使用线程来修改窗口,你应该使用类似计时器的东西。