Link to home
Start Free TrialLog in
Avatar of JazzMan209
JazzMan209

asked on

Passing keypresses to other windows (internet explorer)

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
Avatar of DanRollins
DanRollins
Flag of United States of America image

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
Avatar of errorx666
errorx666

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).
Avatar of JazzMan209

ASKER

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
You should probably use the SendInput api instead of sending the keypresses directly.
ASKER CERTIFIED SOLUTION
Avatar of DanRollins
DanRollins
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
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
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.
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