Link to home
Start Free TrialLog in
Avatar of deal051298
deal051298

asked on

Delay form resize until mouse release?

I'm resizing all my controls as the user resizes one of my forms. I'd like to get rid of the ugly flashing that takes place as the user resizes. Is there any way to prevent the resize until the user releases the mouse button? I want to have a ghost outline of the new form size appear as the user resizes and then update the display once the resizing's done.
Having the form resize without the controls is not enough (ie. all or nothing). I imagine some Win32 API is needed. Cheers & thanks.
Avatar of Mirkwood
Mirkwood

I think that this is a general option in your control panel (or in option in tweekUI), but not per window.
ASKER CERTIFIED SOLUTION
Avatar of anzen
anzen

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
What method are you using to do this? If you're not already doing so, resize the form controls under Form_Resize(). Processing shouldn't occur until the mouse button is released.
Avatar of deal051298

ASKER

Anzen, I've only done windows API calls through Visual Basic so I'm not totally sure what you mean by "subclassing the form" and my "message processing routine". I'll be researching your answer in the win32 documentation but a little help would go a long way.

jgv, the resize code is executed continually as the form is resized, not just on mouse release.

Mirkwood, do you ever sleep man!
To subclass a form You must use the Get/Set..WindowLong API calls together with a user supplied function to process the incoming windows messages, the code is something like this:

' Messages - declare as needed
Private Const WM_ENTERSIZEMOVE = 561&
Private Const WM_SIZING = 532&
Private Const WM_SIZE = 5&
Private Conts WM_EXITSIZEMOVE = 562&

' Subclassing APIs
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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


' Enables/Disables window subclassing, note that
' You must store in a safe place the value returned
' by this function since it's needed to disable the
' subclassing for the window and You MUST disable the
' subclassing whenever You unload the window or all You
' got is a system crash !!
Public Function SubClass(ByVal hWnd As Long, ByVal bOnOff As Boolean) As Long
      Dim lpWindowProc As Long

    On Local Error Resume Next
    If bOnOff = True Then
            ' Enables subclassing
        lpWindowProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
    ElseIf lpWindowProc <> 0 Then
        ' disables subclassing
        lpWindowProc = SetWindowLong(hWnd, GWL_WNDPROC, lpWindowProc)
        lpWindowProc = 0
    End If
    SubClass = lpWindowProc
End Function

' User WindowProc, all messages sent from Windows
' to the subclassed hWnd now come here and can be
' manipulated as needed
Public Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim lRet As Long
   
    ' There MUST be this !!
    On Local Error Resume Next
   
    ' calls default windowproc - just to be safe
      ' You could also decide NOT to call the default
      ' WinProc and to have this function "eat" the message
    lRet = CallWindowProc(lpWindowProc, hWnd, Msg, wParam, lParam)

      ' Now let's do some msg handling
      Select Case Msg
            Case WM_ENTERSIZEMOVE      ' begin size/move
                  ' prepare...
            Case WM_SIZING                  ' sizing (mouse down/moving)
                  ' noop
            Case WM_SIZE                  ' size paused (mouse still down)
                  ' can give some feedback
                  ' e.g. move controls....
            Case WM_EXITSIZEMOVE      ' end size/move (mouse up)
                  ' now do the full resizing !
            Case Else
                  ' nothing here
      End Select
   
    ' returns result to windows
    WindowProc = lRet
End Function

' Helper fn: Extracts HiWord from a Long
Public Function HiWord(dwValue As Long) As Integer
    On Local Error Resume Next
    If dwValue And &H80000000 Then
        HiWord = (dwValue \ 65535) - 1
    Else
        HiWord = dwValue \ 65535
    End If
End Function

' Helper fn: Extracts LoWord from a Long
Public Function LoWord(dwValue As Long) As Integer
    On Local Error Resume Next
    If dwValue And &H8000& Then
        LoWord = &H8000 Or (dwValue And &H7FFF&)
    Else
        LoWord = dwValue And &HFFFF&
    End If
End Function

keep in mind that You MUST store the value returned from the SubClass() function and use it to disable subclassing for Your window whenever You unload it or terminate Your app, failure to do this will result in a system crash !!

Hope it's clear ... Bye


I leave out one thing: before You activate Your code to do the resizing/moving job call the LockWindowUpdate API to avoid flickering, then when You're done call it again to restore painting for the target form, that is:

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

' Disable repainting
lRet = LockWindowUpdate(frmForm.hWnd)

' ... do Your job...

' Re-Enable painting
lRet = LockWindowUpdate( 0&)

Bye



anzen:

I don't know if you're still around, but when I try your code I end up with WindowProc being called in an infinite loop. Any ideas?