简体   繁体   English

IMessageFilter.PreFilterMessage 从未在 Application.AddMessageFilter 之后调用

[英]IMessageFilter.PreFilterMessage never called after Application.AddMessageFilter

After calling Application.AddMessageFilter, the PreFilterMessage method is never called.调用 Application.AddMessageFilter 后,永远不会调用 PreFilterMessage 方法。 It's just in a simple WPF application (below).它只是在一个简单的 WPF 应用程序中(如下)。 Is there something I've missed here?我在这里错过了什么吗?

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var _filter = new PreMessageFilter();
        Application.AddMessageFilter(_filter);
    }
}

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public class PreMessageFilter : IMessageFilter
{
    public bool PreFilterMessage(ref Message m)
    {
        Console.WriteLine(m.ToString());
        return true;
    }
}

I successfully used IMessageFilter under WinForms but I'm not sure if it can work properly under WPF.我在WinForms下成功使用了IMessageFilter ,但我不确定它在WPF下是否可以正常工作。

If you need some messages to be intercepted in WPF, there's the other way of doing it.如果您需要在 WPF 中截获一些消息,还有另一种方法。

This way is different from MessageFilter because it can't filter the messages but just listening for Message Loop.这种方式与MessageFilter不同,因为它不能过滤消息,而只是监听 Message Loop。

Let's listen WM_KEYDOWN message.让我们听听WM_KEYDOWN消息。

Showing the full App code to make it easy to reproduce显示完整的 App 代码,以便于重现

MyMessageHook.cs MyMessageHook.cs

using System;
using System.Windows.Input;
using System.Windows.Interop;

namespace WPFMessageHookExample
{
    public class MyKeyEventArgs : EventArgs
    {
        public Key Key { get; private set; }
        public MyKeyEventArgs(Key key) { Key = key; }
    }

    public class MyMessageHook : IDisposable
    {
        private const int WM_KEYDOWN = 0x0100;

        private readonly HwndSourceHook _hook;
        private static HwndSource _hwndSource;

        public event EventHandler<MyKeyEventArgs> KeyDown;
        public MyMessageHook(HwndSource hwndSource)
        {
            _hook = new HwndSourceHook(WndProc);
            _hwndSource = hwndSource ?? throw new ArgumentNullException(nameof(hwndSource));
            _hwndSource.AddHook(_hook);
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                case WM_KEYDOWN:
                    KeyDown?.Invoke(this, new MyKeyEventArgs(KeyInterop.KeyFromVirtualKey((int)wParam)));
                    break;
            }
            return IntPtr.Zero;
        }

        #region IDisposable
        private bool disposed;
        protected virtual void Dispose(bool disposing)
        {
            if (disposed) return;
            if (disposing)
            {
                _hwndSource.RemoveHook(_hook);
            }
            disposed = true;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        ~MyMessageHook()
        {
            Dispose(false);
        }
        #endregion
    }
}

MainWindow.xaml.cs主窗口.xaml.cs

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Interop;

namespace WPFMessageHookExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private MyMessageHook messageHook;
        private string _myText;

        public string MyText
        {
            get => _myText;
            set
            {
                _myText = value;
                OnPropertyChanged();
            }
        }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private void Window_SourceInitialized(object sender, EventArgs e)
        {
            HwndSource hwnd = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            messageHook = new MyMessageHook(hwnd);
            messageHook.KeyDown += MessageHook_KeyDown;
        }

        private void MessageHook_KeyDown(object sender, MyKeyEventArgs e)
        {
            MyText += e.Key + ", ";
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            messageHook.Dispose();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

MainWindow.xaml主窗口.xaml

<Window x:Class="WPFMessageHookExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFMessageHookExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" SourceInitialized="Window_SourceInitialized" Closing="Window_Closing">
    <Grid>
        <TextBox Margin="5" VerticalScrollBarVisibility="Auto" Text="{Binding MyText}" IsReadOnly="True" TextWrapping="Wrap"/>
    </Grid>
</Window>

Note that TextBox is Read-Only.请注意, TextBox是只读的。

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM