Search code examples
c#winformswinapimousekeyhook

Binding key combinations (strictly) to a specific form


Could you please tell me how to use the "globalmousekeyhook" library (https://github.com/gmamaladze/globalmousekeyhook/blob/vNext/keycomb.md) to write keyboard shortcuts Not to the whole application, but to a specific form? To avoid checking the form for activity, every time (Form.ActiveForm == this). P.S. If you do not do these checks, the keyboard shortcuts, will be triggered simultaneously in all created forms.

private void Form1_Load(object sender, EventArgs e) {
   Action ex1 = () => { if (Form.ActiveForm == this) Dop.ChangeBackColor(this, Color.Black); };
   Action ex2 = () => { if (Form.ActiveForm == this) Dop.ChangeBackColor(this, Color.Green); };

   // Install listener App [Combinations]
   Hook.AppEvents().OnCombination(new Dictionary<Combination, Action> {
      { Combination.FromString("Control + S"), ex1 },
      { Combination.FromString("Control + D"), ex2 }
   });
}

Solution

  • Solution for AppEvents

    private IKeyboardMouseEvents m_ApplHook;
    private void FormName_Activated(object sender, EventArgs e) {
      m_ApplHook = Hook.AppEvents(); // Subscribe
    
        Action d = () => { Dop.ChangeBackColor(this, Color.Black); };
        Action s = () => { Dop.ChangeBackColor(this, Color.Red); };
    
        // Install listener App [Combinations]
        m_ApplHook.OnCombination(new Dictionary<Combination, Action> {
          { Combination.FromString("Control + S"), d },
          { Combination.FromString("Control + D"), s }
        });
    }
    
    private void FormName_Deactivate(object sender, EventArgs e) {
      m_ApplHook.Dispose(); // UnSubscribe
    }
    

    Solution for GlobalEvents (If you have only 1 form in your application)

    Activate GlobalEvents in FormName_Load

    private IKeyboardMouseEvents m_GlobalHook;
    private void FormName_Load(object sender, EventArgs e) {
       m_GlobalHook = Hook.GlobalEvents();
    
       // Install Global listener [Sequences]
       Sequence OpenApps = Sequence.FromString("Control + C, Control + C");
         Dictionary<Sequence, Action> assignments = new Dictionary<Sequence, Action> {
           { OpenApps, () => {
               this.Text = Clipboard.GetText();
             }},
           };
    
      // Replace Hook.GlobalEvents() on m_GlobalHook
      m_GlobalHook.OnSequence(assignments);
    }
    

    Deactivate GlobalEvents in FormName_Closed (Not obligatory: closing the main form will close the entire application

    private void FormName_FormClosed(object sender, FormClosedEventArgs e) {
      m_GlobalHook.Dispose();
    }
    

    Solution for GlobalEvents (If you have more than 1 form in your application)

    Hide the desired form using Hide(), open another one. According to the book (http://it-kniga.narod.ru/5-7502-0222-4/02020903.html), method Hide() is analogous to Visible = false;

    Create the FormName_VisibleChanged event. Write the code in all the necessary forms (example: FormMain, Form1, FormName...). This method allows you to activate GlobalEvents for each individual form instead of all running (hidden) forms.

    private IKeyboardMouseEvents m_GlobalHook;
    // Documentation: https://github.com/gmamaladze/globalmousekeyhook/blob/vNext/keycomb.md
    
    private void FormName_VisibleChanged(object sender, EventArgs e) {
      if (this.Visible) {
        m_GlobalHook = Hook.GlobalEvents(); // Subscribe
    
        Action ex = () => { this.Text += "Ctrl + C x2"; };
        Action ext = () => { this.Text += "Shift + C"; };
    
        // Install Global listener [Sequences]
        m_GlobalHook.OnSequence(new Dictionary<Sequence, Action> {
          { Sequence.FromString("Control + C, Control + C"), ex },
          { Sequence.FromString("Shift + C"), ext },
        });
    
      } else m_GlobalHook.Dispose(); // UnSubscribe
    }