微光互聯 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 程序一樣的行為——光標下沒有任何輸出 , 且不打印任何調試日志,遇到中文字符還會崩潰:

推薦閱讀