2009-07-17 73 views
1

我有一个问题涉及到在RichTextBox中管理OLE对象。删除(或更新)RichTextBox中的图像

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

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”使我能够遍历插入的对象列表和“do stuff”。使用IRichEditOle.GetObject我可以获取每个插入的对象并检查dwUser字段以查看id是否匹配。

2.问题

现在想来问题:

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

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

我对.NET/OLE/ActiveX等知之甚少,但在编程GUI时,应该避免从线程修改/刷新窗口。

我有类似的C++经验。而不是使用线程来修改你的窗口,你应该使用类似计时器的东西。

+1

正如我所说,我正在从* Gui *线程更新。 – Groo 2009-07-17 11:27:54