2016-05-09 1 views
-1

J'automatise certaines tâches J'ai besoin d'envoyer une chaîne à "Modifier" dans la boîte de dialogue Enregistrer sous en utilisant 'SendMessage'. Tout fonctionne correctement sauf que lorsque vous appuyez sur le bouton "Enregistrer" (avec 'SendMessage' aussi) la chaîne qui a été passée correctement à la boîte d'édition change en chaîne qui était précédemment là ... Des idées?SendMessage WM_SETTEXT changements de chaîne

+0

Ne serait-il préférable d'utiliser UI Automation? –

+0

Votre application cible est boguée. Il traite/valide probablement l'entrée en réponse aux messages du clavier seulement. Alors que le contrôle EDIT standard affiche le texte correct, l'application ignore tout changement (vous verrez probablement le même problème lorsque vous collez du texte dans le contrôle EDIT à l'aide de la souris). Cela ne signifie pas que vous devriez écrire du code bogué vous-même. Arrêtez de simuler l'entrée en envoyant des messages. Utilisez le bon outil: [UI Automation] (https://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx). – IInspectable

+0

@IInspectable si l'application cible utilise une boîte de dialogue Enregistrer sous standard ('GetSaveFileName()' ou 'IFileSaveDialog'), ce que vous dites à ce sujet traiter/valider le nom de fichier en réponse à l'entrée au clavier ne s'applique pas à l'application quel que soit le nom du fichier dans le contrôle d'édition, indépendamment de la façon dont il est arrivé là. –

Répondre

-1

Enfin, j'ai réussi à définir la boîte d'édition avec UI Automation avec certains keybd_events. L'utilisation de la méthode SetValue d'UI Automations n'a pas abouti. Je devais d'abord supprimer le chemin prédéfini et après tout sélectionner le chemin que j'ai envoyé en appuyant sur Ctrl + A. Voici le code.

Do 
     Ret = FindWindow(vbNullString, "Save As") 
     If Ret <> 0 Then 
      ChildRet = FindWindowEx(Ret, 0, "DUIViewWndClassName", vbNullString) 
      ChildRet = FindWindowEx(ChildRet, 0, "DirectUIHWND", vbNullString) 
      ChildRet = FindWindowEx(ChildRet, 0, "FloatNotifySink", vbNullString) 
      ChildRet = FindWindowEx(ChildRet, 0, "ComboBox", vbNullString) 
      ChildRet = FindWindowEx(ChildRet, 0, "Edit", vbNullString) 
      If ChildRet <> 0 Then 
       Thread.Sleep(3000) 
       keybd_event(VK_DELETE, MapVirtualKey(VK_DELETE, 0), 0, 0) 
       Thread.Sleep(100) 
       keybd_event(VK_DELETE, MapVirtualKey(VK_DELETE, 0), 2, 0) 

       elementEdit = AutomationElement.FromHandle(ChildRet) 
       elementEditTextBox = elementEdit.GetCurrentPattern(ValuePattern.Pattern) 
       elementEdit.SetFocus() 
       elementEditTextBox.SetValue(pathToSave) 

       keybd_event(VK_LCONTROL, MapVirtualKey(VK_LCONTROL, 0), 0, 0) 
       keybd_event(VK_KEY_A, MapVirtualKey(VK_KEY_A, 0), 0, 0) 
       Thread.Sleep(100) 
       keybd_event(VK_KEY_A, MapVirtualKey(VK_KEY_A, 0), 2, 0) 
       keybd_event(VK_LCONTROL, MapVirtualKey(VK_LCONTROL, 0), 2, 0) 

       Thread.Sleep(1000) 

       SaveAsWindowElements = AutomationElement.FromHandle(Ret).FindAll(TreeScope.Children, Condition.TrueCondition) 
       For Each element In SaveAsWindowElements 
        If element.Current.Name = "Save" Then 
         elementSaveButton = element.GetCurrentPattern(InvokePattern.Pattern) 
         elementSaveButton.Invoke() 
        End If 
       Next 
      End If 
     Else 
      Thread.Sleep(1000) 
     End If 
    Loop 
-1

J'ai eu le même problème et je résolus en simulant une combinaison de touches dans le composant d'édition, en dessous de mon code complet:

[DllImport("user32.dll")] 
private static extern IntPtr GetForegroundWindow(); 

[DllImport("user32.dll")] 
static extern bool SetFocus(IntPtr hWnd); 

[DllImport("user32.dll", SetLastError = false)] 
public static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem); 

[DllImport("USER32.DLL")] 
public static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, string lParam); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); 

public const Int32 VK_SPACE = 0x20; 
public const Int32 BM_CLICK = 0x00F5; 
public const uint WM_SETTEXT = 0x000C; 
enum KEYBOARD_MSG : uint 
{ 
    WM_KEYDOWN = 0x100, 
    WM_KEYUP = 0x101 
} 

public static async void SaveFileName(string text) 
{ 
    IntPtr exportWindow = GetForegroundWindow(); 
    IntPtr comboHandle = GetDlgItem(exportWindow, 13006); //check this control ID is correct 
    IntPtr editHandle = GetDlgItem(comboHandle, 1001); //check this control ID is correct 
    SetControlText(comboHandle, 1001, text); //check this control ID is correct 
    SetFocus(editHandle); 
    //need to simulate a keystroke or the path won't come throught 
    PostMessage(editHandle, (uint)KEYBOARD_MSG.WM_KEYDOWN, VK_SPACE, 0); 
    ClickControl(exportWindow, "&Save"); 
} 

/// <summary> 
/// Sets the text value of a control using Win32API 
/// </summary> 
/// <param name="windowHandle">Handle of the windows the control belongs to</param> 
/// <param name="controlId">ID of the control, to get it use WinSpy and convert the value fron Hex to Decimal</param> 
/// <param name="text">String to be set</param> 
private static void SetControlText(IntPtr windowHandle, int controlId, string text) 
{ 
    IntPtr iptrHWndControl = GetDlgItem(windowHandle, controlId); 
    HandleRef hrefHWndTarget = new HandleRef(null, iptrHWndControl); 
    SendMessage(hrefHWndTarget, WM_SETTEXT, IntPtr.Zero, text); 
} 

/// <summary> 
/// Clicks a button using Win32API 
/// </summary> 
/// <param name="windowHandle">Handle of the windows the control belongs to</param> 
/// <param name="buttonText">Label of the button, to get it correctly use WinSpy</param> 
private static void ClickControl(IntPtr windowHandle, string buttonText) 
{ 
    IntPtr export = FindWindowEx(windowHandle, IntPtr.Zero, null, buttonText); 
    SendMessage(export, BM_CLICK, IntPtr.Zero, IntPtr.Zero); 
}