keypress

Pages: 12
how do I detect a keypress I have looked it up but it all makes no sense
p.s. this is in windows and MSVC++ 2010
If you want keypresses only made in your Window, you want to handle the WM_KEYDOWN or WM_CHAR messages.

If you just want the real-time state of the keyboard (regardless of what window is active), you want GetAsyncKeyState.

Which are you looking for?
State of keyboard could you please explain more


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <windows.h>

//...

if( GetAsyncKeyState( VK_UP ) & 0x8000 )
{
    // the 'Up' arrow key is currently being held down
}

if( GetAsyncKeyState( 'A' ) & 0x8000 )
{
    // the 'A' key is currently being held down
}
closed account (o1vk4iN6)
If i'm not mistaken, most anti-virus programs flag any programs that use GetAsyncKeyState as a keylogger.
now it wont change the position of a pixel here is my code

//header files to include
#include<windows.h>
#include<stdlib.h>
#include<time.h>

//function prototypes (forward declarations)
BOOL InitInstance(HINSTANCE, int);
ATOM MyRegisterClass(HINSTANCE);
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

//the window event callback function

LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
char *title = "gfx engine";
RECT rt;
int x = 80, y = 80, n;
COLORREF c;

switch (message)
{
case WM_PAINT:
//get the dimensions of the window
GetClientRect(hWnd, &rt);

//start drawing on devicce context
hdc = BeginPaint (hWnd, &ps);

//draw some text
c = RGB(192, 192, 192);

SetPixel(hdc, x, 50, c);
SetPixel(hdc, x, 50, c);
if( GetAsyncKeyState( 'd' ) & 0x8000 )
{
x = x + 10;
}
//stop drawing
EndPaint(hWnd, &ps);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

//helper function to set up the window properties
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);

//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "gfx engine";
wc.hIconSm = NULL;

//set up the window with the class info
return RegisterClassEx(&wc);
}

//helper function to create the window and refresh it
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

//create a new window
hWnd = CreateWindow(
"gfx engine", //window class
"gfx engine", //title bar
WS_OVERLAPPEDWINDOW, //window style
CW_USEDEFAULT, //x position of window
CW_USEDEFAULT, //y position of window
1280, //width of the window
720, //height of the window
NULL, //parent window
NULL, //menu
hInstance, //application instance
NULL); //window parameters


//was there an error creating the window?
if(!hWnd)
return FALSE;

//display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//entry point for a Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//declare variables
MSG msg;

//register the class
MyRegisterClass(hInstance);

//initialize application
if(!InitInstance (hInstance, nCmdShow))
return FALSE;

//set random number seed
srand(time(NULL));

//main message loop
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
There are several problems:


1) You need to use the capital 'D' not the lowercase 'd'


2) You are checking GetAsyncKeyState() inside your WM_PAINT message... which is only running when the screen is repainting. It is not constantly running.

So pressing 'D' alone does nothing, you have to press/hold 'D' and make the screen repaint (minimizing it and restoring it... or doing something similar -- since you are not forcing a repaint in your code).


3) You are setting one pixel to a very light gray (192,192,192) which would make this very difficult to see against a white background even if it was working properly.


4) 'x' is local to your WinProc function and is initialized to 50. This means x gets reset to 50 every time a message is processed (ie: every time the screen is drawn). Since you modify x AFTER setting the pixel, you are always setting the pixel at coord 80,80 -- and the addition afterwards does nothing.


5) WM_PAINT gets sent for every repaint. If something happens that causes several repaints per second (like dragging another window over this one), if 'D' is being held down, that pixel will FLY across the window super fast.
ok I fixed it but it still wont work heres the code:
//header files to include
#include<windows.h>
#include<stdlib.h>
#include<time.h>

//function prototypes (forward declarations)
BOOL InitInstance(HINSTANCE, int);
ATOM MyRegisterClass(HINSTANCE);
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

//the window event callback function

LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
char *title = "gfx engine";
RECT rt;
int x, y, n;
COLORREF c;
int x1 = 10, y1 = 10;
if( GetAsyncKeyState( 'D' ) & 0x8000 )
{
x1 = x1 + 10;
goto redraw;
}
switch (message)
{
case WM_PAINT:
//get the dimensions of the window
redraw:
GetClientRect(hWnd, &rt);

//start drawing on devicce context
hdc = BeginPaint (hWnd, &ps);

//draw some text

c = RGB(0, 0, 0);

SetPixel(hdc, x1, 50, c);
SetPixel(hdc, x1, 51, c);

//stop drawing
EndPaint(hWnd, &ps);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

//helper function to set up the window properties
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);

//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "gfx engine";
wc.hIconSm = NULL;

//set up the window with the class info
return RegisterClassEx(&wc);
}

//helper function to create the window and refresh it
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

//create a new window
hWnd = CreateWindow(
"gfx engine", //window class
"gfx engine", //title bar
WS_OVERLAPPEDWINDOW, //window style
CW_USEDEFAULT, //x position of window
CW_USEDEFAULT, //y position of window
1280, //width of the window
720, //height of the window
NULL, //parent window
NULL, //menu
hInstance, //application instance
NULL); //window parameters


//was there an error creating the window?
if(!hWnd)
return FALSE;

//display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//entry point for a Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//declare variables
MSG msg;

//register the class
MyRegisterClass(hInstance);

//initialize application
if(!InitInstance (hInstance, nCmdShow))
return FALSE;

//set random number seed
srand(time(NULL));

//main message loop
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
The GetAsyncKeyState call is still inside your WinProc which means it only happens when a message is being processed. When your program is idle nothing will happen.

Also, using goto here is a bad idea for many reasons. #1 is it ignores whatever message you should be handling and treats it like a WM_PAINT message. #2 is that BeginPaint/EndPaint will only repaint areas that need repainting... so this will not do anything. #3 is that goto is atrocious and should be avoided unless you have a very good reason to use it (read: newbies generally don't -- so to make this easy, let's say you shouldn't be using goto at all)


You seem to still be struggling with the Message Loop and how it actually works. Until you understand it I don't think you should really be trying to do what you're doing, as it is flawed on several levels.


1
2
3
4
5
6
//main message loop
while(GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}


This right here is your message loop.

GetMessage() is where your program is 99% of the time. It just sits in a quiet loop waiting for Windows to tell the program something happened. Whenever the user moves the mouse over the window... or presses a key, or does something else that interacts with your window... Windows will generate a message and send it to your program.

GetMessage receives that message and fills your 'msg' object with the data about it. GetMessage then returns, allowing the program to continue inside that while loop.

Inside the while loop, you call TranslateMessage() which does some additional processing on the message (don't ask me to explain as I don't fully understand it myself)... followed by DispatchMessage which sends the message out to your windows message handler.

So ultimately, DispatchMessage is what calls your WinProc function.


This means that WinProc is being called only when there is a message to process. If nothing of interest is happening... then WinProc is not running. You can put all the calls to GetAsyncKeyState you want in there... but if you're not receiving any messages, they're not running.



Now that I see what you're doing... I realize you probably do not want GetAsyncKeyState. Rather, you want Windows to notify you (send a message) when the key is pressed. This is normally done through the message system.

When a key is pressed, windows sends a WM_KEYDOWN message... with the key being pressed in the 'wParam' paramter. Likewise, when the key is released, Windows sends WM_KEYUP.

1
2
3
4
5
6
7
8
9
10
switch( message )
{
//...
case WM_KEYDOWN:
    if( wParam == 'D' )  // 'D' key is pressed
    {
        // ... do whatever you want here
        InvalidateRect( hWnd, NULL );  // force the entire window to repaint
    }
    break;






Lastly... if you are doing this for a game (which I'm guessing by the text "gfx engine" in there), I strongly suggest you consider using a graphic lib like SFML. WinAPI absolutely sucks for that kind of work.
closed account (Dy7SLyTq)
or you know... pdcurses
InvalidateRect( hWnd, NULL ) this is messed up it says too few arguments in function call
closed account (Dy7SLyTq)
can you give the exact error message?
that was the message
DTSCode wrote:
or you know... pdcurses


pdcurses is a console lib. I fail to see how it applies to what OP is doing.

klay2 wrote:
InvalidateRect( hWnd, NULL ) this is messed up it says too few arguments in function call


Whoops. Looks like InvalidateRect has a 3rd parameter I forgot about:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx
now it says hinstance is undefined heres the code:
//header files to include
#include<windows.h>
#include<stdlib.h>
#include<time.h>

//function prototypes (forward declarations)
BOOL InitInstance(HINSTANCE, int);
ATOM MyRegisterClass(HINSTANCE);
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

//the window event callback function

LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
char *title = "gfx engine";
RECT rt;
int x, y, n;
COLORREF c;
int x1 = 10, y1 = 10;
switch (message)
{
case WM_PAINT:
//get the dimensions of the window
redraw:
GetClientRect(hWnd, &rt);

//start drawing on devicce context
hdc = BeginPaint (hWnd, &ps);

//draw some text

c = RGB(0, 0, 0);

SetPixel(hdc, x1, 50, c);
SetPixel(hdc, x1, 51, c);

//stop drawing
EndPaint(hWnd, &ps);
break;


//...
case WM_KEYDOWN:
if( wParam == 'D' ) // 'D' key is pressed
{
x++;
InvalidateRect( hWnd, NULL, NULL );
break;


case WM_DESTROY:
{ PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

//helper function to set up the window properties
ATOM MyRegisterClass(HINSTANCE hInstance);
{
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);

//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "gfx engine";
wc.hIconSm = NULL;

//set up the window with the class info
return RegisterClassEx(&wc);
}

//helper function to create the window and refresh it
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

//create a new window
hWnd = CreateWindow(
"gfx engine", //window class
"gfx engine", //title bar
WS_OVERLAPPEDWINDOW, //window style
CW_USEDEFAULT, //x position of window
CW_USEDEFAULT, //y position of window
1280, //width of the window
720, //height of the window
NULL, //parent window
NULL, //menu
hInstance, //application instance
NULL); //window parameters


//was there an error creating the window?
if(!hWnd)
return FALSE;

//display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//entry point for a Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//declare variables
MSG msg;

//register the class
MyRegisterClass(hInstance);

//initialize application
if(!InitInstance (hInstance, nCmdShow))
return FALSE;

//set random number seed
srand(time(NULL));

//main message loop
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
1
2
3
4
5
//helper function to set up the window properties
ATOM MyRegisterClass(HINSTANCE hInstance);  // <- you shouldn't have a semicolon here
{
  //create the window class structure
  WNDCLASSEX wc;


But these are pretty basic compiler errors. You should be able to resolve these on your own.
now it says it expected a semicolon
You're missing a close brace in your WM_KEYDOWN handler, and another one in your switch statement.

Again this is pretty basic stuff. I don't mind helping with problems but I don't want to chase down every single compiler error you get.
sorry but now its just not showing a window
your WM_KEYDOWN handler is "bleeding" into your WM_DESTROY handler because you only break if the 'D' key is being pressed.

If any other key is being pressed, it will close the window.

EDIT:
That said, I would appreciate it if you took the time to attempt to solve these kinds of problems yourself. As I said I'm fine with answering questions but when I end up fixing every little problem you have it feels like I might as well just be writing the program myself.
Last edited on
Pages: 12