Sending keystrokes from a C# application to a Java application - strange behaviour? - c#

I'm trying to send keystrokes from my C# program to a Java application
The code for sendig keys is:
private void SendKeysToWindow(string WindowName, string KeysToSend)
{
IntPtr hWnd = FindWindow(null, WindowName);
ShowWindowAsync(hWnd, SW_SHOWNORMAL);
SetForegroundWindow(hWnd);
SendKeys.Send(KeysToSend);
}
This code works fine with all programs, except with the Java application that I'm tyring to control.
For example, if I create a button with the folowing code:
SendKeysToWindow("Java application window name", "{F2}");
SendKeysToWindow("Popoup window name", "123");
This sends an F2 to the main program window, where another window pops up, and the second SendKeysToWindow command sends the "123" to that window.
This is how it is expected to work, and this is the case with all other programs.
However, when I send these commands to the Java program, the following happens: the first SendKeysToWindow command is executed fine (the popup window appears), but it does not send the "123" to that window.
If is press the button again, the "123" is sent to the popup window, and it opens another popoup window.
If I create two separate buttons for the two SendKeysToWindow command, and press them one after another, both commands execute fine.
What can be the probem?
Thanks for the help in advanvce, it's really driving me crazy.
P.S.: I'm a beginner in C#, so please keep the answer simple.

After some trial and error, the following code seems to work fine:
private void SendKeysToWindow(string WindowName, string KeysToSend)
{
IntPtr hWnd = FindWindow(null, WindowName);
ShowWindow(hWnd, SW_SHOWNORMAL);
SetForegroundWindow(hWnd);
Thread.Sleep(50);
SendKeys.SendWait(KeysToSend);
}

It sounds like there might just be a delay between sending {f2} and the Java application opening the popup window.
Have you tried checking whether FindWindow succeeds or fails?

Related

How to make Internet Explorer ActiveX dialog visible

I have an ActiveX control written in C# which operates a scanner from the browser using WIA. Everything works fine except the WIA CommonDialog pops under the browser window. How can I get it to show up on top of the browser?
wiaDialog = new WIA.CommonDialog();
wiaImage = wiaDialog.ShowAcquireImage(WiaDeviceType.ScannerDeviceType, WiaImageIntent.UnspecifiedIntent, WiaImageBias.MaximizeQuality, wiaFormatJPEG, false, false, false);
[Edit]
Thanks very much to Noseratio for putting me onto the right track. The suggestion to use BringWindowToTop invoked via a timer before popping up the dialog does not quite work. Instead the function to use is SetForegroundWindow. The code is as follows (invoked from a System.Timer.Timer prior to opening the scan dialog):
public static void scanDialogToTop(Object caller, EventArgs theArgs) {
scanner.theTimer.Stop();
foreach (Process p in Process.GetProcesses()) {
if (p.MainWindowTitle.StartsWith("Scan using")) {
SetForegroundWindow(p.MainWindowHandle);
break;
}
}
}
See this article for a more complete discussion.
It does not look like you can specify a parent window for ShowAcquireImage. If the caption of the popup window is static, you could use FindWindow to find the popup's handle. If ShowAcquireImage is a blocking call (doesn't return until the popup window is closed), before calling it you'd need to setup a timer and call FindWindow upon a timer event. I also suspect the WIA popup is created on a different thread (you could check that with Spy++). If that's the case, you could use the following hack to give the WIA popup window focus. Otherwise you just do BringWindowToTop.

In C#, how to activate the previously focused window?

I work eg. in Firefox, and my C#.NET app brings its window to the front. That's ok, but when I use SendToBack() to hide the form, it doesn't activate Firefox's window, so altough Firefox is in the foreground, I have to click into the window to be able to scroll, etc. How can I activate the previously focused window in C#?
i have tried these:
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int dwProcessId);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[...]
AllowSetForegroundWindow(System.Diagnostics.Process.GetCurrentProcess().Id);
SendToBack();
SetForegroundWindow(GetForegroundWindow());
I hoped that after sending my window back, the previous one will be returned by GetForegroundWindow, but it doesn't work.
Secondly, I've tried to override WndProc, and handle the WM_ACTIVATE message to get the previous window from lParam, but it doesn't work either if I use SetForegroundWindow() with this handle.
protected override void WndProc(ref Message msg) {
if (msg.Msg == 0x0006) {
prevWindow = msg.LParam;
}
base.WndProc(ref msg);
}
[...]
SetForegroundWindow(prevWindow);
did you try the SetActiveWindow function? Its separate from the SetForgroundWindow function, although it seems that you may need to use them both.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311%28v=vs.85%29.aspx
There is also a SetFocus function which sounds like it could work.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx
Update
To get the current Active Window, I would fire off the GetActiveWindow function before moving your application to the front of the stack, that way you have the handle for the window that was active before hand.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646292%28v=vs.85%29.aspx
Another Update
I did a bit more digging around on the site and came up with the following three links, which might work better. The keyboard input functions seem to be dependent on the Window you are trying to set being part of the calling threads message queue, which since we are dealing with two separate application threads, is likely to not be the case.
GetGUIThreadInfo Get the threads information, including active window
GUITHREADINFO The GUITHREADINFO structure
SwitchToThisWindow Another method of window changing
All of these are in the same method stack as the SetForegroundWindow method, which seems to make them more likely to do what you are attempting.
When you call SetFocus() to move your app forward, it returns the handle of the window that had focus before you.

How to send keystrokes to application UI automation -C#

i need to find out automationid for key board values? how to send keystrokes to application UI automation? i need to automate page up and page down function in key board. What is the best way to do
it?
EDIT:
in my application following the process. Assume end user open MS Word document with 5 pages and he presses page up and page down buttons to move within these pages. i want to automate this scenario using c#. currently i have uses UIAutomationClient.dll and UIAutomationTypes.dll. can i uses these?
A very good way for automated sending of keystrokes of all kinds is the AutoIt automation and scripting language. Lots can be done with it, especially page up and page down sending.
I suggest writing an EXE with autoit, which connects itself to the program it will send keystrokes to.
Active the application's window using P/Invoke.
Call SendWait("C") with any character.
E.g.
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}
See How to: Simulate Mouse and Keyboard Events in Code > "To send a keystroke to a different application"
I think you want to send keystrokes to an application for which you don't have source code.
I can't help you telling you how to do it directly in C#.
But you can do it very easily with AutoIt; it has a DLL you can reference in C# to do exactly what you need.
Have you read
How to send keys instead of characters to a process?
This tells you exactly how to send keys to an application.
//
use a windows form and use this list with send key
https://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm
I'm pretty sure he's just asking for values of the keys for his SendKey.Send("{}");
in this scenario get the word document to fore ground and then used on screen key board
System.Diagnostics.Process.Start("osk.exe");and click page up and down buttons using mouse input
since for the mouse click need screen coordinates for the page up and down button.
( i tried to detect on screen key board using UI automation. but it did not detect keys of the screen.
https://stackoverflow.com/questions/11077738/windows-sdk-inspect-tool-what-are-the-reasons-on-screen-keyboard-does-not-disp couldn't find solution for this problem.so because of that i use this move click method to click the button. )

Sending text into whatever window that is currently in focus

I'm trying to write a program with C# that sends text into other windows.
How do I write a command in C# that sends a text into the window that is currently under the users focus?
For example:
If the user clicks an open notepad window, or an open outlook letter, or an open excel sheet, and then clicks the button on my program, a text will be "pasted" directly into the last notepad window/outlook letter/excel cell that the user clicked on last.
I hope my question is clear enough. I'm not so experienced and am missing a lot of terminology.
Take your application out of focus by minimizing or hiding the main window, and then send your text with
SendKeys.SendWait("Hello World!");
Finally, restore your main window.
If the code is executed in the main form, you could do this
this.Visible = false;
SendKeys.SendWait("Hello World!");
this.Visible = true;
Olivier's response actually seems more accurate (and taught me something :)) than my original "does not seem achievable". If you need an example, then take a look at this:
http://www.codeproject.com/Articles/18366/Sending-Keystrokes-to-another-Application-in-C
However, on a more complex level, without an API to call into, there is not much more that you can do beyond this solution.

Should Form.ShowDialog(IWin32Window) work with any window handle?

When using System.Windows.Forms.ShowDialog(IWin32Window), should I be able to pass in an IWin32Window representing any window handle and have it be modal with respect to that window?
As part of an Internet Explorer 7 extension I'm trying to open a window modal with respect to an Internet Explorer tab. It's not the currently selected tab, but I can get the hwnd of the tab OK. However, when I pass this to ShowDialog my Form is shown, but it's not modal with respect to anything: I can still do things in Internet Explorer, including in the tab that's supposed to be the owner. My form is shown floating above the Internet Explorer windows and it stays on top, so it's not like it's just opened as a normal form, but it's not correctly modal.
Using Spy++, I can find my form and it's owner handle is correctly set.
Does this mean that something has gone wrong, or I'm doing something wrong? How do I make my form correctly modal?
FYI, I'm using this wrapper class to create an IWin32Window from a hwnd (thanks Ryan!):
/// <summary>
/// Wrapper class so that we can return an IWin32Window given a hwnd
/// </summary>
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
private IntPtr _hwnd;
}
UPDATE: Using Internet Explorer 7 & .NET 2.0
UPDATE: Playing around some more with Spy++ and the handles it exposes, I find that if I use a different hwnd then I can make my window modal to the tab:
I was using the tab's hwnd as suggested by the IWebBrowser2.HWND doc, which in Spy++ appears as class TabWindowClass. It has a child of class Shell DocObject View, which has a child of Internet_Explorer_Server. If I use the hwnd of the Internet Explorer_Server then it works correctly, for example, when I click with the mouse on other tabs, Internet Explorer reacts normally. When I click with the mouse on the tab of interest, it plays the windows d'oh sound and doesn't do anything.
I don't yet know how to programatically get the Internet_Explorer_Server hwnd, but it should be possible.
Also, for what it's worth, while playing with other window handles I was generally able to make my form modal to other applications and dialogs. So I guess the answer to my question is 'many but not all handles'... possibly it depends on the application?
UPDATE: Another side-note: The original reason I wanted to make my form modal to the tab instead of the whole window is that when opening a MessageBox from my form, passing the form as owner, the MessageBox would not always open on top of my form. If a new Internet Explorer tab had just been opened but wasn't active then the MessageBox would be hidden and that tab would start flashing. However, since Internet Explorer was disabled with my form opened modal it wasn't possible to switch to that tab, so Internet Explorer would be frozen. I thought that opening my form modal to the tab would solve this, but I've found another solution is to avoid using MessageBox: if I use a second form and ShowDialog(this) from my first form then the second form correctly opens to the front. So it seems that Form.ShowDialog() works better than MessageBox.Show() in some cases. More discussion in Problems with modal dialogs and messageboxes.
ShowDialog() does two important things. It starts pumping a message loop so it acts modally to the calling code. And it disables any other windows in the application with a EnableWindow(false) API call. The latter is what is not happening in your case. Not entirely surprising, considering that the window that needs to be disabled is not a WF window.
You may need to call EnableWindow() yourself. Be sure to re-enable it in before the dialog closes or Windows will go hunting for another app's window to give the focus to.
Your code is correct. The problem you are likely running into though is that IE has a threading model related to its tabs. I don't know the exact details but the short version is that each tab can and likely is running on a different thread than other tabs.
The Modal'ness of a dialog is specific to the thread where the dialog is running. UI on other threads will be unaffected by a model dialog on another thread. It's entirely possible you are able to access tabs which are running on a different thread for this reason.
Here's a more concise version of Ryan/Rory's WindowWrapper code:
internal class WindowWrapper : IWin32Window
{
public IntPtr Handle { get; private set; }
public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}
I have never tried this from an IE extension, but I have a hunch that IE may not "respect" a Win32-style modal window the same way it does a modal window raised from Javascript using window.open().
Have you tested this code against something other than IE, just to confirm it works the way it should for other applications?
here is a build in solution in .NET:
public static NativeWindow FromHandle(IntPtr handle)

Categories