dcsimg
December 11, 2016
Hot Topics:

Controlling the RichTextCtrl Insert State

  • March 9, 1999
  • By Roland Schneewind
  • Send Email »
  • More Articles »

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

Date Posted: 09 March 1999






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel