question

MugsysRapSheet-5056 avatar image
0 Votes"
MugsysRapSheet-5056 asked Castorix31 commented

Detecting resize width vs height

My program lets users resize the form. I maintain the form ratio this way:

 Private Sub frmMain_Resize(sender As Object, e As EventArgs) Handles Me.Resize
     dblRatio = Screen.PrimaryScreen.Bounds.Height / Screen.PrimaryScreen.Bounds.Width
     Me.Height = Me.Width * dblRatio
     ' me.width = me.height * dblRatio
 End Sub

This works just fine if the user grabs the form from the side or the corners, but I can't do the same if resized from the top or bottom (or vice versa if I comment/uncomment me.height/me.width.)

If I knew how to detect what's being dragged, I could precede each with an "If" so only one or the other is executed.

Ideas? TIA

windows-forms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Castorix31 avatar image
0 Votes"
Castorix31 answered Castorix31 commented

A way is to handle WM_SIZING

Something like this :

143611-wm-sizing.gif

 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



wm-sizing.gif (937.4 KiB)
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thx for the detailed reply, but that seems like a lot of code for what I'm already doing (mostly) with just two lines.)

I think your SELECT/CASE is doing what I need (detecting Side vs Top), but the "ByRef m As Message" loses me (as does "DllImport("User32.dll".)) I can't figure out how to adapt it to my code.

There must be an easier way. Thx.

0 Votes 0 ·
Castorix31 avatar image Castorix31 MugsysRapSheet-5056 ·

This is the standard way, adapted from C++ with P/Invoke, to resize a window by keeping a ratio width/height
There is more code because it handles all the cases, the size of the caption and a minimum size

1 Vote 1 ·

Thx, but I'm using a separate "Resize" routine inside the .Resize event that grows/shrinks all objects on the form as it is expanded/shrunk.

When I tried your code, I could not get it to work. VS2019 balked at functions that don't return a value, no idea what "Marshall" refers to, and the two DLL imports that I'm not sure how to implement.

0 Votes 0 ·
Show more comments