C++ + MFC 写一个程序参数修改器(五、界面交互)

一、说明

前面几篇,已经将所有基本的工具函数写完,这一篇,主要是将所有的功能串起来,使界面和功能进行交互。

二、初始化

2.1 初始化两个listctrl

  1. 查找的list控件只需要一栏,显示地址就可以了
  2. 目标list控件需要四栏,分别为说明、地址、类型、值,其中说明可以不考虑

将这两个函数在OnInitDialog中调用
C++ + MFC 写一个程序参数修改器(五、界面交互)_第1张图片
C++ + MFC 写一个程序参数修改器(五、界面交互)_第2张图片

2.2 初始化搜索和编辑设置

将这两个函数在OnInitDialog中调用
C++ + MFC 写一个程序参数修改器(五、界面交互)_第3张图片

C++ + MFC 写一个程序参数修改器(五、界面交互)_第4张图片

2.3 回调函数

C++ + MFC 写一个程序参数修改器(五、界面交互)_第5张图片

三、搜索

3.1 首次搜索

双击首次搜索按钮,在生成的函数中加入以下代码:
逻辑很简单

  1. 获取进程id
  2. 获取界面参数(搜索值、范围、类型)
  3. 按照类型查找
  4. 查完遍历结果显示到listctrl控件上
  5. 清零进度条
void CModifierDlg::OnBnClickedButtonFirst()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_dwProcessId == 0) {
		AfxMessageBox(_T("请选择进程!"));
		OnBnClickedButtonProgress();  // 若未选择进程,则打开进程列表
	}

	if (m_dwProcessId == 0) {
		AfxMessageBox(_T("用户未选择进程!"));
		return;
	}

	m_bGoon = true;		// 开启回调
	m_listAddressTemp.DeleteAllItems();
	//UpdateData(TRUE);
	// 获取界面参数
	CString valueTemp;
	GetDlgItemText(IDC_EDIT_SEARCH_VALUE, valueTemp);
	if (valueTemp.IsEmpty()) {
		AfxMessageBox(_T("请输入搜索的值"));
		return;
	}
	CString start, end;
	GetDlgItemText(IDC_EDIT_LIMIT_START, start);
	GetDlgItemText(IDC_EDIT_LIMIT_END, end);
	_TCHAR* szEnd = NULL;
	DWORD dwLimitBegin = _tcstol(start.GetString(), &szEnd, 0x10);
	DWORD dwLimitEnd = _tcstol(end.GetString(), &szEnd, 0x10);
	GetDlgItem(IDC_BUTTON_FIRST)->EnableWindow(FALSE); // 使首次搜索按钮失效

	
	// 根据选择的不同数据类型,进行不同方式的查找
	int iIdx = m_comboxValueType.GetCurSel();
	bool bFind = false;
	switch (iIdx) {
	case 0: { // 1字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		BYTE bb = (BYTE)(ul & 0x000000FF);
		bFind = m_pFinder->FindFirstEx(m_dwProcessId, dwLimitBegin, dwLimitEnd, bb);
		break;
	}
	case 1: { // 2字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		SHORT bb = (SHORT)(ul & 0x0000FFFF);
		bFind = m_pFinder->FindFirstEx(m_dwProcessId, dwLimitBegin, dwLimitEnd, bb);
		break;
	}
	case 2: { // 4字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		DWORD bb = (DWORD)(ul & 0xFFFFFFFF);
		bFind = m_pFinder->FindFirstEx(m_dwProcessId, dwLimitBegin, dwLimitEnd, bb);
		break;
	}
	case 3: { // float
		TCHAR* szEndPtr = nullptr;
		float f = _tcstof(valueTemp.GetString(), &szEndPtr);
		bFind = m_pFinder->FindFirstEx(m_dwProcessId, dwLimitBegin, dwLimitEnd, f);
		break;
	}
	case 4: { // double
		TCHAR* szEndPtr = nullptr;
		double d = _tcstod(valueTemp.GetString(), &szEndPtr);
		bFind = m_pFinder->FindFirstEx(m_dwProcessId, dwLimitBegin, dwLimitEnd, d);
		break;
	}
	default:
		break;
	}
	if (!bFind) {
		// 恢复按钮 可用状态
		GetDlgItem(IDC_BUTTON_FIRST)->EnableWindow(TRUE);
		// 继续搜索标置(false)
		m_bGoon = false;
		UpdateData(FALSE);
		return;
	}

	const std::list<DWORD>& lst = m_pFinder->GetResults();
	int index = 1024; //最多显示1024结果
	for (auto addr : lst) {
		if (index-- <= 0) {
			break;
		}
		int index = m_listAddressTemp.InsertItem(0, _T(""));
		CString s;
		s.Format(_T("%08X"), addr);
		m_listAddressTemp.SetItemText(index, 0, s);
	}
	// 进度条清0
	m_pProgress.SetPos(0);
	// 恢复按钮 可用状态
	GetDlgItem(IDC_BUTTON_FIRST)->EnableWindow(TRUE);
	// 继续搜索标置(false)
	m_bGoon = false;
	//UpdateData(FALSE);
	return;
}

3.2 再次搜索

双击再次搜索按钮,在生成的函数中加入以下代码
逻辑和首次搜索基本一致

  1. 由于进程id和搜索类型和首次搜索必然一致,所以这两个参数不用再获取和传递
  2. 由于搜索范围必然是在首次搜索的结果上进一步搜索,所以搜索范围这个参数不用再获取
  3. 将findfirst换成findnext即可
void CModifierDlg::OnBnClickedButtonNext()
{
	// TODO: 在此添加控件通知处理程序代码
	m_bGoon = true;
	// 目标值
	CString valueTemp;
	GetDlgItemText(IDC_EDIT_SEARCH_VALUE, valueTemp);
	if (valueTemp.IsEmpty()) {
		AfxMessageBox(_T("请输入目标值"));
		UpdateData(FALSE);
		m_bGoon = false;
		return;
	}
	GetDlgItem(IDC_BUTTON_NEXT)->EnableWindow(FALSE);
	m_listAddressTemp.DeleteAllItems();
	int iIdx = m_comboxValueType.GetCurSel();
	bool bFind = false;
	switch (iIdx) {
	case 0: { // 1字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		BYTE bb = (BYTE)(ul & 0x000000FF);
		bFind = m_pFinder->FindNextEx(bb);
		break;
	}
	case 1: { // 2字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		SHORT bb = (SHORT)(ul & 0x0000FFFF);
		bFind = m_pFinder->FindNextEx(bb);
		break;
	}
	case 2: { // 4字节
		TCHAR* szEndPtr = nullptr;
		unsigned long ul = _tcstoul(valueTemp.GetString(), &szEndPtr, 10);
		DWORD bb = (DWORD)(ul & 0xFFFFFFFF);
		bFind = m_pFinder->FindNextEx(bb);
		break;
	}
	case 3: { // float
		TCHAR* szEndPtr = nullptr;
		float f = _tcstof(valueTemp.GetString(), &szEndPtr);
		bFind = m_pFinder->FindNextEx(f);
		break;
	}
	case 4: { // double
		TCHAR* szEndPtr = nullptr;
		double d = _tcstod(valueTemp.GetString(), &szEndPtr);
		bFind = m_pFinder->FindNextEx(d);
		break;
	}
	default:
		break;
	}
	if (!bFind) {
		// 恢复按钮 可用状态
		GetDlgItem(IDC_BUTTON_NEXT)->EnableWindow(TRUE);
		// 继续搜索标置(false)
		m_bGoon = false;
		UpdateData(FALSE);
		return;
	}

	const std::list<DWORD>& lst = m_pFinder->GetResults();
	int index = 1024; //最多显示1024结果
	for (auto addr : lst) {
		if (index-- <= 0) {
			break;
		}
		int index = m_listAddressTemp.InsertItem(0, _T(""));
		CString s;
		s.Format(_T("%08X"), addr);
		m_listAddressTemp.SetItemText(index, 0, s);
	}
	// 进度条清0
	m_pProgress.SetPos(0);
	// 恢复按钮 可用状态
	GetDlgItem(IDC_BUTTON_NEXT)->EnableWindow(TRUE);
	m_bGoon = false;
	UpdateData(FALSE);
}

3.3 停止搜索

双击停止搜索按钮,加入以下代码
C++ + MFC 写一个程序参数修改器(五、界面交互)_第6张图片
以首次搜索为例:
由于m_bGoon被作为一个回调的变量,此变量一旦为false,则回调函数返回false,则搜索直接结束
C++ + MFC 写一个程序参数修改器(五、界面交互)_第7张图片

四、listctrl控件点击操作

右键添加事件处理程序
C++ + MFC 写一个程序参数修改器(五、界面交互)_第8张图片

在生成的函数中加入以下代码:
C++ + MFC 写一个程序参数修改器(五、界面交互)_第9张图片
以上的代码逻辑很简单:
第一个listctrl双击选中的地址,应在第二个listctrl控件上显示该地址的值以及类型等其他信息
第二个listctrl双击应在软件的右侧修改参数这里,将值、类型、地址显示到edit控件上

五、修改参数

双击修改参数按钮
C++ + MFC 写一个程序参数修改器(五、界面交互)_第10张图片

六、最后

好了,到这里基本功能就写完了,
使用该程序可以修改任意的本地程序的数值类型的参数
比如某游戏的阳光数目,通信程序发送的数据量,某游戏的命数

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