2017-11-03 19 views
2

は、Unicodeの例である:私は、簡潔のためにのためにWin32アプリケーションを使用することを避ける:コントロールからUnicodeテキストを正しく取得する方法は?ここ

メインで、私は、それからテキストを取得するためのbuttoneditコントロールを作成し、押されたときlistboxに追加します。だから私はstruct MSGのオブジェクトを使用し、whileループでブロックpeekingメッセージキューからのメッセージをブロックしました。

int main(){ 

    // An edit control where I can add any unicode text to. 
    HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, 
     L"Edit", L"你好! 你好吗?", WS_BORDER | WS_VISIBLE | WS_SYSMENU, 
     200, 100, 250, 70, 0, 0, GetModuleHandle(NULL), NULL); 

    // A listobx to receive the content of the edit control when pressing the button get text. 
    HWND hLstBx = CreateWindowExW(WS_EX_CLIENTEDGE, 
     L"Listbox", NULL, WS_BORDER | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 
     500, 100, 170, 400, 0, 0, GetModuleHandle(NULL), NULL); 

    // A button when pressed adds the content of the edit to the listbox. 
    HWND hGetText = CreateWindowExW(WS_EX_CLIENTEDGE, 
     L"Button", L"中文", WS_BORDER | WS_VISIBLE, 
     450, 300, 100, 70, 0, 0, GetModuleHandle(NULL), NULL); 


    // msg struct to pass to GetMessage to receive the messages from the queue. 
    MSG msg; 


    // blocking and getting messages from the queue. 
    while (GetMessageW(&msg, 0, 0, 0)) { 
     // some virtual keys translation. 
     TranslateMessage(&msg); 
     // sending the message to the specified window. 
     DispatchMessageW(&msg); 

     // Now after the messages sent to the target Window I check which control the message has been passed to, So if it is the button then: 
     if (msg.message == WM_LBUTTONDOWN && 
      msg.hwnd == hGetText) { 
      std::wstring wstrBuff; 

      int txtLen = SendMessageW(hEdit, WM_GETTEXTLENGTH, 0, 0); 
     // SendMessageW(hEdit, WM_GETTEXT, txtLen + 1, (LPARAM)wstrBuff.c_str()); 
     // MessageBoxW(0, wstrBuff.c_str(), 0, 0); 


      wchar_t lpTxt[MAX_PATH]; 
      SendMessageW(hEdit, WM_GETTEXT, MAX_PATH, (LPARAM)lpTxt); 
      SendMessageW(hLstBx, LB_ADDSTRING, 0, (LPARAM)lpTxt); 
      MessageBoxW(0, lpTxt, L"你好! 你好吗?", 0); 
      //delete[]lpTxt; 
     } 
    } 

    std::wcout << std::endl << std::endl; 
    std::wcin.get(); 
    return 0; 
} 

すべてのものは除いて正常に動作します:I上記I非コメント行は私にtxtLenを示すアサーションメッセージとエディットコントロールのテキストの大きさに直面して実行時エラーを取得する場合。これは、いくつかの文字列が重なっているためですか?

小さなテキストを入力しても問題ありませんが、約14文字のテキストでエラーが発生します。

  • も正しい方法はSendMessageW()からstd::wstring.c_str()がテキストを取得するために渡すということですか?

  • 最後の質問1つ:コントロールからUnicodeテキストを正確かつ効果的に取得する方法動的メモリでLPWSTRを使用する方法:スタックを使い果たしたくありません。

  • NB:ソースファイルをutf8 /BOMとして保存しましたが、読めない文字があります。それについて私を助けてくれたメンバーに感謝します。

+0

@Ron:私はそれを試してみます。ありがとう。 – WonFeiHong

+0

@Ron:いいえ、問題は解決しません。 – WonFeiHong

+0

'lpTxt'配列は' new 'で動的に割り当てられていないので、削除する必要はありません。 –

答えて

4

読み取り専用単一のヌルシンボルではなく、txtLen + 1シンボルのバッファとバッファへのポインタを戻します(LPARAM)wstrBuff.c_str()を送信します。あなたが使用している場合は、最新のVS(とC++ 17標準サポート)あなたが適切なポインタを供給するようにコードを変更することができます。

std::wstring wstrBuff; 
wstrBuff.resize(txtLen + 1); 
const LRESULT copied_symbols_count = SendMessageW 
(
    hEdit 
, WM_GETTEXT 
, static_cast<WPARAM>(wstrBuff.size()) 
, reinterpret_cast<LPARAM>(wstrBuff.data()) 
); 
if(copied_symbols_count == txtLen) 
{ 
    assert(L'\0' == wstrBuff.back()); 
    wstrBuff.pop_back(); // get rid of terminating null 
} 
else 
{ 
    wstrBuff.clear(); // something went wrong... 
} 

注C++ 17標準缶非const修飾wstring::data()メソッドを追加することに書き込み可能なバッファへのポインタを得るために安全に使用されます。

+0

だから間違っていますか?ありがとう。しかし、残っている質問には気にしないでください。 – WonFeiHong

+1

'data()'への変更は標準で行われました。すべてのコンパイラが既に 'const'にキャストされた書き込み可能なポインタを返すからです。したがって、 'data()'から返された値を 'const_cast'すると、それは技術的に未定義の動作であっても、古いコンパイラでもうまくいく可能性があります。しかし、安全な方法は '&wstrbuff [0]'です。 –

+1

@ MarkRansom '&wstrBuff [0]'の "安全な方法"は、C++ 11以降でのみ安全です。その前に、文字はヌル文字で終わる連続したメモリのチャンクに格納されていることが標準で保証されていませんでした。 – zett42

関連する問題