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!

LVL 10
bchoorAsked:
Who is Participating?
 
Mike TomlinsonConnect With a Mentor Middle School Assistant TeacherCommented:
Can you give some more specific example of what you're doing?  SPY++ isn't doing anything to "reset" the app...  =\
0
 
käµfm³d 👽Commented:
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

0
 
bchoorAuthor Commented:
@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.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Can you name the target app and/or give some screenshots?
0
 
bchoorAuthor Commented:
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.

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
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.
0
All Courses

From novice to tech pro — start learning today.