如何将一个.NET应用程序最小化时放置在系统托盘中?

9

请问有没有一个好的VB.NET/C#代码示例,可以让应用程序在最小化时放入系统托盘中。


2
这似乎是 https://dev59.com/fnVD5IYBdhLWcg3wOo9h 的重复。 - Scott Dorman
3个回答

18

在您的窗体中添加一个NotifyIcon控件,然后使用以下代码:

    private void frm_main_Resize(object sender, EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
           this.ShowInTaskbar = false;
           this.Hide();
           notifyIcon1.Visible = true;
        }
    }

    private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        this.Show();
        this.WindowState = FormWindowState.Normal;
        this.ShowInTaskbar = true;
        notifyIcon1.Visible = false;
    }

您可能不需要设置 ShowInTaskbar 属性。


你的样例非常不完整。 - FlySwat
你的表单缺少声明,缺少 notifyIcon 控件,还缺少重写的 dispose 方法 :) - FlySwat
虽然我注意到你进行了编辑并添加了一些说明,所以请忽略我的评论 :) - FlySwat

2
你可以利用一个名为NotifyIcon的内置控件。当显示时,它会创建一个托盘图标。@Phillip提供了一个相对完整的代码示例。
但是要注意一点:
你必须重写应用程序主窗体的Dispose方法,在其中调用NotifyIcon的Dispose方法,否则它将在应用程序退出后继续停留在托盘中。
public void Form_Dispose(object sender, EventArgs e)
{
   if (this.Disposing)
      notifyIcon1.Dispose();
}

类似这样的东西。


2
如果您在设计师中使用通知图标将其放置在窗体上,则不应该需要这样做——VS生成的Dispose()将调用components.Dispose(),它应该会处理所有作为容器创建的组件。 - Jesse C. Slicer

0

您可以通过向表单添加NotifyIcon并处理表单的resize事件来实现此操作。要从托盘返回,请处理NotifyIcon的双击事件。

如果您想添加一些动画效果,也可以这样做...

1)添加以下模块:

Module AnimatedMinimizeToTray
Structure RECT
    Public left As Integer
    Public top As Integer
    Public right As Integer
    Public bottom As Integer
End Structure

Structure APPBARDATA
    Public cbSize As Integer
    Public hWnd As IntPtr
    Public uCallbackMessage As Integer
    Public uEdge As ABEdge
    Public rc As RECT
    Public lParam As IntPtr
End Structure

Enum ABMsg
    ABM_NEW = 0
    ABM_REMOVE = 1
    ABM_QUERYPOS = 2
    ABM_SETPOS = 3
    ABM_GETSTATE = 4
    ABM_GETTASKBARPOS = 5
    ABM_ACTIVATE = 6
    ABM_GETAUTOHIDEBAR = 7
    ABM_SETAUTOHIDEBAR = 8
    ABM_WINDOWPOSCHANGED = 9
    ABM_SETSTATE = 10
End Enum

Enum ABNotify
    ABN_STATECHANGE = 0
    ABN_POSCHANGED
    ABN_FULLSCREENAPP
    ABN_WINDOWARRANGE
End Enum

Enum ABEdge
    ABE_LEFT = 0
    ABE_TOP
    ABE_RIGHT
    ABE_BOTTOM
End Enum

Public Declare Function SHAppBarMessage Lib "shell32.dll" Alias "SHAppBarMessage" (ByVal dwMessage As Integer, ByRef pData As APPBARDATA) As Integer
Public Const ABM_GETTASKBARPOS As Integer = &H5&
Public Const WM_SYSCOMMAND As Integer = &H112
Public Const SC_MINIMIZE As Integer = &HF020

Public Sub AnimateWindow(ByVal ToTray As Boolean, ByRef frm As Form, ByRef icon As NotifyIcon)
    ' get the screen dimensions
    Dim screenRect As Rectangle = Screen.GetBounds(frm.Location)

    ' figure out where the taskbar is (and consequently the tray)
    Dim destPoint As Point
    Dim BarData As APPBARDATA
    BarData.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(BarData)
    SHAppBarMessage(ABMsg.ABM_GETTASKBARPOS, BarData)
    Select Case BarData.uEdge
        Case ABEdge.ABE_BOTTOM, ABEdge.ABE_RIGHT
            ' Tray is to the Bottom Right
            destPoint = New Point(screenRect.Width, screenRect.Height)

        Case ABEdge.ABE_LEFT
            ' Tray is to the Bottom Left
            destPoint = New Point(0, screenRect.Height)

        Case ABEdge.ABE_TOP
            ' Tray is to the Top Right
            destPoint = New Point(screenRect.Width, 0)

    End Select

    ' setup our loop based on the direction
    Dim a, b, s As Single
    If ToTray Then
        a = 0
        b = 1
        s = 0.05
    Else
        a = 1
        b = 0
        s = -0.05
    End If

    ' "animate" the window
    Dim curPoint As Point, curSize As Size
    Dim startPoint As Point = frm.Location
    Dim dWidth As Integer = destPoint.X - startPoint.X
    Dim dHeight As Integer = destPoint.Y - startPoint.Y
    Dim startWidth As Integer = frm.Width
    Dim startHeight As Integer = frm.Height
    Dim i As Single
    For i = a To b Step s
        curPoint = New Point(startPoint.X + i * dWidth, startPoint.Y + i * dHeight)
        curSize = New Size((1 - i) * startWidth, (1 - i) * startHeight)
        ControlPaint.DrawReversibleFrame(New Rectangle(curPoint, curSize), frm.BackColor, FrameStyle.Thick)
        System.Threading.Thread.Sleep(15)
        ControlPaint.DrawReversibleFrame(New Rectangle(curPoint, curSize), frm.BackColor, FrameStyle.Thick)
    Next


    If ToTray Then
        ' hide the form and show the notifyicon
        frm.Hide()
        icon.Visible = True
    Else
        ' hide the notifyicon and show the form
        icon.Visible = False
        frm.Show()
    End If

End Sub
End Module

2) 在你的窗体上添加一个NotifyIcon,并添加以下内容:

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If m.Msg = WM_SYSCOMMAND AndAlso m.WParam.ToInt32() = SC_MINIMIZE Then
        AnimateWindow(True, Me, NotifyIcon1)
        Exit Sub
    End If
    MyBase.WndProc(m)
End Sub

Private Sub NotifyIcon1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.DoubleClick
    AnimateWindow(False, Me, NotifyIcon1)
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接