Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
wpf HwndHost MouseMove事件在前一个元素MouseLeave事件之前_Wpf_Mousemove_Mouseenter_Mouseleave_Hwndhost - Fatal编程技术网

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

wpf HwndHost MouseMove事件在前一个元素MouseLeave事件之前,wpf,mousemove,mouseenter,mouseleave,hwndhost,Wpf,Mousemove,Mouseenter,Mouseleave,Hwndhost,我们有一个Wpf应用程序,其中有一个Hwndhost元素,用于通过DirectX呈现3d内容。我们向客户端公开一个“Panel”接口,其中包含MouseEnter和MouseLeave事件。对于Hwndhost“面板”,由于win32没有WM_MouseEnter事件,因此当我们第一次向Hwndhost.WndProc接收WM_MOUSEMOVE事件时,我们模拟了一个MouseEnter事件。此外,对于HwndHost,我们通过TrackMouseEvent()请求WM_MOUSELEAVE事件

我们有一个Wpf应用程序,其中有一个Hwndhost元素,用于通过DirectX呈现3d内容。我们向客户端公开一个“Panel”接口,其中包含MouseEnter和MouseLeave事件。对于Hwndhost“面板”,由于win32没有WM_MouseEnter事件,因此当我们第一次向Hwndhost.WndProc接收WM_MOUSEMOVE事件时,我们模拟了一个MouseEnter事件。此外,对于HwndHost,我们通过TrackMouseEvent()请求WM_MOUSELEAVE事件,该事件模拟“panel”界面上的MOUSELEAVE事件

问题在于,当用户非常快速地将鼠标移动到HwndHost面板或从HwndHost面板移动鼠标时,我们会从鼠标移动到的面板接收enter事件,然后再接收鼠标移动到的面板的leave事件。如果源面板和目标面板都是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 void InitCommonControls();
        private void ApplicationStartup(object sender, StartupEventArgs args)
        {
            InitCommonControls();
            HostWindow host = new HostWindow();
            host.InitializeComponent();
        }
    }
}

// App.xaml
<Application x:Class="WpfHostingWin32Control.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="MainWindow.xaml"
    Startup="ApplicationStartup">
</Application>

// HostWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;  

namespace WpfHostingWin32Control
{
    public partial class HostWindow : Window
    {
        WpfHostingWin32Control.ControlHost ctrlHost;

        public HostWindow()
        {
            InitializeComponent();
            txtbox1.MouseEnter += MouseEnterHandler;
            txtbox1.MouseLeave += MouseLeaveHandler;
        }

        void MouseEnterHandler(object sender, MouseEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Wpf MouseEnter");
        }

        void MouseLeaveHandler(object sender, MouseEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Wpf MouseLeave");
        }

        private void On_UIReady(object sender, EventArgs e)
        {
            ctrlHost = new ControlHost(600, 600);
            ControlHostElement.Child = ctrlHost;
        }
    }
}

// HostWindow.xaml
<Window x:Class="WpfHostingWin32Control.HostWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Name="mainWindow"
    Width="1250"
    Height="700"
    Background="LightGreen" 
    Loaded="On_UIReady">
    <StackPanel Margin="20" Orientation="Horizontal">
        <Border Name="ControlHostElement" Width="600" Height="600"/>
        <TextBox Margin="5,0,0,0" x:Name="txtbox1" Width="600" Height="600"/>
    </StackPanel>
</Window>  

// ControlHost.cs
using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace WpfHostingWin32Control
{
    public class ControlHost : HwndHost
    {
        IntPtr hwndHost;
        int hostHeight, hostWidth;
        bool m_MouseHasEntered;

        public ControlHost(double height, double width)
        {
            hostHeight = (int)height;
            hostWidth = (int)width;
        }

        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            hwndHost = IntPtr.Zero;
            hwndHost = CreateWindowEx(0, "listbox", "",WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 
                hostWidth, hostHeight, hwndParent.Handle, IntPtr.Zero, IntPtr.Zero, 0);

            return new HandleRef(this, hwndHost);
        }

        protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                case WM_MOUSEMOVE:
                    {
                        if (m_MouseHasEntered == false)
                        {
                            RequestMouesLeaveNotification();
                            m_MouseHasEntered = true;
                            System.Diagnostics.Debug.WriteLine("WM_MOUSEMOVE/ENTER");
                        }
                    }
                    break;

                case WM_MOUSELEAVE:
                    {
                        m_MouseHasEntered = false;
                        System.Diagnostics.Debug.WriteLine("WM_MOUSELEAVE");
                    }
                    break;
            }

            handled = false;
            return IntPtr.Zero;
        }

        private void RequestMouesLeaveNotification()
        {
            var tme = new TRACKMOUSEEVENT()
            {
                cbSize = (uint)Marshal.SizeOf(typeof(TRACKMOUSEEVENT)),
                dwFlags = TME_LEAVE,
                hwndTrack = hwndHost,
                dwHoverTime = 0
            };

            if (!TrackMouseEvent(out tme))
                System.Diagnostics.Debug.WriteLine("TrackMouseEvent failed!");
        }

        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            DestroyWindow(hwnd.Handle);
        }

        //PInvoke declarations
        [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
        internal static extern IntPtr CreateWindowEx(int dwExStyle,
                                                      string lpszClassName,
                                                      string lpszWindowName,
                                                      int style,
                                                      int x, int y,
                                                      int width, int height,
                                                      IntPtr hwndParent,
                                                      IntPtr hMenu,
                                                      IntPtr hInst,
                                                      [MarshalAs(UnmanagedType.AsAny)] object pvParam);

        [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);

        private const int WM_MOUSEMOVE = 0x0200;
        private const int WM_MOUSELEAVE = 0x02A3;
        private const int TME_LEAVE = 0x00000002;
        private const int WS_CHILD = 0x40000000;
        private const int WS_VISIBLE = 0x10000000;
        private const int WS_BORDER = 0x00800000;

        [StructLayout(LayoutKind.Sequential)]
        private struct TRACKMOUSEEVENT
        {
            public uint cbSize;
            public uint dwFlags;
            public IntPtr hwndTrack;
            public uint dwHoverTime;
        }

        [DllImport("user32.dll")]
        private static extern bool TrackMouseEvent(out TRACKMOUSEEVENT tme);
    }
}
//App.xaml.cs
使用制度;
使用System.Windows;
使用System.Runtime.InteropServices;
命名空间WpfHostingWin32Control
{
公共部分类应用程序:应用程序
{
[DllImport(“comctl32.dll”,EntryPoint=“InitCommonControls”,CharSet=CharSet.Auto)]
public static extern void InitCommonControls();
私有void应用程序启动(对象发送方、StartupEventArgs args args)
{
InitCommonControls();
HostWindow主机=新的HostWindow();
host.InitializeComponent();
}
}
}
//App.xaml
//HostWindow.xaml.cs
使用制度;
使用System.Windows;
使用System.Windows.Input;
命名空间WpfHostingWin32Control
{
公共部分类主机窗口:窗口
{
WpfHostingWin32Control.ControlHost ctrlHost;
公共主机窗口()
{
初始化组件();
txtbox1.MouseEnter+=MouseEnterHandler;
txtbox1.MouseLeave+=MouseLeaveHandler;
}
void MouseEnterHandler(对象发送器,MouseEventArgs e)
{
系统、诊断、调试、写入线(“Wpf鼠标器”);
}
void MouseLeaveHandler(对象发送器,MouseEventArgs e)
{
系统。诊断。调试。写线(“Wpf MouseLeave”);
}
_UIReady上的私有无效(对象发送方,事件参数e)
{
ctrlHost=新的控制主机(600600);
ControlHostElement.Child=ctrlHost;
}
}
}
//HostWindow.xaml
//ControlHost.cs
使用制度;
使用System.Windows;
使用System.Windows.Interop;
使用System.Runtime.InteropServices;
命名空间WpfHostingWin32Control
{
公共类控制主机:HwndHost
{
IntPtr-hwndHost;
int主机高度,主机宽度;
布尔m_鼠心;
公共控制主机(双高、双宽)
{
主机高度=(int)高度;
主机宽度=(int)宽度;
}
受保护的覆盖HandleRef BuildWindowCore(HandleRef hwndParent)
{
hwndHost=IntPtr.Zero;
hwndHost=CreateWindowEx(0,“listbox”,“”,WS|u子项| WS|u可见| WS|u边框,0,0,
hostWidth、hostHeight、hwndpresent.Handle、IntPtr.Zero、IntPtr.Zero、0);
返回新的HandleRef(此,hwndHost);
}
受保护的覆盖IntPtr WndProc(IntPtr hwnd、int msg、IntPtr wParam、IntPtr lParam、ref bool HANDED)
{
开关(msg)
{
案例WM_MOUSEMOVE:
{
if(m_MouseHasEntered==false)
{
RequestMouesLeaveNotification();
m_MouseHasEntered=真;
System.Diagnostics.Debug.WriteLine(“WM_MOUSEMOVE/ENTER”);
}
}
打破
案例WM_MOUSELEAVE:
{
m_MouseHasEntered=假;
系统、诊断、调试、写线(“WM_MOUSELEAVE”);
}
打破
}
已处理=错误;
返回IntPtr.Zero;
}
私有void RequestMouesLeaveNotification()
{
var tme=new TRACKMOUSEEVENT()
{
cbSize=(uint)Marshal.SizeOf(typeof(TRACKMOUSEEVENT)),
dwFlags=TME_离开,
HwnTrack=hwndHost,
dwHoverTime=0
};
如果(!TrackMouseeEvent(输出tme))
System.Diagnostics.Debug.WriteLine(“TrackMouseeEvent失败!”);
}
WindowCore的受保护覆盖(HandleRef hwnd)
{
车窗(带把手);
}
//平沃克宣言
[DllImport(“user32.dll”,EntryPoint=“CreateWindowEx”,CharSet=CharSet.Unicode)]
内部静态外部IntPtr CreateWindowEx(int dwExStyle,
字符串lpszClassName,
字符串lpszWindowName,
int风格,
int x,int y,
整数宽度,整数高度,
IntPtr hwndParent,
国际华努,
IntPtr hInst,