その2

引き続きエディットコントロールあれこれです。
今回は少し長いです(´ω`)



EM_SETSEL
指定した範囲を選択状態にする
wParam : 選択の開始文字位置
lParam : 選択の終了文字位置

このメッセージは前回「VC++風(下から上へ)」でやったように、wParamとlParamを入れ替えることで
始点(選択開始点)と終点(現在のキャレット位置)を逆にすることができます。


EM_GETSEL
選択状態の範囲を取得する
wParam : 選択の開始文字位置
lParam : 選択の終了文字位置

EM_SETSELと同じような感じ…と思ったらどっこいです。
始点と終点が逆(start>end)になっていても、常にstart<endが返されます。
これでは選択中にキャレット位置を求めることができません。
で、何とかして位置を知りたくていろいろ実験した結果、以下のことが分かりました。


EM_LINEFROMCHAR
指定した位置の行番号を返す(-1を指定した場合キャレット位置(始点終点問わず値が小さい方)が対象)

EM_LINEINDEX
指定行のオフセット位置を返す(存在しない行なら-1を返す。-1を指定した場合キャレット(終点)のある行が対象)

>-1を指定した場合キャレット(終点)のある行が対象)
待ってました(´▽`*)
早速これを使って逆転の取得をしてみます。


GetCaret() {
    // 終点を返り値に使用するので必ず取得
    ::SendMessage(hEdit, EM_GETSEL, (WPARAM)&nStart, (LPARAM)&nEnd);

    if (GetLineIndex(nStart)==GetLineIndex(nEnd)) {
        // 同じ行にあると逆転の取得不可
    }
    else if (GetLineIndex(-1)==GetLineIndex(GetLinePos(-1))) {
        // 小さい方==終点 → nStart>nEndなので逆転させる
        nStart = nStart ^ nEnd;
        nEnd   = nStart ^ nEnd;
        nStart = nStart ^ nEnd;
    }
}
GetLineIndex() {
    return SendMessage(EM_LINFROMCHAR);
}
GetLinePos() {
    return SendMessage(EM_LINEINDEX);
}

同じ行のときに取得する方法はあるのでしょうか...(´ω`)