分析代码
实战部分
DebugView Not Connected
打印机删掉
添加串口
新建MFC动态库


MFCLEI.dll
// MFCLEI.cpp: 定义 DLL 的初始化例程。//#include "stdafx.h"#include "MFCLEI.h"#ifdef _DEBUG#define new DEBUG_NEW#endif////TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,// 则从此 DLL 导出的任何调入// MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到// 该函数的最前面。//// 例如: //// extern "C" BOOL PASCAL EXPORT ExportedFunction()// {// AFX_MANAGE_STATE(AfxGetStaticModuleState());// // 此处为普通函数体// }//// 此宏先于任何 MFC 调用// 出现在每个函数中十分重要。 这意味着// 它必须作为以下项中的第一个语句:// 出现,甚至先于所有对象变量声明,// 这是因为它们的构造函数可能生成 MFC// DLL 调用。//// 有关其他详细信息,// 请参阅 MFC 技术说明 33 和 58。//// CMFCLEIAppBEGIN_MESSAGE_MAP(CMFCLEIApp, CWinApp)END_MESSAGE_MAP()// CMFCLEIApp 构造CMFCLEIApp::CMFCLEIApp(){ // TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中}// 唯一的 CMFCLEIApp 对象CMFCLEIApp theApp;HWND g_Wnd;WNDPROC g_OldhProc;PWORD g_pHeight = (PWORD)0x1005338;PWORD g_pWidth =(PWORD)0x1005334;PWORD g_pMineCount = (PWORD)0x1005330;#define MINE 0x8FPBYTE g_pBase = (PBYTE)0x1005340;// CMFCLEIApp 初始化LRESULT CALLBACK WindowProc( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam){ if (Msg == WM_KEYDOWN && wParam == VK_F5)//如果键盘按下并且是f5 { //一件秒杀 OutputDebugString(L"F5"); int nHeight = *g_pHeight; int nWidth = *g_pWidth; int nMineCount = *g_pMineCount; CString strString; strString.Format(L"宽度:%d, 高度:%d, 雷数:%d", nHeight, nWidth, nMineCount); OutputDebugString(strString.GetBuffer()); //雷区基地址 //雷区中的元素标识 //01002EE4 | . 8B0D 34530001 MOV ECX, DWORD PTR DS : [<宽度x>]; 宽度 //01002EEA | . 8B15 38530001 MOV EDX, DWORD PTR DS : [<高度y>]; 高度 //01002EF0 | . 8D41 02 LEA EAX, DWORD PTR DS : [ECX + 0x2] //01002EF3 | . 85C0 TEST EAX, EAX //01002EF5 | . 56 PUSH ESI //01002EF6 | . 74 19 JE SHORT winmine.01002F11 //01002EF8 | . 8BF2 MOV ESI, EDX //01002EFA | .C1E6 05 SHL ESI, 0x5 //01002EFD | . 8DB6 60530001 LEA ESI, DWORD PTR DS : [ESI + 0x1005360] //01002F03 | > 48 / DEC EAX //01002F04 | .C680 40530001 > | MOV BYTE PTR DS : [EAX + <数组基地址>], 0x10 //01002F0B | .C60406 10 | MOV BYTE PTR DS : [ESI + EAX], 0x10 //01002F0F | . ^ 75 F2 \JNZ SHORT winmine.01002F03 int nFindCount = 0; int y = 1; for (int y=1;y<nHeight;y++) { CString strLine; for (int x = 1; x < nWidth + 1; x++) { BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32); if (byCode == MINE) { nFindCount++; int xPos, yPos; xPos = (x << 4) - 4; yPos = (y << 4) + 0x27; SendMessage(hWnd, WM_RBUTTONDOWN, 0, MAKELPARAM(xPos, yPos)); SendMessage(hWnd, WM_RBUTTONUP, 0, MAKELPARAM(xPos, yPos)); SendMessage(hWnd, WM_RBUTTONDOWN, 0, MAKELPARAM(xPos, yPos)); SendMessage(hWnd, WM_RBUTTONUP, 0, MAKELPARAM(xPos, yPos)); } else { int xPos, yPos; xPos = (x << 4) - 4; yPos = (y << 4) + 0x27; SendMessage(hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(xPos, yPos)); SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(xPos, yPos)); } CString strCode; strCode.Format(L"%02x", byCode); strLine += strCode; } OutputDebugString(strLine.GetBuffer()); } CString strCode; strCode.Format(L"找到的雷数%d", nFindCount); OutputDebugString(strCode.GetBuffer()); } else if(Msg==WM_MOUSEMOVE) { //鼠标移动 int x, y; x = LOWORD(lParam); y = HIWORD(lParam); x = (x + 4) >> 4; y = (y - 0x27) >> 4; BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32); if (byCode==MINE) { SetWindowText(hWnd, L"此处有雷!!"); } else { CString strPos; strPos.Format(L"(%d,%d", y, x); SetWindowText(hWnd, strPos); } } return CallWindowProc(g_OldhProc, hWnd, Msg, wParam, lParam);}BOOL CMFCLEIApp::InitInstance(){ CWinApp::InitInstance(); //1.通过查找窗口,获取窗口句柄 g_Wnd = ::FindWindow(L"扫雷", L"扫雷"); if (NULL== g_Wnd) { OutputDebugString(L"无法找到 扫雷窗口"); return false; } //2.设置窗口回调函数 g_OldhProc=(WNDPROC)SetWindowLong(g_Wnd,GWL_WNDPROC,(LONG)WindowProc);//设置窗口句柄(窗口句柄,索引值,) if (NULL == g_OldhProc) { OutputDebugString(L"设置窗口回调函数 失败"); return false; } return TRUE;}
