23win32编程基础——消息与消息队列

win32编程中一切都是消息。

当在windows中比如鼠标点下去或者移动等操作会产生一个动作,这个动作就是消息。

问题一:传递的消息里面应该包括哪些内容?

  1、坐标,比如点击的问题

  2、点击的对象,比如点击的是哪个窗体。

  3、鼠标左键还是右键,消息的类型。

 因此查看MSDN中的消息定义,可以知道:

typedef struct tagMSG {     // msg  
   HWND hwnd;          //窗口的句柄,相当于点击的哪个窗体,这个窗体接收点击的消息,然后进行反应。
   UINT message;       //消息ID,代表消息的类型,具体是哪种消息,点击,移动等 
   WPARAM wParam;       //对消息进一步的说明,有的时候存储的消息内容很多,就需要这2个参数进行扩充存储消息的其他信息
   LPARAM lParam;       //对消息进一步的说明,有的时候存储的消息内容很多,就需要这2个参数进行扩充存储消息的其他信息
DWORD time;        //点击的时间
POINT pt;        //坐标 } MSG;

  消息队列和消息处理的流程:

1、当按下键盘,就会产生一个动作,即消息MSG。

2、操作系统OS把这个消息,先保存到自己的消息队列中,os先保存起来,是为了后边的分发,这相当于1个中转站。

3、每个应用程序运行之后,会在内核中有个自己的消息队列,操作系统会把收到的消息分发给每个应用程序的消息队列中。

4、然后自己编写代码,应用程序中写一个死循环,就是从消息队列中不断取出来消息。

5、然后自己编代码,这些消息是不是自己要处理的消息,如果是自己要处理的,就写相应的消息处理函数进行处置。

6、如果不是自己关心的消息,再返回给操作系统进行处置。

以上就是整个消息处置的过程,因此后边的3条是我们自己写的:

消息循环,消息处置和默认操作系统处置。

我们先学会自己创建1个窗体的过程:

//MSDN告诉我们,在windows中,窗口类长下边这样,可以利用这个窗口类创建窗口对象。
typedef struct {
    UINT style;            //哪种格式的窗口,按钮还是下拉框、Edit等
    WNDPROC lpfnWndProc;      //回调函数
    int cbClsExtra;
    int cbWndExtra;      
    HINSTANCE hInstance;      //这个窗口属于哪个应用程序
    HICON hIcon;          //窗体的左上角的那个小图标
    HCURSOR hCursor;        //鼠标是什么形状
    HBRUSH hbrBackground;    //背景色
    LPCTSTR lpszMenuName;    //如果有菜单的话,菜单的名字
    LPCTSTR lpszClassName;  //窗体类的名字
} WNDCLASS, *PWNDCLASS
//并且需要使用RegisterClass进行注册。

  代码如下:

要了解整个代码的流程:

// 20C++Win32CreateWind.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "20C++Win32CreateWind.h"
#include "OutPut.h"

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	//不用系统以及准备好的窗口类,我们自己创建1个窗口类
	TCHAR className[] = L"My Windows";
	//WNDCLASS wndclas;小bug
	WNDCLASS wndclas={0};	//这个用之前必须先初始化。
	wndclas.lpszClassName = className;				//别人用的时候,根据这个类名使用
	wndclas.hbrBackground = HBRUSH(COLOR_GRAYTEXT);	//窗口背景
	wndclas.lpfnWndProc =WndProc ;					//回调函数
	wndclas.hInstance = hInstance;					//应用程序句柄,哪个应用程序创建的这个窗口类
	
	//注册,告诉操作系统有这么1个窗体类长这样,别的地方可以使用了。
	RegisterClass(&wndclas);
	
	//创建
	HWND hwnd = CreateWindow(
		className,			//用我自己定义的窗体类,不用windows里面已经创建好的窗口类
		TEXT("窗口的标题"), //窗口标题
		WS_OVERLAPPEDWINDOW, //窗口外观样式
		10,20,				//坐标
		300,600,			//大小
		NULL,				//父窗口句柄,第一个窗口,目前没有父窗口
		NULL,				//菜单句柄,不带菜单栏
		hInstance,			//当前应用程序的句柄
		NULL);				//附加数据
	//显示窗口
	ShowWindow(hwnd,SW_SHOW);
	//消息循环
	MSG msg;
	int bRet = 0;
	while( (bRet = GetMessage( &msg, hwnd, 0, 0 )) != 0)//不停的取消息
	{ 
		if (bRet == -1)
		{
			// handle the error and possibly exit
			OutputDebugStringF("%d\n",GetLastError());
		}
		else
		{
			TranslateMessage(&msg);			//翻译成更具体的消息 
			DispatchMessage(&msg);			//再传递给操作系统,然后操作系统自动调用回调函数。
		}	
	}

	return 0;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message){
		case WM_DESTROY:
				PostQuitMessage(0);
				return 0;

	}
	//我不关系的消息,操作系统自己去处理
	
				return DefWindowProc(hWnd, message, wParam, lParam);
	
}

  

 

posted @ 2023-10-23 11:18  一日学一日功  阅读(100)  评论(0)    收藏  举报