I would like map a chars that doesn't exists on my keyboard layout is it possible?
My keyboard layout is italian and the the chars is ~ and `
I would like remap when I press AltGr (VK_RMENU) + VK_OEM_4 or VK_OEM_6.
But this chars aren't in Virtual-Key Codes list, so I think I coud't use SendInput for remapping...
For others chars SendInput works
But this chars aren't in Virtual-Key Codes list, so I think I coud't
use SendInput for remapping...
The ~ and ` are in the Virtual-Key Codes list. It is VK_OEM_3 (0xC0).
You can use SendInput enter ~ and ` like this:
UINT result = 0;
DWORD errCode = 0;
tagINPUT inputArray[2] = {};
tagKEYBDINPUT keyboardInput[2] = {};
keyboardInput[1].wVk = 0xC0; // Virtual-Key code for the '`~' key.
keyboardInput[1].wScan = 0x29; // Scan code for the '`~' key.
inputArray[1].type = INPUT_KEYBOARD;
inputArray[1].ki = keyboardInput[1];
keyboardInput[0].wVk = 0x10; // Virtual-Key code for the 'shift' key.
keyboardInput[0].wScan = 0x2A; // Scan code for the 'shift' key.
inputArray[0].type = INPUT_KEYBOARD;
inputArray[0].ki = keyboardInput[0];
// Enter '~' (shift + '`~' key)
result = SendInput(2, inputArray, sizeof(tagINPUT));
errCode = GetLastError();
// Enter '`'
result = SendInput(1, &inputArray[1], sizeof(tagINPUT));
errCode = GetLastError();
If you want to enter these two chars the SendMessage also can do this (similar issue):
LPCWSTR Target_window_Name = TEXT("Untitled - Notepad"); //<- Has to match window name
HWND hWindowHandle = FindWindow(NULL, Target_window_Name);
HWND EditClass = FindWindowEx(hWindowHandle, NULL, L"Edit", NULL);
SendMessage(EditClass, WM_KEYDOWN, 0xC0, 0x002C0001); //VK_OEM_3 0xC0
SendMessage(EditClass, WM_CHAR, 0x7E, 0x002C0001); //~
SendMessage(EditClass, WM_KEYUP, 0xC0, 0xC02C0001);
SendMessage(EditClass, WM_KEYDOWN, 0xC0, 0x002C0001); //VK_OEM_3 0xC0
SendMessage(EditClass, WM_CHAR, 0x60, 0x002C0001); //`
SendMessage(EditClass, WM_KEYUP, 0xC0, 0xC02C0001);
References: "SendInput" "SendMessage"
For scan code you can search "Keyboard Scan Code Specification - Microsoft".
Related
I want to get control text. but this code return parent class name.
const wchar_t* textInput = L"Login";
HWND btnHandle = CreateWindowEx(0, L"BUTTON", textInput, WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
mCoordinate.x, mCoordinate.y, mDimension.cx, mDimension.cy, parentHandle, NULL,
(HINSTANCE)GetWindowLongPtr(parentHandle, GWLP_HINSTANCE), NULL);
wchar_t* textOutput;
int length = GetWindowTextLengthW(btnHandle);
GetWindowText(btnHandle, textOutput, length);
MessageBox(NULL, textOutput, L"Window Text", MB_OK);
As documented, the lpString argument to GetWindowTextW is:
The buffer that will receive the text.
The API does not provide that buffer for you. Instead, you will have to pass it in, as illustrated here:
size_t length{ GetWindowTextLengthW(btnHandle) };
// Allocates a buffer for `length` characters plus a NUL terminator
std::wstring text(length, L'\0');
// The API promises to write a NUL terminator into the final character
// so it is safe to lie about the length
length = GetWindowTextW(btnHandle, text.data(), text.size() + 1);
// Resize in case we got less than promised
text.resize(length);
MessageBoxW(NULL, text.c_str(), L"Window Text", MB_OK);
I am trying to open a device driver in order to send it an ioctl. There are many examples on SO and elsewhere but virtually all address opening "\\.\PhysicalDrive0" or the like. But I am trying to open a non-disk driver, compiled from Microsoft sample code at GitHub "Windows-driver-samples", namely "simgpio". It appears to have installed correctly but I don't know what "\\.\name" to use. I tried "\\.\simgpio" with no joy. Suggestions?
For reference, I've included the driver's .INF file below.
;/*++
;
;Copyright (c) Microsoft Corporation. All rights reserved.
;
;Module Name:
;
; SIMGPIO.INF
;
;Abstract:
; INF file for installing Simulated GPIO Client Driver.
;
;--*/
[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%ProviderName%
DriverVer = 06/30/2020,15.29.58.35
CatalogFile=gpiosamples.cat
[SourceDisksNames]
3426=windows cd
[SourceDisksFiles]
simgpio.sys = 3426
[DestinationDirs]
DefaultDestDir = 12
[ControlFlags]
BasicDriverOk = *
ExcludeFromSelect = *
;******************************************
; SIMGPIO Client driver Install Section
;******************************************
[Manufacturer]
%ManufacturerName%=Standard,NTx86
[Standard.NTx86]
%GPIO.DeviceDesc% = GPIO_Inst,ACPI\TEST0001
[GPIO_Inst.NT]
Copyfiles = GPIOCopyFiles
[GPIOCopyFiles]
simgpio.sys,,,0x100
[GPIO_Inst.NT.Services]
AddService = simgpio,%SPSVCINST_ASSOCSERVICE%,GPIO_Service_Inst
[GPIO_Service_Inst]
DisplayName = %GPIO.SvcDesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_NORMAL%
ServiceBinary = %12%\simgpio.sys
[strings]
; localizable strings
ProviderName = "TODO-Set-Provider"
ManufacturerName = "TODO-Set-Manufacturer"
GPIO.DeviceDesc = "Simulated GPIO Client Driver"
GPIO.SvcDesc = "Simulated GPIO Client Driver"
; non-localizable strings
SPSVCINST_TAGTOFRONT = 0x00000003
SPSVCINST_ASSOCSERVICE = 0x00000002
SERVICE_KERNEL_DRIVER = 1
SERVICE_BOOT_START = 0
SERVICE_SYSTEM_START = 1
SERVICE_DEMAND_START = 3
SERVICE_ERROR_NORMAL = 1
SERVICE_ERROR_IGNORE = 0
SERVICE_ERROR_CRITICAL = 3
REG_EXPAND_SZ = 0x00020000
REG_DWORD = 0x00010001
REG_SZ = 0x00000000
Thanks to comment by #Eryk, I was able to open a driver. I include a sample program below. All error checking was omitted for clarity. I used the CDROM driver class in this example. The real challenge is finding the elusive GUID to use - you must do some deep digging in the SDK, DDK, include files or your driver.
// enumdevices.c - enumerate and open device(s)
#pragma warning( disable : 4090 )
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <setupapi.h>
#include <cfgmgr32.h>
int
main( int argc,char** argv)
{
#define ALLOC(size) GlobalAlloc( GPTR, size)
SP_DEVINFO_DATA *devData;
HANDLE devSet;
HANDLE hDev;
SP_DEVICE_INTERFACE_DATA *devIfData;
SP_DEVICE_INTERFACE_DETAIL_DATA *Details;
GUID *devGuid;
DWORD needed;
DWORD unused;
int count; // count of enumerated devices
DWORD idev; // device index
DWORD iface; // interface index
char deviceID[200]; // device id string
int IDSize;
BOOL ok;
devData = ALLOC( sizeof(SP_DEVINFO_DATA) );
devData->cbSize = sizeof(SP_DEVINFO_DATA);
// GET SET OF DEVICE INTERFACES PRESENT OF SPECIFIED devGuid
devGuid = &GUID_DEVINTERFACE_CDROM; // set dev class guid to enumerate
devSet = SetupDiGetClassDevs( devGuid, NULL, NULL, DIGCF_DEVICEINTERFACE|DIGCF_PRESENT );
// OUTER LOOP
idev = 0;
count = 0;
while( TRUE ) {
// GET DEVICE INFO DATA
ok = SetupDiEnumDeviceInfo( devSet, idev, devData );
if (!ok) break;
// GET ID SIZE
devData->cbSize = sizeof(SP_DEVINFO_DATA);
CM_Get_Device_ID_Size( &IDSize, devData->DevInst, 0 );
// GET DEVICE ID
CM_Get_Device_ID( devData->DevInst, deviceID, 200, 0 );
printf("Device Instance #%d: deviceId = \"%s\"\n", devData->DevInst, deviceID ); // print it
count++;
devIfData = ALLOC( sizeof(SP_DEVICE_INTERFACE_DATA) );
devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
iface = 0; // init index
while ( TRUE ) { // loop over all interfaces in set
// GET DEVICE INTERFACE DATA index=iface
ok = SetupDiEnumDeviceInterfaces(
devSet, // handle to interface set
devData,
devGuid, //&GUID_DEVINTERFACE_USB_DEVICE,
iface, // interface index
devIfData);
if( !ok ) break;
// GET NEEDED BUFFER SIZE
devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
ok = SetupDiGetDeviceInterfaceDetail(
devSet,
devIfData,
NULL,
0,
&needed,
0 );
Details = ALLOC( needed );
Details->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); // IMPORTANT!
// GET DEVICE DETAILS
ok = SetupDiGetDeviceInterfaceDetail(
devSet, // device set
devIfData, // device info data
Details, // detail data
needed, // size of Details
&unused, // unused
NULL ); // device info data (can be NULL)
printf("%s\n", Details->DevicePath); // announce
// OPEN DEVICE
hDev = CreateFile(Details->DevicePath,
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if( hDev != INVALID_HANDLE_VALUE ) {
printf( "Device successfully opened\n" );
// DO SOMETHING WITH DEVICE HANDLE (e.g., DeviceIoControl)...
CloseHandle(hDev);
}
iface++;
}
idev++; // next device
}
printf("\nenumerated %d device interfaces\n", count);
fprintf(stderr, "Press any key to exit...\n");
_getch();
}
Here are some other GUIDs you can use:
static GUID GUID_DEVINTERFACE_DISK =
{ 0x4d36e967L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
static GUID GUID_DEVINTERFACE_USB_DEVICE =
{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER =
{ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27} };
static GUID GUID_DEVINTERFACE_USB_HUB =
{ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
I create an edit window this way:
hwndEdit = CreateWindowEx(
0,
MSFTEDIT_CLASS,
TEXT("EDIT"),
WS_BORDER | WS_CHILD | ES_LEFT,
20,
20,
100,
30,
gHwnd,
NULL,
hInst,
NULL);
I can paste a text using a keyboard shortcut (ctrl + v) but when I use a right mouse button a context menu is not displayed (for a standard edit control it works). I couldn't find any c/c++ example code. How to enable/implement a context menu for a rich edit control ?
It seems that you have created a custom edit window.
You can handle right click on the edit window via checking for WM_CONTEXTMENU in your WndProc.
Grab the handle to the window via the wParam parameter, compare it to your edit window to see if the user right clicked the edit window.
From there, create the popupmenu via CreatePopupMenu().
Insert/Append into the menu via InsertMenu()/AppendMenu().
Finally, call TrackPopupMenu().
Code:
#define IDC_PASTE 102
case WM_CONTEXTMENU:
if ((HWND)wParam == hwndEdit)
{
m_hMenu = CreatePopupMenu();
InsertMenu(m_hMenu, 0, MF_BYCOMMAND | MF_STRING | MF_ENABLED, IDC_PASTE, L"Paste");
TrackPopupMenu(m_hMenu, TPM_TOPALIGN | TPM_LEFTALIGN, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, hWnd, NULL);
}
Next you need to handle the paste message. As can be seen from the problem, your paste shortcut is still useful, so you can use SendInput to simulate paste.
Code:
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDC_PASTE:
{
SetForegroundWindow(hwndEdit);
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
// Press the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Press the "V" key
ip.ki.wVk = 'V';
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the "V" key
ip.ki.wVk = 'V';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
// Release the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
break;
...
I want to save a 'username' and 'ID' in a ComboBox in visual Studio 2010 and WIN32 (c++). Following code is for setting itemdata to combobox:
HWND hCB;
hCB = CreateWindowEx(0, L"COMBOBOX", 0x00,
CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
10, 10, 200, 100,
hWnd, NULL, (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
WCHAR sTemp[256];
for (int i =0 ; i<4 ; i++)
{
wsprintf(sTemp, L"%s%d", L"User", i);
SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM) sTemp);
wsprintf(sTemp, L"%s%d", L"ID", i);
SendMessage(hCB, CB_SETITEMDATA, (WPARAM)i, (LPARAM)sTemp);
}
And code for getting itemdata from combobox is:
WCHAR *sTemp;
for (int i=0; i < 4 ; i++)
{
sTemp = (WCHAR *)SendMessage(hCB, CB_GETITEMDATA, (WPARAM)i, 0);
MessageBox(NULL, sTemp, NULL, MB_OK);
}
The problem is, MessageBox does not show anything.
When I checked the first part of code by adding a CB_GETITEMDATA message for each combobox item, and a MessageBox to show result, I've found that all values of items' itemdata is "ID3", that is the last itemdata in the list.
I think the codes are straightforward, But I can't find what wrong is with my code?
You set the items' data to a pointer to the sTemp temporary string (the same for all items by the way).
When that variable goes out of scope, the pointer becomes invalid, and de-referencing it may cause a crash.
P.S. Just noticed your last comment. If you do it in the same scope, the sTemp contains the last text you wsprintf'ed to it, and every item points to it.
[added]
If you want to add string data to each item in your ComboBox, you need to allocate those strings. For example:
char* p = new char[some_buffer_length];
Then use that p in your call to set item data.
Don't forget to free the memory when you are done by calling:
delete [] p;
for each of your items.
I have some code I've been using to get the current keyboard layout and convert a virtual key code into a string. This works great in most situations, but I'm having trouble with some specific cases. The one that brought this to light is the accent key next to the backspace key on german QWERTZ keyboards. http://en.wikipedia.org/wiki/File:KB_Germany.svg
That key generates the VK code I'd expect kVK_ANSI_Equal but when using a QWERTZ keyboard layout I get no description back. Its ending up as a dead key because its supposed to be composed with another key. Is there any way to catch these cases and do the proper conversion?
My current code is below.
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
if(keyboardLayout)
{
UInt32 deadKeyState = 0;
UniCharCount maxStringLength = 255;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];
OSStatus status = UCKeyTranslate(keyboardLayout,
keyCode, kUCKeyActionDown, 0,
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
if(actualStringLength > 0 && status == noErr)
return [[NSString stringWithCharacters:unicodeString length:(NSInteger)actualStringLength] uppercaseString];
}
That key is a dead key, as you can see if you try it yourself or look at the Keyboard Viewer with the German layout active.
On the Mac, the way to enter a dead key's actual character, without composing it with another character, is to press a space after it. So try that: Turn off kUCKeyTranslateNoDeadKeysBit, and if UCKeyTranslate sets the dead-key state, translate a space after it.
EDIT (added by asker)
Just for future people, here is the fixed code with the right solution.
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
if(keyboardLayout)
{
UInt32 deadKeyState = 0;
UniCharCount maxStringLength = 255;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];
OSStatus status = UCKeyTranslate(keyboardLayout,
keyCode, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
if (actualStringLength == 0 && deadKeyState)
{
status = UCKeyTranslate(keyboardLayout,
kVK_Space, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);
}
if(actualStringLength > 0 && status == noErr)
return [[NSString stringWithCharacters:unicodeString length:(NSUInteger)actualStringLength] uppercaseString];
}