对于程序员来说,如果要提高编程效率,一个好用的,功能强大的并且可以得心应手使用的编程工具往往会给我们程序员带来莫大的方便。其实对于现在的编程工具来说,使用哪一种工具都不是问题的关键,重要的是你能够使用到什么程度,毕竟现在的工具都是非常的强大,对于一般的编程任务来说还没有不能够胜任的工具,否则的话恐怕他就不可能在这个世界上存在哪怕是只有一个月的生命。但是根据个人所好以及周围的人的影响,我们都会去使用某一种或者几种工具。比较Visual Basic 、C++ Builder和Delphi等编程工具,用VC++编写Windows应用程序可以说是最富于挑战性和艰巨性。在本文中我无意去比较各种工具的好坏,仅就我自己学习Visual C++的MFC的体会和心得拿出来与大家一起分享和交流,也希望可以结识更多的志同道合的朋友。
就我个人的偏见,学习VC++就应该要学习他的类库MFC(Microsoft Foundation Classes)。也许有的人一听说MFC就有点望而生畏,这是可以理解的,毕竟Microsoft虽然给了我们一个强大而且非常复杂的类库,但是没有给我们带来学习他的好的方便之处。回想自己学习MFC时的无助和迷茫,以及所走过的弯路,现在想起来还心有余悸,虽然我现在也还是处于非常初级的初级入门阶段,但是还是很乐意把自己的心得和体会拿出来一起与大家分享。也希望得到大家的指点。
一、SDK应用程序结构
我学习MFC之路可是从windows编程开始的(可能这一开始就是弯路了^_^)。首先也请大家跟着我一起看一个SDK应用程序结构的Windows应用程序。当然也是经典的“Hello world!”了,编写的过程就不必罗嗦了,下面给出他的主要源代码(我使用向导生成的,但是为了阅读的方便经过了一点点的编辑):
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
………………………………
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
……………………
return TRUE;
}
//窗口函数WndProc(),回调函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
……………………
switch (message)
{
case WM_COMMAND:
………………
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
……
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
SDK之"Hello World"源程序
首先让我们看一下这个程序的结构,WinMain()是函数的入口点,该函数的主要任务是完成一些初始化的工作和维护了一个消息循环。他们的工作流程如下:入口(WinMain())---à MyRegisterClass()---->InitInstance ()-àwhile消息循环。函数由入口开始执行,之后调用 MyRegisterClass()注册窗口类,之后InitInstance ()生成并显示窗口,这样之后,就完成了一个窗口的初始化工作了(当然,在 MyRegisterClass(),InitInstance ()中都需要调用相应的API函数来具体的实现,不过我这里重点分析的是他的结构,所以不考虑他的具体实现细节),然后就是维护消息循环,至此,这个程序的基本结构就差不多建立了。以后程序的运作就靠个消息循环来推动了。
现在,再让我们看看那个消息循环的结构,在例子程序中,我们是要程序在窗口中输出一句"Hello World"。在主程序中我们似乎已经把应用程序的框架全部分析的滴水不漏了,但是没有看到要求程序输出"Hello World" 呀?这就是Windows消息的作用了,我们当然还记得刚刚我们说过主程序还维持了一个消息循环,不错,就是在这个循环里面大有文章。Window应用程序的特点就是消息驱动,当系统或者用户要求应用程序完成某一个任务的时候,所依靠的就是消息,系统会把用户的要求或者系统的要求放到一个消息结构中,然后发送给应用程序,再去处理。我们现在来看看应用程序是怎么来完成我们的任务的。在应用程序初始化完成之后,调用了一个显示窗口的API函数,所以系统知道了程序要显示窗口了,此时(注意,这里就是产生消息的时机),此时就会在消息队列中产生一个WM_PAINT消息,这样,应用程序的消息循环就可以捕捉到这个消息并且将它发送给窗口函数(注意,这个函数是由系统调用的),然后窗口函数就处理这个消息,我们就是在他处理这个消息的时候让他完成我们的任务的。从这个过程中我们可以看到,如果我们要与程序交互的话,需要做得仅仅就是选择适当的时机让系统产生消息了。现在,我们终于可以完全明白SDK的程序的运作过程了。
OK,一个SDK的应用程序的框架就这样被建立了,下面我们再来看看如何建立一个MFC的应用程序的框架,以及这两者之间的对应关系。(待续)