关于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?。
修复后的效果如下: