Если вы не возражаете против ссылки на 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, но в остальном это очень инкапсулированное решение.
Подробнее об этом можно прочитать здесь