EM_EXGETSEL не относится к порядку выбора текста. Как определить позицию каретки в фрагменте выделенного текста?

Когда я делаю:

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

Я получаю выбранный диапазон текста. Тем не менее, я хочу знать, где находится каретка в этом выборе, то есть в конце ИЛИ в начале.

т. е. выбрал ли пользователь текст "назад", как при перетаскивании справа налево.

EM_EXGETSEL всегда будет иметь меньшее число в cpMin, так что явно не относится к порядку выбора.

Я, очевидно, не могу получить позицию каретки с EM_EXGETSEL для сравнения в этой ситуации, потому что кусок материала уже выбран.

Есть ли способ получить текущую индивидуальную позицию каретки (чтобы я мог сравнить ее с cpMin/cpMax)? Или, альтернативно, есть ли способ определить, где каретка находится в блоке выделенного текста?

РЕДАКТИРОВАТЬ:

Мое объяснение, почему я хочу сделать это: я вставляю текст программно в элемент управления RichEdit только для чтения, из которого пользователь может выбирать текст. Однако, когда текст добавляется в конце, он должен переместить каретку в конец и вставить текст, и это может произойти, когда текст был выбран / пользователь в настоящее время выбирает текст.

Это последний, который беспокоит. я использую EM_EXGETSEL а также EM_EXSETSEL чтобы получить и установить выбранный текст до и после программного ввода текста. По умолчанию, EM_EXGETSEL всегда будет ставить меньшее число в cpMinЭто означает, что если пользователь в настоящее время выбирает текст в обратном направлении (т. е. справа налево), и текст добавляется в элемент управления, положение каретки в области выбора изменяется с начала до конца, потому что я передаю эти числа непосредственно в EM_EXSETSEL, я знаю это EM_EXSETSEL способен к обратному выбору (я проверил это с большим числом в cpMin и меньший в cpMax), но EM_EXGETSEL не дает никаких указаний на то, что пользователь выделил текст в обратном направлении.

Поэтому мне нужно знать позицию каретки, чтобы сравнить ее с cpMin или же cpMax проверить, находится ли он в начале выбора или в конце, и действовать соответственно.

4 ответа

Решение

Мне удалось это сделать, хотя добраться туда было немного сложно из-за недостатка понимания концепции подкласса. ><

Я использовал 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; являются частными переменными члена класса.

Таким образом, я сравниваю новую выбранную область с ранее выбранной областью, чтобы увидеть, какой конец изменился, а какой нет.

Я не знаю, является ли то, что я здесь делаю, плохим способом на самом деле решить это, но если есть лучший способ сделать это, я не нашел это. Вот почему я публикую это как ответ в том случае, если это поможет кому-то другому на моей должности.

Просто наткнулся на этот пост, глядя на ту же проблему.

Я смог решить эту проблему, отслеживая изменения в выборе, о которых уведомил EN_SELCHANGE, и сравнивая результаты на WM_LBUTTONUP.

Нет простого способа сделать это. 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;
}

Таким образом, вы всегда будете знать, где каретка была в последний раз, когда ввод был, что не привело к выбору. Затем вы можете сравнить его с диапазоном выбора, чтобы определить, к какому концу был привязан выбор, и, следовательно, узнать, что каретка находится на другом конце.

Кажется, что EM_LINEFROMCHAR а также EM_LINEINDEX с (WPARAM == -1).

Другие вопросы по тегам