C#-从C#应用程序向Google Chrome发送消息
我一直在搜索,但是还没有找到如何从C#中做到这一点。
我想要这样做,以便可以告诉Google Chrome从我的C应用程序中前进,后退,打开新选项卡,关闭选项卡,打开新窗口和关闭窗口。
我使用WinAmp做过类似的事情
[DllImport("user32", EntryPoint = "SendMessageA")] private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);
和其他一些。但是我不知道要发送什么消息,或者如何找到将其传递给哪个窗口,等等。
有人可以告诉我如何将这6条命令从C#发送到Chrome吗?谢谢
编辑:
好的,我被否决了,所以也许我不够清楚,或者人们以为我没有尝试自己解决这个问题。
首先,我对整个DllImport东西不太满意。我仍在学习这一切的运作方式。
几年前,我发现如何在winamp中实现相同的想法,并且我正在查看自己的代码。我做到了,这样我就可以跳过歌曲,返回,播放,暂停和停止Ccode中的winamp。我从导入开始:
[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;
我将通过以下方式获取hwnd(向其发送消息的程序):
IntPtr hwnd = FindWindow(m_windowName, null);
然后我会向该程序发送一条消息:
SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);
我认为我会为Google Chrome做类似的事情。但是我不知道其中的一些值应该是什么,我四处搜寻试图找到答案的方法,但是我做不到,这就是为什么我在这里问。所以我的问题是如何获取以下值:
m_windowName和WM_COMMAND
然后,不同命令的值,前进,后退,新选项卡,关闭选项卡,新窗口,关闭窗口?
解决方案
在http://dev.chromium.org/developers上开始研究
编辑:向窗口发送消息只是工作的一半。窗口必须响应该消息并采取相应措施。如果该窗口不知道消息或者根本不在乎,则我们没有机会通过发送窗口消息来控制它。
我们正在查看有关如何远程控制Winamp的实现细节。发送消息只是做到这一点的一种方式,也是Winamp开发人员选择的方式。我们正在使用的那些消息是用户定义的消息,仅对Winamp具有特定的含义。
第一步,我们需要了解Chromium是否支持某种远程控制以及这些机制是什么。
我们可以使用Visual Studio的Spy ++并按CTRL + F,然后找到镶边,轻松获得窗口名称。我试了一下
" Chrome_VistaFrame"用于外出窗口。包含网页的实际窗口是" Chrome_RenderWidgetHostHWND"。
就WM_COMMAND而言,我们需要进行实验。我们显然会希望发送按钮点击(我的头顶上方是WM_MOUSEDOWN)。由于后退,前进按钮不是它们自己的窗口,因此我们需要弄清楚如何通过在特定的x,y位置上模拟鼠标单击来做到这一点,以便chrome知道我们在做什么。或者,我们可以将等效的键盘快捷键发送给后退/前进等。
我之前写的一个示例使用trillian和winamp做到了这一点:通过cand winapi将消息发送到Windows
还有一些工具可以将这种情况宏化,使用脚本语言autoit是我使用过的一种:autoit.com
好的,这就是我到目前为止所拥有的...我有点知道我需要做的事,但这只是现在要做的事情...
这是Spy ++的窗口,我锁定到Chrome_RenderWidgetHostHWND并单击键盘上的"后退"按钮。这是我得到的:
所以这是我的假设,而我一直以来一直在玩这个游戏,我只是无法弄清楚这些价值。
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;
我从刚刚显示的图像中获得的后两个值是这两个键的ScanCodes。我不知道我是否做对了。我在Google搜索WM_KEYDOWN值后得到的前两个值,有人用&H100和&H101作为这两个值。我尝试了其他一些随处可见的随机想法。我只是想不通。
哦,这是SendMessage方法
[DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);
这是互操作常量的绝佳站点:
品客
查找值的另一种方法是使用Cas语言搜索koders.com,以获取WM_KEYDOWN或者所需的常量:
Koders.com搜索
&H值看起来像来自VB(6)。 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;
(有趣的是,考虑到VK_ *是1字节0-255的值,并且人们已经将它们设为uint,VK常数有多少错误的定义在浮动着呢?)。
看起来与const略有不同。我认为我们要使用的功能是SendInput(但我没有尝试过),因为它是一个虚拟键。
[DllImport("User32.dll")] private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KEYBOARD_INPUT[] input, int structSize);
有关参数的说明:
参数
- nInputs-pInputs数组中的结构数。
- pInputs-指向INPUT结构数组的指针。每个结构代表一个要插入键盘或者鼠标输入流的事件。
- cbSize-指定INPUT结构的大小(以字节为单位)。如果cbSize不是INPUT结构的大小,则该函数将失败。
这需要一个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; }
最后是一个样本,我还没有测试它是否可行:
/* 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将Chrome窗口聚焦