Click here to Skip to main content
15,901,666 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
How can I activate functions or perform some actions or just clicking a button by pressing a single key associated with that specific action (just like photoshop tools)?

I'm not talking about pressing Ctrl / Shift / Alt + Key, I just want to assign a single key with an action, just like the photoshop tools works:

E = Eraser tool
M = Marquee selection tool
V = Move tool
...

How can I achieve this in C#?
Posted
Comments
CHill60 20-Feb-15 10:14am    
Need more detail. Are you referring to a program that you have written or a 3rd party program?
cass3000 20-Feb-15 11:14am    
I refer to a program I'm writing.
CHill60 20-Feb-15 11:24am    
Then OriginalGriff's solution is the one for you

If you are writing a WinForms app, then it's relatively easy: override ProcessCmdKey
C#
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
    Keys keyOnly = keyData & ~Keys.Modifiers;
    Keys modifiersOnly = Control.ModifierKeys & (Keys.Shift | Keys.Control | Keys.Alt);
    if (modifiersOnly == 0)
        {
        // Key alone
        switch (keyOnly)
            {
            case Keys.Enter:
                PlaySelected();
                return true;
            }
        }
 
Share this answer
 
Comments
BillWoodruff 21-Feb-15 2:38am    
+5 Keys keyOnly = keyData & ~Keys.Modifiers; ... mmm ... tasty !

I've been using (Control.ModifierKeys & keyData) == Keys.None ... now I'm not sure that's equivalent, will have to do some tests.
OriginalGriff 21-Feb-15 3:06am    
:laugh:
I grew up with assembler, so AND NOT(constant value) is second nature to me!
This is a coincidence, I'm working on an article to be published on CP on a "lightweight" custom hotkey utility (lightweight compared to using a GlobalHook in C#). The version in-progress has many more features than I'll show here including the ability to disable and restore any given macro (or delete it), to allow or block key-repeat when the same keys are held down, defining key macros for a single control, all controls of the same type, or all controls on a form, etc.

Here's a simple proof-of-concept version that makes the assumptions:

1. the programmer will want to override key behavior for specific controls: will want over-rides only in certain elements of the UI.

2. specific to your question: will use single-keys only (no modifiers pressed)

3. the code you want to execute when a key is pressed can be expressed with an Action that has no parameters and returns no value.

4. example:
C#
// maps Keys (KeyData) to Action
private Dictionary<keys,> dctKeysToAction;

// which Controls to handle macro keys
private List<control> KeyOverRideControls;

// scratch variable
private Action KeyAction;

// form-scope key-handling override
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (KeyOverRideControls.Contains(ActiveControl))
    {
        if (dctKeysToAction.TryGetValue(keyData, out KeyAction))
        {
            KeyAction();
            return true;
        }
    }
       
    return base.ProcessCmdKey(ref msg, keyData);
}

// how a mapping of Control~Key => Action is defined

private void Form1_Load(object sender, EventArgs e)
{
    KeyOverRideControls = new List<control>
    {
        // look for modified key-presses only for these Controls
        dateTimePicker1,
        userControl11
    };

    dctKeysToAction = new Dictionary<keys,>
    {
        {
            Keys.E, () =>
            {
                Console.WriteLine("E");
            }
        },
        Keys.B, () =>
        {
            if (ActiveControl == dateTimePicker1)
            {
                dateTimePicker1.Value = DateTime.Now;
            }
            else
            {
               MessageBox.Show("B in userControl1");  
            }    
        }
    };
}</control></control>
Discussion:

0. since we use the unique Keys value as the Key in the Dictionary that maps to the Action, I believe this is performant enough for this scenario.

1. Since the 'KeyData value (a Keys enum value) received as a parameter in the ProcessCmdKey override is unique for any/all keys held down, we do not need to check to see if control/alt/shift keys are down.

2. The Form here has a UserControl instance, 'userControl1, and a DateTimePicker, 'dateTimePicker1 sited on the Form at design-time: only those Controls will handle the modified key-evaluation behavior enforced by the ProcessCmdKey override.

3. Since the UserControl ... unlike a Panel, for example ... will "eat first" all keystrokes: if you have a TextBox inside the UserControl, and the 'b/B key is pressed here: that key will not be received by the UserControl ... unless you modified the code in ProcessCmdKey to allow it to "go through."

4. what is shown here just "scratches the surface" of what can be done.
 
Share this answer
 
Comments
cass3000 23-Feb-15 9:20am    
where can I find your final article?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900