wpfpowershellxamlkeyboard-events

PowerShell WPF UI detect key combination


I am writing a UI to run in WinPE. I have everything working so far and am trying to make it so the user cannot close the window. I have made it full screen and disabled the close (X) button, but the user can still press Alt+F4 to close the UI. I have been able to make it so that if the user hits F8 the UI is in front so the user cannot Alt+Tab to it. I have read so many ways to do this but nothing covers it for PowerShell I am not sure how to implement it in the script. It is not running in a Runspace.

Here is what I have tried:

$altF4Pressed = {
    [System.Windows.Input.KeyEventArgs]$Alt = $args[1]
    if ( ($Alt.Key -eq 'System') -or ($Alt.Key -eq 'F4') ) {
        if ($_.CloseReason -eq 'UserClosing') {
            $UI.Cancel = $true
        }
    }
}

$null = $UI.add_KeyDown($altF4Pressed)

I have also read to do this (Disabling Alt+F4 in a Powershell form), but this does not work.

#disable closing window using Alt+F4
$UI_KeyDown = [System.Windows.Forms.KeyEventHandler]{
    #Event Argument: $_ = [System.Windows.Forms.KeyEventArgs]

    if ($_.Alt -eq $true -and $_.KeyCode -eq 'F4') {
        $script:altF4Pressed = $true;
    }
}

$UI_Closing = [System.Windows.Forms.FormClosingEventHandler]{
    #Event Argument: $_ = [System.Windows.Forms.FormClosingEventArgs]

    if ($script:altF4Pressed)
    {
        if ($_.CloseReason -eq 'UserClosing') {
            $_.Cancel = $true
            $script:altF4Pressed = $false;
        }
    }
    Else{
        [System.Windows.Forms.Application]::Exit();
        # Stop-Process $pid
    }
}


$UI.Add_Closing({$UI_Closing})
$UI.add_KeyDown({$UI_KeyDown})

I have also tried to do this:

$UI.Add_KeyDown({
    $key = $_.Key
    If ([System.Windows.Input.Keyboard]::IsKeyDown("RightAlt") -OR [System.Windows.Input.Keyboard]::IsKeyDown("LeftAlt")) {
        Switch ($Key) {
            "F4" {
                $script:altF4Pressed = $true;
                write-host "Alt+f4 was pressed"
            }

        }
    }
})

It detects the first keyboard press, but not the next one while the other is pressed. I think I need to use a Keybinding event instead, just not sure how to implement that in Powershell at the App level (not input level). I read you can add a keybinding to XAML code itself, but how do that with Powershell to detect the key combination (Alt+F4) when the UI presents itself?


Solution

  • You don't have a replicate-able example and I don't want to write one just for this, but I think this may be of assistance.

    $altF4Pressed = {
        [System.Windows.Input.KeyEventArgs]$Alt = $args[1]
        if ( ($Alt.Key -eq 'System') -or ($Alt.Key -eq 'F4') ) {
            if ($_.CloseReason -eq 'UserClosing') {
                $UI.Cancel = $true
                $Alt.Handled = $true
            }
        }
    }
    
    $null = $UI.add_KeyDown([System.Windows.Input.KeyEventHandler]::new($altF4Pressed))
    

    Also IIRC for WPF, you'll want to use System.Windows.Input not System.Windows.Forms, so the second snippet you posted may actually work if you change the namespace.