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

news2024/11/17 7:45:37

学习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:

    初始化列表,树

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

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

  • 填充列表,实现进度条

实现细节:

  • 画出基本窗口:

    主对话框

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

    为列表添加变量:控件类型,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);
    }
    
  • 接下来来设置当我们点击树中保存的文件路径时的操作:

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

      右键菜单

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

      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();
      }
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/831814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache poi 对单元格进行合并

需求背景: 在导出excel时, 需要对内容相同的单元格进行纵向合并 期望达到的效果: poi 实现合并单元格的方法 sheet.addMergedRegion(new CellRangeAddress(开始行, 结束行, 开始列, 结束列)); 个人的实现思路: 1): 举个列子, 就拿截图贴出的 [公司类别] 这一列来进行说明 …

【QT学习】01:helloqt

helloqt OVERVIEW helloqt一、helloqt1.使用向导创建2.手动创建3.pro文件4.Qt应用程序框架 二、按钮创建main.cppmywidget.cpp 三、对象模型1.对象树引入2.存在的问题 一、helloqt 创建一个qt项目&#xff0c;可以使用creator的向导创建&#xff0c;也可自己手动创建&#xff…

企业如何搭建矩阵内容,才能真正实现目的?

当下&#xff0c;新媒体矩阵营销已成为众多企业的营销选择之一&#xff0c;各企业可以通过新媒体矩阵实现扩大品牌声量、维持用户关系、提高销售业绩等不同的目的。 而不同目的的矩阵&#xff0c;它的内容运营模式会稍有差别&#xff0c;评价体系也会大不相同。 企业在运营某类…

性能优化-react路由懒加载和组件懒加载

背景 随着项目越来越大&#xff0c;打包后的包体积也越来越大&#xff0c;严重影响了首屏加载速度&#xff0c;需要对路由和组件做懒加载处理 主要用到了react中的lazy和Suspense。 废话不多说&#xff0c;直接上干货 路由懒加载 核心代码 import React, { lazy, Suspens…

精准感知+高效预判——城市“听诊器”防水患于未然

近期&#xff0c;全国多地遭遇暴雨猛袭&#xff0c;引发城市积涝&#xff0c;更有台风“杜苏芮”登陆后引发沿海内陆极端降水&#xff0c;各地排水防涝工作面临严峻考验。 快速定位城市排水管网系统的管道淤堵点&#xff0c;对河道水位、雨量情况、污水厂进水流量以及泵站运行情…

【云原生K8s】二进制部署单master K8s+etcd集群

一、实验设计 mater节点master01192.168.190.10kube-apiserver kube-controller-manager kube-scheduler etcd node节点node01192.168.190.20kubelet kube-proxy docker (容…

HTTP(超文本传输协议)学习

关于HTTP补学 一、HTTP能干什么 通过下图能够直观的看出&#xff1a;“交换数据 ” 二、HTTP请求例子 一个 HTTP 方法&#xff0c;通常是由一个动词&#xff0c;像 GET、POST 等&#xff0c;或者一个名词&#xff0c;像 OPTIONS、HEAD 等&#xff0c;来定义客户端执行的动作。…

Centos7.x修改密码

Centos7.x修改密码 root修改自己的密码 云服务器 云服务器则直接在控制台修改(例如阿里云服务器直接在阿里云服务器控制台修改&#xff0c;不赘述)命令行方式: 命令行输入: passwd 再两次输入新密码 root修改普通用户的密码 命令行方式: passwd 用户名再输入新的密码 普…

深入理解TCP三次握手:连接可靠性与安全风险

目录 导言TCP简介和工作原理的回顾TCP三次握手的目的和步骤TCP三次握手过程中可能出现的问题和安全风险为什么TCP三次握手是必要的&#xff1f;是否可以增加或减少三次握手的次数&#xff1f;TCP四次挥手与三次握手的异同点 导言 在网络通信中&#xff0c;TCP&#xff08;Tra…

7个更好用的数据可视化工具,建议收藏

在数据可视化工具的帮助下&#xff0c;设计师可以将数据转化为图像进行表达&#xff0c;让数据更加直观&#xff0c;更容易理解。今天本文会与打击分享7个好用的数据可视化工具&#xff0c;一起来get更好用的数据表达方式吧&#xff01; 1、即时设计 即时设计是一个非常受欢迎…

【js】FormData方法介绍和使用:

文章目录 一、接口使用FormData提交数据&#xff1a;二、FormData概述&#xff1a;三、FormData案例&#xff1a; 一、接口使用FormData提交数据&#xff1a; 二、FormData概述&#xff1a; 三、FormData案例&#xff1a; let formData new FormData() for (const key in tha…

一篇聊聊JVM优化:堆

一、Java 堆概念 1、简介 对于Java应用程序来说&#xff0c;Java堆&#xff08;Java Heap&#xff09;是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享 的一块内存区域&#xff0c;在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例&#xff0c;Java 世界…

成为“黑客“前,必须经过的“学习路线“!!!

成为"黑客"前&#xff0c;必须经过的"学习路线"&#xff01;&#xff01;&#xff01; 最近很多小伙伴在看了我的文章后&#xff0c;有一个共同的问题&#xff0c;"我们是小白&#xff0c;我们没有基础&#xff0c;我们如何通过自学&#xff0c;就可…

vue3数组V-for中动态生成$refs

vue3数组V-for中动态生成$refs 在项目实际需求中&#xff0c;可能会遇到使用数组动态生成$refs,根据官方参考&#xff0c;采用了以下方式实现 <template><div class"content"><ul v-for"(item, index) in editableTabs" :key"item.n…

2023全网最全的爆款抓包工具,各有千秋

在处理IP网络的故障时&#xff0c;经常使用以太网抓包工具来查看和抓取IP网络上某些端口或某些网段的数据包&#xff0c;并对这些数据包进行分析&#xff0c;定位问题。 在 IMON项目里&#xff0c;使用抓包工具抓包进行分析的场景在EPG采集、引流模块和软终端监看模块&#xff…

【练】创建两个线程:其中一个线程拷贝图片的前半部分,另一个线程拷贝后半部分

方法一&#xff1a; 先在主函数创建并清空拷贝的目标文件&#xff0c;再创建两个线程&#xff0c;在两个线程内部同时打开要读取的文件以及要拷贝的目标文件&#xff08;两个线程不共用同一份资源&#xff09;。 使用到的函数&#xff1a; 标准IO函数&#xff08;fprintf&…

(数据库系统概论|王珊)第一章绪论-第一节:数据库系统概论

目录 一&#xff1a;四大基本概念 &#xff08;1&#xff09;数据(Data) &#xff08;2&#xff09;数据库(DataBase,DB) &#xff08;3&#xff09;数据库管理系统(DataBase Management System,DBMS) &#xff08;4&#xff09;数据库系统(Database System&#xff0c;DBS…

HBN:2023年原生白护肤白皮书(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 调研数据表明&#xff0c;近九成的消费者对自己肤色不满&#xff0c;其中偏黄、偏黑是大家的核心困扰&#xff08;图1-1&#xff09;。在此情况下&#xff0c;“美白” 在各社媒平台的搜素量近年来一…

开利网络受邀出席数利丰应用研讨会 分享企业数字化转型落地经验

数利丰应用研讨会在广州举办。本次研讨会的主题为「聚焦数据价值&#xff0c;引领数字转型」。 广州市开利网络科技有限公司总经理、和合生态联合发起人付立军先生受邀出席研讨会并同在座40余国内外企业创始人与高管共同探讨企业经营所面临的共性问题&#xff0c;分享在企业数…

【力扣】19. 删除链表的倒数第 N 个结点 <链表指针、快慢指针>

【力扣】19. 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n…