如何使用C#自动右键单击系统托盘中的图标

时间:2011-08-23 14:56:15

标签: c# contextmenu

我想为.NET应用程序编写自动化框架。要启动应用程序,用户应右键单击系统托盘中的图标,然后从上下文菜单中选择选项。我做了一些resaerch,只找到了如何知道托盘中图标的工具提示。:

    [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);

    [DllImport("user32.dll", SetLastError = true)]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);


    [DllImport("kernel32.dll")]
    static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

    [Flags]
    enum ProcessAccessFlags : uint
    {
        All = 0x001F0FFF,
        Terminate = 0x00000001,
        CreateThread = 0x00000002,
        VMOperation = 0x00000008,
        VMRead = 0x00000010,
        VMWrite = 0x00000020,
        DupHandle = 0x00000040,
        SetInformation = 0x00000200,
        QueryInformation = 0x00000400,
        Synchronize = 0x00100000
    }


    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FreeType dwFreeType);

    [Flags]
    public enum FreeType
    {
        Decommit = 0x4000,
        Release = 0x8000,
    }

    const uint TB_GETBUTTON = 1047;
    const uint TB_GETBUTTONTEXTW = 1099;
    const uint TB_BUTTONCOUNT = 1048;
    const uint TB_PRESSBUTTON = 1027;
    const uint TB_HIDEBUTTON = 1028;
    const uint VM_COMMAND = 273;
    const uint WM_RBUTTONDOWN = 0x204;
    const uint WM_RBUTTONUP = 0x205;
    const uint MK_RBUTTON = 2;
    const uint WM_COMMAND = 0x0111;
    const uint BM_CLICK = 245;
    const uint TB_HIGHLIGHTBUTTON = 0x0407;


    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
       uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);

    [DllImport("user32.dll", EntryPoint = "PostMessage")]
    public static extern int PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);


    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint dwSize, out IntPtr lpNumberOfBytesRead);

    [Flags]
    public enum AllocationType
    {
        Commit = 0x1000,
        Reserve = 0x2000,
        Decommit = 0x4000,
        Release = 0x8000,
        Reset = 0x80000,
        Physical = 0x400000,
        TopDown = 0x100000,
        WriteWatch = 0x200000,
        LargePages = 0x20000000
    }

    [Flags]
    public enum MemoryProtection
    {
        Execute = 0x10,
        ExecuteRead = 0x20,
        ExecuteReadWrite = 0x40,
        ExecuteWriteCopy = 0x80,
        NoAccess = 0x01,
        ReadOnly = 0x02,
        ReadWrite = 0x04,
        WriteCopy = 0x08,
        GuardModifierflag = 0x100,
        NoCacheModifierflag = 0x200,
        WriteCombineModifierflag = 0x400
    }


    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);

    [StructLayout(LayoutKind.Sequential)]
    internal struct TBBUTTON
    {
        public Int32 iBitmap;
        public Int32 idCommand;
        public byte fsState;
        public byte fsStyle;
        public byte bReserved1;
        public byte bReserved2;
        public UInt32 dwData;
        public IntPtr iString;
    }

    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);


    //getting systemtray icon
    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;
    }

    public static List<string> texts = new List<string>();

    private static unsafe bool GetTBButton(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
    {
        // One page
        const int BUFFER_SIZE = 0x1000;

        byte[] localBuffer = new byte[BUFFER_SIZE];

        UInt32 processId = 0;
        UInt32 threadId = GetWindowThreadProcessId(hToolbar, out processId);

        IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, (int)processId);
        if (hProcess == IntPtr.Zero) { Debug.Assert(false); return false; }

        IntPtr ipRemoteBuffer = VirtualAllocEx(
            hProcess,
            IntPtr.Zero,
            (uint)new UIntPtr(BUFFER_SIZE),
            AllocationType.Commit,
            MemoryProtection.ReadWrite);

        if (ipRemoteBuffer == IntPtr.Zero) { Debug.Assert(false); return false; }

        // TBButton
        fixed (TBBUTTON* pTBButton = &tbButton)
        {
            IntPtr ipTBButton = new IntPtr(pTBButton);

            int b = (int)SendMessage(hToolbar, TB_GETBUTTON, (IntPtr)i, ipRemoteBuffer);
           // SendMessage(hToolbar, VM_COMMAND, (IntPtr)tbButton.idCommand, ipRemoteBuffer);


            if (b == 0) { Debug.Assert(false); return false; }

            // this is fixed
            Int32 dwBytesRead = 0;
            IntPtr ipBytesRead = new IntPtr(&dwBytesRead);

            bool b2 = ReadProcessMemory(
                hProcess,
                ipRemoteBuffer,
                ipTBButton,
                (uint)new UIntPtr((uint)sizeof(TBBUTTON)),
                out ipBytesRead);

            if (!b2) { Debug.Assert(false); return false; }
        }

        // button text
        fixed (byte* pLocalBuffer = localBuffer)
        {
            IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);

            int chars = (int)SendMessage(hToolbar, TB_GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);

            //SendMessage(hToolbar, BM_CLICK, (IntPtr)tbButton.idCommand, IntPtr.Zero);

           // int getmes = PostMessage(hToolbar, TB_HIDEBUTTON, (IntPtr)tbButton.idCommand, ipRemoteBuffer);



            if (chars == -1) { Debug.Assert(false); return false; }

            // this is fixed
            Int32 dwBytesRead = 0;
            IntPtr ipBytesRead = new IntPtr(&dwBytesRead);

            bool b4 = ReadProcessMemory(
                hProcess,
                ipRemoteBuffer,
                ipLocalBuffer,
                (uint)new UIntPtr(BUFFER_SIZE),
                out ipBytesRead);

            if (!b4) { Debug.Assert(false); return false; }

            text = Marshal.PtrToStringUni(ipLocalBuffer, chars);

            if (text.Contains("Pen"))
            {
                int buttonid = tbButton.idCommand;
                SendMessage(hToolbar, TB_HIGHLIGHTBUTTON, (IntPtr)tbButton.idCommand, IntPtr.Zero);
            }
            texts.Add(text);

            if (text == " ") text = String.Empty;
        }

        VirtualFreeEx(
            hProcess,
            ipRemoteBuffer,
            (int)UIntPtr.Zero,
            FreeType.Release);

        CloseHandle(hProcess);

        return true;
    }



    static void Main(string[] args)
    {

        IntPtr _ToolbarWindowHandle = GetSystemTrayHandle();

        UInt32 count = (uint)SendMessage(_ToolbarWindowHandle, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero);

        for (int i = 0; i < count; i++)
        {
            TBBUTTON tbButton = new TBBUTTON();
            string text = String.Empty;
            IntPtr ipWindowHandle = IntPtr.Zero;

            bool b = GetTBButton(_ToolbarWindowHandle, i, ref tbButton, ref text, ref ipWindowHandle);

        }

        foreach (var item in texts)
        {
            Console.WriteLine(item);
        }
    }
}

有没有办法使用C#右键单击系统托盘图标? 会感谢答案.......

1 个答案:

答案 0 :(得分:3)

没有以编程方式访问其他程序的托盘图标(来源:Raymond Chen)。你尝试的任何东西都只是一个可能破裂和失败的黑客。

尝试找到一种不需要在托盘图标上自动右键单击的方法。也许有问题的程序可以通过某些API或命令行参数来控制。