苦手な分野のプログラムをgoogleりながらやる：windowsのsendInput

# 1. はじめに
私が得意ではないwindowsの機能を叩くプログラム作成のために、どのようにgoogleったか？というメモです。

# 2. 実施内容

c#で、windowsのソフトウエアキーボード作成を目指します。鍵になる単語を知らないところからスタートします。

# 3. 目標と方針の設定

- 期限：5日間以内（1日以内で可否判断）
- 品質：エラー処理無しで良い。動くデモのできるレベル。シリアルポートから叩く場合もある。
- 内容：一通りのキー入力。同時入力対応は無し。
- 他人の力を極力借りる
- 可能性の有無を積み上げて進む


# 4. 作業内容

基本は、googleって、githubで検索して、サンプルコードを試すという流れです。


## 4.1. 可否の確認
まず、**適切な言葉を探す**ためにgoogleります。

「windows キーボード 入力 c#」でgoogle検索(以下同様)。

ここでは、C#をキーワードに付けるのがポイント。当然ながら、キーボード入力を検出する内容が出てくる訳ですが、よく見ていると、**エミュレート**と**API**というキーワードが見えます。そこで検索キーワードは次のようにしました。

「windows キーボード エミュレートAPI c#」
ここで、microsoftのサイトもヒットするようになってきました。**key_input**というキーワードが拾えます。

「windows key_input API c#」
すると、key_inputは、最近**sendInput**になっているという情報が得られます。

「windows sendInput API c#」
ここまでくると、microsoftのサイトが沢山出てきます。qiitaのも出てきます。

これらを読んで、「たぶん、作ることが出来るんだな」という想像がつきます。なので、次に進むことにします。（もし、この時点で作るのが難しいという情報があれば、断念します。）


## 4.2. 既存の有無

そもそも、同じものが配付されているのであれば、それで完了です。まずは、既存のもの探します。もう一度、キーワードを選び直し、それっぽいものがあるかどうかを調べます。

「windows キーボード エミュレート シリアル」
USBのinputクラスに関する情報が出てきます。今は、こっちの話じゃないので、USBを除外します。

「windows キーボード エミュレート シリアル -usb」
ざっと見ると、想定内のは無いです。念のため、次のキーワードでも検索してみます。(と書いてますが、後でみたら、とても合致しているページがヒットしていました）

「windows 仮想キーボード シリアル」
残念ながら、それっぽいのがgoogleでは引っかからないです。

次に検索するのはgithubです。
githubの場合はキーワードの方向性が異なります。先ほど入手したAPI名、sendInput を入力します。

「sendInput」
すると、python、C、C++なども出てきます。今回は、windows用で c# で作りたいので、Languagesの絞り込みで c# を選択してみます。すると、もうそれっぽいのがあります。しかも、日本人であろうユーザ名もあるので、とても安心。

ざっと見ていき、今回のに合致しているのが、https://github.com/AonaSuzutsuki/KimamaKeyConverter でした。

## 4.3. sendInputの確認
まずは、自分の環境でビルドできるのかを確認します。先ほどの AonaSuzutsuki 氏のリポジトリをそのままビルドするのも良いのですが、目的のsendInputだけ、ビルドと動作確認できるかを確認します。すると、運の良いことに、AonaSuzutsuki 氏は、参考にした情報をreadmeに挙げてくれています。
今の目的に合致したのが romichi氏がgistで公開してくれているhttps://gist.github.com/romichi/4971512 で、zを入力して、左に1回 キーを押すというサンプルコードでした。

そこで、これをビルドしてみます。
visual studio で、コンソール版、.net framework 4.7.2で、新規プロジェクトを作り、出てきたProgram.csに全て上書きペーストし、ビルドします。
で、エラーが出ます。ここで動くようにするのが少々ハードルになります。対処したのは次の2つ。

- namespaceが無い
- 未知の型Keysがある

1つ目は、namespace プロジェクト名を書いて括弧でくくる。
2つ目は、厄介でした。ただ、Sendの第一引数の型をKeysからintに置き換え、Keys.Zを0x5Aに、Keys.Leftを0x25に置きかえます。これで、ビルドが通ります。

この2つ目の解決策にたどり着くには、やはりgoogleるしかありません。

「 sendinput Keys.Z 」
これを見ていくと、[仮想キーコード一覧](http://kts.sakaiweb.com/virtualkeycodes.html) という有り難いページにたどり着きます。これを見ると、Keys.Zは単なる整数値だろうと当たりがつきます。
しかも、ソースにも、```inp.ki.wVk = (short)key;```とあるので、16bit整数値であろうということが判ります。

ということで、ビルド確認するだけなので、直接数値を書き込んでしまおうという訳です。

これにてひとまず完了。


# 5. おわりに

ここの内容は、合計2時間ぐらいだったと思います。
いつも心がけているのですが、重要なのは、出来るか出来ないかをとりかかりの1時間程度で、判断するところだと思っています。今回、短時間で終わったのは、romichi氏とAonaSuzutsuki氏の公開してくれている情報があったからこそだと思います。本当に感謝です。

さて、今回は、c#でソフトウエアキーボードが作れるかの可否判断でした。しかし、本格的に何かをやりたいという要望に応える形で作る場合は、c#は歩が悪い可能性があります。なので、もう少しアプローチは根本的なところからになるはずです。まずは、プラットフォームの選択からでしょう。例えば、RPAを作りたいという話であれば、RPA向けプラットフォームが候補になるでしょう。検索キーワードは「RAP プラットフォーム」からスタートでしょうかね。膨大にあるので、予算に応じてになるでしょうか。予算があるならば、オールインワン型が良いと思います。予算が無いのなら、無償のもので将来性があり自分に合っているものという観点でしょうか。

また、マルチプラットフォームのキーボードやマウス操作の場合、pythonのpyautoguiというモジュールが良いでしょう。c#関連の事例があまり多く無いのは、このように他に有用なモジュールがあるからだろうと思います。

今回強調したいのは、知らないことはgoogleるということです。むしろ、このgoogleり方を身につけることが、ものを作れるとういよりも重宝するスキルかもしれません。世の中に無いことをする場合は、googleっても解決策が出ません。しかし、誰かがやっているであろう内容を実践するならば、googleれば大幅な時間短縮になります。