雖 WPF 功能強大,但成熟的 Win32 控件仍具不可替代價值。整合流程始於定義 WNDCLASSEX 結構、註冊視窗類別、呼叫 CreateWindowEx 建立子視窗,最後透過 ShowWindow 顯示。核心步驟如下:
WNDCLASSEX wndClsEx = new WNDCLASSEX();
wndClsEx.Init();
wndClsEx.style = WndClassType.CS_VREDRAW | WndClassType.CS_HREDRAW;
wndClsEx.lpfnWndProc = new WndProcDelegate(User32Dll.DefWindowProc);
wndClsEx.hInstance = Kernal32Dll.GetModuleHandle(null);
wndClsEx.lpszClassName = m_WndClsName;
bool success = User32Dll.RegisterClassEx(ref wndClsEx) != 0;
IntPtr windowHandle = User32Dll.CreateWindowEx(
ExtendedWndStyle.WS_EX_LAYOUTRTL, m_WndClsName, null,
WndStyle.WS_VISIBLE | WndStyle.WS_CHILD,
this.Left, this.Top, this.Width, this.Height,
this.Parent.Handle, IntPtr.Zero,
Kernal32Dll.GetModuleHandle(null), IntPtr.Zero);
WPF 視覺樹與 Win32 HWND 屬不同渲染層,存在「空域」問題導致像素無法互通。HwndHost 類別封裝了視窗父子關係、訊息迴路、鍵盤導航等複雜邏輯,開發者僅需繼承並覆寫 BuildWindowCore 回傳 HandleRef:
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
UserControl1 userControl = new UserControl1();
userControl.Height = hostHeight;
userControl.Width = hostWidth;
User32Dll.SetParent(userControl.Handle, hwndParent.Handle);
return new HandleRef(userControl, userControl.Handle);
}
WPF 無法直接對 Win32 控件套用 Transform,需自行計算矩陣並透過訊息傳遞。以二維旋轉為例,點 P(x,y) 繞原點逆時針旋轉 α 度後座標推導:
x1 = x * cos(α) - y * sin(α) y1 = y * cos(α) + x * sin(α)
引入齊次座標後,平移、旋轉、縮放可統一為 3×3 矩陣乘法。WPF 當前裝置變換矩陣可透過 PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice 取得。
將矩陣參數傳遞給 Win32 控件需使用 SendMessage 搭配 COPYDATASTRUCT 結構。序列化物件至記憶體區塊,透過 Marshal.AllocHGlobal 分配非託管記憶體,接收端再反序列化還原:
public struct CopyDataStruct
{
public int cbData;
public IntPtr lpData;
}
// 發送端
BinaryFormatter formatter = new BinaryFormatter();
byte[] datas;
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, matrix);
datas = ms.ToArray();
}
IntPtr ptr = Marshal.AllocHGlobal(datas.Length);
Marshal.Copy(datas, 0, ptr, datas.Length);
CopyDataStruct data = new CopyDataStruct { cbData = datas.Length, lpData = ptr };
SendMessage(hwndListBox, 700, 0, ref data);
Marshal.FreeHGlobal(ptr);
透過 HwndHost 封裝與矩陣變換同步,可實現 WPF 與 Win32 控件的深度整合。