Link to home
Create AccountLog in
Avatar of ak5745
ak5745

asked on

Using Sendkeys to pass variable to textbox in other app

Hello,

After searching through the community, I'm still a little hazy on how/if this can work.
Here's my problem:

I have an app I built (App A). Said app has a button that when pressed generates a number. I'd
then like App A to send said number to a textbox in App B (third-party app I downloaded. This app
is open). That's basically it. Have App A send a number (variable) to a textbox in App B.

From my simple understanding, I can use SendKeys to send a keystroke from App A to App B.
However, this keystroke would be constantly changing depending on various other parameters.
This leads me to believe that unless SendKeys can pass a variable to another app, it probably
wouldn't work.

I've used Spy++ to locate more names/classes other than the obvious one in plain text at the
top of the window, but other than that, I'm unclear how Spy++ could benefit me (I noticed all
window names also had a hexadecimal (address?) associated with them. Can I use these in
some way, shape, or form?).

Any help would be greatly appreciated.

Thanks!
Avatar of Mez4343
Mez4343

The SendKeys class can send a keystroke to the Active application and will not work with any non-key type value. It will throw an Exception if you try to pass a value in Send() method that is not a valid keystroke. You can use a variable in Send method as long as it is a valid keystroke.

Like this:
 private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string copykeystroke = "^c";
            SendKeys.Send(copykeystroke);
        }

Will this help you? If not, do you have API type of process ot call in AppB? Integration between applications depends on the services that applications can expose or provide

If you are familar with message hooks, SPY++ would be a good tool to help you find the window handle to AppB. Here is a good tutorial on that
 http://msdn.microsoft.com/en-us/magazine/cc188966.aspx
Avatar of ak5745

ASKER

Yes, that does help. I think the problem I'm having is being able to specify which textbox in AppB to send the keystroke to. Even if I was sending a simple keystoke, I'm not sure how I'd tell which textbox I was dealing with. Spy++ is a able to expose them, but I'm clueless on how to use it. Here's an example from Spy++:

+ Window 000123AB "App B" #32770 // This is the main window
 - Window 000456CD "" Edit // This is an empty textbox
 - Window 000789EF "" Edit // This is another empty textbox

I'm trying to isolate the first textbox, but am not sure how (or even if I can). If textboxes are treated like windows, could I just sendkey to specified window (i.e. textbox)?

As for integration with AppB, it's a financial program from my bank, so not sure about integrating with it. My AppA generates a number, and I'd like that number to push to a textbox in AppB from something like a button press - hopefully via FindWindow.

I am unfamiiar with hooks, but will do my homework and will try to find an answer there.

In the meantime, does my above query make sense? Is it possible to send a keystroke to a textbox on AppB from AppA? Would I treat said textbox as a window? If so, where in Spy++ do I need to look?

Thank you!
Avatar of ak5745

ASKER

With some tinkering, I was able to push a textbox value from AppA to AppB. However, it pushed to the wrong textbox since both textboxes have the same class "Edit." Is it possible to tell which textbox I need? Can I use the hexadecimal address from Spy++?

Thanks, and sorry for all the questions!
You will need to use p/invoke for findwindow(), then you will need add a pointer IntPtr to the handle address of the textbox, focus in on the window and then sendkeys.
Avatar of ak5745

ASKER

Russell,

Thanks for the reply. Would you be able to help me out with an example code snippet? I'll start searching around to see if I can find one elsewhere too, and I'll comment again if I do.

Here's the code I'm using:

 private void button2_Click(object sender, EventArgs e)
        {

            IntPtr window = FindWindow(null, "AppB"); //Find the handler of Form2

            if (window != IntPtr.Zero)//If found
            {

                IntPtr tb = FindWindowEx(window, IntPtr.Zero, "Edit", null); //Find the handler of TextBox

                foreach (char c in textBox1.Text.ToCharArray())
                {

                    PostMessage(tb, WM_CHAR, new IntPtr(c), IntPtr.Zero); //Send the chars one by one

                }

            }

        }

Above code borrowed from: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/e64994d6-413e-41e3-976b-e062fe8074b0

The code works for getting me the first textbox on the form, but I need a different one. As I said earlier, they both have the same class "Edit." So are you're saying I can add a new IntPtr somewhere along the process to specifically point to said textbox? Where?

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of Mez4343
Mez4343

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Avatar of ak5745

ASKER

@Mez4343

That worked perfectly. Thank you so much for the code snippet.

Quick question though: If my main window constantly changes (version number), how can I adapt what you gave me? I've looked around and seen a few things on EnumWindow, but am unsure.

I know this is a follow up question, but thought I'd ask - I can post it as a stand-alone if needed. However, I'll go ahead and mark your comment as my solution.

Thank you!
Avatar of ak5745

ASKER

All the help I asked for and more!
ok good. If the window caption of AppB is changing then Enumwindows might be a better choice. see this example.
https://www.experts-exchange.com/questions/21348823/EnumWindows-help-me-please.html?sfQueryTermInfo=1+10+30+c+enumwindow

I hope your not going to programmatically spam your bank now!
Avatar of ak5745

ASKER

Haha, no - no spamming for me. Thank you for the link.

Ran into another problem: The main window (AppB) has various other smaller windows in it. Spy++ shows it as an MDI Client (unfamiliar with that), and I'm unable to access the textboxes on the child forms. (Spy++ does, however, show me the control id's for the textboxs on child forms). I think I just need to drop down a level from the parent to the child in order to access them - any tips?

I've started the new question here: https://www.experts-exchange.com/questions/26704967/Using-FindWindow-to-find-MDI-Client-window-s.html

Thanks for all your help though!

That is not going to be a easy task it will take a lot of code for getting a MDI Child in your case.

You will first need to Enumerate your windows sorting out which window handle you want to use, using EnumWindowsProc (Searching through process threads), Check if Handle using GetWindowThreadProcessId() If your at this point you have already made your win32 API class for all the p/invoke imports and struct's. This function allows you to grab your application and search inside it for a specific window and then select its child MDI window, then you can use something like

bool IsVisableWindow = (pointer to handle)IsWindowVisible();
string Caption = (hWnd)this.GetWindowCaption().ToString() or GetWindowTextLength to help narrow the search for a specific window within.

Things to keep in mind.

FindWindows() is for finding parent windows NOT child windows. That is where FindWindowEx() comes into play. Once again initiate a loop search and make a check to make sure the window is not IntrPtr.Zero and not the main window.  Point to your ChildWin and focus to activate window then get your window caption from there you should already have a hold on the needed window and it will have focus so all you need to do from there is sendkeys.

IntPtr iptrParent = (Control)this.GetParentWindow();
// some more code here

ChildWin selectedWindow = (ChildWin)this.ActiveMdiChild;
selectedWindow.Focus();

sendkeys({enter}); // blah blah blah. I think you get the point? This is no simple job.

Using Process.MainWindowHandle.Equals(GetForegroundWindow())) tells you if its the main window that is active. Good for making sure its not the parent and its the child your dealing with instead.

as you can see it gets really complicated by now. The code should be in the hundreds of lines and not easily shown as a snippet.

win32 wrapper library: http://mwinapi.sourceforge.net/





Also another example is http://www.pinvoke.net/default.aspx/user32.enumchildwindows

and a even better example of what I am trying to talk about. Atleast you will have the concept of what it takes to achieve your goal.

http://moimtechview.blogspot.com/2010/08/prompt-for-save-changes-in-mmc-30.html
Avatar of ak5745

ASKER

@Mez4343,

As you might have seen earlier, I have more than one window to sift through (parent/child) to find the textbox I need. As you and others have said, EnumChildWindows seems to be the ticket. Since you were so helpful with the code snippet earlier, would it be possible to adjust the snippet to use EnumChildWindows? I've tried doing it myself (not sure if it's possible) and have had no luck. The InteropSetText() with SendMessage works great, and I'd love to continue using it. Maybe it's the syntax, or maybe I'm just blind, but EnumChildWindows is eluding me at the moment. Any help would be greatly appreciated - if it's not too late.

@Russell Venable

Thank you for the links - I'm currently trying to wrap my head around the idea of EnumChildWindows. You're right though - this is turning out to be a larger project than I anticipated!

Thanks to you both!