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

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds