locked
Minimize to system tray RRS feed

  • Question

  • Hi,

    Im looking for a solution to minimize my form in the system tray and restore it from the tray.

    I found alot of sites that use the 'DrawAnimatedRects' function that windows use to minimize and maximize window-forms. All this codes were in c++ or vb6.

    Is there anyway to use this function in vb2005?

     

    Here is an Example that i found at http://www.activevb.de/tipps/vb6tipps/tipp0182.html

    Option Explicit

    Private Declare Function SetRect Lib "User32" (lpRect _
            As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal _
            X2 As Long, ByVal Y2 As Long) As Long

    Private Declare Function DrawAnimatedRects Lib "User32" _
            (ByVal hWnd As Long, ByVal idAni As Long, lprcFrom _
            As RECT, lprcTo As RECT) As Long

    Private Type RECT
      Left As Long
      Top As Long
      Right As Long
      Bottom As Long
    End Type

    Const IDANI_OPEN = &H1
    Const IDANI_CLOSE = &H2
    Const IDANI_CAPTION = &H3

    Dim TPP%

    Private Sub Form_Load()
      Dim R1 As RECT, R2 As RECT
       
        TPP = Screen.TwipsPerPixelX
       
        Call SetRect(R1, Screen.Width / TPP, Screen.Height / TPP, _
                     Screen.Width / TPP, Screen.Height / TPP)
        Call SetRect(R2, 0, 0, Me.Width / TPP, Me.Height / TPP)
       
        Call DrawAnimatedRects(Me.hWnd, IDANI_CLOSE Or _
                               IDANI_CAPTION, R1, R2)

        Me.Top = 0
        Me.Left = 0
    End Sub

    Private Sub Form_Unload(Cancel As Integer)
      Dim R1 As RECT, R2 As RECT
     
        Call SetRect(R1, 0, 0, Me.Width / TPP, Me.Height / TPP)
        Call SetRect(R2, Screen.Width / TPP, Screen.Height / TPP, _

    Screen.Width / TPP, Screen.Height / TPP) Call DrawAnimatedRects(Me.hWnd, IDANI_OPEN Or _
                               IDANI_CAPTION, R1, R2)
    End Sub

     

    I hope someone can help me with this.

    Thanks

    Mike

    Thursday, March 23, 2006 2:09 AM

Answers

  • I did some work on the codes i found at the 2 links i mentioned earlier.

    It seems to be working good now in vb2005


    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer

    Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Integer, ByRef lpRect As Rectangle) As Integer

    Private Declare Function DrawAnimatedRects Lib "user32" (ByVal hWnd As Integer, ByVal idAni As Integer, ByRef lprcFrom As Rectangle, ByRef lprcTo As Rectangle) As Integer

    Private Const IDANI_OPEN As Short = &H1S
    Private Const IDANI_CLOSE As Short = &H2S
    Private Const IDANI_CAPTION As Short = &H3S

    Private Function GetTrayHandle() As Integer

    On Error Resume Next
    Dim OurParent As Integer
    Dim OurHandle As Integer
    OurParent = FindWindow(
    "Shell_TrayWnd", "")
    OurHandle = FindWindowEx(OurParent, 0,
    "TrayNotifyWnd", vbNullString)
    Return OurHandle

    End Function

    Public Sub Form_Load()

    On Error Resume Next
    Dim R1 As Rectangle
    Dim R2 As Rectangle

    GetWindowRect(GetTrayHandle(), R1)
    GetWindowRect(
    Me.Handle.ToInt32, R2)

    DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R1, R2)

    End Sub

    Private Sub Form_Unload()

    On Error Resume Next
    Dim R1 As Rectangle
    Dim R2 As Rectangle

    GetWindowRect(GetTrayHandle(), R1)
    GetWindowRect(
    Me.Handle.ToInt32, R2)

    DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R2, R1)

    End Sub


    Users can disable the animation of minimizing and maximizing in windows settings but they cannot disable this animation. So to make it more user friendly you should check the register at: 'HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics' for the value 'MinAnimate'. If its set to '0' then you should disable the animation.


    The following code i use to hide the form when users click the close button on the form. First cancel the exit, then hide the form and then start the animation. The user can only exit when they click a menu/button that directs to 'Application.Exit()'.

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As _ System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

    If e.CloseReason = CloseReason.UserClosing Then

    e.Cancel = True
    Me.Hide()
    Form_Unload()

    End If

    End Sub


    To show the form again add a menu to your NotificationIcon:

    Private Sub ContextMenuOpenen_Click(ByVal sender As System.Object, ByVal e As _  System.EventArgs) Handles ContextMenuOpenen.Click, NotifyIcon1.DoubleClick

    If Me.Visible = False Then

    Form_Load()
    Me.Show()

    End If

    End Sub



     

    Greetz Mike

    Thursday, March 23, 2006 9:00 PM

All replies

  • Yep - the code you've posted looks pretty good.  Have you tried it ?

    http://www.pinvoke.net/search.aspx?search=%20DrawAnimatedRects&namespace=[All]

    That's the site I go to for pinvoke stuff.  It's mostly in C#, of course, but there is a VB section and sometimes it gets filled in.

     

    Thursday, March 23, 2006 3:14 AM
  • I think this code is written in vb6.

    I use vb2005 and have problems to translate some parts of the code. Like 'RECT' i tried to translate to Rectangle but that doesnt seem to be right.

     

    Mike

    Thursday, March 23, 2006 3:34 AM
  • Perhaps - it looks like it could be pinvoke code to me, but I don't 'do' VB, so... If not, try the pinvoke site, and looking up general info on pinvoke, that's how you call old functions like this.

     

    Thursday, March 23, 2006 3:37 AM
  • I just found a code here http://www.vbcity.com/forums/topic.asp?tid=42351

    I have removed some optional functions that i couldnt translate and it worked when i compiled it. I will work on it a bit and post the code here.

    Thanks for your reply

    Greets Mike

    Thursday, March 23, 2006 3:56 AM
  • Hi,

    See if this helps, not sure if this is the usual way of implmenting minimize to tray but it works for me:

        Private Const WM_SIZE As Integer = &H5
        Private Const SIZE_MINIMIZED As Integer = 1

        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)

            Select Case m.Msg
                Case WM_SIZE
                    If m.WParam = SIZE_MINIMIZED Then
                        Me.Hide()
                    End If
            End Select
        End Sub

     

    Thursday, March 23, 2006 4:02 AM
  • Yep that works fine but its not what im looking for.

    Im looking for a code that animates the form to the system tray where the NotifyIcon is.

    The best way to do this is using the 'DrawAnimatedRects' Function i think. Im trying to clean up a code that i found and will post it soon here.

     

    Greets Mike

     

    Thursday, March 23, 2006 4:15 AM
  • Have you tired the code sample found on vbaccelerator.com

    It is just superb and easy as well as elegant also.
    Thursday, March 23, 2006 5:36 AM
  • Yes it looks good but it also doesnt animate from and to system tray.

     

     Mike

    Thursday, March 23, 2006 6:09 PM
  • I did some work on the codes i found at the 2 links i mentioned earlier.

    It seems to be working good now in vb2005


    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer

    Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Integer, ByRef lpRect As Rectangle) As Integer

    Private Declare Function DrawAnimatedRects Lib "user32" (ByVal hWnd As Integer, ByVal idAni As Integer, ByRef lprcFrom As Rectangle, ByRef lprcTo As Rectangle) As Integer

    Private Const IDANI_OPEN As Short = &H1S
    Private Const IDANI_CLOSE As Short = &H2S
    Private Const IDANI_CAPTION As Short = &H3S

    Private Function GetTrayHandle() As Integer

    On Error Resume Next
    Dim OurParent As Integer
    Dim OurHandle As Integer
    OurParent = FindWindow(
    "Shell_TrayWnd", "")
    OurHandle = FindWindowEx(OurParent, 0,
    "TrayNotifyWnd", vbNullString)
    Return OurHandle

    End Function

    Public Sub Form_Load()

    On Error Resume Next
    Dim R1 As Rectangle
    Dim R2 As Rectangle

    GetWindowRect(GetTrayHandle(), R1)
    GetWindowRect(
    Me.Handle.ToInt32, R2)

    DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R1, R2)

    End Sub

    Private Sub Form_Unload()

    On Error Resume Next
    Dim R1 As Rectangle
    Dim R2 As Rectangle

    GetWindowRect(GetTrayHandle(), R1)
    GetWindowRect(
    Me.Handle.ToInt32, R2)

    DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R2, R1)

    End Sub


    Users can disable the animation of minimizing and maximizing in windows settings but they cannot disable this animation. So to make it more user friendly you should check the register at: 'HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics' for the value 'MinAnimate'. If its set to '0' then you should disable the animation.


    The following code i use to hide the form when users click the close button on the form. First cancel the exit, then hide the form and then start the animation. The user can only exit when they click a menu/button that directs to 'Application.Exit()'.

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As _ System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

    If e.CloseReason = CloseReason.UserClosing Then

    e.Cancel = True
    Me.Hide()
    Form_Unload()

    End If

    End Sub


    To show the form again add a menu to your NotificationIcon:

    Private Sub ContextMenuOpenen_Click(ByVal sender As System.Object, ByVal e As _  System.EventArgs) Handles ContextMenuOpenen.Click, NotifyIcon1.DoubleClick

    If Me.Visible = False Then

    Form_Load()
    Me.Show()

    End If

    End Sub



     

    Greetz Mike

    Thursday, March 23, 2006 9:00 PM
  • Mike, this is just soooo great! :)
    Tuesday, September 12, 2006 9:51 PM
  • This is wonderful...
    Tuesday, November 14, 2006 6:25 AM
  •  

         I was wandering how to make my simple application minimize and maximize to and from the system tray also, I was using "Me.Hide()" which takes the forms button off the taskbar and "Me.WindowState = FormWindowState.Normal)" to show the form on top of other windows which works for the most part but doesnt actually show the form droping to the systemtray.

         I would much rather have it show the form dropping to the systemtray while reducing siz like most programs do that utilize the systemtray.

        I was hoping there would be an easy way to do that, maybe    "Me.WindowsState = FormWindowState.ToSystemTray"     or something along those lines.   Anyone know of a simple way to do this?  I am having trouble following some of the code samples in this thread.

    Saturday, December 16, 2006 8:42 AM
  • Hi,

    Its a while ago i worked on this code but in my knowledge there isnt any vb code to animate to the systemtray.

    The most important pinvoke function in this code is "DrawAnimatedRects". Thats the function Windows use to animate forms when you minimize or maximize them. Try to find more information about that function and you will find it easier to understand the code.

    Greetz Mike

    Sunday, December 17, 2006 6:04 AM
  • Something Simple:

    A notify icon "TrayIcon", with a context menu "TrayMenuStrip", a tool strip menu item "TrayToolStripMenuItem":

    Private Sub TrayIcon_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TrayIcon.MouseDown

    Select Case Me.WindowState

    Case FormWindowState.Minimized

    TrayToolStripMenuItem.Text = "Show"

    Case FormWindowState.Normal

    TrayToolStripMenuItem.Text = "Hide"

    Case FormWindowState.Maximized

    TrayToolStripMenuItem.Text = "Hide"

    End Select

    End Sub

    Private Sub TrayIcon_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TrayIcon.MouseDoubleClick

    If Me.WindowState = FormWindowState.Minimized Then

    Me.Show()

    Me.WindowState = FormWindowState.Normal

    Else

    Me.WindowState = FormWindowState.Minimized

    Me.Hide()

    End If

    End Sub

    Private Sub TrayToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrayToolStripMenuItem.Click

    If Me.WindowState = FormWindowState.Minimized Then

    Me.Show()

    Me.WindowState = FormWindowState.Normal

    Else

    Me.WindowState = FormWindowState.Minimized

    Me.Hide()

    End If

    End Sub

    Monday, March 5, 2007 3:56 AM
  • Can you use the Form's ShowInTaskbar property, the NotifyIcon component and the RectAnimation Class?
    Monday, March 5, 2007 9:18 AM
  • RCS300, here is some sample form code. It has 1 button, and when one is pressed it launches another application. This VB Express 2005 code is a usage of Mike's code (above).


    Public Class Form1
        Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

        Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer

        Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Integer, ByRef lpRect As Rectangle) As Integer

        Private Declare Function DrawAnimatedRects Lib "user32" (ByVal hWnd As Integer, ByVal idAni As Integer, ByRef lprcFrom As Rectangle, ByRef lprcTo As Rectangle) As Integer

        Private Const IDANI_OPEN As Short = &H1S
        Private Const IDANI_CLOSE As Short = &H2S
        Private Const IDANI_CAPTION As Short = &H3S
        Private Function GetTrayHandle() As Integer
            On Error Resume Next
            Dim OurParent As Integer
            Dim OurHandle As Integer
            OurParent = FindWindow("Shell_TrayWnd", "")
            OurHandle = FindWindowEx(OurParent, 0, "TrayNotifyWnd", vbNullString)
            Return OurHandle
        End Function
        Public Sub Form_Load()
            On Error Resume Next
            Dim R1 As Rectangle
            Dim R2 As Rectangle
            GetWindowRect(GetTrayHandle(), R1)
            GetWindowRect(Me.Handle.ToInt32, R2)
            DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R1, R2)
        End Sub
        Private Sub Form_Unload()
            On Error Resume Next
            Dim R1 As Rectangle
            Dim R2 As Rectangle
            GetWindowRect(GetTrayHandle(), R1)
            GetWindowRect(Me.Handle.ToInt32, R2)
            DrawAnimatedRects(Me.Handle.ToInt32, IDANI_OPEN Or IDANI_CAPTION, R2, R1)
        End Sub

        Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Me.Hide()
            Form_Unload()
            Shell("""98494\show.exe""", AppWinStyle.NormalFocus, True)
            Form_Load()
            Me.Show()
        End Sub

       
    End Class


    Really, this is the easiest way.
    Tuesday, March 6, 2007 7:07 PM