Link to home
Start Free TrialLog in
Avatar of bchoor
bchoorFlag for United States of America

asked on

Using User32.dll FindWindow/FindWindowEx in .NET

I'm trying to get the handle of a control in another application. If I use SPY++ (Microsoft one) to point to the control in the target application, then I am able to find the control. Without using SPY++, .NET code is finding it. Code I'm using is the generic implementation from http://www.pinvoke.net/default.aspx/user32.FindWindow

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className,  IntPtr windowTitle);

Calling it:
intptr windowhandle = findwindow("classname", "windowname");
intptr objecthandle = findwindowex(windowhandle, intptr.zero, "classname", intptr.zero);

As I said above, it works great once SPY++ is used, as if it forces the target application to repaint/redraw/expose the control. Without using SPY++ on the freshly opened target application, findwindowex doesn't see the control. I've tried enumwindows (and variations of the same i.e. *ex). I tried "UpdatedWindow" and "RedrawWindow"

What is SPY++ doing to force the app to expose the function? Another alternative I considered (again, not sure how feasible), would be inject a dll hook and from the injected dll enumerate controls and push those window handles to a shared memory area (or a file)

Any help is appreciated. Thanks!

ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
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
Just to confirm, are you saying that something like the following does not work for you? Both "hWnd" and "hCtl" hold value when I execute the code below with the document open in TextPad. "windowTitle" is the text you see in the title bar--verbatim. This is equivalent to the Text property of a Form in .NET.
public partial class Form1 : Form
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        IntPtr hWnd;
        IntPtr hCtl;

        hWnd =
            FindWindow("TextPad5",
            @"TextPad - C:\output2.txt");

        hCtl = FindWindowEx(hWnd, IntPtr.Zero, "MDIClient", IntPtr.Zero);
    }
}
}

Open in new window

Avatar of bchoor

ASKER

@kaufmed: that's correct. As I said earlier, once I use SPY++ on the target application - everything works fine. I'm guessing that the code I'm using is good. I've also used enumchildwindows, and I'll get a count of 12, when I use SPY++, the count goes to 37.

Also guys,
I have tried my code on an instance of notepad (as a target application), and all worked well. So, I'm thinking it might be an issue with how the target application is rendering the controls - and that SPY++ might be doing something.

@IdleMind - I know you said that SPY++ wasn't doing anything. I might be justifying causality on a mere coincidence - since the target application only exposes the controls after I have used SPY++ on it (using the target cursor thingy onto the main window).

On a side note, I'm using VS 2008 on W7 x64.
Can you name the target app and/or give some screenshots?
Avatar of bchoor

ASKER

Turns out that SPY++ isn't really 'doing' anything as you said. Just confirmation of this forced me to dig a little more, and my presumption is that the application paints a bitmap (sort of) of the form, and then on idle clock cycles or specific mouse event it fills in the controls - I'm sure I'm missing something. The app is a proof of concept so I should be OK, at least for the prototyping piece.

I might have to do a loop until that control becomes available.

That sounds pretty weird!...and something that would have been impossible for us to determine without the app in front of us.  =\

Glad you figured it out.