|
Hi,
What is the recommended way to listen for a key press globally? At first, adding an infinite loop came to mind (for(;;), or while(true)), but these are bad choices, as they eat a lot of CPU, and adding sleep will cause to lose some of the key press events.
I want to make it to check any key (or key combination), to see what is pressed on Windows OS.
|
|
|
|
|
It depends if "globally" applies to the system (user session) or an application. For an application it depends on the type (console or GUI). With GUI applications it depends also if you want to catch all / multiple or only a single / few key combinations.
The most "global" method is hooking keyboard events with SetWindowsHookEx function (Windows)[^].
For application level handling see About Keyboard Input | Microsoft Docs[^] and follow the links.
To handle only a few specific keyboard events for GUI applications use Accelerators (Hotkeys) processed by the main window of the application.
|
|
|
|
|
This function will be called from Java, which app will be minimized, or maybe running in the background. The app won't be focused, so yes, I need it for the entire user session, even if another application is focused, I want it to still register the key press and do something in case a key I randomly choose is pressed. I will make some profiles: profile 1 has key "A", profile 2 has key "CTRL + A", those combinations will be changeable.
|
|
|
|
|
You might have a look at the AutoIt Scripting Language. I guess you can use that to do what you want.
In any case you should not use a key combination that is used by Windows itself or common applications. See Keyboard shortcuts in Windows for a list of combinations that should not be redirected.
|
|
|
|
|
Valentinor wrote: I want it to still register the key press and do something in case a key I randomly choose is pressed. I will make some profiles: profile 1 has key "A", profile 2 has key "CTRL + A",
Sounds like you are looking for the RegisterHotKey function[^].
Best Wishes,
-David Delaune
|
|
|
|
|
For what I have now, I'll use only one key, and I used "SetWindowsHookEx". Is it possible to use that for a combination of keys? I don't need it in this application, but in future I will need it. All the examples I saw on google were with only 1 key, or using the mouse. If you can use it for key combination, can it be used to combine 4-5 keys? Yes, it is hard to press that many at a time, but you can map an extra key from the keyboard to press all of them at the same time.
Thanks for you help!
|
|
|
|
|
With key combinations I meant a combination of a single key while also Shift, Ctrl, and or Alt are down.
A combination of multiple keystrokes makes no sense because that can't be "eaten" (the initial strokes has to be passed and will be processed by the window having the focus).
It is still unclear what you finally want to do. If is not a personal project, be very careful what you are doing. Such global "features" might interfere with the active application which is a "don't do it".
|
|
|
|
|
So, let me reformulate my last statement.
What is the alternative of SetWindowsHookEx, for a combination of keys, by checking if Ctrl and/or Alt and/or Shift is down + any other key (different from Windows combinations)?
For a single button (keyboard or mouse) it is great, but from what I've seen, it can't be used to check at the same time if any Ctrl, Alt, Shift is down.
|
|
|
|
|
The status of the Alt key is passed to the hook callback. The status of the Shift and Ctrl keys (and any other key) can be determined with the GetKeyState function (Windows)[^].
|
|
|
|
|
|
Hello,
I have registered USB serial devices for notification and get a device arrival & removal notice now in OnDeviceChange. However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out. I have browsed countless examples where the code proceeds to extract for instance a VID/PID from the string. What am I doing wrong? The examples also give me one character. I am using windows 10 & VS2017.
I have even reserved a larger buffer for notification registration to fit in the full dbcc_name string. Nothing helps, just get that one character. I have also tried the WideCharToMultibyte and then instead of a Chinese character I get a single question mark. Please advise.
|
|
|
|
|
Quote: I am using windows 10 & VS2017. Yes, but we cannot guess what code you are using. Please edit your question and provide full details.t
|
|
|
|
|
I am using MFC & C++. This code is missing the WideCharToMultibyte conversion which didn't help one bit. I am using this document as refrence: http://www.ftdichip.com/Support/Documents/AppNotes/AN_152_Detecting_USB_%20Device_Insertion_and_Removal.pdf
BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);
PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)dwPtrData;
if(b != NULL)
{
CString Msg;
Msg.Format(L"%s",b->dbcc_name);
MessageBox(Msg);
}
switch (nEventType)
{
case DBT_DEVICEARRIVAL:
if(hComm==INVALID_HANDLE_VALUE) DeviceInit();
break;
case DBT_DEVICEREMOVECOMPLETE:
ClosePort();
break;
}
return bReturn;
}
|
|
|
|
|
Use your debugger to see exactly what is returned in Dbcc_name . The code looks correct but the actual data may be the problem.
|
|
|
|
|
Yeah, there is nothing more with my debugger than is in the MessageBox added for debugging purposes.
|
|
|
|
|
Member 13899178 wrote: However, always when I try to print out the dbcc_name, its length is one wide character (as defined in the structure documentation) and nothing more prints out.
...
Please advise. Please provide the code you are using to do the printing.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
The handler is called multiple times for a single event with different parameters, and also upon specific device changes even when not registered. So you have to check always if the device type matches and cast then to the corresponding broadcast structure (because all structures have the common _DEV_BROADCAST_HDR | Microsoft Docs[^] header, casting can be done initially when checking for the matching type).
So your code should look like (based on your code snippet posted in the above sub thread):
const GUID CTesterDlg::GUID_DEVINTERFACE_FTDI_D2XX =
{ 0x219D0508, 0x57A8, 0x4FF5, { 0x97, 0xA1, 0xBD, 0x86, 0x58, 0x7C, 0x6C, 0x7E }};
BOOL CTesterDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwPtrData)
{
BOOL bReturn = CWnd::OnDeviceChange(nEventType, dwPtrData);
PDEV_BROADCAST_DEVICEINTERFACE b = reinterpret_cast<PDEV_BROADCAST_DEVICEINTERFACE>(dwPtrData);
if (b &&
b->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE &&
b->dbcc_classguid == GUID_DEVINTERFACE_FTDI_D2XX)
{
}
return bReturn;
} Regarding the encoding of the name, see _DEV_BROADCAST_DEVICEINTERFACE_A | Microsoft Docs[^]:
Quote: When this structure is returned to a window through the WM_DEVICECHANGE message, the dbcc_name string is converted to ANSI as appropriate. That means you will get an ANSI string with ANSI builds and a Unicode string with Unicode builds when having called RegisterDeviceNotification() .
Portions of the above (like the GUID) are from some testing code I have written in 2012 where I have logged the name using
App()->Log(TRACE_LOG_DEBUG,
_T("Device %s has been %s"),
pDev->dbcc_name,
nEventType == DBT_DEVICEARRIVAL ? _T("added") : _T("removed")); As far as I remember, the name was displayed properly .
|
|
|
|
|
All valid points, thank you. The note about device interface was good and got me on the right track. I was blind to that part as the code seemed to work and returned something. The problem seems to have been that I have registered to receive messages to my Hwnd from GUID_DEVCLASS_PORTS which is not an interface class, now I changed to GUID_DEVINTERFACE_USB_DEVICE and I get a proper string with VID & PID. Problem solved, thanks!
|
|
|
|
|
Fine to hear that the problem is solved.
If you don't need the VID and PID but just want to be informed of the plugin / -out for the virtual COM ports, there is even no need to register. Then just check for DBT_DEVTYP_PORT events. They are one of the always signaled events (as already mentioned):
PDEV_BROADCAST_PORT pPort = reinterpret_cast<PDEV_BROADCAST_PORT>(dwData);
if (pPort && DBT_DEVTYP_PORT == pPort->dbcp_devicetype)
{
}
|
|
|
|
|
Thanks for the tip. You've been very helpful.
|
|
|
|
|
Hi,
What should I use to change the display's gamma? I tried looking on google, but I don't see anywhere how to do it. Can you give me a link, or an example of changing the value? I need it to be able to change it when I want and faster, I could go each time in "Display Color Calibration" and change it from there, but that takes time, and I can't add a key shortcut to certain values.
Just as a note, I want to change gamma, not brightness.
modified 10-Jul-18 7:10am.
|
|
|
|
|
|
I tried looking at "Windows Graphics Device Interface" and "Microsoft Direct3D 9’s" but without an example to understand, I got lost in the parameters types they ask. I would like to make it kinda like the slider from "Display Color Calibration" (Calibrate Display Color, as you find it in search box), the difference will be that I will add a function so you can add some default key shortcuts to certain gamma values.
I'm used to code in Java, but there is no way to change gamma using that.
|
|
|
|
|
You have to generate a table that is passed to the setter function.
That is what the calibration does too: It generates the table according to the slider position.
But I do't know the formula (and the range used by the calibration tool). If you only need a few selections, you can use the getter function to read the table for different calibration settings.
|
|
|
|
|
I found the following code in a post, and this note but I didn't figured out what is the min and the max value the float factor should have. Is this the formula you were talking about?
Quote: To change gamma, cycle into ramp buffer and change RGB color where Gamma is the float factor.
WORD ramp[256*3];
for( int i=0; i<256; i++ ) {
ramp[i+0] = ramp[i+256] = ramp[i+512] =
(WORD)min(65535, max(0, pow((i+1) / 256.0, Gamma) * 65535 + 0.5));
}
SetDeviceGammaRamp(::GetDC(NULL), ramp);
I got it from this article (it does contain the source code, but the GUI code is very different from JavaFX):
Gamma correction slider[^]
|
|
|
|