我正在尝试使用DeferWindowPos更新某些对话框的z顺序,但是它不起作用。好吧,z顺序确实会更改,但并不总是按请求的顺序更改。为什么会这样呢?应该可以,对吧?
我正在检查所有返回值。我观察到,如果添加标志SWP_NOSENDCHANGING,则DeferWindowPos返回0,而GetLastError()不返回任何错误代码。我没有在任何对话框类中为WM_WINDOWPOSCHANGING添加消息处理程序。
现在我改用SetWindowPos。总是可以,但速度较慢。
我写了一个测试,请参见下面的代码。任何帮助将不胜感激。
void test()
{
#ifdef DEFER_WINDOW_POS
class DeferPos
{
public:
DeferPos( const int innWindowCount = 1 )
{
m_hdwp = BeginDeferWindowPos( innWindowCount );
assert( m_hdwp != nullptr );
}
~DeferPos()
{
if( !EndDeferWindowPos(m_hdwp) ) { assert( false ); }
}
void Set( HWND hWnd, HWND hWndAfter, int x, int y, int nWidth, int nHeight, UINT uFlags )
{
assert( m_hdwp != nullptr );
assert( GetLastError() == 0 );
m_hdwp = DeferWindowPos( m_hdwp, hWnd, hWndAfter, x, y, nWidth, nHeight, uFlags );
assert( m_hdwp != nullptr );
assert( GetLastError() == 0 );
}
private:
HDWP m_hdwp = nullptr;
};
auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
{
DeferPos dp( static_cast<int>(vec.size()) );
HWND hWndAfter = HWND_TOP;
for( HWND hWnd : vec )
{
dp.Set( hWnd, hWndAfter, 0, 0, 0, 0, flags );
hWndAfter = hWnd;
}
};
#else
auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
{
HWND hWndAfter = HWND_TOP;
for( HWND hWnd : vec )
{
::SetWindowPos(hWnd, hWndAfter, 0, 0, 0, 0, flags );
hWndAfter = hWnd;
}
};
#endif
auto get_dialog_z_order = []()
{
std::vector<HWND> vec;
EnumWindows( [](HWND hWnd, LPARAM lparam)-> BOOL
{
if( dynamic_cast<CDialog*>(CWnd::FromHandle(hWnd)) )
{
reinterpret_cast<std::vector<HWND>*>(lparam)->push_back( hWnd );
}
return TRUE;
}, reinterpret_cast<LPARAM>(&vec) );
return vec;
};
const std::vector<HWND> original_order = get_dialog_z_order();
const std::vector<HWND> reverse_order( original_order.rbegin(), original_order.rend() );
const UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
update_z_order( reverse_order, flags );
const std::vector<HWND> new_order = get_dialog_z_order();
assert( new_order == reverse_order ); // this assert sometimes fails when DEFER_WINDOW_POS is defined
}