DeferWindowPos奇怪的行为

sas*_*alm 5 c++ winapi

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

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

它会去那里但是一旦你点击控件内的任何地方就会移动/调整大小到它的旧矩形.如果我改用MoveWindow

m_pActiveX->MoveWindow(left, top, width, height);
Run Code Online (Sandbox Code Playgroud)

这不会发生.

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

adz*_*dzm 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.

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