共用方式為


教學課程:在 Win32 應用程式中裝載視覺物件

更新:2007 年 11 月

Windows Presentation Foundation (WPF) 提供用來建立應用程式的豐富環境。不過,若您已對 Win32 程式碼投入相當的心力,更有效的方法是將 WPF 功能加入應用程式,而不是重新撰寫程式碼。為了提供在應用程式中同時 Win32 和 WPF 圖形子系統的支援,WPF 提供了一種將物件裝載在 Win32 視窗中的機制。

本教學課程說明如何撰寫下列範例應用程式:使用 Win32 互通性進行點擊測試範例;這個範例應用程式將 WPF 視覺物件裝載在 Win32 視窗中。

這個主題包含下列章節。

  • 需求
  • 建立裝載 Win32 視窗
  • 將視覺物件加入至裝載 Host Win32 視窗
  • 實作 Win32 訊息篩選
  • 處理 Win32 訊息
  • 相關主題

需求

本教學課程假設您已熟悉 WPF 和 Win32 程式設計的基本概念。如需 WPF 程式設計的基本簡介,請參閱 Windows Presentation Foundation 使用者入門。如需 Win32 程式設計的簡介,請參閱討論此主題的各種書籍,尤其是 Charles Petzold 所著的《Programming Windows》。

注意事項:

本教學課程包括摘錄自相關範例的許多程式碼範例。不過,為了方便閱讀,此課程並未包含完整的範例程式碼。如需完整的範例程式碼,請參閱使用 Win32 互通性進行點擊測試範例

建立裝載 Win32 視窗

將 WPF 物件裝載在 Win32 視窗的關鍵是 HwndSource 類別。這個類別會將 WPF 物件包裝在 Win32 視窗中,讓您可以將這些物件當做子視窗加入使用者介面 (UI) 中。

下列範例顯示的程式碼可用來建立 HwndSource 物件,以做為視覺物件的 Win32 容器 (Container) 視窗。若要設定 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 視窗的背景色彩會設定成與其父視窗相同的背景色彩。

將視覺物件加入至裝載 Host Win32 視窗

建立視覺物件的裝載 Win32 容器視窗之後,您就可以將視覺物件加入視窗中。您必須確定視覺物件的任何變化 (例如動畫) 都不會超過裝載 Win32 視窗週框 (Bounding Rectangle) 的範圍。

下列範例顯示的程式碼可用來建立 HwndSource 物件,並將視覺物件加入其中。

注意事項:

HwndSource 物件的 RootVisual 屬性設定為已加入至裝載 Win32 視窗的第一個視覺物件。這個根 (Root) 視覺物件定義了視覺物件樹狀結構的最上層節點。後續加入至裝載 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 視窗需要使用視窗訊息篩選程序來處理從應用程式佇列 (Queue) 傳送到視窗的訊息。視窗程序會接收 Win32 系統傳來的訊息。這些訊息可能是輸入訊息或視窗管理訊息。您可以選擇在視窗程序中處理訊息,或是將訊息傳送給系統進行預設處理。

已定義為視覺物件父代 (Parent) 的 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();
    }
}

如需對視覺物件進行點擊測試的詳細資訊,請參閱視覺分層中的點擊測試

請參閱

工作

使用 Win32 互通性進行點擊測試範例

概念

視覺分層中的點擊測試

參考

HwndSource