Question

I've been searching around, and I haven't found how I would do this from 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.

I did something similar with WinAmp using

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

and a a 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#? 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. 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. I made it so I could skip a song, go back, play, pause, and stop winamp from my C# code. 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:

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. 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. So my question is how do I get the values for:

m_windowName and WM_COMMAND

and then, the values for the different commands, forward, back, new tab, close tab, new window, close window?

Was it helpful?

Solution

Start your research at 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. Sending messages is just one way to do it and it's the way the Winamp developers chose. Those messages you're using are user defined messages that have a specific meaning only to 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.

OTHER TIPS

You can get the window name easily using Visual Studio's Spy++ and pressing CTRL+F, then finding chrome. I tried it and got

"Chrome_VistaFrame" for the out window. The actual window with the webpage in is "Chrome_RenderWidgetHostHWND".

As far as WM_COMMAND goes - you'll need to experiment. You'll obviously want to send button clicks (WM_MOUSEDOWN of the top off my head). 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. 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

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

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. Here's what I got: alt text

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:

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. 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. 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

    [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

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:

Koders.com search

&H values look like that's from VB(6). pinvoke and koders both return results for 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).

Looks slightly different from your consts. I think the function you're after is SendInput (but I haven't tried it) as it's a virtual key.

[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.
  • pInputs - Pointer to an array of INPUT structures. 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. If cbSize is not the size of an INPUT structure, the function fails.

This needs a KEYBOARD_INPUT type:

[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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top