ElementHost 阻止鼠标事件
ElementHost blocks mouse events
注意:我正在尝试解决鼠标问题,而不是键盘问题,键盘问题已经解决
所以我正在创建一个 Visual Studio 2015 扩展,在选项页面上工作。
我使用的是 WPF,所以我使用 ElementHost 来托管 UserControl。起初它没有接收到键盘事件,所以我在以下位置实施了解决方案:
WPF TextBox not accepting Input when in ElementHost in Window Forms
快速 运行 解决方案:
A) 在 UserControl 的 Loaded 事件上,我这样做:
var s = HwndSource.FromVisual(this) as HwndSource;
s?.AddHook(ChildHwndSourceHook);
B) 在 ChildHwndSourceHook() 中,我做了类似的事情:
static IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_GETDLGCODE)
{
handled = true;
return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTTAB);
}
return IntPtr.Zero;
}
但是,现在鼠标悬停在事件上似乎被忽略了,因为光标在文本框或网格分隔符上移动时不会改变,甚至在我创建的新 Windows 上也不会改变。 偶尔,不过,鼠标事件确实起作用,并且会继续起作用,直到我移动到另一个页面或关闭对话框。这是最奇怪的部分。
我已经尝试了所有方法并搜索了 Google 一整天,但我并没有进一步理解为什么点击可以正常工作,但鼠标悬停事件似乎没有被注册。
我确实尝试删除消息处理程序,然后打开一个 Window,但似乎一旦添加了处理程序,删除它就不会解决任何问题。
有谁知道如何让鼠标悬停在事件上以在我的控件上工作?非常感谢!
我使用创建者 Viasfora 使用的方法取得了成功。你可以在GitHub repo here上看到代码。特别是查看 TextObfuscationDialog 及其托管方式。我相信 VS 扩展文档可能有问题,因为我 运行 遇到了你遇到的同样问题。
编辑:
我已经创建了一个示例项目来展示此方法是否有效(我现在正在我自己的 2 个扩展中使用它)。希望这段工作代码可以让您更轻松地在自己的项目中实施它。
您可以从我的 OneDrive here 下载源代码。
UIElementDialogPage
on MSDN 说:
Provides seamless hosting of Windows Presentation Foundation (WPF)
content inside a native dialog running an IsDialogMessage-style
message loop. This class enables tabbing into and out of the WPF child
window handle (HWND), and enables keyboard navigation within the WPF
child HWND.
因此,虽然 ElementHost
在 normal/WinForms DialogPage
的消息循环中无法正常运行,但 UIElementDialogPage
可以。有许多 类 具有 UIElement*
或类似的前缀 - 它们有助于将 VS 的遗留代码从 Windows Forms 迁移到 WPF。
注意:我正在尝试解决鼠标问题,而不是键盘问题,键盘问题已经解决
所以我正在创建一个 Visual Studio 2015 扩展,在选项页面上工作。
我使用的是 WPF,所以我使用 ElementHost 来托管 UserControl。起初它没有接收到键盘事件,所以我在以下位置实施了解决方案:
WPF TextBox not accepting Input when in ElementHost in Window Forms
快速 运行 解决方案:
A) 在 UserControl 的 Loaded 事件上,我这样做:
var s = HwndSource.FromVisual(this) as HwndSource;
s?.AddHook(ChildHwndSourceHook);
B) 在 ChildHwndSourceHook() 中,我做了类似的事情:
static IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_GETDLGCODE)
{
handled = true;
return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTTAB);
}
return IntPtr.Zero;
}
但是,现在鼠标悬停在事件上似乎被忽略了,因为光标在文本框或网格分隔符上移动时不会改变,甚至在我创建的新 Windows 上也不会改变。 偶尔,不过,鼠标事件确实起作用,并且会继续起作用,直到我移动到另一个页面或关闭对话框。这是最奇怪的部分。
我已经尝试了所有方法并搜索了 Google 一整天,但我并没有进一步理解为什么点击可以正常工作,但鼠标悬停事件似乎没有被注册。
我确实尝试删除消息处理程序,然后打开一个 Window,但似乎一旦添加了处理程序,删除它就不会解决任何问题。
有谁知道如何让鼠标悬停在事件上以在我的控件上工作?非常感谢!
我使用创建者 Viasfora 使用的方法取得了成功。你可以在GitHub repo here上看到代码。特别是查看 TextObfuscationDialog 及其托管方式。我相信 VS 扩展文档可能有问题,因为我 运行 遇到了你遇到的同样问题。
编辑:
我已经创建了一个示例项目来展示此方法是否有效(我现在正在我自己的 2 个扩展中使用它)。希望这段工作代码可以让您更轻松地在自己的项目中实施它。
您可以从我的 OneDrive here 下载源代码。
UIElementDialogPage
on MSDN 说:
Provides seamless hosting of Windows Presentation Foundation (WPF) content inside a native dialog running an IsDialogMessage-style message loop. This class enables tabbing into and out of the WPF child window handle (HWND), and enables keyboard navigation within the WPF child HWND.
因此,虽然 ElementHost
在 normal/WinForms DialogPage
的消息循环中无法正常运行,但 UIElementDialogPage
可以。有许多 类 具有 UIElement*
或类似的前缀 - 它们有助于将 VS 的遗留代码从 Windows Forms 迁移到 WPF。