Forwarding keystrokes from panel to Rhino

Hi all,
we have a small annoyance in our panel (RhinoCommon). When the focus is on it the keystrokes are (obviously) sent to the form we created. We capture these and we would like to forward them to the Rhino UI so that all the user shortcuts works just fine.

I know that RhinoApp provides facility for sending keystrokes (RhinoApp.SendKeystrokes) but this is not supporting all the modifiers and F keys. Has somebody already solved this? I would like to avoid using SendKeys as it has weird behaviours if you have multiple windows open.

Thanks a lot!


I did similar things, just not for Rhino. I’m a big fan of low level approaches, although this has other drawbacks. In Windows, you can always p/invoke user32.dll (winapi) functionality and listen to your keyboard. There must be an equivalent for Mac as well.
So what you do is, you build an lowlevel keylogger and only listen if your Rhino-Instance has focus.
There are tons of examples on Stack overflow for both tasks, and there is a nice website called
Unfortunate I don’t have access to the code I’ve written. So you have to find it for yourself :slight_smile:

here is an example of a low level send keys. you can extend ScanKeys enumeration, based on your Keyboard:

 class Keyboard

        // Fields
        private const uint INPUT_KEYBOARD = 1;
        private const int  KEY_EXTENDED = 0x0001;
        private const uint KEY_UP = 0x0002;
        private const uint KEY_SCANCODE = 0x0008;

        // Enum
        public enum ScanKeys : int
            Zirk = 1, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
            Num0, Szet, Apos, Back, Tab, Q, W, E, R, T, Z, U, I, O, P, Ue, Plus, Ent, Ctrl, A,
            S, D, F, G, H, J, K, L, Oe, Ae, Comp, Shift, Eqal, Y, X, C, V, B, N, M,
            Comma, Pnt, Minus, ShiftR, Print, Alt, Space, Caps

        // Native
        internal static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KeyboardInput[] input, int structSize);

        // Methods
        public static void SendKey(ScanKeys key)
        public static void PressKey(int scanCode)
            SendKey(scanCode, true);

        public static void ReleaseKey(int scanCode)
            SendKey(scanCode, false);

        public static void SendString(string s)
            foreach (char c in s)
                switch (c)
                    case 'a':
                        SendKey(ScanKeys.A); break;
                    case 'b':
                        SendKey(ScanKeys.B); break;
                    case 'c':
                        SendKey(ScanKeys.C); break;
                    case 'd':
                        SendKey(ScanKeys.D); break;
                    case 'e':
                        SendKey(ScanKeys.E); break;
                    case 'f':
                        SendKey(ScanKeys.F); break;
                    case 'g':
                        SendKey(ScanKeys.G); break;
                    case 'h':
                        SendKey(ScanKeys.H); break;
                    case 'i':
                        SendKey(ScanKeys.I); break;
                    case 'j':
                        SendKey(ScanKeys.J); break;
                    case 'k':
                        SendKey(ScanKeys.K); break;
                    case 'l':
                        SendKey(ScanKeys.L); break;
                    case 'm':
                        SendKey(ScanKeys.M); break;
                    case 'n':
                        SendKey(ScanKeys.N); break;
                    case 'o':
                        SendKey(ScanKeys.O); break;
                    case 'p':
                        SendKey(ScanKeys.P); break;
                    case 'q':
                        SendKey(ScanKeys.Q); break;
                    case 'r':
                        SendKey(ScanKeys.R); break;
                    case 's':
                        SendKey(ScanKeys.S); break;
                    case 't':
                        SendKey(ScanKeys.T); break;
                    case 'u':
                        SendKey(ScanKeys.U); break;
                    case 'v':
                        SendKey(ScanKeys.V); break;
                    case 'w':
                        SendKey(ScanKeys.W); break;
                    case 'x':
                        SendKey(ScanKeys.X); break;
                    case 'y':
                        SendKey(ScanKeys.Y); break;
                    case 'z':
                        SendKey(ScanKeys.Z); break;
                    case '0':
                        SendKey(ScanKeys.Num0); break;
                    case '1':
                        SendKey(ScanKeys.Num1); break;
                    case '2':
                        SendKey(ScanKeys.Num2); break;
                    case '3':
                        SendKey(ScanKeys.Num3); break;
                    case '4':
                        SendKey(ScanKeys.Num4); break;
                    case '5':
                        SendKey(ScanKeys.Num5); break;
                    case '6':
                        SendKey(ScanKeys.Num6); break;
                    case '7':
                        SendKey(ScanKeys.Num7); break;
                    case '8':
                        SendKey(ScanKeys.Num8); break;
                    case '9':
                        SendKey(ScanKeys.Num9); break;
                    case ' ':
                        SendKey(ScanKeys.Space); break;


            private static void SendKey(int scanCode, bool press)
            KeyboardInput[] input = new KeyboardInput[1];
            input[0] = new KeyboardInput();
            input[0].type = INPUT_KEYBOARD;
            input[0].flags = KEY_SCANCODE;

            if ((scanCode & 0xFF00) == 0xE000)
                input[0].flags |= KEY_EXTENDED;

            if (press)
                input[0].scanCode = (ushort)(scanCode & 0xFF);
                input[0].scanCode = (ushort)scanCode;
                input[0].flags |= KEY_UP;

            uint result = SendInput(1, input, Marshal.SizeOf(input[0]));

            if (result != 1)
                throw new Exception("Could not send key: " + scanCode);


That was something I was thinking about too. Thanks a lot for the help!