こんにちは、りょはです。
今回はサクッとWindowsアプリケーションを作ってみようと思います。
作るアプリのリポジトリのURLは以下です。
https://github.com/ryoha000/narrator
ダウンロードはこちらのzipから。
ここで書くこと
- Windowsアプリケーションの作るときの流れ
- 何かを作るときのりょはくんの考え方
ここで書かないこと
- 言語使用の説明
- VisualStudioのインストール方法
それでは早速行ってみましょ~!
何を作るか
現在は大分落ち着いてきたのですが、実は最近まで喉を壊してました。
しかしど~~~~しても喋りたいしちょっとテキストチャットだけでは困る機会がありました。
今回はその時に作ったWindowsアプリケーションを追っていこうと思います。
入力ウィンドウに文字を打ち込んで、確定した状態でEnterを押すと文字が読み上げがマイクに流れ、文字は消えるものを作ります。
何が必要か
何が必要か考えるとき、僕はまずどの部分を作る必要があって、どの部分は流用で済むかを考えます。
機能をまとめてみると下みたいになります。
- 文字を入力できるウィンドウ
- 常に最前面にある
- 確定状態でEnterを押すと文字が消える
- その文字は↓の読み上げソフトに渡される
- 文字を読み上げるソフト
- 文字を何らかの形で受け取れる
- Softalkというフリーソフトウェアを使います
- 読み上げられた音声をマイクに流し込む
- NETDUETTOというソフトを使います
- Softalkの諸々も含めて↓のリンクを参考にしてください
- 参考: https://talkstone.web.fc2.com/faq/012.html
作る部分が整理されましたね!
じゃあ作り始めましょう
何で作るか
作り始める前に何で作るか考えましょう。
色々な作り方がありますね。
一番頼るものを少なく、Windowsアプリケーションを作るなら、Windowsに備え付けのAPIを使って作ることです。
ただそんなことをする理由は殆どないです。
今はもっと簡単に作る方法がたくさんあります。
今回はVisualStudio上でWPFアプリケーションを作ります。
WPFは簡単にアプリケーションをexeファイルとして出力できる、優れたアプリケーションプラットフォームです。
WPFよりモダンな、UWPというアプリケーションプラットフォームがありますが、セキュリティ上の制約が厳しく、今回使用する機能が使えないため、WPFをアプリケーションプラットフォームとして選択します。
何で作るか決まったところで作っちゃいましょ~~。
プロジェクトを作る
まずVisualStudioをインストールします。
ここで今回の企画の3/4くらいの時間が使われます。気長に待ちましょう。
インストールするものを聞かれたら、C#ってかいてるやつとWPFってかいてるやつを全部選択すれば間違いはないです。
新しいプロジェクトの作成を押したら↓みたいな画面が出るので、検索する文字に「WPF」を入れます。
↓の画像の赤枠で囲ったやつを選択します。順番は違うかも。
表示する部分を書く
作ったプロジェクトを開きます。
こんな感じにしたいので
MainPage.xaml
の要素にHeight
(高さ)、Width
(横幅)、Topmost
(最前面かどうか)を設定する- テキスト入力するところを作る
をやっていきます。
Titleを定義してる部分(Title="MainPage"って書いてるところ
)の横に空白を開けて、Height="100"
、Width="500"
、Topmost="True"
を追記していきます。
この高さとか横幅の単位はピクセルです。
テキスト入力欄をつくります。
<Grid>
</Grid>
こんな感じでGrid
で囲まれたところに<TextBox />
を追加します。
そうすると入力欄ができます。
現時点のMainPage.xaml
の全体のソースコードは以下になります。
<Window x:Class="narator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:narator"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="500" Topmost="True">
<Grid>
<TextBox />
</Grid>
</Window>
F5キーを押してみると入力欄に入力できるので試してみてください。
入力欄に必要な機能を付ける
今回、入力欄に必要な機能は
- 常に最前面にある
- 確定状態でEnterを押すと文字が消える
- その文字は読み上げソフトに渡される
ですね。常に最前面におくのはもうできてるので下の二つですね。
さっきまで書いてた拡張子が.xaml
のファイルでは、文字を消すとかの処理ができません。
そのような諸々の処理はMainPage.xaml.cs
に書いていきます。[1]
MainPage.xaml.cs
で情報を触るために、<TextBox />
に名前をつけます。
<TextBox x:Name="text" />
に変更します。text
のところは自由です。
さらにEnterが押されたときの処理をするために、キーが押されるときに呼ばれる関数を作ります。
x:Name~~
とかいたところに空白を開けて、keyDown=
と書いていくとサジェストが下に出るためそれを選ぶと、MainPage.xaml.cs
にも関数が自動で作られて便利です。
もうMainPage.xaml
に追記することはありません。
以下がMainPage.xaml
全体のソースコードです。
<Window x:Class="narator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:narator"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="500" Topmost="True">
<Grid>
<TextBox x:Name="text" KeyDown="text_KeyDown"/>
</Grid>
</Window>
長い処理だとさらにファイルを分けた方がいいです。 ↩︎
Enterが押されたときの処理を書く
MainPage.xaml.cs
を開きます。
text_KeyDown
という名前の関数が作られてると思うのでその中だけ書き換えます。
Enterが押されたとき以外は何もしてほしくないので、
if (e.Key == Key.Enter)
{
}
を中に書き、さらにこの中にのみ処理を書いていきます。
Enterが押されたとき
- Softalkに文字を渡す
- 入力欄の文字を空にする
という処理をしたいです。
入力欄にtext
という名前をつけましたね。
入力欄に入力されてる文字はtext.Text
になっています。
Softalkに文字を渡す
SoftalkはSoftalkのパスが通っているディレクトリ(簡単に言えばSoftalk.exeがあるフォルダー)で文字を渡して喋らせることができます。
まずSystem.Diagnostics.Process pro = new System.Diagnostics.Process();
を書きます。
これはコマンドを新しく組み立てるよ~っていう宣言です。
さらに以下を書き足します。
pro.StartInfo.FileName = "softalk";
pro.StartInfo.Arguments = "/close /w:" + text.Text;
pro.StartInfo.UseShellExecute = true;
一行目はsoftalkっていうバイナリファイル(今回は.exe)を実行するよ~ってこと。
二行目は引数をとらせています。
softalkでは/close
が引数についてるとき、実行し終えたらプロンプト(黒い画面)を閉じる。(実行は一瞬だから黒い画面は見えない)
そして/w:しゃべらせたい文字
でその文字をしゃべらせられます。
"/close /w:" + text.Text
はtext.Text
があいうえお
のとき、"/close /w:あいうえお"
となります。
三行目はsoftalkに関係ないところなんであんまり気にしないでください。
一応書くとプロセスを起動するときにシェルを使用するようにしてます。
そして最後にpro.Start();
を挿入します。
これはこのコマンドを実行するということです。
このSystem.Diagnostics.Process()
という実装がUWPでは動きません。
UWPで他アプリと連携するときは他プロジェクトを内部に置いたりする必要があり、プロジェクトとしてではなく、バイナリファイルなどとして配布されているSoftalkではできなそうな雰囲気でした。
参考: https://docs.microsoft.com/ja-jp/windows/uwp/app-to-app/
参考: https://blog.okazuki.jp/entry/2018/02/10/174735
入力欄の文字を空にする
これは簡単でtext.Text=""
というようにして空文字を代入することで文字を消します
text_KeyDown
全体のソースコード
private void text_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
System.Diagnostics.Process pro = new System.Diagnostics.Process();
pro.StartInfo.FileName = "softalk";
pro.StartInfo.Arguments = "/close /w:" + text.Text;
pro.StartInfo.UseShellExecute = true;
text.Text = "";
pro.Start();
}
}
いざビルド!
これで完成です!
画像の部分からソリューションのビルドをしましょう
そしたらエクスプローラーで作業しているフォルダーを開いて、bin\Release\netcoreapp3.1
を開きます。
そのフォルダーにSoftalk.exeを貼り付けたら完成です!
プロジェクト名のexeを実行してみてください!
おまけ
僕のリポジトリではホットキー(ctrl+Cで貼り付けみたいなショートカットキーのこと)があります。
このホットキーはctrl
+S
で入力欄にマウスカーソルが合わさるというものです。
これはwin32apiというものを使っています。
win32apiはWindowsの基本的なAPIの集まりのことです。
今回はホットキーの登録に
RegisterHotKey
UnRegisterHotKey
を使っています。
そして最前面のウィンドウの登録や、ホットキー登録前の状態の保存のため
GetForegroundWindow
SetForegroundWindow
GetWindowThreadProcessId
AttachThreadInput
SystemParametersInfo
を使っています。
詳しい使い方などは以下を参考にしたので見てみてください。
参考: http://sourcechord.hatenablog.com/entry/2017/02/13/005456
Windowsアプリの作成はやっぱりwin32apiを使う部分が楽しいところだと思うので、Windowsユーザーのみなさんは是非使ってみてください。
おわりに
いかがでしたか?
これぐらいのアプリだったらプログラミング初心者でもすぐ作れます。
みなさんもtraPに入って一緒にプログラミングとかしましょう!
traPはあなたの入部をお待ちしています。
雑なので質問ある人はお気軽に。