Sophisticated Control Over Window Sizing and Moving

Dynamically control the full-drag property, and take full control over sizing and moving.

Resizing Demonstration Project

VB's control over moving and sizing isn't much - basically you have the Resize event, as has been the case since VB1. Windows gives you a lot more control over moving and sizing forms if you need it though. For example, try resizing an undocked tool window in MS Office. You will see that the size snaps so groups of buttons or controls are kept on the same line.

This sample demonstrates how to get access to all the more sophisticated moving and sizing messages, and how to use them to control your window's resize without the flickering and jumping to position you get if you try to change size during VB's Resize event.

Return To Sender

Windows sends the following messages associated with moving and sizing which VB ignores :

  • WM_SIZING = &H214
    This message is fired whilst the window is being resized. The lParam of the message points to a RECT structure containing the desired position of the window. Any modifications you make to this rectangle are passed back to Windows, which moves or sizes the window directly to the size and position you specify.
  • WM_MOVING = &H216
    This message works the same way as WM_SIZING except it is fired whilst the window is being moved.
  • WM_ENTERSIZEMOVE = &H231
    This message is fired when your window is about to start moving or sizing.
  • WM_EXITSIZEMOVE = &H232
    This message is fired when a moving or sizing operation on your window has completed.
  • WM_SIZE = &H5
    This message is fired whenever your window has its size changed by the SetWindowPos function, for example when windows minimizes, maximizes or restores your window, or when you call a VB function which changes the size of the window. Oh, ok then, VB does notice this one.

The sample application shows how you can subclass these messages for a window and respond correctly to them, providing the following new events for a window:

  • Activate
  • Deactivate
  • EnterSizeMove
  • ExitSizeMove
  • Moving
  • Sizing

Controlling FullDrag State

The Full Window drag setting is a nice option in Windows, but for highly animated or dynamic windows it can cause moving and sizing to be slow. Luckily there is a way to control it on a window by window basis. You achieve this by subclassing for the WM_ACTIVATE message to determine when the window you want to change the state for is activate or not. When the window is activated, you can then call the SystemParametersInfo function to turn off full-drag if it is enabled. When the window is deactivated again, you simply reset the state to its original value.

Here is the code for checking and setting the full drag state:

Private Const SPI_GETDRAGFULLWINDOWS = 38
Private Const SPI_SETDRAGFULLWINDOWS = 37
Private Const SPIF_SENDWININICHANGE = &H2
Private Const SPIF_UPDATEINIFILE = &H1
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" _
      (ByVal uAction As Long, ByVal uParam As Long, lpvParam As Any, ByVal fuWinIni As Long) As Long

Private m_bSwitchOff As Boolean

Private Sub pTurnOffFullDrag()
   Dim lR As Long
   ' Get the full-drag state:
   If Not (SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0&, lR, 0) = 0) Then
      If Not lR = 0 Then
         ' Store the fact we are changing:
         m_bSwitchOff = True
         ' Set the full-drag state:
         lR = SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 0&, ByVal 0&, SPIF_SENDWININICHANGE)
      End If
   End If
End Sub

Private Sub pResetFullDrag()
   If m_bSwitchOff Then
      SystemParametersInfo SPI_SETDRAGFULLWINDOWS, 1&, ByVal 0&, SPIF_SENDWININICHANGE
      m_bSwitchOff = False
   End If
End Sub