GetKeyState doesn't work in Windows 2000 (C++) - c++

I have just tested my DirectX game on a Windows 2000 SP4 system but it won't receive any mouse clicks!
This is how I check for mouse clicks :
unsigned int mButtons = 0;
if (GetKeyState(VK_LBUTTON) < 0) mButtons |= HIDBoss::MOUSE_LEFT;
if (GetKeyState(VK_RBUTTON) < 0) mButtons |= HIDBoss::MOUSE_RIGHT;
if (GetKeyState(VK_MBUTTON) < 0) mButtons |= HIDBoss::MOUSE_MIDDLE;
if (GetKeyState(VK_XBUTTON1) < 0) mButtons |= HIDBoss::MOUSE_4;
if (GetKeyState(VK_XBUTTON2) < 0) mButtons |= HIDBoss::MOUSE_5;
etc...
This code works perfectly on Windows 7 and XP 32/64bit.
The problem is fixed if I use the OIS library instead - which uses DirectX input - but it contains a few bugs so I would rather avoid it.
Can anyone suggest why GetKeyState won't work on W2K? Could it be because the system hasn't been updated - through Windows Update - for the last couple of years..?
Thank you for your time,
Bill

I'm not sure why it doesn't work but I'd recommend using GetAsyncKeyState instead.
Edit: In answer to your comment. It is merely a suggestion but its, equally, pretty easy to find out if the buttons are swapped by calling:
GetSystemMetrics(SM_SWAPBUTTON)
Your big problem arises from the fact that GetKeyState is not supposed to return a value for mouse buttons only keyboard buttons. the fact it DOES work in some OSs is not something you are supposed to be able to rely on across all OSs.
An application calls GetKeyState in
response to a keyboard-input message.
This function retrieves the state of
the key when the input message was
generated.
Its worth noting that it makes specific mention of calling it in response to a keyboard-input message (ie WM_KEY[UP/DOWN]). Equally there is no mention that this should work for mice. As such you really are better off just using GetAsyncKeyState...

Related

ENABLE_VIRTUAL_TERMINAL_PROCESSING and DISABLE_NEWLINE_AUTO_RETURN failing

The point was to make this little multiplayer game in the terminal, applying some basic graphics concepts to get a grasp on how it works and the maths behind it.
Note I wish to do this for fun and I am fully aware there are way better alternatives out there to using a terminal.
I'd need a console I could write to, so the point was to remove scroll bars and have the whole buffer printed to the screen.
But because of the carriage return when characters get written to the end of the previous line:
this would look overall ugly:
After trying for about 3 hours to get this working through SetConsoleMode, I asked about it in a discord.
The answer I got was this:
void main( )
{
auto h = GetStdHandle( STD_OUTPUT_HANDLE );
DWORD mode = 0;
GetConsoleMode( h, &mode );
mode |= DISABLE_NEWLINE_AUTO_RETURN | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
puts( SetConsoleMode( h, mode ) ? "Win" : "Loss" );
char * buf = new char[ 200*2 ];
memset( buf, 0, 200*2 );
memset( buf, 'A', 120*2 );
std::cout << ( buf );
getchar( );
}
with this result:
At first I tried adapting it to my project, which failed.
Then I got frustrated and ended up creating a new project into which I just copy pasted the working code.
And you guessed it, it doesn't work.
Now I've tried quite a bit of stuff, I've changed my program from unicode to ansi and back, and done mode = DISABLE_NEWLINE_AUTO_RETURN | ENABLE_VIRTUAL_TERMINAL_PROCESSING, mode |= DISABLE_NEWLINE_AUTO_RETURN | ENABLE_VIRTUAL_TERMINAL_PROCESSING, and each individually with and without |with no success.
Given it's error 87 which means bad parameter, I even tried putting the exact value from GetConsoleMode to see if it was the handle, but since it worked we can assume it's not the handle's problem.
Basically code that works on another machine doesn't work on mine.
The other machine was windows 10 mine's 8.1 both 64.
On both machines the value gotten off GetConsoleMode the first time is 3, which means ENABLE_PROCESSED_OUTPUT and ENABLE_WRAP_AT_EOL_OUTPUT.
The windows SDK version on my project is 10.0.15063.0, with a platform toolset of Visual Studio 2017 (v141).
I've been at this all day with no success. Now it wouldn't be the first time I read over some important detail, but I've been going through documentation and nothing mentions the failiure of SetConsoleMode using ENABLE_VIRTUAL_TERMINAL_PROCESSING.
As far as I can tell I'm doing it correctly based on the Docs
What should I be doing that I am not?
Sorry for any spelling/grammar mistakes that might have gone noticed and thank you for your time.
Virtual terminal mode is available in the console starting with Windows 10.0.10586. It's not supported by the OS if setting the mode fails with ERROR_INVALID_PARAMETER (87). Also, it's only implemented in the new console. With the legacy console selected in Windows 10, enabling VT mode may succeed, but it won't actually enable VT support.
The failure case is mistakenly documented as "SetConsoleMode returning with STATUS_INVALID_PARAMETER" (0xC000000D) in the Enabling Virtual Terminal Processing example. It seems the writer overlooked that the kernel status code that's returned by the NtDeviceIoControlFile system call (in Windows 8+) gets translated to failing the SetConsoleMode call and translating the status code to a Windows API error code.

Debounce user input in c++

we have a project on school, coding a volleyball - match as console application.
We should make input-output for teams and score etc, and bind keys to Team1-score+1, Team2-score-1 etc. That's fine. We use getch() to bind these keys.
My problem: If you for example press R and R is Team1-score+1 and hold this key, it will continue adding the score+1, and we should stop that so you need to press R again if you want to add another point.
I didn't find this solution anywhere!
Can anyone give an example how to fix it?
I am new on coding so I am inexperienced.
Thanks for help guys!
EDIT: I am using Windows 10, important part of my code:
while (true)
{
_kbhit();
char L = _getch();
if (L == 114)
{
score1 = score1 + 1;
}
else if (L == 99)
{
score1 = score1 - 1;
}
else if (L == 117)
{
score2 = score2 + 1;
}
else if (L == 110)
{
score2 = score2 - 1;
}
else if (L == 113)
{
L=="number" is the ascii-code for buttons r,u,c,n,q
getch() operates on stdio which effectively is just a bytestream coming/going from/into the OS. It doesn't have the concept of "key presses/releases". When you keep a key pressed the OS will start to autorepeat the pressed character. To make things worse for your use case, if you keep a key pressed, and then press another key, the key repeats of the first will cease.
Now there are ways to get raw key down/up events, but these involve OS specific programming interfaces; you didn't tell us which OS you're using, so it's a bit of guesswork there. Doing what you want to do in the console is somewhat possible, but it's awkward to use. For Windows see C++ console keyboard events, for Linux see Receiving key press and key release events in Linux terminal applications?
However I strongly suggest you don't even try to implement all that OS level key event interfacing yourself, and instead make use of a cross platform library that offers a framework for doing exactly what you want to do there. One of the most widely used frameworks these days is SDL http://libsdl.org/ – it will move you out of the console though (when it comes to games: good riddance, except if you're working on a rouge-like game).
If you are using the console then most operating systems will wait a second after you press a key before registering that key press again. You can try it now: press a key on your keyboard and see what the response is.
Making sure someone doesn't accidentally press a key twice is a problem that the OS takes care of, because otherwise every application taking keyboard input would need to code their own solution to the problem.
If you want to go further than what the OS does, you can use a timer in your program with the chrono library, and wait n seconds before allowing input to be registered again.

How would one record player kills in CS:GO using an external program?

I have been trying to write a small program that runs behind Counter-Strike: Global Offensive. The program must be completely external, as there is no way to access live match data or the API during a competitive ranked match. So far, the best approach I could find is as follows:
case WM_TIMER:
COLORREF curColor, safetyColor;
for(int a = 1750;a < 1830;a++)
for (int b = 75;b < 100;b++)
{
curColor = GetPixel(csgoDC, a, b);
safetyColor = GetPixel(csgoDC, 1856, 1060);
if (GetRValue(curColor) == 255 && GetGValue(curColor) == 255 && GetBValue(curColor) == 255 && GetRValue(safetyColor) != 255)
PlaySound(_T("C:\\headshot.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
break;
This is triggered by a timer. It does not work reliably, and I am fairly certain it won't work at all in fullscreen mode (Hard to test when it isn't reliable to begin with). The indices in the nested for loop correspond to the place on the screen where the killfeed shows up. Here is an example of the UI (From Google)
Screenshot
Note that I am not specifically going for a pixel-based approach; this is just the only solution I could think of.
A much more work intensive way of doing this would be to get runtime information from your machine, i.e. variables and associated values in memory. This would require at least to some degree reverse engineering of the CS:GO client code. But, if you could manage it, I imagine it would be the most reliable way of determining the information you desire. (Be wary of a ban-hammer to the face though.)

SDL_GetRelativeMouseState strange behaviour

I have an application in SDL 2.0.3 that enters relative mouse mode before entering the main game loop. In addition, function mouse_input is called in each step:
int mdltx = 0, mdlty = 0;
void mouse_input () {
auto r = SDL_GetRelativeMouseState(&mdltx, &mdlty);
if (mdltx != 0 || mdlty != 0)
cout << "(" << mdltx << "," << mdlty << ")" << endl;
// Update mouse key presses
mpul = !!(r&SDL_BUTTON(1)) | ((!!(r&SDL_BUTTON(3)))<<1);
}
According to the documentation of SDL_GetRelativeMouseState:
(...) x and y are set to the mouse deltas since the last call to SDL_GetRelativeMouseState() or since event initialization.
I've added the output lines for debugging purposes, because the resulting effect in the application was very awkward. It turns out that each time I move the mouse (and only when I move it), the console prints values in an unreasonable range. Below is a sample from doing simple mouse movements. The affected axis seems correct (moving horizontally will set mdlty to 0 and moving vertically will set mdltx to 0), but the numbers can get much higher than the screen resolution, and all of them are positive, regardless of the direction I move the mouse.
(342,216)
(47290,0)
(23696,0)
(23730,0)
(23764,0)
(23799,0)
(71190,0)
(117970,83397)
(23491,41802)
(23457,0)
(23423,83811)
(0,41871)
(23389,208322)
(23355,82847)
(0,41320)
(46812,0)
I have been looking around the web for people having the same problem, without any success.
Also note that this application was previously made for SDL 1, relying on SDL_GetMouseState and SDL_WarpMouse, but the latter function does not seem to do anything in some platforms. I'm working on the application under an Arch Linux + LXDE installation, which seems to simply ignore the mouse warp. This is the same machine where this other strange behaviour is happening.
The question is: why is this happening and how can I fix it with compatibility in mind, while keeping the advantages of having relative mouse mode? I even wonder if it could be an issue within SDL itself.
For anyone else struggling with this problem, it might help to set:
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
SDL_SetRelativeMouseMode(SDL_TRUE);
This seems to give you relative mouse-output, where the center of the screen is (0,0).
However for me it doesn't currently reset the Cursor-coordinates properly, so while every frame resets this to (0,0), it jumps straight to the previous coord += movement.
This is a lot better than the alternative though, it seems.
The same code is working in a different machine, so this seems to be a bug. And it seems that some people found it too, with a broader range of misbehaviours than the one mentioned.
https://bugzilla.libsdl.org/show_bug.cgi?id=2150

Using SetKeyboardState along with GetKeyboardState in C++

I don't know how to write a good question here, but, basically, does anyone know where I can possibly find some C++ source code using these to actually set keyboard state? For some reason using it the way MSDN does on Windows 7 doesn't do...anything at all.
Basic code:
PBYTE keyState;
GetKeyboardState(keyState);
...
// Later on when I need to set the keyboard state (key pressed etc) back to original:
SetKeyboardState(keyState);
and ... nothing happens :(
From:
http://www.gamedev.net/community/forums/topic.asp?topic_id=43463
First off, GetKeyboardState() would be the wrong function to use because as Windows has a chance to process keyboard messages (whether you want it too or not) it updates the results of the keyboard's state for the next call to GetKeyboardState().
Here's a little function that I use to get the status of the keyboard's keys. Be carefull though, depending on how fast your main loop is, it may cause problems if you aren't expecting it.
You need to keep track of whether or not a specific key was pressed the last time you called the ReadKeyboard() function. If your loop polls the keyboard 30 times a second, then pressing a key once probably causes the key to be flagged 3 or 4 calls in a row. Rather confusing sometimes. Just thought I'd mention it.
void ReadKeyboard( char* keys )
{
for (int x = 0; x < 256; x++)
keys[x] = (char) (GetAsyncKeyState(x) >> 8);
}