0

I have an issue, I can"t figure out how to get the char type array( and convert it to wchar_t )or wide char array itself in a created window which would be a reference to LPWSTR( wide-character pointer) for a WinAPI app. I have tried many conversion approaches but it didn't work out, because all the time's characters were not quite the ones to had to be. In the first place, I need the char because I want to display randomly generated ASCII based characters. Code sample:

char *  gen() {
static char ha[10];
for (int i = 0;i < 10;i++)
{
    char p = (rand() % 65 + 90);
    while (p == ' ')
    {
        p = (rand() % 65 + 90);
    }
    ha[i] = p;
    
}
return ha;
}

WndProc(...)
{
...
case WM_COMMAND:
    switch (LOWORD(wparam)) {
    case 1:
        char* m;
        m = gen();
        //conversion which I couldn't figure out goes somewhere here
        wchar_t* xa;
        xa = m;
        
        CreateWindow(L"STATIC",xa, WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);
        
        X += 30;
        break;
    }
    break;
...
}

As you can see, the generated strings should be 65-90 (Latin capital letters) although I'm getting everything what's in Unicode (probably because converted incorrectly).

1 Answer 1

2

Your gen() function is not returning a null-terminated string, but CreateWindow() expects one.

You can't assign a char* pointer to a wchar_t* pointer. You have to actually convert the char data to wchar_t data, such as with MultiByteToWideChar() or equivalent. You can append a null-terminator to the end of that converted wchar_t string, eg:

WndProc(...)
{
    ...
    case WM_COMMAND:
        switch (LOWORD(wparam)) {
            case 1: {
                char* m = gen();

                int wlen = MultiByteToWideChar(CP_ACP, 0, m, 10, NULL, 0);
                wchar_t* xa = new wchar_t[wlen+1];
                MultiByteToWideChar(CP_ACP, 0, m, 10, xa, wlen);
                xa[wlen] = L'\0';
        
                CreateWindow(L"STATIC", xa, WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);

                delete[] xa;
        
                X += 30;
                break;
            }

            ...
        }
        break;

    ...
}

You can instead use CreateWindowA(), then you won't need MultiByteToWideChar(), but you will still need to add a null terminator, eg:

WndProc(...)
{
    ...
    case WM_COMMAND:
        switch (LOWORD(wparam)) {
            case 1: {
                char* m = gen();

                char* xa = new char[11];
                memcpy(xa, m, 10);
                xa[10] = '\0';
        
                CreateWindowA("STATIC", xa, WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);

                delete[] xa;
        
                X += 30;
                break;
            }

            ...
        }
        break;

    ...
}

Alternatively:

#include <string>

WndProc(...)
{
    ...
    case WM_COMMAND:
        switch (LOWORD(wparam)) {
            case 1: {
                char* m = gen();

                std::string xa(m, 10);
        
                CreateWindowA("STATIC", xa.c_str(), WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);

                X += 30;
                break;
            }

            ...
        }
        break;

    ...
}

However, I would suggest changing your gen() function instead to output a null-terminated string to begin with, eg:

char* gen()
{
    static char ha[11]; // <-- add +1 here
    for (int i = 0; i < 10; i++)
    {
        wchar_t p = (rand() % 65 + 90);
        while (p == ' ')
        {
            p = (rand() % 65 + 90);
        }
        ha[i] = p;
    }
    ha[10] = '\0'; // <-- add this
    return ha;
}

WndProc(...)
{
    ...
    case WM_COMMAND:
        switch (LOWORD(wparam)) {
            case 1: {
                char* m = gen();

                CreateWindowA("STATIC", m, WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);

                X += 30;
                break;
            }

            ...
        }
        break;

    ...
}

Or:

wchar_t* gen()
{
    static wchar_t ha[11];
    for (int i = 0; i < 10; i++)
    {
        wchar_t p = (rand() % 65 + 90);
        while (p == L' ')
        {
            p = (rand() % 65 + 90);
        }
        ha[i] = p;
    }
    ha[10] = L'\0';
    return ha;
}

WndProc(...)
{
    ...
    case WM_COMMAND:
        switch (LOWORD(wparam)) {
            case 1: {
                wchar_t* m = gen();

                CreateWindow(L"STATIC", m, WS_VISIBLE | WS_CHILD | WS_EX_WINDOWEDGE | WS_BORDER, 10, X, 100, 20, hWnd, NULL, NULL, NULL);

                X += 30;
                break;
            }

            ...
        }
        break;

    ...
}

Now, that being said, your gen() function is calculating its random letters incorrectly. To produce a string that contains only ASCII capital letters, your function should look like this instead:

char* gen()
{
    static char ha[11];
    for (int i = 0; i < 10; i++)
    {
        ha[i] = (rand() % 26) + 'A'; // <-- produces letters in the range A..Z only ...
    }
    ha[10] = '\0';
    return ha;
}

Or:

wchar_t* gen()
{
    static wchar_t ha[11];
    for (int i = 0; i < 10; i++)
    {
        ha[i] = (rand() % 26) + L'A';
    }
    ha[10] = L'\0';
    return ha;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I highly appreciate this so-in-depth explanation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.