本文配套源码
虽然WPF很强大,但是有些东西win32做的已经很好,我们完全可以拿来主义。
一.如何创建一 个win32控件
1.首先定义一个WNDCLASSEX的类,参考 http://baike.baidu.com/view/1750396.html?tp=0_11
WNDCLASSEX wndClsEx = new WNDCLASSEX();
wndClsEx.Init();//(uint)Marshal.SizeOf(this);得到类的大小
wndClsEx.style = WndClassType.CS_VREDRAW | WndClassType.CS_HREDRAW;//窗口的风格
wndClsEx.lpfnWndProc = new WndProcDelegate(User32Dll.DefWindowProc);//处理类的消息,这 里用的是默认处理
wndClsEx.cbClsExtra = 0;//指定紧跟在窗口类结构后的附加字节数
wndClsEx.cbWndExtra = 0;//如果一个应用程序在资源中用CLASS伪指令注册一个对话框类时,则必 须把这个成员设成DLGWINDOWEXTRA
wndClsEx.hInstance = Kernal32Dll.GetModuleHandle (null);//模块的句柄
wndClsEx.hIcon = IntPtr.Zero;//图标句柄
wndClsEx.hIconSm = IntPtr.Zero;//和窗口类关联的小图标。如果该值为NULL。则把hCursor中的图标转换成大小合适的小 图标。
wndClsEx.hCursor = IntPtr.Zero;//光标句柄
wndClsEx.hbrBackground = IntPtr.Zero;//背景画刷句柄
wndClsEx.lpszClassName = m_WndClsName;//定义自己的类名, 比如curry,或XXX
wndClsEx.lpszMenuName = null;//菜单名称
2.注册类,返回 值非0为成功
bool success = User32Dll.RegisterClassEx(ref wndClsEx) != 0;
Debug.Assert(success, "RegisterWndClass failed.");
3.创建 窗口,参考http://baike.baidu.com/view/1080304.htm
IntPtr windowHandle = User32Dll.CreateWindowEx(ExtendedWndStyle.WS_EX_LAYOUTRTL//扩展样式
, m_WndClsName //刚才注册完的名称
, null //窗体名称
, WndStyle.WS_VISIBLE | WndStyle.WS_CHILD //子窗体
, this.Left //X坐标
, this.Top //Y 坐标
, this.Width //宽度
, this.Height //高度
, this.Parent.Handle //父对象句柄
, IntPtr.Zero //上下文菜单句柄
, Kernal32Dll.GetModuleHandle(null)//实例句柄
, IntPtr.Zero//指向一个值的指针,该值传递给窗口 WM_CREATE消息
);
Debug.Assert(User32Dll.IsWindow(windowHandle), "CreateWindowEx failed.");
如果你想参考其它窗口的样式的信息的话,可以用Spy++这个工具看
4.显示窗口
User32Dll.ShowWindow(windowHandle, (int) (this.Visible ? WindowShowStyle.Show : WindowShowStyle.Hide));
5.销毁窗口 ,注销类
User32Dll.DestroyWindow(windowHandle);
windowHandle = IntPtr.Zero;
User32Dll.UnregisterClass(m_WndClsName, Kernal32Dll.GetModuleHandle(null));
二.把Win32控件放到WPF
其实放到WPF中 这个只是视觉的假象,我们的顶级窗口如Window,Popup也都是通过CreateWindowEx创建出来的,(当然菜 单也是CreateWindowEx)所以我们创建的Win32控件的Parent一般都是顶级窗口,IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(uielement)).Handle; 得到的句柄是顶级窗体的句柄, 因为WPF和GDI+ 的渲染层不一样,两者因为“空域”问题使得像素不能交互,具体的见 http://msdn.microsoft.com/zh-cn/library/aa970688.aspx。
在win32时代有时候把窗体弄成不 规则透明图形时可能会作的事,这里也记录下:参考自 http://www.codeproject.com/KB/dialog/SemiTranDlgWithCtrls.aspx
xp及以上版本中可以使用 UpdateLayeredWindow创建类似PGN图片带ALPHA通道的窗口。
把窗口扩展样式设置为 ExtendedWndStyle.WS_EX_LAYERED |ExtendedWndStyle.WS_E |