Frage

Finding WPF eine steile Lernkurve.

In guten alten Windows Forms, würde ich nur WndProc außer Kraft setzen, und starte Umgang mit Nachrichten, wie sie kamen.

Kann jemand zeigen Sie mir ein Beispiel, wie die gleiche Sache in WPF zu erreichen?

War es hilfreich?

Lösung

Eigentlich soweit ich verstehe so etwas ist in der Tat möglich, in WPF HwndSource und HwndSourceHook verwenden. Siehe diesen Thread auf MSDN als Beispiel. (Relevante Code enthalten unten)

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

Nun, ich bin mir nicht ganz sicher, warum Sie wollen würde Windows Messaging-Nachrichten in einer WPF-Anwendung behandeln (es sei denn, es die naheliegendste Form von Interop ist für mit einem anderen WinForms-Anwendung arbeiten). Die Design-Ideologie und die Art der API in WPF sehr verschieden von WinForms ist, so würde ich vorschlagen, Sie machen Sie sich nur mit WPF mehr genau zu sehen, Warum gibt es keine Entsprechung von WndProc.

Andere Tipps

Sie können über den System.Windows.Interop Namespace tun dies, die eine Klasse mit dem Namen HwndSource enthält.

Beispiel für die Verwendung dieses

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

Komplett von dem hervorragenden Blogeintrag wird: Verwenden einer benutzerdefinierten WndProc in WPF-Anwendungen von Steve Rand

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

Wenn Sie nichts dagegen nicht WinForms Referenzierung, können Sie eine MVVM orientierte Lösung verwenden, die mit dem Blick nicht Paar Dienst tut. Sie müssen erstellen und eine System.Windows.Forms.NativeWindow zu initialisieren, die ein leichtes Fenster ist, die Nachrichten empfangen kann.

public abstract class WinApiServiceBase : IDisposable
{
    /// <summary>
    /// Sponge window absorbs messages and lets other services use them
    /// </summary>
    private sealed class SpongeWindow : NativeWindow
    {
        public event EventHandler<Message> WndProced;

        public SpongeWindow()
        {
            CreateHandle(new CreateParams());
        }

        protected override void WndProc(ref Message m)
        {
            WndProced?.Invoke(this, m);
            base.WndProc(ref m);
        }
    }

    private static readonly SpongeWindow Sponge;
    protected static readonly IntPtr SpongeHandle;

    static WinApiServiceBase()
    {
        Sponge = new SpongeWindow();
        SpongeHandle = Sponge.Handle;
    }

    protected WinApiServiceBase()
    {
        Sponge.WndProced += LocalWndProced;
    }

    private void LocalWndProced(object sender, Message message)
    {
        WndProc(message);
    }

    /// <summary>
    /// Override to process windows messages
    /// </summary>
    protected virtual void WndProc(Message message)
    { }

    public virtual void Dispose()
    {
        Sponge.WndProced -= LocalWndProced;
    }
}

Verwenden SpongeHandle für Nachrichten registrieren Sie interessiert sind und dann außer Kraft setzen WndProc sie zu verarbeiten:

public class WindowsMessageListenerService : WinApiServiceBase
{
    protected override void WndProc(Message message)
    {
        Debug.WriteLine(message.msg);
    }
}

Der einzige Nachteil ist, dass Sie System.Windows.Forms Referenz enthalten müssen, aber ansonsten ist dies eine sehr verkapselte Lösung.

Mehr dazu lesen Sie hier gelesen werden

Es gibt Möglichkeiten, Nachrichten mit einer WndProc in WPF behandeln (zum Beispiel eines HwndSource Verwendung, etc.), aber im Allgemeinen sind diese Techniken reserviert für Interop mit Nachrichten, die nicht direkt über WPF behandelt werden können. Die meisten WPF-Steuerelemente sind nicht einmal Fenster in der Win32 (und durch Erweiterung Windows.Forms) Sinn, damit sie nicht WndProcs haben.

Sie können auf die 'SystemEvents' Klasse der integrierten in Win32-Klasse anhängen:

using Microsoft.Win32;

in einer WPF-Fenster-Klasse:

SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionEnded += SystemEvents_SessionEnded;

private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
    await vm.PowerModeChanged(e.Mode);
}

private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
    await vm.PowerModeChanged(e.Mode);
}

private async void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
    await vm.SessionSwitch(e.Reason);
}

private async void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
    if (e.Reason == SessionEndReasons.Logoff)
    {
        await vm.UserLogoff();
    }
}

private async void SystemEvents_SessionEnded(object sender, SessionEndedEventArgs e)
{
    if (e.Reason == SessionEndReasons.Logoff)
    {
        await vm.UserLogoff();
    }
}

WPF funktioniert nicht auf WinForms Typ wndprocs

Sie können eine HwndHost in einem geeigneten WPF-Elemente Host dann die Wndproc der HwndHost außer Kraft setzen, aber AFAIK, dass so nah ist wie du gehst zu erhalten.

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

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

Die kurze Antwort ist, dass Sie nicht. WndProc Werke von Meldungen an einen HWND auf einer Win32-Ebene übergeben. WPF Fenster haben keine HWND und daher nicht in WndProc Nachrichten teilnehmen können. Die Basis WPF Nachrichtenschleife nicht sitzt oben auf WndProc aber es abstrahiert sie weg von Kern WPF Logik.

Sie können eine HwndHost verwenden und bei einem WndProc dafür bekommen. Dies ist jedoch mit ziemlicher Sicherheit nicht das, was Sie tun mögen. Für die meisten Zwecke ist WPF arbeiten nicht auf HWND und WndProc. Ihre Lösung an Sicherheit grenzender Wahrscheinlichkeit verlässt sich auf Sie eine Änderung in WPF nicht in WndProc.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top