不得不承认使用MFC编程很方便,但是熟练掌握、运用MFC需要,并且了解MFC的实现原理并不是一件容易的事,了解其实现机制将会给我们编程过程带来更大的自由度,现在我们就来窥其究竟,以解知其然而不知其所以然的疑惑。
简单的讲,MFC就是在windows编程的基础上,对Windows函数进行了重新组织、封装,以便程序员们使用更方便,所以我们就需要windows程序的实现机制。
每一个windows程序都有一个入口函数WinMain(),windows程序基本遵循以下几个步骤:
1.定义窗口类。
2.注册窗口类。
3.利用注册的窗口类产生窗口。
4.显示窗口。
5.进入消息循环。
以上四个过程都是在WinMain()函数内进行的,尤其需要注意一点的是,每一个窗口类都和一个窗口过程函数相关联,而窗口过程函数恰恰负责对各种消息的响应。
下面给出代码,代码对关键点进行了注释,与各位分享。
[cpp] view plain copy print ?
- #include <windows.h>
- LRESULT CALLBACK WndProc(HWND,UINT, WPARAM,LPARAM);
- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreinstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT("HelloWin");
- HWND hwnd;
- MSG msg;
- WNDCLASS wndclass;
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = WndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = szAppName;
- RegisterClass(&wndclass);
- hwnd = CreateWindow(szAppName,
- TEXT("The hello program"),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- hInstance,
- NULL);
- ShowWindow(hwnd, iCmdShow);
- UpdateWindow(hwnd);
- while(GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
- }
- LRESULT CALLBACK WndProc(HWND hwnd,UINT message, WPARAM wParam,LPARAM lParam)
- {
- HDC hdc;
- PAINTSTRUCT ps;
- RECT rect;
- switch(message)
- {
- case WM_CREATE:
- PlaySound( TEXT("HELLOWIN>WAV"), NULL, SND_FILENAME | SND_ASYNC );
- return 0;
- case WM_PAINT:
- hdc = BeginPaint(hwnd, &ps);
- GetClientRect(hwnd, &rect);
- DrawText(hdc, TEXT("Hello,Windows98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
- EndPaint(hwnd, &ps);
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //声明窗口过程函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreinstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass; //窗口类结构体变量
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc; //用窗口过程函数名初始化窗口类的成员变量,由此窗口类和窗口过程函数联系了起来
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName; //窗口类的名字
RegisterClass(&wndclass); //注册窗口类
hwnd = CreateWindow(szAppName, //利用窗口类的名字作为CreatWindow的参数来创建窗口,从而窗口和窗口类联系了起来
TEXT("The hello program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow); //显示窗口
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0)) //从消息循环队列中不断的取消息并交由窗口过程函数进行处理
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) //窗口过程函数的实现
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_CREATE:
PlaySound( TEXT("HELLOWIN>WAV"), NULL, SND_FILENAME | SND_ASYNC );
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("Hello,Windows98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam); //窗口过程函数没有处理的消息交给默认窗口函数
}
大家不必为弄清楚每个变量的具体含义,只需看明白关键变量的传递,以及整个窗口产生、消息处理的机制就可以了。
总而言之,就是以窗口类为中间桥梁,将产生的窗口和窗口过程函数关联了起来,而由操作系统负责提取消息,并调用窗口过程函数来完成消息响应。