2

In a C# Windows Form I would like transcode information: when user press CTRL+I, the app detect the key press combination, it takes the code in the clipboard and transcode it.

I find out this code:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        switch (msg.Msg)
        {
            case 0x100:
            case 0x104:
                switch (keyData)
                {
                    case Keys.Control | Keys.I:
                        MessageBox.Show("Ctrl + I pressed");
                        break;
                }
                break;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }

This works fine when windows form has focus.

I would like detect the combination when the app is minimized as tray icon.

SOLUTION:

keyboardhook.cs:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TrayIconForm
{
    public static class Constants
    {
    public const int NOMOD = 0x0000;
    public const int ALT = 0x0001;
    public const int CTRL = 0x0002;
    public const int SHIFT = 0x0004;
    public const int WIN = 0x0008;

    public const int WM_HOTKEY_MSG_ID = 0x0312;
    }
public class KeyHandler
{
    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private int modifier;
    private int key;
    private IntPtr hWnd;
    private int id;
    public KeyHandler(int modifier, Keys key, Form form)
    {
        this.modifier = modifier;
        this.key = (int)key;
        this.hWnd = form.Handle;
        id = this.GetHashCode();
    }
    public override int GetHashCode()
    {
        return modifier ^ key ^ hWnd.ToInt32();
    }
    public bool Register()
    {
        return RegisterHotKey(hWnd, id, modifier, key);
    }
    public bool Unregiser()
    {
        return UnregisterHotKey(hWnd, id);
    }
}
}

Information.cs (Form):

using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TrayIconForm
{
public partial class Information : Form
{
    private KeyHandler ghk;

    public Information()
    {
        InitializeComponent();

        ghk = new KeyHandler(Constants.CTRL, Keys.I, this);
        ghk.Register();

    }
    private void HandleHotkey()
    {
        string s = Get_Copy();

        notifyIcon1.BalloonTipText = s;
        notifyIcon1.BalloonTipTitle = "You have pressed CTRL+i";
        notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

        notifyIcon1.Visible = true;
        notifyIcon1.ShowBalloonTip(500);
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Constants.WM_HOTKEY_MSG_ID)
            HandleHotkey();
        base.WndProc(ref m);
    }

    private string Get_Copy()
    {
        string r;
        // Retrieves data from Clipboard
        IDataObject iData = Clipboard.GetDataObject();
        // Is Data Text?
        if (iData.GetDataPresent(DataFormats.Text))
            r = (String)iData.GetData(DataFormats.Text);
        else
            r = "nothing";
        return r;
    }
    private void Information_Resize(object sender, EventArgs e)
    {
        if (FormWindowState.Minimized == this.WindowState)
        {
            notifyIcon1.BalloonTipText =  "My application still working...";
            notifyIcon1.BalloonTipTitle = "My Sample Application";
            notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

            notifyIcon1.Visible = true;
            notifyIcon1.ShowBalloonTip(500);
            this.Hide();
        }
        else if (FormWindowState.Normal == this.WindowState)
        {
            notifyIcon1.Visible = false;
        }
    }
}
}
Francesco
  • 352
  • 1
  • 8
  • 19
  • check this you just need to convert it to c# https://stackoverflow.com/questions/2450373/set-global-hotkeys-using-c-sharp – Jack Gajanan Mar 31 '18 at 07:39
  • A my colleague suggest me a solution explained in this [article](http://www.dreamincode.net/forums/topic/180436-global-hotkeys/) – Francesco Mar 31 '18 at 11:28

2 Answers2

0

This works just instantiate it, subscibe to the event and you are done. It s not my script. A while ago I searched long for this but I found it and it works great. There were you subscribed to the event you can look if the pressed key (stored in the event args) is your key and when it is you can look with Keyboard.iskeydown(key.lctrl) if control is pressed to and then you can do what the combination should do.

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows.Input;

namespace <yournamespace>
{
    public class LowLevelKeyboardListener
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public event EventHandler<KeyPressedArgs> OnKeyPressed;

        private LowLevelKeyboardProc _proc;
        private IntPtr _hookID = IntPtr.Zero;

        public LowLevelKeyboardListener()
        {
            _proc = HookCallback;
        }

        public void HookKeyboard()
        {
            _hookID = SetHook(_proc);
        }

        public void UnHookKeyboard()
        {
            UnhookWindowsHookEx(_hookID);
        }

        private IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);

                if (OnKeyPressed != null) { OnKeyPressed(this, new KeyPressedArgs(KeyInterop.KeyFromVirtualKey(vkCode))); }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }

    public class KeyPressedArgs : EventArgs
    {
        public Key KeyPressed { get; private set; }

        public KeyPressedArgs(Key key)
        {
            KeyPressed = key;
        }
    }
}
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
juliushuck
  • 1,398
  • 1
  • 11
  • 25
0
[DllImport("user32.dll")]
    public static extern int GetAsyncKeyState(Keys vKeys);

then

var ctrl = GetAsyncKeyState(Keys.ControlKey) & 0x8000;
var key = GetAsyncKeyState(Keys.F10) & 0x8000; //F10 for example
if(ctrl != 0 && key != 0)
{
    //do sth
}
vgf604999
  • 1
  • 1