DeferWindowPos奇怪的行为

时间:2011-04-11 15:55:29

标签: c++ winapi

所有ActiveX控件都会发生这种情况。如果我使用DeferWindowPos重新定位ActiveX控件

HDWP hdwp = BeginDeferWindowPos(1);
DeferWindowPos(hdwp, m_pActiveX->GetSafeHwnd(), NULL, left, top, width, height, SWP_NOZORDER);
EndDeferWindowPos(hdwp);

它去那里但是当你点击控件里面的任何地方后移动/调整大小到它的旧矩形。如果我改用MoveWindow

m_pActiveX->MoveWindow(left, top, width, height);

这不会发生。

任何其他类型的控件都不会发生这种情况,只能使用ActiveX控件,但它会发生在所有控件上。我做了一个测试,以确认这一点,创建一个新的ActiveX控件项目,并没有做任何更改,问题仍然存在。

2 个答案:

答案 0 :(得分:6)

你从来没有得到合适的答案。我试着在这里帮忙。

问题是MFC隐藏了很多在其框架内托管ActiveX控件的技巧。具体来说,如果您进入MoveWindow调用,它不仅仅是Win32 MoveWindow函数的包装器。它调用OLE控件容器支持类。这基本上说,如果我们有一个控制站点接口,那么调用COleControlSite :: MoveWindow,否则调用标准的Win32 MoveWindow。 CWnd等处理的其他几个窗口函数也是如此。例如,COleControlSite :: SetWindowPos处理隐藏/显示控件,然后调用COleControlSite :: MoveWindow移动它,然后最后调用:: SetWindowPos(带有move / show标志)掩盖了其余部分。

在COleControlSite :: MoveWindow中,你会发现它做了几件事:它调用SetExtent,更新它的内部m_rect成员,然后调用SetObjectRects。

直接使用Win32 API绕过这些ActiveX控件(例如通过DeferWindowPos)会导致错过一些关键步骤。根据您的代码的布局方式,通常您可以自己处理。

答案 1 :(得分:1)

什么是 ActiveX控件?

除此之外,考虑DeferWindowPos用于同时定位多个窗口。这个概念是你输入begin语句,为新布局改变一堆窗口位置,然后结束实际移动并应用新的位置和大小。

如果您不更新多个窗口,请考虑使用SetWindowPos

另请注意,在推迟时,您可能会收到移动,调整大小或更改窗口位置的消息。为了防止这种情况,如果发生这种情况,请在每次调用SWP_NOSENDCHANGING时通过DeferWindowPos标志,以便不发送或处理消息并清除收到的WINDOWPOS结构中的所有位以防止不必要的变化。

此调用也可能失败......您是否正在检查返回值?