Home > OS >  Implementing global hotkey in WPF without breaking MVVM
Implementing global hotkey in WPF without breaking MVVM

Time:08-30

Workflow of my app:

Run -> LoginPage -> MainPage(Hotkey registered)

Hotkey logic of MainPage:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    Window window = Window.GetWindow(this);
    IntPtr handle = new WindowInteropHelper(window).Handle;
    RegisterHotKey(handle, 48000, 1, 123);
    Debug.WriteLine("Hotkey Registered");
}

Hotkey logic of MainWindow:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
    source.AddHook(new HwndSourceHook(WndProc));
}

internal IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == 786)
    {
        int key = ((int)lParam >> 16) & 0xFFFF;
        int modifierKey = (int)lParam & 0xFFFF;
        if ((modifierKey == 1) && (key == 123)) // Pressed Alt F12
        {
            // Do something...
        }
    }
    return IntPtr.Zero;
}

I implemented global hotkey in the MainWindow of WPF app using user32.dll. I want to write code displaying a screenshot taken from pressing Alt PrtScn on the Image control of MainPage when GlobalHotkey is pressed. However, Global hotkey is handled by MainWindow, and I need to modify the source of the Image control. How can I write the proper code(using ViewModel)?

CodePudding user response:

Adding the hook/event handler should be done in the view (window). It's not different from raising any other event in response to for example a key press or a mouse click. It's your application logic that should reside in the view model.

In your hook, you could call a method of the view model, e.g.:

internal IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    var viewModel = DataContext as YourViewModel;
    if (viewModel != null)
        viewModel.HandleEvent(msg);

    return IntPtr.Zero;
}

So in short, the event is raised in the view but your logic to handle the event is defined in the view model.

MVVM is not about eliminating code from the views. It's about separation of concerns.

  • Related