C#如何确定hwnd是否在托盘图标中

Ron*_*Ron 1 c# system-tray enumerate winforms

我试图得到当前托盘图标的hwnd.我做的是使用以下代码获取系统trat窗口的hWnd:

[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;
}
Run Code Online (Sandbox Code Playgroud)

我从这里拿到了:找到系统托盘中列出的应用程序和服务?

然后我使用以下代码填充了该hWnd的子窗口:

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
    EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
    EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
    if (listHandle.IsAllocated)
    listHandle.Free();
}
return result;
}

private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
    throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
//  You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}

public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
Run Code Online (Sandbox Code Playgroud)

我从这里拿走:enumchildwindows(user32)

然后我像这样使用它:

IntPtr temp = GetSystemTrayHandle();
List<IntPtr> tst = GetChildWindows(temp);
MessageBox.Show(tst.Count.ToString());
foreach (IntPtr ip in tst)
{
    MessageBox.Show(ip.ToString());
}
Run Code Online (Sandbox Code Playgroud)

但是List<IntPtr> tst空的..任何想法为什么?我做错了吗?

Han*_*ant 6

ToolbarWindow32的'children'不是windows.它们是工具栏按钮.您将使用TB_BUTTONCOUNT消息来检索按钮数量,TB_GETBUTTONINFO消息以检索有关此类按钮的信息.由于窗口属于另一个进程,所以很难做到btw,只使用SendMessage()不起作用,因为指针无效.最终徒劳无功,这样的按钮不包含任何与图标相关的过程类型的信息.这是埋藏在外壳内的信息,你无法达到它.

  • TB_BUTTONCOUNT返回可见图标的数量,我如何获得隐藏的托盘图标? (2认同)
  • 这是另一个窗口,名为"System Promoted Notification Area",TrayNotifyWnd的一个孩子.至少在Win7上.使用Spy ++找到这些东西. (2认同)