none
Резделение клавиатур

    Вопрос

  • Здравствуйте.

    Задача состоит в следующем.

    Имеется две клавиатуры, поключенные к одному ПК. Необходимо перехватывать нажатия клавиш лишь с одной из них. Клавиатура, с которой необходимо перехватывать нажатия, может подключаться как через USB так и через PS/2 - это не принципиально.

    Вопрос - как это реализовать?

    Суть состоит в том, чтобы одна клавиатура оставалась полноценной, а нажатия на другой эмулировались под мои команды (например, заменить "пробел" на "Ctrl+5", а "Esc" на "Открыть Мой компьютер").

    Заранее благодарю.

    17 марта 2014 г. 11:19

Ответы

  • Microsoft Win32 subsystem opens all keyboard and mouse devices for its exclusive use. For each device class, the Win32 subsystem treats input from all the devices as if the input came from a single input device. An application cannot request to receive input from only one particular device.

    а тут говорят что нельзя получить/передать данные с/к определённой клавиатуре. так что как бы вы не пробовали обращаться к winapi, похоже это не возможно

    http://msdn.microsoft.com/en-us/Library/Windows/Hardware/ff557565(v=vs.85).aspx

    а тут WDF, путь к созданию драйвера на с/с++


     



    • Изменено Medet Tleukabiluly 17 марта 2014 г. 17:43
    • Помечено в качестве ответа Hovanskiy 20 марта 2014 г. 15:54
    17 марта 2014 г. 17:40

Все ответы

  • На мой не профессиональны взгляд, это можно реализовать двумя способами:
    1) Написать клавиатурный хук, который бы принимал данные с клавиатур, затем понимал с какой клавиатуры пришел сигнал, а уже потом решал бы, необходимо ли заменить команду или нет;
    2) Написать драйвер на основе стандартного драйвера для клавиатуры, на которой необходимо менять назначения клавиш и соответствующий софт под него.

    Первый способ мне кажется более сложным и думаю он будет задерживать систему (каждое нажатие будет обрабатываться процессором да и реакция системы на нажатия полноценной клавы упадет).
    Второй способ кажется наилучшим, но я совершения не имею понятия как писать драйвера.

    17 марта 2014 г. 11:39
  • Добрый день.

    Зависит от того, что вы хотите. Если на уровне операционной системы, чтобы во всех приложениях работало именно так, то это надо на WinAPI делать хук на клавиатуру. Если конкретно в вашем приложении, то это намного проще, например у аргумента события KeyUp в есть свойство отвечающие за источник сообщения. И по Handle можно различать клавиатуры с которых пришло нажатие.

    17 марта 2014 г. 11:40
    Отвечающий
  • Да, замена клавиш должна быть для всех приложений! Потом в программе-настроек можно будет выбирать различные профили (например для блокнота- одни команды, для медиа плеера - другие), но сама замена должна быть для всей системы!

    17 марта 2014 г. 11:56
  • драйвер не что иное как хук под приложение, но на низком уровне, разницы между ними почти нет. и смысла нет писать драйвер.

    нужен WinApi, но для начало нужны знания, придётся работать с unmanaged код, что само собой является уже не C#. для начало рекомендую http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx

    для начало приложение, а дальше можно и сервис


    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    17 марта 2014 г. 15:52
  • Спасибо за совет, но в C++ я абсолютный 0 !!! Можно какой-нибудь примерчик!?

    Я создал обычный проект в VS на C++ и просто ужаснулся((

    17 марта 2014 г. 16:10
  • Моя основная проблема - это как раз отличить одну клаву от другой! Как можно реализовать именно это!? Перехват нажатий и эмуляцию нажатий я примерно знаю как реализовать - в интернете примеры есть.
    17 марта 2014 г. 16:18
  • сделайте для начало приложение под C# winforms, тогда придет ясность что значит клавиатура, позже попробуйте с эмулировать нажатие. позже работа с winapi, а дальше уже все станет понятно. повторяю. начните с простого, сделайте его настолько правильным насколько можно...стена строится по кирпичу

    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    17 марта 2014 г. 16:32
  • В c# я пока добился:
    - хук на клавиатуру
    - эмуляция нажатий

    Но дело в том, что это распространяется на обе клавы!

    Интересует именно как следить за одной конкретной клавой или слезить за всеми, но получая сигнал, определить с какой имеено клавы он пришел!

    17 марта 2014 г. 16:42
  • Вот нашел на просторах сети хук для клавиатуры, но об блокирует обе клавы!

    using System;
    using System.Runtime.InteropServices; 
    
    namespace WindowsFormsApplication4
    {
        internal class HookDemoHelper
        {
            private const int WH_KEYBOARD_LL = 13;
            private LowLevelKeyboardProcDelegate m_callback;
            private IntPtr m_hHook;
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, int dwThreadId);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern bool UnhookWindowsHookEx(IntPtr hhk);
    
            [DllImport("Kernel32.dll", SetLastError = true)]
            private static extern IntPtr GetModuleHandle(IntPtr lpModuleName);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    
            private IntPtr LowLevelKeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                if (nCode < 0)
                {
                    return CallNextHookEx(m_hHook, nCode, wParam, lParam);
                }
                else
                {
                    var khs = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                    if (khs.VirtualKeyCode == 9 &&
                        wParam.ToInt32() == 260 &&
                        khs.ScanCode == 15) //alt+tab 
                    {
                        Console.WriteLine("Alt+Tab pressed!");
                        IntPtr val = new IntPtr(1);
                        return val;
                    }
                    else
                    {
                        return CallNextHookEx(m_hHook, nCode, wParam, lParam);
                    }
                }
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct KeyboardHookStruct
            {
                public readonly int VirtualKeyCode;
                public readonly int ScanCode;
                public readonly int Flags;
                public readonly int Time;
                public readonly IntPtr ExtraInfo;
            }
            private delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, IntPtr lParam);
    
            public void SetHook()
            {
                m_callback = LowLevelKeyboardHookProc;
                m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
                    m_callback,
                    GetModuleHandle(IntPtr.Zero), 0);
            }
    
            public void Unhook()
            {
                UnhookWindowsHookEx(m_hHook);
            }
        }
    }
    

    17 марта 2014 г. 16:51
  • с таким вряд ли кто сталкивался раньше, поэтому скорей всего дальше вам придётся копать самостоятельно. но слышал что можно подключить мышку/клаву/монитор к нетбуку, и мышка/клава работают самостоятельно


    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    17 марта 2014 г. 17:06
  • с таким вряд ли кто сталкивался раньше, поэтому скорей всего дальше вам придётся копать самостоятельно. но слышал что можно подключить мышку/клаву/монитор к нетбуку, и мышка/клава работают самостоятельно


    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    сколько я не подключал и клавы и мышки к ноутам - всегда они дублировали штатные!

    В этом то и проблема! Потому и спрашивал на счет драйвера! Ведь если я замену стандартный драйвер клавы в диспетчере устройств на свой - я же ведь смогу общаться с этой клавой напрямую из своего приложения!?

    17 марта 2014 г. 17:09
  • в c# драйвер не делают. нужно знать С, и притом очень хорошо, такие штуки как драйвер любят синие экраны смерти, и делать драйвер сплошная мука, не зря же их делают только профи, и обычно вместе с ПО. в общем это плохая идея. ищите софт, может есть какой


    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    17 марта 2014 г. 17:33
  • Microsoft Win32 subsystem opens all keyboard and mouse devices for its exclusive use. For each device class, the Win32 subsystem treats input from all the devices as if the input came from a single input device. An application cannot request to receive input from only one particular device.

    а тут говорят что нельзя получить/передать данные с/к определённой клавиатуре. так что как бы вы не пробовали обращаться к winapi, похоже это не возможно

    http://msdn.microsoft.com/en-us/Library/Windows/Hardware/ff557565(v=vs.85).aspx

    а тут WDF, путь к созданию драйвера на с/с++


     



    • Изменено Medet Tleukabiluly 17 марта 2014 г. 17:43
    • Помечено в качестве ответа Hovanskiy 20 марта 2014 г. 15:54
    17 марта 2014 г. 17:40
  • Хук не различает с какой клавиатуры был ввод.
  • Хук не различает с какой клавиатуры был ввод.
  • Хук не различает с какой клавиатуры был ввод. В winapi есть RAW INPUT
    Функция RegisterRawInputDevices позволяет зарегистрировать устройства, по типу, с которых получать необработанный код. Для клавиатур необходимо вставить usUsagePage = 1; usUsage = 6; и dwFlags = 130h. после чего приложение будет получать сообщение WM_INPUT после каждого нажатия/отжатия клавиши. lParam сообщения содержит handle RAWINPUT структуры. Его небходимо вставить в функцию GetRawInputData  чтобы получить саму структуру. В структуре содержится и scan code, и virtual-key code, а так же hDevice содержит handle устройства на котором была нажата клавиша. Для каждой физической клавиатуры этот handle уникален.
    P.S. Интересно что с виртуальных клавиатур handle ≈ 0. А также на моей мультимедиа клавиатуре клавиши мультимедиа тоже выдают handle = 0 :O
    _
    MSDN мне не разрешил вставлять ссылки на статьи с описанием функций. Так что воспользуйтесь поиском.