Public Type POINTAPI
X As Long
Y As Long
End Type
Public Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Const WM_GETMINMAXINFO = &H24
Public Const GWL_WNDPROC = -4
Private Windows As Collection
Public Sub Hook(hWnd As Long, minWidth As Integer, minHeight As Integer)
Dim SubClass As SubClassInfo
If Windows Is Nothing Then Set Windows = New Collection
On Error Resume Next
Set SubClass = Windows("sc" & hWnd)
If Err Then
Err.Clear
Set SubClass = New SubClassInfo
With SubClass
.hWnd = hWnd
.minWidth = minWidth
.minHeight = minHeight
.lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End With
Windows.Add SubClass, "sc" & hWnd
End If
End Sub
Public Sub Unhook(hWnd)
Dim temp As Long
Dim SubClass As SubClassInfo
On Error Resume Next
Set SubClass = Windows("sc" & hWnd)
If Err = 0 Then
temp = SetWindowLong(hWnd, GWL_WNDPROC, SubClass.lpPrevWndProc)
Windows.Remove "sc" & hWnd
Else
Err.Clear
End If
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim minWidth As Integer
Dim minHeight As Integer
Dim SubClass As SubClassInfo
On Error Resume Next
Set SubClass = Windows("sc" & hw)
If Err = 0 Then
minWidth = SubClass.minWidth
minHeight = SubClass.minHeight
Select Case uMsg
Case WM_GETMINMAXINFO
Dim mmiT As MINMAXINFO
' Copy the parameter lParam to a local variable so that we can play around with it
CopyMemory mmiT, ByVal lParam, Len(mmiT)
' Minimium width and height. The API works with pixels instead of twips :-(.
mmiT.ptMinTrackSize.X = minWidth
mmiT.ptMinTrackSize.Y = minHeight
' Copy modified results back to parameter
CopyMemory ByVal lParam, mmiT, Len(mmiT)
' In this case we don't want VB to handle resizeing.
' We will exit the function without sending the message to VB, forcing the API to deal with it.
Exit Function
End Select
WindowProc = CallWindowProc(SubClass.lpPrevWndProc, hw, uMsg, wParam, lParam)
Else
Err.Clear
' Don't know what to do here - I'm assuming that it is impossible for this
' situation to occur (a custom WindowProc running for an unsubclassed window).
End If
End Function