The standard behavior of the rich edit control when text is inserted is to apply the character formatting that is in effect at the insertion point. That is why after setting the color of the custom format text to green in OnInitDialog typing text at position 0 receives the green color. Following example sets the custom format text as protected and then uses the EN_PROTECTED handler to process inserted text at position 0 (or elsewhere). I didn't try to code the example to handle all possibilities.
In OnInitDialog
m_richeditctrl.SetEventMask(m_richeditctrl.GetEventMask() | ENM_PROTECTED);
CHARFORMAT cfm{ sizeof cfm };
m_richeditctrl.ReplaceSel(_T("%###%"));
cfm.dwMask = CFM_COLOR | CFM_PROTECTED;
cfm.dwEffects = CFE_PROTECTED;
cfm.crTextColor = RGB(0, 255, 0);
m_richeditctrl.SetSel(0, 5);
m_richeditctrl.SetSelectionCharFormat(cfm); // set custom format text to green and make protected
In EN_PROTECTED handler -
LRESULT lres = 0;
ENPROTECTED *pEnProtected = reinterpret_cast<ENPROTECTED *>(pNMHDR);
// TODO: The control will not send this notification unless you override the
// CDialogEx::OnInitDialog() function to send the EM_SETEVENTMASK message
// to the control with the ENM_PROTECTED flag ORed into the lParam mask.
// TODO: Add your control notification handler code here
TRACE(_T("Msg 0x%X, start %d, end %d\n"), pEnProtected->msg, pEnProtected->chrg.cpMin, pEnProtected->chrg.cpMax);
if (pEnProtected->msg == WM_CHAR)
{
CHARRANGE cr = pEnProtected->chrg;
CHARFORMAT cfDefault{ sizeof cfDefault };
m_richeditctrl.GetDefaultCharFormat(cfDefault);
bool bInsertionpoint = true;
if (cr.cpMin == cr.cpMax)
++cr.cpMax;
else
bInsertionpoint = false;
CString str;
m_richeditctrl.GetTextRange(cr.cpMin, cr.cpMax, str);
if ((pEnProtected->chrg.cpMin == 0 && bInsertionpoint) || str.FindOneOf(_T("%#")) == -1) //
{
m_richeditctrl.SetSel(pEnProtected->chrg);
m_richeditctrl.SetSelectionCharFormat(cfDefault);
TRACE(_T("Default format applied\n"));
}
else
{
TRACE(_T("Change not allowed\n"));
lres = 1;
}
}
*pResult = lres;