📄 customeditctrl.cpp
字号:
// CustomEditCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "bcgcbdotnetexample.h"
#include "CustomEditCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
struct TipString
{
LPCTSTR lpszTip;
LPCTSTR lpszContent;
};
static TipString g_aTipText[] =
{
{_T("CMyClass"),_T("class CMyClass")},
{_T("ind"),_T("int ind = -1")},
{_T("memset"),_T("void * memset(void *, int, size_t)")},
{_T("m_lf"),_T("LOGFONT CMyClass::m_lf")},
{_T("m_bTrace"),_T("BOOL CMyClass::m_bTrace")},
{_T("OnDestroy"),_T("void CMyClass::OnDestroy ()")},
{_T("DoMain"),_T("int CMyClass::DoMain ()")},
{_T("printf"),_T("int printf (const char *, ...)")},
{_T("GetAppName"),_T("const char* CMyClass::GetAppName()")},
{_T("EnableTrace"),_T("void CMyClass::EnableTrace(BOOL bTrace = TRUE)")},
{_T("bTrace"),_T("BOOL bTrace = TRUE")},
{_T("DO_TRACE"),_T("#define DO_TRACE(bTrace, lpszText) { if (bTrace) { printf(\"%s\\n\",lpszText); } }")},
{_T("main"),_T("int main(int argc, char* argv[])")},
{_T("pMyClass"),_T("CMyClass* pMyClass = new CMyClass(argc, argv)")},
{_T("nRet"),_T("int nRet = pMyClass->DoMain()")}
};
struct StringIndex
{
LPCTSTR lpszName;
int nIndex;
};
static StringIndex g_aStringIndex1[] =
{
{_T("CMyClass"), 3},
{_T("DoMain"), 3},
{_T("EnableTrace"), 3},
{_T("GetAppName"), 3},
{_T("m_argc"), 5},
{_T("m_argv"), 5},
{_T("m_bTrace"), 4},
{_T("m_lf"), 4},
{_T("OnDestroy"), 6},
{ NULL }
};
static StringIndex g_aStringIndex2[] =
{
{_T("lfHeight"), 7},
{_T("lfWidth"), 7},
{_T("lfEscapement"), 7},
{_T("lfOrientation"), 7},
{_T("lfWeight"), 7},
{_T("lfItalic"), 7},
{_T("lfUnderline"), 7},
{_T("lfStrikeOut"), 7},
{_T("lfCharSet"), 7},
{_T("lfOutPrecision"), 7},
{_T("lfClipPrecision"), 7},
{_T("lfQuality"), 7},
{_T("lfPitchAndFamily"), 7},
{_T("lfFaceName"), 7},
{ NULL }
};
struct IntelliStringArray
{
LPCTSTR lpszName;
StringIndex* ptr;
};
static IntelliStringArray g_aIntelliStringArray[] =
{
{_T("this->"), g_aStringIndex1},
{_T("pMyClass->"), g_aStringIndex1},
{_T("CMyClass::"), g_aStringIndex1},
{_T("this->m_lf."), g_aStringIndex2},
{_T("pMyClass->m_lf."), g_aStringIndex2},
{_T("CMyClass::m_lf."), g_aStringIndex1},
{_T ("this->m_lf.lfFaceName->"), NULL},
{_T ("pMyClass->m_lf.lfFaceName->"), NULL},
{_T ("this->m_argv->"), NULL},
{_T ("pMyClass->m_argv->"), NULL},
};
/////////////////////////////////////////////////////////////////////////////
// CCustomEditCtrl
CStringList CCustomEditCtrl::m_lstFind;
CCustomEditCtrl::CCustomEditCtrl()
{
m_bEnableBreakpoints = FALSE;
m_bCheckColorTags = FALSE;
PrepareIntelliSense();
}
void CCustomEditCtrl::PrepareIntelliSense()
{
for (int ind = sizeof(g_aIntelliStringArray) / (sizeof(IntelliStringArray));
ind-- != 0;
m_mIntelliString.SetAt(g_aIntelliStringArray[ind].lpszName,g_aIntelliStringArray[ind].ptr));
for (ind = sizeof(g_aTipText) / sizeof(TipString);
ind-- != 0;
m_mTipString.SetAt(g_aTipText[ind].lpszTip,g_aTipText[ind].lpszContent));
}
CCustomEditCtrl::~CCustomEditCtrl()
{
}
BEGIN_MESSAGE_MAP(CCustomEditCtrl, CBCGPEditCtrl)
//{{AFX_MSG_MAP(CCustomEditCtrl)
ON_WM_CREATE()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCustomEditCtrl message handlers
BOOL CCustomEditCtrl::FindText(LPCTSTR lpszFind, BOOL bNext /* = TRUE */, BOOL bCase /* = TRUE */, BOOL bWholeWord /* = FALSE */)
{
POSITION pos = m_lstFind.Find(lpszFind);
if (pos != NULL)
{
m_lstFind.RemoveAt (pos);
}
m_lstFind.AddHead(lpszFind);
return CBCGPEditCtrl::FindText(lpszFind, bNext, bCase, bWholeWord);
}
void CCustomEditCtrl::OnDrawMarker (CDC* pDC, CRect rectMarker, const CBCGPEditMarker* pMarker)
{
if (pMarker->m_dwMarkerType & g_dwBreakPointType)
{
CBrush br (RGB (127, 0, 0));
CPen pen (PS_SOLID, 1, RGB (127, 0, 0));
CBrush* pBrOld = pDC->SelectObject (&br);
CPen* pOldPen = pDC->SelectObject (&pen);
rectMarker.DeflateRect (1, 1);
rectMarker.left = rectMarker.left + rectMarker.Width () / 2 - rectMarker.Height () / 2 - 1;
rectMarker.right = rectMarker.left + rectMarker.Height ();
pDC->Ellipse (rectMarker);
pDC->SelectObject (pBrOld);
pDC->SelectObject (pOldPen);
}
else
{
CBCGPEditCtrl::OnDrawMarker (pDC, rectMarker, pMarker);
}
}
int CCustomEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CBCGPEditCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
if (m_lstFind.IsEmpty ())
{
CBCGPToolbarComboBoxButton* pSrcCombo = NULL;
CObList listButtons;
if (CBCGPToolBar::GetCommandButtons (ID_EDIT_FIND_COMBO, listButtons) > 0)
{
for (POSITION posCombo = listButtons.GetHeadPosition ();
pSrcCombo == NULL && posCombo != NULL;)
{
CBCGPToolbarComboBoxButton* pCombo =
DYNAMIC_DOWNCAST (CBCGPToolbarComboBoxButton, listButtons.GetNext (posCombo));
if (pCombo != NULL)
{
pSrcCombo = pCombo;
}
}
}
if (pSrcCombo != NULL)
{
if (const int nMax = pSrcCombo->GetCount())
{
CString sText;
CComboBox* pCombo = pSrcCombo->GetComboBox();
for (int i = 0; i < nMax; i++)
{
pCombo->GetLBText(i,sText);
m_lstFind.AddTail (sText);
}
pCombo->SetCurSel(0);
}
}
}
return 0;
}
BOOL CCustomEditCtrl::CheckIntelliMark(const CString& strBuffer, int& nOffset, CString& strWordSuffix) const
{
BOOL bIntelliMark = (strBuffer.GetAt (nOffset) == _T ('.'));
if (bIntelliMark)
{
strWordSuffix = _T('.');
}
else if (strBuffer.GetAt (nOffset) == _T ('>'))
{
int nTempOffset = nOffset;
if (GetNextPos(strBuffer, m_strNonSelectableChars, nTempOffset, FALSE) >= 0)
{
if (strBuffer.GetAt (nTempOffset) == _T ('-'))
{
strWordSuffix = _T("->");
nOffset = nTempOffset;
bIntelliMark = TRUE;
}
}
}
else if (strBuffer.GetAt (nOffset) == _T (':'))
{
int nTempOffset = nOffset;
if (GetNextPos(strBuffer, m_strNonSelectableChars, nTempOffset, FALSE) >= 0)
{
if (strBuffer.GetAt (nTempOffset) == _T (':'))
{
strWordSuffix = _T("::");
nOffset = nTempOffset;
bIntelliMark = TRUE;
}
}
}
if (bIntelliMark)
{
nOffset--;
}
return bIntelliMark;
}
BOOL CCustomEditCtrl::OnBeforeInvokeIntelliSense (const CString& strBuffer, int& nCurrOffset, CString& strIntelliSence) const
{
if (!IsIntelliSenseEnabled())
{
return FALSE;
}
strIntelliSence.Empty();
int nOffset = nCurrOffset;
if (nOffset > strBuffer.GetLength())
{
nOffset = strBuffer.GetLength();
}
if (nOffset >= 0)
{
for (--nOffset;
nOffset >= 0 &&
m_strIntelliSenseChars.Find(strBuffer.GetAt(nOffset)) == -1 &&
(m_strNonSelectableChars.Find(strBuffer.GetAt(nOffset)) >= 0 ||
m_strWordDelimeters.Find(strBuffer.GetAt(nOffset)) == -1);
nOffset--);
if (nOffset >= 0 &&
FillIntelliSenceWord(strBuffer,nOffset,strIntelliSence) &&
IsIntelliSenceWord(strIntelliSence))
{
nCurrOffset = nOffset + 1;
return TRUE;
}
}
else
{
ASSERT(FALSE);
}
return FALSE;
}
BOOL CCustomEditCtrl::FillIntelliSenseList (CObList& lstIntelliSenseData,
LPCTSTR lpszIntelliSense /* = NULL */) const
{
if (lpszIntelliSense == NULL)
{
BOOL bRet;
CString strIntelliSence;
int nCurrOffset = m_nCurrOffset;
if (!OnBeforeInvokeIntelliSense(m_strBuffer, nCurrOffset, strIntelliSence))
{
return FALSE;
}
bRet = FillIntelliSenseList(lstIntelliSenseData, strIntelliSence.GetBuffer(0));
ASSERT(bRet);
return bRet;
}
if (!IsIntelliSenseEnabled() ||
!IsIntelliSenceWord(lpszIntelliSense))
{
return FALSE;
}
StringIndex* pStringIndex;
if (!m_mIntelliString.Lookup(lpszIntelliSense, (void*&)pStringIndex))
{
return FALSE;
}
CBCGPIntelliSenseData* pData;
lstIntelliSenseData.RemoveAll();
for (int ind = 0; pStringIndex[ind].lpszName != NULL; ind++)
{
pData = new CBCGPIntelliSenseData;
pData->m_strItemName = pStringIndex[ind].lpszName;
pData->m_nImageListIndex = pStringIndex[ind].nIndex;
lstIntelliSenseData.AddTail (pData);
}
return TRUE;
}
BOOL CCustomEditCtrl::IsIntelliSenceWord(const CString& strWord) const
{
if (!IsIntelliSenseEnabled())
{
return FALSE;
}
StringIndex* pStringIndex;
if (m_mIntelliString.Lookup(strWord, (void*&)pStringIndex))
{
return TRUE;
}
return FALSE;
}
BOOL CCustomEditCtrl::OnGetTipText (CString& strTipString)
{
if (!IsIntelliSenseEnabled())
{
return FALSE;
}
CString strTipContent;
if (m_mTipString.Lookup(strTipString,strTipString))
{
return TRUE;
}
return FALSE;
}
BOOL CCustomEditCtrl::IntelliSenseCharUpdate(const CString& strBuffer, int nCurrOffset, TCHAR nChar, CString& strIntelliSense)
{
if (!IsIntelliSenseEnabled())
{
return FALSE;
}
if (nChar == _T('.'))
{
if ((nCurrOffset > 0) && (nCurrOffset <= strBuffer.GetLength()) &&
strBuffer.GetAt(nCurrOffset - 1) == nChar)
{
CString strWord;
int nOffset = nCurrOffset;
if (!OnBeforeInvokeIntelliSense(strBuffer, nOffset, strWord))
{
nOffset = strWord.GetLength();
if ((nOffset > 1) && (strWord.GetAt(nOffset - 1) == nChar))
{
strWord.SetAt(nOffset - 1, _T('-'));
strWord += _T('>');
nOffset++;
if (IsIntelliSenceWord(strWord))
{
strIntelliSense = _T("->");
return TRUE;
}
}
}
}
else
{
ASSERT(FALSE);
}
}
return FALSE;
}
BOOL CCustomEditCtrl::EnableBreakpoints(BOOL bFl /* = TRUE */)
{
const BOOL bEnableBreakpoints = m_bEnableBreakpoints;
m_bEnableBreakpoints = bFl;
return bEnableBreakpoints;
}
int CCustomEditCtrl::GetNextPos(const CString& strBuffer, const CString& strSkipChars, int& nPos, BOOL bForward)
{
if (bForward)
{
for (int nLen = strBuffer.GetLength();
nPos < nLen &&
strSkipChars.Find(strBuffer.GetAt(nPos)) >= 0;
nPos++);
}
else
{
for (--nPos;
nPos >= 0 &&
strSkipChars.Find(strBuffer.GetAt(nPos)) >= 0;
nPos--);
}
return nPos;
}
BOOL CCustomEditCtrl::FillIntelliSenceWord(const CString& strBuffer, int nOffset, CString& strIntelliSence) const
{
CString strISWord, strWordSuffix;
if (!CheckIntelliMark(strBuffer,nOffset,strWordSuffix) || nOffset >= 0)
{
do
{
int nStartOffset = -1,
nEndOffset = -1;
FindWordStartFinish (nOffset, strBuffer, nStartOffset, nEndOffset);
if ((nStartOffset < nEndOffset) && (nStartOffset >= 0))
{
const CString& strWord = strBuffer.Mid(nOffset = nStartOffset, nEndOffset - nStartOffset);
strISWord = strWord + strWordSuffix + strISWord;
}
else
{
strISWord = strWordSuffix + strISWord;
break;
}
strWordSuffix.Empty();
}
while (GetNextPos(strBuffer, m_strNonSelectableChars, nOffset, FALSE) >= 0 &&
CheckIntelliMark(strBuffer,nOffset,strWordSuffix) &&
nOffset >= 0);
}
if ((strISWord = strWordSuffix + strISWord).IsEmpty())
{
return FALSE;
}
strIntelliSence = strISWord;
return TRUE;
}
void CCustomEditCtrl::ReleaseIntelliSenseList(CObList& lstIntelliSenseData)
{
for (POSITION pos = lstIntelliSenseData.GetHeadPosition();
pos != NULL;
delete lstIntelliSenseData.GetNext(pos));
lstIntelliSenseData.RemoveAll();
}
void CCustomEditCtrl::OnGetCharColor (TCHAR ch, int nOffset, COLORREF& clrText, COLORREF& clrBk)
{
if (m_bCheckColorTags)
{
TCHAR chOpen = _T ('<');
TCHAR chClose = _T ('>');
if (ch == chOpen || ch == chClose || ch == _T ('/'))
{
clrText = RGB (0, 0, 255);
}
else
{
COLORREF clrDefaultBack = GetDefaultBackColor ();
COLORREF clrDefaultTxt = GetDefaultTextColor ();
int nBlockStart, nBlockEnd;
if (!IsInBlock (nOffset, chOpen, chClose, nBlockStart, nBlockEnd))
{
clrText = clrDefaultTxt;
clrBk = clrDefaultBack;
}
else if (GetCharAt (nBlockStart + 1) == _T ('%') &&
GetCharAt (nBlockEnd - 1) == _T ('%'))
{
}
else if (clrText == clrDefaultTxt)
{
if (ch == _T ('='))
{
clrText = RGB (0, 0, 255);
}
else
{
clrText = RGB (255, 0, 0);
}
}
}
}
}
void CCustomEditCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (IsEnableBreakpoints() &&
point.x < m_nLeftMarginWidth)
{
ToggleBreakpoint();
}
CBCGPEditCtrl::OnLButtonDblClk(nFlags, point);
}
BOOL CCustomEditCtrl::ToggleBreakpoint(int nCurrRow /* = -1 */)
{
if (nCurrRow == -1)
{
nCurrRow = GetCurRow();
}
BOOL bMarkerSet = ToggleMarker (nCurrRow, g_dwBreakPointType, NULL, FALSE);
if (bMarkerSet)
{
SetLineColorMarker (nCurrRow, RGB (255, 255, 255),
RGB (127, 0, 0), TRUE, 0, g_dwColorBreakPointType);
}
else
{
DeleteMarker (nCurrRow, g_dwColorBreakPointType);
}
return bMarkerSet;
}
void CCustomEditCtrl::RemoveAllBreakpoints()
{
DeleteAllMarkers(g_dwBreakPointType | g_dwColorBreakPointType);
}
void CCustomEditCtrl::OnFailedOperation(DWORD dwOpType)
{
UINT uiID = 0;
switch (dwOpType)
{
case g_dwOpDelete:
case g_dwOpPaste:
case g_dwOpCopy:
case g_dwOpCut:
case g_dwOpIndent:
uiID = IDS_EDITFAILED;
break;
case g_dwOpPgUp:
uiID = IDS_PGUPFAILED;
break;
case g_dwOpDragDrop:
// usually fail for reasons that shouldn't draw any attention
return;
}
if (uiID != 0)
{
CString strMsg;
strMsg.LoadString(uiID);
::AfxMessageBox(strMsg);
}
switch (dwOpType)
{
case g_dwOpDelSelText:
return;
}
::MessageBeep((UINT)-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -