更新系统托盘图标编程 [英] Refreshing system tray icons programmatically

查看:228
本文介绍了更新系统托盘图标编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经有一个系统托盘图标的应用程序。虽然卸载我,如果它的运行终止进程。所以,我无法正常停止的应用程序,图标保留在系统托盘中,如果我们将鼠标悬停在它只会删除。我写了会跑沿托盘光标并获取光标回到其初始位置的代码。这是我做了什么:

I've an application which has a system tray icon. While uninstalling I'm killing the process if its running. So, as am not gracefully stopping the app, the icon remains in the system tray and will remove only if we hover the mouse on it. I wrote a code that would run the cursor along the tray and get the cursor back in its initial position. This is what I have done:

        [DllImport("user32.dll")]
        static extern IntPtr FindWindow(string className, string windowName);
        [DllImport("user32.dll")]
        static extern IntPtr FindWindowEx(IntPtr parent, IntPtr child, string className, string windowName);
        [DllImport("user32.dll")]
        static extern bool GetWindowRect(HandleRef handle, out RECT rct);

        [StructLayout(LayoutKind.Sequential)]
        struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        void RefreshTray()
        {
            IntPtr taskbar_Handle = FindWindow("Shell_Traywnd", "");
            IntPtr tray_Handle = FindWindowEx(taskbar_Handle, IntPtr.Zero, "TrayNotifyWnd", "");

            RECT rct;

            if (!(GetWindowRect(new HandleRef(null, tray_Handle), out rct)))
            {
            }

            System.Drawing.Point init = Control.MousePosition;

            for (int i = rct.Left; i < rct.Right-20; i++)
            {
                Cursor.Position = new System.Drawing.Point(i, (rct.Bottom + rct.Top) / 2);
            }

            Cursor.Position = init;
         }

这在所有的情况下工作良好除非选择不显示通知图标已启用。有没有一些方法,我可以刷新在这种情况下托盘?

This works good in all the cases except when the option "do not show notification icons" is enabled. Is there some way I could refresh the tray in this case?

修改
作为意见建议我改变我的做法。而不是杀死托盘应用程序,我建立了我的通信应用服务之间的(是的,忘了提,我有太多的服务与应用程序一起运行),托盘应用。卸载时,我停止服务,从服务站的方法,我要送一个特定的格式到托盘应用程序的套接字消息,并要求它关闭,我会通知图标可见性设置为false。这将离开托盘应用程序在后台运行,所以我用的taskkill来删除该应用程序。它在Win7和Vista工作得很好,但在Win XP中正常工作。但我没有写任何环境特定的代码。任何可能的线索?

EDIT As the comments suggested I changed my approach. Instead of killing the tray application, I established a communication between my application service (yeah, forgot to mention, I have a service too running along with the application) and tray application. While uninstalling, I stop the service, from the service stop method I would send a socket message of a particular format to the tray application and ask it to close and I would set the notify icon visibility to false. This would leave the Tray Application running in background so I am using "taskkill" to remove the application. It worked fine in Win7 and Vista, but is not working properly in Win XP. But I have not written any environment specific code. Any possible clue?

推荐答案

这是类似于我使用。
一个简单的悬浮式键盘我加入触摸画廊界面。用户想也有我的键盘作为他们的桌面上的一个独立的应用程序。所以,我这样做,创造了一个托盘应用它。现在 - 如果它的开放,他们推出我的画廊?

That's similar to what I use. A simple floating Keyboard I added to a touch gallery interface. The user wanted to also have my keyboard as a standalone application on their desktop. So I did this, created a tray app for it. Now - what if its open and they launch my gallery?

他们将有两个键盘

当然 - 用户可以结束第 - ,但其容易只是结束它。有从我杀死它没有任何的反响,所以我做的。但托盘图标仍然存在,作为其等待的事件。为了解决这个问题,我刷新托盘区

Sure - the user could end the first - but its easier to just end it. There are no repercussions from me killing it, so I do. But the tray Icon remains, as its waiting for an event. To get around this, I refresh the Tray area.

请注意 - 这将只对英语语言环境的安装工作。为了得到这个在另一种语言,更改用户晋升通知区域和通知区域到翻译/等效字符串工作。

Please note - This would only work on an English Locale Installation. To get this to work on another language, change "User Promoted Notification Area", and "Notification Area" to the translated / equivalent string.

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
    string lpszWindow);

[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

public static void RefreshTrayArea()
{
    IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
    IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
    IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
    IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
    if (notificationAreaHandle == IntPtr.Zero)
    {
        notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32",
            "User Promoted Notification Area");
        IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null);
        IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero,
            "ToolbarWindow32", "Overflow Notification Area");
        RefreshTrayArea(overflowNotificationAreaHandle);
    }
    RefreshTrayArea(notificationAreaHandle);
}

private static void RefreshTrayArea(IntPtr windowHandle)
{
    const uint wmMousemove = 0x0200;
    RECT rect;
    GetClientRect(windowHandle, out rect);
    for (var x = 0; x < rect.right; x += 5)
        for (var y = 0; y < rect.bottom; y += 5)
            SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x);
}

这篇关于更新系统托盘图标编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆