0

I'm working on a console game engine, and for it I'd like to make some control interface.

For it I chose approach of making a hidden window, which reads keys being pressed, then pushes them into a queue (this thing i'll implement separately) and then the engine itself just reads those keys via reading the queue and doing things described on each button pressed (control table). Here is what I mean:

bool _CreateMessageWnd(HWND* MWND)
{
    WNDCLASSEX wx = {0};
    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = HandleMessageSetup;        // function which will handle messages
    wx.hInstance = GetModuleHandle(NULL);
    wx.lpszClassName = L"Dummy";
    if (RegisterClassEx(&wx)) {
        *MWND = CreateWindowExW(0, L"Dummy", L"dummy_name", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
        return true;
    }
    return false;
}

This function creates a message window and sets HandleMessageSetup() as a proc func.

In a game loop (replicate with while(1)) I call for

void _DispMessage()
{
    MSG msg;
    if(GetMessageW(&msg, 0, 0, 0) > 0) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

and the message interceptor procedure looks like this:

LRESULT CALLBACK HandleMessageSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        printf("Got a message! %u\n", uMsg);
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

but all the messages it receives are 36, 129, 131, 1, which are creation messages of window itself, but no messages from console are present, any key I press, WM_KEYDOWN message does not appear.

from this question I learned about ChangeWindowMessageFilterEx() but neither ChangeWindowMessageFilterEx(MWND, WM_KEYDOWN,1,NULL); nor ChangeWindowMessageFilterEx(GetConsoleWindow(), WM_KEYDOWN,1,NULL); is working and still no messages received. How to overcome this trouble?

  • 1
    You should go properly to build a GUI app if it's GUI messages you want to monitor. The console window is not an ordinary HWND (as far as your app is concerned) and it cannot process messages. – Michael Chourdakis Apr 25 '19 at 13:22
  • 4
    `WM_KEYDOWN` is only sent to a window if it has the keyboard focus. A hidden window never has the keyboard focus. Look into installing a keyboard hook. – Mark Benningfield Apr 25 '19 at 13:24
  • @MichaelChourdakis I don't need it to process messages, I need it only to pass them – Ilya Pakhmutov Apr 25 '19 at 13:53
  • @Mark Benningfield, why didn't you post it as an answer? You were right! All I needed to do is SetFocus on message window and that's it! – Ilya Pakhmutov Apr 25 '19 at 14:02
  • Yes, you can get it working by calling `SetFocus()`, but that is brittle, since any other window can *also* request the keyboard focus; at which point, your game stops processing keyboard messages. A keyboard hook is a more robust solution for this scenario, I think. – Mark Benningfield Apr 25 '19 at 14:05
  • @MarkBenningfield and where do I find an example of the hook – Ilya Pakhmutov Apr 25 '19 at 14:10
  • Any internet search for "keyboard hook procedure" should get you there. – Mark Benningfield Apr 25 '19 at 14:13
  • @MarkBenningfield, thanks, found one – Ilya Pakhmutov Apr 25 '19 at 14:21
  • @MarkBenningfield Depending on the nature of the game, you might not _want_ it do process keyboard input when the window doesn't have focus. Imagine some slow-paced strategy game that you leave open in the background while doing other stuff. So a keyboard hook might have to keep track of its own window anyway, to check if they key press was for the game or for something else. – Lundin Apr 25 '19 at 14:49
  • @Lundin: Well, the OP is using a *hidden* window to wire up the message pump, so there's not really a user-accessible game window to go back to; there's only the console. Once the hidden window loses kbd focus, getting it back would be real bear. Granted though, implementing a kbd hook will require more thought and planning. – Mark Benningfield Apr 25 '19 at 14:56
  • @MarkBenningfield And what if I could return a focus to the window by using `WM_KILLFOCUS` or scanning if the console window has a focus by `GetFocus()` and handling focus back to kbd hidden window? – Ilya Pakhmutov Apr 25 '19 at 15:00
  • @IlyaPakhmutov: This comment thread is running long (comments are not the place for discussion), but I will say that posting a `WM_KILLFOCUS` msg could be problematic because of UI privilege isolation, and could lead to ping-ponging. – Mark Benningfield Apr 25 '19 at 15:11

1 Answers1

-1

The console is not your window, it does not even live in your process.

You can read low-level console input with ReadConsoleInput and this might be enough for a text-based game but something faster should probably have its own custom window instead of fighting the console API.

Anders
  • 97,548
  • 12
  • 110
  • 164