一起学MFC(二) Windows应用程序编程模型

    MFC从它的本身来说,它的大部分的功能仍是通过调用最基本的WIN32 API来实现的。它利用OOP的技术,把Windows编程复杂细节封装,隐藏。即使你对Windows不太了解,也能通过MFC进行程序设计。但是,不理解Windows的运行机制,你最终仍然不能更深入地从MFC的内部了解MFC,不能更好的发挥MFC的性能。所以,有必要了解Windows应用程序与运行机制。这也是Windows的编程基础。

     Windows运行机制是: 以消息为基础,事件驱动的模型。 如下图

    

      一起学MFC(二) Windows应用程序编程模型_第1张图片

 

    从上图可能看到,每个Windows应用程序都由两个主要部分:主应用程序自身与至少一个能进行消息处理的窗口过程。

    Windows系统位于硬件与应用程序之间,时刻监视着系统的软硬件产生的“输入”,每当有某个应用程序所感兴趣的事件发生时,Windows都会以消息的形式发送到应用程序的消息队列中。应用程序从消息队列中取出消息并处理消息。这与DOS下的编程有很大的不同。当在DOS下编写程序时,你或多或少会凌驾于系统之上。DOS是你的奴隶,但在Windows编程过程中,Window与应用程序之间变得更加的协作。Windows和应用程序进入一个控制循环彼此相互传递消息。从某个角度上来看,Window应用程序是由一系列的消息处理代码构成。

   

    为了更具体的说明上面过程,可看下图:

   

    一起学MFC(二) Windows应用程序编程模型_第2张图片

 

     

     Window通过USER Module来监视着系统硬件与软件产生的“输入”,这一切都有Window的底层驱动来完成。由硬件产生的“输入”信息,会被放在系统队列(system queue)中,而由软件产生的“输入”信息,会被放在应用程序队列(application queue)中。对应用程序来说,它不会太区分是来至系统队列中的消息,还是应用程序队列中的消息。反正应用程序通过GetMessage API函数来取出消息并处理消息。处理消息的过程,通常是由窗口过程(Window Procedure) 来完成,对于不需要处理的消息,通通扔给DefWindowProc API函数由系统给于处理。

      从上面还可以发现,有些消息是不经常消息队列直接通过SendMessage API函数发给应用程序的。也就是说,不是每个消息都会进行队列的。

 

      下面来看一个由C/SDK写的Windows 程序,来具体理解这个处理过程。

 

       #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 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 ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters 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, Windows 98!"), -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) ; }

 

 

      1. 应用程序首先必须有一个WinMain函数,它是整个程序的入口点,应用程序就是通过它从Windows获得运行所必要的信息。这些必要信息包括应用程序的当前实例句柄,应用程序的上一个运行实例句柄,所有的命令行参数以及如何显示等。

      int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)

 

     2. 应用程序至少要注册一个窗口类作为主窗口。

         if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } 

   

     3. 应用程序建立消息循环。如果说消息Windows应用程序的血液,那么消息循环就是它的心脏。

       

         while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; }

       

     4. 应用程序必须提供消息处理函数。这个窗口过程(window procedeure)至少要处理WM_DESTROY消息(除非应用程序永远不结束)

         case WM_DESTROY: PostQuitMessage (0) ; return 0 ;

 

引《深入浅出》关于Win32的生死

      

   一起学MFC(二) Windows应用程序编程模型_第3张图片

 

       

       

 

你可能感兴趣的:(MFC)