I am trying to make a platformer game in windows c# forms, in my main game loop I've got some pieces of code but I can't seem to get the user input to work correctly, any help would be appreciated!
this is my code:
while (true)// this is still in testing so it should go on forver
if (Keyboard.IsKeyDown(Key.Insert) == true)
{
btn1.Left = btn1.Left + 1;// btn is a button
Update();
}
System.Threading.Thread.Sleep(50);
}
whenever I run this the program becomes unresponding and eventually crashes
and when I press insert or any other key I used it does not work
Assuming this code is running in a Form you should subscribe to the Form's KeyDown event:
public partial class YourForm : Form
{
public YourForm()
{
InitializeComponent();
KeyDown += KeyDownHandler; // subscribe to event
KeyPreview = true; // set to true so key events of child controls are caught too
}
private void KeyDownHandler(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Insert) return;
btn1.Left = btn1.Left + 1;// btn is a button
e.Handled = true; // indicate that the key was handled by you
//Update(); // this is not necessary, after this method is finished, the UI will be updated
}
}
So the KeyDownHandler gets called if the user presses the key. There is no need to pull the keyboard state in a loop that blocks your UI thread.
The subscription to the event and the KeyPreview value can be set in the designer window too if you prefer that to writing in your own code.
And btw: the Keyboard class is part of WPF. You should not mix that with Windows Forms.
Related
I need show droppeddown combobox after start program.
I need in dropdown style only, not simple style.
This is simple fragment of my program:
private void Form1_Shown(object sender, EventArgs e)
{
CB1.Items.Add("1");
CB1.DropDownStyle = ComboBoxStyle.DropDown;
CB1.DroppedDown = true;
}
But I found the watch sign as cursor till I click on Form in any place.
I guessed that my Form have not fully active state and wait for something.
When I click Form (or combobox or any control) by LBM, it activated fully and all works fine.
Of course the combobox is dropup then, so I need click combobox twice.
Đ•ell me please what is correct initialization of such style combobox without "Cursor = Cursors.Default;"
You can simply wait until cursor is the default:
while (Cursor.Current != Cursors.Default)
{
Application.DoEvents();
}
CB1.Items.Add("1");
CB1.DropDownStyle = ComboBoxStyle.DropDown;
CB1.DroppedDown = true;
Application.DoEvents simply process messages from the window queue, so you can process message until you get that cursor is the default. In that moment, you can drop down your control without problem.
If you prefer, create a extension method for the Form:
public static class FormExtends
{
public static void WaitToDefaultCursor(this Form form)
{
while (Cursor.Current != Cursors.Default)
{
Application.DoEvents();
}
}
}
And use it:
this.WaitToDefaultCursor();
CB1.Items.Add("1");
CB1.DropDownStyle = ComboBoxStyle.DropDown;
CB1.DroppedDown = true;
NOTE: I use Cursor.Default but not to change the cursor. The form is processing messages and it's difficult to select a good moment to drop down the control.
I need to be alerted before my entire form loses focus. The Deactivate event only triggers after it loses focus. LostFocus and Leave are only for controls.
I have also tried overriding WndProc but this only triggers after the message has been processed.
overriding PreProcessMessage only can be used for keyboard stuff, not form deactivation.
Dodgy Method
Even though this is a quick and hacky way of doing it, changing Input Language is unnatural to start with..
private void Form1_Deactivate(object sender, EventArgs e)
{
((Form)sender).Activate();
System.Diagnostics.Debug.WriteLine(this.ActiveControl.Name);
//Change Input Language here..
//Alt TAB to set focus to the application selected 5 milliseconds ago
SendKeys.SendWait("%{TAB");
}
Correct and orthadox method
How to monitor focus changes? and C#: Detecting which application has focus
Its using the Automation framework, Add references to UIAutomationClient and UIAutomationTypes and use Automation.AddAutomationFocusChangedEventHandler, e.g.:
public class FocusMonitor
{
public FocusMonitor()
{
AutomationFocusChangedEventHandler focusHandler = OnFocusChanged;
Automation.AddAutomationFocusChangedEventHandler(focusHandler);
}
private void OnFocusChanged(object sender, AutomationFocusChangedEventArgs e)
{
AutomationElement focusedElement = sender as AutomationElement;
if (focusedElement != null)
{
int processId = focusedElement.Current.ProcessId;
using (Process process = Process.GetProcessById(processId))
{
Debug.WriteLine(process.ProcessName);
}
}
}
}
Got it, this hack works perfectly.
private void MyForm_Deactivate(object sender, EventArgs e)
{
Thread.Sleep(200); //delay to allow external tab time to open
Form f1 = new Form(); //create a new form that will take focus, switch input, then terminate itself
f1.Shown += new EventHandler((s, e1) => { f1.Activate(); InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage; f1.Close(); });
f1.Show();
}
EDIT: upon further testing I have found this to be equally unreliable. It doesn't seem like there is a good way to do this at all.
For now I am tracking the mouse and keyboard to detect when the user is about to deactivate it. Obviously a mouse and keyboard hook is a horrible solution but its the only reliable solution so far.
In my windows form application, I want the input characters from the keyboard to be collected in a string (even if there is no active input field in the form),
I mean that if my form window is active whenever a key is pressed it should be appended to a string without having any input fields in the form, that I'm going to use the input in the background without showing it to the user.
In your form constructor set KeyPreview property to true and associate event handling with the keyevent you want
public MyForm : base()
{
this.KeyPreview = true;
// handle KeyDown event
this.KeyDown += new KeyEventHandler(MyForm_KeyDown);
}
private void MyForm_KeyDown(object sender, KeyEventArgs e)
{
// do what you need
}
Im trying to do like that: If I press the key "P" a messagebox will open in the screen.But I need to do it without a textbox or other tool, I want to do that direct in the form.
I tried:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.P)
{ MessageBox.Show("Key P pressed"); }
}
Try with the KeyPress Event of the form. It just works fine.
Assuming this is Winforms, on the form you're trying to catch the event on, make sure to set
Form1.KeyPreview = true;
KeyPreview ensures that keyboard events anywhere on the particular form (such as to a textbox with focus) will still count as a keyboard event for the form itself.
I want to move a button using a function which will be activated through a keyboard button, but I can't seem to make it accept my input. If I try to run the function through a button press, it works fine, so I know the function is not to blame. What am I doing wrong that it's not accepting my keyboard input?
private void MoveLeft()
{
_y = btnBot.Location.Y;
_x = btnBot.Location.X;
btnBot.Location = new System.Drawing.Point(_x - 10,_y);
}
void MoveLeft_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
{
MoveLeft();
}
}
To ensure that your form key handle event is triggered, even if another control has focus, make sure the KeyPreview property is set to true.
In your main form, add the following line, or set it during design time.
this.KeyPreview = true;