Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CBFViewCtrl (BigFile Viewer Controller)

0.00/5 (No votes)
9 Sep 2004 1  
Controller that allows you to view very large files

Introduction

View large text file in a controller like CEdit/CStatic is not easy. Especially if the file you want to view is several gigabytes big (like very big log files). CBFViewCtrl can do this. CBFViewCtrlis a CWnd-Derived class that will show files of any size. The controller will only show them. Will not allow you to edit them. Features:

  • Show files of any size.
  • Able to select text with mouse.
  • Support for standard 'copy to Clipboard' keys ( CTRL+C & CTRL+Insert )
  • Copy Selection to Clipboard or File.
  • Font / Color are customizable.
  • Able to auto reload if file is changed.
  • Support for loading file that are dropped on the controller.
  • Design that allow for easy expansions of new view modes. (e.g. UTF8 , Color Syntax text )
  • Low memory usage.
  • High Speed.

How it works

It doesn�t load the entire file into memory. It is using memory mapping. The OS allows you to map a file to memory but the limit is around 2G since then there is no more address space left. And since this controller should be able to work together with other code it should not take all of the address space for it self. So it is only mapping 256K at one time. And it will remap to the next 256K area when needed.

CBFViewCtrl depends on a helper class that is derived from CDataHandler. This classes handle how lines for parsed and drawn. Depending on what view mode is chosen CBFViewCtrl load appropriate helper. There are three helpers includes for different Text Modes , ASCII , Unicode and Binary.

The datahandler class keeps a cache for up to 400 lines so it doesn�t need to reparse everything when we need to redraw. The line cache store a pointer to where in the memory mapped area the line starts and how long the line is in bytes.

Since the total number of rows is unknown when opening a file the vertical scrollbar should not be set to the numbers of lines the file has. And since the scrollbar only allows 32bit values and max file size is 64bit. The file size could not be used as a reference either for the scrollbar. So instead the scroll bar is set to 10.000. And if user drag scrollbar to position 7538 this is translated to 75.38% into the file and it will go there and then scan backward to file the beginning of the line and start showing the file from there.

Limits

It is possible to select ALL text in the controller even if the file is several gigabytes big. And if the user then should choose to copy that to the clipboard it will be a problem. So there is a build in limit of the max size of the allowed clipboard size ( For another size limit change the value of MAX_CLIPBOARD_SIZE in BFViewCtrl.h ).
If the selection is bigger then this value the user will be asked to save the clip to a file instead.

Using the code

To add the controller to you Dialog:

  1. In the resource editor add a custom control to the dialog.
  2. Set ID to something like "IDC_BFV".
  3. Set class to "CBFViewCtrl.
  4. Set Style to 0x50810000. (Replace the 8 with 0 if you do not want any border)
  5. Add a member to you Dialog class.
    CBFViewCtrl m_Viewer;
    
  6. To connect the custom controler in the dialog to your class add a DDX_Control(...) to DoDataExchange.
    void CBFViewCtrlDemoDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
    
        DDX_Control(pDX, IDC_BFV , m_Viewer );
    }
    
  7. Open a file in the controller.
    m_Viewer.Openfile( strFilename , TEXTTYPE_AUTO , TRUE );
    

To Create the controller dynamically you only have to do this.

CRect rc(5,5,400,400);
int nID = 1020;
CBFViewCtrl *pViewer = new CBFViewCtrl();
pViewer->Create( this , rc , nID , WS_VISIBLE | WS_BORDER | WS_CHILD );

Configure the controller

  • Enable drop file support.
     m_Viewer.DragAcceptFiles( TRUE );
  • Change Colors. If a color is -1 that color will not change.
    m_Viewer.SetColor( RGB(255,255,0) , RGB(0,0,0) , 
      RGB(128,0,64) , RGB(255,0,0) , TRUE );
  • Enable auto reload if file changes. If ms are 0 then the checking is stopped.
    // check for file changes every 2.5s
    
    m_Viewer.SetReloadChkTimer( 2500 );
  • Change Font.
    m_Viewer.SetFont( _T("Courier New") , 10 );
    or
    m_Viewer.SetFont( &m_Font );
    
  • Set text selection manually.
    // Selection from position 0 to 2300
    
    m_Viewer.SetSelection( 0 , 2300 );
    

React on notification from the controller

CBFViewCtrl send a notification message when a file is opened and when file is reloaded. To react on them do this.

  1. First add this to let you dialog class handle the messages.
    BEGIN_MESSAGE_MAP(CBFViewCtrlDemoDlg, CDialog)
    
        ON_NOTIFY(  BFVN_OPEN     , IDC_BFV , OnBFVOpen ) 
        ON_NOTIFY(  BFVN_RELOADED , IDC_BFV , OnBFVReloaded ) 
    
    END_MESSAGE_MAP()
    
  2. The Add this functions.
    protected:
        afx_msg void OnBFVOpen (NMHDR *pNotifyStruct, LRESULT* pResult);
        afx_msg void OnBFVReloaded(NMHDR *pNotifyStruct, LRESULT* pResult);
    
  3. Here is how they can be used.
    void CBFViewCtrlDemoDlg::OnBFVOpen(NMHDR *pNotifyStruct, LRESULT* pResult) 
    {
      // A file was open. 
    
      m_strFilename = m_Viewer.GetFileName();
    
    }
    
    void CBFViewCtrlDemoDlg::OnBFVReloaded(NMHDR *pNotifyStruct, LRESULT* pResult) 
    {
       // File is reload. the filesize have change. get the new size
    
       m_nFilesize = m_Viewer.GetTotalSize();
    }
    

To Do

  • Print Support
  • More view modes. DataHandlers for UTF8 , HEX , Color Syntax Text

Credits

To create this controller I have used some classes create by other people. I would like to thanks the following guys.

  • Jamie Nordmeyer for CAutoFont
  • Richard Chambers for File Drag & Drop class
  • Keith Rule for MemDC
  • PJ Naughter for MemMapFile class. But the version included here is highly modified to fit my special needs, so I renamed it to CMemMapFile2 so it would not conflict with the original version.

History

  • v1.0 ( 8-September-2004 )
    • First version.
  • v1.1 ( 9-September-2004 )
    • Buffer overflow and stack overflow problem fixed.
    • Accessing memory out of memory mapped area problem fixed.
    • Parse bug for Unicode fixed.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here