Win32弹出窗口“晃动”调整大小时
我正在编写一个带有最顶层窗口的 C++ 程序,因此您没有任何默认的调整大小的方法,或者至少据我所知没有。所以我实现了调整大小,除了 1 个细节外,它工作正常。
当我调整右侧或底部窗口的大小时,它工作得很好,但是当我调整左侧或顶部的大小时,右侧或底部部分(取决于您调整大小的方式)会晃动。我已经部分“修复”了它,所以当你缩小尺寸时它看起来很好,但是当你放大窗户时它仍然会摇晃。
我也已经尝试在调整大小时禁用和启用重绘,但这完全搞砸了,
这是我当前使用的代码
GetCursorPos(&m_MousePos);
int x( m_rWindowStart.left ),
y( m_rWindowStart.top ),
w( m_pWindow->GetWidth() ),
h( m_pWindow->GetHeight() );
//sizing
switch (m_SizingDir)
{
case SIZING_DIR_LEFT:
//x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - m_MousePos.x - m_MousePosOld.x + x;
w /= m_SnapSizing;
w *= m_SnapSizing;
x = m_rWindowStart.right - w;
break;
case SIZING_DIR_TOP:
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_RIGHT:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
break;
case SIZING_DIR_BOTTOM:
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
case SIZING_DIR_LEFTTOP:
x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - x;
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_LEFTBOTTOM:
x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - x;
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
case SIZING_DIR_RIGHTTOP:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_RIGHTBOTTOM:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
}
//window size snaps
w /= m_SnapSizing;
w *= m_SnapSizing;
h /= m_SnapSizing;
h *= m_SnapSizing;
//limit sizing
if (h < 20)
h = 20;
if (w < 20)
w = 20;
//move window ( x, y, w, h, repaint)
m_pWindow->SetPosAndSize(x, y, w, h, true);
以及从 m_pWindow 调用的方法
void Window::SetPosAndSize(int x, int y, int w, int h, bool repaint)
{
ASSERT( w >= 0, _T("w(Width) must be greater than 0") );
ASSERT( h >= 0, _T("h(Height) must be greater than 0") );
m_Width = w;
m_Height = h;
if( m_hWnd )
{
RECT rPos;
GetRect( rPos );
AdjustFromClient(w, h);
MoveWindow(m_hWnd, x, y, w, h, repaint);
}
}
void Window::GetRect( RECT& r ) const
{
::GetWindowRect( m_hWnd, &r );
}
void Window::AdjustFromClient(int& w, int& h) const
{
RECT rSize2be = { 0, 0, w, h };
AdjustWindowRect(&rSize2be, m_Style, false);
w = rSize2be.right-rSize2be.left;
h = rSize2be.bottom-rSize2be.top;
}
I'm writing a C++ program with a topmost window so you don't have any default way of resizing, or at least not to my knowledge. So I've implemented a resize, which is working fine except for 1 detail.
When I resize the window on the right or bottom it works perfectly, but when I'm resizing left or on the top, then the right, or bottom part, depending on which way you're resizing, shakes. I already "fixed" it partially so when you're downsizing it looks fine, but when you're upsizing the window it still shakes.
I also already tried to disable and enable the redraw when resizing but that screws things up completely,
Here's the code I'm currently using
GetCursorPos(&m_MousePos);
int x( m_rWindowStart.left ),
y( m_rWindowStart.top ),
w( m_pWindow->GetWidth() ),
h( m_pWindow->GetHeight() );
//sizing
switch (m_SizingDir)
{
case SIZING_DIR_LEFT:
//x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - m_MousePos.x - m_MousePosOld.x + x;
w /= m_SnapSizing;
w *= m_SnapSizing;
x = m_rWindowStart.right - w;
break;
case SIZING_DIR_TOP:
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_RIGHT:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
break;
case SIZING_DIR_BOTTOM:
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
case SIZING_DIR_LEFTTOP:
x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - x;
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_LEFTBOTTOM:
x += m_MousePos.x - m_MousePosOld.x;
w = m_rWindowStart.right - x;
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
case SIZING_DIR_RIGHTTOP:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
y += m_MousePos.y - m_MousePosOld.y;
h = m_rWindowStart.bottom - y;
break;
case SIZING_DIR_RIGHTBOTTOM:
w = m_rWindowStart.right - m_rWindowStart.left + m_MousePos.x - m_MousePosOld.x;
h = m_rWindowStart.bottom - m_rWindowStart.top + m_MousePos.y - m_MousePosOld.y;
break;
}
//window size snaps
w /= m_SnapSizing;
w *= m_SnapSizing;
h /= m_SnapSizing;
h *= m_SnapSizing;
//limit sizing
if (h < 20)
h = 20;
if (w < 20)
w = 20;
//move window ( x, y, w, h, repaint)
m_pWindow->SetPosAndSize(x, y, w, h, true);
And the methods which are called from the m_pWindow
void Window::SetPosAndSize(int x, int y, int w, int h, bool repaint)
{
ASSERT( w >= 0, _T("w(Width) must be greater than 0") );
ASSERT( h >= 0, _T("h(Height) must be greater than 0") );
m_Width = w;
m_Height = h;
if( m_hWnd )
{
RECT rPos;
GetRect( rPos );
AdjustFromClient(w, h);
MoveWindow(m_hWnd, x, y, w, h, repaint);
}
}
void Window::GetRect( RECT& r ) const
{
::GetWindowRect( m_hWnd, &r );
}
void Window::AdjustFromClient(int& w, int& h) const
{
RECT rSize2be = { 0, 0, w, h };
AdjustWindowRect(&rSize2be, m_Style, false);
w = rSize2be.right-rSize2be.left;
h = rSize2be.bottom-rSize2be.top;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
汉斯是对的……你正在以艰难的方式解决这个问题。
为
WM_NCHITTEST
编写一个消息处理程序(在 MFC 中,重写::OnNcHitTest
),根据您希望窗口“边框”的位置返回 HT_BOTTOM、HT_LEFT 等是,让 Windows 处理整个事情。Hans is right... you're going about this the hard way.
Write a message handler for
WM_NCHITTEST
(in MFC, override::OnNcHitTest
) that returns HT_BOTTOM, HT_LEFT, etc etc depending on where you want the "borders" of your window to be, and let Windows handle the whole thing.