?
Solved

Passing keypresses to other windows (internet explorer)

Posted on 2003-03-12
10
Medium Priority
?
392 Views
Last Modified: 2013-12-03
In my program I want to pass keypresses to a internet explorer window which I have got the HWND for using FindWindow();
I want to control iexplore through my program and I will cycle through the links using the TAB key and then followed by the RETURN key. I was doing it as follows:

    HWND h = FindWindow(NULL,"Yahoo! - Microsoft Internet Explorer provided by Freeserve.net");

    for(int i=0; i<10; i++)
    {
         PostMessage(h, WM_KEYDOWN, VK_TAB, 0);
         PostMessage(h, WM_KEYUP, VK_TAB, 0);
         Sleep(500);
    }
    PostMessage(h, WM_KEYUP, VK_RETURN, 0);

So this would cycle through 10 links at 0.5 second intervals and click the link afterwards using VK_RETURN.
I have tried this through the keyboard and it works fine, clicking TAB 10 times followed by Enter (its a specific website so I know how many times to click TAB, in this case Yahoo.com).
But when my program does it, it comes off the address bar (which is the first click of TAB), onto the first link of the page on the second TAB command(everything is fine so far), but then afterwards it goes back onto the address bar and continues to select/deselect the address bar.  I can't understand what is happening as I am sending the exact commands that I presume the keyboard sends to IE.  Can anyone help me please as its driving me crazy.
Thanks in advance
Al
0
Comment
Question by:JazzMan209
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 8126710
I don't know for certain why this is failing, but it probably relates to how IE is intepretting keystrokes.  The TAB key in particular works in a 'stateful' way in that IE remember the last hyperlink that was selected and moves to the next one from there.  Even a refresh of the page does not make it 'lose it memory'.  However, if you go to another page and then go to the original, then the first TAB will highlight the Address bar and the next will highlight the first link, etc.

There is a much better way to do this.  It is possible to open a browser and directly access each item in it, without resorting to this kind of keystroke silliness.  If you give me the URL of the page you are messing with and describe what you want to do, I can probably show you a 5-line JScript (executable by a double-click of a desktop item) that will do what you want -- with no IDISPATCH complicated stuff.

-- Dan
0
 

Expert Comment

by:errorx666
ID: 8126891
Possible solution:
When you physically press tab on the browser, the first tab message is sent to the parent browser window which sets the focus to the address bar; the next tab is sent to the address bar (the window with the focus) which passes the focus to the browser content client.  When you are sending these messages, all the tabs go to the parent browser window, and so the parent browser window just sets the focus to the address bar n times.  Try h=GetFocus(); after the delay following each tab press (or maybe just after the first tab).
0
 

Author Comment

by:JazzMan209
ID: 8129034
Dan:
Dan, that code would be very useful, any arbitary site would do, say I wanted to click the Email button at the top of the Yahoo.com website (link seems to be http://www.yahoo.com/r/m1). That'd be great.
errorx666:
Wouldn't GetFocus just return the handle to IE, which I already have anyway, I tried it but none of the TAB keys seem to get passed if I do it.
Thanks again guys
0
Get your Disaster Recovery as a Service basics

Disaster Recovery as a Service is one go-to solution that revolutionizes DR planning. Implementing DRaaS could be an efficient process, easily accessible to non-DR experts. Learn about monitoring, testing, executing failovers and failbacks to ensure a "healthy" DR environment.

 
LVL 1

Expert Comment

by:Hermetic
ID: 8138546
You should probably use the SendInput api instead of sending the keypresses directly.
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 300 total points
ID: 8205929
Sorry I took so long... I just ran across this in my TO list.  
1) Copy this text and place it into a file named YahooLogin.HTA
2) Edit the text line 4 to use your password
3) Double-click the HTA file in the Explorer
4) Click the top button, then wait a while, then click the second button

The basic techique is to open a second window to s specified URL, then access that window's DOM.  For instance,
     gwndWindow.document.all.passwd.value= sYahooPswd;
sets text into a text input box.  And...
     gwndWindow.document.all.Login.click();
executes the code that normally gets executed when the user clicks a buttone whos name is "Login"

So, theere it is!  You can access any input on the page and you can execute any desired action.   You can control the page like a puppetmaster!

-- Dan

-=-==-=-=--==-=-=--=-==- start of file  YahooLogin.HTA
<html>
<script>
var sTargetURL= "http://www.yahoo.com/r/m1";
var sYahooPswd= "mypassword";  // <<<<<<<<<<<--- your password here!
var gwndWindow= null;
//---------------------------------------------
function WaitForBrowserWindowReady()
{
     var fReady= false;
     var oNow= new Date();
     var nMaxTick= oNow.getTime()+ 60000; // 60 seconds
     while ( !fReady ) {
          if ( gwndWindow ) {
               if ( gwndWindow.document.readyState == "complete" )  {
                    fReady= true;
               }
          }
          oNow= new Date();
          if ( oNow.getTime() > nMaxTick ) {
               alert( "page load timed out" );
               break;
          }
     }
     return( fReady );
}
//---------------------------------------------
function OpenBrowserWindow( sURL ) {
     if ( gwndWindow ) {
          try      { gwndWindow.location= sURL;     }
          catch(e) { gwndWindow= null; }
     }
     gwndWindow= window.open( sURL, "Working" );
     var fReady= WaitForBrowserWindowReady();
     return( fReady );
}

function DoOpenWindow() {
     OpenBrowserWindow( sTargetURL );
}
//---------------------------------------------
//--------- i found these by looking at the Yahoo page source
// <input name="passwd" type="password" size="17" maxlength="32">
// <input type=submit name=Login value=Continue></td></tr>

function DoYahooLogin() {
     gwndWindow.document.all.passwd.value= sYahooPswd;
     gwndWindow.document.all.Login.click();
}
</script>
<CENTER>
<H1>Tester!</H1>
<input type=button value="Click to open a Yahoo window" onclick="DoOpenWindow();"><br>
<input type=button value="Auto login to Yahoo" onclick="DoYahooLogin();">
</CENTER>
</html>
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8501489
ping
0
 

Author Comment

by:JazzMan209
ID: 8502305
Cheers Dan, this worked nicely.
I'd like to add though to anyone who had a similar problem, to do this correctly you can use Spy++ and see that there are child windows inside the main window, by finding the child handles
FindWindowEx(...) I think it is, and then pass the keypresses to the children instead of the parent the keypresses are then accepted, though this type of input only works for certain progs.
Thanks again Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8502399
Glad I could help.  
The input boxes, buttons, checkboxes and other controls in a browser window are not "real" windows and cannot be located using FindWindow or GetWindow(...,GW_CHILD...), etc.  Exception: For some reason, comboboxes and listboxes are 'native windows'  The FindWindow technique works great for locating top-level windows.

-- Dan
0
 

Author Comment

by:JazzMan209
ID: 8503887
Yea, what I meant though was that

HWND GeneralHWND = NULL;

GeneralHWND = FindWindow(NULL,
                       "Explorer Top Bar Text");
HWND ChildWin1 = FindWindowEx(GeneralHWND ,NULL,
                     "Shell DocObject View",NULL);
HWND ChildWin2 = FindWindowEx(ChildWin1, NULL ,
                    "Internet Explorer_Server" , NULL);

for(int i=0; i<12; i++)
{
      PostMessage(ChildWin2, WM_KEYDOWN, VK_TAB, 15);
}
PostMessage(ChildWin2,WM_KEYDOWN, VK_RETURN, 29);

That this would successfully select the 12th available link on the IE Window and click it.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8505225
Yes, that would select the twelfth control (link OR button OR edit box, etc...) assuming that the browser was in a known state (i.e., having just loaded a new page that is always the same and that no user has interacted with it by selecting, say the third hyperlink and that the IE address bar is visible and that no state information has caused, say the 7th control to be disabled.... etc.).  If any one of those things vary, then the program will not work as intended -- in fact, it will fail in exactly the way described in this question.

When the programmers provide an alternative way to simulate user interaction -- as with object.click() or object.value= in the IE DOM -- it is invariably the best, most reliable technique to use.  But for a quick-and-dirty utility, sometimes throwing Alt-keys and tab keys at a window will work just fine.

-- Dan
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you have ever found yourself doing a repetitive action with the mouse and keyboard, and if you have even a little programming experience, there is a good chance that you can use a text editor to whip together a sort of macro to automate the proce…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question