Controlling the RichTextCtrl Insert State

Environment: NT 4.0 SP4, VC6.0

Every RichTextCtrl has its own insert state that is independent of the global insert state as well as the insert state of all other RichTextCtrls. That would be fine if you had some way to read and change the state. But you don’t. The RichTextCtrl has no property to check the state, and it has no message to check the state.

The RichEditCtrl always starts with insert mode on and then toggles every time the user presses the Insert key. So we have to keep track of using the insert key.

In this example the state of the insert key is shown in the statusbar, (dimmed or not). It is possible to change the state by pressing the insert key or by doubleclicking on the status pane for the overwrite status. (doubleclicking the NUM or CAP pane will also change the keyboard state)

Step 1:

Keep track of the use of the insert key:


void COverWriteView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (nChar == VK_INSERT) 
	{
		BOOL bShift	= GetKeyState(VK_SHIFT) < 0;
		BOOL bCtrl	= GetKeyState(VK_CONTROL) < 0;
		if (!bShift && !bCtrl)
			((CChildFrame *) GetParent())->ChangeOverwrite();
	}
	CRichEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

Step 2:

Create the status bar in the ChildFrame


static UINT Indicators[] =
{
    ID_SEPARATOR, // status line indicator
    ID_SEPARATOR,
    ID_INDICATOR_OVERWRITE,
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_SEPARATOR,
};


// CChildFrame message handlers

BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
    if (!m_wndStatus.CreateEx(this,SBT_TOOLTIPS ,
        WS_CHILD | WS_VISIBLE | CBRS_BOTTOM ,IDS_STATUS))
    {
        TRACE0("Failed to create status bar in child frame\n");
        return CMDIChildWnd::OnCreateClient(lpcs, pContext);
    }
    m_wndStatus.SetIndicators(Indicators,sizeof(Indicators)/sizeof(UINT));

//    Setting the pane infos
    m_wndStatus.SetPaneInfo(0, m_wndStatus.GetItemID( 0 ),SBPS_STRETCH, NULL );
    m_wndStatus.SetPaneInfo(1, m_wndStatus.GetItemID( 1 ),SBPS_STRETCH, NULL );
    m_wndStatus.SetPaneInfo(2, m_wndStatus.GetItemID( 2 ),SBT_OWNERDRAW, 19 );
    m_wndStatus.SetPaneInfo(3, m_wndStatus.GetItemID( 3 ),SBT_OWNERDRAW, 18 );
    m_wndStatus.SetPaneInfo(4, m_wndStatus.GetItemID( 4 ),SBT_OWNERDRAW, 22 );
    m_wndStatus.SetPaneInfo(5, m_wndStatus.GetItemID( 5 ),SBPS_NOBORDERS, 14 );
    
    m_wndStatus.GetStatusBarCtrl().SetTipText(5, "Doubleclick for Info");
    m_wndStatus.SetStatusBarFlag(0);

    
    return CMDIChildWnd::OnCreateClient(lpcs, pContext);
}

Step3:

Show the status in the status bar


void COverwriteStatus::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
    CDC dc;
    dc.Attach(lpDrawItemStruct->hDC);
    CRect cRect(&lpDrawItemStruct->rcItem);
    int nOldBkMode = dc.SetBkMode(TRANSPARENT);

//    Show only the animation, if the selected measure is identical with the running Id
    COLORREF cOldFgColor = dc.GetTextColor();
    COLORREF cTxColor = RGB(0,0,0);

    switch(lpDrawItemStruct->itemID) 

    { 
    case 2:        //    Insert/Overwrite
        {
            if (((CChildFrame *)GetParent())-> IsOverwrite ()) cTxColor = RGB(0,0,0);

//    This method can only be used, if there is only one Edit-Window
//            if ( ::GetKeyState(VK_INSERT) & 0x0001) cTxColor = RGB(0,0,0);
            else cTxColor = RGB(128,128,128);
            break;    
        }
    case 3:        // Caps-Lock
        {
            if ( ::GetKeyState(VK_CAPITAL) & 0x0001) cTxColor = RGB(0,0,0);
            else cTxColor = RGB(128,128,128);
            break;
        }
    case 4:        //    Num-Lock
        {
            if ( ::GetKeyState(VK_NUMLOCK) & 0x0001) cTxColor = RGB(0,0,0);
            else cTxColor = RGB(128,128,128);
            break;
        }
    }
    dc.SetTextColor(cTxColor);
    CString cText = GetPaneText(lpDrawItemStruct->itemID);
    dc.DrawText(cText,cRect, DT_LEFT); 
    dc.SetTextColor(cOldFgColor);
    dc.SetBkMode(nOldBkMode);
    dc.Detach(); 
}

Step 4:

Change the insert state by double click of the status pane


void COverwriteStatus::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	int nPane = GetPaneAtPosition(point);
	switch (nPane)
	{
	case 2:
		ChangeInsert();
		break;
	case 3:
		ChangeCapsLock();
		break;
	case 4:
		ChangeNumLock();
		break;
	case 5: 
		{
			SetStatusBarFlag(1);
			((COverWriteApp * )AfxGetApp())->OnAppAbout();
			SetStatusBarFlag(0);
		}
		break;
	}
	CStatusBar::OnLButtonDblClk(nFlags, point);
}


int COverwriteStatus::GetPaneAtPosition(CPoint& point)
{
	CRect rect;
	for (int i = 0, n = GetCount(); i < n; i++)
	{
		GetItemRect(i, rect);
		if (rect.PtInRect(point))	return i;
	}
	return -1;
}


void COverwriteStatus::ChangeInsert()
{ 
    keybd_event( VK_INSERT, 0x0, KEYEVENTF_EXTENDEDKEY , 0 );
    keybd_event( VK_INSERT, 0x0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}

Download demo project - 55 KB

Download source - 24 KB



Comments

  • Use TOM interfaces

    Posted by Legacy on 02/09/2004 12:00am

    Originally posted by: Carc

    Use TOM interfaces. 
    
    long l;
    ITextSelection::GetFlags(&l);
    if (l & 0x04) {
    TRACE("overwrite mode\n");
    }
    else {
    TRACE("insert mode\n");

    }

    Reply
  • Simplifying with ON_UPDATE_COMMAND_UI message map macro

    Posted by Legacy on 04/24/1999 12:00am

    Originally posted by: JimB0


    A simpler solution could involve using the ON_UPDATE_COMMAND_UI message map macro. Start by adding a boolean member variable to your class derived from CRichEditView called m_bInsertMode. Be sure to initialize it to true in your overloaded Create or PreCreateWindow to reflect the controls default state.

    Add a message handeler for WM_KEYDOWN wich toggles our boolean variable:

    void CRichEditViewEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
    if (nChar == VK_INSERT)
    {
    BOOL bShift = GetKeyState(VK_SHIFT) < 0;
    BOOL bCtrl = GetKeyState(VK_CONTROL) < 0;
    if (!bShift && !bCtrl)
    m_bInsertMode = !m_bInsertMode;
    }
    CCtrlView::OnKeyDown(nChar, nRepCnt, nFlags);
    }

    Add a message map entry to handel command UI update requests for ID_INDICATOR_OVR (the ID for the over type indecator in the satus bar).

    ON_UPDATE_COMMAND_UI(ID_INDICATOR_OVR, OnUpdateStatusOvertype)

    Add the coresponding member function:

    void CRichEditViewEx::OnUpdateStatusOvertype(CCmdUI* pCmdUI)
    {
    ASSERT_VALID(this);
    pCmdUI->Enable(!m_bInsertMode);
    }

    This example uses the default implementation of a single status bar attached to the mainframe window as created by MFC application wizard. As such you will need to add ID_INDICATOR_OVR to the list of indicators in your MainForm.CPP file:

    static UINT indicators[] =
    {
    ID_SEPARATOR, // status line indicator
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
    ID_INDICATOR_OVR,
    };

    ID_INDICATOR_OVR is allready defined for you in the MFC header files and there is a string table entry for it as well.

    Reply
  • Set Insert state for multiply RichEditCtrls on formview

    Posted by Legacy on 03/23/1999 12:00am

    Originally posted by: Adnan Malik

    I had problems trying to set the insert state for RichEditCtrls on a formview. In the OnInitialUpdate function of the form view, I set the focus on the RichEditCtrl and then send the keybd_event fuction with VK_INSERT parameter. This works, but when I try to set the state for multiply RichEditCtrls, it does not work. Thanks for any input.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Confused by all the agile advice? Relax! With the Agile for Dummies eBook by your side you'll learn the fundamentals of agile and how to increase the productivity of your software teams while enabling them to produce higher-quality solutions that better fulfill customer needs much faster.

  • The latest release of SugarCRM's flagship product gives users new tools to build extraordinary customer relationships. Read an in-depth analysis of SugarCRM's enhanced ability to help companies execute their customer-facing initiatives from Ovum, a leading technology research firm.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds