user32.dll FindWindowEx, finding elements by classname on remote WPF window
I have a WPF application that is being started from a command-line application.
I am trying to do some simple automation (get/set text, click some buttons, etc). I cannot seem to find any of the child windows in WPF.
I have working models with WPF and UIA Framework, WinForms and WinAPI, but cannot seem to get WinAPI and WPF to play nicely.
I have used UISpy, WinSpy++, Winspector, the UIA Verify app to look at the controls, etc, but they do not seem to carry the same information for WPF as WinForms.
For example, in the WinForms app, I see a textbox with a ClassName of "WindowsForms10.EDIT.app.0.33c0d9d" when I look via the spy tools. The UIA Automation Verify app is the only one to acknowledge the element exists and reports "TextBox".
So, my question is how do I find the correct class name to pass or is there an easier route to find the child elements?
// does not work in wpf
IntPtr child = NativeMethods.FindWindowEx(parent, prevElement, "TextBox", null);
// works in winforms
IntPtr child = NativeMethods.FindWindowEx(parent, prevElement, "WindowsForms10.EDIT.app.0.33c0d9d", null);
and here is the user32.dll imports I am using:
public class NativeMethods
{
public const int WM_SETTEXT = 0x000C;
public const int WM_GETTEXT = 0x000D;
public const uint CB_SHOWDROPDOWN = 0x014F;
public const uint CB_SETCURSEL = 0x014E;
public const int BN_CLICKED = 245;
public const uint WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll", SetLastError = true)开发者_运维知识库]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("user32.dll", SetLastError = false)]
public static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, string lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);
}
If you want to automate WPF, you must use the UI Automation, not the "old thing of the past" windows API :-).
There is a good introduction on UI automation here: Bugslayer: GUI Control to Major Tom
There is also an interesting open source project named "White" that leverages UI automation: White on codeplex. There are some samples in there if you want to dig in.
精彩评论