C++语言学习笔记13
Win32-游戏壳改进-消息映射表
//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标准单文档界面](https://cdn.jsdelivr.net/gh/mozro0327/mynotes/images/20220405154247.jpg)
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)封装了用于显示软件版本,版权等相关信息。
-
-
消息:
-
标准消息: 由系统发送。 以WM_开头除了(WM_COMMAND)的消息,比如WM_LBUTTONDOWN。
- 添加方法:在类视图下,选择某个类右键属性。
- 由系统发送 ( 子类 到 父类 查找消息映射表)
- 添加消息的处理–>类视图–>选择一个类–>右键属性–>选择一个消息添加
-
命令消息: 菜单、工具栏、快捷键。 WM_COMMAND。
-
添加方法:菜单/快捷键:资源->【右键】->【添加事件处理程序】->选择COMMAND 和要添加的类;
-
工具栏:需要手动添加。
-
由菜单,工具条,快捷键发送 (消息路由 : CView–>CDoc—>CDocTemplate—>CFrameWnd—>CWinApp)
-
添加消息的处理–>资源按钮–>右键添加事件处理–>选择一个消息和一个添加的类
-
-
自定义消息: ON_MESSAGE (确定了,查找调用者那个类)
- SendMessage:直接调用窗口对应的回调函数,立即处理,不会送入消息队列。即必须等待消息处理函数处理完,才能返回。
- PostMessage:将消息发送到系统的消息队列中,即发送完消息立即返回,不管对方是否接收到并处理完。
-
通知消息: 控件发出的消息时。 (子窗口 到 父窗口 查找消息映射表)
-
PS:窗口样式/绘图等不做赘述,自行查找资料:
资料链接: