How to detect more than one keypress simultaneously in C#? - c#

I am working on a map editor for my game and I use the arrow keys to scroll around the map area. Currently I'm using the KeyDown event, which works fine for scrolling up, down, left or right - but my question would be how to allow diagonal scrolling. Currently, if I hold the right-arrow and then (whilst keeping the right-arrow held) I then press and hold the down-arrow, the down direction replaces the scrolling to the right instead of scrolling diagonally to the bottom right.
Is there a way, for instance, that I could check whether another arrow key is being pressed whilst in the KeyDown event? How can I respond to more than one key being held?
Thanks

Not easily, the key-down of the 2nd keystroke stops the 1st one from repeating. What you have to do is record that the key is down in the KeyDown event. Cancel that state in the KeyUp event. Next, use a Timer (~250 msec) and in its Tick event check the state of the keys.

The easiest way to do this is to use a Windows API call to get the state of every key on they keyboard, and then check the keys you are interested in: GetKeyboardState via PInvoke.
You can call it on KeyDown/KeyUp, check the state of the keyboard, and act appropriately.

Related

Holding down arrow keys in DataGridView not moving cursor smoothly

If I press and hold down either the UP or DOWN arrow key when focused on a DataGridView, the cursor (blue highlighted cell) doesn't move evenly down the rows, instead it jumps several rows at a time in batches. Sometimes it doesn't even seem to move at all until the key is finally released, then the cursor jumps directly to several rows ahead having presumably stored all the key presses.
Here is a GIF image showing the behaviour when pressing and holding the DOWN arrow, then releasing it and pressing and holding the UP arrow.
This movement looks wrong and makes it hard for the user to judge when to release the key to navigate smoothly over several rows. It doesn't even seem to move an number of rows on each jump it makes (like 10-20 rows on each jump, sometimes the whole page, or even reappearing many rows beyond when the user finally releases the key).
For example if the user wants to move the cursor about half way down the page, by pressing the DOWN arrow key and holding it down, then it is very hard to know when to release the key because the cursor is not moving down in an even progress.
Why doesn't it visibly move to each row one at a time in a smooth repeating manner, instead of doing ugly hopping over batches of rows?
This can be reproduced as follows:
Make a new forms project.
Drop a DataGridView control onto the form.
Add a DataGridViewTextBoxColumn in the designer.
Add some rows to the DataGridView, and add a little formatting to make enough rows visible for your test, in the FormLoad event:
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.RowTemplate.Height = 14;
dataGridView1.Rows.Add(50);
dataGridView1.Dock = DockStyle.Fill;
}
Then run the program and press and hold the DOWN arrow key to see how the blue highlight jumps down strangely instead of moving smoothly down from row to row.
The strange behaviour exists even when the DataGridView is read only.
I have tried making the grid and the form DoubleBuffered but no success. I have also tried setting the grid to Virtual mode and ReadOnly and changing just about every setting of the grid, but nothing works.
The only way I have discovered to make the cursor to move smoothly and rapidly up or down the rows without jumping over batches of rows, has been to not let the DataGridView be focused. To do this I make another control on the form (for example a textbox, and give focus to the text Box). Then I override the processCmdKey method on the form to capture the keyboard input and if it detects an arrow key then I programmatically change the current cell in the DataGridView (for example to the next row if the DOWN key was detected in processCmdKey). This moves the current cell without ever giving actual focus to the DataGridView. The movement of the highlight then appears to progress evenly and doesn't jump down in strange batches.
Add a text box onto the form
Add this code to the form:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
int currentRowIndex = dataGridView1.CurrentCell.RowIndex;
switch (keyData)
{
case Keys.Up:
// Check not already at the first row in the grid before moving up one row
if (currentRowIndex > 0)
dataGridView1.CurrentCell = dataGridView1.Rows[currentRowIndex - 1].Cells[dataGridView1.CurrentCell.ColumnIndex];
return true;
case Keys.Down:
// Check not already at the last row in the grid before moving down one row
if (currentRowIndex + 1 < dataGridView1.Rows.Count)
dataGridView1.CurrentCell = dataGridView1.Rows[currentRowIndex + 1].Cells[dataGridView1.CurrentCell.ColumnIndex];
return true;
}
// Line below is reached if we didn't handle the key in this method, it tells the form/control to handle it
return base.ProcessCmdKey(ref msg, keyData);
}
Then run the program to test again as follows:
Click on the text box to give it focus (instead of the grid). Then press and hold the DOWN key, to see that the blue highlighted current cell progresses smoothly down through the rows. Release the key.
Then click on the grid to give it focus, then press and hold the UP or DOWN arrow key and witness the blue highlight jumping across several rows instead of progressing smoothly.
So the problem exists whenever the DataGridView has focus, regardless of whether the grid handles the keys presses or if I handle them in processCmdKey.
I don't want to rely of keeping focus away from the grid, because there are times when a grid needs to have focus. I'd also have to add a lot more code to processCmdKey to handle all the other potential key presses for a grid, such as tab, page up / down, enter etc., which doesn't seem sensible.
The grid will actually be read only in my application, so it is probably only really the ability to move around smoothly that I need to use, but nevertheless having a dummy control that is focussed instead of the grid doesn't seem sensible.
A slightly similar problem was mentioned here (DataGrid not scrolling smoothly), but it is not Windows Forms and the original poster seemed to state that his problem was fixed by getting rid of all event handling and turning on virtualization, but I've tried virtual mode and I am not handling any events of the grid. He also states that he was on a very busy server. So I think this probably merits me adding this as its own separate question.
Any help would be much appreciated. Thanks :)
The problem has now been solved by changing the keyboard repeat speed settings on the computer. I went to Control Panel | Ease of Access | Change How Your Keyboard Works | Scroll down and choose 'See also: Keyboard Settings'. This then displays a window called 'Keyboard Properties', where I had to lower the 'Repeat Rate', I moved the slider slightly form Maximum (about a quarter of the way from maximum) and clicked apply.
The when I re-tested the program, it worked normally and the cursor moved smoothly down the grid when I pressed and held the Down arrow key.
So I am guessing that there is something strange about my PC that made it not able to cope well when using the maximum keyboard repeat rate, in the case of a DataGridView.
In an ideal world, I'd be able to use a really fast keyboard repeat rate set to maximum, but I am happy enough to settle for a slower keyboard repeat rate in order to solve my problem using the arrow keys smoothly on a DataGridView.
#Sinatr, thanks again for helping me by testing the code on your PC, just telling me that you couldn't reproduce it and that I probably had a problem with my PC rather than my code, was a big help.

Click and hold on Windows 8 Tablet PC in C#

I'm converting a reaction time test to tablet PC. The test involves the user pressing the 5 key on the numeric keypad and holding it down until a random timer fires off and gives them a direction stimulus. They are then supposed to release the key and press the corresponding direction key (8, 4, 6, 2) and then return to pressing and holding the 5 key.
The problem I'm having is that the tablet treats a long press or press and hold as a right click. I need to be able to override this behavior. If I put a button on the form with a mousedown and mouseup event, the mousedown event fires properly if I tap-taphold, and then mouseup fires when I release. but I need a similar event to mousedown for a long press that isn't preparing the tablet for right click.
Any ideas?
Assuming you are using WinRT-XAML and not WPF, Silverlight or Windows Forms - you could use the PointerPressed/PointerReleased events instead of the click or gesture events.

WPF: MouseEvents blocked for a short perioid of time after keystroke

"Resolved", Thanks for input
i cant figure this out.
After i press the keyboard (With or without attatching event handlers for keystrokes)
MouseEvents gets blocked for a short period of time.
-Modifier keys does not block the mouse events (ctrl, shift...)
So what happends is, if i press like 'A', and press the mouse on some control, it does not register. (It takes somewhere between 500ms to 1s for the mouseclicks to register again)
Anyone else experienced this? Is there a workaround?
Iv tried hooking onto PreviewKeyDown and Up on all my contols/windows and done e.Handled = true, but no luck.
Kind Regards Tor Einar

How do I make a button seem like pressed and then unpressed from code naturally in c# for WP7?

I am trying to make buttons seem like pressed automatically so the user can then follow the buttons pressed but everytime I try it doesn't seem natural because the computer does it really fast all the changes!
Any ideas? I have to get a serious of buttons pressed that look like user pressed and then pass to unpressed again
Thanks a lot!!!!
Well I'm trying to make a game where you remember the buttons that were randomly selected by the computer and then you press them, so I need computer to act like if the user were touching them and then the user follows...
How about using a custom storyboard animation that takes the button to the pressed, and then unpressed state?

DateTimePicker Winforms: Move focus left arrow key

I am making one "keyboard operated application" in which the user will use only keyboard.
The user will use left and right arrow keys, sometimes Up and Down arrow keys to navigate through different controls while filling a form.For that I use the keydown event and use SendKeys.SendWait({TAB}) for right key and SendKeys.SendWait(+{TAB}) for left key.
I have one DateTimePicker with custome format of dd/MM/yyyy.
When the year part is selected and the user presses the left arrow key, the focus moves to month part. when the arrow key is again pressed the focus moves to day part.
What I want is that when the day part is selected and the user presses the left arrow key, focus should move to the previous control (SendKeys.SendWait(+{TAB})).
Please suggest a solution.
Edit: The standard DateTimePicker does not expose any way to tell what element is selected, unfortunately, so it isn't possible to achieve this without creating your own control.

Categories

Resources