C#: KeyDown Event does not work in controls - c#

I am trying to finish my final school project. I am creating a c# winform game to be specific. We can not use anything else.
I will not be posting here code because I got it pretty messed up and I guess u can answer me just with this info.
Setup:
I got my program set up like this. The is main form and two user controls. I switch those controls within the main form during the game. The first one is MENU and the second one is GUI with picturebox acting as a gamescene.
Problem:
Setup quite not important I guess. But what I need to do is to do some action when I press key Down on the first Control (while it is active in the form). Sounds easy I thought at first but the onKeyDown event in the menu.cs(1st usercontrol) is doing nothing when i press the key(The event method is not blank). I tried this.previewKey = true; in the menu load method but it did not even recognize it.
So my question is: Is there any way to use onKeyDown in usercontrols code?
I did it this way becouse I use the same keys in the second controls and i didnt want it to get messy (which obviously did the oposite huh)
TLDR: Need to use onKeyDown event in userControls (keyPreview might be the key)
BONUS
I also need to somehow link variables from Controls 1 to Form and Controls 2.
I looked it up and found out it would be easy in situacion like "Form to Form" but since it is userControls I cant figure it out and I feel like I am just a tiny bit from finishing it.(feels terrible sitting here 9 hours xD please help)

On the keypress event make sure it is for the selected control an not the main form. If you are capturing for the form to determine which key was pressed then use the keypress event for that. You can use a messagebox to verify that you have the right control. Every key has an integer value and you can access and use those by using the properties of e.
Bonus. Depending on how you implemented your code you will have to use either global varibles to pass the data across the forms or use delegates to actively access and set controls on another form

You have to register the event in the Form.Designer.cs :
private void InitializeComponent()
{
// Your form properties here
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
}
You're KeyDown event can be used like this in the Form.cs code :
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// To know if your event is working and the value of the key who's pressed
MessageBox.Show("Key Pressed = "
+ e.KeyCode.ToString()
+ ", Value = "
+ e.KeyValue.ToString());
// Example - add some actions bellow
if (e.KeyValue == 13)
MessageBox.Show("Return Key Pressed");
}

Related

Making sure that a C# form has focus when it should

I am a fairly new to Visual C# but have coded in Delphi for a long time. I have created a form that has a simple panel that is hidden unless you type in a particular key on the keyboard (I do have "KeyPreview" set for true for the form and I am using the KeyDown event to handle determining if the correct key was pressed and to make the panel visible/invisible). Just beneath the panel is a webBrowser component.
What is happening is as follows:
When my form initially starts, I have code for the "Shown" event that makes sure the form has focus initially:
private void Form1_Shown(object sender, EventArgs e)
{
if (!Focused)
{
Focus();
}
}
When the form is focused at this point, my code for detecting the proper keystroke to get the panel to appear or disappear works fine.
Here is where things get strange and I'm not sure of what to do. There are two parts I am dealing with for what is wrong:
If I click on another form and then on the caption bar of my form again to get focus on my form and try a keystroke, the keystroke detection does not work. However, if I click on another form and then back on my form one more time, the keystroke detection for the form does work. What can I do to make sure that this works each time my from has focus again?
If I click on the web browser component within my own form, the KeyDown code for the form no longer gets enacted. Even if I click on the caption bar for the form, the KeyDown event does not work. What do I need to do to assure that, if a component within my form is clicked, my form will still respond for the KeyDown event?
Thanks in advance for any advice.
I can't say why your caption bar seems to be intercepting key events. It may be that various components on the form can have focus and thus capture keyboard events. I know the web browser control works this way. You may consider capturing keyboard events globally.
I saw something on Codeproject that shows how to do this. I hope this helps.
They use UserActivityHooks.
UserActivityHook actHook;
void MainFormLoad(object sender, System.EventArgs e)
{
actHook= new UserActivityHook(); // crate an instance
// hang on events
actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);
actHook.KeyDown+=new KeyEventHandler(MyKeyDown);
actHook.KeyPress+=new KeyPressEventHandler(MyKeyPress);
actHook.KeyUp+=new KeyEventHandler(MyKeyUp);
}
As for the webbrowser control, of course it is going to interecept keyboard events. Users often have to enter text in forms and developers often code javascript on webpages to specifically hook into keyboard events. So the webbrowser control must be able to capture those.

KeyDown Events in WPF Application only work with Focus

I have a calculator with a WPF Interface, and there is a grid containing most of the buttons. I want these buttons to react to, say, the NumPad keys, among others. I created KeyDown Events for all of them, but this only works when the button whose key I press is currently focused. I read about the KeyPreview property, but that only exists for Windows Forms, correct? I feel like I just need to change a property of my ButtonGrid, but I can't figure it out.
Relatively new to programming by the way.
Edit: This is one of the methods, how would a generic method look like? OnlyDigitsInTextBox is a custom method consisting of the .AppendText Extension method.
private void Button6_Key(object sender, KeyEventArgs e)
{
if (e.Key == Key.NumPad6)
{
OnlyDigitsInTextBox("6");
}
}
Best approach would be to use Custom Commands with KeyBindings.
WPF Custom Commands
WPF KeyBindings
I made it work now with an EventHandler using switch case for every possible button, and putting that EventHandler up as a property of the MainWindow, setting the Focusable property of all buttons to False. This is probably far from ideal, but it works for now, so thanks everybody!

How can a control handle a Mouse click outside of that control?

I'm writing a custom control and I'd like the control to switch from an editing state to it's normal state when a user clicks off of the control. I'm handling the LostFocus event and that helps when a user tabs away or if they click on to another control that's Focusable. But if they don't click on something Focusable, it won't switch out of it's editing state. So I have two solutions in mind:
Walk up the tree to the top most element when it goes in to an editing state and add a handler for MouseDownEvent (and handle "handled" events). In the handler I'd kick the control out of it's editing state and remove the handler from the top most element. This seems like a bit of a hack, but it would probably work well.
Example code:
private void RegisterTopMostParentMouseClickEvent()
{
_topMostParent = this.FindLastVisualAncestor<FrameworkElement>();
if ( _topMostParent == null )
return;
_topMostParent.AddHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ), true );
}
private void UnRegisterTopMostParentMouseClickEvent()
{
if ( _topMostParent == null )
return;
_topMostParent.RemoveHandler( Mouse.MouseDownEvent, new MouseButtonEventHandler( CustomControlMouseDownEvent ) );
_topMostParent = null;
}
Use Mouse.PreviewMouseDownOutsideCapturedElement and add a handler to my control. In the handler I'd kick the control out of it's editing state. But I don't seem to get the event to fire. When does the Mouse.PreviewMouseDownOutsideCapturedElement get kicked off?
Example code:
AddHandler( Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler( EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent ), true );
Just to clarify the answer provided about mouse focus - it was useful but I had to do some further digging + mucking about to get something that actually worked:
I was trying to implement something like a combobox and needed similar behaviour - to get the drop down to disapear when clicking on something else, without the control having knowledge of what something else was.
I had the following event for a drop down button:
private void ClickButton(object sender, RoutedEventArgs routedEventArgs)
{
//do stuff (eg activate drop down)
Mouse.Capture(this, CaptureMode.SubTree);
AddHandler();
}
The CaptureMode.SubTree means you only get events that are outside the control and any mouse activity in the control is passed through to things as normal. You dont have the option to provide this Enum in UIElement's CaptureMouse, this means you will get calls to HandleClickOutsideOfControl INSTEAD of calls to any child controls or other handlers within the control. This is the case even if you dont subscribe to the events they are using - full Mouse capture is a bit too much!
private void AddHandler()
{
AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true);
}
You would also need to hang on to + remove the handler at the appropriate points but I've left that out here for the sake of clarity/brevity.
Finally in the handler you need to release the capture again.
private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
{
//do stuff (eg close drop down)
ReleaseMouseCapture();
}
Capture the mouse.
When an object captures the mouse, all mouse related events are treated as if the object with mouse capture perform the event, even if the mouse pointer is over another object.
I usually get the parent window and add a preview handler, even if already handled. Sometimes when MouseCapture is not enough, this technique comes handy:
Window.GetWindow(this).AddHandler
(
UIElement.MouseDownEvent,
(MouseButtonEventHandler)TextBox_PreviewMouseDown,
true
);
I would approach this a different way - have the form that contains the control remove focus from the control when a user clicks on another part of the form.
Having the control actually loose focus is far cleaner than attempting to have the control "simulate" focus being lost in certain situations, when in fact it hasn't. Bear in mind that unless the control has really lost focus it will still accept things like keyboard input.

How to force control to fire leave event in winforms using c#?

I am pasting text in textbox1.text and I need textbox1 should fire its leave event by itself.
For now I am using this following code. but i will appreciate if anyone can suggest me an elegant or better way:-
private void event()
{
textbox1.Text = SearchedText;
textbox1.Focus();
textbox2.Focus();
}
First I am pasting text, then setting up Focus on the control, then set up focus again on second control. It is firing leave event of textbox1, but any thing better?
Just call the code directly, no need to wait for an event:
private void textBox1_Leave(object sender, EventArgs e) {
mumble();
}
private void someEvent() {
textBox1.Text = SearchedText;
mumble();
}
void mumble() {
// etc...
}
Just calling textBox1_Leave(this, EventArgs.Empty) works fine too.
You should handle the TextChanged or Validated events instead of the Leave event.
To FORCE Leave, Validating and so on Events, no matter what, I've found ONE working solution.
First i tried:
ProcessTabStop(true);
ProcessTabStop(false);
instead of:
textbox1.Focus();
textbox2.Focus();
Problem with the TextBox 1 and 2 Focus() is that its only Active Component that needs Leave, Validating and so on fired, not other Controls, and besides, what if the form is dynamic, you as a programmer not necessarily have any idea what Control you are trying to Leave, that's why i changed Control.Focus() method to ProcessTabStop method above. The problem is then, if only ONE Control has TabStop true, there is no control to go to and back from. So Events are NOT Fired.
Next problem is that i not necessarily Close the Form with the mouse so Focus doesn't change, I use a Key (Ctrl+Enter) to Accept the Form, and then Leave, validating and so on are NOT fired, when i Send Form Close, as Form Close registers weather there are changes or not. But Values are set in Leave on TextBoxes, so I had to find a solution that worked no matter what i did to it. I almost gave up, actually i had a problem report all filled out, when I thought, what if i set ActiveControl to Null and then to the Control it came from. It worked, but had som "Flicker" due to color change on Parent Panel depending on Active or Inactive.
The "Workaround" that works in all cases is:
Control Old = ActiveControl;
// ActiveControl.SuspendLayout();
// ActiveControl.FindForm().SuspendLayout();
ActiveControl = null;
ActiveControl = Old;
// ActiveControl.FindForm().ResumeLayout();
// ActiveControl.ResumeLayout();
That seems to fire Leave, Validating and so on Events, no matter number of Form Controls and TabStopped Controls. You MAY need to SuspendLayout on either ActiveControl, or Form. My Control (Parent Panel) changes color when Active/Inactive, if I do not Suspend Layout on Form, parent panel gets an unwanted "flicker" effect.
Looking at the solution, it is very obvious, now I've found it, but took me half a day to try different things that solved one or another problem, but not all.
I know this a VERY old thread, but one of very few articles I've found on the subject of Forcing Leave Event to be Fired.

create textbox one by one on enter keypress event

am using c# vs-2005
am on project to create textbox one by one on form1 and am success on button click event my code is below.
// declare location point of textbox on Global Area.
private point txtboxstartpoint=new point(10,10);
private void button_click (Object sender,EventArgs)
{
Textbox tbx = new TextBox();
tbx.Location= txtboxstartpoint;
tbx.size=new size (200,20);
this.panel1.control.add(tbx);
txtboxstartpoint.y += 25;
}
this works fine on button click event but problem is on keypress event like on enter
i wants to create textbox on enter one by one. and for that i assume that any method have
to create and call enter keypress event on newly created control like textbox to create
another new textbox below the previous one.
Kindly help me. suggest proper code for the same.
It's very hard to understand your question, but let's try some guessing:
You have a form, and if a user presses some specific key, you'd like to create a new TextBox and show it on your form regardless which control has currently the focus in your form.
If this statement is true, you can set Form.KeyPreview to true. And add an event handler to Form.KeyDown.
Due to the fact, that you set the preview to true you'll get every keyboard hit before it will be give further to the control that has currently the focus. So here you can check if the key that was pressed is the one you're listening for. And if yes, just call your TextBoxFactory and set the e.Handled to true to prevent that this key stroke will additionally reach the currently focused control.
I use the KeyDown event, to intercept the 'F1' key to provide my small help in a very small programm. Here is the code:
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
//Your Code here
}
}

Categories

Resources