1. 程式人生 > >WPF與Win32互操作

WPF與Win32互操作

如何 guid 生命周期 parameter gpa 指定 combo zed inter

一、WPF如何使用HWND

當您創建WPF Window時,WPF會創建頂級HWND,並使用HwndSource將Window及其WPF內容放入HWND中。應用程序中其余的WPF內容共享此單個HWND。不過,菜單、組合框下拉列表和其他彈出窗口例外。 這些元素創建它們自己的頂級窗口,這正是 WPF 菜單能跳出包含它的窗口 HWND 之外的原因。

二、HwndSource類

一個HwndSource實現Win32窗口可以包含WPF內容。在窗口中的WPF內容是可安排的,可測量的,和可渲染的;是可交互式輸入的。因為HwndSource是專被設計來與Win32進行交互的,這個類展示了底層的Win32的特點。您可以使用這個類執行以下操作:

  • 指定窗口樣式、窗口類樣式和擴展窗口樣式。
  • 在窗口程序的鉤子中添加處理函數。
  • 提供窗口句柄(HWND)。
  • 銷毀窗口。

HwndSource類被設計來用於處理一般的互操作,並不是被設計成一個包裝管理HWND的角色。一般來說,它不提供用於管理窗口或檢查屬性狀態的托管方法。相反,該HwndSource類可以通過Handle屬性訪問Win32窗口句柄(HWND),可以通過PInvoke Win32 API技術操作窗口。
1 創建
HwndSource只能在構造時被指定。創建一個HwndSource,首先要創建一個HwndSourceParameters結構並用所需的參數填充它。這些參數包括以下內容:

  • 類、窗口和擴展的窗口樣式。您必須在窗口被創建前使用PInvoke去改變樣式。並非所有樣式都可以在創建窗口後更改。更改窗口樣式之前請參考win32文檔。
  • 窗口的初始位置。
  • 窗口的初始大小,包括是否指定尺寸或以WPF內容大小的確定窗口的大小。
  • 父窗口。
  • HwndSourceHook包括窗口的處理函數鏈。如果在構建時指定鉤子,它將接收窗口的所有消息。你可以使用AddHook後創建窗口添加一個鉤子。
  • 透明度設置。

2 對象生存周期
HwndSource是正規的公共語言運行庫(CLR)對象,其生命周期是由垃圾收集器管理。因為HwndSource代表非托管資源,所以HwndSource實現IDisposable接口。如果從所有者線程調用,同步調用處理立即破壞win32窗口。如果從另一個線程調用,win32窗口將異步銷毀。在互操作的代碼中顯式調用Dispose可能對某些互操作場景是必要的。
3 窗口處理函數


HwndSource類實現了它自己的窗口處理函數。此窗口處理函數用於處理重要的窗口消息,如與布局、呈現和輸入相關的消息。不過,您也可以在鉤子上添加自己的處理函數。你可以在構造時,通過設置HwndSourceParameters.HwndSourceHook屬性,在鉤子中指定自己的處理函數,或者你也可以使用AddHook和RemoveHook在窗口創建之後添加和刪除鉤子中的處理函數。

三、HwndSource類

該例子中在鉤子中擴展處理函數。

// 在Window類中
protected overried void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    // 獲取窗體句柄
    IntPtr hwnd = new WindowInteropHelper(this).Handle;
    // 獲取HwndSource對象
    HwndSource hwndSource = HwndSource.FromHwnd(hwnd);
    // 向鉤子中添加處理程序
    if(hwndSource != null)
        hwndSource.AddHook(WndProc);
}

private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wideParam, IntPtr longParam, ref bool handled)
{
    swicth(msg)
    {
        // 對特定消息進行處理
    }
    return IntPtr.Zero;
}

WPF與Win32互操作