3

I'm new to the Windows API and am programming in C++. I would like to have a console to output information to and receive keyboard commands via GetMessage. However, I can't just create a console application because if I do, it's impossible to read keyboard messages sent to that console with GetMessage. Reacting to keyboard input via GetMessage is a requirement for this project.

When I create Win32 GUI application in Code::Blocks 13.12 (using MinGW to compile) and call AllocConsole at the beginning, I get error 5: "Access is denied". If I instead first use FreeConsole, FreeConsole succeeds without error; if I then use AllocConsole, a console window appears. The MSDN description of FreeConsole is:

Detaches the calling process from its console.

This indicates that before I call FreeConsole, a console already existed (even though I couldn't see it and didn't explicitly create it). Is it an invisible console, or is it the one that always appears when running a Code::Blocks project? Is it pointless for me to use FreeConsole and then AllocConsole? Is there instead a way to make the console that already exists visible (if it's invisible) and able to receive keyboard input via GetMessage?

Here's an example of the stripped-down code that exhibits this behavior:

#include <windows.h>

DWORD dw = 0;

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nCmdShow)
{
    if (FreeConsole() == 0) {
        dw = GetLastError();
        return dw;
    }

    if (AllocConsole() == 0) {
        dw = GetLastError();
        return dw;
    }
    return 1;
}
Cerran
  • 2,087
  • 2
  • 21
  • 33
  • Why do you want to use GetMessage? Anyway, you *can* use it in console application. – dsi Jan 22 '14 at 15:10
  • @dsi The reason I need to use GetMessage is complicated, but you can read more about my situation [here](http://stackoverflow.com/questions/21139698/how-can-i-recognize-keyboard-input-in-c-with-windows-api-using-getmessage-in) if you really want to know. – Cerran Jan 22 '14 at 15:33
  • @dsi I know I can use GetMessage, but I don't think I can use it *to get input from the keyboard*. At the question linked to in my previous comment, I asked "Does anyone have any tips for how to direct keyboard input to the messaging system in my console application?" To which Hans Passant replied, "That's not possible. The console window is managed by a completely different executable, you can't mess with it." – Cerran Jan 22 '14 at 15:33
  • @Cerran ok, have a look at MsgWaitForMultipleObjects function. It might be what you're looking for. – dsi Jan 22 '14 at 16:48
  • I cannot reproduce. I build a GUI app with mingw and my call to `AllocConsole` succeeds. – David Heffernan Jan 22 '14 at 20:52
  • @DavidHeffernan Well, that's interesting! I'm also using MinGW. Just to be sure, `AllocConsole` succeeds without first calling `FreeConsole`? – Cerran Jan 23 '14 at 09:02
  • Dsi is correct that you can call `GetMessage` from a console application. However, you cannot use it to get *console keyboard input*, which seems to be what you want. Instead, I think you should put your USB-message-handling code into a separate thread, and then keep ordinary console I/O. Another option is to use Windows-specific console-input functions like `ReadConsoleInput`, and then use `MsgWaitForMultipleObjects` to wait on the console handle. It will tell you when you receive console input or a message, so you can know whether to call `GetMessage` or `ReadConsoleInput` next. – Rob Kennedy Jan 23 '14 at 14:16

1 Answers1

1

When I create Win32 GUI application in Code::Blocks (using MinGW to compile) and call AllocConsole at the beginning, I get error 5: Access is denied.

The explanation for your call to AllocConsole failing is that you are actually building a console application. Even though you use WinMain, mingw will still produce, by default, an executable that targets the console subsystem. You can use a tool like dumpbin to inspect the PE header to confirm my conclusion.

Compile with -mwindows to make sure that the executable targets the GUI subsystem.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    That appears to be correct. Thanks for the help! When I specify `-mwindows` as a linker option, `AllocConsole` succeeds without first using `FreeConsole`, and the new console appears. It seems strange to me that this wouldn't automatically be specified in my project, considering I explicitly created it as a "Win32 GUI project" rather than a "Console application" in Code::Blocks. I still don't know why the console was invisible, but with `-mwindows`, I don't have to worry about that because the only console created is the one I explicitly create, which is visible by default. – Cerran Jan 23 '14 at 09:31
  • I tried using dumpbin on my executable, but because I'm unfamiliar with the tool, I wasn't sure how to find the relevant information. But I guess the difference that `-mwindows` makes basically already proved your point. Thanks again, that was very helpful. – Cerran Jan 23 '14 at 10:22
  • `dumpbin /headers myexe.exe | more` is what you need, and the value of interest is the subsystem. Either Windows CUI or Windows GUI. – David Heffernan Jan 23 '14 at 10:24
  • Ah yes, I forgot about `more`. Indeed, without `-mwindows`, I get `3 subsystem (Windows CUI)`; with `-mwindows`, I get `2 subsystem (Windows GUI)`. – Cerran Jan 23 '14 at 10:40