문제

가파른 학습 곡선을 찾는다.

좋은 ol '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;
}

이제 WPF 애플리케이션에서 Windows 메시징 메시지를 처리하려는 이유는 확실하지 않습니다 (다른 WinForms 앱으로 작업하기위한 가장 확실한 Interop이 아닌 한). 디자인 이데올로기와 API의 특성은 Winforms와 WPF에서 매우 다르므로 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;
        }
    }
}

훌륭한 블로그 게시물에서 완전히 가져 왔습니다. Steve Rands의 WPF 앱에서 사용자 정의 WNDPROC 사용

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 참조를 포함해야한다는 것입니다. 그렇지 않으면 이것은 매우 캡슐화 된 솔루션입니다.

이것에 대한 자세한 내용은 읽을 수 있습니다 여기

WPF (예 : HWNDSOURCE 등 사용)에서 WNDPROC로 메시지를 처리하는 방법이 있지만 일반적으로 해당 기술은 WPF를 통해 직접 처리 할 수없는 메시지와 연결되어 있습니다. 대부분의 WPF 컨트롤은 Win32 (및 Extension Windows.forms)의 Windows가 아니므로 WNDProc가 없습니다.

내장 된 Win32 클래스의 'SystemEvents'클래스에 첨부 할 수 있습니다.

using Microsoft.Win32;

WPF 창 클래스에서 :

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에서 작동하지 않습니다

적절한 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

짧은 대답은 당신이 할 수 없다는 것입니다. WNDPROC는 Win32 레벨에서 HWND로 메시지를 전달하여 작동합니다. WPF Windows에는 HWND가 없으므로 WNDPROC 메시지에 참여할 수 없습니다. 기본 WPF 메시지 루프는 WNDPROC 위에 놓여 있지만 핵심 WPF 로직에서 멀리 떨어져 있습니다.

당신은 hwndhost를 사용하고 그것을 위해 wndproc에 갈 수 있습니다. 그러나 이것은 거의 확실히 당신이하고 싶은 일이 아닙니다. 대부분의 목적을 위해 WPF는 HWND 및 WNDPROC에서 작동하지 않습니다. 귀하의 솔루션은 거의 확실히 WNDPROC가 아닌 WPF를 변경하는 데 의존합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top