WIN32 VC Windows消息循环简单例子

最近项目又用到windows消息,多线程环境并遇到了问题:

1、消息处理函数没有执行。

2、GetMessage API一直等待。

详见 :多线程与WINDOWS消息。

因时间久了没接触windows消息,有点忘记了,需要熟悉一下创建窗口都消息循环的步骤流程,

下面给出两种实现,都需要windows环境:

1、控制台程序:通用方式,任意的程序都可以直接用。

      ------多线程注意事项参考另一篇:多线程与WINDOWS消息。

2、WIN32窗体程序:一般方式。

控制台程序流程

程序入口:int main();

#include <windows.h>    //包含 Windows 相关的 API 函数

// 消息处理函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// 注册窗口
bool RegisterWindow();
// 窗口创建
bool Create();
// 消息循环
void MsgLoop();


/*************************
* 入口函数,测试窗口消息
***************************/
int main()
{
	RegisterWindow(); // 窗口注册
	Create();                 // 窗口创建
	MsgLoop();           //  消息循环
	return 0;
}

// 消息处理函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	bool handle = true;
	switch (uMsg)    //消息选择
	{
	case WM_LBUTTONDOWN:
		break;
	default:
		handle = false;
		break;
	}
	if (handle) {
		return S_OK;
	}
	return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

// 注册窗口
bool RegisterWindow() {
	HINSTANCE hInstance = GetModuleHandleA(NULL);

	//当然, 如果不创建窗口, 不使用窗口 也可以使用 main.
	WNDCLASSEXA wc = { 0 };            //窗口类结构, 为注册窗口类作准备
	wc.cbClsExtra = 0;                //附加的类信息, 没有, 设为0
	wc.cbSize = sizeof(wc);            //WNDCLASSEX结构的大小
	wc.cbWndExtra = 0;                //窗口额外内存, 没有, 设为0
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);            //窗口背景, 这里使用灰色背景
	wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));        //应用程序使用的鼠标类型
	wc.hIcon = LoadIconA(NULL, MAKEINTRESOURCEA(IDI_APPLICATION));    //光标类型
	wc.hIconSm = NULL;                    //应用程序程序的小光标, 不管, 设为 NULL
	wc.hInstance = hInstance;            //应用程序程序实例句柄, 由 WinMain 函数传递过来

	//当前窗口的消息处理函数, 传递 WndProc 的地址
	wc.lpfnWndProc = WndProc;

	wc.lpszClassName = "vbgk_class";    //创建类时使用的类名, 可以自定义
	wc.lpszMenuName = NULL;                //菜单, 没有, 就使用 NULL
	wc.style = CS_HREDRAW | CS_VREDRAW;    //类的风格, 垂直重绘, 水平重绘

	if (!RegisterClassExA(&wc)) { //注册窗口类
		MessageBoxA(NULL, "Register Class Failed!", NULL, MB_OK);
		return false;
	}
	return true;
}

// 窗口创建
bool Create() {
	HINSTANCE hInstance = GetModuleHandleA(NULL);
	//创建窗口
	HWND hWnd = CreateWindowExA(
		0,                    //扩展窗口风格
		"vbgk_class",        //这里就是我们刚才创建的窗口类名
		"test title",
		WS_OVERLAPPEDWINDOW,//窗口风格
		CW_USEDEFAULT,        //初始化时的 X 坐标
		CW_USEDEFAULT,        //Y坐标
		320,        //窗口宽度, 我们这里设为 320
		240,        //窗口高度
		NULL,        //父窗口句柄, 没有
		NULL,        //菜单, 没有
		hInstance,    //实例句柄, 来自WinMain
		NULL        //发送 WM_CREATE 消息时的附加参数, 一般为零
	);
	
	if (!hWnd || INVALID_HANDLE_VALUE == hWnd) {
		return false;
	}

	UpdateWindow(hWnd);                //更新窗口
	ShowWindow(hWnd, SW_HIDE);        //隐藏窗口
	return true;
}

// 消息循环
void MsgLoop() {
	MSG msg = {0};
	BOOL bRet = TRUE;
	while ((bRet = GetMessageA(&msg, NULL, 0, 0)) != -1) {
		if (bRet == 0) {
			break;
		}
		TranslateMessage(&msg);  
		DispatchMessageA(&msg);
	}
}

WIN32窗体程序流程

程序入口:int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

网上查了一下发现一篇简单易懂的例子文章,转载过来了,做个记录,

内容来自:木木ing 的博客: Win32 SDK 编程开始, 创建窗口, 消息的处理, 消息循环

以下是正文:

Windows SDK 编程的一般步骤为:
    1. 注册窗口类, 使用到的结构 WNDCLASSEX, 函数 RegisterClassEx.
    2. 创建窗口, 函数 CreateWindowEx.
    3. 消息循环, 结构 MSG, 函数 GetMessage, TranslateMessage, DispatchMessage.
    4. 进入无限循环, 消息处理 :-)

下面是代码, 当然, 还有分析:

#include <windows.h>    //包含 Windows 相关的 API 函数

//这里就是所谓的消息处理函数了
//CALLBACK 说明当前函数是回调函数, 就是说明调用约定
//hwnd:窗口句柄, uMsg:收到的消息, wParam, lParam:与该消息有关的参数
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)    //消息选择
	{
		//这里我添加一个左键按下的消息
	case WM_LBUTTONDOWN:
		MessageBoxA(hwnd, "左键按下", "提示", MB_OK);
		return 0;

	case WM_DESTROY:    //当前窗口被销毁时
		PostQuitMessage(0);    //发出退出程序的消息
		return 0;    //如果处理了该消息, 就返回 0 来告知 Windows

	case WM_CLOSE:    //当用户点击窗口右上角的关闭按钮时
		DestroyWindow(hwnd);    //销毁窗口
		return 0;

	case WM_PAINT:    //当窗口需要重绘时
	{
		PAINTSTRUCT ps = { 0 };
		BeginPaint(hwnd, &ps);    //开始重绘

		EndPaint(hwnd, &ps);    //结束重绘
		return 0;
	}
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
	//对于我们不想处理的消息, 比如鼠标在窗口上移动时发出的消息
	//我们就原样传给默认的窗口消息处理函数处理, 不然应用程序会失去响应
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	
	//注意 Windows 程序应该使用 WinMain 入口函数了, 不再使用 main 函数
	//当然, 如果不创建窗口, 不使用窗口 也可以使用 main.
	WNDCLASSEXA wc = { 0 };            //窗口类结构, 为注册窗口类作准备
	wc.cbClsExtra = 0;                //附加的类信息, 没有, 设为0
	wc.cbSize = sizeof(wc);            //WNDCLASSEX结构的大小
	wc.cbWndExtra = 0;                //窗口额外内存, 没有, 设为0
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);            //窗口背景, 这里使用灰色背景
	wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCE(IDC_ARROW));        //应用程序使用的鼠标类型
	wc.hIcon = LoadIconA(NULL, MAKEINTRESOURCE(IDI_APPLICATION));    //光标类型
	wc.hIconSm = NULL;                    //应用程序程序的小光标, 不管, 设为 NULL
	wc.hInstance = hInstance;            //应用程序程序实例句柄, 由 WinMain 函数传递过来
	wc.lpfnWndProc = WndProc;            //这个很重要, 就是当前窗口的消息处理函数, 传递 WndProc 的地址
	wc.lpszClassName = "vbgk_class";    //创建类时使用的类名, 可以自定义
	wc.lpszMenuName = NULL;                //菜单, 没有, 就使用 NULL
	wc.style = CS_HREDRAW | CS_VREDRAW;    //类的风格, 垂直重绘, 水平重绘

	if (!RegisterClassExA(&wc))    //注册窗口类
	{
		MessageBoxA(NULL, "Register Class Failed!", NULL, MB_OK);
		return 1;
	}

	//创建窗口咯, 介绍一下 CreateWindowEx 函数的参数
	HWND hWnd = CreateWindowExA(
		0,                    //扩展窗口风格
		"vbgk_class",        //这里就是我们刚才创建的窗口类名
		"木木ing",
		WS_OVERLAPPEDWINDOW,//窗口风格
		CW_USEDEFAULT,        //初始化时的 X 坐标
		CW_USEDEFAULT,        //Y坐标
		320,        //窗口宽度, 我们这里设为 320
		240,        //窗口高度
		NULL,        //父窗口句柄, 没有
		NULL,        //菜单, 没有
		hInstance,    //实例句柄, 来自WinMain
		NULL        //发送 WM_CREATE 消息时的附加参数, 一般为零
	);
	if (!hWnd)
	{
		MessageBoxA(NULL, "CreateWindowEx Failed!", NULL, MB_OK);
		return 2;
	}

	UpdateWindow(hWnd);                //更新窗口
	ShowWindow(hWnd, nCmdShow);        //显示窗口

	MSG msg;
	BOOL bRet;

	//进入消息循环,
	//注意,消息循环一定要和上面的窗口创建在同一个线程
	// 否则GetMessage函数不会返回,会一直等到。
	while ((bRet = GetMessageA(&msg, NULL, 0, 0)) != -1)
	{
		if (bRet == 0)
		{
			break;
		}

		TranslateMessage(&msg);    //翻译消息

		//分发消息- 即会调用wc.lpfnWndProc = WndProc;
		DispatchMessageA(&msg);    
	}

	return msg.wParam;    //WinMain函数结束, 整个程序退出
}

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值