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. )
Related
I'm trying to obtain process information for the current active application (or window), using .Net/C#.
Currently I'm using
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
To get the current active window.
I understand there's no native way to do this other than use this API function.
From that, I use:
[DllImport("user32")]
private static extern UInt32 GetWindowThreadProcessId(IntPtr hWnd, out Int32 lpdwProcessId);
To get the process name that belongs to that window and then I get further process information.
I also use
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
To get the current Window Text or caption.
Now, using the Process class, I can use
MainWindowTitle
to get the main Window title as well.
The thing is, MainWindowTitle and GetWindowText does not return the same information.
For example, let's say the main application opened is "Toad" with a connection and an editor open.
Then with GetWindowText I get:
"Toad for Oracle - myConnection - Somequery.sql".
and Process.MainWindowTitle returns
"myConnection".
So, the question is how do I get the exact same text as I get using GetWindowText, but using merely .Net classes?
Edit:
I found out that actually the reason is simply because both functions are not querying the same window handle.
The window handle returned in the GetForegroundWindow, is the number 198982.
And the MainWindowHandle property, which I suppose is the one used in the MainWindowTitle propery is the number 198954.
Using Spy++ I could find and confirm those windows handle captions are the one returned by their corresponding function.
So the "problem", if any, is that the Process class does not correctly identify the most foreground window as the Main Window.
GetForegroundWindow gives you the active window the user is working in and that might be a owned window or a modal dialog, not necessarily the applications main/root window.
MainWindow is a .NET concept, native win32 does not have such a thing and there can be 0, 1 or multiple "main windows" in an application.
Some Delphi/C++Builder applications have a HWND for the taskbar button and each form is a owned window belonging to this "invisible" window. Other UI frameworks may pull similar stunts that might confuse "main window" detection.
You can use UI Automation to inspect other applications if you don't want to use p-invoke. Start with the foreground window and walk up the tree of owned and child windows...
What i have now: my app in C# is half-transparent, and does not catch winapi events - every click, drag etc is catch by underlaying window, which is separate app (like webbrower). I use this to overlay information on top of what browser shows. This is my code for this:
int exstyle = GetWindowLong(this.Handle, GWL_EXSTYLE);
exstyle |= WS_EX_TRANSPARENT;
SetWindowLong(this.Handle, GWL_EXSTYLE, exstyle);
IntPtr hwndf = this.Handle;
IntPtr hwndParent = GetDesktopWindow();
SetParent(hwndf, hwndParent);
But now, i would like to send all events to both my app window (which is half-transparent on top) and web browser (under my app). So for example if i click, the click works in both windows as if they were on top. I imagine that only way to do that is to catch all events and then forward them to lower window, but is there any way to do that?
I use winforms as window lib.
What i do now is not that important, because i want to normally consume events, then forward them to underlaying window. So this is something completly different from what i'm doing now with WS_EX_TRANSPARENT. The point of this is to drag content in both windows simultaneously. If there is any better way of doing it, i would be glad to hear it.
As least what i need is to transfer drag events to both windows, and all other events to underlaying window (not under my control). So, perhaps it will be easier to stay with my window as WS_EX_TRANSPARENT (makes events pass-thru to underlaying window) and simply install global hook to receive drag events? What do you think?
BTW i don't have experience with Winapi, so solution might be obvious.
You can capture Windows events sent your own form by overloading WndProc on the form, or alternatively by calling user32!GetMessage
You can send messages to other Windows forms via the user32!PostMessage or user32!SendMessage apis (read PostMessage function on msdn).
You could try forwarding the event after the underlying form has handled it. Something like
protected override void OnDragOver(DragEventArgs drgevent)
{
base.OnDragOver(drgevent);
MyControl.ForwardDragEvent(drgevent);
}
In MyControl:
public void ForwardDragEvent(DragEventArgs drgevent)
{
base.OnDragOver(drgevent);
//Or call your own method to handle the event
}
I have used this to forward scroll-events, in my case however, only one of the controls handled the event..
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.
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?
I have done a global mouse event in my windows application. When i click the center button of my mouse, i want to make a particular form topmost...
There are some applications which runs in the full screen mode, so i need to do this, in order to make my form visible to the users, because this is the only way to view it. Since Alt + Tab is disabled. This is a Kiosk application.
I tried using Topmost = true for that particular form and
I tried using below code...But no use. I am not getting my form in front.
[DllImport("User32.dll")]
public static extern Int32 SetForegroundWindow(int hWnd);
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
private void BringToFront(string className,string CaptionName)
{
SetForegroundWindow(FindWindow(className,CaptionName));
}
The global hotkey which has to trigger this form to bring front is working perfectly.
How to make my form come front ??? Thanks.
I solved it, doing this:
this.TopMost = true;
this.TopMost = false;
Not my thing but have you tried messing with:
this.BringToFront();
this.Activate();
get the handle of the window and do this
SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE| SWP_SHOWWINDOW);
You need set the fullscreen form's topmost to false, then continue on.
You may not be calling your BringToFront method correctly. For the FindWindow API function, lpClassName would be your application's name (e.g. "MyApplication.exe"), while lpWindowName refers to the caption in the particular form's title bar (e.g. "Form1"). Usually with FindWindow you pass in one or the other, eg:
FindWindow("MyApplication.exe", null);
// or
FindWindow(null, "Form1");
I'm not sure what happens when you pass both.
You may also just need to do something simple to achieve this, like calling the particular form's Activate() method.