【问题标题】:GetWindowTextW doesnt grab a wide stringGetWindowTextW 不抓取宽字符串
【发布时间】:2016-12-23 05:45:30
【问题描述】:

我有以下代码从文本框输入(纯 winapi)获取数据

BOOL CALLBACK DlgProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg)
    {
    case WM_INITDIALOG:
        SendDlgItemMessage(hw, IDC_EDITMASK, EM_SETLIMITTEXT, 512, 0);
        return true;

        case WM_CLOSE:
            DestroyWindow(hw);
            return TRUE; 


        case WM_COMMAND:
            HWND hCtrl;
            int length;
            wchar_t * text;
            switch (LOWORD(wp))
            {

                case IDCPROCESS:

                    nElements = 1;
                    hCtrl = GetDlgItem(hw, IDC_EDITMASK); 

                    length = GetWindowTextLengthW(hCtrl);        
                    if (length == 0) {
                        MessageBox(hw, L"Неверная маска", L"Ошибка", 0);
                        return FALSE;
                    }

                    text = (wchar_t*)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, length * sizeof(wchar_t) + sizeof(wchar_t));

                    GetWindowTextW(hCtrl, text, length + sizeof(wchar_t));

                    char *test = (char*)text;

                    int pos = 0;
                    int startPos = 0;
                    char dbg[2] = { 0 };
                    while (pos <= length) {
                        dbg[0] = text[pos];
                        OutputDebugStringA(dbg); // here i output the text by characters
                        if (text[pos] == ',' || pos == length) {

                            if(!szMasks)
                                szMasks = (wchar_t**)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(wchar_t*)*nElements);
                            else
                                szMasks = (wchar_t**)HeapReAlloc(hProcessHeap, HEAP_ZERO_MEMORY,szMasks, sizeof(wchar_t*)*nElements);

                            int bufferSize = pos - startPos;
                            szMasks[nElements - 1] = (wchar_t*)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, (bufferSize + 2) * sizeof(wchar_t));
                            if(bufferSize % sizeof(wchar_t) != 0)
                                bufferSize++;
                            int copyLength = bufferSize / sizeof(wchar_t);

                            wcsncpy(szMasks[nElements - 1], text + startPos, copyLength);
                            OutputDebugStringW(szMasks[nElements - 1]);
                            OutputDebugStringW(L"\r\n");

                            nElements++;
                            startPos = pos+1;

                        }

                        pos++;
                    }

                    searchMasks.count = nElements-1;
                    searchMasks.szMasks = szMasks;

                    HeapFree(hProcessHeap, 0, text);
                    DestroyWindow(hw);

                    return TRUE;


            }
            break;



    case WM_DESTROY:
            PostQuitMessage(0);
            return TRUE;
    }

    return FALSE;
}

因此,例如,如果我输入俄语文本,我会得到有效的宽字符串,一切正常。如果我切换到英语并输入让我们说“单词”,我会在文本中得到缓冲区,它不是一个宽字符串,我希望它是: “w\0o\0r\0d” 但我明白了 “词”

但是我得到了一个常规的char* 字符串,这真的很糟糕,因为我需要通过一些规则来解析文本,搜索字符“,”并根据它复制数据到另一个缓冲区,使用@987654323 @,所以我必须始终有一个格式正确的wchar_t* 字符串。有什么办法可以解决这个问题,为什么GetWindowTextW 没有形成合适的宽字符串?我正在使用UNICODE 字符集而不是多字节来编译我的项目。

更新了代码

char * test = (char*) text 给出一个有效的 ansi 字符串,如果在输入框中只输入拉丁字符,而不是正确格式的wchar_t*

【问题讨论】:

  • 你怎么看text,你能看出它不是w\0o\0r\0d
  • 我们不知道 hCtrl 是什么。请提供所有必需的信息。在这种情况下:句柄是否引用了控件?在同一个进程还是另一个进程?它是标准控件还是自定义控件?如果它是自定义控件,请同时显示它的代码。
  • @andlabs 我在 for 循环中输出
  • 请也显示for循环。
  • @yasofiz 我可以向您保证,GetWindowTextW 完全按照文档记录的方式执行,以及按照文档记录的方式执行此操作。在您的问题代码中包含“for 循环中的输出”的 exact 代码。不是“像”你的 for 循环。 exact 循环,包括所有使用变量的所有正确声明,并且还包括 textlength 的 decl。还包括您从中获取文本的控件的窗口类名称。

标签: c++ c winapi unicode widechar


【解决方案1】:

C 风格的字符串是一个字符序列,以NUL 字符结尾。从第一个 NUL 字符开始的任何内容都不会被视为字符串的一部分。

当您使用 char[2] 类型的参数调用 OutputDebugStringA 时,其中第一个元素是 ASCII 字符,第二个字符是 \01 它被解释为长度为的字符串1. 因此,您只打印 ASCII 字符。

您正在处理宽字符串。你推断字符串类型的逻辑是错误的。


1 这就是 UTF-16LE 编码的 ASCII 字符在给定场景中的存储方式。

【讨论】:

  • 我检查了调试器,每次dbg[0] 不是\0。所以文字“单词”我得到了 4 次迭代
  • @yasofiz:当然dbg[0]0 在处理ASCII 字符时是不同的,编码为UTF-16LE。这是dbg[1] 那是0。是的,迭代 4 个代码单元需要 4 次迭代。为什么这让你感到惊讶?
  • 我知道我现在搞砸了。
【解决方案2】:

基于更新的代码...

当您为应该为零的字节之一调用 OutputDebugStringA 时,您将看不到任何输出。您已经有效地打印了一个空字符串。所以看起来好像零字节不存在,但它们确实存在。

【讨论】:

  • 但我在调试器中看到dbg[0] 不为零,并且计数器正好停在4 处,用于文本“word”
  • 你在我的代码中也看到一行char *test = (char*)text;如果我输入一个文本“word”并断点这个,我可以看到char * test的值是“word”,这意味着它不是w\0o\0r\0d 像我期望的那样
【解决方案3】:

您的 text 变量是一个 wchar_t 指针(即使未显示定义),因此任何显示它的尝试当然都会显示整个 UTF-16 字符。如果您正在检查 char * 缓冲区,您只会得到嵌入的 \0 字符,因为它会将每个 wchar_t 单元分成多个部分。

【讨论】:

  • @yasofiz 该代码几乎无法遵循。我看到您声明了 char * test,但我没有看到您在任何地方使用它。
  • 我把它放在那里进行测试,如果text 是适当的宽格式。我可以看到 char * 测试值是“word”,这意味着它不像我期望的那样 w\0o\0r\0d
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多