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 проверить, находится ли он в начале выбора или в конце, и действовать соответственно.

-1

Решение

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

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

1

Другие решения

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

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

0

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

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

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

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

0
По вопросам рекламы [email protected]