My WinForms app (targeting NET 3.5) uses keyboard shortcuts that I handle with ProcessCmdKey. I also have a small number of keys that are press and hold. For example the user presses the R key and drags out an area, or holds down the D key to temporarily display some objects. All this is associated with a Canvas control.

I have been handling the press and hold keys via the canvas Key_Down and Key_Up events.

I thought all this worked since most of it has been in the code for some time. However it has just become apparent that the press and hold actions are erratic and not guaranteed.

I am aware that ProcessCmdKey gets called before the Key_Down event and I can stop the Key_Down event by returning true from ProcessCmdKey for handled short cuts. As far as I can tell I can't stop the Key_Up event from being triggered though

The press and hold actions worked sometimes but then stop. The most reliable way to stop then is to press a Modifier Key. I had code in the Key_Down and Key_Up events related to the modifier keys which I suspect was responsible.

As an alternative I tried the code Hans proposed in the answer to this question: ProcessCmdKey - wait for KeyUp? I got it to work and disabled the code in the Key down and up events. This worked but stopped after pressing a modifier key since there was code for them in the Key_Down and Key_Up events. Removing that seems to get it working and I am left with the press and hold keys still failing if I use some other keys such as F8.

I have checked a number of other anwers to similar questions: Skipping KeyDown On Override ProcessCmdKey EventHandller and Key Events: ProcessCmdKey.

My ProcessCmdKey code is standard as far as I can tell. I can offer the code but I am just handling the KeyData in a switch block and acting on the combinations I want.

The code for the Key_Down and Key_Up follows this pattern

private void OnPCanvasKeyDown(object sender, KeyEventArgs e)
{
    if (e.Modifiers == Keys.Control)
    {
        controlDown = true;
        ctrlLabel.Text = "CTRL";
    }
    if (e.KeyCode == Keys.D)
    {
       if (!hiddenObjectsVisible)
       {
            hiddenObjectsVisible = true;
            services.ShowCustomHideObjects();
       }
     }
     OnKeyDown(e);
}

private void OnPCanvasKeyUp(object sender, KeyEventArgs e)
{
  if (e.KeyCode == Keys.ControlKey)
  {
      controlDown = false;
      ctrlLabel.Text = string.Empty;
  }

  if (e.KeyCode == Keys.D)
  {
      hiddenObjectsVisible = false;
      services.HideCustomHideObjects();
  }
   OnKeyUp(e);
}

I have tried with both the forms KeyPreview Property set to true and to false. This does not appear to change the behavior.

So in summary I need to handle both keyboard short cuts and press and hold keys at the same time on a single canvas. Overall I have sort of got it working but at the cost of losing the code that shows the user when a modifier key is down and it all seems a bit of a lash-up now. I am sure there must be a better way but I am running out of ideas so would appreciate some advice.

EDIT

I have now found that the keys that block the Press and Hold keys are all special in some way or another. Esc, F1-F2, Home, End, PageUp, PageDown and the arrow keys. Hit one of these to stop the Press and Hold working; hit one of these to allow it to work. Any and all of these keys toggle the working of the press and hold.

I have tried forcing focus onto the canvas but that is not it. I have tried to override IsInputKey but that does not work. So I am no further forward other than knowing it is these 'special keys'

有帮助吗?

解决方案

I am answering this in embarrassment. After testing my code on another computer the problem is the keyboard. For reasons that I do not understand the 'special keys' on keyboard on this computer appears responsible for blocking the capturing of press and hold key strokes.

So far as I can tell the code is fine so there is not a C# or WinForms issue here at all.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top