سؤال

العثور على WPF منحنى تعليمي حاد.

في نماذج Windows الجيدة، كنت سأتجاوز فقط WndProc, ، وابدأ في التعامل مع الرسائل فور ورودها.

هل يمكن لأحد أن يريني مثالاً لكيفية تحقيق نفس الشيء في WPF؟

هل كانت مفيدة؟

المحلول

في الواقع، بقدر ما أفهم، فإن مثل هذا الشيء ممكن بالفعل في استخدام 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;
}

الآن، لست متأكدًا تمامًا من سبب رغبتك في التعامل مع رسائل Windows Messaging في تطبيق WPF (ما لم يكن هذا هو الشكل الأكثر وضوحًا للتشغيل المتداخل للعمل مع تطبيق WinForms آخر).تختلف أيديولوجية التصميم وطبيعة واجهة برمجة التطبيقات (API) كثيرًا في WPF عن WinForms، لذا أقترح عليك أن تتعرف على WPF أكثر لترى بالضبط لماذا لا يوجد ما يعادل WndProc.

نصائح أخرى

ويمكنك القيام بذلك عن طريق مساحة 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;
        }
    }
}

واتخذت تماما من بلوق وظيفة ممتازة: <لأ href = "http://web.archive.org/web/20091019124817/http://www.steverands.com/2009/03/19/custom-wndproc- برنامج الأغذية العالمي-التطبيقات / "يختلط =" نوفولو noreferrer "> باستخدام WndProc مخصصة في تطبيقات WPF التي كتبها ستيف راند

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

إذا كنت لا تمانع الرجوع WinForms عناصر، يمكنك استخدام أكثر من حل الموجهة MVVM التي لا خدمة الزوجين مع وجهة النظر. تحتاج إلى إنشاء وتهيئة System.Windows.Forms.NativeWindow وهو نافذة خفيفة الوزن التي يمكن أن تلقي الرسائل.

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

استخدم SpongeHandle للتسجيل في رسائل كنت مهتما ثم تجاوز WndProc لمعالجتها:

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

والجانب السلبي الوحيد هو أن لديك لتشمل System.Windows.Forms المرجعية، ولكن على خلاف هذا هو الحل مغلفة للغاية.

وأكثر على هذا يمكن قراءة هنا

وهناك طرق للتعامل مع الرسائل مع WndProc في برنامج الأغذية العالمي (على سبيل المثال باستخدام HwndSource، وما إلى ذلك)، ولكن عموما تلك التقنيات محجوزة لإمكانية التشغيل المتداخل مع الرسائل التي لا يمكن التعامل معها مباشرة من خلال برنامج الأغذية العالمي. معظم الضوابط WPF ليست النوافذ حتى في Win32 و(وWindows.Forms التمديد) المعنى، بحيث لن يكون WndProcs.

ويمكنك إرفاق إلى فئة "SystemEvents" من المدمج في الصف Win32 و:

using Microsoft.Win32;

وفي فئة إطار برنامج الأغذية العالمي:

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 لا تعمل على نوع WinForms عناصر wndprocs

ويمكنك استضافة HWndHost في عنصر WPF المناسب ثم تجاوز wndproc وHwndhost، ولكن AFAIK هذا أقرب ما كنت ذاهب الى الحصول عليها.

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

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

والجواب القصير هو لا يمكنك. WndProc يعمل عن طريق تمرير الرسائل إلى HWND على مستوى Win32 و. نوافذ WPF ليس لها HWND، وبالتالي لا يمكن أن تشارك في رسائل WndProc. حلقة رسالة قاعدة WPF لا يجلس على رأس WndProc كنها خلاصات بها بعيدا عن منطق WPF الأساسية.

ويمكنك استخدام HWndHost والحصول على WndProc لذلك. ولكن هذا يكاد يكون من المؤكد ليس ما تريد القيام به. وبالنسبة لغالبية الأغراض، WPF لا تعمل على HWND وWndProc. الحل يعتمد بشكل شبه مؤكد على إجراء تغيير في برنامج الأغذية العالمي ليس في WndProc.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top