3

現在のトレイ アイコンの 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;
}

私はここから取った:システムトレイにリストされているアプリケーションとサービスを見つける?

次に、次のコードを使用して、その 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);

ここから取ったもの: enumchildwindows (user32)

次に、次のように使用しました。

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

しかし、List<IntPtr> tst空です..理由は何ですか?私はこれを間違っていますか?

4

3 に答える 3

7

ToolbarWindow32 の「子」はウィンドウではありません。これらはツールバー ボタンです。TB_BUTTONCOUNT メッセージを使用してボタンの数を取得し、TB_GETBUTTONINFO メッセージを使用してそのようなボタンに関する情報を取得します。ウィンドウが別のプロセスに属しているため、実行するのは非常に困難です。ポインタが有効でないため、 SendMessage() を使用するだけでは機能しません。そして最終的には無駄です。そのようなボタンには、アイコンに関連付けられているプロセスの種類に関する情報が含まれていません。それはシェルの中に埋もれている情報であり、アクセスすることはできません。

于 2011-03-02T22:40:41.773 に答える
1

子ハンドルはありません。これは Spy++ で確認できます。

サブコントロールをホストするのではなく、ツールチップなどを直接レンダリングして処理します。

ここに画像の説明を入力

于 2011-03-02T22:40:16.317 に答える
0

ウィンドウがデスクトップで開かれている場合、スタイルがあることを確認しました:

WS_VISIBLE=true
WS_MINIMIZE=false

ウィンドウがタスクバーにある場合:

WS_VISIBLE=true
WS_MINIMIZE=true

ウィンドウがシステム トレイにある場合:

WS_VISIBLE=false
WS_MINIMIZE=true

したがって、スタイルを操作して、ウィンドウがトレイにあるかどうかを判断できます。

public IsWindowFromTray(hWnd)
{    
    bool isMinimized = Win32Natives.IsIconic(hWnd);
    bool isVisible = Win32Natives.IsWindowVisible(hWnd);

    return isMinimized && !isVisible;
}

ほとんどのアプリで機能します。

PS: pinvoke を使用しました

[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr hWnd);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
于 2014-09-04T07:02:28.323 に答える