Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ EM_EXGETSEL与文本选择顺序无关。如何确定所选文本中插入符号的位置?_C++_Winapi_Richedit Control - Fatal编程技术网

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;
}