当我这样做时:
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
进行比较,以检查它是在选择的开头还是结尾,并采取相应的行动。
答案 0 :(得分:1)
在调查同样的问题时,我刚看过这篇文章。
我能够通过跟踪EN_SELCHANGE通知的选择的更改并比较WM_LBUTTONUP的结果来解决。
答案 1 :(得分:0)
没有简单的方法可以做到这一点。 EM_GETSEL
和EM_EXGETSEL
返回当前选择的范围。只有在没有选择的情况下才会返回插入符号的位置。
请注意,插入符号不能 所选文本块 - 它始终位于结尾或开头。
您可以通过对控件进行子类化并使用EM_GETSEL
在任何键或鼠标输入后查询和存储插入符的位置,相当容易地实现解决方案。 E.g。
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;
}
通过这种方式,您将始终知道最后一次输入没有导致选择时插入符号的位置。然后,您可以将其与选择范围进行比较,以确定选择锚定在哪一端,因此知道插入符号位于另一端。
答案 2 :(得分:0)
似乎可以使用EM_LINEFROMCHAR
和EM_LINEINDEX
(WPARAM == -1)。
答案 3 :(得分:0)
我设法做到了这一点,虽然到达那里due to my lack of understanding on the concept of sub-classing有点复杂。 &GT;&LT;
我使用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;
是私有类成员变量。
这样,我将新选择的区域与先前选择的区域进行比较,以查看哪个区域已更改,哪个区域没有更改。
我不知道我在这里做什么是实际解决这个问题的一个坏方法,但如果有更好的方法来做到这一点,我还没有找到它。这就是为什么我发布这个作为答案的原因,以帮助其他人担任我的职位。