C++ EM_EXGETSEL与文本选择顺序无关。如何确定所选文本中插入符号的位置?
当我这样做时:C++ EM_EXGETSEL与文本选择顺序无关。如何确定所选文本中插入符号的位置?,c++,winapi,richedit-control,C++,Winapi,Richedit Control,当我这样做时: SendMessage(editControlHWND, EM_EXGETSEL, 0, (LPARAM)&charRange); 我得到选定的文本范围。然而,我想知道插入符号在这个选择中的位置,即在末尾或开头 例如,用户是否选择了“向后”文本,例如从右向左拖动 EM_EXGETSEL在cpMin中总是有较小的数字,因此显然与选择顺序无关 在这种情况下,我显然无法使用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_exsetel
。我知道EM_exsetel
能够向后选择(我已经用cpMin
中较大的数字和cpMax
中较小的数字进行了测试),但是EM_EXGETSEL
没有给出任何用户向后选择文本的指示
因此,我需要知道插入符号的位置,将其与
cpMin
或cpMax
进行比较,以检查它是在选择的开始还是结束,并相应地采取行动。没有简单的方法可以做到这一点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;
}
LRESULT WINAPI EditControlSubclassProc(…)
{
LRESULT lRes=CallWindowProc(…);//调用原始窗口过程
如果((uMsg>=WM\u KEYFIRST&&uMsg=WM\u MOUSEFIRST&&uMsg似乎可以使用EM\u LINEFROMCHAR
和EM\u LINEINDEX
with(WPARAM=-1)来使用。我已经成功地做到了这一点,尽管实现起来有点复杂。>只是在研究同样的问题时遇到了这篇文章
我可以通过跟踪EN_SELCHANGE通知的选择的更改并比较WM_LBUTTONUP的结果来解决问题。是的,我只对开始或结束感兴趣。不太确定插入符号如何最终进入选择本身…无论如何,我想我明白你的意思。有没有办法取消选择文本不移动插入符号?或者我必须模拟某种类型的按键,要么不移动插入符号,要么稍微移动插入符号,然后再返回?是的,您可以使用EM_setel
消息取消选择。是的,但这不会告诉我插入符号的原始位置在哪一端,对吗?取消选择是指取消选择d文本,但将插入符号的位置保持在最初选择的文本块的开头或结尾。不,您需要使用类似于我建议的方法来计算插入符号的位置,然后使用EM_setel
将其设置为该位置。我指的模拟按键等是因为这需要独立操作用户输入的依赖性。你为什么需要知道这一点?我觉得你的问题要简单得多。我已经在我的问题中添加了一个解释,解释了我为什么要这样做。为什么这一点被降低了?遗憾的是,这两个问题似乎都在拉回cpMin
所在的行,而不是在选择文本块时插入符号本身所在的行。
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;
}