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

本文关键字:图标 系统 单击 何使用 右键 | 更新日期: 2023-09-27 18:06:21

我想为。net应用程序编写自动化框架。要启动应用程序,用户应该右键单击系统托盘中的图标,并从上下文菜单中选择选项。我做了一些研究,找到了唯一的方法来知道托盘图标的工具提示:

    [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#右键单击系统托盘图标?感谢解答.......

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

没有编程的方式来访问其他程序的托盘图标(来源:Raymond Chen)。你所做的任何尝试都只是一种hack,很可能会被破坏和失败。

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