技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

VOICEROID+でSkypeメッセージ喋らせる(3)

無事東北ずん子もしゃべるものを作成。
喋ってる間に次の命令来たらどう対処すんべ、、、、ずん子はUIのステータスチャックで拾えるけど、結月ゆかりはどうしようかな

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;

namespace net.azworks.VoiceroidAccess
{
    class Zunko
    {
        private Process getVoiceroidProcess()
        {
            Process[] proceses = Process.GetProcessesByName("VOICEROID");

            if (proceses.Length == 0)
                throw new ApplicationInirializeException(
                    "VOCALOID.exe プロセスが存在していません。");

            foreach (Process process in proceses)
            {
                string processName = process.ProcessName;
                string windowTitle = process.MainWindowTitle;
                if (process.MainWindowTitle.StartsWith("VOICEROID+ 東北ずん子"))
                    return process;
            }
            return null;
        }

        private Process process = null;

        private IntPtr getVoiceroidWindwHandle()
        {
            try
            {
                return process.MainWindowHandle;
            }
            catch (Exception e)
            {
                playButton = IntPtr.Zero;
                textbox = IntPtr.Zero;
                process = getVoiceroidProcess();
                if (process == null)
                    throw new ApplicationInirializeException(
                        "VOICEROID+ 東北ずん子 が起動してないっぽいです。");
                return process.MainWindowHandle;
            }
        }

        private IntPtr FindButton(List<IntPtr> tgts, String caption)
        {
            foreach (var p in tgts)
            {
                string className = Win32.GetWindowClassName(p);
                string captionText = Win32.GetWindowCaption(p);
                bool left = className.StartsWith("WindowsForms10.BUTTON");
                bool right = captionText.Contains(caption);
                if (left && right)
                    return p;
            }
            return IntPtr.Zero;
        }

        private IntPtr playButton = IntPtr.Zero;
        private IntPtr GetPlayButton()
        {
            if (playButton == IntPtr.Zero)
            {
                var children = Win32.GetChildWindows(getVoiceroidWindwHandle());
                playButton = FindButton(children, "再生");
            }
            return playButton;
        }

        private IntPtr textbox = IntPtr.Zero;
        private IntPtr GetTextbox()
        {
            if (textbox == IntPtr.Zero)
            {
                IntPtr current = Win32.GetWindow(getVoiceroidWindwHandle(), Win32.GW_CHILD);
                current = Win32.GetWindow(current, Win32.GW_CHILD);
                current = Win32.GetWindow(current, Win32.GW_HWNDNEXT);
                current = Win32.GetWindow(current, Win32.GW_CHILD);
                current = Win32.GetWindow(current, Win32.GW_CHILD);
                current = Win32.GetWindow(current, Win32.GW_CHILD);
                current = Win32.GetWindow(current, Win32.GW_CHILD);
                textbox = Win32.GetWindow(current, Win32.GW_CHILD);
            }

            return textbox;
        }

        IntPtr VK_DELETE = new IntPtr(46);

        public void Talk(String message, int delay = 10)
        {
            IntPtr textEdit = GetTextbox();

            // コピペ
            IntPtr currentTextLength = Win32.SendMessage(textEdit, Win32.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
            Win32.SendMessage(textEdit, Win32.EM_SETSEL, IntPtr.Zero, new IntPtr(currentTextLength.ToInt32()));
            Win32.SendMessage(textEdit, Win32.WM_KEYDOWN, new IntPtr(46), IntPtr.Zero);

            Clipboard.SetText(message);
            Win32.SendMessage(textEdit, Win32.WM_PASTE, IntPtr.Zero, IntPtr.Zero);
        }

        public void Play()
        {
            IntPtr playButton = GetPlayButton();
            Win32.SendMessage(playButton, 245, IntPtr.Zero, IntPtr.Zero);
        }
    }
}

ずん子の方が楽でした RichEdit コンポーネントとか使ってるっぽいので、Windowsメッセージをフルに投げて操作できる。
とはいえ、これで幾つか新しい情報が手に入ったのも事実。どっかでフィードバック居るかなぁ(;´Д`)
あと弄ってみてNGワードがあるのは気づいたが、どうもその処理は単語認識ではなく、単純な文字列一致としてNGらしい。
文章を扱うプログラムでその作りはどうなんだ?と思わなくもないが、まぁ要するにVOICEROIDに食わせる前にそれを伏字にすればいいだけの話ではある。