"message only" window not receiving messages....

Im just annoyed with this, its really just a means to an end that i need to recieve messages and for whatever reason. Im just running out of rocks to turn over and have no idea why this bit of code is behaving the way it is. At this point i'd be happy to simply have the window register that a key was pressed on the keyboard. I'm probably missing something obvious. The provided code is really just a mashup of a couple different examples that i found online which is the most annoying part bc theyre supposedly working for others...

I'm almost wondering if the window is like getting pushed to the background and not seeing the messages. I have no idea. This is exactly why i avoid creating windows with c++ but here we are....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
std::cout << "Got a message!" << std::endl;

	//if (uMsg == WM_COPYDATA)
		
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

void createwindow() {
	static const char* class_name = "DUMMY_CLASS";
	static const char* name = "DUMMY";
	WNDCLASSEX wx = {};
	wx.cbSize = sizeof(WNDCLASSEX);
	wx.lpfnWndProc = WindowProcedure;      
	wx.hInstance = GetModuleHandle(NULL);
	wx.lpszClassName = (LPCWSTR)class_name;

	if (RegisterClassEx(&wx)) {
		if (CreateWindowEx(0, (LPCWSTR)class_name, (LPCWSTR)name, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL) == NULL) {
			cout << "failed to create window";
		}
	}
}


int main()
{
	createwindow();
	MSG msg;
	while (GetMessage(&msg, 0, 0, 0)  != 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}
Last edited on
You need to use a global hook to receive Windows messages in a console window.
https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks

From: https://social.msdn.microsoft.com/forums/vstudio/en-US/d96e9e84-1a79-4163-b90b-62d390f95321/how-to-receive-windows-message-in-a-command-line-app-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <cstdio>
#include <cstdlib>
#include <windows.h>

DWORD   g_main_tid = 0;
HHOOK   g_kb_hook = 0;

BOOL CALLBACK con_handler(DWORD)
{
   PostThreadMessage(g_main_tid, WM_QUIT, 0, 0);
   return TRUE;
}

LRESULT CALLBACK kb_proc(int code, WPARAM w, LPARAM l)
{
   PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) l;
   const char* info = NULL;

   if (w == WM_KEYDOWN)
      info = "key dn";
   else if (w == WM_KEYUP)
      info = "key up";
   else if (w == WM_SYSKEYDOWN)
      info = "sys key dn";
   else if (w == WM_SYSKEYUP)
      info = "sys key up";

   printf("%s - vkCode [%04x], scanCode [%04x]\n", info, p->vkCode, p->scanCode);

   // always call next hook
   return CallNextHookEx(g_kb_hook, code, w, l);
}

int main()
{
   g_main_tid = GetCurrentThreadId();

   SetConsoleCtrlHandler(&con_handler, TRUE);

   g_kb_hook = SetWindowsHookEx(WH_KEYBOARD_LL, &kb_proc,
                                GetModuleHandle(NULL), // cannot be NULL, otherwise it will fail
                                0);

   if (g_kb_hook == NULL)
   {
      fprintf(stderr, "SetWindowsHookEx failed with error %d\n", ::GetLastError());
      return 0;
   }

   MSG msg;

   while (GetMessage(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   };
   UnhookWindowsHookEx(g_kb_hook);
   return 0;
}

To terminate the app either use CTRL+C or the X button on the console window.
1
2
You need to use a global hook to receive Windows messages in a console window.
https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks 


I appreciate the fast response and that does look like a step in the right direction. You are spot on with the dilemma that I'm having. I'm actually attempting to look at the rawinputdata. Not attempting to make a keylogger or anything nefarious. To look at the raw data i need the lParam of the MSG structure to create a RAWINPUTHEADER structure or something along those lines. The fact that apparently (according to the rest of the internet) you supposedly can't receive messages without a window. The keyboard hook never really crossed my thought process bc of said "fact".

I would still like to know what the problem is with the code that i had posted above. I had assumed that registering the device would allow me to receive all messages from said device. If that's not the case then what the heck is this for? https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerrawinputdevices

That works great btw.


Ya I'm still doing something wrong bc i can't suck out any relevant data. The keyboard hook works great but I need to intercept the WM_INPUT message somehow and I'm still not able to do that. All of the following seems to work just fine. I'm successfully registering the devices. but not able to receive the appropriate message...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;

USHORT MOUSE_USAGE_1 = 0x0001;
USHORT MOUSE_USAGE_2 = 0x0002;
USHORT GPAD_USAGE_1 = 0x0004;
USHORT GPAD_USAGE_2 = 0x0005;
USHORT KYBD_USAGE_1 = 0x0006;
USHORT KYBD_USAGE_2 = 0x0007;
USHORT USAGE_PAGE = 0x0001;


void PrintRawInputDeviceNames() {
	UINT devices{};
	//get the number of devices
	GetRawInputDeviceList(NULL, &devices, sizeof(RAWINPUTDEVICELIST));

	vector<RAWINPUTDEVICELIST> ridl((int)devices);

	GetRawInputDeviceList(&ridl[0], &devices, sizeof(RAWINPUTDEVICELIST));

	for (int x = 0; x < ridl.size(); x++) {
		char data[1048]{};
		UINT size = 1048;

		GetRawInputDeviceInfo(ridl[x].hDevice, RIDI_DEVICENAME, data, &size);

		for (int y = 0; y < 1048; y++) {
			cout << data[y];
		}
		cout << '\n';

	}

}

void RegisterRawKybd() {
	tagRAWINPUTDEVICE rid[2];

	rid[0].usUsagePage = USAGE_PAGE;
	rid[0].usUsage = KYBD_USAGE_1;
	rid[0].dwFlags = 0;
	rid[0].hwndTarget = NULL;

	rid[1].usUsagePage = USAGE_PAGE;
	rid[1].usUsage = KYBD_USAGE_2;
	rid[1].dwFlags = 0;
	rid[1].hwndTarget = NULL;

	if (!RegisterRawInputDevices(rid, 2, sizeof(tagRAWINPUTDEVICE))) {
		cout << "failed to register kybd";
	}

}

void GetRegisteredRawKybd() {

	UINT num{};
	GetRegisteredRawInputDevices(NULL, &num, sizeof(RAWINPUTDEVICE));
	cout << "number of rawKYBD's registered"<<num<<'\n';
}

vector<HANDLE> RetRawKybdHwd() {
	UINT devices{};
	//get the number of devices
	vector<HANDLE> h{};

	GetRawInputDeviceList(NULL, &devices, sizeof(RAWINPUTDEVICELIST));

	vector<RAWINPUTDEVICELIST> ridl((int)devices);

	GetRawInputDeviceList(&ridl[0], &devices, sizeof(RAWINPUTDEVICELIST));

	for (int x = 0; x < ridl.size(); x++) {
		if (ridl[x].dwType == 1) {
			h.push_back(ridl[x].hDevice);
		}
	}
	return h;
}


Last edited on
ok so now I can at least verify that the registration did in fact work (the above code plus below ) I'm able to at least trigger a messagebox when a WM_INPUT message is received.


theres still some trash in there from a windows walkthrough etc... and this is based off an example. Again I absolutely hate creating windows in c++ .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = _T("Hello, Windows desktop!");

    if (message == WM_INPUT) {
        MessageBox(NULL, _T("hello"), _T("hello"), MB_OK);
        //cout << "wm_input recieved" << '\n';
    }

    switch (message)
    {

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

    return 0;
}

int CALLBACK WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow){

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex)){
        MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Windows Desktop Guided Tour"),NULL);
        return 1;
    }

    hInst = hInstance;
    HWND hWnd = CreateWindow(szWindowClass, szTitle, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
    if (!hWnd)
    {
        MessageBox(NULL, _T("Call to CreateWindow failed!"),_T("Windows Desktop Guided Tour"),NULL);
        return 1;
    }
    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    RegisterRawKybd();

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}
Topic archived. No new replies allowed.