O WNDPROC é uma função de retorno de chamada que cuida das mensagens do sistema enviadas do sistema operacional. Ao contrário do WinForms, no WPF, ele não é diretamente exposto a você, pois está escondido sob a camada de abstração da estrutura.
Há momentos, no entanto, quando você precisa processar essas mensagens manualmente, por exemplo, ao lidar com a API do Windows. Vejamos algumas maneiras pelas quais podemos fazê -lo.
Maneira não mvvm
Podemos usar esses métodos auxiliares especiais para obter o identificador de uma das janelas e, em seguida, adicionar um gancho:
var window = Application.Current.MainWindow;
var source = HwndSource.FromHwnd(new WindowInteropHelper(window).Handle);
source.AddHook(WndProc);
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
return IntPtr.Zero;
}
No exemplo acima, usamos a janela principal do aplicativo como host, pois normalmente permanece aberto enquanto o aplicativo estiver em execução. Você pode especificar uma janela diferente através de um parâmetro no FromVisual(...)
método, mas depois ligue source.RemoveHook(...)
e source.Dispose()
Depois que você terminar.
A abordagem acima sofre de não ser amigável para MVVM-o WndProc(...)
O método, que provavelmente será definido na camada do modelo, é realmente acoplado a uma janela. Como resultado, ele pode introduzir uma dependência circular entre a visão e o modelo, o que geralmente pode levar a consequências indesejáveis.
MVVM Way
Como alternativa, podemos dissociar o processamento de mensagens da camada de visualização criando uma janela “esponja” invisível especializada.
Convenientemente, System.Windows.Forms.NativeWindow
se encaixa exatamente nesse objetivo – é uma classe de janela de baixo nível que não faz nada além de ouvir as mensagens do sistema. Podemos usá -lo adicionando uma referência ao System.Windows.Forms
conjunto.
Aqui está como eu defini minha janela de esponja:
public sealed class SpongeWindow : NativeWindow
{
public event EventHandler<Message> WndProcCalled;
public SpongeWindow()
{
CreateHandle(new CreateParams());
}
protected override void WndProc(ref Message m)
{
WndProcCalled?.Invoke(this, m);
base.WndProc(ref m); // don't forget this line
}
}
Certifique -se de não esquecer de ligar base.WndProc(ref m)
caso contrário, a janela não inicializará corretamente.
Agora, assumindo que temos algum tipo de WndProcService
podemos usar nossa janela de esponja como assim:
public class WndProcService : IDisposable
{
private readonly SpongeWindow _sponge;
public WndProcService()
{
_sponge = new SpongeWindow();
_sponge.WndProcCalled += (s, e) => ProcessMessage(e);
RegisterMessages();
}
private void RegisterMessages()
{
// Some Windows API calls here to register
// window messages with sponge's handle.
}
private void ProcessMessage(Message message)
{
// Here we process incoming messages
}
public void Dispose()
{
_sponge.Dispose();
}
}
Lidando com o WndProcCalled
Evento, você pode ouvir mensagens recebidas. Normalmente, você gostaria de ligar para algum método da API do Windows que assina uma janela para mensagens WNDPROC adicionais usando seu identificador, por exemplo, RegisterPowerSettingNotification(...)
ou RegisterHotKey(...)
.
Por exemplo, se estivéssemos interessados em registrar uma tecla de atalho global e ouvir seus eventos, poderíamos fazê -lo de tal maneira: Solana Token Creator
public class GlobalHotkeyService : IDisposable
{
(DllImport("user32.dll", EntryPoint = "RegisterHotKey", SetLastError = true))
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
private readonly SpongeWindow _sponge;
public GlobalHotkeyService()
{
_sponge = new SpongeWindow();
_sponge.WndProcCalled += (s, e) => ProcessMessage(e);
RegisterMessages();
}
private void RegisterMessages()
{
// Register F1 as a global hotkey
var id = 1;
RegisterHotKey(_sponge.Handle, id, 0, 0x70);
}
private void ProcessMessage(Message message)
{
// Only interested in hotkey messages, so skip others
if (message.Msg != 0x0312)
return;
// Get hotkey id
var id = message.WParam.ToInt32();
// Do something else...
}
public void Dispose()
{
_sponge.Dispose();
}
}

Luis es un experto en Inteligência Empresarial, Redes de Computadores, Gestão de Dados e Desenvolvimento de Software. Con amplia experiencia en tecnología, su objetivo es compartir conocimientos prácticos para ayudar a los lectores a entender y aprovechar estas áreas digitales clave.