ColmanJ
ColmanJ

Reputation: 456

Win32 popup window "shaking" on resize

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;
}

Upvotes: 1

Views: 1281

Answers (1)

Joel Spolsky
Joel Spolsky

Reputation: 33697

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.

Upvotes: 2

Related Questions