[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Min, Max and Close Buttons

Posted on 2004-09-26
3
Medium Priority
?
188 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 86

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 86

Accepted Solution

by:
Mike Tomlinson earned 1000 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

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

829 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