windows消息机制

整个windows包括七个步骤
1.入口函数
2.窗口注册信息
3.窗口创建
4.显示窗口
5.更新窗口
6.消息循环
7.入口函数结束
FindWindow这个函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串。这个函数不搜索子窗口
消息队列(Message Queue)是一种进程间通信或同一进程的不同线程间的通信方式。
CS类风格
WS是窗口风格

SendMessage
函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。
函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。一般用if语句,外面用while嵌套
DispatchMessage
函数功能:该函数分发一个消息给窗口程序。通常消息从GetMessage函数获得或者TranslateMessage函数传递的。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。

**windows操作系统最大的特色是良好的用户交互性
消息机制:产生消息,传递消息并处理消息的过程**
1、产生消息  不可控
typedef struct tagMSG
{
HWND hwnd;//窗口句柄
UINT message;//消息id
WPARAM wParam;//消息的辅助参数
LPARAM lParam;//消息的辅助参数
DWORD time;//消息产生的时间
POINT pt;//消息产生时鼠标的坐标
} 	MSG;
2、传递消息 (分成两个部分,1、系统传递消息给应用程序 不可控;2、应用程序传递消息给应用程序 可控(自己可以这么觉得))
windows操作系统为每一个正在运行的应用程序维护一个消息队列 

3、处理消息 可控 把消息当成条件,怎么拿到这个条件 

DispatchMessage
点击右上角关闭按钮直接产生的,仅仅是WM_CLOSE消息,如果我们没有去捕获WM_CLOSE,或者捕获后使用的是break而不是return,那么DefWindowProc有机会执行。
DefWindowProc是一个会产生消息的函数,当WM_CLOSE消息产生之后,如果去执行了DefWindowProc函数,那么他会 接着依次连续产生WM_DESTROY WM_NCDESTROY这两个消息。
而在WM_DESTROY处理函数中写上了PostQuitMessage(0)这个函数,WM_QUIT 是由这个函数参数的。WM_QUIT这个消息 在过程函数(WndProc)中无法捕捉到,因为在GetMessage的时候捕获到WM_QUIT 时返回值为0,就会导致主函数退出了。

// class03.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "class03.h"

#define MAX_LOADSTRING 100

// 全局变量: 
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名

// 此代码模块中包含的函数的前向声明: 
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO:  在此放置代码。
	MSG msg = {};
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_CLASS03, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 执行应用程序初始化: 
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLASS03));//加载快捷键


	 主消息循环: 
	GetMessage 是从消息队列得到消息,如果消息队列没有消息,函数阻塞,等待消息,如果得到了消息,要判断这个消息是否是WM_QUIT消息,如果是,函数返回false,如果不是,函数返回true
	//while (GetMessage(&msg, NULL, 0, 0))//从消息队列取消息,取出来放在第1个参数,最后两个参数表示消息的过滤,第3个参数表示的id到第4个参数表示的id这个区间表示的消息id才能被得到,给0,表示不过滤
	//{
	//	if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))//翻译快捷键
	//	{
	//		TranslateMessage(&msg);//翻译消息,主要做键盘消息的翻译
	//		DispatchMessage(&msg);//投递消息
	//	}
	//}

	//PeekMessage 从消息队列去取得消息,如果消息队列有消息,返回true,没有消息,返回false
	ZeroMemory(&msg, sizeof(msg));  //ZeroMemory宏用0来填充一块内存区域。
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))//最后一个参数表示从消息队列移除消息
		{
			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))//翻译快捷键
			{
				TranslateMessage(&msg);//翻译消息,主要做键盘消息的翻译
				DispatchMessage(&msg);//投递消息
			}
		}
		//游戏的画面更新
		//游戏的数据更新
	}


	return (int) msg.wParam;
}



//
//  函数:  MyRegisterClass()
//
//  目的:  注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLASS03));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_CLASS03);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   函数:  InitInstance(HINSTANCE, int)
//
//   目的:  保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }
//只更新一次
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数:  WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;//重要消息讲
	PAINTSTRUCT ps;//gdi讲
	HDC hdc;//gid讲

	switch (message)
	{
	//case WM_LBUTTONDOWN://鼠标左键点击消息
	//{
	//						SendMessage 可以理解为插队,理解为递归,直接把消息投递给窗口对应的消息处理函数
	//						//SendMessage(hWnd,//发给哪个窗口
	//						//	WM_KEYDOWN,//发送的消息id
	//						//	0, 0);//后两个参数表示这个消息id的辅助信息
	//						PostMessage(hWnd, WM_KEYDOWN, 0, 0);//理解为排队,把消息直接投递给窗口对应的消息队列,以供下一次得到消息时从消息队列取出
	//						Sleep(1000);
	//						hdc = GetDC(hWnd);
	//						TextOut(hdc, 0, 0, _T("button"), 6);
	//						ReleaseDC(hWnd, hdc);
	//}
	//	break;
	//case WM_KEYDOWN://键盘按下消息
	//{
	//					Sleep(2000);
	//					hdc = GetDC(hWnd);
	//					TextOut(hdc, 200, 0, _T("keydown"), 7);
	//					ReleaseDC(hWnd, hdc);
	//}
	//	break;
	case WM_SYSCOMMAND:
		switch (wParam)
		{
		case SC_CLOSE:
			if (IDYES == MessageBox(0, _T("你是真的要退出吗?"), 0, MB_YESNO))   //IDYES选择确定
				DefWindowProc(hWnd, message, wParam, lParam);
			break;
		default:
			DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_COMMAND://菜单里面讲
		wmId    = LOWORD(wParam);//重要消息讲
		wmEvent = HIWORD(wParam);
		// 分析菜单选择: 
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);//对话框讲
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);//销毁窗口
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);//默认的窗口处理函数
		}
		break;
	case WM_PAINT://gdi讲的
		hdc = BeginPaint(hWnd, &ps);
		// TODO:  在此添加任意绘图代码...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY://销毁消息
		PostQuitMessage(0);//投递退出消息(PostMessage(hWnd, WM_QUIT, 0, 0);)
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风赤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值