简体   繁体   English

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

[英]C# - Sending messages to Google Chrome from C# application

I've been searching around, and I haven't found how I would do this from C#. 我一直在寻找,我还没有找到我将如何从C#中做到这一点。

I was wanting to make it so I could tell Google Chrome to go Forward , Back , Open New Tab , Close Tab , Open New Window , and Close Window from my C# application. 我想要这样做,所以我可以告诉谷歌Chrome从我的C#应用​​程序前进后退打开新标签关闭标签打开新窗口关闭窗口

I did something similar with WinAmp using 我使用WinAmp做了类似的事情

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

and aa few others. 还有一些其他人。 But I don't know what message to send or how to find what window to pass it to, or anything. 但我不知道要发送什么消息或者如何找到传递给它的窗口,或者其他什么。

So could someone show me how I would send those 6 commands to Chrome from C#? 那么有人可以告诉我如何从C#向Chrome发送这6个命令吗? thanks 谢谢

EDIT: Ok, I'm getting voted down, so maybe I wasn't clear enough, or people are assuming I didn't try to figure this out on my own. 编辑:好的,我正在投票,所以也许我不够清楚,或者人们假设我没有试图自己解决这个问题。

First off, I'm not very good with the whole DllImport stuff. 首先,我对整个DllImport的东西不太满意。 I'm still learning how it all works. 我还在学习它是如何运作的。

I found how to do the same idea in winamp a few years ago, and I was looking at my code. 几年前我在winamp找到了如何做同样的想法,我正在查看我的代码。 I made it so I could skip a song, go back, play, pause, and stop winamp from my C# code. 我做了所以我可以跳过一首歌,回去,播放,暂停,并停止从我的C#代码winamp。 I started by importing: 我开始导入:

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

Then the code I found to use this used these constants for the messages I send. 然后我发现使用它的代码使用这些常量来发送我发送的消息。

    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;

I would get the hwnd (the program to send the message to) by: 我会通过以下方式获得hwnd (发送消息的程序):

IntPtr hwnd = FindWindow(m_windowName, null);

then I would send a message to that program: 然后我会向该程序发送一条消息:

SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);

I assume that I would do something very similar to this for Google Chrome. 我认为我会为Google Chrome做一些非常类似的事情。 but I don't know what some of those values should be, and I googled around trying to find the answer, but I couldn't, which is why I asked here. 但是我不知道这些价值观应该是什么,我用Google搜索找到答案,但我不能,这就是我在这里问的原因。 So my question is how do I get the values for: 所以我的问题是如何获取以下值:

m_windowName and WM_COMMAND m_windowNameWM_COMMAND

and then, the values for the different commands, forward , back , new tab , close tab , new window , close window ? 然后,不同命令的值, 前进后退新选项卡关闭选项卡新窗口关闭窗口

Start your research at http://dev.chromium.org/developers http://dev.chromium.org/developers开始您的研究


EDIT : Sending a message to a window is only half of the work. 编辑 :向窗口发送消息只是工作的一半。 The window has to respond to that message and act accordingly. 窗口必须响应该消息并相应地采取行动。 If that window doesn't know about a message or doesn't care at all you have no chance to control it by sending window messages. 如果该窗口不知道消息或根本不关心,则您无法通过发送窗口消息来控制它。

You're looking at an implementation detail on how you remote controlled Winamp. 您正在查看有关如何远程控制Winamp的实现细节。 Sending messages is just one way to do it and it's the way the Winamp developers chose. 发送消息只是实现它的一种方式,而这正是Winamp开发人员选择的方式。 Those messages you're using are user defined messages that have a specific meaning only to Winamp. 您正在使用的那些消息是用户定义的消息, 仅对 Winamp具有特定含义。

What you have to do in the first step is to find out if Chromium supports some kind of remote controlling and what those mechanisms are. 你在第一步要做的是找出是否铬支持某种远程控制的以及这些机制。

You can get the window name easily using Visual Studio's Spy++ and pressing CTRL+F, then finding chrome. 您可以使用Visual Studio的Spy ++轻松获取窗口名称,然后按CTRL + F,然后找到chrome。 I tried it and got 我试过了,得到了

"Chrome_VistaFrame" for the out window. 用于out窗口的“Chrome_VistaFrame”。 The actual window with the webpage in is "Chrome_RenderWidgetHostHWND". 带有网页的实际窗口是“Chrome_RenderWidgetHostHWND”。

As far as WM_COMMAND goes - you'll need to experiment. 就WM_COMMAND而言 - 你需要进行实验。 You'll obviously want to send button clicks (WM_MOUSEDOWN of the top off my head). 你显然想要发送按钮点击(我头顶的WM_MOUSEDOWN)。 As the back,forward buttons aren't their own windows, you'll need to figure out how to do this with simulating a mouse click at a certain x,y position so chrome knows what you're doing. 由于后退,前进按钮不是他们自己的窗口,你需要弄清楚如何通过在某个x,y位置模拟鼠标点击来实现这一点,以便Chrome知道你正在做什么。 Or you could send the keyboard shortcut equivalent for back/forward and so on. 或者您可以发送等效于后退/前进的键盘快捷键等。

An example I wrote a while ago does this with trillian and winamp: sending messages to windows via c# and winapi 我刚才写的一个例子是trillian和winamp: 通过c#和winapi向windows发送消息

There's also tools out there to macro out this kind of thing already, using a scripting language - autoit is one I've used: autoit.com 还有一些工具可以使用脚本语言来解决这种问题 - autoit是我使用过的: autoit.com

Ok, here's what I've got so far... I kinda know what I need to do, but it's just a matter of doing it now... 好的,这就是我到目前为止所得到的......我知道我需要做什么,但这只是现在做的事情......

Here's the window from Spy++, I locked onto the Chrome_RenderWidgetHostHWND and clicked the Back button on my keyboard. 这是Spy ++的窗口,我锁定了Chrome_RenderWidgetHostHWND并单击了键盘上的Back按钮。 Here's what I got: 这是我得到的: 替代文字

So here's my assumptions, and I've been playing with this forever now, I just can't figure out the values . 所以这是我的假设,我现在一直在玩这个,我只是无法弄清楚价值观

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

Now, I just don't know what I should make the WM_KEYDOWN/UP values or the VK_BROWSER_BACK/FORWARD values... I tried this: 现在,我只是不知道我应该做什么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;

The latter two values I got from the image I just showed, the ScanCodes for those two keys. 我从刚刚显示的图像中得到的后两个值,这两个键的ScanCodes。 I don't know if I did it right though. 我不知道我是否做得对。 The former two values I got after searching google for the WM_KEYDOWN value, and someone used &H100 and &H101 for the two values. 我在搜索谷歌获取WM_KEYDOWN值后得到的前两个值,有人使用&H100和&H101作为两个值。 I've tried several other random ideas I've seen floating around. 我已经尝试了其他一些我见过的随机想法。 I just can't figure this out. 我只是想不出来。

Oh, and here's the SendMessage method 哦,这是SendMessage方法

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);

This is a great site for interop constants: 这是互操作常量的一个很好的站点:

pinvoke 的PInvoke

Another way of finding the values is to search koders.com, using C# as the language, for WM_KEYDOWN or the constant you're after: 查找值的另一种方法是使用C#作为语言搜索koders.com,WM_KEYDOWN或您之后的常量:

Koders.com search Koders.com搜索

&H values look like that's from VB(6). &H值看起来像是VB(6)。 pinvoke and koders both return results for VK_BROWSER_FORWARD, pinvoke和koders都返回VK_BROWSER_FORWARD的结果,

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;

(It's funny how many wrong defintions of VK constants are floating about, considering VK_* are 1 byte 0-255 values, and people have made them uints). (有趣的是,有多少错误的VK常量定义正在浮动,考虑到VK_ *是1字节0-255的值,而人们已经使它们变得不正常)。

Looks slightly different from your consts. 看起来与你的consts略有不同。 I think the function you're after is SendInput (but I haven't tried it) as it's a virtual key. 我认为你所追求的功能是SendInput(但我还没试过),因为它是一个虚拟键。

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

Explanation about the parameters: 有关参数的说明:

Parameters 参数

  • nInputs- Number of structures in the pInputs array. nInputs- pInputs数组中的结构数。
  • pInputs - Pointer to an array of INPUT structures. pInputs - 指向INPUT结构数组的指针。 Each structure represents an event to be inserted into the keyboard or mouse input stream. 每个结构表示要插入键盘或鼠标输入流的事件。
  • cbSize - Specifies the size, in bytes, of an INPUT structure. cbSize - 指定INPUT结构的大小(以字节为单位)。 If cbSize is not the size of an INPUT structure, the function fails. 如果cbSize不是INPUT结构的大小,则该函数将失败。

This needs a KEYBOARD_INPUT type: 这需要KEYBOARD_INPUT类型:

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

And finally a sample, which I haven't tested if it works: 最后是一个样本,我没有测试它是否有效:

/*
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]));
}

Also you'll need to focus the Chrome window using SetForegroundWindow 此外,您还需要使用SetForegroundWindow关注Chrome窗口

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM