【问题标题】:Char array or Wide char array display in an app(WinAPI) with LPWSTR pointer使用 LPWSTR 指针在应用程序(WinAPI)中显示字符数组或宽字符数组
【发布时间】:2020-11-30 20:42:44
【问题描述】:

我有一个问题,我无法弄清楚如何在创建的窗口中获取 char 类型数组(并将其转换为 wchar_t)或宽 char 数组本身,这将是对 LPWSTR(宽字符指针)的引用对于 WinAPI 应用程序。我尝试了很多转换方法,但没有成功,因为所有时间的字符都不是必须的。首先,我需要 char 因为我想显示随机生成的基于 ASCII 的字符。代码示例:

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

如您所见,生成的字符串应该是 65-90(拉丁文大写字母),尽管我得到了 Unicode 格式的所有内容(可能是因为转换不正确)。

【问题讨论】:

    标签: c++ winapi character-encoding


    【解决方案1】:

    您的 gen() 函数没有返回一个以 null 结尾的字符串,但 CreateWindow() 需要一个。

    您不能将 char* 指针分配给 wchar_t* 指针。您必须将char 数据实际转换为wchar_t 数据,例如使用MultiByteToWideChar() 或等效项。您可以在转换后的wchar_t 字符串的末尾附加一个空终止符,例如:

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

    你可以改用CreateWindowA(),那么你就不需要MultiByteToWideChar(),但你仍然需要添加一个空终止符,例如:

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

    或者:

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

    但是,我建议更改您的 gen() 函数以输出一个以 null 结尾的字符串开头,例如:

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

    或者:

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

    现在,话虽如此,您的gen() 函数正在错误地计算其随机字母。要生成仅包含 ASCII 大写字母的字符串,您的函数应如下所示:

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

    或者:

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

    【讨论】:

    • 谢谢,我非常感谢这个如此深入的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    相关资源
    最近更新 更多