C++ GetAsyncKeyState alternative - c++

I was using Windows.h library's GetAsyncKeyState function to define which key was pushed on the keyboard . Here is the program which returns the int value of the pushed key for example.
#include <iostream>
#include <windows.h>
using namespace std;
int main (){
char i;
for(i=8;i<190;i++){
if(GetAsyncKeyState(i)== -32767){
cout<<int (i)<<endl;
}
}
return 0;
}
But now I am trying to make an openGl very simple game and this function appeared to be very slow for that . Is there a function which will not need a for cycle 180 times and an if statement .
Thanks

You're trying to make a opengl game, so you're probably going to use GLFW. If that's the case then you can get away with using glfwGetKey() as such:
if (glfwGetKey(GLFW_KEY_UP) == GLFW_PRESS) {...}
if (glfwGetKey(GLFW_KEY_DOWN) == GLFW_PRESS) {...}
That method is nicely explained in tutorial 6 from opengl-tutorial.org. But you should probably start from the first tutorial of beginners tutorials and later intermediate tutorials.
If you're going to make the win32 window by yourself you can listen for the WM_KEYDOWN or WM_KEYUP messages and get the virtual key code from wparam. After a minute of googling I found you these two sites for examples here and here.

You can use a combination of PeekMessage and TranslateMessage and DispatchMessage. It's quite simple to register your own windows procedure (WNDPROC) to process input messages from windows.
MSG msg;
while(PeekMessage( &msg, NULL, 0, 0 ))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
The DispatchMessage function calls your registered procedure. See: this for more info.

Related

does not go inside the Windows GetMessage loop on console application

I want to detect keypress in C++ and i need to use Windows System Call. So, i did some research and this is what i got using Hooks and Message:
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
switch (wParam) {
case WM_KEYDOWN:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
char c = char(MapVirtualKey(p->vkCode, MAPVK_VK_TO_CHAR));
cout << c << endl;
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
int main() {
HHOOK HKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
cout << "bRet = " << bRet << endl; // I want to do something here, but the program doesn't seem to go in here
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(HKeyboard);
return 0;
}
My question is why my program doesn't go inside the loop(and instead stuck on GetMessage function)? I need it to set conditions to terminate after some seconds, so where should i put the conditions? I know the GetMessage function reads Message, but when i press keys on my keyboard it still not going in and the callback function works just fine.
The events are posted to the active window. Console windows are owned by the console subsystem, csrss.exe, and it receives the events, then translates them to characters and puts them in the console object which is your application's stdin.
If you want to process events the Win32 GUI way, you should use a Win32 window (e.g. RegisterClass and CreateWindow), not a console window.
If you just want the callbacks to work for a certain period of time, you can use an alertable wait such as SleepEx or MsgWaitForMultipleObjects, which accept a timeout.
That's not surprising, there aren't really any messages on your thread queue and you have no window so there's no window queue either.
If you want to play with values returned from your hook, put the code in the hook callback function.
I should warn you that hooks like these won't work in console applications since the console window resides in another process. Also, if you look at the MSDN page for SetWindowsHookEx, you'll see that WH_KEYBOARD_LL is a global hook only, ie you have to put your hook handler in a DLL library and inject the hook in the other applications. Then you have to handle the 32/64 bit issue yourself.
And as a last note, when you say cout << c; in your handler, that would be printing in the process's output file handle, not your own.

Task Manager's "Switch to" doesn't work properly on DirectX 8 application on windows 7

Task Manager's "Switch to" doesn't work properly with DirectX 8 application on Windows 7
Hi! I have very specific and strange problem.
My game is using DirectX 8. Main cycle looked something like this:
while( WM_QUIT != msg.message )
{
if(IsIconic(m_hWnd))
{
if(GetMessage( &msg, NULL, 0U, 0U))
{
// Translate and dispatch the message
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
// Use PeekMessage() if the app is active, so we can use idle time to
// render the scene. Else, use GetMessage() to avoid eating CPU time.
if(PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE))
{
// Translate and dispatch the message
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
m_pGame->Render();
}
}
}
The Render function has some basic functionality like this:
void CGame::Render()
{
//...
HRESULT hr = m_pD3DDevice->TestCooperativeLevel();
if(hr == D3DERR_DEVICENOTRESET)
Reset();
else if( SUCCEEDED( hr ) )
{
// Render
//...
}
//...
}
In fullscreen, when application loses focus (by Alt+Tab, Windows Button, Ctrl+Shift+Esc etc.) it just minimizes, stay in task bar and doesn't uses any resources. No problem. Then I can activate it by using Alt+Tab or clicking on task bar icon. Also works perfectly: application activates and Resets Direct3D device in fullscreen.
But using Task Manager's “Switch to” feature leads to strange thing: My application window unfolds and then suddenly minimizes again!
I tried to analyze messages input. It's look like my window receives deactivation massage just after the activation message. Like Task Manager activates my application and deactivates it again.
First I tried
LockSetForegroundWindow(LSFW_LOCK);
It helps on machines with slow motherboard integrated GPU, but strangely it doesn't help on machines with faster GPUs. Some times it works. But most of the time it doesn't.
Then I tried SetForegroundWindow to force-bring my window to foreground:
DWORD dwTimeout;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &dwTimeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0);
SetForegroundWindow(hWindow);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)dwTimeout, 0);
LockSetForegroundWindow(LSFW_LOCK);
It doesn't help, so I tried another hack:
HWND hCurrWnd;
int iMyTID;
int iCurrTID;
hCurrWnd = GetForegroundWindow();
iMyTID = GetCurrentThreadId();
iCurrTID = GetWindowThreadProcessId(hCurrWnd,0);
AttachThreadInput(iMyTID, iCurrTID, TRUE);
SetForegroundWindow(hWindow);
AttachThreadInput(iMyTID, iCurrTID, FALSE);
LockSetForegroundWindow(LSFW_LOCK);
Not working.
Why the Task Managers acts so strangely? What else can I do?
///////////////////////////////////////////////////
UPPDATE+SOLUTION.
So, I solve the problem, though I didn't understand completely why it's works.
I find out two solutions. Each of them works for particular set of computers. One for older and weaker computers (or older OS like WindowsXP), and another for more advanced computers with faster videocards and Windows 7. I managed to unite this two solutions and now my game responds to "Switch to" without problems.
For older and weaker computers all I just place LockSetForegroundWindow(LSFW_LOCK) in key places like before main loop start and in WM_ACTIVATE message.
For faster computers I just need to resize my window (made it small) and call for WindowsUpdate when it deactivates. When my window activates again device resets and during device Reset I just restore my window's fullscreen size automatically.
LRESULT APIENTRY WndProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_ACTIVATE:
if((LOWORD(wParam)==WA_ACTIVE)||(LOWORD(wParam)==WA_CLICKACTIVE))
{
if(m_pGame->m_bFullScreen)
LockSetForegroundWindow(LSFW_LOCK);
break;
}
else
{
if(m_pGame->m_bFullScreen)
{
SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,
128,64,SWP_NOMOVE);
UpdateWindow(hWnd);
};
break;
};
//...
}
}

Creating Responsive Windows winapi c++

I am just learning to create a gui using the winapi, but i have run into an issue. I can create a window like this
#include "stdafx.h"
#include <windows.h>
int main()
{
HWND hwnd = CreateWindow(L"STATIC",NULL,WS_VISIBLE|WS_SYSMENU|WS_CAPTION,0,0,600,600,NULL,NULL,NULL,NULL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_gettch();
}
But the windows will not close when the close button is clicked, and the window can not be dragged around or moved. I was wondering how i would enable these features of the window.
Static windows are not there for normal windows, you should try and look up how to register and handle your own class with RegisterWindowEx then use the same class name to create a window. You have to have your own window procedure in order to handle messages.
All window classes registered by the system run their own default window procudure and as far as I know none of them handle WM_CLOSE ( that is the close button ) this is why you can't close it.
For you main windows always use something like WS_OVERLAPPEDWINDOW so it'll be clear if it's okay or not and from that eliminate the flags you don't need.
How you set it up :
WNDCLASSEX wndcls;
HWND hMainWnd;
// Register your own window class
ZeroMemory(&wndcls,sizeof(WNDCLASSEX));
wndcls.cbSize=sizeof(WNDCLASSEX);
wndcls.style=CS_VREDRAW+CS_HREDRAW;
wndcls.lpfnWndProc=&appWndFunc;
wndcls.hInstance=hInstance;
wndcls.hIcon=hMainIcon; // or just LoadIcon(hInstance,MAKEINTRESOURCE(IDI_MAIN_ICON))
wndcls.hIconSm=hMainIcon;
wndcls.hCursor=LoadCursor((HINSTANCE)NULL,IDC_ARROW);
wndcls.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE;
wndcls.lpszClassName="myWndClass";
if (RegisterClassEx(&wndcls)==0)
{
// failed to register class name
return false;
}
// Create window with your own class
hMainWnd=CreateWindowEx(0,\
"myWndClass","widnow title",\
WS_OVERLAPPEDWINDOW|WS_VISIBLE,\
0,\
0,\
250,\
250,\
hMainWnd,NULL,hInstance,NULL);
if (hMainWnd==(HWND)NULL)
{
// failed to create main window
return false;
}
Then your main loop :
bool bAppMainLoop=false
while(!bAppMainLoop)
{
WaitMessage();
while(PeekMessage(&emsg,NULL,0,0,PM_NOREMOVE))
{
if(GetMessage(&emsg,NULL,0,0)==0)
{
bAppMainLoop=true;
break;
}
TranslateMessage(&emsg);
DispatchMessage(&emsg);
}
}
This is a bit more than usual setup, so let me explain , in order to not burn CPU, you wait for a message with WaitMessage, it'll block until something happens, like move window, click, paint etc. PeekMessage will return true if there is a message so calling it in a while loop will make sure it drains the message quene, GetMessage will obtain the message if it returns 0 it means that your app called the PostQuitMessage(0) so a WM_QUIT arrived was found in the message loop that means it's time to break out from the message loop. The rest Translate and Dispatch does what it name says.
Finally you need your own window procedure :
LRESULT CALLBACK appWndFunc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if (uMsg==WM_CLOSE)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
DefWindowProc is essential that handles all commonly occurring messages from the system, thus you don't need to handle those here. You simply respond to the WM_CLOSE message which is sent when you want to close the window and post a quit message into the message loop that you will catch and exit.
Additional info :
It's not required to release your stuff since windows does that for you so it wont be locked the next time you start your program , but it's a good practice to at least Unregister your window class after your main loop.
Btw that is the wrong main function : WinMain that is the correct one. Plus to avoid even more bugs make sure you compile a windows GUI application.

SetWindowsHookEx with WH_KEYBOARD doesn't work for me, what do I wrong?

#include <iostream>
#include <fstream>
#define _WIN32_WINNT 0x501
#include <windows.h>
using namespace std;
HHOOK hKeyboardHook = 0;
LRESULT CALLBACK KeyboardCallback(int code,WPARAM wParam,LPARAM lParam) {
cout << "a key was pressed" << endl;
ofstream myfile;
myfile.open ("hookcheck.txt", ios::ate | ios::app);
myfile << "a key was pressed\n";
myfile.close();
return CallNextHookEx(hKeyboardHook,code,wParam,lParam);
}
int main() {
HWND consoleWindow = GetConsoleWindow();
HINSTANCE hInstCons = (HINSTANCE)GetWindowLong( consoleWindow, GWL_HINSTANCE );
hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyboardCallback, (HINSTANCE)consoleWindow, GetCurrentThreadId());
MessageBox(NULL, "It is keyboard time!", "Let's Go", MB_OK);
}
This code on every key press while the loop is going should print message on console and create a file, but nothing is happening. What do I wrong ?
I will quote from another topic:
Console windows are handled entirely by CSRSS, which is a system
process. Installing a hook into a process means injecting your DLL
into it. Since CSRSS is so important (it's vital for running of the
system, and code within runs as LocalSystem, which is the local
super-admin user), you're not allowed to inject code into it. So you
can't hook any of its windows.
There are no real window messages taking place in your simple console application, so your hook does not have to be called, and in your case you are not even injecting your hook but using thread mode hook only. Per MSDN documentation it is called when messages are about to be processed:
An application-defined or library-defined callback function used with
the SetWindowsHookEx function. The system calls this function whenever
an application calls the GetMessage or PeekMessage function and there
is a keyboard message (WM_KEYUP or WM_KEYDOWN) to be processed.
Now let me show you what you can do to start receiving calls on your hook:
MessageBox(NULL, _T("It is keyboard time!"), _T("Let's Go"), MB_OK);
//for(int i=0; i<=10; i++) {
// cout << i << endl;
// Sleep(1000);
//}
Do MessageBox and before closing it start typing - you will start getting hook calls.
Read the documentation for SetWindowsHookEx. Is it working, it will return NULL if it fails and GetLastError() can be called to get an error code to help diagnose what is wrong.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
Sleep(1000) suspends the execution of the current thread until the time-out interval elapses. It means that your program is not actually running (ie. processing messages) during this sleep.
You need to use a different kind of command, that will keep the message loop running. The simplest thing would be to wait for user input
while(true)
std::cin.get();
I have created a dll that hooked the keyboard and in there I used the DllMainfunction to retrieve a HINSTANCE that can be used in SetWindowsHookEx.
Next to that I also used 0 as the threadid so all threads get hooked.
Perhaps you could try a similar tactic as well.

DoEvents equivalent for C++?

I'm new to native c++. Right now, I made it so when I press the left mouse button, it has a for loop that does InvalidateRect and draws a rectangle, and increments X by the box size each time it iterates. But, C++ is so much faster and efficient at drawing than C# that, it draws all this instantly. What I would like is for it to invalidate the rectangle, show the rectangle, wait 50ms, then continue the loop. I tried Sleep(50) but it still waits until painting is done before showing the result. I also tried PeekMessage but it did not change anything.
Any help would be appreciated. Thanks
DoEvents basically translates as:
void DoEvents()
{
MSG msg;
BOOL result;
while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE ) )
{
result = ::GetMessage(&msg, NULL, 0, 0);
if (result == 0) // WM_QUIT
{
::PostQuitMessage(msg.wParam);
break;
}
else if (result == -1)
{
// Handle errors/exit application, etc.
}
else
{
::TranslateMessage(&msg);
:: DispatchMessage(&msg);
}
}
}
I am a bit rusty in Win32 API, but the asynchronous way of doing this would be:
Invalidate the rect
Set a timer (see below) to send a message after 50ms
Return to the event loop to let WM_PAINT events happen
On receiving the timer message, move the rect, then repeat
This way integrates nicely with being event driven. I realize this is not exactly what you ask for, but I thought I'd mention it as a possible solution anyway :)
EDIT: A quick google turns up the Windows API call [SetTimer](http://msdn.microsoft.com/en-us/library/ms644906(VS.85,loband).aspx) which you can use to facilitate this. The message will be a WM_TIMER one.