Provides static methods to convert between Win32 VirtualKeys and our Key enum.
Esempio n. 1
0
        private void PreNotifyInput(object sender, NotifyInputEventArgs e)
        {
            RawKeyboardInputReport keyboardInput = ExtractRawKeyboardInputReport(e, InputManager.PreviewInputReportEvent);

            if (keyboardInput != null)
            {
                CheckForDisconnectedFocus();

                // Activation
                //
                // MITIGATION: KEYBOARD_STATE_OUT_OF_SYNC
                //
                // It is very important that we allow multiple activate events.
                // This is how we deal with the fact that Win32 sometimes sends
                // us a WM_SETFOCUS message BEFORE it has updated it's internal
                // internal keyboard state information.  When we get the
                // WM_SETFOCUS message, we activate the keyboard with the
                // keyboard state (even though it could be wrong).  Then when
                // we get the first "real" keyboard input event, we activate
                // the keyboard again, since Win32 will have updated the
                // keyboard state correctly by then.
                //
                if ((keyboardInput.Actions & RawKeyboardActions.Activate) == RawKeyboardActions.Activate)
                {
                    //if active source is null, no need to do special-case handling
                    if (_activeSource == null)
                    {
                        // we are now active.
                        _activeSource = new SecurityCriticalDataClass <PresentationSource>(keyboardInput.InputSource);
                    }
                    else if (_activeSource.Value != keyboardInput.InputSource)
                    {
                        IKeyboardInputProvider toDeactivate = _activeSource.Value.GetInputProvider(typeof(KeyboardDevice)) as IKeyboardInputProvider;

                        // we are now active.
                        _activeSource = new SecurityCriticalDataClass <PresentationSource>(keyboardInput.InputSource);

                        if (toDeactivate != null)
                        {
                            toDeactivate.NotifyDeactivate();
                        }
                    }
                }

                // Generally, we need to check against redundant actions.
                // We never prevet the raw event from going through, but we
                // will only generate the high-level events for non-redundant
                // actions.  We store the set of non-redundant actions in
                // the dictionary of this event.

                // If the input is reporting a key down, the action is never
                // considered redundant.
                if ((keyboardInput.Actions & RawKeyboardActions.KeyDown) == RawKeyboardActions.KeyDown)
                {
                    RawKeyboardActions actions = GetNonRedundantActions(e);
                    actions |= RawKeyboardActions.KeyDown;
                    e.StagingItem.SetData(_tagNonRedundantActions, actions);

                    // Pass along the key that was pressed, and update our state.
                    Key key = KeyInterop.KeyFromVirtualKey(keyboardInput.VirtualKey);
                    e.StagingItem.SetData(_tagKey, key);
                    e.StagingItem.SetData(_tagScanCode, new ScanCode(keyboardInput.ScanCode, keyboardInput.IsExtendedKey));

                    // Tell the InputManager that the MostRecentDevice is us.
                    if (_inputManager != null)
                    {
                        _inputManager.Value.MostRecentInputDevice = this;
                    }
                }

                // We are missing detection for redundant ups
                if ((keyboardInput.Actions & RawKeyboardActions.KeyUp) == RawKeyboardActions.KeyUp)
                {
                    RawKeyboardActions actions = GetNonRedundantActions(e);
                    actions |= RawKeyboardActions.KeyUp;
                    e.StagingItem.SetData(_tagNonRedundantActions, actions);

                    // Pass along the key that was pressed, and update our state.
                    Key key = KeyInterop.KeyFromVirtualKey(keyboardInput.VirtualKey);
                    e.StagingItem.SetData(_tagKey, key);
                    e.StagingItem.SetData(_tagScanCode, new ScanCode(keyboardInput.ScanCode, keyboardInput.IsExtendedKey));

                    // Tell the InputManager that the MostRecentDevice is us.
                    if (_inputManager != null)
                    {
                        _inputManager.Value.MostRecentInputDevice = this;
                    }
                }
            }

            // On KeyDown, we might need to set the Repeat flag

            if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyDownEvent)
            {
                CheckForDisconnectedFocus();

                KeyEventArgs args = (KeyEventArgs)e.StagingItem.Input;

                // Is this the same as the previous key?  (Look at the real key, e.g. TextManager
                // might have changed args.Key it to Key.TextInput.)

                if (_previousKey == args.RealKey)
                {
                    // Yes, this is a repeat (we got the keydown for it twice, with no KeyUp in between)
                    args.SetRepeat(true);
                }

                // Otherwise, keep this key to check against next time.
                else
                {
                    _previousKey = args.RealKey;
                    args.SetRepeat(false);
                }
            }

            // On KeyUp, we clear Repeat flag
            else if (e.StagingItem.Input.RoutedEvent == Keyboard.PreviewKeyUpEvent)
            {
                CheckForDisconnectedFocus();

                KeyEventArgs args = (KeyEventArgs)e.StagingItem.Input;
                args.SetRepeat(false);

                // Clear _previousKey, so that down/up/down/up doesn't look like a repeat
                _previousKey = Key.None;
            }
        }