Solved

Min, Max and Close Buttons

Posted on 2004-09-26
3
178 Views
Last Modified: 2010-05-02
Ok, I'm trying to make my particular form have a MinButton that minimizes to the system tray (not the default of taskbar), but not a MaxButton or close button.

I have seen programs (ZoneAlarm) that when the Close (X) button is clicked, it automatically minimizes to the system tray instead of closing, and that would work fine for me as well. So, how do I do it? (Newbie here, and the help file for VB6 is too complicated).
0
Comment
Question by:RunBoris
  • 2
3 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 12155572
Create a New Project and add a PictureBox.  Set the MaxButton property of the form to False as this property can only be changed at design-time at not via code.  Set the Picture property of the PictureBox to the Icon you want to appear in the System Tray.  The app will load to the System Tray.  Double clicking the Tray Icon will bring the app back up.  Clicking on the Minimize or Close Button on the form will minimize the app back to the System Tray.  The COMPILED app can only be closed from the Task Manager.

Regards,

Idle_Mind

Option Explicit

Private Declare Sub Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA)

Private Type NOTIFYICONDATA
    cbSize As Long
    hWnd As Long
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As Long
    szTip As String * 64
End Type

Private Const NIM_ADD = &H0
Private Const NIM_MODIFY = &H1
Private Const NIM_DELETE = &H2
Private Const NIF_MESSAGE = &H1
Private Const NIF_ICON = &H2
Private Const NIF_TIP = &H4
Private Const NIF_DOALL = NIF_MESSAGE Or NIF_ICON Or NIF_TIP
Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_RBUTTONDOWN = &H204

Private tic As NOTIFYICONDATA
Private inTray As Boolean

Private Sub Form_Load()
    Picture1.Visible = False
    Me.WindowState = vbMinimized
End Sub

Private Sub Form_Resize()
    If Me.WindowState = vbMinimized Then
        dropToTray
    End If
End Sub

Private Sub dropToTray()
    tic.cbSize = Len(tic)
    tic.hWnd = Picture1.hWnd ' Callback Control
    tic.uID = 1&
    tic.uFlags = NIF_DOALL
    tic.uCallbackMessage = WM_MOUSEMOVE
    tic.hIcon = Picture1.Picture
    tic.szTip = "My Application" & Chr$(0)
   
    Me.Visible = False
    Shell_NotifyIcon NIM_ADD, tic
    inTray = True
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    X = X / Screen.TwipsPerPixelX
    Select Case X
        Case WM_LBUTTONDBLCLK
            Shell_NotifyIcon NIM_DELETE, tic
            Me.Visible = True
            Me.WindowState = vbNormal
            Me.Show
            inTray = False
    End Select
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Select Case UnloadMode
        Case vbAppTaskManager, vbAppWindows
            If inTray Then
                Shell_NotifyIcon NIM_DELETE, tic
            End If

        Case Else
            Cancel = True
            If Me.Visible = True Then
                dropToTray
            End If
           
    End Select
End Sub
0
 

Author Comment

by:RunBoris
ID: 12158050
Very good, minus 2 small difficulties:

1) When the application is killed, the icon stays, and I think the problem may lie in the following Sub. When Case A is stated, I see a comma separating 2 case points, but I though each point had to be separately defined in VB6. If so, I'm not sure how to fix it to say "If Case A AND B are true, then."

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Select Case UnloadMode
        Case vbAppTaskManager, vbAppWindows
            If inTray Then
                Shell_NotifyIcon NIM_DELETE, tic
            End If

        Case Else
            Cancel = True
            If Me.Visible = True Then
                dropToTray
            End If
           
    End Select
End Sub

2) What if I do want to have a means of killing the program via a cmdButton? How would I go about doing that? And since I'm a pain in the rear, more points up for grabs.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 250 total points
ID: 12158122
If you press the Stop button in the IDE then the tray icon will stay behind.  

I also noticed that sometimes when the form was being restored it would get placed back into the tray at the same time the form reappeared.  This is becuase I toggled the visibility property before setting the windowstate back to normal.  Making the form visible caused a resize event while the windowstate was still minimized causing the dropToTray() sub to be called again.  I switched the order of the statements, changing the windowstate to normal first, and then setting the visiblity to true and the problem went away.

To make the form close with a button, we just issue an Unload Me command and then add another constant, vbFormCode, to the select case statement in the query_unload event.  You can separate values by commas with no problems.

~IM


Option Explicit

Private Declare Sub Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA)

Private Type NOTIFYICONDATA
    cbSize As Long
    hWnd As Long
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As Long
    szTip As String * 64
End Type

Private Const NIM_ADD = &H0
Private Const NIM_MODIFY = &H1
Private Const NIM_DELETE = &H2
Private Const NIF_MESSAGE = &H1
Private Const NIF_ICON = &H2
Private Const NIF_TIP = &H4
Private Const NIF_DOALL = NIF_MESSAGE Or NIF_ICON Or NIF_TIP
Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_RBUTTONDOWN = &H204

Private tic As NOTIFYICONDATA
Private inTray As Boolean

Private Sub Form_Load()
    Picture1.Visible = False
    Me.WindowState = vbMinimized
End Sub

Private Sub Form_Resize()
    If Me.WindowState = vbMinimized Then
        dropToTray
    End If
End Sub

Private Sub dropToTray()
    tic.cbSize = Len(tic)
    tic.hWnd = Picture1.hWnd ' Callback Control
    tic.uID = 1&
    tic.uFlags = NIF_DOALL
    tic.uCallbackMessage = WM_MOUSEMOVE
    tic.hIcon = Picture1.Picture
    tic.szTip = "My Application" & Chr$(0)
   
    Me.Visible = False
    Shell_NotifyIcon NIM_ADD, tic
    inTray = True
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    X = X / Screen.TwipsPerPixelX
    Select Case X
        Case WM_LBUTTONDBLCLK
            Shell_NotifyIcon NIM_DELETE, tic
            Me.WindowState = vbNormal      ' <<------------ Switched the order of these two commands to prevent an
            Me.Visible = True                       ' <<------------ unintentional resize with the windowstate at minimized
            Me.Show
            inTray = False
    End Select
End Sub

Private Sub Command1_Click()  ' <<------------ Added a button to close the form
    Unload Me
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Select Case UnloadMode
        Case vbAppTaskManager, vbAppWindows, vbFormCode  ' <<------------ vbFormCode constant traps "Unload Me"
            If inTray Then
                Shell_NotifyIcon NIM_DELETE, tic
            End If

        Case Else
            Cancel = True
            If Me.Visible = True Then
                dropToTray
            End If
           
    End Select
End Sub
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now