I'm building a c++ tetris game (not c++ .Net). I feel my controls are weird. I want to make it so that when user presses one of the arrow keys, about 10ms of holding it down will start the repeat function windows has. It is set to about 500ms by default, and it is too laggy for my game. How can I set the speed at which it changes from the keydown to the repeat keydown? Not how many times / sec it repeats.
Thanks
*what I want to do is change the repeat delay to short
In control panel in keyboard settings there is repeat rate, how do i set this?
Typically what you would do for this is instead of reacting to the WM_CHAR message that is subject to the normal key repeat settings, you would look for WM_KEYDOWN and WM_KEYUP, and take action based on a timer that you've got running. If you set the timer to fire every 50 ms for example, then you can repeat every 50 ms and still take the first action immediately when you get the WM_KEYDOWN message.
According to MSDN, it also looks like you could use the SystemParametersInfo function, and call use SPI_SETKEYBOARDSPEED, SPI_SETKEYBOARDDELAY.
void Key_Set()
{
DWORD old = 0;
SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &old, 0);
SystemParametersInfo(SPI_SETKEYBOARDDELAY,0, &old, 0);
}
Related
I bought a really nice keyboard (logitech G915) that for whatever inane reason doesn't have a numlock indicator. Thus, I'm using Logitech's lighting SDK to make the functionality myself using the key's rgb backlight.
I have an extremely simple console proof of concept that works:
while (true)
{
if (GetKeyState(VK_NUMLOCK) & 0x1)
LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName::NUM_LOCK, 0, 100, 100);
else
LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName::NUM_LOCK, 0, 0, 0);
}
But I don't think it's good to eat up cpu cycles with a perpetual while loop for such a tiny feature. Should I just have it sleep for time (length suggested?) or is there a way to sleep until the system gets a numlock state change or am I simply going about this wrong?
Additionally, I haven't looked into it yet, but I want to make this a background process or a tray application (doesn't matter, just hidden away) so I guess answers should have that limitation in mind if it is one.
Thanks!
At app startup, use GetAsyncKeyState() instead of GetKeyState() to get the key's current state and update the light accordingly.
Then, use SetWindowsHookEx() to install a global WH_KEYBOARD_LL hook to detect whenever the key is pressed afterwards. On each callback event, use the state information provided by the hook, or start an asynchronous task to get the current key state immediately after your hook callback exits (as GetAsyncKeyState() has not been updated yet when the callback is called), and then update the light accordingly.
Alternatively, use the Raw Input API to monitor the keyboard and receive WM_INPUT window messages on each key press. And then get the key's current state and update the light accordingly.
I am trying to create a code which will detect if the mouse button has been pressed. So far i have a code which will detect if the button has been pressed once. But it isn't letting me check if the button was continuously pressed. For e.g left mouse button pressed, this will start a timer, after 0.5 seconds it will check again and if it is still down output something.
I want to set it up like this
while (true)
{
if (GetAsyncKeyState(VK_LBUTTON) & (0x8000 != 0))
{
cout << ("left button pressed") << endl;
Sleep(500);
if (GetAsyncKeyState(VK_LBUTTON) & (0x8000 != 0))
{
cout << ("Left button held down") << endl;
}
}
}
However, it does not work, it only outputs the second statement if i double click in quick succession.
Determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.
The msdn website says that. Does this mean i should check if it is UP after the time to get the result i want.
GetAsyncKeyState just tells you the state right now, it should not be used to monitor possible changes over time!
If you want to track the mouse no matter which application is receiving the input then you should use SetWindowsHookEx to install a low-level mouse hook.
If you only care about mouse events in your own window then it would be better to track WM_LBUTTON* mouse messages as suggested in the other answer.
In response to WM_LBUTTONDOWN you set a global flag to true and start the timer. In response to WM_LBUTTONUP you set it to false and stop the timer. If the timer fires and the flag is true then perform your desired task.
If you're trying to implement this in WINAPI GUI application, here is your answer - write the first timestamp on WM_LBUTTONDOWN, write the second on WM_LBUTTONUP, and calculate the elapsed time you need. What is actually better - it will only catch messages that will come into YOUR application window, and won't catch other apps' key presses as you could do with GetAsyncKeyState.
UPDATE: Anyway, getting user-generated data(like clicks, key presses, etc) to work is way better using the standard windows message handling(as it is event-based, more natural to the programmer) instead of checking the state of an object once per a period of time - you can possibly miss the required event altogether. It looks like you're trying to solve the XY problem.
UPDATE2: Here is a nice tutorial of how to do it properly.
The scenario is the following:
When my active Widget is a QSpinBox, I can change the value by clicking or holding a click on an arrow of the box or by pressing or holding Page Up/Page Down/ ▲ / ▼ .
The problem is, that i have some hardware communications on valueChanged() which needs some milliseconds.
While i permascroll (mouse) or hold the click on a boxes arrow, this isn't a problem, because the scroll seems to be slower here (acceleration off), but when i use my keyboard (acceleration also off), the scrollspeed is much faster which causes the timing problem. The application slows down, then freezes for some seconds until the event queue is finished.
I need to allow using the keyboard input (including holding the keyboard key), so I'd like to know if there is a way to slow down key repeat rate of arrow/page up/down.
Actually I'm triggering a 200 msec oneshot timer on value changed, which passes the spinbox value on timeout. The timer will only be triggered if it's not running. That means when i change the value it will always have a 200 msec delay and the update frequency can only be 5 updates/sec or slower. It actually works, but I'd really like to improve this by reducing the key repeat rate somehow.
Ok no I see problem. Here problem is keyboard repaying character on button hold.
To overcome this without direct interaction with keyboard, I would try use event filter, observe key press events and reject some of them if then are arriving to fast.
Your device communication subsystem has two states: busy and available. When it's busy, you should schedule an update of a particular variable in your target, but don't execute it just yet. When the previous communications are done, and the subsystem is available, it should pick up any outstanding changes and propagate them.
I have a transparent window (WS_EX_TRANSPARENT) floating topmost.
Whenever there is a mouse move (anywhere on the screen) or keyboard stroke, it needs to display the related info (e.g. mouse position).
Is it possible to capture mouse/keyboard activities without using a global hook? Anti-virus software almost always triggers false alarms for the use of global
hooks.
Any idea greatly appreciated.
I guess, GetAsyncKeyState and GetCursorPos might help. You probably can have a thread calling these functions every 300-500 msec, and posting a message to your main thread.
You could register for receiving raw input messages via RegisterRawInputDevices. Have a look over here, there are some links in the accepted answer of RRUZ, one points to a C# implementation. This works with window messages, no hooks involved.
(With this method you also get information about the specific device the input came from, so you could distinguish between multiple keyboards. That's where most questions having "use RegisterRawInputDevices" as answer are heading. But you can also use it to just capture the input, not caring about the source.)
You can get notified of keyboard/mouse activity (GetLastInputInfo), and I am fairly certain you can get the cursor position (GetMouseMovePointsEx). If you do not need the actual keyboard strokes, then that should do it. If you do, I do not think it can be done...
LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
UInt32 lastInputTick = lastInputInfo.dwTime;
return Environment.TickCount - (Int32)lastInputInfo.dwTime
This code (C#) return the inactivity time (keyboard and mouse both). So you can have the time since the user is inactive.
Basically, when one types, a keydown event happens. If the key is held for more than a certain time (~1 sec) then the key is repeatedly pressed until keyup hapens. I would like to change the time it takes for the key to be automatically repressed in my c++ application. How can this be done?
Thanks
The speed at which a keypress becomes automatically recurring is controlled by Windows.
If you want to manipulate automatic recurrences of key-presses, it might be more advantageous to poll for the state of the key rather than waiting for the keydown event. It depends on how responsive you need your application to be.
This article may help you in figuring out how to query for key states: link
You can use the SystemParametersInfo function to change the keyboard delay and refresh rate, as described in this newsgroup thread.
A simple way to handle this is to establish a buffer of time around the OnKeyDown event. Setup a timer that determines whether control passes to a secondary event handler. If the timer has expired, then it is OK to pass control. If the timer hasn't expired, then you should return and leave the event unhandled. Start the timer right before passing control to your secondary event handler.
void KeyDownHandler(...)
{
// ...
if (TimeLeft() <= 0)
{
StartTimer();
handleKeyDown();
}
}
A timer is better than counting duplicate events because you can't assume that a given system will have the same repeat rate set as yours.
I agree with Stuart that polling for the state of the key might work better. It depends upon what you are trying to accomplish.
Also note that this type of behavior might be highly annoying to your user - why do you need to ignore duplicates?
You might be able to tap into a Windows API but this might be controlled by the OS. Not sure...
You might need to manually draw a command such as to simulate a key press multiple times after a set number of seconds after the key has been pressed.
Use SetKeySpeed api (Kernel)