Scocia888
Scocia888

Reputation: 49

Hiding a system tray from another application in C#

Okay last attempt on this, I am trying to resolve the issue detailed below the URLs. I have looked at the articles detailed in the URLs but I am still unable to hide the relevant icon. Anyone any ideas?

http://www.codeproject.com/Articles/10807/Shell-Tray-Info-Arrange-your-system-tray-icons

http://social.msdn.microsoft.com/Forums/da/vbgeneral/thread/a11faa45-a3ea-4060-8de4-a6bc22e1516d

I want to be able to hide the system tray icon that is loaded by Windows speech recognition (comes as part of Windows 7 and Windows 8 and Windows Vista). I need to do it in C# and have been trying Google solutions for the last couple of days to no avail. It seems the best way forward would be to use this code:

//NotifyIconData structure defined above

private void button1_Click(object sender, EventArgs e)
{
    NOTIFYICONDATA pnid = new NOTIFYICONDATA();
    pnid.uCallbackMessage = 0x800;
    pnid.uFlags = 1;
    pnid.hwnd = ???;
    pnid.uID = 1;
    pnid.szTip = null;
    pnid.uFlags |= 2;
    pnid.hIcon = ???;
    pnid.uFlags |= 4;
    pnid.szTip = "Speech Recognition is listening";

    bool b = Shell_NotifyIcon(2, ref pnid);

The first argument of Shell_NotifyIcon API function (2) is to delete. Problem is I don't know how to find the arguments with question marks including the icon handle. I have tried using ExtractIcon using the executable indicated by the window speech recognition shortcut and by the file location indicated in the task manager file location ( %windir%\Speech\Common\sapisvr.exe -SpeechUX) but it tells me that the executable has no associated icons. I also verified it with a free application that I downloaded to check the icons with that executable and it said the same thing.

I can get the window handle of the icon tray using:

    IntPtr hWnd = Win32API.FindWindow("Shell_TrayWnd", null);
    if(hWnd.ToInt32() > 0)
        {
            hWnd = Win32API.FindWindowEx(hWnd, IntPtr.Zero, "TrayNotifyWnd", null);
            if (hWnd.ToInt32() > 0)
            {
                hWnd = Win32API.FindWindowEx(hWnd,IntPtr.Zero, "SysPager", null);
                if (hWnd.ToInt32() > 0)
               {
                    hWnd = Win32API.FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null);
                }                    
               // count = Win32API.SendMessage(hWnd, 1048 , 0, 0);
            }
        }

however even with the handle and the count of the icons I don't know how to ennumerate the icon handles.

If anyone can give me a working solution in C# I would be happy to pay consultancy, like I say you can easily try it by loading Windows speech recognition which comes free with Windows 7 and Windows 8 and you will see the icon I mean. I could live with a C++ solution but it would have to be completely in managed C++ (.NET)

Upvotes: 2

Views: 2669

Answers (1)

MethodMan
MethodMan

Reputation: 18843

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName);

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

static IntPtr GetSystemTrayHandle()
{           
    IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
    if (hWndTray != IntPtr.Zero)
    {
        hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "TrayNotifyWnd", null);
        if (hWndTray != IntPtr.Zero)
        {
            hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "SysPager", null);
            if (hWndTray != IntPtr.Zero)
            {
                hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "ToolbarWindow32", null);
                return hWndTray;
            }
        }
    }

    return IntPtr.Zero;
}

After you have the window handle, you can choose to iterate through the processes to find the ones that are in the system tray and do whatever work you need with them:

using System.Diagnostics;
Process [] processes = System.Diagnostics.Process.GetProcesses();

foreach (System.Diagnostics.Process process in processes)
{
    if (process.MainWindowHandle == hWndTray)
    {
        // ...
    }
}

Upvotes: 1

Related Questions