4

This issue is caused by an inconsistent setting in vmware fusion - the secondary mouse function of MacOS (ie, right click) was being triggered by the control-left click, in spite of being configured in vmware fusion settings to send control through as a separate key.

I am leaving this here as it outlines the diagnostic steps taken to isolate the issue.

This behaviour might be present in other virtualisation solutions on MacOS.

This is not a duplicate - I have tried the approaches suggested - They Do Not Work. Genuine help is required please.

I am trying to implement a multiple select function in a WPF canvas, and need to be able to detect when either control key is held while clicking on an item.

I have already tried using the documented and accepted methods of getting the key (Keyboard.IsKeyDown and Keyboard.Modifiers) and although they are supposed to work, they do not in this case.

I cannot place a key handler in the main window of the application as this solution is implemented in a component, and as such, I do not have access to the main window.

I cannot create a keyboard OnKeyDown override, as it does not register the event. I do not know why this is, but suffice to say, I have tried all the methods I can find after an extensive search on Stack Overflow, and am currently out of ideas.

In the current logic, clicking an item in my canvas will clear any selected items already. If the control key is held, I will not clear selected items.

The structure of my application is as follows:

Main Window -> Dock Panel -> ScrollViewer -> Main Custom Component (extends Canvas) -> ChildCanvas objects (multiple instances, all also extend Canvas).

The component will not have any reference back to the main window - this is absolutely not negotiable.

The component must not require a reference to the main window to be passed in to it.

The component cannot rely on any logic, properties, methods or other functional code being placed in the MainWindow - it must be totally reusable.

Multiple instances of a custom object (ChildCanvas) which itself derives from Canvas are placed onto a base custom object (ExtendedCanvas) which also extends Canvas.

I am detecting the mouse click in a mouse event handler within my custom item.

Although I can in theory handle the key event and set a bool flag when the key goes down and clear it when the key goes up, this is not a reliable way to do things as it would require the focus to be on whichever component is handling the key.

All the examples I have looked at require a specific event handler for the key press, but I cannot apply that approach in this case as it simply does not seem to register the key press, even if the component where the event handler is implemented has focus at the time.

I would like to find a way to check if a key is held down in the mouse click handler if this is possible in WPF.

EDIT: I have tried using the Keyboard.Modifiers approach, but this returns no result.

EDIT: I have also tried Keyboard.IsKeyDown(Key.LeftCtrl), which does not return any values.

EDIT: I have tried to handle the key event globally by registering on the EventManager as shown. What I have found is that key up and key down events are triggered in quick succession. The first event has the property e.IsRepeat as false, and all subsequent event occurrences have e.IsRepeat set as true. Using these events, I have set a bool which is set to true in the first keyDown event is e.IsRepeat is false (the first initial key press), and set to false in the keyUp event if e.IsRepeat is false (the keyUp event fire when the key is physically released).

This does not work - clicking the item on the canvas when the key is held altered the state of the bool setting it to false.

This behaviour is totally inconsistent with what Microsoft document for the way the keyboard handling should work.

EventManager.RegisterClassHandler(typeof(Control),
    Keyboard.KeyDownEvent,new KeyEventHandler(keyDown),true);

I can call Keyboard.IsKeyToggled(Key.LeftCtrl) which does show the toggled state, but it changes with every key press, and does not show me whether the key is held down at the time of the mouse click.

public class ExtendedCanvas:Canvas {
    public ExtendedCanvas() {
        MouseUp += thisMouseUp;
    }


    void thisMouseUp(object sender,MouseButtonEventArgs e) {

        if ((Keyboard.Modifiers & ModifierKeys.Control) > 0) {
            //This does not work - no key is registered, as for some reason, Keyboard.Modifiers does not register that the key is held.
        }

        //If CONTROL is held down 
        if (!ControlKeyHeldDown) {
            ClearSelectedItems();
        }

        IsSelected = true;    
    }
}
Alex
  • 1,643
  • 1
  • 14
  • 32
  • Possible duplicate of [Getting shift/ctrl/alt states from a mouse event?](https://stackoverflow.com/questions/1275371/getting-shift-ctrl-alt-states-from-a-mouse-event) – scharette Jul 30 '18 at 13:01
  • Apologies, have tried the `Keyboard.Modifiers` approach, but it did not work. I neglected to add this to my question originally. – Alex Jul 30 '18 at 13:05
  • Possible duplicate of [How to detect modifier key states in WPF?](https://stackoverflow.com/questions/5750722/how-to-detect-modifier-key-states-in-wpf) – dhilmathy Jul 30 '18 at 13:31
  • Not a duplicate, the modifier key states solution does not work in this case. I have added more details. – Alex Jul 30 '18 at 13:50
  • This works for me based on what you've shown for code. Do you get the MouseUp event at all? – Jeff R. Jul 30 '18 at 14:33
  • @JeffR. The mouse up event fires, but I get nothing in the key modifiers when holding the CTRL down while clicking. – Alex Jul 30 '18 at 14:33

1 Answers1

1

The inconsistent behaviour is the result of a VMWare option.

This VM is being run on MacOS and in spite of VMWare Fusion being configured to send the Control key straight through, Control Click was still triggering the secondary mouse button (ie, right click in this case).

The solution is:

1) Shut down the VM.

2) In VMWare Fusion Preferences -> Keyboard And Mouse -> Mouse Shortcuts, ENABLE (Check) the "Secondary Button" option if it is not checked.

3) Close the preferences window to save the settings.

4) Close VMWare Fusion

5) Reboot the host system

6) In VMWare Fusion Preferences -> Keyboard And Mouse -> Mouse Shortcuts, DISABLE (UnCheck) the "Secondary Button" option.

7) Start the VM, and confirm that Control Click no longer triggers the secondary click.

This option had been configured to send Control straight through prior to upgrading VMWare Fusion from 8 to 10.

It appears that although the Secondary Function checkbox was unchecked, the property was set to true, and it was behaving inconsistently from the way the settings suggested it should.

Alex
  • 1,643
  • 1
  • 14
  • 32