How to handle WndProc messages in WPF?

前端 未结 9 1004
不知归路
不知归路 2020-11-22 10:46

In Windows Forms, I\'d just override WndProc, and start handling messages as they came in.

Can someone show me an example of how to achieve the same thi

相关标签:
9条回答
  • 2020-11-22 10:55

    The short answer is you can't. WndProc works by passing messages to a HWND on a Win32 level. WPF windows have no HWND and hence can't participate in WndProc messages. The base WPF message loop does sit on top of WndProc but it abstracts them away from core WPF logic.

    You can use a HWndHost and get at a WndProc for it. However this is almost certainly not what you want to do. For the majority of purposes, WPF does not operate on HWND and WndProc. Your solution almost certainly relies on making a change in WPF not in WndProc.

    0 讨论(0)
  • 2020-11-22 10:57

    There are ways to handle messages with a WndProc in WPF (e.g. using a HwndSource, etc.), but generally those techniques are reserved for interop with messages that can't directly be handled through WPF. Most WPF controls aren't even windows in the Win32 (and by extension Windows.Forms) sense, so they won't have WndProcs.

    0 讨论(0)
  • 2020-11-22 11:00

    You can do this via the System.Windows.Interop namespace which contains a class named HwndSource.

    Example of using this

    using System;
    using System.Windows;
    using System.Windows.Interop;
    
    namespace WpfApplication1
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
            protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
                source.AddHook(WndProc);
            }
    
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                // Handle messages...
    
                return IntPtr.Zero;
            }
        }
    }
    

    Completely taken from the excellent blog post: Using a custom WndProc in WPF apps by Steve Rands

    0 讨论(0)
  • 2020-11-22 11:02

    Here is a link on overriding WindProc using Behaviors: http://10rem.net/blog/2010/01/09/a-wpf-behavior-for-window-resize-events-in-net-35

    [Edit: better late than never] Below is my implementation based on the above link. Although revisiting this I like the AddHook implementations better. I might switch to that.

    In my case I wanted to know when the window was being resized and a couple other things. This implementation hooks up to the Window xaml and sends events.

    using System;
    using System.Windows.Interactivity;
    using System.Windows; // For Window in behavior
    using System.Windows.Interop; // For Hwnd
    
    public class WindowResizeEvents : Behavior<Window>
        {
            public event EventHandler Resized;
            public event EventHandler Resizing;
            public event EventHandler Maximized;
            public event EventHandler Minimized;
            public event EventHandler Restored;
    
            public static DependencyProperty IsAppAskCloseProperty =  DependencyProperty.RegisterAttached("IsAppAskClose", typeof(bool), typeof(WindowResizeEvents));
            public Boolean IsAppAskClose
            {
                get { return (Boolean)this.GetValue(IsAppAskCloseProperty); }
                set { this.SetValue(IsAppAskCloseProperty, value); }
            }
    
            // called when the behavior is attached
            // hook the wndproc
            protected override void OnAttached()
            {
                base.OnAttached();
    
                AssociatedObject.Loaded += (s, e) =>
                {
                    WireUpWndProc();
                };
            }
    
            // call when the behavior is detached
            // clean up our winproc hook
            protected override void OnDetaching()
            {
                RemoveWndProc();
    
                base.OnDetaching();
            }
    
            private HwndSourceHook _hook;
    
            private void WireUpWndProc()
            {
                HwndSource source = HwndSource.FromVisual(AssociatedObject) as HwndSource;
    
                if (source != null)
                {
                    _hook = new HwndSourceHook(WndProc);
                    source.AddHook(_hook);
                }
            }
    
            private void RemoveWndProc()
            {
                HwndSource source = HwndSource.FromVisual(AssociatedObject) as HwndSource;
    
                if (source != null)
                {
                    source.RemoveHook(_hook);
                }
            }
    
            private const Int32 WM_EXITSIZEMOVE = 0x0232;
            private const Int32 WM_SIZING = 0x0214;
            private const Int32 WM_SIZE = 0x0005;
    
            private const Int32 SIZE_RESTORED = 0x0000;
            private const Int32 SIZE_MINIMIZED = 0x0001;
            private const Int32 SIZE_MAXIMIZED = 0x0002;
            private const Int32 SIZE_MAXSHOW = 0x0003;
            private const Int32 SIZE_MAXHIDE = 0x0004;
    
            private const Int32 WM_QUERYENDSESSION = 0x0011;
            private const Int32 ENDSESSION_CLOSEAPP = 0x1;
            private const Int32 WM_ENDSESSION = 0x0016;
    
            private IntPtr WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, ref Boolean handled)
            {
                IntPtr result = IntPtr.Zero;
    
                switch (msg)
                {
                    case WM_SIZING:             // sizing gets interactive resize
                        OnResizing();
                        break;
    
                    case WM_SIZE:               // size gets minimize/maximize as well as final size
                        {
                            int param = wParam.ToInt32();
    
                            switch (param)
                            {
                                case SIZE_RESTORED:
                                    OnRestored();
                                    break;
                                case SIZE_MINIMIZED:
                                    OnMinimized();
                                    break;
                                case SIZE_MAXIMIZED:
                                    OnMaximized();
                                    break;
                                case SIZE_MAXSHOW:
                                    break;
                                case SIZE_MAXHIDE:
                                    break;
                            }
                        }
                        break;
    
                    case WM_EXITSIZEMOVE:
                        OnResized();
                        break;
    
                    // Windows is requesting app to close.    
                    // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa376890%28v=vs.85%29.aspx.
                    // Use the default response (yes).
                    case WM_QUERYENDSESSION:
                        IsAppAskClose = true; 
                        break;
                }
    
                return result;
            }
    
            private void OnResizing()
            {
                if (Resizing != null)
                    Resizing(AssociatedObject, EventArgs.Empty);
            }
    
            private void OnResized()
            {
                if (Resized != null)
                    Resized(AssociatedObject, EventArgs.Empty);
            }
    
            private void OnRestored()
            {
                if (Restored != null)
                    Restored(AssociatedObject, EventArgs.Empty);
            }
    
            private void OnMinimized()
            {
                if (Minimized != null)
                    Minimized(AssociatedObject, EventArgs.Empty);
            }
    
            private void OnMaximized()
            {
                if (Maximized != null)
                    Maximized(AssociatedObject, EventArgs.Empty);
            }
        }
    
    <Window x:Class="MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            xmlns:behaviors="clr-namespace:RapidCoreConfigurator._Behaviors"
            Title="name" Height="500" Width="750" BorderBrush="Transparent">
    
        <i:Interaction.Behaviors>
            <behaviors:WindowResizeEvents IsAppAskClose="{Binding IsRequestClose, Mode=OneWayToSource}"
                                          Resized="Window_Resized"
                                          Resizing="Window_Resizing" />
        </i:Interaction.Behaviors>
    
        ... 
    
    </Window>
    
    0 讨论(0)
  • 2020-11-22 11:11

    WPF doesn't operate on WinForms type wndprocs

    You can host an HWndHost in an appropriate WPF element then override the Hwndhost's wndproc, but AFAIK that's as close as you're going to get.

    http://msdn.microsoft.com/en-us/library/ms742522.aspx

    http://blogs.msdn.com/nickkramer/archive/2006/03/18/554235.aspx

    0 讨论(0)
  • 2020-11-22 11:12
    HwndSource src = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
    src.AddHook(new HwndSourceHook(WndProc));
    
    
    .......
    
    
    public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
    
      if(msg == THEMESSAGEIMLOOKINGFOR)
        {
          //Do something here
        }
    
      return IntPtr.Zero;
    }
    
    0 讨论(0)
提交回复
热议问题