Wednesday, December 17, 2008

[vb6] Make ANY form fixed size

Visual Basic forms can be made non-sizable by setting the borderstyle property to 0, 1, 3 or 4. However, that also means that the user cannot minimize the form to the taskbar. Worse, the MDI form cannot be made non-sizable at all. That is, unless you implement the code below. This trick requires that you subclass the form and intercept the WM_GETMINMAXINFO message, not passing the message on to VB. This message is sent to a window when Windows queries for the maximum and minimum sizes of the window and of the tracking rectangle displayed when resizing. The code works by setting the minimum equal to the maximum, effectively making the form fixed in size. In order not to confuse the user, the maximize button in the right side of the title bar should be disabled. Do that by modifying the window style - see other tip "ModifyStyle". In this particular example, the form is fixed at VGA-size and initially centered on the screen, but the size and position is up to you, of course.
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Const WM_GETMINMAXINFO = &H24
Private Const WS_MAXIMIZEBOX& = &H10000

Private Type POINTAPI
x As Long
y As Long
End Type

Private Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type

Dim MinMax As MINMAXINFO

Private Sub Form_Load()
ModifyStyle hwnd, WS_MAXIMIZEBOX, 0 'Disable Maximize box
Dim nLeft As Long, nTop As Long

With MinMax
.ptMaxSize.x = 640
.ptMaxSize.y = 480
.ptMinTrackSize.x = .ptMaxSize.x
.ptMinTrackSize.y = .ptMaxSize.y
.ptMaxTrackSize.x = .ptMaxSize.x
.ptMaxTrackSize.y = .ptMaxSize.y
nLeft = (Screen.Width - .ptMaxSize.x * Screen.TwipsPerPixelX) / 2
nTop = (Screen.Height - .ptMaxSize.y * Screen.TwipsPerPixelY) / 2
'Display with new size and centered on screen
Move nLeft, nTop, .ptMaxSize.x * Screen.TwipsPerPixelX, _
.ptMaxSize.y * Screen.TwipsPerPixelY
End With
End Sub
In the window procedure, add the following code to intercept the message. The code works by copying our private MinMax over the MINMAXINFO pointed to by lParam.
    If msg = WM_GETMINMAXINFO Then
CopyMemory ByVal lParam, MinMax, LenB(MinMax)
End If

No comments:

Post a Comment