簡體   English   中英

單擊NotifyIcon(任務欄圖標)切換C#窗口

[英]C# toggle window by clicking NotifyIcon (taskbar icon)

我的C#應用​​程序包含一個任務欄圖標(NotifyIcon)和一個最初隱藏的開銷窗口。 我希望用戶能夠通過單擊NotifyIcon(左鍵單擊)來切換窗口可見性。 失去焦點時窗口也被隱藏。

這是我到目前為止,一個子類System.Windows.Forms.Form

初始化:

this.ControlBox = false;
this.ShowIcon = false;
this.ShowInTaskbar = false;

// Instance variables: bool allowVisible;
//                     System.Windows.Forms.NotifyIcon notifyIcon;

this.allowVisible = false;
this.notifyIcon = new NotifyIcon();
this.notifyIcon.MouseUp += new MouseEventHandler(NotifyIconClicked);
this.Deactivate += new EventHandler(HideOnEvent);

實例方法:

private void NotifyIconClicked(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        if (this.Visible)
            this.Hide();
        else
            this.Show();
    }
}

new public void Show()
{
    this.allowVisible = true;
    this.Visible = true;
    this.Activate();
}

new public void Hide()
{
    this.allowVisible = false;
    this.Visible = false;
}

private void HideOnEvent(object sender, EventArgs e)
{
    this.Hide();
}

protected override void SetVisibleCore(bool visible)
{
    base.SetVisibleCore(this.allowVisible ? visible : this.allowVisible);
}

單擊該圖標會顯示窗口。 但是,只要按下鼠標,再次單擊它會隱藏它,然后將其重置為可見。

我的猜測是,鼠標按下事件會從窗口中竊取焦點,因此它會消失。 然后觸發鼠標按下事件,顯示隱藏的窗口。

我的下一個想法是在鼠標按下事件時讀取窗口可見性,因此我測試了三個事件並記錄了UNIX時間,因為它們被調用:

notifyIcon.MouseDown
notifyIcon.MouseUp
this.LostFocus

結果很奇怪:假設窗口是可見的。 單擊圖標時會發生這種情況:立即調用焦點丟失。 在鼠標向上事件之前釋放鼠標時立即調用鼠標按下。

1312372231 focus lost
1312372235 mouse down
1312372235 mouse up

為什么鼠標停止事件會延遲?
如何切換窗口?

我認為這可能對你有用。

我找到了一個專家交換帖子,其中包含一個類,該類提供檢查光標當前是否在托盤上方的方法。

NotifyIcon - 檢測MouseOut

使用這個類我修改了你的HideOnEvent方法,如下所示:

    private void HideOnEvent(object sender, EventArgs e)
    {
        if (!WinAPI.GetTrayRectangle().Contains(Cursor.Position))
        {
            this.Hide();
        }
    }

這似乎做你需要的。

我把下面的課程包括在內:

using System.Runtime.InteropServices;
using System.Drawing;

public class WinAPI
{
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public override string ToString()
        {
            return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")";
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);


    public static IntPtr GetTrayHandle()
    {
        IntPtr taskBarHandle = WinAPI.FindWindow("Shell_TrayWnd", null);
        if (!taskBarHandle.Equals(IntPtr.Zero))
        {
            return WinAPI.FindWindowEx(taskBarHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
        }
        return IntPtr.Zero;
    }

    public static Rectangle GetTrayRectangle()
    {
        WinAPI.RECT rect;
        WinAPI.GetWindowRect(WinAPI.GetTrayHandle(), out rect);
        return new Rectangle(new Point(rect.left, rect.top), new Size((rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1));
    }
}

這不是一個完美的解決方案,但我希望這會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM