ডাব্লুপিএফ-এ কীভাবে ডাব্লুড্রপোক বার্তা হ্যান্ডেল করবেন?


112

উইন্ডোজ ফর্মগুলিতে আমি কেবল ওভাররাইড করব WndProc এবং বার্তাগুলি আসার সাথে সাথে তাদের পরিচালনা করা শুরু করব।

ডাব্লুপিএফ-তে একই জিনিস কীভাবে অর্জন করা যায় তার উদাহরণ কেউ আমাকে দিতে পারে?

উত্তর:


62

প্রকৃতপক্ষে, আমি যতদূর বুঝতে পেরেছি ডাব্লুপিএফ ব্যবহার করে HwndSourceএবং এর পক্ষে সত্যই সম্ভব HwndSourceHook। উদাহরণ হিসাবে এমএসডিএন-এ এই থ্রেডটি দেখুন । (নীচে প্রাসঙ্গিক কোড অন্তর্ভুক্ত)

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

এখন, আমি কেন নিশ্চিত নই যে আপনি কেন ডাব্লুপিএফ অ্যাপ্লিকেশনটিতে উইন্ডোজ মেসেজিং বার্তাগুলি পরিচালনা করতে চান (যদি না এটি অন্য উইনফোর্স অ্যাপ্লিকেশনটির সাথে কাজ করার জন্য ইন্টারপের সবচেয়ে সুস্পষ্ট রূপ)। উইনফরমগুলি থেকে ডাব্লুপিএফ-এ ডিজাইনের মতাদর্শ এবং এপিআইয়ের প্রকৃতি খুব আলাদা, তাই ডাব্লুড্রপকের সমতুল্য কেন নেই তা দেখার জন্য আমি আপনাকে নিজেকে আরও ডাব্লুপিএফের সাথে পরিচিত করার পরামর্শ দিচ্ছি ।


48
ঠিক আছে, ইউএসবি ডিভাইস (ডিস) সংযুক্ত ইভেন্টগুলি এই বার্তাটির
লুপটির মধ্যে

7
@ নলডোরিন: আপনি কি দয়া করে এমন রেফারেন্স (নিবন্ধ / বই) সরবরাহ করতে পারেন যা "উইনফোর্ডস থেকে ডাব্লুপিএফ এর নকশার মতাদর্শ এবং এপিআইয়ের প্রকৃতি খুব আলাদা, ... কেন WndProc এর সমতুল্য নেই"?
আতিয়ার

2
WM_MOUSEWHEELউদাহরণস্বরূপ, এই বার্তাগুলি নির্ভরযোগ্যভাবে ফাঁদে ফেলার একমাত্র উপায় ছিল WndProcডাব্লুপিএফ উইন্ডোতে যুক্ত করে। এটি আমার পক্ষে কাজ করেছে, যেখানে কর্মকর্তা MouseWheelEventHandlerকেবল প্রত্যাশার মতো কাজ করেননি। আমি সঠিক ডাব্লুপিএফ টাচিয়ন্সকে নির্ভরযোগ্য আচরণের জন্য সঠিকভাবে সারিবদ্ধভাবে পেতে অক্ষম হয়েছি MouseWheelEventHandler, সুতরাং এর সরাসরি অ্যাক্সেসের প্রয়োজন WndProc
ক্রিস ও

4
সত্যটি হ'ল, অনেকগুলি (সর্বাধিক?) ডাব্লুপিএফ অ্যাপ্লিকেশনগুলি স্ট্যান্ডার্ড ডেস্কটপ উইন্ডোতে চালিত হয়। ডাব্লুপিএফ আর্কিটেকচার উইন 32 এর সমস্ত অন্তর্নিহিত ক্ষমতা প্রকাশ করার জন্য নয় যেটি মাইক্রোসফ্টের পক্ষ থেকে ইচ্ছাকৃত, তবে তা মোকাবেলা করার জন্য এখনও বিরক্তিকর। আমি একটি ডাব্লুপিএফ অ্যাপ্লিকেশন তৈরি করছি যা কেবলমাত্র ডেস্কটপ উইন্ডোজকে টার্গেট করে তবে ইউএসবি ডিভাইসগুলির সাথে সংযুক্ত করে যেমন @flq উল্লিখিত এবং ডিভাইস বিজ্ঞপ্তিগুলি প্রাপ্ত করার একমাত্র উপায় বার্তা লুপটি অ্যাক্সেস করা। কখনও কখনও বিমূর্ততা বিরতি অনিবার্য।
নাথানএলডেনএসআর

1
ক্লিপবোর্ড পর্যবেক্ষণ করা আমাদের ডাব্লুড্রপ্রোকের প্রয়োজনের একটি কারণ। অন্যটি হ'ল বার্তা প্রক্রিয়াকরণের মাধ্যমে অ্যাপ্লিকেশনটি নিষ্ক্রিয় নয় তা সনাক্ত করা।
ব্যবহারকারী 34660

135

আপনি 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;
        }
    }
}

সম্পূর্ণরূপে দুর্দান্ত ব্লগ পোস্ট থেকে নেওয়া: স্টিভ র্যান্ডস দ্বারা ডাব্লুপিএফ অ্যাপ্লিকেশনগুলিতে একটি কাস্টম ডাব্ল্যান্ডপ্রোক ব্যবহার করা


1
লিঙ্কটি নষ্ট হয়ে গেছে। আপনি এটি ঠিক করতে পারেন?
মার্টিন হেনিংস

1
@ মার্টিন, এটি কারণ স্টিভ র্যান্ডের ওয়েবসাইট আর নেই। আমি এটির অপসারণের জন্য কেবলমাত্র ঠিক করতে পারি। আমি মনে করি ভবিষ্যতে যদি সাইটটি ফিরে আসে তবে এটি এখনও মূল্যবোধ যুক্ত করে তাই আমি এটিকে সরিয়ে দিচ্ছি না - তবে আপনি যদি দ্বিমত পোষণ করেন তবে সম্পাদনা করতে দ্বিধা বোধ করবেন না।
রবার্ট ম্যাকলিন

উইন্ডো ছাড়াই কি ডাব্লুড্রপোক বার্তা পাওয়া সম্ভব?
Mo0gles

8
@ মো0gles - আপনি যা জিজ্ঞাসা করেছেন সে সম্পর্কে সাবধানে চিন্তা করুন এবং আপনার উত্তর পাবেন।
ইয়ান কেম্প

1
@ মো0gles পর্দায় আঁকা একটি উইন্ডো ছাড়া এবং ব্যবহারকারীর জন্য দৃশ্যমান? হ্যাঁ. এ কারণেই কিছু প্রোগ্রামের অদ্ভুত খালি উইন্ডোজ রয়েছে যা প্রোগ্রামের রাজ্যটি দূষিত হয়ে গেলে মাঝে মাঝে দৃশ্যমান হয়।
পিটার

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

3

আপনি যদি উইনফর্মগুলি উল্লেখ করতে কিছু মনে করেন না, আপনি এমন আরও একটি এমভিভিএম-ভিত্তিক সমাধান ব্যবহার করতে পারেন যা দর্শনটির সাথে কোনও দম্পতি পরিষেবা দেয় না। আপনাকে একটি সিস্টেম তৈরি করতে হবে এবং প্রারম্ভিক করা দরকার W উইন্ডোজ For ফর্মস ative নেটিভ উইন্ডো যা হালকা ওজনের উইন্ডো যা বার্তা পেতে পারে।

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

আপনার আগ্রহী বার্তাগুলির জন্য নিবন্ধভুক্ত করতে স্পঞ্জহ্যান্ডল ব্যবহার করুন এবং তারপরে প্রক্রিয়া করার জন্য ডাব্ল্যান্ডড্রোককে ওভাররাইড করুন:

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

একমাত্র নেতিবাচকতা হ'ল আপনাকে System.Windows. forms রেফারেন্স অন্তর্ভুক্ত করতে হবে তবে অন্যথায় এটি একটি খুব এনক্যাপসুলেটেড সমাধান।

এ সম্পর্কে আরও এখানে পড়তে পারেন


1

এখানে আচরণে আবরণে ব্যবহার WindProc অগ্রাহ্য একটি লিঙ্ক হল: http://10rem.net/blog/2010/01/09/a-wpf-behavior-for-window-resize-events-in-net-35

[সম্পাদনা করুন: আগের তুলনায় আরও দেরী] উপরের লিঙ্কটির উপর ভিত্তি করে নীচে আমার বাস্তবায়নটি দেওয়া হল। যদিও এটি পুনর্বিবেচনা আমি অ্যাডহুক বাস্তবায়ন আরও ভাল পছন্দ করি। আমি এটি যেতে পারে।

আমার ক্ষেত্রে আমি জানতে চাইছিলাম কখন উইন্ডোটি পুনরায় আকার দেওয়া হচ্ছে এবং আরও কয়েকটি জিনিস। এই বাস্তবায়ন উইন্ডো এক্সএএমএল পর্যন্ত দেখায় এবং ইভেন্টগুলি প্রেরণ করে।

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>

যদিও এই লিঙ্কটি প্রশ্নের উত্তর দিতে পারে, উত্তরের প্রয়োজনীয় অংশগুলি এখানে অন্তর্ভুক্ত করা এবং রেফারেন্সের জন্য লিঙ্কটি সরবরাহ করা ভাল। লিঙ্কযুক্ত পৃষ্ঠাগুলি পরিবর্তিত হলে লিঙ্ক-শুধুমাত্র উত্তরগুলি অবৈধ হতে পারে।
সর্বোচ্চ

@ ম্যাক্স> এটির জন্য এখন সম্ভবত কিছুটা দেরি।
রক

1
@ রুক আমার মনে হয় স্ট্যাকওভারফ্লো পর্যালোচনা পরিষেবাটি অদ্ভুত আচরণ করছে, আমার ঠিক 20 টির মতো Here is a link...উত্তর ছিল: উপরের মত উত্তরগুলি।
সর্বোচ্চ

1
@ ম্যাক্স কিছুটা দেরি হলেও প্রাসঙ্গিক কোডটি অন্তর্ভুক্ত করার জন্য আমি আমার উত্তর আপডেট করেছি।
ওয়েজ

0

আপনি বিল্ট-ইন উইন 32 ক্লাসের 'সিস্টেমএভেন্টস' শ্রেণিতে সংযুক্ত করতে পারেন:

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

-1

ডাব্লুপিএফ-তে একটি ডাব্লুড্রপ্রোকের সাথে বার্তাগুলি হ্যান্ডেল করার উপায় রয়েছে (উদাহরণস্বরূপ, এইচএনডিউসোর্স ব্যবহার করা ইত্যাদি) তবে সাধারণত সেই কৌশলগুলি ডেস্কটপগুলির সাথে ইন্টারপের জন্য সংরক্ষিত থাকে যা ডাব্লুপিএফের মাধ্যমে সরাসরি পরিচালনা করা যায় না। বেশিরভাগ ডাব্লুপিএফ নিয়ন্ত্রণগুলি উইন 32 (এবং এক্সটেনশন উইন্ডোজ। ফর্মস) অর্থে উইন্ডোও নয়, তাই তাদের ডাব্লুড্রপ্রোকস নেই।


-১ / অসম্পূর্ণ। যদিও এটি সত্য যে ডাব্লুপিএফ ফর্মগুলি উইনফোর্ডস নয়, এবং এর ফলে WndProcওভাররাইডের কোনও উন্মুক্ততা নেই , এর System.Windows.Interopফলে আপনি HwndSourceকোনও উপায় পেতে HwndSource.FromHwndবা কোনও উপায় পেতে PresentationSource.FromVisual(someForm) as HwndSourceপারেন যা আপনি একটি বিশেষ নকশার প্রতিনিধিকে বেঁধে রাখতে পারেন। এই প্রতিনিধিটির WndProcবার্তা অবজেক্টের মতো একই যুক্তি রয়েছে ।
অ্যান্ড্রু গ্রে

আমি উত্তরে HwndSource উল্লেখ করছি? অবশ্যই আপনার শীর্ষ স্তরের উইন্ডোতে এইচডব্লিউএনডি থাকবে তবে এটি বেশিরভাগ নিয়ন্ত্রণ নয় বলে এখনও সঠিক ।
লোগান ক্যাপাল্ডো

-5

ডাব্লুপিএফ উইনফর্মস প্রকারের wndprocs এ পরিচালনা করে না

আপনি একটি উপযুক্ত ডাব্লুপিএফ উপাদানটিতে একটি এইচডব্লুহোস্ট হোস্ট করতে পারেন তারপরে হুন্ডহোস্টের ডাব্লুড্রপ্রোককে ওভাররাইড করতে পারেন, তবে আফাইক যেটি আপনি পেতে চলেছেন তত কাছাকাছি।

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

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


-13

সংক্ষিপ্ত উত্তরটি আপনি পারবেন না। ডাব্লুড্রপোক একটি উইন 32 স্তরে এইচডাব্লুএনডি-তে বার্তা পাঠিয়ে কাজ করে। ডাব্লুপিএফ উইন্ডোগুলির কোনও এইচডব্লিউএনডি নেই এবং তাই ডাব্লুড্রপোক বার্তায় অংশ নিতে পারে না। বেস ডাব্লুপিএফ বার্তা লুপটি ডাব্লুডিপি্রোকের শীর্ষে বসে তবে এটি তাদের মূল ডাব্লুপিএফ যুক্তি থেকে দূরে রাখে।

আপনি এইচডাব্লুডহোস্ট ব্যবহার করতে পারেন এবং এর জন্য একটি ডাব্লুড্রপ্রোক পেতে পারেন। তবে এটি অবশ্যই আপনি যা করতে চান তা নয়। সিংহভাগ উদ্দেশ্যে, ডাব্লুপিএফ এইচডাব্লুএনডি এবং ডাব্লুএনডিপ্রোকে কাজ করে না। আপনার সমাধানটি অবশ্যই ডাব্লুপিএফ পরিবর্তন করার উপর নির্ভর করে ডাব্লুড্রপ্রোকে নয়।


13
"ডাব্লুপিএফ উইন্ডোগুলির কোনও HWND নেই" - এটি কেবল অসত্য।
স্কট সলমার 13
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.