116

Windowsフォームでは、をオーバーライドWndProcして、メッセージが届いたときに処理を開始します。

誰かがWPFで同じことを達成する方法の例を教えてもらえますか?

4

9 に答える 9

143

System.Windows.Interopという名前のクラスを含む名前空間を介してこれを行うことができますHwndSource

使用例

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;
        }
    }
}

優れたブログ投稿から完全に抜粋: Steve Rands による WPF アプリでのカスタム WndProc の使用

于 2009-12-18T07:12:42.617 に答える
64

実際、私が理解している限り、このようなことはWPFでとを使用して実際に可能HwndSourceですHwndSourceHook。例として、MSDNのこのスレッドを参照してください。(以下に含まれる関連コード)

// 'this' is a Window
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    //  do stuff

    return IntPtr.Zero;
}

さて、WPFアプリケーションでWindowsメッセージングメッセージを処理する理由がよくわかりません(別のWinFormsアプリを操作するための相互運用の最も明白な形式でない限り)。WPFとWinFormsでは、設計のイデオロギーとAPIの性質が大きく異なるため、WndProcに相当するものがない理由を正確に理解するために、WPFに精通することをお勧めします。

于 2009-03-08T22:18:57.910 に答える
17
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;
}
于 2009-07-14T16:58:59.010 に答える
2

Behaviors を使用したWindProcのオーバーライドに関するリンクは次のとおりです。

[編集: 遅刻するよりはまし] 以下は、上記のリンクに基づく私の実装です。これを再訪しましたが、私は AddHook の実装の方が気に入っています。それに乗り換えるかも。

私の場合、ウィンドウのサイズが変更された時期と、その他のいくつかのことを知りたかったのです。この実装は Window xaml に接続し、イベントを送信します。

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>
于 2011-04-08T17:26:36.380 に答える
-1

WPFでWndProcを使用してメッセージを処理する方法はいくつかありますが(たとえば、HwndSourceを使用するなど)、通常、これらの手法は、WPFを介して直接処理できないメッセージとの相互運用のために予約されています。ほとんどのWPFコントロールは、Win32(および拡張機能としてWindows.Forms)の意味でのウィンドウではないため、WndProcsはありません。

于 2009-03-08T21:58:22.953 に答える
-7

WPFはWinFormsタイプのwndprocsでは動作しません

適切なWPF要素でHWndHostをホストしてから、Hwndhostのwndprocをオーバーライドできますが、これは、取得するのと同じくらい近いAFAIKです。

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

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

于 2009-03-08T21:56:42.147 に答える
-15

簡単な答えはあなたができないということです。WndProcは、Win32レベルのHWNDにメッセージを渡すことによって機能します。WPFウィンドウにはHWNDがないため、WndProcメッセージに参加できません。基本のWPFメッセージループはWndProcの上にありますが、コアWPFロジックからそれらを抽象化します。

HWndHostを使用して、WndProcで入手できます。しかし、これはほぼ間違いなくあなたがやりたいことではありません。ほとんどの場合、WPFはHWNDおよびWndProcでは動作しません。あなたのソリューションは、ほぼ確実に、WndProcではなくWPFに変更を加えることに依存しています。

于 2009-03-08T21:57:37.400 に答える