2016-05-09 5 views
-1

私はいくつかのタスクを自動化しています。「SendMessage」を使用して名前を付けて保存ダイアログボックスの「編集」ボックスに文字列を送信する必要があります。 "Save"ボタン( "SendMessage"と同様)を押すと、編集ボックスに正しく渡された文字列が以前にそこにあった文字列に変わる以外は、すべて正常に動作します。SendMessage WM_SETTEXT文字列の変更

+0

は、UIオートメーションを使用する方が良いと思いませんか? –

+0

ターゲットアプリケーションがバグです。おそらく、キーボードメッセージのみに応答して入力を処理/検証します。標準のEDITコントロールは正しいテキストを表示しますが、アプリケーションは変更を認識しません(マウスを使用してEDITコントロールにテキストを貼り付けると同じ問題が発生する可能性があります)。これはあなた自身がバグのコードを書くべきではありません。メッセージを送信して偽の入力を停止します。適切なツール、[UI Automation](https://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx)を使用してください。 – IInspectable

+0

@IInspectableターゲットアプリケーションが標準の名前を付けて保存ダイアログ( 'GetSaveFileName()'または 'IFileSaveDialog')を使用している場合、キーボード入力に応答してファイル名の処理/検証を行うダイアログは適用されませんどのようにそれがそこにあったかにかかわらず、編集コントロール内のファイル名に関係なく、アプリに。 –

答えて

-1

最後に、いくつかのkeybd_eventsを使ってUI Automationで編集ボックスを設定することができました。 UIオートメーションのSetValueメソッドのみを使用できませんでした。最初に定義済みのパスを削除し、Ctrl + Aを押して送信したパスを選択しなければなりませんでした。ここにコードがあります。

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

私は同じ問題を持っていたと私は私の完全なコードの下に、編集コンポーネントにキーストロークをシミュレートすることで解決:

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