Windows各种内置消息

MFC在VS2010\VC\atlmfc\include\afxmsg_.h中宏定义的Windows消息的消息映射表,即将某Windows消息同其响应函数关联的宏定义:
Window Notifications

在这里插入图片描述
1、WM_CREATE消息
在这里插入图片描述
消息响应函数OnCreate(LPCREATESTRUCT lpCreateStruct)传入参数是一个指向CREATESTRUCT结构体对象的指针:
Windows Procedures窗口过程:

//VS2010:
class CWnd:public CCmdTarget
protected:
	// for processing Windows messages
	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
	virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//VS2010中afxwin.h中CWnd::WindowProc成员函数与微软官网的全局WindowProc函数不是一个东西,前者由this窗口调用,后者则需要传入窗口句柄,Window precedure概念理解这里看LRESULT CALLBACK WindowProc()
//[https://docs.microsoft.com官方最新文件中WindowProc函数](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633573%28v=vs.85%29?redirectedfrom=MSDN)
LRESULT CALLBACK WindowProc(
  _In_ HWND   hwnd,
  _In_ UINT   uMsg,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

Window Procedures
每个窗口都有一个关联的窗口过程——一个处理所有发送到该(窗口)类的所有窗口的所有消息的函数。一个窗口各个方面的外观和行为都取决于window procedure对这些消息的响应。
一、关于窗口过程:
每个窗口都是特定窗口类的成员。窗口类确定单个窗口(对象)用于处理其消息的默认窗口过程。属于同一(窗口)类的所有窗口都使用相同的默认窗口过程。例如,系统为组合框类COMBOBOX定义了一个窗口过程window procedure。然后,所有组合框(对象)都将使用该窗口过程window procedure。
应用程序通常注册至少一个新的窗口类及其关联的窗口过程(自定义窗口类往往派生自CWnd基类,而CWnd基类定义了WindowProc()窗口过程函数?)。注册一个(窗口)类后,应用程序类可以创建该类的许多窗口,所有这些窗口都使用相同的窗口过程函数WindowProc()。因为这意味着多个源可以同时调用同一段代码,所以从窗口过程修改共享资源时必须小心。有关更多信息,请参见窗口类Window Classes.
1.1
窗口过程的结构
窗口过程函数WindowProc是具有4个参数并返回带符号值的函数。这些参数包括一个窗口句柄(微软官网最新的全局WindowProc函数与VS2010中afxwin.h中CWnd::WindowProc成员函数不是一个东西,后者由this窗口调用,前者则需要传入窗口句柄)、一个UINT消息标识符以及两个使用WPARAM和LPARAM数据类型声明的消息参数。
消息参数通常包含其低位和高位字信息。应用程序使用几个宏来从消息参数中提取信息:

//...
#define MAKEWORD(a, b)      ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
#define LOWORD(l)           ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l)           ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
#define LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
#define HIBYTE(w)           ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))
    返回值的解释取决于特定的消息。
    1.2
    默认窗口过程
    默认的窗口过程函数DefWindowProc()定义了所有窗口共享的某些基本行为。默认的窗口过程为窗口提供了最少的功能。应用程序定义的窗口过程应将未处理的任何消息传递给DefWindowProc()函数,以进行默认处理,该函数确保处理所有消息。DefWindowProc()函数用窗口过程WindowProc()函数接收到的相同参数调用。
LRESULT LRESULT DefWindowProcA(
  HWND   hWnd,
  UINT   Msg,
  WPARAM wParam,
  LPARAM lParam
);
   1.3
   窗口过程子类化
   当应用程序创建窗口时,系统会分配一块内存,用于存储特定于该窗口的信息,包括处理该窗口消息的窗口过程的地址。当系统需要将消息传递给窗口时,它将在特定于窗口的信息中搜索窗口过程的地址,然后将消息传递给该过程函数。
   应用程序通过将窗口的原始窗口过程的地址替换为新窗口过程的地址(称为子类过程)来对窗口进行子类化。此后,子类过程接收发送或发布到窗口的任何消息。
   子类化是一种技术,它允许应用程序在窗口有机会处理它们之前,拦截和处理发送或发布到特定窗口的消息(这是窗口的原窗口过程的工作)。通过子类化窗口,应用程序可以扩充、修改或监视窗口的行为。应用程序可以将属于系统全局类(直接派生自CWnd类)的窗口(例如,编辑控件或EditCtrl列表框List Box)子类化(即替换其窗口过程)。例如,应用程序可以将编辑控件子类化,以防止该控件接收某些字符(检测到这些字符输入后并不会在Edit Control控件中UpdateData()显示,同时可以Tip提示)。但是,不能将属于另一个应用程序的窗口或类子类化(即子类化是针对某个应用程序的窗口类或控件类的,另一应用程序的窗口类或控件类不受影响)。所有子类化必须在同一过程中执行 (All subclassing must be performed within the same process)。
   子类过程在收到消息时可以采取三个动作:它可以将消息传递给原始窗口过程,修改消息并将其传递给原始窗口过程,或者处理该消息而不将其传递给原始窗口过程。如果子类过程处理消息,则可以在将消息传递到原始窗口过程之前,之后或之前和之后进行处理。
   系统提供两种类型的子类:实例和全局。在实例子类化中,应用程序替换窗口的单个实例(窗口对象)的窗口过程地址。应用程序必须使用实例子类化来子类化现有窗口。在全局子类化中,应用程序替换窗口类的WNDCLASS结构中的窗口过程地址。使用该类创建的所有后续窗口都具有子类过程的地址,但是该类的现有窗口不受影响。
   1.3.1
   实例子类化
   应用程序使用SetWindowLongA()函数将窗口的实例(窗口对象)子类化。
LONG SetWindowLongA(
  HWND hWnd,
  int  nIndex,
  LONG dwNewLong
);
   应用程序将GWL_WNDPROC标志(nIndex)、窗口的句柄(hWnd)传递给子类,并将子类过程(自定义新的窗口过程函数)的地址(dwNewLong)传递给SetWindowLongA。子类过程可以驻留在应用程序的可执行文件或DLL中。
   SetWindowLongA()返回窗口原始窗口过程的地址。应用程序必须保存该地址,以便在后续对CallWindowPro()函数的调用中使用该原始窗口过程的地址,已将截获的消息传递给原始窗口过程。应用程序还必须具有原始的窗口过程地址,才能从窗口类删除子类。为了删除子类,应用程序再次调用SetWindowLongA(),将原始窗口过程的地址与GWL_WNDPROC标志和窗口句柄一起传递给窗口(即SetWindowLongA()函数相当于用传入的窗口过程函数地址替换前一窗口过程函数地址)。
   由于实例子类化是在创建窗口之后(产生窗口对象句柄)发生的,因此您无法向该窗口添加任何额外的字节。子类化窗口的应用程应使用窗口的属性列表来存储子类化窗口的实例所需的任何数据。???
   当应用程序对子类化窗口进行子类化时,它必须以与执行相反的顺序删除子类。如果移除顺序不正确,则可能发生不可恢复的系统错误。???
   1.3.2
   全局子类化
   ???

afxwin.h文件中声明了MFC中设备描述表类CDC、菜单类CMenu、基窗口类CWnd、基对话框类CDialog、各种控件类、应用程序类CWinApp

typedef struct tagCREATESTRUCTA {
  LPVOID    lpCreateParams;
  HINSTANCE hInstance;
  HMENU     hMenu;
  HWND      hwndParent;
  int       cy;
  int       cx;
  int       y;
  int       x;
  LONG      style;
  LPCSTR    lpszName; //表示该窗口类所在的应用程序名
  LPCSTR    lpszClass;
  DWORD     dwExStyle;
} CREATESTRUCTA, *LPCREATESTRUCTA;

2、WM_COPYDATA消息

/*一个应用程序发送WM_COPYDATA消息以将数据传递给另一个应用程序*/
#define ON_WM_COPYDATA() \
	{ WM_COPYDATA, 0, 0, 0, AfxSig_bWCDS, \
		(AFX_PMSG)(AFX_PMSGW) \
		(static_cast< BOOL (AFX_MSG_CALL CWnd::*)(CWnd*, COPYDATASTRUCT*) > ( &ThisClass :: OnCopyData)) },

OnCopyData()函数处理WM_COPYDATA消息从一个应用程序传到另一个应用程序 逼格太高还没用过
3、WM_DESTROY消息
在这里插入图片描述

4、WM_MOVE消息
在这里插入图片描述
消息响应函数OnMove(int x,int y)传入(x,y)为窗口客户区左上角的x,y坐标。

template <typename NumType>
char* Num2Char(NumType Num)
{
	const type_info& t=typeid(Num);
	const char* TypeName=t.name();
	char* Result=new char[327];
	if(TypeName[0]=='i'&&TypeName[1]=='n'&&TypeName[2]=='t')
	{
		int Digit=0,ten=1000000000; //int –2147483648至十进制2147483647
		int index=0;
		Result[index++]=Num<0?'-':' ';
		while(ten>=1)
		{
			Digit=std::abs(Num)/ten;
			Num-=(std::abs(Num)/ten)*ten;
			Result[index++]=('0'+Digit);
			ten/=10;
		}
		Result[index]='\0';
		//cut the front '0's
		index=0;
		for(;;)
		{
			if(Result[index]=='0'||Result[index]==' '){++index;}
			else break;
		}
		for(int i=0;i<index;++i) ++Result;
		return Result;
	}
	else if(TypeName[0]=='f'&&TypeName[1]=='l'&&TypeName[2]=='0'||TypeName[0]=='d'&&TypeName[1]=='o'&&TypeName[2]=='u')
	{
		return Result;
	}
	else return Result;
}

5、WM_SIZE消息
要使对话框窗口能改变大小,需在建立MFC应用程序时——用户界面功能,选中最小化框、最大化框
在这里插入图片描述
6、WM_ACTIVATE消息
WM_ACTIVATE消息发送到被激活的窗口和被禁用的窗口。如果窗口使用相同的输入队列,则消息将同步发送,首先发送到被停用的顶层窗口的窗口过程,然后发送到被激活的顶层窗口的窗口过程。如果窗口使用不同的输入队列,则消息将异步发送,因此将立即激活窗口?

afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
/*nState表示this窗口被操作即将变成的状态
  nState=WA_ACTIVE(1)表示this窗口是通过鼠标单击以外的其他方法被激活的(例如,通过调用SetActiveWindow()函数或使用键盘界面选择窗口)。
  nState=WA_CLICKACTIVE(2)表示this窗口是通过鼠标单击被激活的。
  nState=WA_INACTIVE(3)表示this窗口被停用(即不处于被激活状态)。
  pWndOther被解释为 被激活或停用的窗口的句柄,取决于nState值。当为WA_INACTIVE时,pWndOther为正在被激活的窗口的句柄。当未WA_ACTIVE或WA_CLICKACTIVE时,pWndOther未正在被灭活的窗口的句柄(我调试时pWndOther始终为0x00)。该句柄可以为NULL
*/

在这里插入图片描述
7、WM_SETFOCUS消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值