Article > Fixing a problem with TForm's resizing algorithm
Description :: Ever noticed forms moving when resized? Annoyed?
A few days ago, I set out to add "drawers" (as they're called in the Mac OS X world) to a Windows application. For various reasons, the default behavior of TForm (or TCustomForm) in Builder applications became a problem. When you resize a form (or window) from the left or the top, and reach the minimum or maximum size constraints for the window, suddenly the whole thing starts to move. It goes from resizing to moving, without blinking. I needed the forms to stay in place, and only resize to their limits. Dragging was out of the question.

Guess what? I couldn't find anyone talking about this anywhere on the internet. I was terribly annoyed. So after several failed attempts, some example code from somewhere (reference included below) was re-used, and I decided to overwrite the handling of WM_SIZING for all of my forms (luckily, we derive from a single base class, so that wasn't the hard part.) It seems that even if you're just enforcing the Constraints property of your form, doing it yourself works better than letting TForm or its descendents to it for you.

Don't bother telling me about the redundancy of the following code, I really don't care. The following now appears in my code that catches messages before anything else does. (You can do this with something like WndProc or a MESSAGE_MAP, or in my case, redirecting the window procedure to my own, rather than overriding the one that already exists.)

  // enforce correct sizing that does NOT move the window when resizing from the side
  case WM_SIZING:
  {
   TMessage * msg = (TMessage*)Message;
   RECT* pRect = reinterpret_cast(msg->LParam);
   // minimum width
   if (pRect->right - pRect->left < this->Constraints->MinWidth && this->Constraints->MinWidth)
   {
    switch (msg->WParam)
    {
     case WMSZ_LEFT:
     case WMSZ_TOPLEFT:
     case WMSZ_BOTTOMLEFT:
     {
      pRect->left = pRect->right - this->Constraints->MinWidth;
      break;
     }
     case WMSZ_RIGHT:
     case WMSZ_TOPRIGHT:
     case WMSZ_BOTTOMRIGHT:
     {
      pRect->right = pRect->left + this->Constraints->MinWidth;
      break;
     }
    }
   }
   // minimum height
   if (pRect->bottom - pRect->top < this->Constraints->MinHeight && this->Constraints->MinHeight)
   {
    switch (msg->WParam)
    {
     case WMSZ_TOPLEFT:
     case WMSZ_TOP:
     case WMSZ_TOPRIGHT:
     {
      pRect->top = pRect->bottom - this->Constraints->MinHeight;
      break;
     }
     case WMSZ_BOTTOMLEFT:
     case WMSZ_BOTTOM:
     case WMSZ_BOTTOMRIGHT:
     {
      pRect->bottom = pRect->top + this->Constraints->MinHeight;
      break;
     }
    }
   }
   // maximum width
   if (pRect->right - pRect->left > this->Constraints->MaxWidth && this->Constraints->MaxWidth)
   {
    switch (msg->WParam)
    {
     case WMSZ_LEFT:
     case WMSZ_TOPLEFT:
     case WMSZ_BOTTOMLEFT:
     {
      pRect->left = pRect->right - this->Constraints->MaxWidth;
      break;
     }
     case WMSZ_RIGHT:
     case WMSZ_TOPRIGHT:
     case WMSZ_BOTTOMRIGHT:
     {
      pRect->right = pRect->left + this->Constraints->MaxWidth;
      break;
     }
    }
   }
   // maximum height
   if (pRect->bottom - pRect->top > this->Constraints->MaxHeight && this->Constraints->MaxHeight)
   {
    switch (msg->WParam)
    {
     case WMSZ_TOPLEFT:
     case WMSZ_TOP:
     case WMSZ_TOPRIGHT:
     {
      pRect->top = pRect->bottom - this->Constraints->MaxHeight;
      break;
     }
     case WMSZ_BOTTOMLEFT:
     case WMSZ_BOTTOM:
     case WMSZ_BOTTOMRIGHT:
     {
      pRect->bottom = pRect->top + this->Constraints->MaxHeight;
      break;
     }
    }
   }
   TForm::Dispatch(Message);
   break;
  }