在从Win32如何一步步到MFC(以消息映射为例子)(一)中,我写的主要是WIN32程序,但是在MFC下,他封装的实际上是一个个的C++的类,所以,这一篇中,我会将上一篇的Win程序模仿MFC,将其封装到C++类中。
首先贴上上一篇的代码:
#include<windows.h>
#include<stdio.h>
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnChar(HWND,UINT,WPARAM,LPARAM);
LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);
LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);
LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);
//因为业务需求增加WM_CREATE消息
LRESULT OnCreate(HWND, UINT, WPARAM, LPARAM);
typedef LRESULT (*FXN)(HWND, UINT, WPARAM, LPARAM);
#define dim(x) sizeof(x)/sizeof(x[0])
struct tagMESSAGEMAP
{
UINT uMsg;
FXN pFun;
};
tagMESSAGEMAP MessageMaps[]=
{
WM_CHAR, OnChar,
WM_LBUTTONDOWN, OnLButtonDown,
WM_PAINT, OnPaint,
WM_DESTROY, OnDestroy,
WM_CREATE, OnCreate
};
int WINAPI WinMain(
HINSTANCE hInstance, // 当前实力句柄
HINSTANCE hPrevInstance, // 前一实例句柄
LPSTR lpCmdLine, //命令行参数
int nShowCmd) //窗口显示方式
{
//定义窗口
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WinProc; // 指定消息处理函数
wc.lpszClassName = "gzw";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
//注册窗口
RegisterClass(&wc);
HWND hWnd;
hWnd = CreateWindow(
wc.lpszClassName, //窗口类的名称
"一个简单的win32程序",//窗口标题
WS_OVERLAPPEDWINDOW, //窗口风格
0,0, //窗口位置的x,y坐标
600,400, //窗口的宽度和高度
NULL, //父窗口的句柄
NULL, //菜单句柄
hInstance, //应用程序实力句柄
NULL //窗口创建数据指针
);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
for (int i = 0; i < dim(MessageMaps); i++)
{
if (uMsg == MessageMaps[i].uMsg)
{
FXN func = MessageMaps[i].pFun;
return func(hwnd,uMsg,wParam,lParam);
}
}
return DefWindowProc(hwnd, uMsg, wParam,lParam);
}
LRESULT OnChar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char szChar[20];
sprintf(szChar, "你按下了%c键", (char)wParam);
MessageBox(hwnd, szChar, "WM_CHAR", 0);
return 0;
}
LRESULT OnLButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
hdc = GetDC(hwnd);
TextOut(hdc, 0, 50, "左键按下", strlen("左键按下"));
ReleaseDC(hwnd, hdc);
return 0;
}
LRESULT OnPaint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd, &ps);
TextOut(hDC, 0, 0, "Hello World!", strlen("Hello World!"));
EndPaint(hwnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MessageBox(NULL,"我是新加的","aaa",MB_OK);
return 0;
}
接下来,我定义一个类,我给他取名叫做CMyWnd.顾名思意,这是一个关于窗口的类,然后我爸上一段代码中关于窗口相关的函数放到一个个对应的成员函数中去,如下:
首先是定义一个类:
在头文件中:
源文件中:
#include<windows.h>
#include<stdio.h>
#include "MiniMFC.h"
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnChar(HWND, UINT, WPARAM, LPARAM);
LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);
LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);
LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);
//因为业务需求增加WM_CREATE消息
LRESULT OnCreate(HWND, UINT, WPARAM, LPARAM);
typedef LRESULT(*FXN)(HWND, UINT, WPARAM, LPARAM);
#define dim(x) sizeof(x)/sizeof(x[0])
struct tagMESSAGEMAP
{
UINT uMsg;
FXN pFun;
};
tagMESSAGEMAP MessageMaps[] =
{
WM_CHAR, OnChar,
WM_LBUTTONDOWN, OnLButtonDown,
WM_PAINT, OnPaint,
WM_DESTROY, OnDestroy,
WM_CREATE, OnCreate
};
CMyWnd::CMyWnd()
{
}
CMyWnd::~CMyWnd()
{
}
BOOL CMyWnd::Create()
{
//定义窗口
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = NULL;
wc.lpfnWndProc = WinProc; // 指定消息处理函数
wc.lpszClassName = "gzw";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
//注册窗口
RegisterClass(&wc);
m_hWnd = CreateWindow(
wc.lpszClassName, //窗口类的名称
"一个简单的win32程序",//窗口标题
WS_OVERLAPPEDWINDOW, //窗口风格
0, 0, //窗口位置的x,y坐标
600, 400, //窗口的宽度和高度
NULL, //父窗口的句柄
NULL, //菜单句柄
NULL, //应用程序实力句柄
NULL //窗口创建数据指针
);
return m_hWnd != NULL;
}
BOOL CMyWnd::ShowWindow()
{
return ::ShowWindow(m_hWnd, SW_SHOWNORMAL);
}
BOOL CMyWnd::UpdateWindow()
{
return ::UpdateWindow(m_hWnd);
}
int WINAPI WinMain(
HINSTANCE hInstance, // 当前实力句柄
HINSTANCE hPrevInstance, // 前一实例句柄
LPSTR lpCmdLine, //命令行参数
int nShowCmd) //窗口显示方式
{
CMyWnd* pMainWnd = new CMyWnd;
pMainWnd->Create();
pMainWnd->ShowWindow();
pMainWnd->UpdateWindow();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
for (int i = 0; i < dim(MessageMaps); i++)
{
if (uMsg == MessageMaps[i].uMsg)
{
FXN func = MessageMaps[i].pFun;
return func(hwnd, uMsg, wParam, lParam);
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT OnChar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char szChar[20];
sprintf(szChar, "你按下了%c键", (char)wParam);
MessageBox(hwnd, szChar, "WM_CHAR", 0);
return 0;
}
LRESULT OnLButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
hdc = GetDC(hwnd);
TextOut(hdc, 0, 50, "左键按下", strlen("左键按下"));
ReleaseDC(hwnd, hdc);
return 0;
}
LRESULT OnPaint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd, &ps);
TextOut(hDC, 0, 0, "Hello World!", strlen("Hello World!"));
EndPaint(hwnd, &ps);
return 0;
}
LRESULT OnDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MessageBox(NULL, "我是新加的", "aaa", MB_OK);
return 0;
}
在WinMain中,我定义一个与窗口相关的类,然后创建窗口,显示窗口、更新窗口。
为了模仿MFC,我接下来在定义一个类,叫做CMyApp,故名思意,他是应用程序类:
在这个类中,我定义InitInstane,里面放与窗口相关的函数,在定义一个Run成员函数,里面放消息相应相关函数。如下:
在WinMain中,我就就可以写:
现在是不是很像了,回到上面InstInstance成员函数中,我把CMyWnd定义在了成员函数中,但是在MFC中,通常会将它定义为应用程序类的成员变量,所以稍微变一下,如下:
编译输出同样不变,接下来我把InitInstance和Run放到构造函数中去,如下:
那么在WinMain中,我就只需要写:
现在就和MFC基本上一样了是不是,在MFC中,应用程序是全局,那我就把他放到全局就可以了,如下:
是不是就一模一样了,编译输出:
点确认:
在鼠标左键按下:
是不是一摸一样了现在。这个就是MFC初始化过程的创建过程的由来。
接下来,还没完,还有最核心的部分,请继续看从Win32如何一步步到MFC(以消息映射为例子)(三)。