Setting selected text to read-only


If you do not want to allow any editing in the control you can call the function SetReadOnly(). This will disable all editing in the control. But that's not what this topic is about. The rich edit control also allows setting any text in the control to read only, somewhat akin to setting the text color. You can actually set the attribute of any selection of text to protected. Thereafter, if the user tries to change the text a EN_PROTECTED notification can be generated by the control.

Step 1: Set the ENM_PROTECTED event mask

For performance reasons, the rich edit control will generate some event notification only if the programmer has set the proper event mask. Since we are going to be using protected text, we have to enable the EN_PROTECTED notification message. We do this by calling the SetEventMask() function. If you are using a CRichEditView sub class, you can use the following code
void CMyRichEditView::OnInitialUpdate()
{
	CRichEditView::OnInitialUpdate();

	long eventmask = GetRichEditCtrl().GetEventMask() | ENM_PROTECTED;
	GetRichEditCtrl().SetEventMask( eventmask );
}

If instead, you are deriving from CRichEditCtrl, you can set the event mask in the PreSubclassWindow() function after calling the base class version of the function.

Step 2: Add handler for EN_PROTECTED

As I've already mentioned, the EN_PROTECTED notification message is sent whenever the user tries to modify a protected text. If you don't set the event mask as explained in step 1, then the control allows changing the protected text. If you do set the event mask but do not handle the notification, then the control still allows changing the protected text. In the EN_PROTECTED handler, you can decide whether to allow the modification or not.

The class wizard does not help in adding a handler for the EN_PROTECTED notification; you will have to add it manually. First the code snippet from the header file.

	//{{AFX_MSG(CMyRichEditView)
	:
	:
	//}}AFX_MSG
	afx_msg void OnProtected(NMHDR* pNMHDR, LRESULT* pResult);
	DECLARE_MESSAGE_MAP()

Now the message map entry in the implementation file and the function definition. In the handler we simply set the result to TRUE. This will disallow any change. If you want to allow editing in special circumstances, this is where you would add to code to decide whether to allow the edit.

BEGIN_MESSAGE_MAP(CMyRichEditView, CRichEditView)
	//{{AFX_MSG_MAP(CMyRichEditView)
	:
	:
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT(EN_PROTECTED, OnProtected)
END_MESSAGE_MAP()


void CMyRichEditView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult) 
{
	ENPROTECTED* pENPROTECTED = (ENPROTECTED* )pNMHDR;


	// Returning non zero will disallow change
	*pResult = TRUE;
}

Step 3: Change the character format to protected

Now we are ready to change the attribute of any selection to protected. Here's a function that will change the currect selection to protected text.
void CMyRichEditView::SetSelectionProtected() 
{
	CHARFORMAT cf;

	cf.cbSize = sizeof( cf );
	cf.dwMask = CFM_PROTECTED;
	cf.dwEffects = CFE_PROTECTED;

	GetRichEditCtrl().SetSelectionCharFormat( cf );
}