C# - 从 C# 应用程序向 Google Chrome 发送消息
-
02-07-2019 - |
题
我一直在四处寻找,但没有找到如何从 C# 中做到这一点。
我想要做到这一点,这样我就可以告诉 Google Chrome 走了 向前, 后退, 打开新标签, 关闭选项卡, 打开新窗口, , 和 关闭窗口 来自我的 C# 应用程序。
我用 WinAmp 做了类似的事情
[DllImport("user32", EntryPoint = "SendMessageA")]
private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);
和其他一些。但我不知道要发送什么消息,也不知道如何找到将其传递到哪个窗口,或者其他任何事情。
那么有人可以告诉我如何从 C# 向 Chrome 发送这 6 个命令吗?谢谢
编辑:好吧,我被否决了,所以也许我不够清楚,或者人们认为我没有尝试自己解决这个问题。
首先,我不太擅长 DllImport 的全部内容。我仍在学习这一切是如何运作的。
几年前,我发现如何在 winamp 中实现相同的想法,并且我正在查看我的代码。我这样做是为了让我可以通过 C# 代码跳过一首歌曲、返回、播放、暂停和停止 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;
我会得到 汉德 (将消息发送到的程序)通过:
IntPtr hwnd = FindWindow(m_windowName, null);
然后我会向该程序发送一条消息:
SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);
我想我会为 Google Chrome 做一些非常类似的事情。但我不知道其中一些值应该是什么,我用谷歌搜索试图找到答案,但我找不到,这就是我在这里问的原因。所以我的问题是如何获取以下值:
m_窗口名称 和 WM_命令
然后,不同命令的值, 向前, 后退, 新标签, 关闭选项卡, 新窗户, 关闭窗口?
解决方案
开始您的研究 http://dev.chromium.org/developers
编辑: :向窗口发送消息只是工作的一半。窗口必须响应该消息并采取相应的行动。如果该窗口不知道消息或根本不关心,您就没有机会通过发送窗口消息来控制它。
您正在查看有关如何远程控制 Winamp 的实现细节。发送消息只是一种方法,也是 Winamp 开发人员选择的方法。您使用的这些消息是具有特定含义的用户定义的消息 仅有的 到 Winamp。
你第一步要做的就是找出 如果 Chromium 支持某种远程控制以及这些机制是什么。
其他提示
您可以使用 Visual Studio 的 Spy++ 并按 CTRL+F,然后查找 chrome 轻松获取窗口名称。我尝试了一下并得到了
“Chrome_VistaFrame”用于外窗口。包含网页的实际窗口是“Chrome_RenderWidgetHostHWND”。
就 WM_COMMAND 而言 - 您需要进行试验。显然你会想要发送按钮点击(我头上的WM_MOUSEDOWN)。由于后退、前进按钮不是它们自己的窗口,因此您需要弄清楚如何通过在某个 x、y 位置模拟鼠标单击来实现此操作,以便 chrome 知道您在做什么。或者您可以发送相当于后退/前进等的键盘快捷键。
我不久前写的一个例子是用 trillian 和 winamp 来实现这一点的: 通过c#和winapi向windows发送消息
还有一些工具可以使用脚本语言来宏化此类事情 - autoit 是我使用过的一种: 汽车网站
好吧,这就是我到目前为止所得到的......我有点知道我需要做什么,但现在只是做的问题......
这是 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;
后两个值是我从刚刚显示的图像中获得的,即这两个键的扫描代码。我不知道我是否做对了。前两个值是我在谷歌搜索 WM_KEYDOWN 值后得到的,有人使用 &H100 和 &H101 作为这两个值。我还尝试过其他一些我见过的随机想法。我就是想不通。
哦,这是 SendMessage 方法
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);
这是一个很棒的互操作常量网站:
查找值的另一种方法是使用 C# 作为语言在 koders.com 中搜索 WM_KEYDOWN 或您要查找的常量:
&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]));
}
此外,您还需要使用以下命令将 Chrome 窗口聚焦 设置前景窗口