禁用alt键临时c#

Posted

技术标签:

【中文标题】禁用alt键临时c#【英文标题】:Disable alt key temporary c# 【发布时间】:2016-12-11 23:26:49 【问题描述】:

我正在寻找一种在按下时禁用 alt 和 ctrl 键输入的方法。 我实际上正在开发一个宏配置器,当我按下我的宏(例如 Alt+Ctrl+NumPad0)并且我希望发送 H+E+L+L+O 键时,它不起作用,因为我按 Alt。计算机可能会尝试执行 Alt+Ctrl+H、Alt+Ctrl+E 的未知快捷方式... 所以我希望当我按下宏并且程序检测到我按下它时,它会在发送输出键时禁用临时 alt,并在完成时再次启用 Alt。 我使用 LowLevelKeyboardProc 来检测我何时按下一个键,但我无法阻止 Alt 按下,因为我实际上是在按下它来执行我的宏。

//我表单中的代码

private void Listener_OnKeyUp(object sender, KeyUpArgs e)

    KeyAction.RemoveKeyDown(e.KeyUp);



private void Listener_OnKeyPressed(object sender, KeyPressedArgs e)

    try
    
        KeyAction.PutKeyDown(e.KeyPressed);
        foreach (MacroEntree macro in macros)
        
            if (macro.Activated)
                if (macro.Action != null)
                    if (macro.isMacroDown())
                    
                        listener.OnKeyPressed -= new EventHandler<KeyPressedArgs>(Listener_OnKeyPressed);
                        new Thread(delegate ()
                        
                            while (IsAltCtrlDown()) ;
                            macro.ExecuteAction();
                            Thread.Sleep(100);
                            listener.OnKeyPressed += new EventHandler<KeyPressedArgs>(Listener_OnKeyPressed);

                        ).Start();
                    
        
    
    catch (Exception ex)
    

        MessageBox.Show("Erreur : " + ex.Message);
    

private bool IsAltCtrlDown()

    if (KeyAction.isKeyDown(Key.LeftAlt) || KeyAction.isKeyDown(Key.RightAlt))
        return true;
    if (KeyAction.isKeyDown(Key.LeftCtrl) || KeyAction.isKeyDown(Key.RightCtrl))
        return true;
    return false;



//the code from my class that checks if the macro is down
public class KeyAction

   static List<Key> keyDown = new List<Key>();

    public static bool isKeyDown(Key k)
    
        return keyDown.Contains(k);
    
    public static void PutKeyDown(Key k)
    
        if (!keyDown.Contains(k))
            keyDown.Add(k);
    
    public static void RemoveKeyDown(Key k)
    
        keyDown.Remove(k);
    

【问题讨论】:

您不能为 Ctrl + Alt 发送KeyUp 吗?也许这样系统可能会认为您已经释放了密钥(使用 keybd_event)。 我会试试这个,我没想过。 编辑:我刚试了一下,效果很好,想起来太容易了....谢谢!! 很高兴听到这个消息。您可以发布实际解决方案作为此问题的答案,以便有相同问题的人也可以使用它。 【参考方案1】:

您可以设置 low-level keyboard hook 来吞下 Windows 中的键盘输入消息。

每个本地 Windows 程序都基于所谓的message loop,基本上就是这样。

MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 

使用low-level keyboard hook,您可以在desktop 进程上处理此循环中的消息,并防止按键被按下。

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

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

private const int WH_KEYBOARD_LL = 13;
private static IntPtr SetHook(LowLevelKeyboardProc proc)

    return SetWindowsHookEx(
        WH_KEYBOARD_LL, 
        proc, 
        0, // hook on all input (https://***.com/questions/7715480/is-zero-ever-a-valid-handle)
        0); // for all threads

您可以使用如下代码。当您不调用CallNextHookEx 时,按键事件不会有任何影响。

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

private const int WM_KEYDOWN = 0x0100;

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)

    // check if it is a key down message
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    
        int vkCode = Marshal.ReadInt32(lParam);
        // check if the pressed key is the `Alt` key
        if((Keys)vkCode == Keys.Alt)
        
            // return 1 for handled if its the alt key
            return (IntPtr) 1; 
        
     

    // let the message bubble if its not a keydown message or it wasn't the alt key which was pressed               
    return CallNextHookEx(_hookID, nCode, wParam, lParam);


// with this line you can set the `HookCallback` into the message loop
IntPtr hookID = SetHook(HookCallback);

别忘了解开钩子。

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

UnhookWindowsHookEx(hookID);

【讨论】:

感谢您的回复。我已经尝试过了,但如果我真的按下它来执行我的宏,我无法阻止按下 Alt 键。我需要在按下 Alt 键时禁用它,直到执行的操作完成。 @FosheusBadabu 代码应该如何确定是否按下了作为宏的一部分的任何键?如果用户按下 Alt 键,但等待一分半钟完成宏怎么办? 抱歉回复晚了。宏将在一分半后执行,这不是我想要的。我的表单捕获的 Hookcallback 中有一个事件。我还有一个检查宏是否关闭的类。当一个键在事件中被捕获时,我检查其他键是否与我的班级一起关闭(这是一个列表,当一个键被按下或向上时我会填写和清理),当宏被关闭时,我等到 alt 和ctrl 被释放。 @FosheusBadabu 这是与您的其他代码相关的问题。显示有关您所做工作的代码示例。但是如果它与这个问题或完全新的问题有关,请先考虑它 我实际上知道如何禁用某些键,但我只想禁用 alt 键几微秒来执行我的宏并在之后重新启用它。问题是我无法在 HookCallback 中禁用 alt 键,因为我已经在按下它。【参考方案2】:

感谢@Manfred Radlwimmer,我解决了这个问题。在执行我的操作之前,我发送了一个 Alt 和 Ctrl 键,它工作正常。

    private void Listener_OnKeyPressed(object sender, KeyPressedArgs e)
    
        try
        
            KeyAction.PutKeyDown(e.KeyPressed);
            foreach (MacroEntree macro in macros)
            
                if (macro.Activated)
                    if (macro.Action != null)
                        if (macro.isMacroDown())
                        
                            listener.OnKeyPressed -= new EventHandler<KeyPressedArgs>(Listener_OnKeyPressed);
                            new Thread(delegate ()
                            
                                KeyboardOperations.SendKeyUp(KeyboardOperations.KeyCode.LALT);
                                KeyboardOperations.SendKeyUp(KeyboardOperations.KeyCode.LCONTROL);

                                macro.ExecuteAction();
                                Thread.Sleep(100);
                                listener.OnKeyPressed += new EventHandler<KeyPressedArgs>(Listener_OnKeyPressed);

                            ).Start();
                        
            
        
        catch (Exception ex)
        

            MessageBox.Show("Erreur : " + ex.Message);
        
    

【讨论】:

以上是关于禁用alt键临时c#的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MySQL 中临时禁用外键约束?

如何在 MySQL 中临时禁用外键约束?

如何在 MySQL 中临时禁用外键约束?

如何在 Firebird 2.1 中临时禁用表中的所有约束?

禁用 osgi 临时文件夹

在函数调用期间临时禁用窗口