简体   繁体   English

使用“SendInput”时如何处理按下的 Windows 徽标键?

[英]How can I deal with depressed Windows logo key when using `SendInput`?

My application synthesises keystrokes in other apps by using SendInput .我的应用程序使用SendInput合成其他应用程序中的击键。 This almost works, except that due to circumstances I cannot change, the left Windows key will always be physically depressed when sending the input.这几乎有效,除了由于我无法更改的情况,发送输入时始终会物理按下左 Windows 键。 This means that if, for example, the keystroke being sent is the 'd' key, then Windows sees the keystroke as its Win+D shortcut and displays the Desktop, and the 'd' keystroke never makes it to its intended target.这意味着,例如,如果发送的击键是“d”键,则 Windows 会将击键视为其 Win+D 快捷方式并显示桌面,而“d”击键永远不会到达其预期目标。

The documentation mentions this problem but is frustratingly vague about how to fix it (emphasis mine):文档提到了这个问题,但关于如何解决它却令人沮丧地含糊不清(强调我的):

This function does not reset the keyboard's current state.此功能不会重置键盘的当前状态。 Any keys that are already pressed when the function is called might interfere with the events that this function generates.调用该函数时已按下的任何键可能会干扰该函数生成的事件。 To avoid this problem, check the keyboard's state with the GetAsyncKeyState function and correct as necessary .为避免此问题,请使用GetAsyncKeyState函数检查键盘状态并根据需要进行更正

How should I "correct as necessary"?我应该如何“根据需要更正”?

I've tried using SetKeyboardState to turn off the keyboard state of the VK_LWIN key, after first attaching my thread to the thread of the window that I am sending the keystrokes to (with AttachThreadInput ), but this doesn't seem to affect the behaviour at all.我尝试使用SetKeyboardState关闭VK_LWIN键的键盘状态,在首先将我的线程附加到我将击键发送到的窗口的线程(使用AttachThreadInput )之后,但这似乎不会影响行为根本。

I've also tried inserting a KEYEVENTF_KEYUP event at the start of the input I am sending with SendInput , but this causes the Start Menu to pop up and grab focus, which is obviously not acceptable.我还尝试在使用SendInput发送的输入开始时插入KEYEVENTF_KEYUP事件,但这会导致开始菜单弹出并获取焦点,这显然是不可接受的。

What is the correct method of dealing with a depressed Windows logo key when calling SendInput?调用 SendInput 时处理按下的 Windows 徽标键的正确方法是什么?

EDIT:编辑:

As per @Brian's answer I can prevent the win key from interfering with my code by installing a low-level keyhook which traps win-key keydown events.根据@Brian 的回答,我可以通过安装一个捕获 win-key keydown 事件的低级 keyhook 来防止 win 键干扰我的代码。

This, however, has the undesired effect that the Windows key is now disabled entirely.但是,这会产生不希望的效果,即现在完全禁用了 Windows 键。 I can sort of envisage some solution to this where I keep a note of the state of all the keys within my keyhook, and simulate presses of the windows key when other keys are pressed, depending on whether or not they are the ones I'm simulating, but that sounds like a hack to me.我可以设想一些解决方案,我会记录我的钥匙扣内所有键的状态,并在按下其他键时模拟 Windows 键的按下,这取决于它们是否是我的键模拟,但这对我来说听起来像是一个黑客。 Alternatively, I could use my keyhook to emulate important windows keyboard shortcuts.或者,我可以使用我的 keyhook 来模拟重要的 Windows 键盘快捷键。

But the documentation implies it should all work in a much more straightforward way.但是文档暗示它应该以更直接的方式工作。 Brian's solution is to prevent the win key from getting to the pressed down state in the first place. Brian 的解决方案是首先防止 win 键进入按下状态。 But the documentation states that you should be able to check if it's pressed down later on, and correct it if it is.但是文档指出您应该能够检查它是否被按下,如果是,则进行更正。

Is it actually possible to do this?实际上有可能做到这一点吗?

I basically solved this exact problem yesterday :) My code is in C#, but it mostly consists of win32 API calls via p/invoke, so it should translate directly to C++. 我昨天基本上解决了这个确切的问题:) 我的代码是用 C# 编写的,但它主要由通过 p/invoke 调用 win32 API 组成,所以它应该直接转换为 C++。

The solution is to use a Low-Level Keyboard Hook to intercept the initial Windows key KeyDown event (and tell the OS that you handled it so that it won't be passed to other Applications and/or the OS).解决方案是使用低级键盘钩子拦截初始 Windows 键 KeyDown 事件(并告诉操作系统您处理了它,以便它不会传递给其他应用程序和/或操作系统)。 Then, depending on OS, simulate the Windows key KeyUp event before your input.然后,根据操作系统,在输入之前模拟 Windows 键 KeyUp 事件。 It sounds like you're half-way there, you just need to intercept the initial KeyDown.听起来您已经完成了一半,您只需要拦截初始 KeyDown。

My solution is targeted at Windows Vista and Windows 7, so if you're in XP or below, it's possible that you don't need to send the KeyUp.我的解决方案是针对 Windows Vista 和 Windows 7 的,因此如果您使用的是 XP 或更低版本,则可能不需要发送 KeyUp。 That's what I'll be testing soon, it may work in both;这就是我很快将要测试的,它可能适用于两者; however, Vista and 7 intercept the windows key more aggressively than XP, hence my suspicions.然而,Vista 和 7 比 XP 更积极地拦截 windows 键,因此我怀疑。

There is not a more "straightforward way" for a program to do this without modifying the registry.没有更“直接的方法”让程序在不修改注册表的情况下执行此操作。 The ideal solution is to track the keypresses in a table (std::map, Dictionary, etc).理想的解决方案是跟踪表(std::map、Dictionary 等)中的按键。 The intent of this on MS's part is to prevent viruses/malware from taking control of the keyboard and preventing the user from using important keyboard combos such as WinKey-L and Ctrl-Alt-Delete. MS 方面的目的是防止病毒/恶意软件控制键盘并防止用户使用重要的键盘组合,例如 WinKey-L 和 Ctrl-Alt-Delete。

You can, however, remap the keyboard scan codes in the registry if keyboard hooking is not for you.但是,如果键盘挂钩不适合您,您可以在注册表中重新映射键盘扫描代码。 This isn't ideal, since it's hard to reverse (especially if you make a mistake, or your program crashes, or the user uninstalls the application but the registry hack is not reverted).这并不理想,因为它很难逆转(特别是如果你犯了一个错误,或者你的程序崩溃了,或者用户卸载了应用程序但注册表黑客没有恢复)。 But it does work.但它确实有效。 Here are some references:以下是一些参考:

http://www.howtogeek.com/howto/windows-vista/map-any-key-to-any-key-on-windows-xp-vista/ http://www.howtogeek.com/howto/windows-vista/map-any-key-to-any-key-on-windows-xp-vista/

http://www.howtogeek.com/howto/windows-vista/disable-caps-lock-key-in-windows-vista/ http://www.howtogeek.com/howto/windows-vista/disable-caps-lock-key-in-windows-vista/

http://www.usnetizen.com/fix_capslock.php http://www.usnetizen.com/fix_capslock.php

"Correcting" the state of a modifier key by inserting a KEYEVENTF_KEYUP event may have side-effects, but they can be avoided by inserting additional events.通过插入KEYEVENTF_KEYUP事件“更正”修饰键的状态可能会产生副作用,但可以通过插入其他事件来避免它们。

The Start menu is triggered when the Win key is pressed and released, except when there is an intervening key event or if it was pressed in combination with another modifier.按下并释放 Win 键时会触发“开始”菜单,除非存在中间键事件或与其他修饰符一起按下。 So instead of inserting just Win-up , insert Ctrl-down , Win-up , Ctrl-up .因此,不要只插入Win-up ,而是插入Ctrl-downWin-upCtrl-up

Aside from the Start menu, releasing modifier keys might have other side-effects:除了开始菜单之外,释放修饰键可能还有其他副作用:

  • Releasing Alt can activate the active window's menu (even if it doesn't appear to have one).释放 Alt 可以激活活动窗口的菜单(即使它似乎没有)。
  • Releasing Alt or Shift can activate the Alt+Shift language hotkey.释放 Alt 或 Shift 可以激活 Alt+Shift 语言热键。
  • Releasing Ctrl or Shift can activate the Ctrl+Shift language hotkey.释放 Ctrl 或 Shift 可以激活 Ctrl+Shift 语言热键。
  • Releasing any modifier key can activate the Office hotkey (in Windows 1903 and later, pressing and releasing Ctrl+Alt+Shift+Win opens the Office app).释放任何修饰键都可以激活 Office 热键(在 Windows 1903 及更高版本中,按下并释放 Ctrl+Alt+Shift+Win 将打开 Office 应用程序)。

Inserting a key-down and key-up (or possibly just a key-up without a prior key-down) with almost any other virtual keycode first will generally prevent any of these hotkeys from activating.首先插入几乎所有其他虚拟键码的按键和按键(或可能只是没有先前按键的按键)通常会阻止这些热键中的任何一个被激活。 One can use an undefined or reserved keycode such as 0xE8, although there is still a risk that another program makes use of it.可以使用未定义或保留的键码,例如 0xE8,尽管仍有其他程序使用它的风险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM