变量说明
cxChar 字符宽度
cyChar 字符高度
cxBuffer 行内最大字符数
cyBuffer 最大行数
pBuffer 输入内容存储区
xCaret 光标x坐标
yCaret 光标y坐标
创建时获取字符的基本信息
int CMyEditorView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
cxChar = tm.tmAveCharWidth;
cxCaps = (tm.tmPitchAndFamily&1?3:2)*cxChar/2;
cyChar = tm.tmHeight + tm.tmExternalLeading;
CreateSolidCaret( tm.tmAveCharWidth,tm.tmHeight );
ShowCaret();
return 0;
}
窗口大小调整时的范围信息获取
void CMyEditorView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
cxClient = cx;
cyClient = cy;
cxBuffer = max(1,cxClient/cxChar);
cyBuffer = max(1,cyClient/cyChar);
if(pBuffer!=NULL)
free(pBuffer);
pBuffer = (TCHAR *)malloc(cxBuffer*cyBuffer*sizeof(TCHAR));
for(int y=0;y<cyBuffer;y++)
for(int x=0;x<cxBuffer;x++)
BUFFER(x,y)=0;
xCaret = 0;
yCaret = 0;
CPoint caretPoint(xCaret*cxChar,yCaret*cyChar);
if( this==GetFocus() )
SetCaretPos(caretPoint);
InvalidateRect(NULL);
}
字符消息处理
#define BUFFER(x,y) *(pBuffer+y*cxBuffer+x)
void CMyEditorView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CClientDC dc(this);
switch (nChar)
{
case '\t': // tab
do
{
SendMessage (WM_CHAR, ' ', 1) ;
}
while (xCaret % 4 != 0) ;
break ;
case '\n': // line feed
if (++yCaret == cyBuffer)
yCaret = 0 ;
break ;
case '\r': // carriage return
xCaret = 0 ;
if (++yCaret == cyBuffer)
yCaret = 0 ;
break ;
case '\x1B': // escape
for (int y = 0 ; y < cyBuffer ; y++)
for (int x = 0 ; x < cxBuffer ; x++)
BUFFER (x, y) = 0 ;
xCaret = 0 ;
yCaret = 0 ;
InvalidateRect (NULL, FALSE) ;
break ;
case '\b': // backspace
if (xCaret > 0)
{
xCaret--;
SendMessage (WM_KEYDOWN, VK_DELETE, 1) ;
}
break;
default: // character codes
BUFFER (xCaret, yCaret) = (TCHAR) nChar ;
HideCaret () ;
CDC *pDC = GetDC () ;
HDC hdc = pDC->GetSafeHdc();
SelectObject (hdc, CreateFont(0,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,FIXED_PITCH, NULL)) ;
TextOut (hdc, xCaret * cxChar, yCaret * cyChar,& BUFFER (xCaret, yCaret), 1) ;
DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
ReleaseDC (pDC);
ShowCaret ();
if (++xCaret == cxBuffer)
{
xCaret = 0 ;
if (++yCaret == cyBuffer)
yCaret = 0 ;
}
break ;
}
SetCaretPos ( CPoint(xCaret * cxChar, yCaret * cyChar)) ;
}
功能键处理
void CMyEditorView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_HOME:
xCaret = 0; break;
case VK_END:
xCaret = cxBuffer-1; break;
case VK_PRIOR:
yCaret = 0; break;
case VK_NEXT:
yCaret = cyBuffer-1; break;
case VK_LEFT:
xCaret = max(xCaret-1,0); break;
case VK_RIGHT:
xCaret = min(xCaret+1,cxBuffer-1); break;
case VK_UP:
yCaret = max(yCaret-1,0); break;
case VK_DOWN:
yCaret = min(yCaret+1,cyBuffer-1); break;
case VK_DELETE:
for(int x=xCaret;x<cxBuffer;x++)
BUFFER(x,yCaret) = BUFFER(x+1,yCaret);
BUFFER(cxBuffer-1,yCaret)=0;
HideCaret();
CDC *pDC = GetDC();
HDC hdc = pDC->GetSafeHdc();
SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,FIXED_PITCH,NULL));
TextOut (hdc, xCaret * cxChar, yCaret * cyChar,& BUFFER (xCaret, yCaret), cxBuffer) ;
DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
ReleaseDC (pDC) ;
ShowCaret () ;
if (xCaret+1 == cxBuffer)
{
xCaret = 0 ;
if (++yCaret == cyBuffer)
yCaret = 0 ;
}
}
SetCaretPos (CPoint(xCaret*cxChar,yCaret*cyChar)) ;
}
文本输出
void CMyEditorView::OnPaint()
{
PAINTSTRUCT ps;
CDC *pDC = BeginPaint (&ps) ;
HDC hdc = pDC->GetSafeHdc();
SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,
dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;
for (int y = 0 ; y < cyBuffer ; y++)
TextOut (hdc, 0, y * cyChar, & BUFFER(0,y), cxBuffer) ;
DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
EndPaint (&ps) ;
}