Identify key uniquely from WM_KEYDOWN message - winapi

I tried to use the virtual key code provided by wParam, however that didn't work very well:
multiple keys mapped to the same key code
some keys were not recognized at all
virtual keys seemed to be adapted to the keyboard layout (which i don't want/need)
Then i saw that the lParam will give me a scancode along with an "extended" flag, which seem to produce a different value for every single key on the keyboard when calculated like this:
value = (lParam & 0x01FF0000) >> 16;
Will this value always be identical for the same key on the keyboard, even across various keyboards/systems?

Scancodes can be different for different keyboards. Best to use virtual key codes. From http://msdn.microsoft.com/en-us/library/ms646267(v=vs.85).aspx:
Assigned to each key on a keyboard is a unique value called a scan
code, a device-dependent identifier for the key on the keyboard. A
keyboard generates two scan codes when the user types a key—one when
the user presses the key and another when the user releases the key.
The keyboard device driver interprets a scan code and translates
(maps) it to a virtual-key code, a device-independent value defined by
the system that identifies the purpose of a key.

Related

Key-remapping using Macbook command-line

The "delete" key on my Macbook is broken. I am attempting to use the hidutil command to remap F1 as my new delete key. The command isn't performing as expected.
The command requires the hex ID's for the keys whose values I'd like to interchange. I've located a resource that provides these hex ID's as well as an overview of how to perform the remapping (https://developer.apple.com/library/archive/technotes/tn2450/_index.html).
I've posted my specific code below. It adheres to the suggested format, but my OS doesn't seem to register any change. Can someone help me identify the issue? I suspect my Hex ID's are wrong, but it may very well be another issue.
Input :
hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc":0x2a,"HIDKeyboardModifierMappingDst":0x3a}, {"HIDKeyboardModifierMappingSrc":0x3a,"HIDKeyboardModifierMappingDst":0x2a}]}'
Output :
UserKeyMapping:(
{
HIDKeyboardModifierMappingDst = 58;
HIDKeyboardModifierMappingSrc = 42;
},
{
HIDKeyboardModifierMappingDst = 42;
HIDKeyboardModifierMappingSrc = 58;
})
There are no error objects. And judging by the output after the command is run some key remapping has occurred. However, my F1 key still retains functionality as F1 and doesn't delete I'd expected.
Your referenced link on apple.com says "The keys take a hexadecimal value that consists of 0x700000000 or’d with the desired keyboard usage value." So I think you should try e. g. HIDKeyboardModifierMappingSrc":0x70000002a ...
Thanks for the above information, I was able to remap the right Ctrl key to be the Command key on the mac with the following command.
% hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc":0x7000000e4,"HIDKeyboardModifierMappingDst":0x7000000e3}]}'
This is because I am using a very old IBM original keyboard that does not have a windows key, just an empty space between the Ctrl and Alt keys on the left and right of the Space bar.

How to get modifier key event(alt+ctrl+shift),

If anyone is working on win32 API.Please have a look to below issue.
I have a requirement to call a function when modifier keys are pressed(alt+ctrl+shift) at same time in win32 programming.But I am not getting how to handle this event when modifiers keys are pressed at same time.
If someone have any idea please post it.
To get the status of key there is an API GetKeyState. With help of this you can check whether a key is down or up.
For example:
if (GetKeyState(VK_SHIFT)& 0x8000)
//Key is pressed
you can also check in combination like this:
if (GetKeyState(VK_SHIFT)& 0x8000 && GetKeyState(VK_CONTROL)& 0x8000)
//ctrl+shift key is pressed.
You should handle WM_KEYDOWN and WM_KEYUP messages, and track the state (up or down) for all of these keys: VK_SHIFT, VK_CONTROL, VK_MENU.

Determine if Control key was used to generate character in WM_CHAR

When receiving character input, is there a way to know whether the character code in wParam was generated as a result of the keyboard state we get back from GetKeyboardState()? For example, if you hit Ctrl+A then the character 'a' would not be a result of the control key but if you're using a Swedish keyboard and type Ctrl+Alt+7 the result would be {. In that case, is there any way of knowing that the keyboard state (Ctrl and Alt) were necessary to generate that character code?
(To be honest, as an English speaker who has really only ever used a US keyboard layout, I have no definite idea that this will work, but...) I believe that the VkKeyScan function (or VkKeyScanEx) might do what you want.
As input, it takes a character, not a scan code or a virtual key, so this is the wParam value that you get from WM_CHAR.
Its return is a value that provides both the virtual-key code (which I guess you can ignore) in the low-byte, and the (mis-named) "shift state" in the high-byte, which is actually a set of flags representing the qualifier keys needed to produce that character.
So if you get a WM_CHAR message and wanted to tell if the control key was needed in order to generate it, in theory you could do:
case WM_CHAR:
if (HIBYTE(VkKeyScan((TCHAR)wParam)) & 2) {
// control pressed!
}
break;
If you are only looking at the data provided by the WM_CHAR message, then no. You would likely have to look at the WM_KEY... messages to keep track of what the surrounding keystrokes where doing at the time, if Get(Async)KeyboardState() does not provide what you need.

In OS X (lion) how can I find whether a key combination is in use as a keyboard shortcut?

I want to put a bunch of keyboard shortcuts in my app (OS X lion) so I can do most things from the keyboard. There are of course a bunch of lists of hot key combos in use already, including the one in the HIG.
Is there some utility that can be used to type a key combination and find out if it already means something (either globally, or mac standard -- I'm not too worried about reusing some special combo used by another app -- or should I be?)?
You can use Carbon to do this. Don't be afraid to use Carbon here, there is no Cocoa way to get this information and the Carbon methods are still supported.
The CopySymbolicHotKeys() function returns an array of dictionaries, containing information about the system-wide symbolic hot keys defined in the Keyboard preferences pane. Each dictionary contains information about a single hot key.
Specifically, each dictionary has three keys:
kHISymbolicHotKeyCode: The virtual key code of the hot key, represented as a CFNumber.
kHISymbolicHotKeyModifiers: The hot key’s keyboard modifiers, represented as a CFNumber.
kHISymbolicHotKeyEnabled: The enabled state of the hot key, represented as a CFBoolean.
Obviously these are raw key codes so you will need to do some work if you want to see what the key codes actually refer to.
Note that the array doesn't contain custom, application-specific hotkeys, but this is a minor problem.
Here's a simple example:
#import <Carbon/Carbon.h>
CFArrayRef registeredHotKeys;
if(CopySymbolicHotKeys(&registeredHotKeys) == noErr)
{
CFIndex count = CFArrayGetCount(registeredHotKeys);
for(CFIndex i = 0; i < count; i++)
{
CFDictionaryRef hotKeyInfo = CFArrayGetValueAtIndex(registeredHotKeys, i);
CFNumberRef hotKeyCode = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyCode);
CFNumberRef hotKeyModifiers = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyModifiers);
CFBooleanRef hotKeyEnabled = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyEnabled);
NSLog(#"key code: %# modifiers: %# enabled: %#", hotKeyCode, hotKeyModifiers, hotKeyEnabled);
}
//you MUST release the dictionary when finished with it
CFRelease(registeredHotKeys);
}
Remember that you'll need to add the Carbon framework to the Link Binary with Libraries build phase in your project settings.
For more information you should look at the Carbon Event Manager docs (11Mb PDF).
Thear used to be an API in Carbon to get the global keyboard shortcuts, however, I do not believe there is a Cocoa API for this. I don't think you should worry about other third party apps, but you could refer to http://support.apple.com/kb/HT1343 and just hard code to avoid those. He that helps.

Hiding an entry (or a "fin the registry

I'm trying to hide some values in the registry (such as serial numbers) with C++/windows
so I've been looking at this article http://www.codeproject.com/KB/system/NtRegistry.aspx
which says:
How is this possible? The answer is
that a name which is a counted as a
Unicode string can explicitly include
NULL characters (0) as part of the
name. For example, "Key\0". To include
the NULL at the end, the length of the
Unicode string is specified as 4.
There is absolutely no way to specify
this name using the Win32 API since if
"Key\0" is passed as a name, the API
will determine that the name is "Key"
(3 characters in length) because the
"\0" indicates the end of the name.
When a key (or any other object with a
name such as a named Event, Semaphore,
or Mutex) is created with such a name,
any application using the Win32 API
will be unable to open the name, even
though they might seem to see it.
so I tried doing something similar:
HKEY keyHandle;
PHKEY key;
unsigned long status = 0;
wchar_t *wKeyName = new wchar_t[m_keyLength];
MultiByteToWideChar(CP_ACP, 0, m_keyName, m_keyLength, wKeyName, m_keyLength);
wKeyName[18] = '\0';
long result = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
wKeyName,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&keyHandle,
&status);
where m_keyName is the ASCII text and wKeyName is the wide char text, but in regedit I see that it is treated the same and the key is just cut where I put the '\0'.
what is wrong with it?
The problem is that you are using the Win32 API and not the NT Native API. There is a table about 1/2 way through the article that you referenced that contains the list of Native APIs. For example, you would use NtCreateKey or ZwCreateKey instead of RegCreateKeyExW. The Win32 API assumes that alls strings are terminated by a NUL character whereas the Native API counterparts use a UNICODE_STRING structure for the name.
I'll take a stab in the dark, as I have never tried to do this.
It appears that you are using the wrong function to create your registry key. You should be using the NtCreateKey method because RegCreateKeyEx[AW] will notice your '\0' and chop off past it.
Why not use the class provided in the example? It provides a method called CreateHiddenKey. To use it, simply call SetKey before it. It would be much cleaner.

Resources