2010-12-15 99 views
0

J'ai une application WPF en cours de démarrage à partir d'une application de ligne de commande. J'essaie de faire une automatisation simple (obtenir/définir du texte, cliquer sur certains boutons, etc.). Je n'arrive pas à trouver les fenêtres enfants dans WPF.user32.dll FindWindowEx, recherche d'éléments par nom de classe sur la fenêtre WPF distante

J'ai des modèles de travail avec WPF et UIA Framework, WinForms et WinAPI, mais je n'arrive pas à faire en sorte que WinAPI et WPF fonctionnent correctement. J'ai utilisé UISpy, WinSpy ++, Winspector, l'application UIA Verify pour regarder les contrôles, etc, mais ils ne semblent pas porter les mêmes informations pour WPF que WinForms. Par exemple, dans l'application WinForms, je vois une zone de texte avec un nom de classe "WindowsForms10.EDIT.app.0.33c0d9d" lorsque je regarde via les outils d'espionnage. L'application UIA Automation Verify est la seule à reconnaître l'existence de l'élément et à signaler "TextBox". Donc, ma question est de savoir comment trouver le bon nom de classe à passer ou y a-t-il un chemin plus facile pour trouver les éléments enfants?

// 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); 

et voici les importations de user32.dll J'utilise:

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); 


} 

Répondre

3

Si vous souhaitez automatiser WPF, vous doit utiliser l'UI Automation, pas la « vieille chose du passé "API windows :-).

Il y a une bonne introduction sur l'automatisation de l'interface utilisateur ici: Bugslayer: GUI Control to Major Tom

Il y a aussi un intéressant projet open source nommé « White » qui tire parti de l'automatisation de l'interface utilisateur: White on codeplex. Il y a quelques échantillons là-dedans si vous voulez creuser dedans.

+0

Je préfère de loin la route d'UI Automation. J'ai ceci fonctionnant dans WPF et l'automation d'UI, aussi bien que WinForms et WinAPI. Une partie de cet exercice consistait à déterminer si oui ou non (WPF avec WinAPI) pourrait être fait. De commentaires ci-dessous, il semble que pour WinForms et les applications précédentes, WinAPI est une option, WPF et au-delà d'utiliser UI Automation. Merci! – ajberry

+0

Eh bien, UI Automation fonctionne également pour Windows et Winforms, car il peut s'appuyer sur le SDK MSAA (Accessibility), mais mon expérience montre que le support n'est pas totalement cohérent sur toutes les plateformes. Mais oui, l'automatisation de l'interface utilisateur est vraiment la voie à suivre pour WPF plus, si vous possédez le code côté serveur, vous pouvez équiper vos propres contrôles et UIElements avec des homologues d'automatisation qui facilitent la gestion des clients externes. –