Trap keystrokes/keyboard events in controls

M

michelQA

Hi,

I need to catch keyboard input in several net control.

With KeyUp, KeyDown and KeyPress managing combined keys (like Ctrl-,C
Ctrl-Alt-Ins or Shift-End) seems to be a real pain since keys like
Shift+End are not "Real" keys for keypress.

When using keyUp/KeyDown I dont understand why e.KeyCode, e.KeyValue
return letters in uppercase and I dont found any way to represents
keys in a more readable way like "<Ctrl+C>" instead of "ControlKey"
and "C" Is there any kind of converter for e.KeyCode, e.KeyValue and
e.KeyChar

I was surprised to see that there is no examples of using theses
events for properly catch any keys and key combinaison and represents
it in a fancy way like a native HotKey control.

After experiencing diffrent way to track keyboard input i'm still
trying to figure out what is the proper way to do this. I my latest
try, I use keyup/keydown to catch "Modifier" and use keypress to
display the result but it still not working properly for key Like
(Shift-End,Arrows, etc..)

Is anybody can guide me to the proper "Clean" way to achieve this
since i'm restarting everyting from scratch and currently investigate
native way to do the same thing (maybe an example could be found),
subclassing WndProc and learn about overiding ProcessCmdKey. Any
advises or even better, an example (managed or not) will be really
appreciated.

Thanks,
Michel
 
F

Family Tree Mike

michelQA said:
Hi,

I need to catch keyboard input in several net control.

With KeyUp, KeyDown and KeyPress managing combined keys (like Ctrl-,C
Ctrl-Alt-Ins or Shift-End) seems to be a real pain since keys like
Shift+End are not "Real" keys for keypress.

When using keyUp/KeyDown I dont understand why e.KeyCode, e.KeyValue
return letters in uppercase and I dont found any way to represents
keys in a more readable way like "<Ctrl+C>" instead of "ControlKey"
and "C" Is there any kind of converter for e.KeyCode, e.KeyValue and
e.KeyChar

I was surprised to see that there is no examples of using theses
events for properly catch any keys and key combinaison and represents
it in a fancy way like a native HotKey control.

After experiencing diffrent way to track keyboard input i'm still
trying to figure out what is the proper way to do this. I my latest
try, I use keyup/keydown to catch "Modifier" and use keypress to
display the result but it still not working properly for key Like
(Shift-End,Arrows, etc..)

Is anybody can guide me to the proper "Clean" way to achieve this
since i'm restarting everyting from scratch and currently investigate
native way to do the same thing (maybe an example could be found),
subclassing WndProc and learn about overiding ProcessCmdKey. Any
advises or even better, an example (managed or not) will be really
appreciated.

Thanks,
Michel


I don't normally do the key handling in the individual controls unless the
actions are different for the key combo at the control level. I would put
the code in the Form, KeyDown handler. Code such as the following could be
used to get a better formatted output of what the user is keying:

string[] mods = e.Modifiers.ToString().Split(new char[] {
',' });
StringBuilder sb = new StringBuilder();

foreach (string s in mods)
{
string s1 = string.Format("<{0}-{1}>", s, e.KeyCode);
sb.AppendLine(s1);
}

But, if you are really interested in intercepting/handling as an example,
Alt-C, then you should not need to build the string. Just check the
Modifiers for Alt, and the KeyCode for C. Make sure you set the handled
flag on the KeyEventArgs.

Hope this helps.
 
M

michelQA

Hi,

I finally figure it out with your help!

Modifier are flagged in the KeyDown event

In KeyPress if no modifier found in keydown then just print the
character else print the "control/function" key flagged by the KeyDown

In KeyUp, I have to check if the KeyPress was called since the
KeyDown. If no KeyPress found then print the character (like "Home",
Shift-End, etc..)

The KeyConverter can ConvertToString the KeyCode and get Better result
than KeyCode.ToString(). (Ex: PgUp instead of Prior) Thanks for
pointing me to this even if I dont understand the little small
difference between conversion and PgUp/PdDn is the only difference I
saw ;o)

The rest is just try and modify to get the expected results for all my
specific needs

There still two questions :

1- Why I can't catch KeyDown,KeyUp and KeyPress if the sender is the
form?? Mike's suggestion make sense to catch key from the form
instead of from each control. Is theses events are suppose the work
the same way for a Form ??

2- I want to learn more about "methods for Control sub-classes to
further manipulate input ("Preview...",
"Process...", etc.)" Peter I dont even know what you mean by
"Preview and Process" releated to Control subclassing? Could you tell
me more detail about this suggestion or a link to understand what you
mean? (Any subclassing things can be really usefull for my needs)

Thanks again

Michel
 
F

Family Tree Mike

michelQA said:
Hi,
There still two questions :

1- Why I can't catch KeyDown,KeyUp and KeyPress if the sender is the
form?? Mike's suggestion make sense to catch key from the form
instead of from each control. Is theses events are suppose the work
the same way for a Form ??

Michel


Yes, I had this as the form KeyDown handler. Make sure that for the form,
you set the property KeyPreview to true.
 
M

michelQA

I'll repeat my previous advice, that splitting key input handling between
the two events is probably not a good idea.
To do this I will need to declare and watch keys like "Up, Down, End,
Home" in the KeyDown

I can't see any problem with the Caps lock, shift key in my "ugly"
solution. The only problem I can see is when keys is not managed by
KeyPress the display is not totally correctly formated in some rare
case like Ctrl-{ or Ctrl-+

ex: Ctrl-{ is displayed as <Ctrl+OemOpenBrackets> instead of <Ctrl+{>
but I dont really care for <Ctrl+OemPlus> instead of <Ctrl++>

Since I take a lot of your precious time for trying to help me take a
minute to try my code so you will understand exactly what I'm trying
to do and I will be able to understand what you are trying to tell
me ;o)

Just to let you know and give a little background I need to support
non us keyboards. I need to capture Keyboard inputs in a more
"readable" ay for a kind of script in a macro tool. This means
replaying keyboard events so my fancy display will need to be
reconverted to real keys at then end.

Here is my testing application for Key capture. You comment suggest
rewriting again all key management so I need to know what is wrong
with my approach.

Here is the code :
Just put a Label named "label1" in a form and paste the following code
for the 3 form key form events. .......with the KeyPreview
enabled! ;o)



ArrayList KeyCodesModifier=new ArrayList();
string Code="";
private void Form1_KeyDown(object sender,
System.Windows.Forms.KeyEventArgs e)
{
KeyPressEvent=false;
KeyCodesModifier.Clear();
string[] mods = e.Modifiers.ToString().Split(new char[] {','});
foreach (string s in mods)
{
if (s!="None")
KeyCodesModifier.Add(s.Trim());
}
KeysConverter kc = new KeysConverter();
Code=kc.ConvertToString(e.KeyCode);
}
//-----------------------------------------
bool KeyPressEvent=false;
private void Form1_KeyPress(object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
KeyPressEvent=true;
string KeyStr="";
if (KeyCodesModifier.Count>0)
{
//KeyStr=Code;
int ModCnt=0;
foreach (string KeyMod in KeyCodesModifier)
{
if (KeyCodesModifier.Count==1&& KeyMod=="Shift") //Shift without
modifier is ignored
KeyStr=e.KeyChar.ToString();
else
{
if (ModCnt==0)
KeyStr="<";
KeyStr+=KeyMod+"+";
if (ModCnt+1==KeyCodesModifier.Count)
{
KeyStr+=Code.ToString();
KeyStr+=">";
}
}
ModCnt++;
}
}
else
KeyStr=e.KeyChar.ToString();
label1.Text=KeyStr;
}
//-----------------------------------------

private void Form1_KeyUp(object sender,
System.Windows.Forms.KeyEventArgs e)
{
string KeyStr;
KeysConverter kc = new KeysConverter();
if (!KeyPressEvent)
{
if (KeyCodesModifier.Count>0)
{
int ModCnt=1;
KeyStr="<";
foreach (string KeyMod in KeyCodesModifier)
{
KeyStr+=KeyMod;
if (ModCnt==KeyCodesModifier.Count)
{
if (Code!="ShiftKey"&&Code!="ControlKey")
KeyStr+="+"+Code;
KeyStr+=">";
}
else
KeyStr+="+";
ModCnt++;
}
}
else
KeyStr="<"+Code.ToString()+">";
label1.Text=KeyStr;
}
}



Thanks
 
M

michelQA

If you are trying to capture key input to be sent back to an application
later, you definitely should be using KeyDown and not KeyPress. Composed
characters are for things involving text, not simulating input to an
application.
My Idea was :
In recording : Record formated keys and text like : TypeKeys
("Blablabla<Shift-Home><Control+C><Control+V><Control+V>");
in playback : Read the string and type the characters corresponding to
the right modifier(s) and key KeyChar based on it's string
representation as displayed in KeyPress

Your comment suggest that finding the real key code in my playback
process will be impossible. Sorry but as you can notice it's my first
experience with keyboard things. Even now I dont clearly understand
what are the potential problems of these composed characters and what
you mean by just minimal character processing.

The keys need to be presented in the "Script" in way to be easy to
read, use and understand so it's not trying to "Record" the exact same
key code sequence without feedback to the user. If I understand it
right you suggest creating my TypeKeys command this way instead?? :
TypesKeys
("<ShiftDown>B<ShiftUp>lablabla<ShiftDown><HomeDown><HomeUp><ShiftUp><CtrlDown>C<CtrlUp><CtrlDown>V<CtrlUp><CtrlDown>V<CtrlUp>");

What would be the "ISO Pete" representation of keys typed to an
application for my TypeKeys fonction?

Will work for the next hours on a KeyUp - KeyDown only solution to
understand the benifits and what can be wrong....

Thanks!
 
M

michelQA

I'm currently trying figuring out the playback part. The goal will be
to replay characters. As suggested doing that with the plain exact Up/
Down characters sequence make sense. After that we will see if
formatted mixed combined characters sequences can be easily done
without falling into ugly heavy code.
All that said, my goal is not to force you into doing something you don't
want to do. I'm just trying to point out the potential pitfalls, so that
if you do decide to go the mixed route, you at least do so with your eyes
open. :)
Dont worry! this is exactly what I want. I have a job to do but
i'm here to learn and get more experience. You and mike point me to
different interresting things.

Michel
 
M

michelQA

About the playback part :

- All known virtual keys (thoses one with frendly name in my
TypesKeys) will be sent by using keybd_event since the match between
my "friendly key name" and VK code is easy to do.
- All other unknow characters (character processed by KeyPress,
character that can be displayed on screen with or without combined
code) will be simply sent by using SendKeys() fonction. This asume
sendKey is correctly working for any characters of any language.

At least I know now that keybd_event can be easily use to replay
characters so the solution is already found!

Is anybody see a problem for international keyboard support or
anything else if I plan to use keybd_event (for know VK) and SendKeys
(for any other character or unknow characters)?

Thanks

Michel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top