c++mfceditbox

Caret position in EditBox after change in text length


I have an EditBox in a MFC-dialog. The user is supposed to enter a number. I'm trying to automatically add separators to the number while the user is inputting it:

When the number is more than 3 digits long, a separator is added between the hundreds and the thousands digit; a second one between the hundredthousands and the millions when it gets longer than 6 digits and so forth (so that 1234567 becomes 1,234,567 for example).

This is done in a function executed by ON_EN_CHANGE and basically works fine already. But the problem is that the caret position is set to the beginning of the EditBox once my function changes the length of the string in it, preventing continous typing.

I tried simulating the press of the end-key to send the caret to the end of the EditBox, which works as long as the user only enters a number from left to right. But it won't work when the user is trying to add, remove or edit digits in the middle of the number. I need the caret position at the exact spot of the number where it was before the user pressed a key.

I tried calculating the new caret position from the previous one (gotten with CEdit::GetSel()) and the previous length of the number:

OnEnChange()
{
    int prevCursPos {HIWORD(m_editCtrl.GetSel())};
    int prevStrLen {m_editCtrl.GetWindowTextLengthW()};
    UpdateData(TRUE);
    // Adding/Removing of separators as needed
    UpdateData(FALSE);
    int difference {m_editCtrl.GetWindowTextLengthW() - prevStrLen))};
    if(difference > 0) // a separator has been added to the string
        m_editCtrl.SetSel(-1, prevCursPos + 1);
}

However, the SetSel() function doesn't seem to have any effect. I also tried to send an EM_SETSEL message instead, but I couldn't figure out how to make that work either, the caret always resets itself to the beginning of the EditBox.

Does anyone have another idea on how to accomplish what I'm trying to do?


Solution

    1. It is unclear how you are handling "/ Adding/Removing of separators as needed".
    2. SetSel with the first parameter set to -1 will position the caret at the beginning of the string if the string changes after calling UpdateData(false)

    Create CString type of the variable (m_csEdit for example) for this edit control and

        int iLen = m_csDDx.GetLength();
        m_editCtrl.SetSel(iLen, -1);
    

    or

        m_editCtrl.SetSel(iLen, iLen);
    

    You can calculate the length differently from what I suggested. Consider using masked edit control (maybe).

    Forgot to mention. Use GetNumberFormatEx to format number with thousand delimiter.