views:

1014

answers:

3

I have a form positioned slightly above the taskbar/system tray in the bottom right corner of my desktop window. It's sort of like a pop-up notification. The notification itself looks great, but there's a button on it which resizes the form up, animating the sizing in increments of 5px whilst keeping it's position relative to the bottom-right corner of the screen.

The problem with this is that it doesn't look very smooth. Adjusting Me.Width resizes from the left so you have to then move the form to the left with Me.Left to compensate. Me.SetBounds just seems to be a wrapper for setting those properties anyway.

Is there anything I can do to have the form smoothly (or at least appear to) resize outwards from the left of the form?

A: 

I never tried this, but have you tried setting the DoubleBuffer property of the form to True? This should smooth the drawing.

Jon
I think the choppiness the OP is referring to comes from the fact that you have to set the Width and Left properties one after another and in between the form is moved/resized already. Double-buffering might work fine for things _on_ the form, but not the form itself, because moving and resizing it is first a job for the window manager.
Joey
Yeah, I am quite interested to see if this is possible to actually pull off. Resizing a form so that the width grows by the Left and Right at the same time. This would be pretty cool.
Jon
A: 

You might try reducing the pixel steps it's incrementing down to 1-2 as well, 5px seems like a lot to be adjusting size, I could see how this could appear choppy.

thismat
+3  A: 

ETA: You can actually do this using SetBounds, as SetBounds will delegate to SetBoundsCore which, in turn will invoke SetWindowPos. So SetBounds will internally really set all bounds at once and the window manager will redraw the window only after all properties are set.


Another option would be to import the MoveWindow function and use that instead. It produces a smooth animation here, as it can set size and position simultaneously before telling the window manager to redraw the window.

My test code looked like this (converted from C# via IL to VB with help from Reflector):

Private button1 As Button
Private components As IContainer = Nothing
Private tm As Timer = New Timer

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
    MyBase.Left = (Screen.PrimaryScreen.WorkingArea.Width - MyBase.Width)
    MyBase.Top = (Screen.PrimaryScreen.WorkingArea.Height - MyBase.Height)
    Me.tm.Enabled = False
    Me.tm.Interval = 20
    AddHandler Me.tm.Tick, Function 
        If (MyBase.Width < 500) Then
            Form1.MoveWindow(MyBase.Handle, (MyBase.Left - 5), (MyBase.Top - 5), (MyBase.Width + 5), (MyBase.Height + 5), True)
        Else
            Me.tm.Enabled = False
        End If
    End Function
End Sub

<DllImport("user32.dll", SetLastError:=True)> _
Friend Shared Function MoveWindow(ByVal hWnd As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Boolean) As Boolean
End Function
Joey
Sorry it took me so long to mark this answer, I've only just noticed it since you edited it. The MoveWindow function works perfectly.
Andy E
Note also that you can use `SetBounds`, since it does call `MoveWindow` underneath and therefore should work fine.
Joey