代码之家  ›  专栏  ›  技术社区  ›  Joel

C-从C应用程序向Google Chrome发送消息

  •  19
  • Joel  · 技术社区  · 16 年前

    我一直在四处寻找,但我还没有找到如何从C做到这一点。

    我本来想让谷歌Chrome去的 福沃德 , 背部 , 打开新标签 , 关闭标签 , 打开新窗口 关闭窗口 从我的C申请。

    我用winamp做了类似的事情

    [DllImport("user32", EntryPoint = "SendMessageA")]
    private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);
    

    还有其他一些。但我不知道该发送什么消息,也不知道如何找到传递消息的窗口,或者其他什么。

    有人能告诉我如何从C向Chrome发送这6个命令吗?谢谢

    编辑: 好吧,我正在被投票否决,所以也许我不够清楚,或者人们认为我没有试图自己解决这个问题。

    首先,我不太擅长处理所有的问题。我还在学习这一切是如何运作的。

    几年前,我在Winamp上发现了如何实现同样的想法,当时我正在研究我的代码。我做到了,这样我就可以跳过一首歌,返回,播放,暂停,并停止Winamp从我的C代码。我从导入开始:

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int SendMessageA(IntPtr hwnd, int wMsg, int wParam, uint lParam);
        [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hwnd, string lpString, int cch);
        [DllImport("user32", EntryPoint = "FindWindowExA")]
        private static extern int FindWindowEx(int hWnd1, int hWnd2, string lpsz1, string lpsz2);
        [DllImport("user32", EntryPoint = "SendMessageA")]
        private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);
    

    然后我发现使用这个的代码将这些常量用于我发送的消息。

        const int WM_COMMAND = 0x111;
        const int WA_NOTHING = 0;
        const int WA_PREVTRACK = 40044;
        const int WA_PLAY = 40045;
        const int WA_PAUSE = 40046;
        const int WA_STOP = 40047;
        const int WA_NEXTTRACK = 40048;
        const int WA_VOLUMEUP = 40058;
        const int WA_VOLUMEDOWN = 40059;
        const int WINAMP_FFWD5S = 40060;
        const int WINAMP_REW5S = 40061;
    

    我会得到 父窗口句柄 (发送消息的程序)通过:

    IntPtr hwnd = FindWindow(m_windowName, null);
    

    然后我会给那个程序发送一条消息:

    SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);
    

    我想我会为谷歌Chrome做一些类似的事情。但我不知道其中的一些价值应该是什么,我到处搜索,试图找到答案,但我找不到,这就是我在这里问的原因。因此,我的问题是如何获得以下各项的值:

    MyWrWONNAMEM WMX命令

    然后,不同命令的值, 向前地 , 后面 , 新标签页 , 关闭标签 , 新窗口 , 关闭窗口 ?

    4 回复  |  直到 13 年前
        1
  •  9
  •   VVS    16 年前

    开始你的研究 http://dev.chromium.org/developers


    编辑 :向窗口发送消息只是工作的一半。窗口必须响应该消息并相应地执行操作。如果那个窗口不知道一条消息或者根本不关心,你就没有机会通过发送窗口消息来控制它。

    您正在查看有关如何远程控制Winamp的实现细节。发送消息只是一种方式,也是Winamp开发人员选择的方式。您使用的消息是用户定义的具有特定含义的消息 只有 到WiNAMP公司。

    第一步你要做的就是找出 如果 铬支持某种远程控制以及这些机制是什么。

        2
  •  7
  •   Chris S    16 年前

    使用Visual Studio的Spy++并按ctrl+f,然后找到chrome,您可以轻松地获得窗口名。我试过了

    “Chrome vistaframe”用于外窗。网页所在的实际窗口是“chrome-renderwidgethostwind”。

    至于wm_命令,您需要进行试验。很明显,你会想发送按钮点击(wm_mousedown of the top off my head)。作为背面,前进按钮不是他们自己的窗口,你需要弄清楚如何在某个X,Y位置模拟鼠标点击,这样Chrome知道你在做什么。或者,您可以发送键盘快捷键,相当于后退/前进等等。

    我刚才用Trillian和Winamp写了一个例子: sending messages to windows via c# and winapi

    还有一些工具可以用脚本语言来宏处理这类事情——autoit是我使用过的一种语言: autoit.com

        3
  •  4
  •   Community CDub    8 年前

    好吧,这是我到目前为止得到的……我知道我需要做什么,但现在做只是个问题…

    这是Spy++的窗口,我锁定了 铬合金渲染器 然后点击我键盘上的后退按钮。我得到的是: alt text

    这是我的假设,我一直在玩这个游戏,直到现在,我都不知道 价值观 .

    IntPtr hWnd = FindWindow("Chrome_RenderWidgetHostHWND", null);
    SendMessage(hWnd, WM_KEYDOWN, VK_BROWSER_BACK, 0);
    SendMessage(hWnd, WM_KEYUP,   VK_BROWSER_BACK, 0);
    

    现在,我只是不知道我应该把wm_keydown/up值或者vk_browser_back/forward值设为什么… 我试过这个:

    const int WM_KEYDOWN = 0x100;
    const int WM_KEYUP = 0x101;
    const int VK_BROWSER_BACK = 0x6A;
    const int VK_BROWSER_FORWARD = 0x69;
    

    后两个值是从我刚才显示的图像中得到的,这两个键的扫描码。但我不知道我是否做得对。在谷歌搜索wm_keydown值后得到的前两个值,有人使用了&h100和&h101作为这两个值。我还尝试过其他一些随机的想法。我就是想不出来。

    哦,这里是sendmessage方法

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);
    
        4
  •  4
  •   Chris S    16 年前

    这是一个很好的interop常量站点:

    pinvoke

    另一种查找值的方法是使用c作为语言搜索koders.com,查找wm诳keydown或所需常量:

    Koders.com search

    &h值看起来像是来自vb(6)。Pinvoke和Koders都返回vk_浏览器转发的结果,

    private const UInt32 WM_KEYDOWN        = 0x0100;
    private const UInt32 WM_KEYUP          = 0x0101;
    
    public const ushort VK_BROWSER_BACK = 0xA6;
    public const ushort VK_BROWSER_FORWARD = 0xA7;
    public const ushort VK_BROWSER_REFRESH = 0xA8;
    public const ushort VK_BROWSER_STOP = 0xA9;
    public const ushort VK_BROWSER_SEARCH = 0xAA;
    public const ushort VK_BROWSER_FAVORITES = 0xAB;
    public const ushort VK_BROWSER_HOME = 0xAC;
    

    (有趣的是,考虑到vk_u*是1字节的0-255值,并且人们已经将它们设置为uint,所以有多少对vk常量的错误定义在浮动)。

    看起来和你的警察有点不同。我认为您需要的函数是sendinput(但我没有尝试过),因为它是一个虚拟密钥。

    [DllImport("User32.dll")]
    private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KEYBOARD_INPUT[] input, int structSize);
    

    参数说明:

    参数

    • ninputs-精确定位数组中的结构数。
    • 精确定位-指向输入结构数组的指针。每个结构表示要插入到键盘或鼠标输入流中的事件。
    • cbsize—指定输入结构的大小(以字节为单位)。如果cbsize不是输入结构的大小,则函数失败。

    这需要键盘输入类型:

    [StructLayout(LayoutKind.Sequential)] 
    public struct KEYBOARD_INPUT
    { 
        public uint type; 
        public ushort vk; 
        public ushort scanCode; 
        public uint flags; 
        public uint time; 
        public uint extrainfo; 
        public uint padding1; 
        public uint padding2; 
    }
    

    最后是一个样本,我还没有测试它是否有效:

    /*
    typedef struct tagKEYBDINPUT {
        WORD wVk;
        WORD wScan;
        DWORD dwFlags;
        DWORD time;
        ULONG_PTR dwExtraInfo;
    } KEYBDINPUT, *PKEYBDINPUT;
    */
    public static void sendKey(int scanCode, bool press)
    {
            KEYBOARD_INPUT[] input = new KEYBOARD_INPUT[1];
            input[0] = new KEYBOARD_INPUT();
            input[0].type = INPUT_KEYBOARD;
            input[0].vk = VK_BROWSER_BACK;
    
        uint result = SendInput(1, input, Marshal.SizeOf(input[0]));
    }
    

    此外,还需要使用 SetForegroundWindow