微光互联 TX800-U 扫码器无法输出中文到光标的问题( 五 )

至于编辑框随视图大小变化而变化这种基本功 , 就不赘述了 , 后面会放出完整源码 。注意这里的 hEdit,它存储着编辑框的句柄,后面会用到 。
console 改 win32 最大的变化是 printf 日志输出没有了,为了解决这个问题,改写 printf 为 my_printf,在里面做些文章:
extern HWND hEdit;void my_printf(char const* format, ...){    char line[4096] = { 0 };    va_list vp;    va_start(vp, format);    vsprintf(line, format, vp);    va_end(vp);    // replace '\n' to '\r\n'    if (strlen(line) > 0)        line[strlen(line) - 1] = '\r';    strcat(line, "\n");     //std::wstring data = gb2312_to_unicode(line);    // SendMessage(hEdit, WM_SETTEXT, 0, (WPARAM)data.c_str());    SendMessage(hEdit, EM_SETSEL, -2, -1);    SendMessageA(hEdit, EM_REPLACESEL, true, (long)line);    SendMessage(hEdit, WM_VSCROLL, SB_BOTTOM, 0);    OutputDebugStringA(line);}基本就是将日志发往刚才的 hEdit,注意这里不使用 WM_SETTEXT 以免冲掉历史消息,最后上张效果图:

微光互联 TX800-U 扫码器无法输出中文到光标的问题

文章插图
再看下新版 set_text_to_active_windows 的实现:
void set_text_to_active_windows(std::string const& data){    int ret = 0;    wchar_t const* str;    HWND wnd = GetForegroundWindow();    //HWND wnd = GetActiveWindow();    //HWND wnd = GetDesktopWindow();    if (wnd == NULL)    {        my_printf("no active windows\n");        return;    }    my_printf("get active window\n");    DWORD SelfThreadId = GetCurrentThreadId();    DWORD ForeThreadId = GetWindowThreadProcessId(wnd, NULL);    if (!AttachThreadInput(ForeThreadId, SelfThreadId, true))    {        my_printf("attach thread input failed\n");        return;    }    my_printf("attach thread input\n");    //wnd = GetFocus();    wnd = GetActiveWindow();    if (wnd == NULL)    {        my_printf("no focus windows\n");        return;    }    my_printf("get focus window\n");    AttachThreadInput(ForeThreadId, SelfThreadId, false);    //std::wstring unicode = gb2312_to_unicode(data);    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;    std::wstring tst = converter.from_bytes(data);    str = tst.data();    //ret = SendMessageA(wnd, WM_SETTEXT, 0, (LPARAM)data.c_str());    for (int i=0; str[i] != '\n'; ++i)    {        ret = SendMessage(hEdit, WM_CHAR, str[i], 0);    }    my_printf("send text to active window return %d: %s\n", ret, data.c_str());}与之前版本相比,除了 printf 变为 my_printf,最大的变化是在结尾部分:使用 WM_CHAR 消息代替 WM_SETTEXT 。这样做是为了更好的模拟光标行为,毕竟不能假设用户光标一定位于 windows edit 控件上,有可能位于绘制界面框架 (Qt) 或描述界面框架 (Electron) 生成的 App 的控件上 , 这个消息可以实现字符被一个个输入编辑框的效果,兼容上述所有控件 。
满怀期待的启动应用后,出现和 console 程序一样的行为——光标下没有任何输出 , 且不打印任何调试日志,遇到中文字符还会崩溃:

推荐阅读