Ejemplo n.º 1
0
        // Uses User32 SendInput to send keystrokes
        private static void SendInput(byte[] oldKeyboardState, Queue previousEvents)
        {
            // Should be a No-Opt most of the time
            AddCancelModifiersForPreviousEvents(previousEvents);

            // SKEvents are sent as sent as 1 or 2 inputs
            // currentInput[0] represents the SKEvent
            // currentInput[1] is a KeyUp to prevent all identical WM_CHARs to be sent as one message
            NativeMethods.INPUT[] currentInput = new NativeMethods.INPUT[2];

            // all events are Keyboard events
            currentInput[0].type = NativeMethods.INPUT_KEYBOARD;
            currentInput[1].type = NativeMethods.INPUT_KEYBOARD;

            // set KeyUp values for currentInput[1]
            currentInput[1].inputUnion.ki.wVk     = (short)0;
            currentInput[1].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_UNICODE | NativeMethods.KEYEVENTF_KEYUP;

            // initialize unused members
            currentInput[0].inputUnion.ki.dwExtraInfo = IntPtr.Zero;
            currentInput[0].inputUnion.ki.time        = 0;
            currentInput[1].inputUnion.ki.dwExtraInfo = IntPtr.Zero;
            currentInput[1].inputUnion.ki.time        = 0;

            // send each of our SKEvents using SendInput
            int INPUTSize = Marshal.SizeOf <NativeMethods.INPUT>();

            // need these outside the lock below
            uint eventsSent = 0;
            int  eventsTotal;

            // A lock here will allow multiple threads to SendInput at the same time.
            // This mimics the JournalHook method of using the message loop to mitigate
            // threading issues.  There is still a theoretical thread issue with adding
            // to the events Queue (both JournalHook and SendInput), but we do not want
            // to alter the timings of the existing shipped behavior.  I did not run into
            // problems with 2 threads on a multiproc machine
            lock (events.SyncRoot)
            {
                // block keyboard and mouse input events from reaching applications.
                bool blockInputSuccess = UnsafeNativeMethods.BlockInput(true);

                try
                {
                    eventsTotal = events.Count;
                    ClearGlobalKeys();

                    for (int i = 0; i < eventsTotal; i++)
                    {
                        SKEvent skEvent = (SKEvent)events.Dequeue();

                        currentInput[0].inputUnion.ki.dwFlags = 0;

                        if (skEvent.wm == Interop.WindowMessages.WM_CHAR)
                        {
                            // for WM_CHAR, send a KEYEVENTF_UNICODE instead of a Keyboard event
                            // to support extended ascii characters with no keyboard equivalent.
                            // send currentInput[1] in this case
                            currentInput[0].inputUnion.ki.wVk     = (short)0;
                            currentInput[0].inputUnion.ki.wScan   = (short)skEvent.paramL;
                            currentInput[0].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_UNICODE;
                            currentInput[1].inputUnion.ki.wScan   = (short)skEvent.paramL;

                            // call SendInput, increment the eventsSent but subtract 1 for the extra one sent
                            eventsSent += UnsafeNativeMethods.SendInput(2, currentInput, INPUTSize) - 1;
                        }
                        else
                        {
                            // just need to send currentInput[0] for skEvent
                            currentInput[0].inputUnion.ki.wScan = 0;

                            // add KeyUp flag if we have a KeyUp
                            if (skEvent.wm == Interop.WindowMessages.WM_KEYUP || skEvent.wm == Interop.WindowMessages.WM_SYSKEYUP)
                            {
                                currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_KEYUP;
                            }

                            // Sets KEYEVENTF_EXTENDEDKEY flag if necessary
                            if (IsExtendedKey(skEvent))
                            {
                                currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_EXTENDEDKEY;
                            }

                            currentInput[0].inputUnion.ki.wVk = (short)skEvent.paramL;

                            // send only currentInput[0]
                            eventsSent += UnsafeNativeMethods.SendInput(1, currentInput, INPUTSize);

                            CheckGlobalKeys(skEvent);
                        }

                        // We need this slight delay here for Alt-Tab to work on Vista when the Aero theme
                        // is running.  Although this does not look good, a delay
                        // here actually more closely resembles the old JournalHook that processes each
                        // event individually in the hook callback.
                        System.Threading.Thread.Sleep(1);
                    }

                    // reset the keyboard back to what it was before inputs were sent, SendInupt modifies
                    // the global lights on the keyboard (caps, scroll..) so we need to call it again to
                    // undo those changes
                    ResetKeyboardUsingSendInput(INPUTSize);
                }
                finally
                {
                    SetKeyboardState(oldKeyboardState);

                    // unblock input if it was previously blocked
                    if (blockInputSuccess)
                    {
                        UnsafeNativeMethods.BlockInput(false);
                    }
                }
            }

            // check to see if we sent the number of events we're supposed to
            if (eventsSent != eventsTotal)
            {
                // calls Marshal.GetLastWin32Error and sets it in the exception
                throw new Win32Exception();
            }
        }
Ejemplo n.º 2
0
        private static void SendInput(byte[] oldKeyboardState, Queue previousEvents)
        {
            int count;

            AddCancelModifiersForPreviousEvents(previousEvents);
            System.Windows.Forms.NativeMethods.INPUT[] pInputs = new System.Windows.Forms.NativeMethods.INPUT[2];
            pInputs[0].type = 1;
            pInputs[1].type = 1;
            pInputs[1].inputUnion.ki.wVk         = 0;
            pInputs[1].inputUnion.ki.dwFlags     = 6;
            pInputs[0].inputUnion.ki.dwExtraInfo = IntPtr.Zero;
            pInputs[0].inputUnion.ki.time        = 0;
            pInputs[1].inputUnion.ki.dwExtraInfo = IntPtr.Zero;
            pInputs[1].inputUnion.ki.time        = 0;
            int  cbSize = Marshal.SizeOf(typeof(System.Windows.Forms.NativeMethods.INPUT));
            uint num2   = 0;

            lock (events.SyncRoot)
            {
                bool flag = UnsafeNativeMethods.BlockInput(true);
                try
                {
                    count = events.Count;
                    ClearGlobalKeys();
                    for (int i = 0; i < count; i++)
                    {
                        SKEvent skEvent = (SKEvent)events.Dequeue();
                        pInputs[0].inputUnion.ki.dwFlags = 0;
                        if (skEvent.wm == 0x102)
                        {
                            pInputs[0].inputUnion.ki.wVk     = 0;
                            pInputs[0].inputUnion.ki.wScan   = (short)skEvent.paramL;
                            pInputs[0].inputUnion.ki.dwFlags = 4;
                            pInputs[1].inputUnion.ki.wScan   = (short)skEvent.paramL;
                            num2 += UnsafeNativeMethods.SendInput(2, pInputs, cbSize) - 1;
                        }
                        else
                        {
                            pInputs[0].inputUnion.ki.wScan = 0;
                            if ((skEvent.wm == 0x101) || (skEvent.wm == 0x105))
                            {
                                pInputs[0].inputUnion.ki.dwFlags |= 2;
                            }
                            if (IsExtendedKey(skEvent))
                            {
                                pInputs[0].inputUnion.ki.dwFlags |= 1;
                            }
                            pInputs[0].inputUnion.ki.wVk = (short)skEvent.paramL;
                            num2 += UnsafeNativeMethods.SendInput(1, pInputs, cbSize);
                            CheckGlobalKeys(skEvent);
                        }
                        Thread.Sleep(1);
                    }
                    ResetKeyboardUsingSendInput(cbSize);
                }
                finally
                {
                    SetKeyboardState(oldKeyboardState);
                    if (flag)
                    {
                        UnsafeNativeMethods.BlockInput(false);
                    }
                }
            }
            if (num2 != count)
            {
                throw new Win32Exception();
            }
        }