TWAINを使ってスキャナを操作するWPFアプリを作っていて、情報源の少なさにかなり苦労した。1週間ほど格闘した中でわかったのは、TWAINはStateによって実行できるコマンドが変わることだ。ここかなり重要だった。
ここから参照できる仕様書(PDF)でしっかりとそのあたりに触れている。切羽詰まっていてちゃんと読んでいなかった・・・反省。
Stateについて触れているのは
- The State-Based Protocol
- Controlling a TWAIN Session from Your Application
- Best Practices for TWAIN Compliant Applications
あたりだろうか。Stateで実行できるコマンドが変わるため、本来実行すべき箇所でコマンド実行せずに見当違いな箇所で実行してしまい、思ったような結果が得られずにネットで検索を行うも解決せず、トライアンドエラーを繰り返して遠回りし泥沼にハマるパターンが多かった。
ざっと流れを説明すると、以下のように状態が変わる。
- Data Source Managerを開く(Stateは2 -> 3)
- Data Group: DG_CONTROL
- Data Argument Type: DAT_PARENT
- Message ID: MSG_OPENDSM
- デバイスを選択する(Stateは3)
- Source Managerを使ってダイアログから選択できる
- Data Group: DG_CONTROL
- Data Argument Type: DAT_IDENTITY
- Message ID: MSG_USERSELECT
- またはSource Managerを使って全件取得し、利用したいものを探す
- Data Group: DG_CONTROL
- Data Argument Type: DAT_IDENTITY
- Message ID: MSG_GETFIRST&MSG_GETNEXT
- Source Managerを使ってダイアログから選択できる
- Data Sourceを開く(Stateは3 -> 4)
- Data Group: DG_CONTROL
- Data Argument Type: DAT_IDENTITY
- Message ID: MSG_OPENDS
- デバイスの機能設定を行う(Stateは4)
- Operation TripletsでValid States=4を利用できる
- Data Sourceを有効にする(Stateは4 -> 5)
- デバイスが提供する設定ダイアログを開くことができるし、開かずそのまま進めることもできる
- Data Group: DG_CONTROL
- Data Argument Type: DAT_USERINTERFACE
- Message ID: MSG_ENABLEDS
- デバイスが提供する設定ダイアログを開くことができるし、開かずそのまま進めることもできる
- デバイスから転送を始める(Stateは6 -> 7)
- Data Group: DG_CONTROL
- Data Argument Type: DAT_IMAGExxxxXFER
- MSG_IMAGENATIVEXFER
- MSG_IMAGEFILEXFER
- MSG_IMAGEMEMFILEXFER
- MSG_IMAGEMEMXFER
- Message ID: MSG_GET
- 保留中の転送を確認する(Stateは7 -> 6)
- Data Group: DG_CONTROL
- Data Argument Type: DAT_PENDINGXFERS
- Message ID: MSG_ENDXFER
Stateの状態を把握しておけば、下記のサンプルコードを使って思い通りの処理を作れるだろう*1。いつかTWAINを使った実装に関して、ケースバイケースで解説したい。
その他、公式ドキュメントにはたくさんの実装する上で欠かせない情報が掲載されている。
- 実装のチュートリアルは4章「Advanced Application Implementation」
- エントリーポイント定義は6章「Entry Points and Triplet Components」
- エントリーポイントを使ってコマンドを実行するときのパラメーター組み合わせは7章「Operation Triplets」
定数定義やデバイス機能設定(Capability)に関しても他の章で扱っている。とにかく困ったら一読することをおすすめする。