标签: hwndhost

在WPF窗口中托管外部应用程序

我们正在开发WPF中的布局管理器,其具有可由用户移动/调整大小/等的视口.视口通常通过布局管理器中我们控制的提供程序填充数据(图片/电影/等).我的工作是检查它是否也可以在视口中托管任何外部Windows应用程序(即记事本,计算,土坯阅读器等).我遇到了一些问题.

大多数资源都指向使用HwndHost类.我正在试验微软本身的演练:http://msdn.microsoft.com/en-us/library/ms752055.aspx

我已经对此进行了调整,因此列表框将替换为外部应用程序的Windows句柄.任何人都可以帮我解决这些问题:

  1. 演练添加了一个额外的静态子窗口,其中ListBox放置了该子窗口.我不认为我需要外部应用程序.如果我省略它,我必须使外部应用程序成为子窗口(使用来自user32.dll的Get/SetWindowLong设置GWL_STYLEWS_CHILD).但是,如果我这样做,应用程序的菜单栏消失(因为WS_CHILD样式),它不再接收输入.
  2. 如果我确实使用子窗口,并使外部应用程序成为合理的工作的孩子,但有时外部应用程序不能正常工作.
  3. 此外,我需要子窗口调整大小到视口.这可能吗?
  4. 当exernal应用程序生成子窗口(即记事本 - >帮助 - >关于)时,此窗口不由托管HwndHost(因此可以移动到视口外).有什么办法可以阻止吗?
  5. 由于我不需要外部应用程序和布局管理器之间的进一步交互,我是否正确地假设我不需要捕获和转发消息?(演练将HwndSourceHook添加到子窗口以捕获列表框中的选择更改).
  6. 当您运行(未修改的)示例VS2010并关闭窗口时,VS2010看不到程序已结束.如果你打破所有,你最终会在没有来源的情况下进行组装.有点臭,但我找不到.
  7. 演练本身似乎非常草率编码,但我没有找到关于这个主题的更好的文档.还有其他例子吗?
  8. 另一种方法是不使用HwndHost,但WindowsFormHost作为讨论在这里.它工作(并且更简单!)但我无法控制应用程序的大小?另外,WinFormHost真的不是这个意思吗?

感谢您指出正确的方向.

c# wpf winapi hwndhost

38
推荐指数
3
解决办法
4万
查看次数

如何将Win32鼠标消息转换为WPF鼠标事件?

我有一个Win32(OpenGL)控件,我需要嵌入我们的WPF应用程序.它必须响应并传播鼠标和键盘事件.

我已经创建了一个HwndHost派生实例来托管本机窗口并覆盖了这个类中的WndProc函数.要将win32消息传播到WPF,我处理特定的鼠标消息并将它们映射到WPF事件,然后使用静态InputManager类来引发它们.

问题是,当我去处理它们时,鼠标坐标会混乱.

下面是我用来引发事件的代码示例:

IntPtr MyHwndHost::WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% handled)
{
  switch (msg)
  {
    case WM_LBUTTONDOWN:
    {
        MouseButtonEventArgs^ eventArgs = gcnew MouseButtonEventArgs(
          Mouse::PrimaryDevice,
          Environment::TickCount,
          MouseButton::Left);

        eventArgs->RoutedEvent = UIElement::PreviewMouseDownEvent;
        eventArgs->Source = this;

        // Raise the WPF event from the specified WPF event source.
        InputManager::Current->ProcessInput(eventArgs);

        eventArgs->RoutedEvent = UIElement::MouseDownEvent;
        InputManager::Current->ProcessInput(eventArgs);

        CommandManager::InvalidateRequerySuggested();

        handled = true;
        return IntPtr::Zero;
    }
    break;
  }

  return HwndHost::WndProc(hwnd, msg, wParam, lParam, handled);
}
Run Code Online (Sandbox Code Playgroud)

当我的WPF事件处理程序被触发并且我尝试检索鼠标坐标(例如e.GetPosition((IInputElement) sender))时,我收到错误的值(并且无论我的控件中原始事件发生在何处,它们总是相同的值).

我得到的值似乎与托管应用程序的WPF窗口的屏幕位置有关,因为它们在窗口位置发生变化时会发生变化,但它们也不对应于应用程序窗口的实际位置.

我认为这可能与WPF InputManager的内部状态有关,而且私有字段MouseDevice._inputSourcenull …

.net wpf winapi hwndhost

11
推荐指数
1
解决办法
1619
查看次数

'{DependencyProperty.UnsetValue}'不是属性'FocusVisualStyle'的有效值

我有一个奇怪的错误,我试图调试没有运气.

我有子类hwndhost显示一些内容,我在该类中有以下功能设置为全屏:

    private void SetFullScreen(bool enable)
    {
        if (enable)
        {
            fs = new Window();
            fs.ResizeMode = ResizeMode.NoResize;
            fs.WindowState = System.Windows.WindowState.Maximized;
            fs.WindowStyle = System.Windows.WindowStyle.None;
            fs.Topmost = true;
            fs.PreviewKeyDown += delegate(object sender, KeyEventArgs e) { 
                if (e.Key==Key.Escape)
                    FullScreen = false;
            };
            fs.Show();
        }
        else
        {
            fs.Close();
            fs = null;
        }
    }
Run Code Online (Sandbox Code Playgroud)

这在我的原型WPF应用程序中运行良好但是当我在我的主应用程序中使用此代码时,在关闭窗口(转义键)和fs.close()通话时出现此错误:

'{DependencyProperty.UnsetValue}' is not a valid value for property 'FocusVisualStyle'.

奇怪的是它在窗户关闭后大约1500ms发生.我已经尝试将FocusVisualStyle设置fs为null,但它看起来像是其他东西.直觉是它试图将另一个元素集中在我没有这个属性的app中,但我真的不知道!

谢谢!

编辑.问题是我的全屏按钮上的自定义设置FocusVisualStyle.我设置为{x:Null},问题就消失了.

wpf dependency-properties hwndhost

9
推荐指数
3
解决办法
1万
查看次数

将输入事件从HwndHost传递到基础WPF控件?

有没有办法将HwndHost上发生的输入事件(主要是鼠标,但最终也是键盘输入)传递回基础WPF控件(例如面板)?我可以在HwndHost中连接到WndProc并重新发送Windows消息.我可以手动创建一个用于鼠标单击的routedevent并将其发送给父级以使其冒泡吗?和想法将不胜感激.谢谢jkersch

wpf hwnd routedevent hwndhost

7
推荐指数
1
解决办法
2159
查看次数

如果窗口包含HwndHost元素,则自定义dwm绘制的窗口框架会在调整大小时闪烁

我一直在考虑这个问题,但我认为我对Windows和wpf如何在内部工作以解决这个问题缺乏一些基本的了解.

问题是这样的:

我创建了一个窗口,可以让我在空中标题栏(如办公室)上绘制wpf控件.只要我不向窗口添加Hwndhost元素,这种方法就可以正常工作,在这种情况下,每当我调整框架大小并且HwndHost开始闪烁时(其他元素似乎正确渲染).我也尝试使用WPF Shell Integration库中的自定义框架窗口实现,结果是一样的,所以我认为这不完全是我的错.

以下代码是一个简单的可编译程序,可以重现该问题.样本在c#中,但答案不一定是.

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;

namespace DwmTest {
    class Program {
        [STAThread]
        static void Main( ) {
            var w = new CustomFrameWindow{ Content =  new WindowHost() };
            w.Show( );
            ((Border)VisualTreeHelper.GetChild( w, 0 )).Margin = new Thickness( 11, 33, 11, 11 );
            Dispatcher.Run( );
        }
    }

    public class CustomFrameWindow : Window {

        const int resizeFrameWidth = 11;
        const int captionHeight = 33;

        public enum …
Run Code Online (Sandbox Code Playgroud)

wpf dwm hwndhost aero-glass

6
推荐指数
1
解决办法
3636
查看次数

使用 HwndHost 在 WPF 中托管外部窗口的正确方法

我想在我的 WPF 应用程序中托管一个外部进程的窗口。我是这样推导的HwndHost

    class HwndHostEx : HwndHost
    {
        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        private IntPtr ChildHandle = IntPtr.Zero;

        public HwndHostEx(IntPtr handle)
        {
            this.ChildHandle = handle;
        }

        protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
        {
            HandleRef href = new HandleRef();

            if (ChildHandle != IntPtr.Zero)
            {
                SetParent(this.ChildHandle, hwndParent.Handle);
                href = new HandleRef(this, this.ChildHandle);
            }

            return href;
        }

        protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
        {

        }
    }
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

 HwndHostEx host = new HwndHostEx(handle);
 this.PART_Host.Child = host;
Run Code Online (Sandbox Code Playgroud)

handle我想托管的外部窗口的句柄在哪里,是PART_Host我的 WPF …

c# wpf hwndhost

6
推荐指数
1
解决办法
4774
查看次数

强制初始化HwndHost

在我的WPF应用程序中,我使用HwndHost托管Win32内容.但是,创建HwndHost不会创建本机窗口.相反,这是在重写的BuildWindowCore()方法中完成的,该方法稍后由WPF调用.

我的托管内容需要本机窗口的窗口句柄以进行自己的初始化.不幸的是,我无法强制创建窗口(即让WPF调用BuildWindowCore),所以我有第二个线程轮询HwndHost,直到它被初始化.

在.NET 4.0/WPF 4.0中,WindowInteropHelper.EnsureHandle()添加了一种新方法.我希望这可以解决这种情况,但它只适用于Window,而不适用于HwndHost(它不是从Window派生的).你有建议我可以做什么吗?

编辑:

我忘了为可能的解决方案添加更多约束:

  1. HwndHost放置在一个控件中,根据用户设置,该控件可以是应用程序主窗口的子窗口,也可以放在新窗口中(通过第三方停靠管理器).这意味着在创建窗口期间,我不确定父窗口(以及它的hWnd)将是什么.
  2. 虽然本机代码在初始化期间需要hWnd,但窗口仅在用户请求显示时显示(即,它首先是不可见的).如果可能的话,应该避免显示窗口,只是立即再次隐藏它.

.net wpf hwndhost wpf-4.0

5
推荐指数
1
解决办法
2132
查看次数

wpf HwndHost MouseMove 事件在前一个元素之前 MouseLeave 事件

我们有一个带有 Hwndhost 元素的 Wpf 应用程序,用于通过 DirectX 渲染 3D 内容。我们向客户端公开一个“Panel”接口,其中包含 MouseEnter 和 MouseLeave 事件。对于 Hwndhost“面板”,当我们第一次收到 HwndHost.WndProc 的 WM_MOUSEMOVE 事件时,我们模拟 MouseEnter 事件,因为 win32 没有 WM_MOUSEENTER 事件。另外,对于 HwndHost,我们通过 TrackMouseEvent() 请求 WM_MOUSELEAVE 事件,该事件在我们的“面板”界面上模拟 MouseLeave 事件。

问题是,当用户非常快速地将鼠标移动到 HwndHost 面板或从 HwndHost 面板移出时,我们会先收到鼠标移动到的面板的 Enter 事件,然后再收到鼠标移动的面板的离开事件。 当源面板和目标面板都是 wpf 元素时,不会发生这种情况,仅当涉及 hwndhost 元素时。另外,如果有两个 HwndHost 元素彼此相邻,则会发生相同的行为,因此看起来 win32 没有按照消息发生的顺序发送消息。

有谁知道解决这个问题的方法吗? 如果有一种方法可以让 Win32 按照事件发生的顺序发送事件,那就太好了。

下面是一个示例应用程序,它演示了向调试器输出窗口打印消息的问题:

// App.xaml.cs
using System;
using System.Windows;
using System.Runtime.InteropServices;

namespace WpfHostingWin32Control
{
    public partial class App : Application
    {
        [DllImport("comctl32.dll", EntryPoint = "InitCommonControls", CharSet =         CharSet.Auto)]
        public static extern …
Run Code Online (Sandbox Code Playgroud)

wpf mouseenter mouseleave mousemove hwndhost

5
推荐指数
0
解决办法
791
查看次数