i'm trying getting the richedit caret positions. seems that i can't use the caret functions.

LONG firstCharIndex(HWND hwnd)
    {
        POINT pt;
        pt.x=0;
        pt.y=0;
        LONG n = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt);
        return LOWORD(n);
    }

   COORD GetCaretPos( )
        {
            COORD pos;
            //getting the line from caret position:
            pos.Y=(LONG) SendMessage(consoleedit, EM_LINEFROMCHAR,(WPARAM)-1,0);
            CHARRANGE cr;
            cr.cpMin = 0;
            cr.cpMax = 0;
            SendMessage(consoleedit, EM_EXGETSEL, 0, (LPARAM)&cr);
            pos.X=cr.cpMin - firstCharIndex(consoleedit);
            DebugText("min: " + to_string(cr.cpMin) + " first: " + to_string(firstCharIndex(consoleedit)) );
            return pos;
        }

i get the Y correctly, but i don't understand how can i get the X.. can anyone advice me?

Dani AI

Generated

Nice catch by — the final approach (subtract the line’s first-character index from the caret character index) is the right, robust way to get a caret “column” in a RichEdit. Those messages are zero-based and accept -1 to mean “current line,” so the +1/−1 confusion comes from mixing a 1-based display with 0-based message semantics. See EM_LINEFROMCHAR and EM_LINEINDEX for the exact behavior. EM_LINEFROMCHAR EM_LINEINDEX. (learn.microsoft.com)

A couple of important pitfalls to watch for: read the selection with EM_EXGETSEL/EM_GETSEL — when there is no selection the start and end are equal (that position is the insertion point). If a selection exists and you specifically need the insertion endpoint, either collapse the selection first or pick the endpoint you intend. EM_GETSEL / EM_EXGETSEL. (learn.microsoft.com)

If the goal is the visual/pixel X (not the character column) — for variable-width fonts, tabs, bidi text, wrapped lines, etc. — use EM_POSFROMCHAR to get client coordinates of a character and EM_CHARFROMPOS to go from a point back to a character. That avoids guessing X by character counts. EM_POSFROMCHAR EM_CHARFROMPOS. (learn.microsoft.com)

Quick checklist: keep line numbers zero-based internally and only add 1 for UI; use EM_EXGETSEL to get the caret index, EM_LINEINDEX (or EM_LINEFROMCHAR) to find the line start, subtract to get the column, or call EM_POSFROMCHAR if you need pixel coordinates. For very large documents note the extended messages (e.g., EM_EXLINEFROMCHAR) as documented. EM_EXLINEFROMCHAR. (learn.microsoft.com)

Recommended Answers

All 6 Replies

the GetCaretPos() don't works on richedit :(
unless, first, i need recreate it?

Sorry about that. I was guessing you are on a win32/64 app. Let's hear a little more detail. The user32.dll should work but of course not on non-windows.

Try EM_LINEINDEX message, specifying -1 for the wParam

commented: thanks for all +3

nullptr: that gives me the character position on where is the caret. but give me the text position and not the line position.(the coordenates are gived by entire text, and not line position). i can't divide with number of lines because the lines don't have the same lenght deppending on it's font

finally it's working greate:

void SetCaretPos(POINT pos)
    {
        LONG characterIndexLine =0;
        characterIndexLine=(LONG) SendMessage(consoleedit, EM_LINEINDEX, (WPARAM) pos.y-1,0);
        characterIndexLine+=(LONG)pos.x;
        CHARRANGE cr;
        cr.cpMin = characterIndexLine;
        cr.cpMax = characterIndexLine;
        SendMessage(consoleedit, EM_EXSETSEL, 0, (LPARAM)&cr);
    }

    COORD GetCaretPos( )
    {
        COORD pos;
        //getting the line where is the caret(WPARAM is -1 for the caret position):
        pos.Y=(LONG) SendMessage(consoleedit, EM_LINEFROMCHAR,(WPARAM)-1,0)+1;

        //getting the caret on text position:
        CHARRANGE cr;
        cr.cpMin = 0;
        cr.cpMax = 0;
        SendMessage(consoleedit, EM_EXGETSEL, 0, (LPARAM)&cr);

        //getting the 1st charater line position(is gived on text position). for use the caret position, we can use -1:
        LONG firstcharacter=SendMessage(consoleedit, EM_LINEINDEX, (WPARAM)-1,0);

        //the caret text position minus the 1st character on that line, will give me the x:
        pos.X=cr.cpMin-firstcharacter;
        return pos;
    }

why on set '-1' and on get '+1'?
because the lines are indexed by zero.
thanks for all
PS: readers when we need use 1 function name igual of the win32 function name, we must use '::' before the win32 functions name ;)

nullptr: you tryied tell me something. but with more search i get it.. thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.