简体   繁体   中英

Char array or Wide char array display in an app(WinAPI) with LPWSTR pointer

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).

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM