-1

私がする時:

SendMessage(editControlHWND, EM_EXGETSEL, 0, (LPARAM)&charRange);

選択した範囲のテキストを取得します。ただし、キャレットがこの選択のどこにあるか、つまり最後か最初かを知りたいです。

つまり、右から左にドラッグするなどのように、ユーザーがテキストを「後方」に選択しました。

EM_EXGETSELは常に の小さい方の数にcpMinなるため、明らかに選択順序とは関係ありません。

EM_EXGETSELかなりの量が既に選択されているため、この状況では比較のためにキャレットの位置を取得できません。

キャレットの現在の個々の位置を取得する方法はありますか (それを cpMin/cpMax と比較できるようにするため)? または、選択したテキストのブロック内でキャレットがどこにあるかを判断する方法はありますか?

編集:

これを行う理由についての私の説明: ユーザーがテキストを選択できる読み取り専用の RichEdit コントロールにプログラムでテキストを挿入します。ただし、テキストが最後に追加されると、キャレットを最後に移動してテキストを挿入する必要があります。これは、テキストが選択されている/ユーザーが現在テキストを選択しているときに発生する可能性があります。

面倒なのはこの最後のものです。テキストがプログラムによって入力される前後に、選択したテキストを取得および設定するために andEM_EXGETSELを使用します。EM_EXSETSELデフォルトでは、EM_EXGETSELは常に小さい方の数値を に配置します。cpMinつまり、ユーザーが現在テキストを後方 (右から左) に選択しており、テキストがコントロールに追加されている場合、選択領域のキャレットの位置が最初から最後に、これらの数値を に直接フィードするためEM_EXSETSELです。が逆方向に選択できることはわかっています ( の大きな数字と の小さなEM_EXSETSEL数字でこれをテストしました) が、ユーザーがテキストを逆方向に選択したことを示すものは何もありません。cpMincpMaxEM_EXGETSEL

したがって、キャレットの位置を比較したり、選択の最初または最後にあるかどうcpMincpMaxを確認したり、それに応じて行動する必要があります。

4

4 に答える 4

1

同じ問題を調べているときに、この投稿に出くわしました。

EN_SELCHANGE で通知された選択の変更を追跡し、WM_LBUTTONUP で結果を比較することで解決できました。

于 2016-02-20T16:02:19.700 に答える
0

これを行う簡単な方法はありません。EM_GETSEL現在の選択範囲をEM_EXGETSEL返します。選択がない場合にのみ、キャレットの位置を返します。

キャレットは、選択したテキストのブロック内に配置できないことに注意してください。キャレットは常に末尾または先頭にあります。

コントロールをサブクラス化し、EM_GETSELキーまたはマウス入力の後にキャレットの位置を照会して保存するために使用することで、おそらくソリューションをかなり簡単に実装できます。例えば

LRESULT WINAPI EditControlSubclassProc(...)
{
    LRESULT lRes = CallWindowProc(...); // call original window procedure
    if ((uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST)
    ||  (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
    {
        DWORD dwStart, dwEnd;
        SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
        if (dwStart == dwEnd)
        {
            // no current selection, so simply store the position of the caret
            g_dwCaretPos = dwStart;
        }
    }
    return lRes;
}

このようにして、最後に入力が選択されなかったときにキャレットがどこにあったかを常に知ることができます。次に、それを選択範囲と比較して、選択範囲がどちらの端に固定されているかを判断できるため、キャレットがもう一方の端にあることがわかります。

于 2013-08-23T00:58:43.790 に答える
0

サブクラス化の概念を理解していないため、そこにたどり着くのは少し複雑でしたが、なんとかこれを行うことができました。><

Spy++ を使用して、テキストを選択しているときに送信されたメッセージを確認しました。

これは明らかにEM_GETPASSWORDCHARメッセージだけでした。

だから私はした:

case EM_GETPASSWORDCHAR:
    {
        if(hwnd == editControlHwnd)
        {
            CHARRANGE tempCharRange;
            SendMessage(editControlHwnd, EM_EXGETSEL, 0, (LPARAM)&tempCharRange);
            SetSelectionDirection(tempCharRange.cpMin, tempCharRange.cpMax);
            return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
        }
    }

と:

void SubWindow::SetSelectionDirection(int newCpMin, int newCpMax) //Set selectionDirection to false if selecting backwards, true if selecting forwards
{
    if((newCpMin != prevCpMin) && (newCpMax == prevCpMax))
        selectionDirection = false;
    else if((newCpMin == prevCpMin) && (newCpMax != prevCpMax))
        selectionDirection = true;

    prevCpMin = newCpMin;
    prevCpMax = newCpMax;
}

ここbool selectionDirection;で、int prevCpMin;int prevCpMax;はプライベート クラス メンバ変数です。

このようにして、新しく選択した領域と以前に選択した領域を比較して、変更された端と変更されていない端を確認します。

ここで行っていることが実際にこれを解決する悪い方法であるかどうかはわかりませんが、これを行うためのより良い方法がある場合、私はそれを見つけていません. そのため、私の立場で他の誰かを助ける場合に備えて、これを回答として投稿しています。

于 2013-08-24T18:45:32.290 に答える