26win32编程基础——VisualStdio2010资源文件创建对话框和消息断点的本质是什么?

先创建1个空的win32项目

然后在资源文件--->右键---->添加*.rc

 添加完之后,解决方案会多出来2个文件

 然后切换到“资源视图”-->右键---->添加资源----->Dialog

 就会出来1个对话框

 然后在“解决方案管理器”中添加一个cpp文件,作为入口函数。

#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	return 0;
}

基本框架就搭建好了。

然后按照之前学过的窗口创建过程创建对话框(对话框、按钮等凡事皆窗口):

	//1、创建窗口类
	//2、窗口类赋值
	//3、注册窗口类
	//4、创建窗口------>我们只需要做这一步
	//5、显示窗口
	//6、消息循环
	//7、回调函数------>回调函数也需要写,其他的都是系统做好的

  Dialog也是窗口,之前我们创建窗口的7步,系统为我们做了一些事情,我们可以直接从4创建对话框开始,使用:

INT_PTR DialogBox(        
HINSTANCE hInstance,   //属于哪个应用程序 LPCTSTR lpTemplate,    //对话框模板 HWND hWndParent,      //父窗口 DLGPROC lpDialogFunc    //回调函数 );

 因此

#include <windows.h>
#include "resource.h"
HINSTANCE hIns;
INT_PTR CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,  WPARAM wParam,LPARAM lParam);//对话框回调函数的声明
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	
	//1、创建窗口类
	//2、窗口类赋值
	//3、注册窗口类
	//4、创建窗口------------>需要我们做
	//5、显示窗口
	//6、消息循环
	//7、回调函数------------>需要我们做

	//Dialog也是窗口,之前我们创建窗口的7步,系统为我们做了一些事情,我们只需要做2步,可以直接创建对话框
	hIns = hInstance;
	DialogBox(hIns,MAKEINTRESOURCE(ID_DialogMain),NULL,DialogProc);

	return 0;
}
//对话框的消息处理函数:处理了返回true,未处理返回false
//窗口的消息处理函数:处理了返回0,未处理使用默认的消息处理函数让系统处置
INT_PTR CALLBACK DialogProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam)
{
	int idDialog = LOWORD(wParam);

	switch(uMsg)
	{
	case  WM_INITDIALOG :
		return TRUE;
	case WM_QUIT:
		PostQuitMessage(0);
		return TRUE;
	case WM_COMMAND:
	{
		int idDialog = LOWORD(wParam);
		switch(idDialog){
			case IDC_BUTTON_OK:
				{
				HWND hUserEdit = GetDlgItem(hwndDlg,IDC_USER_EDIT);
				HWND hPassEdit = GetDlgItem(hwndDlg,IDC_PASS_EDIT);
				char User[20];
				char Pass[20];
				//GetDlgItemText(hwndDlg,IDC_USER_EDIT,User,20);
				//GetDlgItemText(hwndDlg,IDC_PASS_EDIT,Pass,20);
				GetWindowText(hUserEdit,User,20);
				GetWindowText(hPassEdit,Pass,20);
				if(strcmp(User,"123")==0 && strcmp(Pass,"456")==0)
				{
					MessageBox(0,"输入正确!\n","正确",0);
				}else{
					MessageBox(0,"输入的用户名或者密码错误\n","ERROR",0);
				}
				
				return 0;
				}
			case IDC_BUTTON_CANCEL:
				MessageBox(0,"CANCEL","点击的",0);
				return 0;

		}
			
		break;
	}
		
	}
	return FALSE;
};

  由于我们只需要:创建对话框和编写回调函数,那么我们如何定位到我们感兴趣的回调函数的代码位置呢?

 问题一:

  假如我们的DialogBox对话框上有100个按钮,我们如何找到“注册”按钮对应的处理方法的位置呢?

我们以我们上边的最简单的对话框函数为例,结合od把windows的整个消息处理过程说清楚:

DialogBox创建的对话框,其实内部调用的是DialogBoxParamA这个函数,
然后根据第4个参数,找到DialogBox的回调函数,但是如果对话框上的按钮太多了,我们不可能1个1个的去找,如何快速找到“确定”按钮对应的消息处理位置呢?

用消息断点,可以快速的找到感兴趣的按钮的对应处理方法:

1、先od加载对应程序

2、F9先运行起来,把相关的界面和按钮都显示出来

3、然后在菜单“W”中----->找到对应的控件

 我们知道,如果直接使用系统提供的窗口类创建窗口(对话框、按钮),系统会自动为我们注册1个回调函数,然后系统的这个回调函数最终会调用我们自己编写的回调函数。

 因此从上图我们可以知道,可以从系统回调函数找到我们想要的回调过程,系统提供的回调函数是:0x7650739D

4、我们先在系统的回调函数位置下断点,右键--->在回调函数上设置消息断点

但是现在出现1个问题,我们怎么知道到底是鼠标按下去,还是鼠标松开产生的消息呢?

小技巧pis:测试一下,打开程序,然后对着按钮长按不松,如果是按下产生的消息,那么就会有反应,如果定义的是松开,那么程序就不会有反应(提示错误)

然后再松开,如果有反应(弹出提示),那么就能知道到底是WM_LBUTTONDOWN还是WM_LBUTTONUP

 下完消息断点,然后输入直接点击“确定”;

 然后程序就会在0x7650739D断下来,

 5、我们知道最终会从0x7650739D----------到------>“确定”的消息处理位置

  1、笨方法,单步执行,肯定最终会到“确定”的消息处理位置

  2、既然最终会执行到“确定”的消息处理位置,也就是最终回到.text代码段

我们下一步就在.text代码段下访问断点,当从0x7650739D执行到.text代码段的第一行代码的时候就会停下来。

 下完内存访问断点之后,我们F9运行起来。

 这个位置就很有可能就是我们要找的位置,我们看下[ESP+8]的位置应该是WM_COMMAND(0x111)

 说明这个位置还不是我们要找到WM_COMMAND消息的位置,为什么?

//对话框的消息处理函数:处理了返回true,未处理返回false
//窗口的消息处理函数:处理了返回0,未处理使用默认的消息处理函数让系统处置
INT_PTR CALLBACK DialogProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam)

我们现在段下来的位置,就是对话框的回调函数的位置:

  回调函数是无时无刻被系统调用的,所以消息是一直有的,并不是我们按下按钮之后,当我们不按的时候,就没有消息了,当暂停的时候,还有别的消息传递过来。

我们先把代码段的消息访问断点删除掉,不然访问一下代码段就会停一下:

 

因此我们还需要完善我们的条件:

 当是控件0x3E9(注册按钮的id),并且是WM_COMMAND的消息的时候,才是我们想要的消息处理函数,然后我们单步F8,就找到我们正确的消息处理位置了。

 我们只有对前边的:消息循环和消息传递充分理解,才能知道每一步在od中为什么操作。

  外边的很多文章在消息循环这一块,只是讲了怎么操作,

  根本没有讲为什么这样做?

  我们做的逻辑都是前边的基础,并不是瞎做的,只有基础打牢,才能对各个过程充分理解,这就是学习底层的魅力所在。

 

posted @ 2023-10-24 17:28  一日学一日功  阅读(222)  评论(0)    收藏  举报