はじめに
このリモートシャッターを前回は、RaspberryPi3 のシャットダウンボタンにしましたが、今回は Windows の Bluetooth 2ボタンキーボードにしてみようと。
色々ネットを探してみたのですが、Windows で使用している記事が無くて結構ハマりました。
※ABShutter3の仕様が変わったらしく、2つのボタンで送信キーの差がなくなったようです。どちらのボタンを押しても同じになってしまいました。 1ボタンとしては使えます。2020/10/26更新
Bluetoothリモートシャッターとは
- そもそもこれは、スマホのシャッター用ボタン
- スマホとBluetooth接続して使う
- iOSボタンとAndroidボタンの2つある
- 使わないと自動的に数分で電源OFFになる
- ボタン電池のRS2032
- HIDキーボードとして認識される
用途
キーボードフックを使って、別のキーにねじ曲げてしまおう!
ハード
- Bluetoothリモートシャッター(AB Shutter3)(ダイソー 324円)
- Windows10 Pro 1909
開発用IDE
ソース
作成したソース:ABShutter3Key(github)
Windowsとペアリング
このリモートシャッターは、Windowsとペアリングすれば HIDキーボードとして認識される。ドライバーなどのインストールは必要ない。
リモートシャッターの電源をOFFにしておく
Windows10 > 設定 > デバイス > Bluetoothとその他のデバイス
+Bluetooth またはその他のデバイスを追加する
を押下
Bluetooth
を押下。リモートシャッターの電源をONにする。
通信距離が短いので、近くで行う。1m以内。
AB Shutter3
を押下
##ペアリング済み:
先程のWindows10 > 設定 > デバイス > Bluetoothとその他のデバイス
画面に戻ると以下のようになっているはず。もしくは「接続済み」。
デバイスがWindowsに登録された状態。次回以降は、リモートシャッターの電源を入れるとすぐに接続される。この状態はまだ使用できない。リモートシャッターは数分使用しないと電源がOFFになりPCとはこの状態になる。
##接続済み:
ペアリングが完了して、リモートシャッターと通信できる状態にある。この状態でないと使用できない。
もしリモートシャッターの電源がONで「ペアリング済み」状態ならiOSボタンを押してみよう「接続済み」になるはず。もしならなけれは、一度電源をOFF→ONにすればいい。
接続動作確認
「接続済み」の状態で iOS/Androidボタンを押して、デスクトップ画面の左上に下図のようボリューム表示が出てれくればOK。
開発メモ
「能書きはいいから使いたんじゃ」というひとは **使い方**へ
iOS/Androidボタン
- iOSボタンは、キー
VK_VOLUME_UP
にマッピングされている。なので先程のボリューム表示される。 - Androidボタンは、キー
VK_ENTER
VK_VOLUME_UP
にマッピングされている。VOLUME_UP
の前にENTER
が送信されるので、エディタを開いた状態で押すと、改行とボリューム表示がされる。
今回はこのキーVK_ENTER
VK_VOLUME_UP
をねじ曲げて、別のボタンにしてしまおうということです。
※新しいモノだと仕様が変わったらしく、AndroidボタンでVK_ENTER
キーが送信されなくなっています。2020/10/26更新
RawInput API
キーVK_ENTER
VK_VOLUME_UP
は、当たり前だが通常使用しているキーボードからも送信さる。なので通常のキーボードとリモートシャッターの判定をしないといけない。判定方法として RawInput API を使用する。RawInput APIを使うと HID デバイスの一覧と入力されたHIDデバイスが取得できる。だがRawInput APIでは入力されたキーの変更は一切できない、参照のみ。
##VID
HIDデバイスには、VID(ベンダーID)とPID(プロダクトID)があって、これをRawInput APIで取得できるのでリモートシャッターの判定として使う。以下がリモートシャッターのVIDとPID(デバイスドライバ)。
違うようであれば setting.ini
を変更する。
[ABShutter3Key]
VID="_VID&02248a_PID&8266"
##システムフックAPI SetWindowsHookEx()
昔からあるWindowsシステムAPIで user32.dll にあります。これを使うと色々なイベントをフックできる。SetWindowsHookExW function(winuser.h)
今回はこの中でも、 WH_KEYBOARD
と WH_KEYBOARD_LL
を使う。昔は WH_KEYBOARD
しかなかったと思う。WH_KEYBOARD_LL
は 低レベルキーボードフックと言って WH_KEYBOARD
よりも低レベルでフックするよう。どちらもグローバルフック(システム全体にフック)することは可能だが、WH_KEYBOARD_LL
は実行ファイルだけでグローバルフックできるのに対し、WH_KEYBOARD
は DLL にフックプロシージャを書かないといけない決まりがある。そして両フックともフックプロシージャで 戻り値 を 0 以外にすると残りのフックチェーンにメッセージが渡らなくなり、その入力キーをブロックできるはずなのだが VK_VOLUME_UP
が WH_KEYBOARD
ではブロックできない・・・。仕方がないので両方使う
低レベルであるWH_KEYBOARD_LL
のイベントが先に来る。さきほどの RawInput API を含めると
WH_KEYBOARD_LL
→ RawInput API → WH_KEYBOARD
(※あくまでも私の環境での実測値。公式ではないので、動かなかった場合はゴメンナサイ。)
-
VK_ENTER
は RawInput API で HIDデバイス判定をして、WH_KEYBOARD
でその入力がリモートシャッターならブロックする -
VK_VOLUME_UP
はWH_KEYBOARD_LL
でブロックする
ということは、VK_VOLUME_UP
は HIDデバイス判定をしていないので、すべてのHIDデバイスでブロックされてしまうことになる。しかし、どのみち RawInput API で VK_VOLUME_UP
は判定できないようだった。VK_VOLUME_UP
時のHIDデバイスハンドルがNULLなのだ。
まぁ VK_VOLUME_UP
キーなんて普段使わないしブロックされても特に日常で困ることはないのでOKとする。
##SendKeys
キーボードフックして、VK_ENTER
VK_VOLUME_UP
キーをブロックしたタイミングで、代替したいキー(もしくは文字列)を送信する。送信は WindowsAPIのSendInput() を使うのだが、ライブラリとして完成度の高いこちらを使わせて頂いた。
#使い方
-
ここから(ABShutter3Key)一式をダウンロードする。
(Code > Download Zip)
- ダウンロード>解凍後に、
x64/Release
フォルダにあるsettings.ini
をエディタで開く - ボンタンに割り当てたいキーを iOS="任意のキー"、Andoroid="任意のキー" に記述し保存(※)
-
x64/Release
フォルダにあるABShutter3Key.exe
を実行する - iOS/Androidボタンを押して任意のキーが出力できたら成功
- 終了する場合は、タスクトレイ(システムトレイ)の
ABShutter3Key
アイコンをクリックしてEXIT
をクリック - 任意のキーが出力できずに、ボリューム表示されるようならばキーボードフックに失敗してかも。
ABShutter3Key
を再起動する - それでもダメなら、
setting.ini
の VIDを確認する - 任意のキーが出力できずに、ボリューム表示もされないようならば 「接続済み:」か再確認する
[ABShutter3Key]
VID="_VID&02248a_PID&8266"
iOS="iOS{ENTER}"
Android="Android{ENTER}"
(※)キーの記述は、一文字だけであれば "A"。その他は
KEY | CODE | 記述例 |
---|---|---|
WIN | @ | @d :デスクトップ表示 |
SHIFT | + | +2 :"ダブルクォーテーション |
CTRL | ^ | ^c :コピー |
ALT | % | %{TAB} :タスク切換え |
なお、こちら(SendKeys in C++) の記述が使用可能。ただし、DELAYは使えない。
画面ロック(WIN+L) は {LOCKWORKSTATION}。
(※) settings.ini
を編集したら 再起動が必要
#最後に
- 私の持っているリモートシャッターが数年前のモノなので VID などが変わっている可能性大です。
- 2つ持っているのですが、個体差があります。
- チャタリングが凄いです(特にAndroidボタン)、連続して表示されるかもしれません。
- SendKeysのDELAYコマンドが使えないので、そのうち使えるように改良したい。
- チャタリング対応もソフト的にしたい。
もし「動いたよ!」とかあればコメントして頂けると励みになります。
良い IoT ライフを!
#SpecialThanks!!
SendKeys-in-C (CodeProject)
Combining Raw Input and keyboard Hook to selectively block input from multiple keyboards (CodeProject)