将一个键组合转换为另一个 [英] Converting a key combo into another one

查看:84
本文介绍了将一个键组合转换为另一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测和抑制组合键,而是发送另一个组合键.
(带有WPF的C#.)

我找到了两个不错的库,一个用于处理键盘和鼠标挂钩:
http://globalmousekeyhook.codeplex.com/ [ ^ ]
另一个用于发送虚拟键和鼠标事件:
http://inputsimulator.codeplex.com/ [ ^ ]
尽管我的问题是理论上的,但可能与
的内部运作方式有关 系统.

因此,现在我可以检测和抑制组合键,但是只要发送虚拟
按键,两个模块开始干涉.

假设我要将"Alt + D"转换为"K".我按住
上的"Alt"和"D" 键盘,可在应用程序中创建两个KeyDown事件.相关功能是
调用时,将识别该组合,并按下虚拟的"K".但这瞬间
调用KeyDown事件,启动组合检测,现在正在查看Alt + D + K
这不是我们要寻找的组合,所以整个过程都坏了...

在组合检测期间,我可以忽略我刚刚伪造的密钥,但这会破坏
发送的密钥是原始组合的一部分的情况.
(例如:"Alt + A"->"Shift + A",组合检测不应忽略"A".)

我尝试在发送击键之前先关闭挂钩,然后再重新启动
以防止我的应用注意到虚拟按键.不幸的是,这也有一个问题:如果应用程序不知道按键,那么它就无法抑制任何按键
因此原始的不需要的组合键会泄漏出去.

我是C#的新手,从没接触过低级的东西(也不想这么做),所以
这个问题对我来说有点不知所措.我会很感激关于如何
的任何建议 解决这个问题,任何示例或相关故事...

I''m trying to detect and suppress a key combo and send another instead.
(C# with WPF.)

I''ve found two nice libraries, one for handling keyboard and mouse hooks:
http://globalmousekeyhook.codeplex.com/[^]
and another for sending virtual key and mouse events:
http://inputsimulator.codeplex.com/[^]
although my problem is theoretical, probably more related to inner workings of the
system.

So now I can detect and suppress a key combination but as soon as I send a virtual
key press, the two modules start to interfere.

Let''s say I want to convert "Alt+D" into "K". I press and hold "Alt" and "D" on the
keyboard which creates two KeyDown events in the app. The related functions are
called, the combo is recognized and a virtual "K" is pressed. But that instantly
calls the KeyDown event, starts the combo detection which is now looking at Alt+D+K
which is not the combo we are looking for so the whole thing breaks...

During combo detection I could ignore the key I''ve just faked but that would break
cases where the sent key is part of the original combination.
(For example: "Alt+A" -> "Shift+A", combo detection shouldn''t ignore "A".)

I tried turning off the hooks before sending the keystroke and back on after that
to prevent my app noticing the virtual keypress. Unfortunately that too has a problem: if the app don''t know about keypresses then it can''t suppress any of them
so the original, unwanted key combo leaks through.

I''m new at C# and have never touched low level stuff (and don''t really want to) so
this problem is a bit overwhelming for me. I''d appreciate any suggestions on how to
tackle this, any examples or related stories...

推荐答案

这里有几件事可以尝试.您已经提到过一种方法(在发送虚拟按键时关闭全局键盘挂钩),但这似乎不起作用.但是,如果您创建了一个全局变量来跟踪自己在逻辑中的位置,则可能可行.如果您正在发送虚拟按键,则布尔值var或设置为true的字符串之类的东西.另外,您可以尝试使用SendKeys代替inputsimulator.这将要求焦点集中在您将密钥发送到的应用程序上. (您可以使用AppActivate来激活向其发送击键的应用程序)如果检测到Alt + D + K,整体中断"为什么...这不是您要查找的匹配项,所以逻辑应该只是跳过此错误. (也许尝试一下,在这里捕捉语句?).请发布一些代码,以及发送虚拟按键时收到的错误.这可能会进一步说明您遇到的问题.我已经使用了上面提到的globalkeyboardhook,它的运行效果非常好.但是,我正在使用一些win32 api函数调用来移动鼠标光标,并且我正在使用SendKeys将击键发送到应用程序.

想通了一点...我把这段代码与我周围放置的其他代码放在一起了...可能根本不起作用,但可能有一定用处

There are several things to try here. One you have already mentioned (turning off the global keyboard hook while sending virtual key presses), but that does not appear to work. However, it could maybe work if you created a global variable to keep track of where you are in the logic. Something like a boolean var or string set to true if you are in the process of sending a virtual keypress. Also, you could try using SendKeys instead of the inputsimulator. This would require that focus exists on the application you are sending the key to. (You could use AppActivate to activate the application you are sending the keystroke to) Why does the "whole thing break" if it detects Alt+D+K... this is not the match you are looking for, so the logic should just pass over this error. (maybe a try, catch statement here?). Please post some code, and the error that you receive when sending the virtual keypress. This may shed additional light on exactly what problem you are encountering. I have used the globalkeyboardhook mentioned above, and it works beautifully. However, I am using some win32 api function calls to move the mouse cursor, and I am using SendKeys to send keystrokes to an application.

Figured I''d take a stab at this... I threw this code together from some other code that I had laying around... may not work at all, but could possibly be of some use

    //setup boolean variable to keep track of whether or
    //not you are currently sending a virtualized keyPress
public bool sendingVirtualKeyPress = false;

//setup background worker to handle the execution of the virtual key press
BackgroundWorker bw = new BackgroundWorker();

public Form1()
    {
        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        InitializeComponent();
    }

private void startButton_Click(object sender, EventArgs e)
    {
        if (bw.IsBusy != true && childThreadExists == false)
        {
    //i am using this boolean variable to control only having
            //one thread other than the GUI thread
            childThreadExists = true;
            startButton.Enabled = false;
    //test call using defined string with expected result
    string testString = "A,B,C";
    //string testString should cause "CBA" to be printed
            //to a richtextbox when ran through the Do_Work method
    bw.RunWorkerAsync(testString);
    //RunWorkerAsync calls the DoWork method
        }
    }

//this is whatever method you currently have defined for
    //detecting global key presses
detectInputReceivedEvent()
{
    //adding a boolean check here to ensure that a Virtual
            //Key Press is not happening elsewhere, will prevent
            //you from detecting a virtualized key press
    if(sendingVirtualKeyPress == false)
    {
        //get input from global hook
        string detectedInputFromGlobalHook = "";
        //send current keys being pressed to background worker
        bw.RunWorkerAsync(detectedInputFromGlobalHook);
    }
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    //determine if keys are a combo that you want
    //if so, then do two things:
    //turn on global boolean variable
    //sendTranslatedVirtualKeyPress();
    //else return;

    BackgroundWorker worker = sender as BackgroundWorker;
        string keysFromGlobalHook = (string)e.Argument;

        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            return;
        }
        else
        {
            //this is where we want to do our work
    //first translate the string received by the global Keyboard hook
    //into the key presses that you are wanting
    string translation = getTranslatedKeys(keysFromGlobalHook);
            //then send the virtualized keypress
    sendVirtualizedKeyPress(translation);

            //worker.ReportProgress((1));
    // Perform a time consuming operation and report progress.
            System.Threading.Thread.Sleep(500);
        }
}

    private string getTranslatedKeys(string inputKeys)
    {
        if(inputKeys.ToUpper() == "A,B,C")
        {
            return "CAB";
        }
    }

    private void sendVirtualizedKeyPress(string inputKeys)
    {
        try
        {
             System.Windows.Forms.SendKeys.SendWait(keyString);
        }
        catch (Exception e)
        {
             MessageBox.Show("An Error Occurred With Send Keys..." + "\n\r");
        }
    }

private void cancelButton_Click(object sender, EventArgs e)
    {
        if (bw.WorkerSupportsCancellation == true)
        {
            bw.CancelAsync();
            //if you have disabled buttons, etc. when running the
            //background worker this would be a good place to re-enable them
    startButton.Enabled = true;
        }
    }

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if ((e.Cancelled == true))
        {
            this.richTextBox1.AppendText("Canceled!");
        }

        else if (!(e.Error == null))
        {
            this.richTextBox1.AppendText("Error: " + e.Error.Message);
        }

        else
        {
            this.richTextBox1.AppendText("BackgroundWorkerCompleted" + "\r\n");

            childThreadExists = false;
        }
    }


这篇关于将一个键组合转换为另一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆