I need to capture keystokes from a wedge device and prevent any controls or the form from receiving them. I also need to be able to know the value (char). I have tried overriding the ProcessCmdKey(Keys) and ProcessDialogChar(char) events. In the ProcessCmd event I can suppress the keystroke if it's one I want, but I the character isn't a parameter of the event. In the ProcessDialogChar event the character is there, but I cannot prevent the form or control with the focus from receiving the key. Suggestions?
You'll want to add this during Form load:
Application.AddMessageFilter(this);
Add this constant:
private const int WM_KEYDOWN = 0x100;
And this method:
public bool PreFilterMessage(ref Message m)
{
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
bool retVal = false;
if (m.Msg == WM_KEYDOWN)
{
// Handle the keypress
retVal = true;
}
return retVal;
}
By returning true, your form and control(s) will never see the key press.
It was not how I wanted to do it, but because I needed to fix this and move on I put a hidden textbox on the form and as soon as I see the character that signals the possible start of the string of data I want to capture I set focus to that text box and respond to the TextChanged event. If I haven't seen the ending character before I timer expires I clear the textbox and start again. Kludge, but it works and got me to the next task.
Related
I have a .net application which includes search screen which has a panel with has three text boxes, each with a varying character lengths.
What I'd like to do is capture when the paste command when invoked from the first box and paste my clipboard into the three boxes.
This functionality is similar to many modern applications accepting input for serial keys and phone numbers.
As far as I can find there is no other sensible way of doing this than to capture the WM_PASTE event.
Derive a class from TexBox and implement this method:
using System.Windows.Forms;
using System.ComponentModel;
class TextBoxWithOnPaste : TextBox
{
public delegate void PastedEventHandler();
[Category("Action")]
[Description("Fires when text from the clipboard is pasted.")]
public event PastedEventHandler OnPaste;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x302 && OnPaste != null) // process WM_PASTE only if the event has been subscribed to
{
OnPaste();
}
else
{
base.WndProc(ref m);
}
}
}
Then put three of those custom controls on your form, and assign the OnPaste event on all three textboxes to the same method, in this case I called it textPasted():
private void textPasted()
{
String input = Clipboard.GetText();
int l1 = textBoxWithOnPaste1.MaxLength;
int l2 = textBoxWithOnPaste2.MaxLength;
int l3 = textBoxWithOnPaste3.MaxLength;
try
{
textBoxWithOnPaste1.Text = input.Substring(0, l1);
textBoxWithOnPaste2.Text = input.Substring(l1, l2);
textBoxWithOnPaste3.Text = input.Substring(l2, l3);
}
catch (Exception)
{ }
}
Since you implied "like a serial", I guessed you want the pasted string to be split among the textboxes. The code above is not perfect for that (try pasting a single space into the third text box after entering data manually in all three, so it would be nice if you knew in which textbox the text was pasted, for example by altering the event's parameters and that way sending the sender with it), but it basically works and I guess you can figure out the rest (you could use the Tag property to identify the textbox).
Capture the paste event:
protected override void WndProc(ref Message m) {
// Did paste occur?
if (m.Msg == 0x302) {
//Paste occurred, add your logic here
}
base.WndProc(ref m);
}
Then, access the Clipboard object to get the desired text.
you can get the captured text
String txt = Clipboard.GetText();
and place it in the "Text" property of the other textbox
You can bind key down event, and when you get Ctrl + V or Ctrl + v, you update the value of the three textbox with value in the clipboad. You can do this on TextChanged event off first text box.
You could increase the character limit of the boxes and register for TextChanged and if the pasted (or typed) text is longer jump/cut to the next TextBox.
I need to close the application (C#) when user doesn't use it - let's say that when there is no Click event on any form of the program (there are about 100 forms). Is there any way to do that without handling Click even on each form of the app. (I have the thread running each minute, where it could be checked)?
Thanks in advance!
You can hook into the application message loop using the Application.AddMessageFilter function. Write a message filter that inspects all mouse click messages and/or keyboard messages, or anything you're interested in.
For instance:
public class DetectActivityMessageFilter : IMessageFilter
{
private const int WM_LBUTTONDOWN = 0x0201;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN)
{
// The left mouse button was pressed
}
return false;
}
}
I'm making a custom Terminal in a C# winform. When the user presses a key in the TextBox that I'm using I have to make sure that it's a valid key. I need to prevent them from being able to delete stuff and do whatever they want. I managed to handle the backspace and delete and others via the KeyPress and KeyDown events. I had a problem with the user pressing shift + delete. It deletes stuff just like backspace. I don't know what the integer equivalent of it is. I made a C++ program to detect it, it was simple:
char c = _getch();
cout << (int)c << endl;
I got a -32. It didn't work in C#.
After so many tries to encircle its value, I found that it was 0.
It worked, at least for yesterday, but now it doesn't. I'm also able to delete stuff with the shift+delete.
Here's my key validation method:
private bool IsInvalidKey(char key)
{
bool condition1 = !IsAsciiKey(key) && !IsNavigatingKey(key); // by navigation I mean: left, right, end and home keys.
bool condition2 = (GetCaretPosition() == CaretPosition.OutsideCommandLine && !IsNavigatingKey(key));
bool condition3 = ((key == (char)Keys.Back) && GetCaretPosition() == CaretPosition.BeginningOfCommandLine);
return (condition1 || condition2 || condition3);
}
private bool IsAsciiKey(char key)
{
return ((int)key > 0 && (int)key <= 127); // char(0) should be shift+delete
}
How can I detect this key and where (in which event, KeyPress or KeyDown?)
I'm using a normal TextBox control, not a RichTextBox.
You could try something like this in the KeyDown event.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift && e.KeyCode == Keys.Delete) e.Handled = true;
}
Rather than trying to look at each individual key through the use of the KeyDown event, what you really need to do is do all of your validation in the TextChanged event, and you need to validate the entire entry (not just the last character) every time anything changes. This is the only way to support everything that the user could possibly do. As an example, the user could use the mouse to cut or paste text in the textbox, and that doesn't trigger any key press events at all.
If you want, you can handle the key press event as well so that you can prevent invalid characters/key from changing the text in the first place (and causing a full validation) but that's basically like performing client side validation of a field on a webpage; it's nice to do, but since you can get around it you can't only use it.
I have a .net application which includes search screen which has a panel with has three text boxes, each with a varying character lengths.
What I'd like to do is capture when the paste command when invoked from the first box and paste my clipboard into the three boxes.
This functionality is similar to many modern applications accepting input for serial keys and phone numbers.
As far as I can find there is no other sensible way of doing this than to capture the WM_PASTE event.
Derive a class from TexBox and implement this method:
using System.Windows.Forms;
using System.ComponentModel;
class TextBoxWithOnPaste : TextBox
{
public delegate void PastedEventHandler();
[Category("Action")]
[Description("Fires when text from the clipboard is pasted.")]
public event PastedEventHandler OnPaste;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x302 && OnPaste != null) // process WM_PASTE only if the event has been subscribed to
{
OnPaste();
}
else
{
base.WndProc(ref m);
}
}
}
Then put three of those custom controls on your form, and assign the OnPaste event on all three textboxes to the same method, in this case I called it textPasted():
private void textPasted()
{
String input = Clipboard.GetText();
int l1 = textBoxWithOnPaste1.MaxLength;
int l2 = textBoxWithOnPaste2.MaxLength;
int l3 = textBoxWithOnPaste3.MaxLength;
try
{
textBoxWithOnPaste1.Text = input.Substring(0, l1);
textBoxWithOnPaste2.Text = input.Substring(l1, l2);
textBoxWithOnPaste3.Text = input.Substring(l2, l3);
}
catch (Exception)
{ }
}
Since you implied "like a serial", I guessed you want the pasted string to be split among the textboxes. The code above is not perfect for that (try pasting a single space into the third text box after entering data manually in all three, so it would be nice if you knew in which textbox the text was pasted, for example by altering the event's parameters and that way sending the sender with it), but it basically works and I guess you can figure out the rest (you could use the Tag property to identify the textbox).
Capture the paste event:
protected override void WndProc(ref Message m) {
// Did paste occur?
if (m.Msg == 0x302) {
//Paste occurred, add your logic here
}
base.WndProc(ref m);
}
Then, access the Clipboard object to get the desired text.
you can get the captured text
String txt = Clipboard.GetText();
and place it in the "Text" property of the other textbox
You can bind key down event, and when you get Ctrl + V or Ctrl + v, you update the value of the three textbox with value in the clipboad. You can do this on TextChanged event off first text box.
You could increase the character limit of the boxes and register for TextChanged and if the pasted (or typed) text is longer jump/cut to the next TextBox.
I'm currently working on a simple game that is drawn on a form by overriding the OnPaint method. The game requires Keyboard input and was working perfectly until I decided to enhance the GUI and add a few Buttons to the form.
The moment I added these Buttons, the form stopped receiving any Keyboard input, no matter how hard I tried the focus was always on the buttons. This behavior can be replicated by placing any Focus-able Control on the form. (ie. TextBox)
I don't need ANY Kayboard interaction with these buttons, I want the user to interact with them with the mouse only.
I've tried the following techniques to try and get around this problem - none of these worked:
1) Normal KeyDown and KeyUp events of the form. (This is the way
I was capturing Keyboard input before placing the buttons.)
2) Overriding the Form's OnKeyDown and OnKeyUp events.
3) Overriding ProcessCmdKey - Works, but cannot differentiate
between KeyUp and KeyDown events, so it is inadequate for me.
I also tried create a MessageFilter for the application, but I couldn't force it to capture only the Keyboard keys that I needed.
I've been looking into this for many hours already and can't find a suitable solution.
Help would be greatly appreciated.
Here is a sample form with a IMessageFilter for the up and down arrow keys, hope this helps:
public partial class MainForm : Form
{
private class MessageFilter : IMessageFilter
{
public MainForm Main { get; set; }
public bool PreFilterMessage(ref Message msg)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (msg.Msg == WM_KEYDOWN)
{
var keyData = (Keys)msg.WParam;
if (keyData == Keys.Down || keyData == Keys.Up)
{
return true; // Process keys before return
}
}
else if (msg.Msg == WM_KEYUP)
{
var keyData = (Keys)msg.WParam;
if (keyData == Keys.Down || keyData == Keys.Up)
{
return true; // Process keys before return
}
}
return false;
}
}
public MainForm()
{
this.InitializeComponent();
Application.AddMessageFilter(new MessageFilter { Main = this });
}
}
For a list of possible Windows messages check:
List Of Windows Messages
Set the KeyPreview property of the form to True, and then set event.Handled = True when you handle KeyDown/KeyUp. This will ensure that the form gets a chance to handle events before its children. Because you set the handled property to true, the childen won't see the keyboard events.
More info here: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx