Reputation: 15885
I would like to simulate keystrokes within an embedded System.Windows.Controls.WebBrowser
. Various techniques for simulating keystrokes are documented already here on StackOverflow, however they do not seem to work for the WebBrowser control.
Knowing that the control wraps another window/hwnd, I would have expected the following to work however it's not:
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
...
SendMessage(myWebBrowser.Handle, WM_CHAR, key, 0);
I am already using SendMessage
to forward simulated keystrokes to other parts of the WPF application, and would prefer a consistent solution; however this is failing for the WebBrowser
.
How can I forward simulated keystrokes to WebBrowser
?
Upvotes: 3
Views: 7041
Reputation: 61
You have have to use PostMessage instead of SendMessage, then it should work.
PS: 9 years late I know
Upvotes: 0
Reputation: 91
I found I could do movement around an HTML form (Chrome Browser) from within a C# program by using sendmessage to the process #.
However, I couldn't insert text into an input field. Tried most everything (from pure C#).
While hacking, I noticed I could pop-up a context editing menu while the cursor was on the input I was trying to set, and one of the items on the menu was paste! WhatDoYouKnow! I could interact with that!
Here are the codes I used, once I had tabbed to the input I wanted to set:
Clipboard.SetText("52118"); // from C#, put the input value onto the clipboard
chrome.SendKey((char)93); // char 93 opens pop-up menu that includes paste
System.Threading.Thread.Sleep(30);
chrome.SendKey((char)0x28); // down to the first menu item
System.Threading.Thread.Sleep(30);
chrome.SendKey((char)0x28); // down to the second menu item (paste)
System.Threading.Thread.Sleep(100);
chrome.SendKey((char)0x0D); // fire the paste
Check here for the code used for the ChromeWrapper (Thanks for that!):
Sending keyboard key to browser in C# using sendkey function
Upvotes: 0
Reputation: 1499
You were so close! The handle reported by WebBrowser.Handle is the outter most handle, while all of the input is directed to the inner most handle:
var hwnd = _browser.Handle;
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Shell Embedding", null);
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Shell DocObject View", null);
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Internet Explorer_Server", null);
SendMessage(hwnd, WM_CHAR, new IntPtr(0x0D), IntPtr.Zero);
FindWindowEx definition from pinvoke.net:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
Highlighted is the WebBrowser control:
Upvotes: 1
Reputation: 15885
My solution was to use SendInput()
instead of SendMessage()
.
The import:
[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, User32.Input[] pInputs, int cbSize);
For the additional types and constants see here: http://pinvoke.net/default.aspx/user32/SendInput.html
For the expected behavior see here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx.
My virtual keypress method:
private void VirtualKeypress(Key keyCode, bool shift, char keyChar)
{
User32.Input[] inputSequence;
if (keyChar == '\0' && keyCode == Key.None)
{
throw new ArgumentException("Expected a key code or key char, not both.");
}
else if (keyChar != '\0')
{
inputSequence = KeyboardUtils.ConvertCharToInputArray(keyChar);
}
else
{
inputSequence = KeyboardUtils.ConvertKeyToInputArray(keyCode, shift);
}
User32.SendInput(
(uint)inputSequence.Length,
inputSequence,
Marshal.SizeOf(typeof(User32.Input))
);
}
I have two helper methods, ConvertCharToInputArray()
and ConvertKeyToInputArray()
, which return an array of length 2 or 4 depending if we need to tell windows that the shift key is depressed. For example:
'A' -> [] { shift down, A down, A up, shift up }
while just
'a' -> [] { A down, A up }
.
Upvotes: 3
Reputation: 4856
Well i'm only used to using this in VB6 but Try sending to myWebBrowser.object.Handle or myWebBrowser.object.HWND is what i see in VB6, but you probably have .Handle in your .net version.
try the .object and let me know how it goes!!
Upvotes: 0