实现步骤:
1、建立SDI或者MDI的MFC程序,View选择CEditView(这里假设工程名字为Stylepad)
2、在CEditView的继承类中追加
protected:
void UpdateLineNumber();
LRESULT OnIdle(WPARAM wp, LPARAM lCount);
LONG cxCharWidth;
LONG cyCharHeight;
3、响应 WM_VSCROLL 消息
void CStylepadView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CEditView::OnVScroll(nSBCode, nPos, pScrollBar);
this->UpdateLineNumber();
}
4、响应 WM_SIZE 消息
void CStylepadView::OnSize(UINT nType, int cx, int cy)
{
CEditView::OnSize(nType, cx, cy);
RECT rectWin;
this->GetClientRect(&rectWin);
SIZE size ;
CClientDC dc(this);
GetTextExtentPoint32W (dc.m_hDC, L"W", 1, &size) ;
this->cxCharWidth = size.cx;
this->cyCharHeight = size.cy;
rectWin.left = cxCharWidth * 4 + 3;
this->GetEditCtrl().SetRect(&rectWin);
this->Invalidate();
}
5、追加 #include <afxpriv.h>
然后再在 MESSAGE_MAP 中追加 ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdle)
结果为:
BEGIN_MESSAGE_MAP(CStylepadView, CEditView)
ON_WM_VSCROLL()
ON_WM_SIZE()
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdle)
END_MESSAGE_MAP()
实现:
LRESULT CStylepadView::OnIdle(WPARAM wp, LPARAM lCount)
{
UpdateLineNumber();
return 0;
}
6、最后就是如何输出行号
void CTestEditViewView::UpdateLineNumber()
{
RECT rectWin;
this->GetClientRect(&rectWin);
UINT uViewWidth = cxCharWidth * 4;
UINT uViewHeight = rectWin.bottom;
// Count Visible Line
int nViewLineMin = this->GetEditCtrl().GetFirstVisibleLine() + 1;
int nViewLineMax = (uViewHeight / cyCharHeight) + nViewLineMin;
// Get DC
CClientDC dc(this);
HDC hdcView = ::CreateCompatibleDC(dc.GetSafeHdc());
HBITMAP hbmScaled = CreateCompatibleBitmap(dc.GetSafeHdc(), uViewWidth, uViewHeight);
HGDIOBJ hbmOld = SelectObject(hdcView, (HGDIOBJ)hbmScaled);
// Fill Rect
RECT rectLine;
rectLine.left = rectLine.top = 0;
rectLine.bottom = uViewHeight;
rectLine.right = uViewWidth;
FillRect(hdcView, &rectLine, (HBRUSH) (COLOR_WINDOW + 1));
// Draw the Number
static TCHAR strNumber[7];
wmemset(strNumber, 0, 7);
int nLeft = uViewWidth - 3;
int nBufferSize = 0;
SetTextAlign(hdcView, TA_RIGHT);
int nCurrentLine = this->GetEditCtrl().LineFromChar(-1) + 1;
SetTextColor(hdcView, RGB(41,41,41));
for (UINT i = 1; i <= uViewHeight ; i += cyCharHeight)
{
if(nCurrentLine == nViewLineMin)
{
SetTextAlign(hdcView, TA_LEFT);
SetTextColor(hdcView, RGB(255,0,0));
TextOutW(hdcView, 0, i, L"*", 1);
SetTextColor(hdcView, RGB(41,41,41));
SetTextAlign(hdcView, TA_RIGHT);
}
nBufferSize = ::wsprintfW(strNumber, L"%d", nViewLineMin++);
TextOutW(hdcView, nLeft, i, strNumber, nBufferSize);
}
// Draw the Line
// Initialize the pen's brush.
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(255,0,0);
lb.lbHatch = HS_CROSS;
// Create a pen to darw line
HPEN hPen = ExtCreatePen(PS_GEOMETRIC | PS_DASHDOTDOT, 1, &lb, 0, NULL);
HGDIOBJ hOldPen = SelectObject(hdcView, (HGDIOBJ)hPen);
MoveToEx(hdcView, uViewWidth - 1, 0, 0) ;
LineTo(hdcView, uViewWidth - 1, uViewHeight);
// Restore the old Pen
SelectObject(hdcView, hOldPen);
DeleteObject(hPen);
// Draw the Image To Client View
BitBlt(dc.GetSafeHdc(), 0, 0, uViewWidth, uViewHeight, hdcView, 0, 0, SRCCOPY);
// Restore the old Bitmap
SelectObject(hdcView, hbmOld);
DeleteDC(hdcView);
DeleteObject(hbmScaled);
}