c/c++ win32 学习之二 消息循环

c/c++ win32 学习之二 消息循环(学习笔记)

win32学习内容总结

  1. window窗口开发基础
  2. 消息循环
  3. 重要消息
  4. 菜单
  5. GDI画图
  6. 其他控件[暂无]
  7. 文件操作
  8. 内存映射
  9. 进程线程
  10. 线程调度
  11. 网络编程

消息

消息:
MSG 结构体
1.hWnd 消息属于哪个窗口
2.消息
3.lParam
4.wParam

消息处理过程:

事件 -> 封装成消息 -> 存入消息队列 -> 消息响应

消息循环:

  1. 消息产生后 进入消息队列

  2. 应用程序 从消息队列中获取消息

  3. 获取到消息后 翻译消息

  4. 翻译好之后 派发消息 发送给每个窗口

  5. 窗口接收到调用消息处理函数 WndProc

消息队列的分类:

  1. 系统消息队列: os message queue
    操作系统维护的队列
    例如:鼠标消息 键盘消息

  2. 应用程序消息队列:
    应用程序来维护 存放当前应用程序的消息 WM_PAINT 绘图

消息的分类:

  1. 系统消息:
    操作系统已经定义好了。 WM_ 0-0x3FF 1024
    1111111111

  2. 用户消息(自定义消息): WM_USER 0x400 - 0x7FF

  3. 队列消息:
    存储和取出都要经过消息队列
    WM_PAINT

  4. 非队列消息:
    不需要存储 直接处理
    WM_CREATE : 窗口被创建后,显示前发送的消息
    WM_SIZE : 窗口大小被改变的时候产生并发送的消息

PeekMessage 和 GetMessage

  1. PeekMessage:非阻塞方式接受消息
    检查消息队列,如果有消息就看最后一个参数:
    最后一个参数为False 0: 直接返回1
    最后一个参数为true : 从消息队列中删除消息然后返回1
    如果消息队列中没有消息
    直接返回0

  2. GetMessage:从消息队列中获取一个消息存放到MSG结构体中
    从消息队列中获取消息,如果当前程序消息队列中有消息。
    把消息存入MSG,删除当前程序消息队列里的消息。返回非0。直到遇到WM_QUIT消息才返回0.
    如果当前程序消息队列中没有消息。
    去系统消息队列里看有没有消息
    有消息:
    把系统消息队列中的消息放入当前程序消息队列。
    没有消息:
    检查窗口是否需要重新绘制
    需要重新绘制:
    发送WM_PAINT消息
    不需要重新绘制:
    查看是否有定时器
    有定时器:
    处理定时器消息
    没有定时器:
    优化资源,处理内存,然后继续等待

使用资源:

  1. 创建资源文件:鼠标右键->添加资源
    resourece.h ***.rc
  2. 导入资源
    鼠标右键->添加资源->导入->选择资源文件->确定
  3. 获取资源id
    从资源视图得知id
  4. 添加头文件

使用命令行窗口:

  1. 得到命令行窗口使用权限
    AllocConsole
  2. 得到命令行窗口句柄
    GetStdHandle
  3. 使用命令行窗口:
    WriteConsole
#include 
#include 
#include "resource.h"

HINSTANCE g_hInstance;
HANDLE g_hConsole;	//命令行窗口句柄
HCURSOR g_hCursor1, g_hCursor2;

void OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hParInstance,
	LPSTR lpCmdLine,
	int nCmd
	)
{
	g_hInstance = hInstance;
	//1.注册窗口类
	WNDCLASSEXW wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.lpszClassName = L"firstWindow";
	wc.lpfnWndProc = WndProc;
	wc.hbrBackground = NULL;
	wc.hCursor = NULL;//LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_CURSOR1));
	wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));		//图标
	wc.hIconSm = NULL;		//小图标
	wc.hInstance = hInstance;
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClassExW(&wc);

	//2.创建窗口
	HWND hWnd = CreateWindowExW(
		NULL,
		wc.lpszClassName,
		L"我的第一个窗口",
		WS_OVERLAPPEDWINDOW,
		500, 500,
		600, 600,
		NULL,
		NULL,
		wc.hInstance,
		NULL
		);

	if (!hWnd)
	{
		MessageBoxExW(NULL, L"未创建窗口", L"提示", MB_OK, 0);
	}
	//3.显示窗口
	ShowWindow(hWnd, nCmd);
	//4.刷新窗口
	UpdateWindow(hWnd);

	AllocConsole();
	g_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

	g_hCursor1 = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1));
	g_hCursor2 = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR2));
	//5.消息循环
	MSG msg;
	BOOL bRet;
	while (true)
	{
		if (PeekMessageW(&msg, nullptr, 0, 0, false))
		{
			if ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0)//检测到窗口退出,返回0,不退出,返回非0
			{
				if (bRet == -1)
				{
					//出现错误
				}
				else
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
			}
			else
			{
				break;
			}
		}
	}

	return 0;
}

//5.消息处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_COMMAND:
		break;
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此处添加使用 hdc 的任何绘图代码...
		EndPaint(hWnd, &ps);
		break;
	}
	case WM_MOUSEMOVE:
	{
		OnMouseMove(hWnd, wParam, lParam);
		break;
	}
	case WM_DESTROY:
	{
		PostQuitMessage(0);
		break;
	}
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return NULL;
}

void OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	int y = HIWORD(lParam);
	int x = LOWORD(lParam);

	WCHAR buf[256] = { 0 };
	swprintf(buf, L"(%d, %d)\n", x, y);
	WriteConsole(g_hConsole, buf, wcslen(buf), NULL, NULL);

	RECT rect;
	GetWindowRect(hWnd, &rect);
	int width = rect.right - rect.left;
	int height = rect.bottom - rect.top;

	if (x < width / 2)
	{
		SetClassLongPtrW(hWnd, GCL_HCURSOR, (LONG_PTR)g_hCursor1);
	}
	else
	{
		SetClassLongPtrW(hWnd, GCL_HCURSOR, (LONG_PTR)g_hCursor2);
	}
}

你可能感兴趣的:(window桌面开发)