Tutorial: Hosting Visual Objects in a Win32 Application
Windows Presentation Foundation (WPF)は、アプリケーションを作成するための豊かな環境を提供します。しかしながら、あなたが、Win32コードに多額の投資をしている場合、コードを書き直すよりも、アプリケーションに、WPF機能を追加する方が効果的な場合があります。アプリケーションで同時に使用されるWin32、および、WPFグラフィック・サブ・システムのサポートを提供するために、WPFは、Win32ウィンドウでオブジェクトをホストするためのメカニズムを提供します。
このチュートリアルは、Win32ウィンドウ内で、WPFのビジュアル・オブジェクトをホストする、Win32相互運用サンプルを使用したヒットテストのサンプル・アプリケーションを、どのように、記述するかを説明します。
必要条件
Requirements
このチュートリアルは、WPFとWin32の両方のプログラミングに関する基本的な知識があることを前提としています。WPFプログラミングの基本的な概要については、「ウォークスルー」を参照してください。:私の最初のWPFのデスクトップ・アプリケーション。Win32プログラミングの概要については、この主題に関係する数多くの本のいずれかを参照してください。特に、Charles Petzoldによる「プログラミングWindows」。
このチュートリアルには、関連するサンプルの多くのコード例が含まれています。しかしながら、読みやすさのために、それには、完全なサンプルコードが、含まれていません。完全なサンプルコードについては、「Win32相互運用サンプルを使用したヒットテスト」を参照してください。
ホストWin32ウィンドウを作成する
Creating the Host Win32 Window
Win32ウィンドウに、WPFオブジェクトをホストするための鍵は、HwndSourceクラスです。このクラスは、Win32ウィンドウ内に、WPFオブジェクトをラップします。それらは、子ウィンドウとして、あなたのユーザー・インターフェイス(UI)に、取り込むことができます。
次の例は、ビジュアル・オブジェクトのWin32コンテナ・ウィンドウとして、HwndSourceオブジェクトを作成するためのコードを示しています。Win32ウィンドウのウィンドウ・スタイル、位置、および、その他のパラメータを設定するために、HwndSourceParametersオブジェクトを使用します。
// Constant values from the "winuser.h" header file.
// "winuser.h"ヘッダ・ファイル定数値。
internal const int WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000;
internal static void CreateHostHwnd(IntPtr parentHwnd)
{
// Set up the parameters for the host hwnd.
// ホストhwndのパラメーターを設定します。
HwndSourceParameters parameters = new HwndSourceParameters("Visual Hit Test", _width, _height);
parameters.WindowStyle = WS_VISIBLE | WS_CHILD;
parameters.SetPosition(0, 24);
parameters.ParentWindow = parentHwnd;
parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
// Create the host hwnd for the visuals.
// ビジュアルのために、ホストhwndを作成します。
myHwndSource = new HwndSource(parameters);
// Set the hwnd background color to the form's background color.
// hwndの背景色をフォームの背景色に設定します。
myHwndSource.CompositionTarget.BackgroundColor = System.Windows.Media.Brushes.OldLace.Color;
}
ExtendedWindowStyleプロパティの値を、WS_EX_TRANSPARENTに設定することはできません。これは、ホストのWin32ウィンドウを透明にできないことを示しています。この理由から、ホストWin32ウィンドウの背景色は、その親のウィンドウと同じ背景色に設定されます。
ホストWin32ウィンドウにVisualオブジェクトを追加します。
Adding Visual Objects to the Host Win32 Window
一旦、あなたが、ビジュアル・オブジェクトのために、ホストWin32コンテナ・ウィンドウを作成すると、あなたは、それに、ビジュアル・オブジェクトを追加できます。あなたは、ホストWin32ウィンドウの境界矩形の境界を超えて拡張しないで、アニメーションのような、ビジュアル・オブジェクトのどんな変形も確実に行うことを望むでしょう。
次の例は、HwndSourceオブジェクトを作成し、それにビジュアル・オブジェクトを追加するためのコードを示します。
HwndSourceオブジェクトのRootVisualプロパティは、ホストWin32ウィンドウに追加される1つ目のビジュアル・オブジェクトに設定されます。ルート・ビジュアル・オブジェクトは、ビジュアル・オブジェクト・ツリーの最上位のノードを定義します。ホストのWin32ウィンドウに追加された後続のビジュアル・オブジェクトは、すべて、子オブジェクトとして追加されます。
public static void CreateShape(IntPtr parentHwnd)
{
// Create an instance of the shape.
// シェイプのインスタンスを作成します。
MyShape myShape = new MyShape();
// Determine whether the host container window has been created.
// ホスト・コンテナ・ウィンドウが、作成されているかどうかを確認します。
if (myHwndSource == null)
{
// Create the host container window for the visual objects.
// ビジュアル・オブジェクトのために、ホスト・コンテナ・ウィンドウを作成します。
CreateHostHwnd(parentHwnd);
// Associate the shape with the host container window.
// ホスト・コンテナ・ウィンドウを持つシェイプを関連付けます。
myHwndSource.RootVisual = myShape;
}
else
{
// Assign the shape as a child of the root visual.
// ルート・ビジュアルの子として、シェイプを割り当てます。
((ContainerVisual)myHwndSource.RootVisual).Children.Add(myShape);
}
}
Win32メッセージ・フィルタを実装する
Implementing the Win32 Message Filter
ビジュアル・オブジェクトのホストWin32ウィンドウは、アプリケーション・キューからウィンドウに送信される、メッセージを処理するためのウィンドウ・メッセージ・フィルタ・プロシージャが必要です。ウィンドウ・プロシージャは、Win32システムからメッセージを受け取ります。これらは、入力メッセージやウィンドウ管理メッセージである場合があります。あなたは、オプションとして、ウィンドウ・プロシージャで、メッセージを取り扱うことができるか、デフォルトの処理のためのシステムに、メッセージを渡すことができます。
あなたが、ビジュアル・オブジェクトの親として定義したHwndSourceオブジェクトは、提供したウィンドウ・メッセージ・フィルター・プロシージャを参照する必要があります。あなたが、HwndSourceオブジェクトを作成するとき、ウィンドウ・プロシージャを参照するために、HwndSourceHookプロパティを設定します。
parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
次の例は、マウスのヒットした位置の座標値が、lParamパラメータの値に含まれている、マウスの左ボタンと右ボタンのアップメッセージを処理するためのコードを示しています。
// Constant values from the "winuser.h" header file.
// "winuser.h"ヘッダ・ファイル定数値。
internal const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;
internal static IntPtr ApplicationMessageFilter(
IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages passed to the visual.
// ビジュアルに渡されるメッセージを処理します。
switch (message)
{
// Handle the left and right mouse button up messages.
// マウスの左ボタンと右ボタンのアップ・メッセージを処理します。
case WM_LBUTTONUP:
case WM_RBUTTONUP:
System.Windows.Point pt = new System.Windows.Point();
pt.X = (uint)lParam & (uint)0x0000ffff; // LOWORD = x
pt.Y = (uint)lParam >> 16; // HIWORD = y
MyShape.OnHitTest(pt, message);
break;
}
return IntPtr.Zero;
}
Win32メッセージを処理する
Processing the Win32 Messages
次の例のコードは、ホストWin32ウィンドウに含まれている、ビジュアル・オブジェクトの階層に対してヒット・テストを、どのように、実行するかを示しています。あなたは、点が、ビジュアル・オブジェクトのジオメトリーの中にあるかどうか、識別することができます。HitTestメソッドを使用して、ヒットテストの対象となるルート・ビジュアル・オブジェクトと座標値を指定します。この場合、ルート・ビジュアル・オブジェクトは、HwndSourceオブジェクトのRootVisualプロパティの値です。
// Constant values from the "winuser.h" header file.
// "winuser.h"ヘッダ・ファイル定数値。
public const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;
// Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
// どのビジュアル・オブジェクトが、クリックされたか判別することで、
// WM_LBUTTONUP、あるいは、WM_RBUTTONUPメッセージに、応答します。
public static void OnHitTest(System.Windows.Point pt, int msg)
{
// Clear the contents of the list used for hit test results.
// ヒット・テスト結果のために使用されるリストのコンテンツをクリアします。
hitResultsList.Clear();
// Determine whether to change the color of the circle or to delete the shape.
// 円の色を変更するか、形状を削除するかを決定します。
if (msg == WM_LBUTTONUP)
{
MyWindow.changeColor = true;
}
if (msg == WM_RBUTTONUP)
{
MyWindow.changeColor = false;
}
// Set up a callback to receive the hit test results enumeration.
// ヒット・テスト結果の列挙体を受け取るために、コールバックを設定します。
VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual,
null,
new HitTestResultCallback(CircleHitTestResult),
new PointHitTestParameters(pt));
// Perform actions on the hit test results list.
// ヒット・テスト結果のリストで、動作を実行します。
if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}
ビジュアル・オブジェクトに対するヒット・テストの詳細については、「ビジュアル・レイヤーでのヒットテスト」を参照してください。
こちらもご覧ください
See also
- HwndSource
- Win32相互運用サンプルを使用したヒットテスト(Hit Test with Win32 Interoperation Sample)
- Visualレイヤーのヒット・テスト(Hit Testing in the Visual Layer)