none
CRichEditCtrl と CEdit の違いを吸収したい

    質問


  • VS2010 MFC で開発しています。

    現在CEditを使っているソースを CRichEditCtrlに変えているのですが2点の違いにハマっています。


    1. GetSelで返ってくる値が違う

       CEditとCRichEditCtrlに改行付の"\r\nA2-2 ト書き\r\n\r\nA2-4 ト書き"の文字を入れて
       GetSelを行うと、 CEditだと0,22 が返ってきて CRichEditCtrlは0,20が返ります。
       CEditは改行を2文字で計算しているようですが、 CRichEditCtrlの20文字はどうゆう意味なのか
       判りません。
       CEditと同じ解釈で値を得る方法はありますでしょうか?


    2. 日本語入力したとき CRichEditCtrlだと OnCharに来ない。

       文字入力全て自前でハンドリングするため、 OnCharで入力文字を得て処理をしています。
       CEditでは日本語入力確定のReturnキーを押すと OnCharに来るのですが、
       CRichEditCtrlでは来ません。 CRichEditCtrlでも同じようにOnCharかどこかで日本語入力文字を得る事は出来ますでしょうか?

    ご教授
    よろしくお願いします

    2017年9月20日 13:30

すべての返信

  • 1.についてですが、マニュアルでは、

    CEdit::GetSel( nStartChar, nEndChar)
      nStartChar 選択対象の最初の文字の位置。
      nEndChar   選択対象の終了文字に続く、最初の選択されていない文字の位置


    CRichEditCtrl::GetSel( nStartChar, nEndChar)
      nStartChar 現在の選択の先頭の文字の 0 から始まるインデックス
      nEndChar   現在の選択の最後の文字の 0 から始まるインデックス

    と説明されています。その通りの動作ではないでしょうか。

    両者は異なるコントロールなので、共通の派生元に無いメンバ関数においては、
    たとえ関数名が同じであっても、異なる動作を覚悟しなければなりません。
    本件の場合、両者はCWndの派生クラスであるという以外に、共通点は何もないと考えるべきかもしれません。

    2017年9月21日 1:23
  • 1. について、

    CRichEditCtrl では "\r\n" で設定された改行は GetSel では "\r" だけカウントされるようです(GetSelText で確認)。また、CRichEditCtrl でテキストを全選択すると文字列の最後尾の後ろの文字(終端文字?)も選択されるようです。そのため、CEdit で 22 と返された値は、CRichEditCtrl では、22 - 3(改行文字分) + 1(文字列終端文字分) = 20 となるようです。改行文字を "\r\n" として選択文字列の文字数を取得するには下記のようなコードでできるようです。この取得方法では、文字列の最後尾の後ろの文字もカウントされないため CEdit と同じ値になるのではないかと思います。

    // リッチエディットの文字数を取得
    GETTEXTLENGTHEX	textLenthEx = { 0 };
    textLenthEx.codepage = 1200;
    textLenthEx.flags = GTL_NUMCHARS | GTL_USECRLF;
    int nTextLen = m_richedit.SendMessageW(EM_GETTEXTLENGTHEX, (WPARAM)&textLenthEx, 0);
    
    // 選択文字列用のメモリ確保
    LPWSTR lpszSelectedText = (LPWSTR)GlobalAlloc(GMEM_FIXED, sizeof(WCHAR) * (nTextLen + 1));
    
    // 選択文字取得
    GETTEXTEX textEx = { 0 };
    textEx.cb = sizeof(WCHAR) * (nTextLen + 1);
    textEx.codepage = 1200;
    textEx.flags = GT_USECRLF | GT_SELECTION;
    m_richedit.SendMessageW(EM_GETTEXTEX, (WPARAM)&textEx, (LPARAM)lpszSelectedText);
    
    CString strMessage;
    strMessage.Format(TEXT("選択された文字数は %d"), lstrlenW(lpszSelectedText));
    MessageBox(strMessage);
    
    // 選択文字メモリ解放
    GlobalFree(lpszSelectedText);
    2017年9月21日 1:40
  • 2. について

    私の環境でも CRichEditCtrl で、IME での日本語入力確定時に OnChar が呼ばれませんでした。IME 終了のメッセージ WM_IME_ENDCOMPOSITION で文字列を取得するようにしてみてはいかがでしょうか?

    #include <Imm.h>
    #pragma comment(lib, "Imm32")
    
    LRESULT CMyRichEditCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    	if (message == WM_IME_ENDCOMPOSITION)
    	{
    		HIMC hIMC = ImmGetContext(this->GetSafeHwnd());
    		if (hIMC)
    		{
    			int nTextLength = ImmGetCompositionString(hIMC, GCS_RESULTSTR, 0, 0);
    			LPTSTR lpszText = (LPTSTR)GlobalAlloc(GMEM_ZEROINIT, sizeof(TCHAR)*(nTextLength + 1));
    			ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpszText, nTextLength);
    
    			// ここで IME の入力文字列に対しての処理を行う
    			OutputDebugString(lpszText);
    			OutputDebugString(TEXT("\r\n"));
    
    			GlobalFree(lpszText);
    			ImmReleaseContext(this->GetSafeHwnd(), hIMC);
    		}		
    	}
    
    	return CRichEditCtrl::WindowProc(message, wParam, lParam);
    }
    2017年9月21日 2:47
  • kenjinote様

    ソースは早速試してみます。

    ありがとうございました。

    2017年9月21日 3:14
  • 久しぶりのMFC さん、こんにちは
    フォーラム オペレーターの立花楓です。

    本件について、その後いかがでしょうか。
    課題が解決されたのであれば幸いですが、なにか進展がございましたらこちらのスレッドへご返信いただけますと幸いです。

    また、お寄せいただいた情報がお役に立った場合は、 [回答としてマーク] をお願いいたします。

    よろしくお願いいたします。


    MSDN/TechNet Community Support 立花楓

    2017年9月28日 6:42
    モデレータ