Tablet PC でインクを使用することの利点の 1 つは、通常のペンと用紙を使用して書いている感覚に非常に近いことです。 これを実現するために、タブレット ペンはマウスよりも非常に高いレートで入力データを収集し、ユーザーが書いたとおりにインクを描画します。 アプリケーションのユーザー インターフェイス (UI) スレッドは、ブロックされる可能性があるため、ペンのデータを収集し、インクを描画するためには十分ではありません。 これを解決するために、WPF アプリケーションでは、ユーザーがインクを書く際に、2 つの追加スレッドを使用します。
デジタル インクの収集および描画に関与するスレッドを次のリストに示します。
ペン スレッド - スタイラスから入力を取得するスレッド (これは実際にはスレッド プールですが、ここではペン スレッドと呼びます)。
アプリケーション ユーザー インターフェイス スレッド - アプリケーションのユーザー インターフェイスを制御するスレッド。
動的レンダリング スレッド - ユーザーがストロークを描画している間にインクを描画するスレッド。 動的レンダリング スレッドは、アプリケーションの他の UI 要素を描画するスレッドとは別のものです。詳細については、Window Presentation Foundation の「スレッド モデル」を参照してください。
インク モデルは、アプリケーションが InkCanvas を使用している場合でも、「インク入力コントロールの作成」で示したようなカスタム コントロールを使用している場合でも同じです。 ここでは、InkCanvas でのスレッドについて説明していますが、カスタム コントロールを作成する場合でも、同じ概念が当てはまります。
スレッド処理の概要
ユーザーがストロークを描画する場合のスレッド モデルを次の図に示します。
ユーザーがストロークを描画している間に発生するアクション
ユーザーがストロークを描画すると、スタイラス ポイントはペン スレッドに入ります。 DynamicRenderer などのスタイラス プラグインは、ペン スレッドでスタイラス ポイントを受け入れ、InkCanvas が受け取る前にそれらのポイントを変更することができます。
DynamicRenderer が、動的レンダリング スレッドでスタイラス ポイントを描画します。 これは、前の手順と同時に行われます。
InkCanvas が、UI スレッドでスタイラス ポイントを受け取ります。
ユーザーがストロークを終了した後に発生するアクション
ユーザーがストロークの描画を終了すると、InkCanvas が Stroke オブジェクトを作成し、それを静的に描画する InkPresenter に追加します。
UI スレッドはストロークが静的に描画されることを DynamicRenderer に通知し、DynamicRenderer はストロークの視覚的表現を削除します。
インク コレクションとスタイラス プラグイン
各 UIElement には、StylusPlugInCollection があります。 StylusPlugInCollection の StylusPlugIn オブジェクトは、ペン スレッドでスタイラス ポイントを受け取り、それを変更することができます。 StylusPlugIn オブジェクトは、StylusPlugInCollection での順序に従って、スタイラス ポイントを受け取ります。
UIElement の StylusPlugIns コレクションに、stylusPlugin1、DynamicRenderer、および stylusPlugin2 がこの順序で含まれていると仮定した場合の状況を次の図に示します。
この図では、次の動作が実行されます。
StylusPlugin1 が、x と y の値を変更します。
DynamicRenderer が、変更されたスタイラス ポイントを受け取り、それらを動的レンダリング スレッドで描画します。
StylusPlugin2 が、変更されたスタイラス ポイントを受け取り、x と y の値をさらに変更します。
アプリケーションはスタイラス ポイントを収集し、ユーザーがストロークを終了すると、ストロークを静的に描画します。
stylusPlugin1 がスタイラス ポイントを四角形に制限し、stylusPlugin2 がスタイラス ポイントを右に平行移動するとします。 前のシナリオでは、DynamicRenderer は制限されたスタイラス ポイントを受け取りますが、平行移動されたスタイラス ポイントは受け取りません。 ユーザーがストロークを描画すると、そのストロークは四角形の境界内に描画されますが、ユーザーがペンを持ち上げるまで平行移動されません。
UI スレッドでスタイラス プラグインを使用した操作を実行する
ペン スレッドでは正確なヒット テストを実行できないため、場合によっては、一部の要素が他の要素を対象としたスタイラス入力を受け取ることがあります。 操作を実行する前に、入力が正しくルーティングされていることを確認する必要がある場合は、OnStylusDownProcessed、OnStylusMoveProcessed、または OnStylusUpProcessed の各メソッドにサブスクライブし、そのメソッド内で操作を実行します。 これらのメソッドは、正確なヒット テストが実行された後に、アプリケーション スレッドによって呼び出されます。 これらのメソッドにサブスクライブするには、ペン スレッドで実行されるメソッド内で NotifyWhenProcessed メソッドを呼び出します。
StylusPlugIn のスタイラス イベントに関連した、ペン スレッドと UI スレッドの関係を次の図に示します。
インクのレンダリング
ユーザーがストロークを描画すると、DynamicRenderer はインクを別スレッドで描画するため、UI スレッドがビジー状態であっても、インクはペンから "流れ出る" ように見えます。 DynamicRenderer は、スタイラス ポイントを収集しながら、動的レンダリング スレッドでビジュアル ツリーを構築します。 ユーザーがストロークを終了すると、DynamicRenderer は、アプリケーションが次の描画パスを実行する際に通知するように要求します。 アプリケーションが次の描画パスを完了した後、DynamicRenderer はビジュアル ツリーをクリーンアップします。 このプロセスを説明する図を次に示します。
ユーザーがストロークを開始したとき。
- DynamicRenderer がビジュアル ツリーを作成します。
ユーザーがストロークを描画している間。
- DynamicRenderer がビジュアル ツリーを構築します。
ユーザーがストロークを終了したとき。
InkPresenter がストロークを自分のビジュアル ツリーに追加します。
メディア統合レイヤー (MIL) がストロークを静的に描画します。
DynamicRenderer がビジュアルをクリーンアップします。