I'm trying the get the inputted values from the user and save it on a char variable, but the problem is that nothing occurs, and I think the problem is with the Form Focus, this is the code, and when I run it no errors occurs, but also nothing happen. What I did wrong?
char keyPressed;
public FrmZigndSC()
{
InitializeComponent();
this.Focus();
}
private void FrmZigndSC_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
keyPressed = e.KeyChar;
LblResult.Text += Convert.ToString(keyPressed);
}
You can try with this code - Based on KeyPressEventHandler
public FrmZigndSC()
{
InitializeComponent();
this.Focus();
//Subscribe to event
this.KeyPress += new KeyPressEventHandler(FrmZigndSC_KeyPress);
}
private void FrmZigndSC_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
keyPressed = e.KeyChar;
LblResult.Text += Convert.ToString(keyPressed);
// Indicate the event is handled.
e.Handled = true;
}
If you want to recieve a key notification from the application'e mesage pipeline, relaying on focus of the element, in this case, make architecture fragile. You can not gurantee that from other forms in your app that one would be focused, or the form is nto covered by some control that absorbes that event. You can not forse to a form having a focus, cause it's completely bad UX design (not very sure even if this is possible to implement in 100% working way).
What you can do it, instead, is declare class derived from IMessageFilter:
public class MessageFilter : IMessageFilter
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
public bool PreFilterMessage(ref Message m)
{
// Intercept KEY down message
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
if ((m.Msg == WM_KEYDOWN)
{
//get key pressed
return true;
}
else
{
return false;
}
}
}
and after register it within your application:
MessageFilter filter = new MessageFilter(); //init somewhere
Application.AddMessageFilter(filter ); // add
.....
//on application end don't forget to remove it
Application.RemoveMessageFilter(filter );
I tried to reproduce it in an empty little Windows Forms project. This code worked just fine without the Shown event handler:
public partial class FrmZigndSC : Form
{
public FrmZigndSC()
{
InitializeComponent();
this.KeyPress += (s, e) => this.LblResult.Text += e.KeyChar.ToString();
// this might be a solution, but i did not need it
this.Shown += (s, e) => this.Activate();
}
}
You could try to use this.Activate() anyway and see if it helps. If you got other input controls such as text boxes on your form, try setting the form's KeyPreview property to true.
Using the FocusManager instead of this.Focus() should do the trick!
http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.aspx
I Think the problem is that when you have differenct controls on your Form that catch ketpressed. I had the same probmel with an DateTimePicker on my control.
Try to delete all of them and then try it, it will work. And from that point add the controls again to see which on is the problem.
The code you have given is working fine for me. Set the startup page as FrmZigndSC and try again.
Related
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.
How to catch keyboard events of the WinForm main form, where other controls are.
So I want to catch one event Ctrl + S and doesn't matter where focus is.
But without Pinvoke (hooks and such ...)
Only .NET managed internal power.
Try this code. Use the interface IMessageFilter you can filter any ctrl+key.
public partial class Form1 :
Form,
IMessageFilter
{
public Form1()
{
InitializeComponent();
Application.AddMessageFilter(this);
this.FormClosed += new FormClosedEventHandler(this.Form1_FormClosed);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Application.RemoveMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
//here you can specify which key you need to filter
if (m.Msg == 0x0100 && (Keys)m.WParam.ToInt32() == Keys.S &&
ModifierKeys == Keys.Control)
{
return true;
}
else
{
return false;
}
}
}
I tested this and worked for me.
the Form Class (System.Windows.Forms) has OnKeyDown, OnKeyPress, and OnKeyUp event methods that you can use to detect Ctrl + S
use the KeyEventArgs in those methods to determine which keys were pressed
EDIT
be sure to enable Form.KeyPreview = true; so the form will capture the events regardless of focus.
Handle the KeyDown on the form and all its controls.
private void OnFormLoad(object sender, EventArgs e)
{
this.KeyDown += OnKeyDown;
foreach (Control control in this.Controls)
{
control.KeyDown += OnKeyDown;
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.KeyValue == (int)Keys.S)
{
Console.WriteLine("ctrl + s");
}
}
}
You may add a MenuStrip and then create a menu strip item named save and give it a short cut Ctrl + S. Add a event handler for that. This will fire even if the focus is on other control on the form. If you don't like to see the MenuStrip; you can set visible = false too. I must admit this is ugly.
I know this has been asked hundred of times, but I haven't been able to find a solution that helps me. I'm using a barcode scanner and I want to be able to get the keys that are typed using just the keydown events. For some reason, I can't use both keydown and keypress events (my keypress events won't run).
I need to be able to get the characters, including hyphens, uppercase letters and dots and also need to detect the enter key.
These are my listeners:
form.KeyDown += new KeyEventHandler(Input_KeyDown);
form.KeyPress += new KeyPressEventHandler(Input_KeyPress);
And these are my methods:
private void TimedOut(object sender, EventArgs e)
{
_barcode = "";
}
private void Input_KeyDown(object sender, KeyEventArgs e)
{
_timer.Stop();
_timer.Start();
if (e.KeyData == Keys.Enter)
{
if (!_barcode.Equals(""))
{
this.BarcodeScanned(_barcode, new EventArgs());
}
}
else
{
}
}
private void Input_KeyPress(object sender, KeyPressEventArgs e)
{
_timer.Stop();
_timer.Start();
_barcode += e.KeyChar;
}
Your code above works...on a blank form. However there are several things that can interfere with the key events, especially when there are other controls on the page. Make sure that
The AcceptButton property isn't set on the form (this will trap the Enter key)
That there are no controls on the form with TabStop set to true (might not be viable but give it a go)
That the form has focus when you're typing (unlikely given the description but check anyway)
That focus is not otherwise on any control in the form when typing, e.g., a TextBox
That no other controls are trying to process the KeyPress or KeyDown events and that no other custom events are configured/set anywhere else in your code
One thing I notice is that you are registering the events like so;
form.KeyDown += new KeyEventHandler(Input_KeyDown);
This implies that you are instantiating this form from another place and trying to get it to send its key events to the calling code. Are you sure that the form instance is persisted/saved to a private class level variable or some such?
I am using a windows form and within the form i have a user control with two labels, one that has a message ENTER AMOUNT and the other where I am putting the values typed by the user (like when you go to an ATM) it starts showing the number .. it works fine if i dont have any other controls on the user control.. but the moment i add a button it does not work, it wont start showing the numbers as I use my numeric key pad.. but if i remove whatever button i added it works again... Here is my user control code.
public partial class OperationAmount : UserControl
{
public OperationAmount()
{
InitializeComponent();
}
private int _inputNumber = 0;
private void OperationAmount_Load(object sender, EventArgs e)
{
}
private void Form_KeyAmountPressed(object sender, KeyPressEventArgs e)
{
if (!Char.IsNumber(e.KeyChar))
{
return;
}
else if (lblOperationAmount.Text.Length > 9)
{
return;
}
else
{
_inputNumber = 10 * _inputNumber + Int32.Parse(e.KeyChar.ToString());
ReformatOutput();
}
}
private void ReformatOutput()
{
lblOperationAmount.Text = String.Format("{0:0.00}", (double)_inputNumber / 100.0);
}
}
Probably the new control steals the keypresses from your Form_KeyAmountPressed method because now it has the focus and receive the event KeyPress.
A simple workaround would be to add the method Form_KeyAmountPressed also at the KeyPress event of the button. Try also to set the TabStop property of the button to false. (not sure if this has any effect when the button is the only control that can get focus on your user control).
I use c# winforms visual studio 2010. I have a textbox that have a list as autocomplete data source. Everything is fine except I dont find the event when the autocomplete is clicked. I want on autocomplete row hit do and something else except only fill the textbox with the selected row value. Is it possible?
Thanks a lot
I ran a quick test this appears to work, don't mind me if this is quite hacky. I created a UserControl that inherits from TextBox. It monitors the KeyDown event, which fires before the TextChanged event, toggles a bit to true and has the TextChanged event review the bit and throw an event (AutoCompleteUsed) to alert monitoring classes that the auto-complete functionality was used.
public partial class MyTextBox : TextBox
{
public delegate void AutoCompleteDelegate();
public event AutoCompleteDelegate AutoCompleteUsed;
public MyTextBox()
{
InitializeComponent();
this.TextChanged += MyTextBox_TextChanged;
this.KeyDown += MyTextBox_KeyDown;
}
private bool keyPressed = false;
void MyTextBox_KeyDown(object sender, KeyEventArgs e)
{
keyPressed = true;
}
void MyTextBox_TextChanged(object sender, EventArgs e)
{
if (!keyPressed && AutoCompleteUsed != null)
{
AutoCompleteUsed();
}
keyPressed = false;
}
}
Edit 1: #Hans Passant gave me the answer in his comment, I just gave you a working(ish?) example.