1

I am trying to play around with WinAPI to be able to manipulate the console, mostly just be able to write whatever I want, wherever I want without having to rewrite the whole console. I remember that I once got it to work earlier but that was long ago and I seem to have lost that code... whoops.

Anyway, I remember, that I succeeded with much less effort than what it is taking me now.

I am using this MS Docs page for reference and I remember using it earlier, successfully.

Right now, there is truly only a couple of lines that I am trying to get to work:

#include <windows.h>
#include <iostream>

using namespace std;

int main()
{
    HANDLE hndl = GetStdHandle(STD_INPUT_HANDLE);
    if (hndl == INVALID_HANDLE_VALUE)
    {
        cout << "Invalid handle, error " << GetLastError();
        return 0;
    }
    long unsigned int *chars_written = new long unsigned int;
    if (!WriteConsoleOutputCharacter(hndl, "mystring", 8, {20, 30}, chars_written))
    {
        cout << "Could not write, error " << GetLastError();
        return 0;
    }
    return 0;
}

The result is the console window displaying "Could not write, error 6" and then ending the application.

Error 6, according to System Error Codes is "the handle is invalid".

What am I doing wrong? I must be missing something.

It seems to be important that I am trying to work in Code::Blocks.

BONUS: I tried MS Visual Studio with the full WinAPI SDK (some important parts seem to be missing in Code::Blocks) and, while the main problem is the same, the functions in MS Visual Studio don't seem to all fit the official reference I am using, e.g. WriteConsoleOutputCharacter requires an LPCWSTR as its 2nd argument instead of a LPCSTR as mentioned in the source and as works in Code::Blocks. Windows Data Types

Edit: I found that WriteConsoleOutputCharacter is a macro actually, and is defined differently between Code::Blocks and MS Visual Studio, as two different, existing in both versions functions: WriteConsoleOutputCharacterA() and WriteConsoleOutputCharacterW(), which sadly, is not mentioned in the MS Docs.

Thank you in advance, Maurice.

  • The Win32API has for a lot of functions actually two flavors - an 8 bit character flavor and a wide character flavor. The `WriteConsoleOutputCharacter` is actually nothing else than a macro which expands to `WriteConsoleOutputCharacterA` or `WriteConsoleOutputCharacterW` depending on another certain macro define. – Scheff's Cat May 08 '19 at 10:03
  • Yep, thank you very much, I have noticed slightly earlier but it's good that you've confirmed. These macros are also inconsistent, sometimes leading to the A version and sometimes to the W version. – Maurycy Wojda May 08 '19 at 10:04
  • I personally prefer to use only the functions (ignoring the macros) i.e. explicitly use the `A` or `W` suffixed identifier. (Actually, I try to prevent Win32 API at all, relying on C++ standard lib. but this doesn't work always and PC/Windows is our main delivery platform.) ;-) – Scheff's Cat May 08 '19 at 10:05
  • While I got your reply I googled and found this: [SO: WinAPI Unicode and ANSI functions](https://stackoverflow.com/q/33714546/7478597). – Scheff's Cat May 08 '19 at 10:06

1 Answers1

3

First of all WriteConsoleOutputCharacter() requires a wide string as argument, while you're passing a normal string "mystring" as argument. To make it a wide literal, you just add the letter L as a prefix - e.g: L"mystring". And the program is giving you an error because the handle you're retrieving is an input handle (STD_INPUT_HANDLE). Meanwhile, if you want to output to the console through a handle you need to retrieve an output handle (STD_OUTPUT_HANDLE).

Andro
  • 2,232
  • 1
  • 27
  • 40
Nadpher
  • 186
  • 1
  • 10
  • can I do both? Also, I read that all the WriteConsoloeOutputCharacter() function needs is the GENERIC_WRITE attribute which is always given by GetStdHandle() – Maurycy Wojda May 08 '19 at 10:05
  • Yes, you can do both, but you would need to create a handle yourself. You can do this by using the CreateConsoleScreenBuffer() function, with its first parameters being GENERIC_READ | GENERIC_WRITE, which will give you ability to both input and output. Then you have to set it as the active console screen buffer with the function SetConsoleActiveScreenBuffer() function. – Nadpher May 08 '19 at 10:08
  • Am I understanding this correctly, that it will flush my console window and use it in a sort of "new layer", instead of creating a new window? – Maurycy Wojda May 08 '19 at 10:17
  • Yes, that is how it works. You can have multiple console screen buffers, but only the active one will be the one shown in the console. – Nadpher May 08 '19 at 10:52