【MFC]实现16进制文件浏览器-详细步骤+代码

学习MFC已经两天了,我们来写一个小项目:16进制文件浏览器,简单实现,因为我们MFC学的还不是很透彻,这里会给出详细的每一个步骤,并且详细解释每一个方法:

文章目录

  • 提前了解步骤:
  • 基本步骤:
  • 实现细节:

提前了解步骤:

拖拽文件消息:

WM_DROPFILES

WCHAR szPath[MAX_PATH]={0};
int nRes = DragQueryFile(hDropInfo,-1,NULL,0);
CDialogEx::OnDropFIles(hDropInfo);
if(nRes<=0){
  return;
}else{
  第二个参数:如果为-1,则代表返回文件个数,如果是nRes-1,则代表第n个文件
  int nRes = DragQueryFile(hDropInfo,nRes-1,szPath,MAX_PATH);:
  CDialogEx::OnDropFIles(hDropInfo);
}

基本步骤:

  • 画出基本窗口,列表,树,进度条,菜单

  • OnInitDialog:

    初始化列表,树

  • 实现菜单中打开文件功能能,实现拖拽打开文件功能

  • 获取打开文件路径字符串,打开文件,获取文件句柄,将文件二进制码读取到内存中

  • 填充列表,实现进度条

实现细节:

  • 画出基本窗口:

    【MFC]实现16进制文件浏览器-详细步骤+代码_第1张图片

    主对话框需要设置属性:接受文件。

    为列表添加变量:控件类型,m_HexVIewList

    为树添加变量:控件类型,m_FilePathTree

  • 画出菜单

菜单

将主对话框MENU设置为创建好的菜单资源名称。

  • 初始化列表,树控件

    类中添加public变量:HTREEITEM hTreeRoot

    在OnInitDialog函数中,初始化树控件,初始化列表由于比较繁琐,将其封装为函数后,添加在OnInitDialog函数中:

    VOID CHexBrowserDlg::InitFileList()
    {
    	m_HexViewList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_SNAPTOGRID);
    	m_HexViewList.InsertColumn(0, L"Addr", 0, 80);
    
    	m_HexViewList.InsertColumn(1, L"0", 0, 30);
    	m_HexViewList.InsertColumn(2, L"1", 0, 30);
    	m_HexViewList.InsertColumn(3, L"2", 0, 30);
    	m_HexViewList.InsertColumn(4, L"3", 0, 30);
    	m_HexViewList.InsertColumn(5, L"4", 0, 30);
    	m_HexViewList.InsertColumn(6, L"5", 0, 30);
    	m_HexViewList.InsertColumn(7, L"6", 0, 30);
    	m_HexViewList.InsertColumn(8, L"7", 0, 30);
    	m_HexViewList.InsertColumn(9, L"8", 0, 30);
    	m_HexViewList.InsertColumn(10, L"9", 0, 30);
    	m_HexViewList.InsertColumn(11, L"A", 0, 30);
    	m_HexViewList.InsertColumn(12, L"B", 0, 30);
    	m_HexViewList.InsertColumn(13, L"C", 0, 30);
    	m_HexViewList.InsertColumn(14, L"D", 0, 30);
    	m_HexViewList.InsertColumn(15, L"E", 0, 30);
    	m_HexViewList.InsertColumn(16, L"F", 0, 30);
    
    	m_HexViewList.InsertColumn(17, L"  ", 0, 15);
    
    	m_HexViewList.InsertColumn(18, L"0", 0, 22);
    	m_HexViewList.InsertColumn(19, L"1", 0, 22);
    	m_HexViewList.InsertColumn(20, L"2", 0, 22);
    	m_HexViewList.InsertColumn(21, L"3", 0, 22);
    	m_HexViewList.InsertColumn(22, L"4", 0, 22);
    	m_HexViewList.InsertColumn(23, L"5", 0, 22);
    	m_HexViewList.InsertColumn(24, L"6", 0, 22);
    	m_HexViewList.InsertColumn(25, L"7", 0, 22);
    	m_HexViewList.InsertColumn(26, L"8", 0, 22);
    	m_HexViewList.InsertColumn(27, L"9", 0, 22);
    	m_HexViewList.InsertColumn(28, L"A", 0, 22);
    	m_HexViewList.InsertColumn(29, L"B", 0, 22);
    	m_HexViewList.InsertColumn(30, L"C", 0, 22);
    	m_HexViewList.InsertColumn(31, L"D", 0, 22);
    	m_HexViewList.InsertColumn(32, L"E", 0, 22);
    	m_HexViewList.InsertColumn(33, L"F", 0, 22);
    }
    
    
    // TODO: 在此添加额外的初始化代码
    hTreeRoot = m_FilePathTree.InsertItem(L"最近打开的文件", TVI_ROOT, TVI_LAST);
    InitFileList();
    
  • 为菜单中,打开文件添加消息处理程序:

    这里先给出加载十六进制文件的函数,打开文件后就要调用:

    VOID CHexBrowserDlg::InitFileViewList(WCHAR * szPath)
    {
    	if (szBuffer != nullptr) {
    		//代表上次的还存在,如果需要显示的话,要释放掉
    		delete[] szBuffer;
    	}
    	//清空列表上显示的内容:
    	m_HexViewList.DeleteAllItems();
    	//打开文件,获取文件句柄:
    	HANDLE hFile = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    	//获取文件大小:
    
    	DWORD dwFileSize = GetFileSize(hFile, NULL);
    	//申请内存:
    	szBuffer = new char[dwFileSize];
    	memset(szBuffer, 0, dwFileSize);
    	//读取文件:
    	DWORD dwReadSize = 0;
    	ReadFile(hFile, szBuffer, dwFileSize, &dwReadSize, NULL);
    
    	DWORD dwLines = (dwReadSize / 0x16 + 1);//列表中一共要显示的行数
    	//初始化进度条:
    	m_Progress.SetRange32(0, dwLines);
    	DWORD nIndex = 0;//当前显示的行数,随着设置,会增加
    	DWORD dwAddr = 0;//每一行最开始的,地址
    	CString cValue;
    	for (size_t i = 0; i + 16 <= dwLines; i+=16)
    	{
    		//设置每一行第一列:地址
    		cValue.Format(L"%08X", dwAddr);
    		m_HexViewList.InsertItem(nIndex, cValue, NULL);
    		//设置十六进制文件浏览:
    		for (size_t j = 0; j < 0x10; j++)
    		{
    			UCHAR uCode = szBuffer[i + j];
    			cValue.Format(L"%02X", uCode);
    			m_HexViewList.SetItemText(nIndex, j + 1, cValue);
    		}
    		m_HexViewList.SetItemText(nIndex, 17, L"  ");
    		//设置ASCII浏览:
    		for (size_t j = 0; j < 0x10; j++)
    		{
    			UCHAR uCode = szBuffer[i + j];
    			if (uCode == 0) {
    				cValue.Format(L".");
    			}
    			else {
    				cValue.Format(L"%c", uCode);
    			}
    			m_HexViewList.SetItemText(nIndex, 18 + j, cValue);
    		}
    		dwAddr += 0x10;
    		m_Progress.SetPos(i+1);
    		nIndex++;
    	}
    	CloseHandle(hFile);
    }
    
    void CHexBrowserDlg::OnSeleteFile()
    {
    	// TODO: 在此添加命令处理程序代码
    	CFileDialog cFileDlg(TRUE, NULL, NULL, NULL, L"EXE|*.exe|DLL|*.dll|SYS|*.sys|All File|*.*||", this);
    	cFileDlg.DoModal();
    	CString szPath = cFileDlg.GetPathName();
    	m_FilePathTree.InsertItem(szPath, hTreeRoot, TVI_LAST);
    	InitFileViewList(szPath.GetBuffer(0));//CString.GetBuffer方法可以将字符串自动转化为WCHAR类型的字符串
    }
    
  • 接下来,我们设置拖拽打开文件:

    拖拽文件消息:

    WM_DROPFILES

    void CHexBrowserDlg::OnDropFiles(HDROP hDropInfo)
    {
    	// TODO: 在此添加消息处理程序代码和/或调用默认值
    	TCHAR szPath[MAX_PATH] = { 0 };
    	int nRes = DragQueryFile(hDropInfo, -1, NULL, 0);
    	if (nRes <= 0) {
    		return;
    	}
    	nRes = DragQueryFile(hDropInfo, -1, szPath, _countof(szPath));
    	m_FilePathTree.InsertItem(szPath, hTreeRoot, TVI_LAST);
    	InitFileViewList(szPath);
    	CDialogEx::OnDropFiles(hDropInfo);
    }
    
  • 接下来来设置当我们点击树中保存的文件路径时的操作:

    • 首先我们添加右键菜单:

      【MFC]实现16进制文件浏览器-详细步骤+代码_第2张图片

    • 这里给出的函数分别是:打开文件,删除节点,清空节点的代码:

      void CHexBrowserDlg::OnContinueOpenFile()
      {
      	// TODO: 在此添加命令处理程序代码
      	HTREEITEM hTreeNode = m_FilePathTree.GetSelectedItem();
      	CString szPath = m_FilePathTree.GetItemText(hTreeNode);
      	InitFileViewList(szPath.GetBuffer(0));
      }
      
      
      void CHexBrowserDlg::OnDeleteTreeNode()
      {
      	// TODO: 在此添加命令处理程序代码
      	HTREEITEM hTreeNode = m_FilePathTree.GetSelectedItem();
      	m_FilePathTree.DeleteItem(hTreeNode);
      }
      
      
      void CHexBrowserDlg::OnClear()
      {
      	// TODO: 在此添加命令处理程序代码
      	m_FilePathTree.DeleteAllItems();
      }
      

你可能感兴趣的:(MFC,mfc,c++)