努力したWiki

推敲の足りないメモ書き多数

ユーザ用ツール

サイト用ツール


documents:voiceroid:tips:tips-003

VOICEROID2をコマンドラインから操作するための簡単なサンプルソース

2018/06/06

2017/12/15

  • 取りあえず最低限の方法をみえるようにしておけば?という事なのでソースを上げてみる。

概要

VOICEROID2はVOICEROID+/+EXの時とは違い、ウインドウハンドルがアプリケーションウインドウのものしか検索できないようです。

VOICEROID2 VOICEROID+EX 京町セイカ
VOICEROID2のVOICEROIDEDITORはアプリケーションウインドウのハンドルしか取れない VOICEROID+EX 京町セイカはウインドウハンドルが取れる

ですが、UI AutomationのフレームワークからGUIコンポーネントへのアクセスが可能な事がわかりました。
inspect.exeで確認した例

VOICEROID+/+EXもUI AutomationでGUIコンポーネントのAutomationElementオブジェクトを取得できるので、ある問題をクリアできればUI Automationを使う方法に移行できるかもしれません。

UI Automation

要はVOICEROID2 UIのAutomationElementオブジェクトを取る事ができればそのオブジェクトを介して操作が可能、という事。

簡易ソース

琴葉姉妹がいないなら、“琴葉 葵>葵ですよ!”を“結月ゆかり>ゆかりさんですよ!”にでも“紲星あかり>あかりです!”にでも書き換える。

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;
 
namespace vroid2test
{
    class VRoid2test
    {
        static void Main(string[] args)
        {
            talk(GetVoiceroid2hWnd(), "琴葉 葵>葵ですよ!");
        }
 
        // VOICEROID2 EDITOR ウインドウハンドル検索
        static IntPtr GetVoiceroid2hWnd()
        {
            IntPtr hWnd = IntPtr.Zero;
 
            string winTitle1 = "VOICEROID2";
            string winTitle2 = winTitle1 + "*";
            int RetryCount = 3;
            int RetryWaitms = 1000;
 
            for (int i = 0; i < RetryCount; i++)
            {
                Process[] ps = Process.GetProcesses();
 
                foreach (Process pitem in ps)
                {
                    if ((pitem.MainWindowHandle != IntPtr.Zero) &&
                           ((pitem.MainWindowTitle.Equals(winTitle1)) || (pitem.MainWindowTitle.Equals(winTitle2))))
                    {
                        hWnd = pitem.MainWindowHandle;
                    }
                }
                if (hWnd != IntPtr.Zero) break;
                if (i < (RetryCount - 1)) Thread.Sleep(RetryWaitms);
            }
 
            return hWnd;
        }
 
        // テキスト転記と再生ボタン押下
        static void talk(IntPtr hWnd, string talkText)
        {
            if (hWnd == IntPtr.Zero) return;
 
            AutomationElement ae = AutomationElement.FromHandle(hWnd);
            TreeScope ts1 = TreeScope.Descendants | TreeScope.Element;
            TreeScope ts2 = TreeScope.Descendants;
 
            // アプリケーションウインドウ
            AutomationElement editorWindow = ae.FindFirst(ts1, new PropertyCondition(AutomationElement.ClassNameProperty, "Window"));
 
            // 再生ボタン、テキストボックスが配置されているコンテナの名前は“c”
            AutomationElement customC = ae.FindFirst(ts1, new PropertyCondition(AutomationElement.AutomationIdProperty, "c"));
 
            // テキストボックスにテキストを転記
            AutomationElement textBox = customC.FindFirst(ts2, new PropertyCondition(AutomationElement.AutomationIdProperty, "TextBox"));
            ValuePattern elem1 = textBox.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
            elem1.SetValue(talkText);
 
            // 再生ボタンを押す。再生ボタンはボタンのコレクション5番目(Index=4)
            AutomationElementCollection buttons = customC.FindAll(ts2, new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, "ボタン"));
            InvokePattern elem2 = buttons[4].GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
            elem2.Invoke();
        }
    }
}

この方法での問題

アプリケーションウインドウにフォーカスが渡ってしまうのをどうしても回避できないでいます。
たとえば、ゲームのメッセージをVOICEROID2に読ませるようなアプリケーションを書いた場合、ゲームのバックグラウンドで発声させることができません。
ゲームのフォーカスを奪ってしまうので、ゲームプレイに影響大となるでしょう。

コメント

RoyCrz, 2018/01/17 14:47

こちらに書かれているソースを利用して Windows上で使えるツールを無償公開しようと考えています。 (https://twitter.com/roy_crz/status/953625506825453568)

ライセンス等の記載がありませんでしたので 使用許可等どのような形になりますでしょうか?

ご回答いただけると幸いです。 よろしくお願いいたします。

k896951, 2018/01/17 14:52

検索エンジンで調べればわかる内容ですから、このソースについて権利を主張するつもりはありません。 ツールの完成を心待ちにしております。 ファイト!

コメントを入力. Wiki文法が有効です:
画像の文字が読めなければ、文字を読んだ.wavファイルをダウンロードして下さい。
 
documents/voiceroid/tips/tips-003.txt · 最終更新: 2018/06/24 23:16 by k896951

ページ用ツール