public async Task Play(String msg) { await Task.Run(async() => { talkTextBox.EmulateChangeText(msg); if (!saveButton.IsEnabled) { while (!saveButton.IsEnabled) { await Task.Delay(100); } } playButton.EmulateClick(); await Task.Delay(1000); if (!saveButton.IsEnabled) { while (!saveButton.IsEnabled) { await Task.Delay(100); } } }); }
async void consumeMessage() { await initTask; var lastPlay = DateTime.Now; var talkCooldown = TimeSpan.FromSeconds(0.3); while (!cancelled) { string message; if (!messageQueue.TryTake(out message, 1000)) { continue; } // VOICEROID2が発話中の時は「先頭」ボタンが無効になるので、それを利用して発話中かどうかを判定します while (!beginButton.IsEnabled) { Thread.Sleep(50); // spin wait } var now = DateTime.Now; if ((now - lastPlay) < talkCooldown) { Thread.Sleep(talkCooldown - (now - lastPlay)); } lastPlay = DateTime.Now; stopButton.EmulateClick(); talkTextBox.EmulateChangeText(message); beginButton.EmulateClick(); playButton.EmulateClick(); } }
/// <summary> /// https://hgotoh.jp/wiki/doku.php/documents/voiceroid/tips/tips-003 様より /// </summary> // テキスト転記と再生ボタン押下 public static void Talk(string talkText) { if (hWnd == IntPtr.Zero) { hWnd = GetVoiceroid2HWnd(); } if (hWnd == IntPtr.Zero) { Console.WriteLine("VOICEROID2を起動してください。"); return; } try { // プロセスに接続する var app = new WindowsAppFriend(hWnd); // テキスト入力欄と再生ボタンを特定する var uiTreeTop = WindowControl.FromZTop(app); var textEditView = uiTreeTop.GetFromTypeFullName("AI.Talk.Editor.TextEditView")[0].LogicalTree(); var talkTextBox = new WPFTextBox(textEditView[4]); var playButton = new WPFButtonBase(textEditView[6]); // テキストを入力し、再生する talkTextBox.EmulateChangeText(talkText); playButton.EmulateClick(); } catch (Exception e) { Console.WriteLine(e); hWnd = IntPtr.Zero; } }
public void RegisterFemaleSns() { Thread.Sleep(1000); dynamic window = _app.Type <Application>().Current.MainWindow; var nameTextBox = new WPFTextBox(window.Name); nameTextBox.EmulateChangeText("Peach"); Thread.Sleep(1000); var sexRadio = new WPFButtonBase(window.Female); sexRadio.EmulateClick(); Thread.Sleep(1000); var reasonComboBox = new WPFComboBox(window.Reason); reasonComboBox.EmulateChangeSelectedIndex(2); Thread.Sleep(1000); var registerBtn = new WPFButtonBase(window.RegisterBtn); registerBtn.EmulateClick(); var outputTxtBlock = new WPFTextBlock(window.Output); Assert.AreEqual(outputTxtBlock.Text.Replace("\n", ""), $"登録者名: Peach\n性別: 女性\n登録する経緯: SNSで見た".Replace("\n", "")); Thread.Sleep(1000); }
public void TestEmulateChangeText() { WPFTextBox textBox = new WPFTextBox(Target); textBox.EmulateChangeText(TestValue); string textBoxText = textBox.Text; Assert.AreEqual(TestValue, textBoxText); }
public void TestEmulateChangeTextAsync() { WPFTextBox textBox = new WPFTextBox(Target); CallRemoteMethod("AttachChangeTextEvent", textBox); textBox.EmulateChangeText(TestValue, new Async()); ClickNextMessageBox(); string textBoxText = textBox.Text; Assert.AreEqual(TestValue, textBoxText); }
public void コントロール特定2() { AppVar main = _app.Type <Application>().Current.MainWindow; var tab = new WPFTabControl(main.LogicalTree().ByType <TabControl>().Single()); tab.EmulateChangeSelectedIndex(1); var userControl = main.LogicalTree().ByType("WpfApplication.DemoItemsControl").Single(); var listBox = new WPFListBox(userControl.LogicalTree().ByType <ListBox>().Single()); var textBoxAge = new WPFTextBox(listBox.GetItem(2).VisualTree().ByBinding("Age").Single()); textBoxAge.EmulateChangeText("50"); }
private void SetTextAndSave(string outputFilePath, string text) { string t = _libraryName + _promptString + text; if (_queue.Count == 0) { WPFTextBox textbox = new WPFTextBox(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 5, 3, 0, 2)); textbox.EmulateChangeText(t); Save(outputFilePath); } else { _queue.Enqueue(t); } }
public void Clear() { dynamic window = _app.Type <Application>().Current.MainWindow; var nameTextBox = new WPFTextBox(window.Name); nameTextBox.EmulateChangeText(string.Empty); var sexRadio = new WPFButtonBase(window.Male); sexRadio.EmulateClick(); var reasonComboBox = new WPFComboBox(window.Reason); reasonComboBox.EmulateChangeSelectedIndex(-1); }
internal virtual void SetText(string text) { text = text.Trim() == "" ? "." : text; string t = _libraryName + _promptString + text; if (_queue.Count == 0) { WPFTextBox textbox = new WPFTextBox(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 5, 3, 0, 2)); textbox.EmulateChangeText(t); Play(); } else { _queue.Enqueue(t); } }
private void timer_Elapsed(object sender, EventArgs e) { _timer.Stop(); // 途中の処理が重いため、タイマーをいったん止める lock (_lockObject) { _tickCount += _timer.Interval; // ここからプロセス間通信&UI操作(重い) //WPFButtonBase playButton = new WPFButtonBase(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 6, 3, 0, 3, 0)); WPFButtonBase playButton = new WPFButtonBase(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 6, 3, 0, 0, 0, 1, 3, 0)); var d = playButton.LogicalTree(); System.Windows.Visibility v = (System.Windows.Visibility)(d[2])["Visibility"]().Core; // [再生]の画像の表示状態 // ここまで if (v != System.Windows.Visibility.Visible && !_isRunning) { _isRunning = true; } else // 再生開始から 500 ミリ秒程度経過しても再生ボタンがうまく確認できなかった場合にも完了とみなす if (v == System.Windows.Visibility.Visible && (_isRunning || (!_isRunning && _tickCount > 500))) { if (_queue.Count == 0) { StopSpeech(); return; // タイマーが止まったまま終了 } else { // 喋るべき内容が残っているときは再開 string t = _queue.Dequeue(); // WPFTextBox textbox = new WPFTextBox(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 6, 3, 0, 2)); WPFTextBox textbox = new WPFTextBox(_root.IdentifyFromLogicalTreeIndex(0, 4, 3, 6, 3, 0, 0, 0, 1, 2)); textbox.EmulateChangeText(t); playButton.EmulateClick(); _isPlaying = true; _isRunning = false; _tickCount = 0; } } _timer.Start(); } }
private void SetEffect(EffectType t, float value) { WPFTextBox textbox = new WPFTextBox(_root.IdentifyFromLogicalTreeIndex(0, 4, 5, 0, 1, 0, 3, 0, 6, (int)t, 0, 7)); textbox.EmulateChangeText($"{value:0.00}"); }
public void WPF() { var app = new WindowsAppFriend(Process.Start("Wpf.exe")); var window = app.Type().System.Windows.Application.Current.MainWindow; //ガタガタ言わずにx:Name使えばいいじゃん。 var _textBox = new WPFTextBox(window._textBox); _textBox.EmulateChangeText("x:Name最高!"); //嫌って言う人いるから頑張ったよ。 AppVar windowAppVar = window; var logicalTree = windowAppVar.LogicalTree(); var textBox = new WPFTextBox(logicalTree.ByBinding("Memo").ByType<System.Windows.Controls.TextBox>().Single()); var textBlock = new WPFTextBlock(logicalTree.ByBinding("Memo").ByType<System.Windows.Controls.TextBlock>().Single()); var buttonModal = new WPFButtonBase(logicalTree.ByBinding("CommandModal").Single()); var buttonModalSequential = new WPFButtonBase(logicalTree.ByBinding("CommandModalSequential").Single()); var buttonModeless = new WPFButtonBase(logicalTree.ByBinding("CommandModeless").Single()); var listBox = new WPFListBox(logicalTree.ByBinding("Persons").Single()); //VisualTreeにしか現れない要素は気を付けて var item = listBox.GetItem(20); var itemText = new WPFTextBlock(item.VisualTree().ByBinding("Name").Single()); //これでもダメな場合は工夫してね! Process.GetProcessById(app.ProcessId).Kill(); }
static void Main(string[] args) { // プロセスの取得 Process[] ps = Process.GetProcessesByName("VoiceroidEditor"); if (ps.Length == 0) { Console.Error.WriteLine("VOICEROID2を起動してください"); return; } // WindowsAppFriendをプロセスから作成する // 接続できない旨のエラーの場合、別のプロセスでテスト対象のプロセスを操作している場合がある。 // TestAssistant使いながら動作できないようなので、注意。 var app = new WindowsAppFriend(ps[0]); var mainWindow = WindowControl.FromZTop(app); // 茜ちゃんしゃべる WPFTextBox txtMessage = new WPFTextBox(mainWindow.IdentifyFromLogicalTreeIndex(0, 4, 3, 5, 3, 0, 2)); txtMessage.EmulateChangeText("アカネチャンカワイイヤッタ"); WPFButtonBase btnPlay = new WPFButtonBase(mainWindow.IdentifyFromLogicalTreeIndex(0, 4, 3, 5, 3, 0, 3, 0)); btnPlay.EmulateClick(); // ステータスバーを監視してしゃべり終わるまでまつ String sts; do { System.Threading.Thread.Sleep(500); var txtStatusItem = mainWindow.IdentifyFromVisualTreeIndex(0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0).Dynamic();; sts = txtStatusItem.Text.ToString(); } while (!sts.Equals("テキストの読み上げは完了しました。")); // 保存ボタン押下 // ダイアログが表示されると引数なしのEmulateClickだと止まるのでAsyncオブジェクトを渡しておく var async = new Async(); WPFButtonBase btnSave = new WPFButtonBase(mainWindow.IdentifyFromLogicalTreeIndex(0, 4, 3, 5, 3, 0, 3, 5)); btnSave.EmulateClick(async); // 音声保存ダイアログ操作 var dlgSaveWav = mainWindow.WaitForNextModal(); var asyncSaveWin = new Async(); WPFButtonBase buttonOK = new WPFButtonBase(dlgSaveWav.IdentifyFromLogicalTreeIndex(0, 1, 0)); buttonOK.EmulateClick(asyncSaveWin); // ファイル名指定後の保存 var asyncSaveFile = new Async(); var dlgFileSave = dlgSaveWav.WaitForNextModal(); NativeEdit editFileName = new NativeEdit(dlgFileSave.IdentifyFromZIndex(11, 0, 4, 0, 0)); editFileName.EmulateChangeText(System.DateTime.Now.ToString("yyyymMMddhhmmss") + ".wav"); NativeButton btnSaveOk = new NativeButton(dlgFileSave.IdentifyFromDialogId(1)); btnSaveOk.EmulateClick(asyncSaveFile); // 情報ダイアログが表示されるまで待機してOKを押下 var dlgInfo = WindowControl.WaitForIdentifyFromWindowText(app, "情報"); NativeButton btn = new NativeButton(dlgInfo.IdentifyFromWindowText("OK")); btn.EmulateClick(); //非同期で実行した保存ボタン押下の処理が完全に終了するのを待つ asyncSaveFile.WaitForCompletion(); asyncSaveWin.WaitForCompletion(); async.WaitForCompletion(); // 葵ちゃんに切り替えてしゃべる // UIAutomationだと葵ちゃん切り替えが行えない。 WPFListView ListView = new WPFListView(mainWindow.IdentifyFromLogicalTreeIndex(0, 4, 3, 3, 0, 1, 0, 2)); ListView.EmulateChangeSelectedIndex(1); txtMessage.EmulateChangeText("オネエチャンカワイイヤッタ"); btnPlay.EmulateClick(); ListView.EmulateChangeSelectedIndex(0); }
public void コントロール特定() { // STEP1. // 複数のウィンドウ取得方法がある。 // 1.最前面のウィンドウを取得する。 var main = WindowControl.FromZTop(_app); // 2.アセンブリの正式名称を指定してウィンドウを取得する。 var main2 = WindowControl.IdentifyFromTypeFullName(_app, "WpfApplication.MainWindow"); // 3.ウィンドウタイトルを指定してウィンドウを取得する。 var main4 = WindowControl.IdentifyFromWindowText(_app, "Friendly Handson"); // 4.Application からアクセスしてメインウィンドウ=ターゲットのウィンドウを取得する。 var appWindow = _app.Type <Application>().Current.MainWindow; var main3 = new WindowControl(appWindow); // STEP2. // LogicalTree から対象のコントロールを取得する。 // ここで取得できるLogicalTree はFriendly 独自に列挙している。 var logical = main2.LogicalTree(); // .ByType<T>() で指定した型のコントロールを列挙する。 // .Single() で一つのコントロール用データに変換する。 AppVar tabCore = logical.ByType <TabControl>().Single(); var tabControl = new WPFTabControl(tabCore); tabControl.EmulateChangeSelectedIndex(1); tabControl.EmulateChangeSelectedIndex(0); // STEP3. // 独自コントロール(ユーザーコントロール)を取得する。 // 基本的にユーザーコントロールは1画面に一つなので.ByType() がおすすめ。 AppVar demoSimpleControlCore = logical.ByType("WpfApplication.DemoSimpleControl").Single(); // ここで取得するLogicalTree はDemoSimpleControl.xaml のルート要素から取得できるものとなる。 var innerLogicalTree = demoSimpleControlCore.LogicalTree(); // こんな方法でアクセスもできる。 var x = demoSimpleControlCore.Dynamic(); var fullNameCore = x.GetType().FullName; string fullName = fullNameCore; Console.WriteLine(fullName); // 動作は上と同じ。 //AppVar type = demoSimpleControlCore["GetType"](); //var fullNameCore = type["FullName"](); //string fullName = (string)fullNameCore.Core; // ユーザーコントロール配下のテキストボックスへアクセスする。 // x:Name をつけていればコントロール名でアクセス可能。 var textBox = new WPFTextBox(demoSimpleControlCore.Dynamic()._textBox); textBox.EmulateChangeText("abc"); // STEP4. // Window のDataContext(ViewModel)からコントロールを取得する。 var textBoxMail = new WPFTextBox(innerLogicalTree.ByBinding("Mail").Single()); textBoxMail.EmulateChangeText("[email protected]"); // Assertをかける。 Assert.AreEqual("[email protected]", textBoxMail.Text); // ComboBox を取得する。 var comboBoxLanguage = new WPFComboBox(innerLogicalTree.ByBinding("Language").Single()); comboBoxLanguage.EmulateChangeSelectedIndex(1); // GUIのテストシナリオ // https://github.com/Ishikawa-Tatsuya/WPFFriendlySampleDotNetConf2016 // シナリオテストをする場合、Driver は開発者、シナリオは開発者以外がかけるようになっている。 }