关于SendMessageA和SendMessageW的问题
再一次陷入A和W的问题,用时约四个小时,终于找到原因了。如下图,左边是正确的情况,右边是错误的情况:

代码在这里:“ysouyno/fake_tide81”。
究其原因其实就是由于current_pos这个变量的值出现了问题,但是到底在哪里出错了呢?分析了一下流程:
- 在
SCI_ADDTEXT消息处是最终添加文本的地方,这里通过current_position()获得的current_pos已经出错。 - 设置
current_pos的值是在SCI_GOTOPOS消息中处理的。 - 代码中共有三个向
errorlist窗口发送SCI_GOTOPOS的地方,通过添加LPARAM参数筛选发现错误的调用来自:
void TideWindow::output_append_string(char* s, int len) {
if (-1 == len)
len = strlen(s);
send_output(SCI_ADDTEXT, len, (LPARAM)s);
dprintf("WM_GETTEXTLENGTH get length: %d\n", send_output(WM_GETTEXTLENGTH));
send_output(SCI_GOTOPOS, send_output(WM_GETTEXTLENGTH));
}
- 问题就出在
send_output(WM_GETTEXTLENGTH)这里,它返回的值出错了,添加输出:
case WM_GETTEXTLENGTH:
dprintf("WM_GETTEXTLENGTH set length: %d\n", length());
return length();
通过日志发现,set和get的值不一致,如下:
[21772] WM_GETTEXTLENGTH set length: 1
[21772] WM_GETTEXTLENGTH get length: 1
[21772] WM_GETTEXTLENGTH set length: 22
[21772] WM_GETTEXTLENGTH get length: 21
[21772] WM_GETTEXTLENGTH set length: 23
[21772] WM_GETTEXTLENGTH get length: 21
[21772] WM_GETTEXTLENGTH set length: 48
[21772] WM_GETTEXTLENGTH get length: 21
原来整个工程属性是Use Unicode Character Set,而send_output用的是SendMessage并没有指定A还是W版本,所以默认以SendMessageW发送消息了,这可能造成了数据长度被截段了(我是这么猜想的),所以将SendMessage指定为SendMessageA即可以修复这个问题。再看日志输出就正确了:
[6668] WM_GETTEXTLENGTH set length: 1
[6668] WM_GETTEXTLENGTH get length: 1
[6668] WM_GETTEXTLENGTH set length: 22
[6668] WM_GETTEXTLENGTH get length: 22
[6668] WM_GETTEXTLENGTH set length: 23
[6668] WM_GETTEXTLENGTH get length: 23
[6668] WM_GETTEXTLENGTH set length: 48
[6668] WM_GETTEXTLENGTH get length: 48
见commit:Fix why is the output here messy, like multiple threads writing to the same place?。
修复后的效果如下:


本文讲述了作者在使用SendMessageA和SendMessageW函数时遇到的问题,发现是由于工程属性设置为Unicode导致数据长度被截断。通过指定SendMessage为SendMessageA,解决了文本混乱的问题并给出了修复后的日志对比。
2655

被折叠的 条评论
为什么被折叠?



