WIN API, How to check if the user pressed a key

I have a problem detecing if the user clicked a key...

I have a Edit Box :
1
2
3
4
5
6
7
8
9
10
11
12
Edit = CreateWindow( TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | ES_LEFT, 20, 50, 150, 30, hwnd, NULL, GetWikiInstance(), NULL);
/code]

And I am trying to detect if the user pressed a key.... though I cant seem to do it using this code :

[code]
		case WM_KEYDOWN:
			if (wParam == VK_ESCAPE)
			{
				DestroyWindow(hwnd);
			}
		break;


Thanks!
Last edited on
Anyone ?
Tried WM_KEYUP?
Are you receiving the message?
Which window is focused? Remember only the focused window will receive the message.
It worked to me with other windows, but since the edit box isnt a window, but a window on a dialogless window(I have other stuff under the edit box)

So if I use key down, it works outside the editbox, but not inside..
The edit box is a new hwnd.. So I dont know where to check if a key was pressed in the hwnd, not the w dproc(which works but outside the editbox....

EssGeEich has already identified the problem.

When the Edit control has focus, it is the window which is sent the key stroke messages.

If you need WM_KEYDOWN to arrive in your app's main WndProc, you will have to either:

(a) subclass the Edit control
(b) intercept the message in the message loop (only really accepable if you have so many controls that subclassing would be a right pain.)

Andy

Subclassing the Edit control involves:

1 - adding an include, if you don't already have it (you also need to link to comctl32.lib)

#include <commctrl.h>

2 - defining a custom (user) message (and control ID, if you don't already have one)

1
2
#define WM_USER_KEYDOWN (WM_USER + 1000)
#define ID_EDIT_ONE    200 


3 - foward declaring the subclass proceedure

LRESULT CALLBACK EscapeWndProc(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);

4 - subclassing in WM_CREATE, along these lines (where s_hwndEdit is declared as a static HWND in the main WndProc.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        case WM_CREATE:
        {
            s_hwndEdit = CreateWindow( TEXT("EDIT"),
                                       NULL,
                                       WS_CHILD | WS_VISIBLE | ES_LEFT,
                                       20, 50,
                                       150, 30,
                                       hWnd,
                                       (HMENU)ID_EDIT_ONE,
                                       g_hInst,
                                       NULL );

            SetWindowSubclass(s_hwndEdit, EscapeWndProc, ID_EDIT_ONE, 0);
        }
        break;


5 - unsubclassing in WM_DESTROY

1
2
3
4
5
6
7
        case WM_DESTROY:
        {
            RemoveWindowSubclass(s_hwndEdit, EscapeWndProc, ID_EDIT_ONE);

            PostQuitMessage(0);
        }
        break;


6- providing the implentation of the subclass proceedure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LRESULT CALLBACK EscapeWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                               UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    // Usually you use a switch statement and return appropriate value
    // to indicate that you've handled a message. But here we're just
    // letting our parent know what's going on.
    if((uMsg == WM_KEYDOWN) && (wParam == VK_ESCAPE))
    {
        HWND hWndParent = GetParent(hWnd);
        PostMessage(hWndParent, WM_USER_KEYDOWN, wParam, lParam);
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}


7 - and handling the custom message as well as WM_KEYDOWN

1
2
3
4
5
6
7
8
9
        case WM_KEYDOWN:
        case WM_USER_KEYDOWN:
        {
            if (wParam == VK_ESCAPE)
            {
                DestroyWindow(hWnd);
            }
        }
        break;


Notes:

- I am deliberately using a custom message so I can tell the difference between the normal and re-posted messages.

- The ID used to subclass a control does not need to be the same as the control ID, but it's easier to keep track of things if you keep them in step.

- I am using the "new style" subclassing mechanism (SetWindowSubclass, RemoveWindowSubclass, ...), introduced in Windows XP back in 2001, rather than the older (ancient) approach using SetWindowLongPtr with GWLP_WNDPROC (or the even older SetWindowLong with GWL_WNDPROC) which is still referred to all over the place.
Last edited on
andywestken wrote:
- I am deliberately using a custom message so I can tell the difference between the normal and re-posted messages.

Not exactly:

PostMessage(hwndParent, uMsg, wParam, lParam);
This will re-send a WM_KEYDOWN.
You should change from uMsg to WM_USER_KEYDOWN.
But either way will work.
Oops - I meant to swap the message...

Thanks, Andy
Topic archived. No new replies allowed.