0

In this below code, hWnd is the "URL Handle" in Spy++:

'WorkerW -> ReBarWindow32 -> Address Band Root -> Edit' 

The URL is what I want to open.

I use the same method to open tabs in IE7 and send hWnd appropriately. I see that this works fine for IE7 and not for IE8. In IE8, it only opens 4 tabs and then IE8 stops honoring the SendMessage request; however, I can still press CTRL+T OR ALT+Enter to open new tabs in IE8 (so IE8 is still responsive).

/**
 * Open URL in IE (open new tab when newTab is true)
 * hWnd is found at runtime 
 **/
private void LaunchURLinIE(IntPtr hWnd, String url, bool newTab = false)
{
    StringBuilder ob = new StringBuilder(url);
    // Type text in the URL window
    SendMessage(hWnd, WM_SETTEXT, 0, ob);
    if (!newTab)
    {   // Press Enter
        SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, 1);
    }
    else
    {   // Press ALT Enter to open new tab
        SendMessage(hWnd, WM_SYSKEYDOWN, VK_RETURN, 1 << 29);
    }
}

My environment is: Windows XP Service Pack 3 [32-bit OS] , IE8 version 8.0.6001.18702

So, is it IE8 or something I am missing?

UPDATE - 1 I have updated comments on the code so that its clear what code does. The above code works perfectly fine for IE7 (tested upto 15 tabs) but with IE8 it only opens upto 4 tabs.

Update - 2 I was able to sove this by using PostMessage instead of SendMessage.

   private void LaunchURLinIE(IntPtr hWnd, String url, bool newTab = false)
    {
        StringBuilder ob = new StringBuilder(url);
        // Type text in the URL window
        SendMessage(hWnd, WM_SETTEXT, 0, ob);
        if (!newTab)
        {   // Press Enter
            PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 1);
        }
        else
        {   // Press ALT Enter to open new tab
            PostMessage(hWnd, WM_SYSKEYDOWN, VK_RETURN, 1 
karephul
  • 1,473
  • 4
  • 19
  • 36
  • CTRL+TAB doesn't really open new tabs. It just switches to the next one like ALT+TAB switches application windows. So if it works to open new windows with ALT+TAB after running the application it could indicate that .. erhm... you've done something wrong. :) – Tedd Hansen Apr 04 '11 at 14:52
  • 1
    You do realize that the `hWnd` is **not** a fixed value, right? You can't just get it one time using Spy++ and use it from then on. Every time the application is closed and re-opened (or the control's handle is re-created), the value will change. – Cody Gray - on strike Apr 04 '11 at 14:57
  • 1
    Why are you trying to directly manipulate IE to open tabs? It is generally simpler and more reliable to use ShellExecute to launch a URL. – Jon Apr 04 '11 at 15:39
  • @Cody - we are trying to control the tabs in a window such that to do similar things app will open tab in existing IE window, otherwise it will open a new IE window. We keep track of IE Handle and then find the "Edit" handle when ever needed – karephul Apr 04 '11 at 15:58
  • I don't know what "whenever needed" means. You aren't supposed to keep track of it at all. That's an implementation detail, not something your code should track. Anyway, as others are trying to tell you, this is the wrong way of doing it for plenty of other reasons, as well. My suggestion is simpler yet: change your IE settings to open new pages in a new tab. UI automation is difficult; no reason to make things unnecessarily complicated. – Cody Gray - on strike Apr 04 '11 at 16:00

2 Answers2

4

You might want to try using the COM exposed by the ShDocVw object which can be found as a .dll named Interop.ShDocVw.dll this contains an InternetExplorerClass interface which allows you to do most IE automation reliably.

I am a contributor to SWAT http://sourceforge.net/projects/ulti-swat/, if you would like some good examples feel free to use our source for IE automation located in SWAT.Core/InternetExplorer.cs

There are alot of problems with your code actually, window handles are hardcoded (why?) also you are only sending a key down, the application usually expects a keydown/keyup combo or sometimes a keydown/keypress/keyup sequence in order for it to be valid. Your application makes it seem as if you are holding down the keys you are sending. You may want to use the FindWindow windows API call which can help you find the window handle at runtime for the window you want to send the messages to.

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
  • Thanks for the advice Ramos, we were planning to look into that but there is lot of code changes to incorporate Interop.ShDocVw.ll and we want a quick fix for this. Why IE8 opens only 4 tabs with above code, why not more? thats what I am trying to diagnose. – karephul Apr 04 '11 at 14:44
  • 1
    Remember that SendMessage sends a message to application and the application fires the correct handler for the message, nowhere is it guaranteed that the application will respond to the message and it is perfectly legal for it to ignore the message altogether. – Jesus Ramos Apr 04 '11 at 14:46
  • @Ramos: Thanks for the advice, I am going to look at this framework more closely. I am sure I will learn quite a few things from it. – karephul Apr 05 '11 at 19:10
1

Should you not send WM_KEYUP as well?

VK_RETURN? Not sure what it does. Would it be better to send CTRL+T keystrokes instead?

  • KEYDOWN CTRL
  • KEYDOWN T
  • KEYUP T
  • KEYUP CTRL

You can find key codes with KeyInterop.VirtualKeyFromKey.

I also think you need to use PostMessage:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

private const UInt32 WM_KEYDOWN = 0x0100;
private const UInt32 WM_KEYUP = 0x0101;

public static void IENewTab(IntPtr HWnd)
{
    PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.LeftCtrl), 0);
    PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.T), 0);
    PostMessage(HWnd, WM_KEYUP, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.T), 0);
    PostMessage(HWnd, WM_KEYUP, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.LeftCtrl), 0);
}
Tedd Hansen
  • 12,074
  • 14
  • 61
  • 97
  • Sending ctrl message to unactive windows is probably not possible, alteast I was not able to do it. So, according to me it will not work. REF: http://stackoverflow.com/questions/5144877/sending-ctrl-s-message-to-a-window – karephul Apr 04 '11 at 18:19
  • @karephul: Yes, it's certainly possible to send keyboard input to unactive windows. To do it, you use the aptly-named [`SendInput` function](http://msdn.microsoft.com/en-us/library/ms646310.aspx). Who told you to use `PostMessage`? It's not for generating keyboard input events. – Cody Gray - on strike Apr 05 '11 at 06:25
  • @Cody: Yes, we can send normal key storkes to inactive or out-of-focus window, but I was not able to send Ctrl message to minmized / inactive or out-of-focus window. I was not able to send Ctrl-S message to a notepad window when its minimized or out-of focus. http://stackoverflow.com/questions/5144877/sending-ctrl-s-message-to-a-window. – karephul Apr 05 '11 at 19:08