HexViewer

HexViewer
1、建立名为HexViewer的SDI项目,在创建单文档时把Base Class(基类)改为CScrollView。CScrollView就是CView的一个派生类,通过它可以很容易地处理水平和垂直滚动。
2、打开和读取文件
      首先,在CHexViewerDoc类中定义两个成员变量,分别用于检索要打开文件的指针以及文件的大小,并初始化这些值,同时添加用于清除的代码。
class  CHexViewerDoc :  public  CDocument
{
..
public :
    CFile
*  m_pFile;
    LONG m_lFileSize;
..
};

CHexViewerDoc::CHexViewerDoc()
{
    m_pFile
= NULL;
    m_lFileSize
= 0L ;
}

CHexViewerDoc::
~ CHexViewerDoc()
{
    
if  (m_pFile != NULL)
    {
        m_pFile
-> Close();
        delete m_pFile;
        m_pFile
= NULL;
        m_lFileSize
= 0L ;
    }
}
      在使用MFC框架的因公程序中打开文档后,还会调用CHexViewerDoc::OnOpenDocument虚函数。
BOOL CHexViewerDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
    
if  ( ! CDocument::OnOpenDocument(lpszPathName))
        
return  FALSE;

    
if  (m_pFile != NULL)
    {
        m_pFile
-> Close();
        delete m_pFile;
        m_pFile
= NULL;
        m_lFileSize
= 0L ;
    }

    
try
    {
        m_pFile
= new  CFile(lpszPathName,CFile::modeRead | CFile::typeBinary);
    }
    
catch (CFileException *  e)
    {
        CString strError;
        strError.Format(_T(
" Couldn't open file:%d " ),_sys_errlist[e -> m_lOsError]);
        AfxMessageBox(strError);
        
return  FALSE;
    }

    m_lFileSize
= m_pFile -> GetLength();
    
return  TRUE;
}
      最后添加一个辅助成员函数,视图调用该函数从打开的文件中读取一行数据。
BOOL CHexViewerDoc::ReadLine(CString &  strLine, int  nLength,LONG lOffset /*  =-1L  */ )
{
    LONG lPosition;

    
if (lOffset !=- 1L )
        lPosition
= m_pFile -> Seek(lOffset,CFile::begin);
    
else
        lPosition
= m_pFile -> GetPosition();

    
if (lPosition ==- 1L )
    {
        TRACE(
" CHexViewDoc::ReadLine returns False Seek (%8.8lX,%8.8lX)\n " ,lOffset,lPosition);
        
// 这个宏是用来调试用的,在VC的窗口的输入框中会看到输出的内容!只有在debug版本中才会运行 
         return  FALSE;
    }

    BYTE
*  pszBuffer = new  BYTE[nLength]; 
    
int  nReturned = m_pFile -> Read(pszBuffer,nLength);

    
if (nReturned <= 0 )
    {
        TRACE2(
" CHexViewDoc::ReadLine returns FALSE Read (%d,%d) " ,nLength,nReturned);
        delete pszBuffer;
        
return  FALSE;
    }

    CString strTemp;
    CString strCharsIn;

    strTemp.Format(_T(
" %8.8lX -  " ),lPosition);
    strLine
= strTemp;

    
for ( int  nIndex = 0 ;nIndex < nReturned;nIndex ++ )
    {
        
if (nIndex == 0 )
            strTemp.Format(_T(
" %2.2X " ),pszBuffer[nIndex]);
        
// 以2位的十六进制读取
         else   if (nIndex % 16 == 0 )
            strTemp.Format(_T(
" =%2.2X " ),pszBuffer[nIndex]);
        
else   if (nIndex % 8 == 0 )
            strTemp.Format(_T(
" -%2.2X " ),pszBuffer[nIndex]);
        
else
            strTemp.Format(_T(
"  %2.2X " ),pszBuffer[nIndex]);

        
if (_istprint(pszBuffer[nIndex]))
            strCharsIn
+= pszBuffer[nIndex];
        
else
            strCharsIn
+= _T( ' . ' );
        strLine
+= strTemp;
    }
    
if (nReturned < nLength)
    {
        CString strPadding(_T(
'   ' ), 3 * (nLength - nReturned));
        strLine
+= strPadding;
    }
    strLine
+= _T( "    " );
    strLine
+= strCharsIn;

    delete pszBuffer;
    
return   true ;
}
3、视图的编码
      首先,定义一些变量,并对数据的字体进行改变
class  CHexViewerView :  public  CScrollView
{
.
protected :
    CFont
*  m_pFont;
    LOGFONT m_logfont;
    
int  m_nPointSize;
    
int  m_nPageHeight;
    
int  m_nPageWidth;
.
};

CHexViewerView::CHexViewerView()
{
    
//  TODO: add construction code here
    memset( & m_logfont, 0 , sizeof (m_logfont));
    m_nPointSize
= 120 ;
    _tcscpy(m_logfont.lfFaceName,_T(
" Fixedsys " ));
    
// 函数原型:char *strcpy( char *strDestination, const char *strSource );


    CWindowDC dc(NULL);
    m_logfont.lfHeight
= ::MulDiv(m_nPointSize,dc.GetDeviceCaps(LOGPIXELSY), 720 );
    
// MulDiv字体高度值和磅值有如下的换算公式;GetDeviceCaps该函数检索指定设备的设备指定信息。
    
// LOGPIXELSY沿屏幕高度每逻辑英寸的像素数,在多显示器系统中,该值对所显示器相同;
    m_logfont.lfPitchAndFamily = FIXED_PITCH; // 指定字体间距和字体族,低端二位指定字体的字符间距
    m_pFont = new  CFont;
    m_pFont
-> CreateFontIndirect( & m_logfont);
}

CHexViewerView::
~ CHexViewerView()
{
    
if  (m_pFont != NULL)
    {
        delete m_pFont;
    }
}
      设置滚动的大小,可以向其传递映射模式(MM_TEXT显示文本)和文档大小(m_lFileSize)
void  CHexViewerView::OnInitialUpdate()
{
    CScrollView::OnInitialUpdate();

    CHexViewerDoc
*  pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    CSize sizeTotal(
0 ,pDoc -> m_lFileSize);
    
// sizeTotal.cx = sizeTotal.cy = 100;
    SetScrollSizes(MM_TEXT, sizeTotal);
}
      给视图添加为当前设备上下文(DC)计算字体高度(以像素计)的辅助函数。这里的技巧是传递-1作为字符串长度。这意味着不进行任何实际绘制操作,但是DrawText函数仍返回指定文本的高度。
int  CHexViewerView::MeasureFontHeight(CFont *  pFont,CDC *  pDC)
{
    CFont
*  pOldFont;
    pOldFont
= pDC -> SelectObject(pFont);

    CRect rectDummy;
    CString strRender
= _T( " 1234567890ABCDEF-  " );
    
int  nHeight = pDC -> DrawText(strRender, - 1 ,rectDummy,DT_TOP | DT_SINGLELINE | DT_CALCRECT);

    pDC
-> SelectObject(pOldFont);

    
return  nHeight;
      最后队试图进行修改,用GetScrollPosition返回用户滚动的位置,用GetClientRect来返回工作区的大小,用MeasureFontHeight返回每行的高度,然后可以用一个for循环通过ReadLine函数来从文档中检索每行数据。
void  CHexViewerView::OnDraw(CDC *  pDC)
{
    CHexViewerDoc
*  pDoc  =  GetDocument();
    ASSERT_VALID(pDoc);

    CString strRender;
    CFont
*  pOldFont;
    CSize ScrolledSize;
    
int  nStartLine;
    
int  nHeight;
    CRect ScrollRect;
    CPoint ScrolledPos
= GetScrollPosition(); // 获取该屏滚动条的位置


    CRect rectClient;
    GetClientRect(
& rectClient);

    pOldFont
= pDC -> SelectObject(m_pFont);
    nHeight
= MeasureFontHeight(m_pFont,pDC);

    ScrolledSize
= CSize(rectClient.Width(),rectClient.Height());
    ScrollRect
= CRect(rectClient.left,ScrolledPos.y,rectClient.right,ScrolledSize.cy + ScrolledPos.y);
    nStartLine
= ScrolledPos.y / 16 ;

    ScrollRect.top
= nStartLine * nHeight;

    
if (pDoc -> m_pFile != NULL)
    {
        
int  nLine;
        
for (nLine = nStartLine;ScrollRect.top < ScrollRect.bottom;nLine ++ )
        {
            
if ( ! pDoc -> ReadLine(strRender, 16 ,nLine * 16 ))
                
break ;

            nHeight
= pDC -> DrawText(strRender, - 1 , & ScrollRect,DT_TOP | DT_NOPREFIX | DT_SINGLELINE);
            ScrollRect.top
+= nHeight;
        }
    }

    pDC
-> SelectObject(pOldFont);
}

你可能感兴趣的:(HexViewer)