チュートリアル: Win32 での WPF コンテンツのホストWalkthrough: Hosting WPF Content in Win32

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) は、アプリケーションの作成に適した環境を提供します。provides a rich environment for creating applications. ただし、Win32Win32 コードにかなりの投資がある場合は、元のコードを書き換えるより、アプリケーションに WPFWPF の機能を追加するほうがより効果的であることがあります。However, when you have a substantial investment in Win32Win32 code, it might be more effective to add WPFWPF functionality to your application rather than rewriting your original code. WPFWPFウィンドウでコンテンツをホストWPFWPFするための簡単なメカニズムを提供します。 Win32Win32provides a straightforward mechanism for hosting WPFWPF content in a Win32Win32 window.

このチュートリアルでは、 Win32Win32ウィンドウのコンテンツをホストWPFWPFするサンプルアプリケーション ( Win32 ウィンドウサンプルで WPF コンテンツをホストする) を記述する方法について説明します。This tutorial describes how to write a sample application, Hosting WPF Content in a Win32 Window Sample, that hosts WPFWPF content in a Win32Win32 window. このサンプルを拡張すると、いずれの Win32Win32 ウィンドウでもホストできます。You can extend this sample to host any Win32Win32 window. マネージコードとアンマネージコードの混在が必要になるため、 C++アプリケーションは/cli で記述されています。Because it involves mixing managed and unmanaged code, the application is written in C++/CLI.

必要条件Requirements

このチュートリアルは、WPFWPFWin32Win32 プログラミングの基礎知識があることを前提としています。This tutorial assumes a basic familiarity with both WPFWPF and Win32Win32 programming. WPFWPFプログラミングの基本的な概要については、「はじめに」を参照してください。For a basic introduction to WPFWPF programming, see Getting Started. Win32Win32プログラミングの概要については、「チャールズ petzold 著) による特定のプログラミングウィンドウ」で、件名に関する多くの書籍を参照する必要があります。For an introduction to Win32Win32 programming, you should reference any of the numerous books on the subject, in particular Programming Windows by Charles Petzold.

このチュートリアルに付属するサンプルは/Cli でC++実装されているので、このチュートリアルでC++は、を使用して Windows API をプログラミングする方法とマネージコードプログラミングについて理解していることを前提としています。Because the sample that accompanies this tutorial is implemented in C++/CLI, this tutorial assumes familiarity with the use of C++ to program the Windows API plus an understanding of managed code programming. /Cli にC++関する知識は役に立ちますが、必須ではありません。Familiarity with C++/CLI is helpful but not essential.

注意

このチュートリアルには、関連するサンプルからのコード例が多数含まれています。This tutorial includes a number of code examples from the associated sample. しかし、読みやすくするため、完全なサンプル コードは含まれていません。However, for readability, it does not include the complete sample code. 完全なサンプルコードについては、「 Win32 ウィンドウでの WPF コンテンツのホスト」のサンプルを参照してください。For the complete sample code, see Hosting WPF Content in a Win32 Window Sample.

基本手順The Basic Procedure

このセクションWPFWPF Win32Win32では、ウィンドウでコンテンツをホストするために使用する基本的な手順の概要を説明します。This section outlines the basic procedure you use to host WPFWPF content in a Win32Win32 window. 残りのセクションでは、各手順の詳細について説明します。The remaining sections explain the details of each step.

ウィンドウでコンテンツをWPFWPFホストするためのキーはHwndSource 、クラスです。 Win32Win32The key to hosting WPFWPF content on a Win32Win32 window is the HwndSource class. このクラスは、 WPFWPF Win32Win32ウィンドウ内のコンテンツをラップし、子ウィンドウユーザー インターフェイス (UI)user interface (UI)としてに組み込むことができるようにします。This class wraps the WPFWPF content in a Win32Win32 window, allowing it to be incorporated into your ユーザー インターフェイス (UI)user interface (UI) as a child window. 次の方法では、Win32Win32 および WPFWPF を単一のアプリケーションに統合します。The following approach combines the Win32Win32 and WPFWPF in a single application.

  1. WPFWPFコンテンツをマネージクラスとして実装します。Implement your WPFWPF content as a managed class.

  2. /Cli を使用してC++Windows アプリケーションを実装するImplement a Windows application with C++/CLI. 既存のアプリケーションとアンマネージC++コードから開始する場合は、通常、 /clrコンパイラフラグを含めるようにプロジェクトの設定を変更することによって、マネージコードを呼び出すことができます。If you are starting with an existing application and unmanaged C++ code, you can usually enable it to call managed code by changing your project settings to include the /clr compiler flag.

  3. スレッド処理モデルをシングル スレッド アパートメント (STA: Single Threaded Apartment) に設定します。Set the threading model to single-threaded apartment (STA).

  4. ウィンドウプロシージャでWM_CREATE通知を処理し、次の手順を実行します。Handle the WM_CREATEnotification in your window procedure and do the following:

    1. 新しい HwndSource オブジェクトを、親ウィンドウがその parent パラメーターとなるように指定して作成します。Create a new HwndSource object with the parent window as its parent parameter.

    2. WPFWPF コンテンツ クラスのインスタンスを作成します。Create an instance of your WPFWPF content class.

    3. WPFWPFコンテンツオブジェクトへの参照をのRootVisualプロパティHwndSourceに割り当てます。Assign a reference to the WPFWPF content object to the RootVisual property of the HwndSource.

    4. コンテンツの HWND を取得します。Get the HWND for the content. Handle オブジェクトの HwndSource プロパティにウィンドウ ハンドル (HWND) が格納されます。The Handle property of the HwndSource object contains the window handle (HWND). アプリケーションのアンマネージ部分で使用できる HWND を取得するには、Handle.ToPointer() を HWND にキャストします。To get an HWND that you can use in the unmanaged part of your application, cast Handle.ToPointer() to an HWND.

  5. WPFWPF コンテンツへの参照を保持する静的フィールドを含むマネージド クラスを実装します。Implement a managed class that contains a static field to hold a reference to your WPFWPF content. このクラスを使用すると、WPFWPF コードから Win32Win32 コンテンツへの参照を取得できるようになります。This class allows you to get a reference to the WPFWPF content from your Win32Win32 code.

  6. WPFWPF コンテンツを静的フィールドに割り当てます。Assign the WPFWPF content to the static field.

  7. 1つWPFWPF WPFWPF以上のイベントにハンドラーをアタッチして、コンテンツから通知を受信します。Receive notifications from the WPFWPF content by attaching a handler to one or more of the WPFWPF events.

  8. 静的フィールドに格納した参照を使用して WPFWPF コンテンツと通信し、プロパティの設定などを行います。Communicate with the WPFWPF content by using the reference that you stored in the static field to set properties, and so on.

注意

また、を使用Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML)してWPFWPFコンテンツを実装することもできます。You can also use Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) to implement your WPFWPF content. ただし、ダイナミックリンクライブラリ (dll) として個別にコンパイルし、その dll をWin32Win32アプリケーションから参照する必要があります。However, you will have to compile it separately as a dynamic-link library (DLL) and reference that DLL from your Win32Win32 application. 手順の残りの部分は、前述の手順と同様です。The remainder of the procedure is similar to that outlined above.

ホスト アプリケーションの実装Implementing the Host Application

ここでは、基本的なWPFWPF Win32Win32アプリケーションでコンテンツをホストする方法について説明します。This section describes how to host WPFWPF content in a basic Win32Win32 application. コンテンツ自体は、マネージクラスC++として/cli に実装されます。The content itself is implemented in C++/CLI as a managed class. ほとんどの部分が、簡単な WPFWPF のプログラミングです。For the most part, it is straightforward WPFWPF programming. コンテンツの実装の重要な側面については、「 WPF コンテンツの実装」で説明します。The key aspects of the content implementation are discussed in Implementing the WPF Content.

基本的なアプリケーションThe Basic Application

ホストアプリケーションの開始点は、Visual Studio 2005 テンプレートを作成することでした。The starting point for the host application was to create a Visual Studio 2005 template.

  1. Visual Studio 2005 を開き、[ファイル] メニューの [新しいプロジェクト] をクリックします。Open Visual Studio 2005, and select New Project from the File menu.

  2. プロジェクトの種類のVisual C++Visual C++一覧から [Win32] を選択します。Select Win32 from the list of Visual C++Visual C++ project types. 既定の言語がでないC++場合は、これらのプロジェクトの種類が [その他の言語] の下に表示されます。If your default language is not C++, you will find these project types under Other Languages.

  3. Win32 プロジェクトテンプレートを選択し、プロジェクトに名前を割り当てて、[ OK ] をクリックして、 win32 アプリケーションウィザードを起動します。Select a Win32 Project template, assign a name to the project and click OK to launch the Win32 Application Wizard.

  4. ウィザードの既定の設定をそのまま使用し、[完了] をクリックしてプロジェクトを開始します。Accept the wizard's default settings and click Finish to start the project.

このテンプレートは、次のような基本的な Win32Win32 アプリケーションを作成します。The template creates a basic Win32Win32 application, including:

  • アプリケーションのエントリ ポイント。An entry point for the application.

  • 関連するウィンドウ プロシージャ (WndProc) を含むウィンドウ。A window, with an associated window procedure (WndProc).

  • ファイルヘルプの見出しを持つメニュー。A menu with File and Help headings. [ファイル] メニューには、アプリケーションを閉じる [終了] 項目があります。The File menu has an Exit item that closes the application. [ヘルプ] メニューには、簡単なダイアログボックスを起動する [ About ] 項目があります。The Help menu has an About item that launches a simple dialog box.

WPFWPFコンテンツをホストするコードの記述を開始する前に、基本テンプレートに2つの変更を加える必要があります。Before you start writing code to host the WPFWPF content, you need to make two modifications to the basic template.

1 つ目は、プロジェクトをマネージド コードとしてコンパイルすることです。The first is to compile the project as managed code. 既定では、プロジェクトはアンマネージ コードとしてコンパイルされます。By default, the project compiles as unmanaged code. ただし、WPFWPF はマネージド コードで実装されているため、プロジェクトは状況に応じてコンパイルする必要があります。However, because WPFWPF is implemented in managed code, the project must be compiled accordingly.

  1. ソリューションエクスプローラーでプロジェクト名を右クリックし、コンテキストメニューの [プロパティ] をクリックして、[プロパティページ] ダイアログボックスを開きます。Right-click the project name in Solution Explorer and select Properties from the context menu to launch the Property Pages dialog box.

  2. 左側のウィンドウのツリービューで、[構成プロパティ] を選択します。Select Configuration Properties from the tree view in the left pane.

  3. 右ペインの [プロジェクトの既定値] の一覧から [共通言語ランタイムサポート] を選択します。Select Common Language Runtime support from the Project Defaults list in the right pane.

  4. ドロップダウンリストボックスから [共通言語ランタイムサポート (/clr) ] を選択します。Select Common Language Runtime Support (/clr) from the drop-down list box.

注意

このコンパイラ フラグを使用すると、アプリケーションでマネージド コードを使用できますが、アンマネージド コードは以前と同様にコンパイルされます。This compiler flag allows you to use managed code in your application, but your unmanaged code will still compile as before.

WPFWPF は、シングル スレッド アパートメント (STA) スレッド処理モデルを使用します。uses the single-threaded apartment (STA) threading model. WPFWPFコンテンツコードを正しく操作するには、エントリポイントに属性を適用して、アプリケーションのスレッドモデルを STA に設定する必要があります。In order to work properly with the WPFWPF content code, you must set the application's threading model to STA by applying an attribute to the entry point.

[System::STAThreadAttribute] //Needs to be an STA thread to play nicely with WPF
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{

WPF コンテンツのホスティングHosting the WPF Content

コンテンツWPFWPFは、単純なアドレス入力アプリケーションです。The WPFWPF content is a simple address entry application. それは、ユーザー名やアドレスなどを取得する複数の TextBox コントロールで構成されています。It consists of several TextBox controls to take user name, address, and so on. また、 Button [OK][キャンセル] の2つのコントロールもあります。There are also two Button controls, OK and Cancel. ユーザーが [OK] をクリックするとClick 、ボタンのイベントハンドラーによっTextBoxてコントロールからデータが収集され、それが対応するプロパティOnButtonClickedに割り当てられ、カスタムイベントが発生します。When the user clicks OK, the button's Click event handler collects the data from the TextBox controls, assigns it to corresponding properties, and raises a custom event, OnButtonClicked. ユーザーが [キャンセル] をクリックすると、 OnButtonClickedハンドラーは単にを発生させます。When the user clicks Cancel, the handler simply raises OnButtonClicked. OnButtonClicked のイベント引数オブジェクトには、どのボタンをクリックしたかを示すブール型フィールドが含まれています。The event argument object for OnButtonClicked contains a Boolean field that indicates which button was clicked.

WPFWPFコンテンツをホストするコードは、ホストウィンドウでWM_CREATE通知を行うためのハンドラーに実装されます。The code to host the WPFWPF content is implemented in a handler for the WM_CREATE notification on the host window.

case WM_CREATE :
  GetClientRect(hWnd, &rect);
  wpfHwnd = GetHwnd(hWnd, rect.right-375, 0, 375, 250);
  CreateDataDisplay(hWnd, 275, rect.right-375, 375);
  CreateRadioButtons(hWnd);
break;

メソッドGetHwndは、サイズと位置の情報と親ウィンドウハンドルを取得し、ホストWPFWPFされたコンテンツのウィンドウハンドルを返します。The GetHwnd method takes size and position information plus the parent window handle and returns the window handle of the hosted WPFWPF content.

注意

#using 名前空間に System::Windows::Interop ディレクティブを使用することはできません。You cannot use a #using directive for the System::Windows::Interop namespace. 使用すると、その名前空間の MSG 構造体と winuser.h で宣言した MSG 構造体の間で名前の競合が発生します。Doing so creates a name collision between the MSG structure in that namespace and the MSG structure declared in winuser.h. 代わりに、その名前空間のコンテンツにアクセスするための完全修飾名を使用する必要があります。You must instead use fully-qualified names to access the contents of that namespace.

HWND GetHwnd(HWND parent, int x, int y, int width, int height)
{
    System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters(
    "hi" // NAME
    );
    sourceParams->PositionX = x;
    sourceParams->PositionY = y;
    sourceParams->Height = height;
    sourceParams->Width = width;
    sourceParams->ParentWindow = IntPtr(parent);
    sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; // style
    System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
    WPFPage ^myPage = gcnew WPFPage(width, height);
    //Assign a reference to the WPF page and a set of UI properties to a set of static properties in a class
    //that is designed for that purpose.
    WPFPageHost::hostedPage = myPage;
    WPFPageHost::initBackBrush = myPage->Background;
    WPFPageHost::initFontFamily = myPage->DefaultFontFamily;
    WPFPageHost::initFontSize = myPage->DefaultFontSize;
    WPFPageHost::initFontStyle = myPage->DefaultFontStyle;
    WPFPageHost::initFontWeight = myPage->DefaultFontWeight;
    WPFPageHost::initForeBrush = myPage->DefaultForeBrush;
    myPage->OnButtonClicked += gcnew WPFPage::ButtonClickHandler(WPFButtonClicked);
    source->RootVisual = myPage;
    return (HWND) source->Handle.ToPointer();
}

アプリケーションウィンドウでコンテンツWPFWPFを直接ホストすることはできません。You cannot host the WPFWPF content directly in your application window. 代わりに、まず HwndSource コンテンツをラップするための WPFWPF オブジェクトを作成します。Instead, you first create an HwndSource object to wrap the WPFWPF content. このオブジェクトは、基本的に、コンテンツをWPFWPFホストするように設計されたウィンドウです。This object is basically a window that is designed to host a WPFWPF content. オブジェクトはHwndSource 、アプリケーションの一部であるWin32Win32ウィンドウの子として作成することによって、親ウィンドウでホストします。You host the HwndSource object in the parent window by creating it as a child of a Win32Win32 window that is part of your application. HwndSource コンストラクターのパラメーターには、Win32Win32 の子ウィンドウの作成時に CreateWindow に渡される情報とほとんど同じ情報が含まれています。The HwndSource constructor parameters contain much the same information that you would pass to CreateWindow when you create a Win32Win32 child window.

次に、 WPFWPFコンテンツオブジェクトのインスタンスを作成します。You next create an instance of the WPFWPF content object. この場合、 WPFWPF /cli を使用しC++て、コンテンツが別のWPFPageクラスとして実装されます。In this case, the WPFWPF content is implemented as a separate class, WPFPage, using C++/CLI. さらに、WPFWPF コンテンツを XAMLXAML で実装することもできます。You could also implement the WPFWPF content with XAMLXAML. ただし、これを行うには、別のプロジェクトを設定し、そのWPFWPF内容を DLL としてビルドする必要があります。However, to do so you need to set up a separate project and build the WPFWPF content as a DLL. この DLL への参照をプロジェクトに追加し、その参照を使用してWPFWPFコンテンツのインスタンスを作成することができます。You can add a reference to that DLL to your project, and use that reference to create an instance of the WPFWPF content.

コンテンツWPFWPF RootVisual へのHwndSource参照をのプロパティに割り当てることによって、子ウィンドウにコンテンツを表示します。WPFWPFYou display the WPFWPF content in your child window by assigning a reference to the WPFWPF content to the RootVisual property of the HwndSource.

次のコード行は、イベント ハンドラー WPFButtonClickedWPFWPF コンテンツの OnButtonClicked イベントにアタッチしています。The next line of code attaches an event handler, WPFButtonClicked, to the WPFWPF content OnButtonClicked event. このハンドラーは、ユーザーが [OK] または [キャンセル] ボタンをクリックしたときに呼び出されます。This handler is called when the user clicks the OK or Cancel button. このイベントハンドラーの詳細については、「 communicating_with_the_WPF content 」を参照してください。See communicating_with_the_WPF content for further discussion of this event handler.

示されているコードの最後の行は、HwndSource オブジェクトに関連付けられているウィンドウ ハンドル (HWND) を返します。The final line of code shown returns the window handle (HWND) that is associated with the HwndSource object. このハンドルは、Win32Win32 コードから使用してホストされたウィンドウにメッセージを送信することができます。ただし、サンプルではこれはできません。You can use this handle from your Win32Win32 code to send messages to the hosted window, although the sample does not do so. HwndSource オブジェクトは、メッセージを受信するたびにイベントを発生させます。The HwndSource object raises an event every time it receives a message. メッセージを処理するには、AddHook メソッドを呼び出してメッセージ ハンドラーをアタッチしてから、そのハンドラーでメッセージを処理します。To process the messages, call the AddHook method to attach a message handler and then process the messages in that handler.

WPF コンテンツへの参照の保持Holding a Reference to the WPF Content

多くのアプリケーションでは、後で WPFWPF コンテンツと通信することができます。For many applications, you will want to communicate with the WPFWPF content later. たとえば、WPFWPF コンテンツのプロパティを変更したり、場合によっては HwndSource オブジェクトが異なる WPFWPF コンテンツをホストするようにしたりできます。For example, you might want to modify the WPFWPF content properties, or perhaps have the HwndSource object host different WPFWPF content. そのためには、HwndSource オブジェクトまたは WPFWPF コンテンツへの参照が必要です。To do this, you need a reference to the HwndSource object or the WPFWPF content. HwndSource オブジェクトと関連する WPFWPF コンテンツは、ウィンドウ ハンドルを破棄するまでメモリに残ります。The HwndSource object and its associated WPFWPF content remain in memory until you destroy the window handle. ただし、HwndSource オブジェクトに割り当てる変数は、ウィンドウ プロシージャから戻ると同時にスコープの外に出ます。However, the variable you assign to the HwndSource object will go out of scope as soon as you return from the window procedure. Win32Win32 アプリケーションでこの問題を処理するためによく使用される方法は、静的変数またはグローバル変数を使用することです。The customary way to handle this issue with Win32Win32 applications is to use a static or global variable. 残念ながら、このような変数の種類に対してマネージド オブジェクトを割り当てることはできません。Unfortunately, you cannot assign a managed object to those types of variables. HwndSource オブジェクトに関連付けられているウィンドウ ハンドルを、グローバル変数または静的変数に割り当てることができますが、オブジェクト自体にアクセスすることはできません。You can assign the window handle associated with HwndSource object to a global or static variable, but that doe not provide access to the object itself.

この問題の最も簡単な解決法は、静的フィールドのセットを含むマネージド クラスを実装して、アクセスが必要なすべてのマネージド オブジェクトへの参照を保持することです。The simplest solution to this issue is to implement a managed class that contains a set of static fields to hold references to any managed objects that you need access to. サンプルでは、WPFPageHost クラスを使用して、WPFWPF コンテンツへの参照、および後でユーザーが変更する可能性があるプロパティの数の初期値を保持します。The sample uses the WPFPageHost class to hold a reference to the WPFWPF content, plus the initial values of a number of its properties that might be changed later by the user. これは、ヘッダーで定義します。This is defined in the header.

public ref class WPFPageHost
{
public:
  WPFPageHost();
  static WPFPage^ hostedPage;
  //initial property settings
  static System::Windows::Media::Brush^ initBackBrush;
  static System::Windows::Media::Brush^ initForeBrush;
  static System::Windows::Media::FontFamily^ initFontFamily;
  static System::Windows::FontStyle initFontStyle;
  static System::Windows::FontWeight initFontWeight;
  static double initFontSize;
};

GetHwnd 関数の後半部分では、後に、myPage がスコープ内にある間に使用するため、対象のフィールドに値を割り当てます。The latter part of the GetHwnd function assigns values to those fields for later use while myPage is still in scope.

WPF コンテンツとの通信Communicating with the WPF Content

WPFWPF コンテンツとの通信には次の 2 種類があります。There are two types of communication with the WPFWPF content. アプリケーションは、ユーザーがWPFWPF [OK] ボタンまたは [キャンセル] ボタンをクリックすると、コンテンツから情報を受け取ります。The application receives information from the WPFWPF content when the user clicks the OK or Cancel buttons. アプリケーションには、背景色や既定のフォント サイズなどのさまざまな UIUI コンテンツのプロパティをユーザーが変更できるようにする WPFWPF があります。The application also has a UIUI that allows the user to change various WPFWPF content properties, such as the background color or default font size.

前述のように、ユーザーがいずれかのボタンをクリックすると、WPFWPF コンテンツは OnButtonClicked イベントを発生させます。As mentioned above, when the user clicks either button the WPFWPF content raises an OnButtonClicked event. アプリケーションは、これらの通知を受信するため、このイベントにハンドラーをアタッチします。The application attaches a handler to this event to receive these notifications. [OK ] ボタンがクリックされた場合、ハンドラーはWPFWPFコンテンツからユーザー情報を取得し、一連の静的コントロールに表示します。If the OK button was clicked, the handler gets the user information from the WPFWPF content and displays it in a set of static controls.

void WPFButtonClicked(Object ^sender, MyPageEventArgs ^args)
{
    if(args->IsOK) //display data if OK button was clicked
    {
        WPFPage ^myPage = WPFPageHost::hostedPage;
        LPCWSTR userName = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Name: " + myPage->EnteredName).ToPointer();
        SetWindowText(nameLabel, userName);
        LPCWSTR userAddress = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Address: " + myPage->EnteredAddress).ToPointer();
        SetWindowText(addressLabel, userAddress);
        LPCWSTR userCity = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("City: " + myPage->EnteredCity).ToPointer();
        SetWindowText(cityLabel, userCity);
        LPCWSTR userState = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("State: " + myPage->EnteredState).ToPointer();
        SetWindowText(stateLabel, userState);
        LPCWSTR userZip = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Zip: " + myPage->EnteredZip).ToPointer();
        SetWindowText(zipLabel, userZip);
    }
    else
    {
        SetWindowText(nameLabel, L"Name: ");
        SetWindowText(addressLabel, L"Address: ");
        SetWindowText(cityLabel, L"City: ");
        SetWindowText(stateLabel, L"State: ");
        SetWindowText(zipLabel, L"Zip: ");
    }
}

ハンドラーは、カスタム イベント引数オブジェクトを WPFWPF のコンテンツ、MyPageEventArgs から受信します。The handler receives a custom event argument object from the WPFWPF content, MyPageEventArgs. [OK ] ボタンがクリックされた場合、およびfalse [キャンセル] ボタンがクリックされた場合、オブジェクトのIsOKプロパティはにtrue設定されます。The object's IsOK property is set to true if the OK button was clicked, and false if the Cancel button was clicked.

[OK ] ボタンがクリックされた場合、ハンドラーはコンテナー WPFWPFクラスからコンテンツへの参照を取得します。If the OK button was clicked, the handler gets a reference to the WPFWPF content from the container class. その後、関連する WPFWPF コンテンツ プロパティが保持するユーザー情報を収集し、静的コントロールを使用して親ウィンドウに情報を表示します。It then collects the user information that is held by the associated WPFWPF content properties and uses the static controls to display the information on the parent window. WPFWPF コンテンツ データは、マネージド文字列の形式であるため、Win32Win32 コントロールによってマーシャリングする必要があります。Because the WPFWPF content data is in the form of a managed string, it has to be marshaled for use by a Win32Win32 control. [キャンセル] ボタンがクリックされた場合、ハンドラーは静的コントロールからデータをクリアします。If the Cancel button was clicked, the handler clears the data from the static controls.

アプリケーション UIUI には、ユーザーが WPFWPF コンテンツの背景色を変更できるようにするラジオ ボタンのセット、および複数のフォント関連のプロパティが用意されています。The application UIUI provides a set of radio buttons that allow the user to modify the background color of the WPFWPF content, and several font-related properties. 次の例は、アプリケーションのウィンドウ プロシージャ (WndProc)、および背景色など、各種のメッセージに対してさまざまなプロパティを設定するそのプロシージャのメッセージ処理からの抜粋です。The following example is an excerpt from the application's window procedure (WndProc) and its message handling that sets various properties on different messages, including the background color. その他は類似しているため、示していません。The others are similar, and are not shown. 詳細とコンテキストについては、完全なサンプルを参照してください。See the complete sample for details and context.

case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);

  switch (wmId)
  {
  //Menu selections
    case IDM_ABOUT:
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    break;
    case IDM_EXIT:
      DestroyWindow(hWnd);
    break;
    //RadioButtons
    case IDC_ORIGINALBACKGROUND :
      WPFPageHost::hostedPage->Background = WPFPageHost::initBackBrush;
    break;
    case IDC_LIGHTGREENBACKGROUND :
      WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightGreen);
    break;
    case IDC_LIGHTSALMONBACKGROUND :
      WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightSalmon);
    break;

背景色を設定するには、WPFWPF から hostedPage コンテンツ (WPFPageHost) への参照を取得して、背景色のプロパティを適切な色に設定します。To set the background color, get a reference to the WPFWPF content (hostedPage) from WPFPageHost and set the background color property to the appropriate color. サンプルでは、元の色、明るい緑、または明るいサーモン色の 3 つの色のオプションを使用します。The sample uses three color options: the original color, light green, or light salmon. 元の背景色は静的フィールドとして WPFPageHost クラスに格納されます。The original background color is stored as a static field in the WPFPageHost class. 他の 2 つの色を設定するには、新しい SolidColorBrush オブジェクトを作成して、Colors オブジェクトからコンストラクターに静的な色の値を渡します。To set the other two, you create a new SolidColorBrush object and pass the constructor a static colors value from the Colors object.

WPF ページの実装Implementing the WPF Page

実際の実装についてWPFWPFの知識がなくても、コンテンツをホストして使用することができます。You can host and use the WPFWPF content without any knowledge of the actual implementation. コンテンツがWPFWPF別の DLL にパッケージ化されている場合は、任意の共通言語ランタイム (CLR) 言語でビルドされている可能性があります。If the WPFWPF content had been packaged in a separate DLL, it could have been built in any common language runtime (CLR) language. 次に、サンプルで使用さC++れる/cli 実装の簡単なチュートリアルを示します。Following is a brief walkthrough of the C++/CLI implementation that is used in the sample. このセクションには、次のサブセクションが含まれています。This section contains the following subsections.

レイアウトLayout

コンテンツ内の要素はUIUI 、コントロールがTextBox関連付けられLabelた5つのコントロールで構成されます。 WPFWPF名前、住所、市区町村、都道府県、および郵便番号。The UIUI elements in the WPFWPF content consist of five TextBox controls, with associated Label controls: Name, Address, City, State, and Zip. また、 Button [OK][キャンセル] の2つのコントロールもあります。There are also two Button controls, OK and Cancel

WPFWPF コンテンツは WPFPage クラスに実装されています。The WPFWPF content is implemented in the WPFPage class. レイアウトは、Grid レイアウト要素で処理されます。Layout is handled with a Grid layout element. クラスは Grid から継承されます。これにより、クラスは効果的に WPFWPF コンテンツのルート要素になります。The class inherits from Grid, which effectively makes it the WPFWPF content root element.

コンテンツWPFWPFコンストラクターは、必要な幅と高さを取得し、 Gridそれに応じてサイズを調整します。The WPFWPF content constructor takes the required width and height, and sizes the Grid accordingly. 次に、 ColumnDefinitionオブジェクトとRowDefinitionオブジェクトのセットを作成Gridし、それらをオブジェクトのベースColumnDefinitionsRowDefinitionsコレクションにそれぞれ追加することによって、基本的なレイアウトを定義します。It then defines the basic layout by creating a set of ColumnDefinition and RowDefinition objects and adding them to the Grid object base ColumnDefinitions and RowDefinitions collections, respectively. これにより、5 つの行と、7 つの列のグリッドが定義され、セルの内容によって大きさが決定します。This defines a grid of five rows and seven columns, with the dimensions determined by the contents of the cells.

WPFPage::WPFPage(int allottedWidth, int allotedHeight)
{
  array<ColumnDefinition ^> ^ columnDef = gcnew array<ColumnDefinition ^> (4);
  array<RowDefinition ^> ^ rowDef = gcnew array<RowDefinition ^> (6);

  this->Height = allotedHeight;
  this->Width = allottedWidth;
  this->Background = gcnew SolidColorBrush(Colors::LightGray);
  
  //Set up the Grid's row and column definitions
  for(int i=0; i<4; i++)
  {
    columnDef[i] = gcnew ColumnDefinition();
    columnDef[i]->Width = GridLength(1, GridUnitType::Auto);
    this->ColumnDefinitions->Add(columnDef[i]);
  }
  for(int i=0; i<6; i++)
  {
    rowDef[i] = gcnew RowDefinition();
    rowDef[i]->Height = GridLength(1, GridUnitType::Auto);
    this->RowDefinitions->Add(rowDef[i]);
  }

次に、コンストラクターは UIUI 要素を Grid に追加します。Next, the constructor adds the UIUI elements to the Grid. 最初の要素はタイトルのテキストです。これは、グリッドの 1 行目の中央に表示される Label コントロールです。The first element is the title text, which is a Label control that is centered in the first row of the grid.

//Add the title
titleText = gcnew Label();
titleText->Content = "Simple WPF Control";
titleText->HorizontalAlignment = System::Windows::HorizontalAlignment::Center;
titleText->Margin = Thickness(10, 5, 10, 0);
titleText->FontWeight = FontWeights::Bold;
titleText->FontSize = 14;
Grid::SetColumn(titleText, 0);
Grid::SetRow(titleText, 0);
Grid::SetColumnSpan(titleText, 4);
this->Children->Add(titleText);

次の行には、名前の Label コントロールと関連する TextBox コントロールが格納されます。The next row contains the Name Label control and its associated TextBox control. ラベルとテキスト ボックスの各ペアに同じコードが使用されるため、コードはプライベート メソッドのペアに配置され、5 つのラベルとテキスト ボックスのペアすべてに使用されます。Because the same code is used for each label/textbox pair, it is placed in a pair of private methods and used for all five label/textbox pairs. メソッドは適切な制御を作成し、Grid クラスの静的な SetColumn および SetRow メソッドを呼び出して、適切なセルにコントロールを配置します。The methods create the appropriate control, and call the Grid class static SetColumn and SetRow methods to place the controls in the appropriate cell. コントロールが作成されると、サンプルは AddChildren プロパティの Grid メソッドを呼び出して、グリッドにコントロールを追加します。After the control is created, the sample calls the Add method on the Children property of the Grid to add the control to the grid. 残りのラベルとテキスト ボックスのペアを追加するコードは似ています。The code to add the remaining label/textbox pairs is similar. 詳細については、サンプル コードを参照してください。See the sample code for details.

//Add the Name Label and TextBox
nameLabel = CreateLabel(0, 1, "Name");
this->Children->Add(nameLabel);
nameTextBox = CreateTextBox(1, 1, 3);
this->Children->Add(nameTextBox);

2 つのメソッドの実装は、次のとおりです。The implementation of the two methods is as follows:

Label ^WPFPage::CreateLabel(int column, int row, String ^ text)
{
  Label ^ newLabel = gcnew Label();
  newLabel->Content = text;
  newLabel->Margin = Thickness(10, 5, 10, 0);
  newLabel->FontWeight = FontWeights::Normal;
  newLabel->FontSize = 12;
  Grid::SetColumn(newLabel, column);
  Grid::SetRow(newLabel, row);
  return newLabel;
}
TextBox ^WPFPage::CreateTextBox(int column, int row, int span)
{
  TextBox ^newTextBox = gcnew TextBox();
  newTextBox->Margin = Thickness(10, 5, 10, 0);
  Grid::SetColumn(newTextBox, column);
  Grid::SetRow(newTextBox, row);
  Grid::SetColumnSpan(newTextBox, span);
  return newTextBox;
}

最後に、このサンプルでは、 [OK] ボタンと [キャンセル] ボタンClickを追加し、イベントにイベントハンドラーをアタッチします。Finally, the sample adds the OK and Cancel buttons and attaches an event handler to their Click events.

//Add the Buttons and atttach event handlers
okButton = CreateButton(0, 5, "OK");
cancelButton = CreateButton(1, 5, "Cancel");
this->Children->Add(okButton);
this->Children->Add(cancelButton);
okButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);
cancelButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);

データをホスト ウィンドウに返すReturning the Data to the Host Window

いずれかのボタンをクリックすると、その Click イベントが発生します。When either button is clicked, its Click event is raised. ホスト ウィンドウはこれらのイベントにハンドラーをアタッチして、TextBox コントロールから直接データを取得します。The host window could simply attach handlers to these events and get the data directly from the TextBox controls. サンプルは、いくぶん直接的ではない方法を使用します。The sample uses a somewhat less direct approach. Click WPFWPFコンテンツ内のを処理し、カスタムイベントOnButtonClickedを発生させてコンテンツを通知します。 WPFWPFIt handles the Click within the WPFWPF content, and then raises a custom event OnButtonClicked, to notify the WPFWPF content. これによりWPFWPF 、コンテンツは、ホストに通知する前にパラメーターの検証を行うことができます。This allows the WPFWPF content to do some parameter validation before notifying the host. ハンドラーは、TextBox コントロールからテキストを取得し、パブリック プロパティに割り当てます。ここからホストは情報を取得します。The handler gets the text from the TextBox controls and assigns it to public properties, from which the host can retrieve the information.

WPFPage.h でのイベント宣言:The event declaration, in WPFPage.h:

public:
  delegate void ButtonClickHandler(Object ^, MyPageEventArgs ^);
  WPFPage();
  WPFPage(int height, int width);
  event ButtonClickHandler ^OnButtonClicked;

WPFPage.cpp での Click イベント ハンドラー:The Click event handler, in WPFPage.cpp:

void WPFPage::ButtonClicked(Object ^sender, RoutedEventArgs ^args)
{

  //TODO: validate input data
  bool okClicked = true;
  if(sender == cancelButton)
    okClicked = false;
  EnteredName = nameTextBox->Text;
  EnteredAddress = addressTextBox->Text;
  EnteredCity = cityTextBox->Text;
  EnteredState = stateTextBox->Text;
  EnteredZip = zipTextBox->Text;
  OnButtonClicked(this, gcnew MyPageEventArgs(okClicked));
}

WPF のプロパティを設定するSetting the WPF Properties

ホストWin32Win32では、ユーザーがいくつかWPFWPFのコンテンツプロパティを変更できます。The Win32Win32 host allows the user to change several WPFWPF content properties. Win32Win32 側では、これはプロパティの変更の問題にすぎません。From the Win32Win32 side, it is simply a matter of changing the properties. WPFWPF のコンテンツ クラスの実装はいくらか複雑になります。これは、全コントロールのフォントを制御する 1 つのグローバル プロパティがないためです。The implementation in the WPFWPF content class is somewhat more complicated, because there is no single global property that controls the fonts for all controls. 代わりに、各コントロールの適切なプロパティは、プロパティの set アクセサーで変更されます。Instead, the appropriate property for each control is changed in the properties' set accessors. 次の例は、 DefaultFontFamilyプロパティのコードを示しています。The following example shows the code for the DefaultFontFamily property. プロパティを設定すると、プライベート メソッドが呼び出され、さまざまなコントロールに FontFamily プロパティが設定されます。Setting the property calls a private method that in turn sets the FontFamily properties for the various controls.

WPFPage.h から:From WPFPage.h:

property FontFamily^ DefaultFontFamily
{
  FontFamily^ get() {return _defaultFontFamily;}
  void set(FontFamily^ value) {SetFontFamily(value);}
};

WPFPage.cpp から:From WPFPage.cpp:

void WPFPage::SetFontFamily(FontFamily^ newFontFamily)
{
  _defaultFontFamily = newFontFamily;
  titleText->FontFamily = newFontFamily;
  nameLabel->FontFamily = newFontFamily;
  addressLabel->FontFamily = newFontFamily;
  cityLabel->FontFamily = newFontFamily;
  stateLabel->FontFamily = newFontFamily;
  zipLabel->FontFamily = newFontFamily;
}

関連項目See also