WNDPROC es una función de devolución de llamada que se encarga de los mensajes del sistema enviados desde el sistema operativo. A diferencia de WinForms, en WPF, no está directamente expuesto a usted, ya que está oculto debajo de la capa de abstracción del marco.
Sin embargo, hay momentos en que necesita procesar estos mensajes manualmente, por ejemplo, cuando se trata de la API de Windows. Veamos algunas formas en que podemos hacerlo.
Forma no mvvm
Podemos usar estos métodos de ayuda para ayudar a usar una de las ventanas, y luego agregarle un 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;
}
En el ejemplo anterior, utilizamos la ventana principal de la aplicación como host, ya que generalmente permanece abierto mientras la aplicación se esté ejecutando. Puede especificar una ventana diferente a través de un parámetro en el FromVisual(...)
método, pero luego asegúrate de llamar source.RemoveHook(...)
y source.Dispose()
Después de que hayas terminado.
El enfoque anterior sufre de no ser amigable con MVVM, el WndProc(...)
El método, que probablemente se definirá en la capa del modelo, en realidad se acopla a una ventana. Como resultado, puede introducir una dependencia circular entre la vista y el modelo, lo que a menudo puede conducir a consecuencias indeseables.
Forma de MVVM
Como alternativa, podemos desacoplar el procesamiento de mensajes desde la capa de vista creando una ventana especializada de “esponja” invisible.
Convenientemente, System.Windows.Forms.NativeWindow
Se adapta exactamente a este propósito: es una clase de ventana de bajo nivel que no hace nada más que escuchar los mensajes del sistema. Podemos usarlo agregando una referencia al System.Windows.Forms
asamblea.
Así es como definí mi ventana 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
}
}
Asegúrate de no olvidar llamar base.WndProc(ref m)
de lo contrario, la ventana no se inicializará correctamente.
Ahora, suponiendo que tengamos algún tipo de WndProcService
podemos usar nuestra ventana de esponja así:
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();
}
}
Al manejar el WndProcCalled
Evento, puede escuchar mensajes entrantes. Por lo general, desea llamar a algún método de API de Windows que suscribe una ventana a mensajes WNDPROC adicionales utilizando su identificación, por ejemplo, RegisterPowerSettingNotification(...)
o RegisterHotKey(...)
.
Por ejemplo, si estuviéramos interesados en registrar una tecla de acceso rápido global y escuchar sus eventos, podríamos hacerlo de esa manera: 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.