チュートリアル : Win32 アプリケーションでのビジュアル オブジェクトのホスト
更新 : 2007 年 11 月
Windows Presentation Foundation (WPF) は、アプリケーションの作成に適した環境を提供します。ただし、Win32 コードに多くの投資を行った場合は、コードを記述し直すよりも、WPF の機能をアプリケーションに追加する方が、より効率的である場合があります。アプリケーション内で現在使用されている Win32 と WPF グラフィック サブシステムのサポートを提供するため、WPF は Win32 ウィンドウのオブジェクトをホストする機能を提供します。
このチュートリアルでは、サンプル アプリケーション「Win32 相互運用によるヒット テストのサンプル」の記述方法を説明します。このサンプル アプリケーションでは、Win32 ウィンドウの WPF ビジュアル オブジェクトがホストされます。
このトピックには次のセクションが含まれています。
- 要件
- ホスト Win32 ウィンドウの作成
- ホスト Win32 ウィンドウへのビジュアル オブジェクトの追加
- Win32 メッセージ フィルタの実装
- Win32 メッセージの処理
- 関連トピック
要件
このチュートリアルは、WPF および Win32 のプログラミングに関する基本的な知識があることを前提としています。WPF プログラミングの概要については、「Windows Presentation Foundation の概要」を参照してください。Win32 プログラミングの概要については多数の書籍が出版されていますので、それらを参照してください。特に『プログラミング Windows』(Charles Petzold 著) が参考になります。
メモ : |
---|
このチュートリアルには、関連するサンプルからのコード例が数多く含まれています。ただし、読みやすさのために、完全なサンプル コードは含まれていません。サンプル コード全体については、「Win32 相互運用によるヒット テストのサンプル」を参照してください。 |
ホスト Win32 ウィンドウの作成
Win32 ウィンドウの WPF オブジェクトをホストするキーとなるのは、HwndSource クラスです。このクラスは Win32 ウィンドウの WPF オブジェクトをラップし、そのオブジェクトを子ウィンドウとして ユーザー インターフェイス (UI) に組み込むことができます。
次の例では、ビジュアル オブジェクトの Win32 コンテナ ウィンドウとして HwndSource オブジェクトを作成するためのコードを示します。Win32 ウィンドウのウィンドウ スタイル、位置、およびその他のパラメータを設定する場合は、HwndSourceParameters オブジェクトを使用します。
// Constant values from the "winuser.h" header file.
internal const int WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000;
internal static void CreateHostHwnd(IntPtr parentHwnd)
{
// Set up the parameters for the host 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.
myHwndSource = new HwndSource(parameters);
// Set the hwnd background color to the form's background color.
myHwndSource.CompositionTarget.BackgroundColor = System.Windows.Media.Brushes.OldLace.Color;
}
メモ : |
---|
ExtendedWindowStyle プロパティの値を WS_EX_TRANSPARENT に設定することはできません。これは、ホスト Win32 ウィンドウを透明にできないことを意味します。このため、ホスト Win32 ウィンドウの背景色はその親ウィンドウと同じ背景色に設定されます。 |
ホスト Win32 ウィンドウへのビジュアル オブジェクトの追加
ビジュアル オブジェクトのホスト Win32 コンテナ ウィンドウを作成したら、そのコンテナ ウィンドウにビジュアル オブジェクトを追加できます。アニメーションなどでビジュアル オブジェクトが変形しても、ビジュアル オブジェクトがホスト Win32 ウィンドウの境界を示す四角形を超えて拡大されないようにする必要があります。
次の例では、HwndSource オブジェクトを作成し、ビジュアル オブジェクトを追加するコードを示します。
メモ : |
---|
HwndSource オブジェクトの RootVisual プロパティが、ホスト Win32 ウィンドウに追加される最初のビジュアル オブジェクトに設定されます。ルートのビジュアル オブジェクトによりビジュアル オブジェクト ツリーの最上位ノードが定義されます。ホスト 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 メッセージ フィルタの実装
ビジュアル オブジェクトのホスト Win32 ウィンドウでは、アプリケーション キューからウィンドウに送信されるメッセージを処理するために、ウィンドウ メッセージのフィルタ プロシージャが必要です。ウィンドウ プロシージャは Win32 システムからのメッセージを受け取ります。受け取るメッセージは、入力メッセージまたはウィンドウ管理メッセージです。ウィンドウ プロシージャでメッセージを処理するか、システムにメッセージを渡して既定の処理を行うこともできます。
ビジュアル オブジェクトの親として定義した HwndSource オブジェクトは、提供するウィンドウ メッセージのフィルタ プロシージャを参照する必要があります。HwndSource オブジェクトを作成する場合は、HwndSourceHook プロパティがウィンドウ プロシージャを参照するように設定します。
parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
次の例では、左右のマウス ボタンのメッセージを処理するコードを示します。マウスのヒット位置の座標値は、lParamパラメータの値に格納されます。
// Constant values from the "winuser.h" header file.
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 メッセージの処理
次のコード例では、ホスト Win32 ウィンドウに格納されたビジュアル オブジェクトの階層に対して、ヒット テストがどのように実行されるかを示します。HitTest メソッドを使用することにより、ビジュアル オブジェクトのジオメトリ内にポイントがあるかどうかを識別して、ヒット テストを実行するルートのビジュアル オブジェクトと座標値を指定できます。この場合、ルートのビジュアル オブジェクトは、HwndSource オブジェクトの RootVisual プロパティの値です。
// Constant values from the "winuser.h" header file.
public const int WM_LBUTTONUP = 0x0202,
WM_RBUTTONUP = 0x0205;
// Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
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();
}
}
ビジュアル オブジェクトに対するヒット テストの詳細については、「ビジュアル層でのヒット テスト」を参照してください。