将WPF的文本框转换为IWin32Window(WinForm)。
WPF中的TextBox控件不像Win32中的控件那样使用Win32句柄,只有窗口本身才使用Win32句柄。换句话说,从Win32的角度来看,整个WPF窗口对象是一个具有单个句柄的窗口。
因此,为IWin32Window返回WPF TextBox的“实际”Win32句柄是没有意义的:WPF TextBox根本没有Win32句柄。因此,您将需要返回其他对象的Win32句柄。
如何做这取决于您将如何使用IWin32Window。有几种可能的方法可以创建与您的TextBox对应的Win32窗口:
1. 您可以创建一个与TextBox重叠的透明Win32窗口(用于命中测试或覆盖绘制场景)
2. 您可以创建一个大小为零且位于TextBox居中的窗口(用于对话框初始位置和所有权场景)
3. 您可以将TextBox托管到一个ElementHost中,而不是WPF窗口(如果您希望TextBox与其他Win32内容(例如旧的MFC应用程序)相适应,则很有用)
4. 您可以将TextBox托管到WindowsFormsHost中的ElementHost中(如果您需要一个围绕TextBox的Win32窗口,但仍然需要WPF布局,则很有用)
关于“额外窗口”解决方案(1和2)的说明:
要创建一个覆盖TextBox的Win32窗口(透明或大小为零),您可以使用传统的Win32或WinForms技术。
由于TextBox可以在屏幕上移动,因此您需要在TextBox移动时移动Win32窗口。可以在OnRendering事件中使用textBox.TransformToAncestor(window)来转换为设备坐标。
关于ElementHost解决方案(3和4)的说明:
将ElementHost包装在XAML中的TextBox周围非常简单,例如:
...
可以变成:
...
也可以通过从父级中删除TextBox,将其添加到新创建的ElementHost中,然后将ElementHost添加到新创建的WindowsFormsHost中,再将WindowsFormsHost添加回父级中来实现。
请注意,WPF样式和属性(包括DataContext、TextElement属性等)不会通过ElementHost传播下去,即使包装在WindowsFormsHost中,因此必须手动传播所需的设置和资源。