開発担当の橋本孔明です。
昨年10月、Microsoftの発表会において、同社のフラグシップ タブレットPCとなるSurface Studioに加え、Surface Dialという新しい入力デバイスが発表されました。
オーディオ アンプのボリュームのような外観をしているSurface Dialは、主に回転入力を受け取って何らかのUI操作を行うためのデバイスですが、机の上に置いて使う通常の方式に加え、Surface Studio(およびシステム アップデートを行ったSurface BookとSurface Pro 4)の画面上に置いて使うことで、その位置に直接UI要素を表示し、直感的に操作できるというのが特徴です。
Microsoftのデモンストレーションでは、主にペイント系やベクター系のグラフィックス ツールと組み合わせ、ペンの太さや選択色といった操作コンテキストの切り替えに活用するストーリーが紹介されていました。
Surface Dialは、その名称や一部の紹介記事などにより、「対応するSurfaceシリーズと組み合わせないと使えない」という誤解をされている場合も見られるようですが、そのようなことはありません。Windows 10 Anniversary Update(バージョン1607)以降であれば他のコンピューターでも問題無く使用することができます。Surfaceシリーズ以外での制限事項は「画面上に置く」使い方ができないことだけです。
去る6月15日、Surface StudioとともにSurface Dialも日本での正規取り扱いが開始され、10,000円強という価格で国内でも入手できるようになりました。
Surface Dialの技術背景
Surface DialはBLE(Bluetooth Low Energy)デバイスです。購入したDialを手元のコンピューターにペアリングし、しばらく使用してみましたが、標準対応しているアプリはまだまだ少ないものの、拡大縮小や音量調整といったWindows標準の入力操作を割り当てることができるほか、設定画面でグローバルあるいはアプリごとにキーストロークを割り当てることができるため、多くのアプリで最低限の利用はできるようになっています。
標準機能(音量調整・拡大縮小・スクロール・アンドゥ/リドゥ)に割り当てた場合、アプリに対してはSurface Dial固有のメッセージなどは発行されず、例えばスクロールであればWM_MOUSEWHEELウィンドウ メッセージが、拡大縮小であればWM_KEYUP+WM_KEYDOWN(Ctrlキーの上げ下げ)とWM_MOUSEWHEELの組み合わせが、アンドゥであればCtrl+Zキーのキーストローク メッセージが、それぞれアクティブなウィンドウ宛てに飛んでくるようです。
デバイス マネージャーで見てみると、特別なドライバなどはインストールされておらず、HIDデバイスの一種として認識されていました。試しにAndroidでペアリングしてみましたが、入力デバイスとして認識されました(ただし、OSが対応していないため現時点では何もできません)。HIDデバイス アクセス用のAPIで読み取れば、(Windows以外のOSでも)OSの機能をバイパスして入力データを直接取得することはできそうです。(パケットの調査をされているブログ記事を見つけました:https://blog.tmyt.jp/entry/2016/11/27/145402)
アプリをSurface Dialに対応させる
Surface Dialをアプリから使いたい場合、Windows 10の開発ではおなじみのUWP APIとして提供されています。OS同様、SDKもWindows 10 Anniversary Update(バージョン 14393)以降での対応ですが、Windows 10 Creators Update(バージョン 15063)からは標準メニューの省略などいくつか機能が追加されており、それらの機能を使いたい場合はバージョン 15063のSDKをプロジェクトから参照指定する必要があることに注意が必要です。
Surface Dialは、WindowsのUI上(「設定」アプリなど)では「ホイール デバイス」と表記されていますが、内部名称は「Radial Controller」となるようです。APIでは「RadialController」というクラスが入り口となっています。
UWP APIは、これまで書いてきた記事でも説明した通り、いわゆる「UWPアプリ」ではない、普通のデスクトップ アプリでも使用することができます。C#であれば参照を追加するだけで簡単に扱えますが、C#でのサンプルはマイクロソフトの技術ブログなどで割と豊富に提供されているようですので、今回もC++言語をベースに開発を行ってみたいと思います。
今回のサンプル プログラムについて
今回ご紹介するサンプル プログラムは、マイクロソフトがGitHubで公開しているサンプル コード集「Windows-classic-samples」(https://github.com/Microsoft/Windows-classic-samples)に含まれている、「RadialController」というサンプル プログラムを改造し、機能をいくつか追加削除したものとなります。学習を兼ねて試行錯誤しながらの改造だったため、未使用変数や未使用コードなどが発生・混入している可能性がある点をご了承ください。
サンプルの動作内容は、独自のメニュー アイコンを表示した上、入力などのイベントが発生すると一緒に表示したコンソール ウィンドウに出力するものとなっています。
新しく追加された機能を使えるようにするため、Windows 10 Creators UpdateのSDK(バージョン 15063)を参照指定しています。サンプルの動作にもWindows 10 Creators Updateが必要です。Anniversary Update以前で動作させると、APIの実行に失敗したり、オブジェクト生成に失敗することでNULLアクセス違反などが発生するものと思われます。
なお、UWP API利用のためにこれまでの記事のサンプル プログラムでも利用していた「WRL」を使っているほか、一部WRLだけでは面倒な部分(IVectorの操作など、そのままではMIDLの記述なども必要)を簡潔に記述できるようにするため、同じくマイクロソフトがオープンソース プロジェクトとして公開している、「cppwinrt」ライブラリ(https://github.com/Microsoft/cppwinrt)を利用しています。cppwinrtは、WinRTのAPI群を、C++/CXを使わず、かつWRLよりもさらに簡潔に記述できることを目的としたライブラリです。
今回のサンプルをビルドするためには、cppwinrtライブラリに含まれるヘッダファイル フォルダ(「10.0.15063.0」サブフォルダ内)を、標準インクルード ディレクトリの参照先へ追加するという事前準備が必要となります。SDK標準のインターフェースおよびWRLとcppwinrtを相互運用する場合、似たようなnamespaceやインターフェース名・オブジェクト名が混在して紛らわしいコードとなるため、充分ご注意ください。
元のサンプルに追加した部分として、オリジナルのPNG画像ファイルから独自のメニュー項目を追加するコードや、回転検知角度の設定・バイブレーションのオンオフ・メニュー項目選択の無効化(常に回転入力を得られる状態にする、コード上ではコメントアウト)などが入っています。
終わりに
かつてマイクロソフトは、2ボタン(Macintosh用に至っては1ボタン)のみが標準だったマウスに「ホイール」という新たな入力部を追加した「インテリマウス」を発売し、現在ではホイール(および第4・第5の追加ボタンなど)はマウスの標準機能として、Windowsの垣根を超えたデファクト スタンダードなものとなりました。
Surface Dialも、今後サード パーティーから互換デバイス(ダイヤル単体のほか、例えば多機能キーボードの左側にダイヤルが付いたタイプなど)が発売されたり、他OSでの対応が進んだりして、将来的にはキーボード・マウス・ペン・画面タッチなどに続く標準的な入力デバイスの一種となっていくかどうかが注目されます。
現時点では標準対応のアプリも少なく、Dial自身も1万円ちょっとと気楽には買いにくい価格のため、今すぐ幅広い普及が見込めるわけではなさそうですが、みなさんのアプリで対応することで操作性が向上し、製品のアピール ポイントのひとつとなるかもしれません。Adobe製品での対応も現在協議中という報道を見かけましたので、著名アプリでの対応がこれから進んでいくことも期待したいところです。
当方では、個人的に鉄道模型のコントローラーとしての利用を思いつき、既存の鉄道模型デジタル制御システム用のアプリにDial対応機能を組み込んでみました。ダイヤル回転で速度制御のスライダーを動かせるようにし、ダイヤル押下で方向転換コマンドを発行するというだけのものですが、据え付けのコントローラーを使わずにポータブルな運転ができるようになりました。このように、既存のアプリの機能拡張以外にも、IoT機器との連携などアイディア次第でいろいろ応用していくことができそうです。