A way is to handle WM_SIZING
Something like this :
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_SIZING Then
Dim nAspectRatio As Double = Screen.PrimaryScreen.Bounds.Width / Screen.PrimaryScreen.Bounds.Height
Dim windowRect, clientRect As RECT
GetWindowRect(m.HWnd, windowRect)
GetClientRect(m.HWnd, clientRect)
Dim nAddX As Integer = (windowRect.right - windowRect.left) - clientRect.right
Dim nAddY As Integer = (windowRect.bottom - windowRect.top) - clientRect.bottom
Dim rc As RECT = CType(Marshal.PtrToStructure(m.LParam, GetType(RECT)), RECT)
If (rc.bottom - rc.top + nAddY <= 200) Then
rc.bottom = rc.top + 200 - nAddY - 2
End If
Select Case CInt(m.WParam)
Case WMSZ_LEFT, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_RIGHT
rc.bottom = CInt(rc.top + (CSng((rc.right - rc.left - nAddX)) / nAspectRatio) + nAddY)
Case WMSZ_TOPRIGHT, WMSZ_TOP, WMSZ_BOTTOM
rc.right = CInt(rc.left + (CSng((rc.bottom - rc.top - nAddY)) * nAspectRatio) + nAddX)
Case WMSZ_TOPLEFT
rc.left = CInt(rc.right - (CSng((rc.bottom - rc.top)) * nAspectRatio) + nAddX)
End Select
Marshal.StructureToPtr(rc, m.LParam, False)
m.Result = CType(1, IntPtr)
Return
End If
MyBase.WndProc(m)
End Sub
with declarations :
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Dim left As Integer
Dim top As Integer
Dim right As Integer
Dim bottom As Integer
End Structure
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function GetClientRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
Public Const WMSZ_LEFT = 1
Public Const WMSZ_RIGHT = 2
Public Const WMSZ_TOP = 3
Public Const WMSZ_TOPLEFT = 4
Public Const WMSZ_TOPRIGHT = 5
Public Const WMSZ_BOTTOM = 6
Public Const WMSZ_BOTTOMLEFT = 7
Public Const WMSZ_BOTTOMRIGHT = 8
Public Const WM_SIZING = &H214