How to send keystrokes to WebBrowser? - c#

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?

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

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:

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

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

You have have to use PostMessage instead of SendMessage, then it should work.
PS: 9 years late I know

Related

Send keystroke to application in c# (sendkeys, postmessage, sendmessage all not working)

I am trying to do one of the following
1. open desired program and press a key programmatically
2. find open window of program and press a key programmatically
(either is fine)
I have tried numerous implementations of SendKeys.SendWait(), PostMessage(), and SendMessage() unsuccessfully. Below are my code snippets
//included all these for attempts
[DllImport("User32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
static extern byte VkKeyScan(char ch);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
Get handle of window, variables used by sendmessage/postmessage/sendkeys
IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly
//IntPtr ptrOBS = FindWindow(null, "Open Broadcaster Software v0.472b");
SetForegroundWindow(ptrOBS);
const UInt32 WM_CHAR = 0x0102;
const uint WM_KEYDOWN = 0x100;
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
const int VK_S = 0x53;
SendMessage attempt:
SendMessage(ptrOBS, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);//tried both WM_CHAR and WM_KEYDOWN
PostMessage attempt:
string message = "rs";
bool sent = PostMessage(ptrOBS, WM_KEYDOWN, VkKeyScan(message[0]), 0);
SendKeys attempt:
SendKeys.SendWait("{r}");
Tried SetFocus on the parent window (application) and child window (button triggered by keypress im trying to send):
static void SetFocus(IntPtr hwndTarget, string childClassName)
{
// hwndTarget is the other app's main window
// ...
IntPtr targetThreadID = GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id
IntPtr myThreadID = GetCurrentThread(); // calling thread id, our thread id
try
{
bool lRet = AttachThreadInput(myThreadID, targetThreadID, -1); // attach current thread id to target window
// if it's not already in the foreground...
lRet = BringWindowToTop(hwndTarget);
SetForegroundWindow(hwndTarget);
// if you know the child win class name do something like this (enumerate windows using Win API again)...
IntPtr hwndChild = (IntPtr)1183492;//(IntPtr)EnumAllWindows(hwndTarget, childClassName).FirstOrDefault();
if (hwndChild == IntPtr.Zero)
{
// or use keyboard etc. to focus, i.e. send keys/input...
// SendInput (...);
return;
}
// you can use also the edit control's hwnd or some child window (of target) here
SetFocus(hwndChild); // hwndTarget);
SendKeys.SendWait("{r}");
}
finally
{
SendKeys.SendWait("{r}");
bool lRet = AttachThreadInput(myThreadID, targetThreadID, 0); //detach from foreground window
SendKeys.SendWait("{r}");
}
}
For NSGaga:
string windowName = "Open Broadcaster Software v0.472b";
IntPtr outerPtr = FindWindow(null, windowName);
IntPtr ptrOBS = (IntPtr)527814;//button that im trying to trigger keypress on
SetForegroundWindow(outerPtr);
SetForegroundWindow(ptrOBS);
SetFocus(outerPtr, "OBSWindowClass");//SetFocus(ptrOBS, "Button");
const UInt32 WM_CHAR = 0x0102;
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
const int VK_S = 0x53;
//SetForegroundWindow(ptrOBS);
System.Threading.Thread.Sleep(3000);
SendKeys.SendWait("{r}");
SendMessage(outerPtr, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);
PostMessage(outerPtr, WM_KEYDOWN, VkKeyScan('r'), 0);
You cannot reliably use SendMessage and PostMessage for synthesizing keyboard input. They are just not designed for this. These messages (WM_CHAR, WM_KEYDOWN, etc.) are notifications raised by lower-level subsystems when keyboard input has been received, processed, and forwarded on to the appropriate recipient. Sending or posting these messages yourself is like prank-calling someone.
SendKeys (like all other input synthesizer methods, including the SendInput function which was explicitly designed for synthesizing keyboard input and in at least some implementation is what SendKeys actually uses under the hood) works only when the window you wish to receive the keyboard input has the focus. In Windows, only focused (active) windows receive input events.
So SendKeys is probably the way to go if you're ever going to get this to work (either that or P/Invoking SendInput and all of its associated structures), but you do need to respect the caveat that the recipient window must have the focus. Otherwise, it's not going to get anything.
It looks like from your sample code that you're trying to use the SetForegroundWindow function to meet this precondition. Unfortunately, you're passing it an invalid value, and not doing any error checking that might alert you to this mistake. Specifically, this code is wrong:
IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly
SetForegroundWindow(ptrOBS); // WRONG, ptrOBS is not a window handle
Even if I trust you on ptrOBS being initialized correctly, that makes it a valid handle to a process, which is a very different thing than a valid handle to a window. Aside from the obvious nominal differences, processes can have multiple windows and only a single window can have the focus (i.e., be "in the foreground").
You will need to obtain the handle to a particular window before calling SetForegroundWindow, and given that we know a process can have multiple windows, that can be tricky. You need some reliable way of determining which window you want. Lots of people accomplish this by hard-coding the name of the window as a string, which works great until the target app is recompiled and this implementation detail changes. The only bulletproof way that I can think of is to have the user click the target window and your code to retrieve the handle of the window that is currently under the mouse pointer.
And of course all of this assumes that you've observed the restrictions on the use of SetForegroundWindow, enumerated in the "Remarks" section of the linked SDK documentation.
There is lot of trial and error with that, to get it working
Here is a bit of code I posted before, you might wanna give a try (and there is some more info attached)...
Pinvoke SetFocus to a particular control
Try setting focus first (using the mechanism mentioned) - and then using SendKeys or SendInput.
Here is some detailed code for SendInput...
How to send a string to other application including Microsoft Word

C# - How to PostMessage to a flash window embedded in a WebBrowser?

I would like to know if there was any way to lock onto a Flash window and post a message to it? Another person here had the answer to it, his name is Spencer K. His question was:
Sending simulated click via WebBrowser in C# to flash object embedded in HTML
Unfortunately, Mr. K wasn't very specific, and all he left behind for people reading his question was that he "got the handle and then iterated through the handles." I'm not extremely sure what he meant by that. I iterated through all visible handles using EnumWindows to no avail, as that did not return a window that was a flash window.
I hope somebody here could tell me, as it's been driving me mad for the past few days.
EDIT: I've just settled on inserting an SWF Object into my form and posting messages to the handle of that.
Actually flash window has its own handle too. To get it you have to get the class names of the controls it is embedded in from Spy++, then you can reach it like this:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
public IntPtr Flash()
{
IntPtr pControl;
pControl = FindWindowEx(webBrowser1.Handle, IntPtr.Zero, "Shell Embedding", IntPtr.Zero);
pControl = FindWindowEx(pControl, IntPtr.Zero, "Shell DocObject View", IntPtr.Zero);
pControl = FindWindowEx(pControl, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
pControl = FindWindowEx(pControl, IntPtr.Zero, "MacromediaFlashPlayerActiveX", IntPtr.Zero);
return pControl;
}
When you get the handle, you can post the clicks:
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public enum WMessages : int
{
WM_LBUTTONDOWN = 0x201,
WM_LBUTTONUP = 0x202
}
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
public void DoMouseLeftClick(IntPtr handle, Point x)
{
PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
PostMessage(handle, (uint)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
}
The points will be relative to the client, so when you save them, you should save it like this:
List<Point> plist = new List<Point>();
private void webBrowser1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.C:
plist.Add(webBrowser1.PointToClient(Cursor.Position));
break;
default:
break;
}
}
Hope this was helpful
You can do it via javascript.
Import this:
import flash.external.ExternalInterface;
Ad this to your AS code:
if (ExternalInterface.available) {
// add external interface
ExternalInterface.addCallback("jsFunction", asFunction);
}
public static function asFunction(message:String):void {
}
On your JS object of the flash object you can call this function:
jsObject.jsFunction("message");
This is the function to get the js object of the flash object:
var InternetExplorer = navigator.appName.indexOf("Microsoft") != -1;
jsObject = InternetExplorer ? window.jsObjectName: window.document.jsObjectName;
I did not test this code, I just copied it out of a project.
edit: added js function to get js object
The Flash window will probably not have its own handle, since it is embedded in a webpage. You would want to post the message to the web browser window (that's what Mr. K did).
If that doesn't work for you, the only other option that I'm aware of is to gain control of the browser via WebDriver or WatiN and interact with the flash object using javascript.
for calling a function in flash object u can use this code
swfobject.CallFunction(
"<invoke name=\"yourfunction\" returntype=\"xml\">" +
" <arguments><number>" yourvalue "</number></arguments> </invoke> ");
for more information follow this link:communicate-betwen-c-and-an-embeded-flash-application
i try it for a flash object in my form application and it work,but i did not use it for webbrowser

C# WinAPI Clicking on menu items

I'm trying to click on a menu item inside a program called Media Subtitler and whatever I'm trying to do it's not working.
First, I tried to use the function GetMenu but it returned IntPtr.Zero.
Then, I tried using the ALT key + using the first letter of my menu (F stands for file) but it did nothing.
Then, I tried using a simple MOUSEDOWN and MOUSEUP messages but again, it did nothing (I also tried creating a loop that clicks on everything in that range but there was no click in that area).
What I clearly know is that I'm working on the correct window.
What am I doing wrong?
If someone wants to test it out you can download Media Subtitler for free and it doesn't weight that much.
Also, Here's the code I've been testing:
Process p = Process.Start(#"C:\Program Files\DivXLand\Media Subtitler\MediaSub.exe");
p.WaitForInputIdle(1500);
Thread.Sleep(3000);
SetForegroundWindow(p.MainWindowHandle);
ShowWindow(p.MainWindowHandle, SW_MAXIMIZE);
IntPtr handle = p.MainWindowHandle;
SendMessage(handle, WM_NCHITTEST, 0, MakeLParam(18, 29));
//for (int i = 0; i < 200; i++)
//{
// for (int x = 0; x < 200; x++)
// {
// SendMessage(p.MainWindowHandle, WM_LBUTTONDOWN, 0, MakeLParam(i, x));
// SendMessage(p.MainWindowHandle, WM_LBUTTONUP, 0, MakeLParam(i, x));
// }
//}
//IntPtr menuItems = GetMenu(p.MainWindowHandle);
return;
//SendMessage(p.MainWindowHandle, WM_COMMAND, 6, 0);
SendMessage(p.MainWindowHandle, WM_KEYDOWN, VK_MENU, 0);
SendMessage(p.MainWindowHandle, WM_KEYUP, VK_MENU, 0);
SendMessage(p.MainWindowHandle, WM_KEYDOWN, VK_F, 0);
SendMessage(p.MainWindowHandle, WM_KEYUP, VK_F, 0);
Thanks for any help!
By monitoring the messages sent to the main window of the application, I extracted the menu identifiers for the menu items. You can post WM_COMMAND message to the window, with the ID of the menu items as the wParam:
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, Message msg, int wParam, int lParam);
PostMessage(handle, WM_COMMAND, 2, 0); // File->New subtitle
PostMessage(handle, WM_COMMAND, 3, 0); // File->New from clipboard
PostMessage(handle, WM_COMMAND, 5, 0); // File->Open text or subtitle
PostMessage(handle, WM_COMMAND, 6, 0); // File->Open video
...
I've tested the code with Media Subtitler, and it works like a charm! The only situation that this will not work, is when on windows Vista or Seven, your target program is running as Administrator and you C# program is not. Be aware of that!
The menu IDs can be easily examined by monitoring the WM_COMMAND message (using Spy++).
You can also use SendMessage instead of PostMessage, but then your program freezes until the user closes the window opened by the menu action.
You can use the same approach to send other command to other windows of the application. For example, clicking the 'Open' button of the 'Open video' window.
You can also do all of this using the System.Windows.Automation namespace: http://msdn.microsoft.com/en-us/library/ms590934.aspx
Using this namespace, you do not need to do any interop with the Win32 API. Here's an example of how to get a window by searching for a string that its name contains:
public static AutomationElement GetWindowByName(string name)
{
AutomationElement root = AutomationElement.RootElement;
foreach (AutomationElement window in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window)))
{
if (window.Current.Name.Contains(name) && window.Current.IsKeyboardFocusable)
{
return window;
}
}
return null;
}
After you have the window as an AutomationElement object, you can search it for controls and perform operations on those controls, etc.
Hope this helps!
In Visual Studio there is a tool Spy++ with which you should be able to see handle of objects.
If you see it there, you should be able to get to it using user32.dll function
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string lpszWindow);
to get to them(handle will be different everytime you run your app)
If you get the right handle, you should be able to use SendMessage to send enter, or click.
Tried this only on one app, and I used it only to read and write text, so sorry if it wont work

Send key "MediaPlayPause" to an application without setting focus to it

I am creating a program that will send media key inputs (such as MediaPlayPause, MediaNextTrack, etc) to an application that I have the IntPtr of. Sort of like a virtual remote control.
So after researching I found this, which almost tells me exactly how to solve my problem.
However, there are three problems with the approach mentioned in the link.
I cannot set the application as foreground window as I need my application to be focused.
They use the SendKeys function which requires the target window to be focused, goes against problem 1.
From what I know, SendKeys cannot send keyboard buttons such as the keyboard Play/Pause button.
In the end, I am rather confused on what I have to use (SendInput?, SendMessage?).
Any help would be appreciated.
EDIT
Using the answer I received, I hacked together the sample code below.
Theoretically, it is supposed to find notepad and insert the letter "L" into it.
However nothing shows up on notepad, nor does the application crash. Is there an obvious error I am missing?
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam);
const int WM_KEYDOWN = 0x100;
//const int WM_KEYUP = 0x101;
const int L_KEY = 0x4C;
private void button1_Click(object sender, EventArgs e)
{
IntPtr ip = FindWindowByCaption(0, "Untitled - Notepad");
SendMessage(ip, WM_KEYDOWN, L_KEY, IntPtr.Zero);
//SendMessage(ip, WM_KEYUP, L_KEY, IntPtr.Zero);
}
Most of these keys are translated to WM_APPCOMMAND* messages... so you can try SendMessage, the other option being SendInput (if the application is DirectInput-based)...
Check out the links in Windows API for common media player functions? - perhaps there is some information you can use...
As for the focus problem - there is no 100% reliable solution (see How do I send key strokes to a window without having to activate it using Windows API?)... best you can achieve with 100% reliability is to focus the application, send the keys, refocus your application... except you would write some sort of device driver (kernel mode)...
To send multimedia keys, including Play/Pause, NextTrack, PrevTrack, etc, you can use keybd_event:
public class Program
{
public const int KEYEVENTF_EXTENTEDKEY = 1;
public const int KEYEVENTF_KEYUP = 0;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
[DllImport("user32.dll")]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public static void Main(string[] args)
{
keybd_event(VK_MEDIA_PLAY_PAUSE, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // Play/Pause
//keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // PrevTrack
//keybd_event(VK_MEDIA_NEXT_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // NextTrack
}
Here is a list to the supported key codes that this windows api can handle:
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
The SendKeys class is very nice, but it's also limited. The approach above sends the key command directly to Windows OS.

Open Tab in IE8 using SendMessage() C#

In this below code, hWnd is the "URL Handle" in Spy++:
'WorkerW -> ReBarWindow32 -> Address Band Root -> Edit'
The URL is what I want to open.
I use the same method to open tabs in IE7 and send hWnd appropriately. I see that this works fine for IE7 and not for IE8. In IE8, it only opens 4 tabs and then IE8 stops honoring the SendMessage request; however, I can still press CTRL+T OR ALT+Enter to open new tabs in IE8 (so IE8 is still responsive).
/**
* Open URL in IE (open new tab when newTab is true)
* hWnd is found at runtime
**/
private void LaunchURLinIE(IntPtr hWnd, String url, bool newTab = false)
{
StringBuilder ob = new StringBuilder(url);
// Type text in the URL window
SendMessage(hWnd, WM_SETTEXT, 0, ob);
if (!newTab)
{ // Press Enter
SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, 1);
}
else
{ // Press ALT Enter to open new tab
SendMessage(hWnd, WM_SYSKEYDOWN, VK_RETURN, 1 << 29);
}
}
My environment is: Windows XP Service Pack 3 [32-bit OS] , IE8 version 8.0.6001.18702
So, is it IE8 or something I am missing?
UPDATE - 1
I have updated comments on the code so that its clear what code does. The above code works perfectly fine for IE7 (tested upto 15 tabs) but with IE8 it only opens upto 4 tabs.
Update - 2
I was able to sove this by using PostMessage instead of SendMessage.
private void LaunchURLinIE(IntPtr hWnd, String url, bool newTab = false)
{
StringBuilder ob = new StringBuilder(url);
// Type text in the URL window
SendMessage(hWnd, WM_SETTEXT, 0, ob);
if (!newTab)
{ // Press Enter
PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 1);
}
else
{ // Press ALT Enter to open new tab
PostMessage(hWnd, WM_SYSKEYDOWN, VK_RETURN, 1
You might want to try using the COM exposed by the ShDocVw object which can be found as a .dll named Interop.ShDocVw.dll this contains an InternetExplorerClass interface which allows you to do most IE automation reliably.
I am a contributor to SWAT http://sourceforge.net/projects/ulti-swat/, if you would like some good examples feel free to use our source for IE automation located in SWAT.Core/InternetExplorer.cs
There are alot of problems with your code actually, window handles are hardcoded (why?) also you are only sending a key down, the application usually expects a keydown/keyup combo or sometimes a keydown/keypress/keyup sequence in order for it to be valid. Your application makes it seem as if you are holding down the keys you are sending. You may want to use the FindWindow windows API call which can help you find the window handle at runtime for the window you want to send the messages to.
Should you not send WM_KEYUP as well?
VK_RETURN? Not sure what it does. Would it be better to send CTRL+T keystrokes instead?
KEYDOWN CTRL
KEYDOWN T
KEYUP T
KEYUP CTRL
You can find key codes with KeyInterop.VirtualKeyFromKey.
I also think you need to use PostMessage:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
private const UInt32 WM_KEYDOWN = 0x0100;
private const UInt32 WM_KEYUP = 0x0101;
public static void IENewTab(IntPtr HWnd)
{
PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.LeftCtrl), 0);
PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.T), 0);
PostMessage(HWnd, WM_KEYUP, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.T), 0);
PostMessage(HWnd, WM_KEYUP, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.LeftCtrl), 0);
}

Categories

Resources