C++语言学习笔记13

Win32-游戏壳改进-消息映射表

image-20220405130442442

//WinMain.cpp

// window 应用程序,多字符集
#include <windows.h>
#include <windowsx.h>
#include "Gameapp.h"

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HINSTANCE hIns = 0;  //全局变量,程序实例句柄

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nShowCmd)
{
	//-----------------------------------------------------
	HWND hwnd = 0;
	MSG msg;       //  装消息的结构体
	WNDCLASSEX wndclass;
	//-----------------------------------------------------

	hIns = hInstance;
	LPCSTR lClassName = "yue";				//窗口类名CN
	extern int nx;							//窗口位置X
	extern int ny;							//窗口位置Y
	extern int nwidth;						//窗口宽度W
	extern int nheigh;						//窗口高度H
	extern CHAR* strTitle;					//窗口标题名T
	int pos_x = nx;
	if (pos_x < 0) {
		pos_x = 0;
	}
	int pos_y = ny;
	if (pos_y < 0) {
		pos_y = 0;
	}
	int nWidth = nwidth;
	if (nWidth <= 0) {
		nWidth = 500;
	}
	int nHeight = nheigh;
	if (nHeight <= 0) {
		nHeight = 500;
	}

	//----------------------创建窗口过程-----------------------------------
	//  1. 设计
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.cbSize = sizeof(wndclass);
	wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wndclass.hCursor = LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW));
	wndclass.hIcon = 0;
	wndclass.hIconSm = 0;
	wndclass.hInstance = hInstance;
	wndclass.lpfnWndProc = WindowProc;
	wndclass.lpszClassName = lClassName;
	wndclass.lpszMenuName = 0;
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	// 2.  注册
	if (RegisterClassEx(&wndclass) == FALSE)
	{
		MessageBox(0, "注册失败", "提示", MB_OK);
		return 0;
	}
	//  3.  创建
	hwnd = CreateWindow(lClassName, strTitle, WS_OVERLAPPEDWINDOW, pos_x, pos_y, nWidth, nHeight, 0, 0, hInstance, 0);
	if (hwnd == 0)
	{
		MessageBox(0, "创建失败", "提示", MB_OK);
		return 0;
	}
	//  4.  显示窗口
	ShowWindow(hwnd, SW_SHOW);
	//---------------------------创建窗口过程-----------------------------------------

	//----------------------------消息循环-------------------------------------------
	while (GetMessage(&msg, 0, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	//----------------------------消息循环-------------------------------------------

	return 0;
}

CGameApp* pGameAPP = Get_Object();	//获取子类
const MessageEntry* MsgMap = pGameAPP->GetMessageMap();	//获取子类的消息映射表的首地址

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	const MessageEntry* p = MsgMap;
	while (p && p->MessageID != 0) 
	{
		if (p->MessageID == uMsg) 
		{
			(pGameAPP->*(p->p_Fun))();
			break;
		}
		p++;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//GameApp.h

#pragma once
#include <windows.h>

class CGameApp;		//父类声明

typedef void(CGameApp::* P_FUN) ();

//定义一个消息映射结构
struct MessageEntry {
	int MessageID;	//消息ID
	P_FUN p_Fun;	//类成员函数指针
};

class CGameApp {
public:
	HINSTANCE m_hInstance;
	HWND m_hWnd;
public:
	CGameApp() {}
	virtual ~CGameApp() {}
public:
	void SetHandle(HINSTANCE hIns, HWND hWnd) {
		m_hInstance = hIns;
		m_hWnd = hWnd;
	}
public:
	//获取子类的消息映射表
	virtual const MessageEntry* GetMessageMap() = 0;
};

CGameApp* Get_Object();

#define GET_OBJECT(CHILD_CLASS)\
	CGameApp* Get_Object() {\
		return new CHILD_CLASS;\
	}

#define CLASS_CONFIG(PARAM_X,PARAM_Y,PARAM_WIDTH,PARAM_HEIGH,PARAM_TITLE)\
	int nx = PARAM_X;\
	int ny = PARAM_Y;\
	int nwidth = PARAM_WIDTH;\
	int nheigh = PARAM_HEIGH;\
	CHAR* strTitle = (CHAR*)PARAM_TITLE;
//AA.h

#pragma once
#include"GameApp.h"

#define WM_AAA (WM_USER+1)		
		//自定义消息需要从(WM_USER+1)开始,不要和系统的冲突

class CAA :public CGameApp
{
public:
	CAA(void);
	~CAA(void);
public:
	void OnCreate();
	void OnPaint();
	void OnAAA();
public:
	virtual const MessageEntry* GetMessageMap();
};
//AA.cpp

#include "AA.h"

GET_OBJECT(CAA)
CLASS_CONFIG(400, 0, 500, 500, "消息映射表")

CAA::CAA(void) { }
CAA::~CAA(void) { }

const MessageEntry* CAA::GetMessageMap() {

	static const MessageEntry MessageMap[] = {
		{WM_CREATE,(P_FUN)&CAA::OnCreate},	//typedef void(CGameApp::* P_FUN) ();
		{WM_PAINT,(P_FUN)&CAA::OnPaint},	//因此需要强转
		{WM_AAA,(P_FUN)&CAA::OnAAA},		

		{0,NULL}	//尾,结束标志
	};

	return MessageMap;
}

void CAA::OnCreate() {
	int a = 1;
}

void CAA::OnPaint() {
	int a = 2;
}

void CAA::OnAAA() {
	int a = 3;
}

MFC标准单文档界面图示

MFC标准单文档界面

MFC:微软基础类库

  • Microsoft Foundation Class(微软基础类库),微软公司实现的一个c++类库(class libraries),主要封装了大部分的windows API函数,并且包含一个应用程序框架,以减少应用程序开发人员工作量。

  • MFC引入面向对象的开发思维,而不是过程驱动的模式。

  • MFC是对win32的封装,使用win32编程方法,写了一个又一个类,让我们不用再重复大量劳动。

  • win32是编程者自己把消息和响应函数联系在一起。MFC是编程者采用微软为我们做好了消息映射表(MessageMap)机制,来处理消息。

  • 单文档模板

    • 1.应用程序类(CxxxApp)封装了 Windows 应用的初始化,实例初始化,运行以及终止的全过程,一个应用程序有且只有一个应用类的对象,它控制主框架窗口类、视图窗口类、文档类等。

    • 2.主框架窗口类(CMainFrame)应用程序的主框架窗口,应用程序中的所用其它窗口都直接或间接地为主窗口的子窗口。3.视图窗口类(CxxxView)显示文档数据,提供文档的可视化表示以图形化的方式显示出来,也为文档对象和用户之间提供了用以交互的可视接口,将用户输入转换为操作文档数据的命令。

    • 4.文档类(CxxxDoc)文档类实际上是一种数据结构,包含应用中所需的数据及处理这些数据的方法,提供与其存储的数据相关的服务。

    • 5."关于"对话框类(CAboutDlg)封装了用于显示软件版本,版权等相关信息。

      MFC 一些类的封装成员

  • 消息:

    • 标准消息: 由系统发送。 以WM_开头除了(WM_COMMAND)的消息,比如WM_LBUTTONDOWN。

      • 添加方法:在类视图下,选择某个类右键属性。
      • 由系统发送 ( 子类 到 父类 查找消息映射表)
      • 添加消息的处理–>类视图–>选择一个类–>右键属性–>选择一个消息添加
    • 命令消息: 菜单、工具栏、快捷键。 WM_COMMAND。

      • 添加方法:菜单/快捷键:资源->【右键】->【添加事件处理程序】->选择COMMAND 和要添加的类;

      • 工具栏:需要手动添加。

      • 由菜单,工具条,快捷键发送 (消息路由 : CView–>CDoc—>CDocTemplate—>CFrameWnd—>CWinApp)

      • 添加消息的处理–>资源按钮–>右键添加事件处理–>选择一个消息和一个添加的类

    • 自定义消息: ON_MESSAGE (确定了,查找调用者那个类)

      • SendMessage:直接调用窗口对应的回调函数,立即处理,不会送入消息队列。即必须等待消息处理函数处理完,才能返回。
      • PostMessage:将消息发送到系统的消息队列中,即发送完消息立即返回,不管对方是否接收到并处理完。
    • 通知消息: 控件发出的消息时。 (子窗口 到 父窗口 查找消息映射表)

PS:窗口样式/绘图等不做赘述,自行查找资料:

资料链接:

1.MFC类库详解

2.MFC主要类层次

3.Win32Api2

4.WIn32-API程序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

97Marcus

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

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

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

打赏作者

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

抵扣说明:

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

余额充值