关于Win32程序的基本原理

来源:互联网 发布:淘宝评价发图片 编辑:程序博客网 时间:2024/05/17 07:00

为了了解MFC,必须先了解Win32。因为Win32程序的来龙去脉和消息动向等等这些重要的动作在MFC应用程序中被Application Framework 封装起来了,所以对于程序员来说,必须先弄清楚Win32才能很好的理解MFC

 

上图所示是Win32应用程序与操作系统之间的关系。

 

详细的代码框架如下:

Generic.h文件中

 

BOOL InitApplication(HANDLE);                                                                     //初始化程序

BOOL InitInstance(HANDLE, int);                                                                    //初始化进程实例

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);        //窗口函数

LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);                    //关于

 

Genric.c文件中

 

#i nclude <windows.h>               //每个Windows程序都要载入此头文件

#i nclude “resource.h”               //内涵各个resource IDs

#i nclude <generic.h>                //本程序的头文件

 

//……全局变量的声明

HINSTANCE _hInst;

HWND _hwnd;

Char _szAppName[] = “Generic”; // 程序名称

Char _szTitle[] = “Generic Sample Application” ;//窗口标题

/////////////////////////////////////////////////////////////////////

//WinMain 程序进入点

/////////////////////////////////////////////////////////////////////

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

UNREFERENCED_PARAMETER(lpCmdLine); //避免编译的时候警告

If(! hPrevInstance)

              If (! InitApplication(hInstance))

                     Return (FALSE);

If(! InitInstance(hInstance, nCmdShow))

              Return FALSE;

While(GetMessage(&msg, NULL, 0 , 0))

{

              TranslateMessage(&msg);           //转换键盘消息

              DispatchMessage(&msg);            //分派消息

}

return msg.wParam;                  //传回PostQuitMessage的参数

}

 

/////////////////////////////////////////////////////////////////////

//InitApplication 注册窗口类

/////////////////////////////////////////////////////////////////////

BOOL InitApplication(HINSTANCE hInstance)

{

WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.hInstance = hInstance;

wc.lpfnWndProc = (WNDPROC)WndProc;   //窗口函数

wc.lpszClassName = _szAppName;               //窗口类名称

 

return (RegisterClass(&wc));

}

 

/////////////////////////////////////////////////////////////////////

//InitInstance 产生窗口

/////////////////////////////////////////////////////////////////////


 

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

_hInst = hInstance;     //存储为全局变量,方便使用

_hWnd = CreateWindow(

                                                 _szAppName,             //窗口类名称

                                                 _szTitle,                      //窗口标题(caption

                                                 …

);

if(! _hWnd)

              return FALSE;

ShowWindow(_hWnd, nCmdShow);             //显示窗口

UpdateWindow(_hWnd);                      //送出WM_PAINT

Return TRUE;

}

 

/////////////////////////////////////////////////////////////////////

//WndProc 窗口函数

/////////////////////////////////////////////////////////////////////

LPRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

int wmId, wmEvent;

switch (message)

{

case WM_COMMAND:

              wmId = LOWORD(wParam);

              wmEvent = HIWORD(wParam);

              switch (wmId)

{

              case IDM_ABOUT:

                     ……break;

              case IDM_EXIT:

                     ……break;

              default:

                     return (DefWindowProc(hWnd, message, wParam, lParam));

}

break;

case WM_DESTROY:

PostQuitMessage(0);

Break;

Default:

              return (DefWindowProc(hWnd, message, wParam, lParam));

}

return 0;

}

其他函数省略。

基本上代码中的Win32程序和示意图是一致的。

1WinMain

其中WinMain函数是Windows 程序的进入点,在Win32CALLBACK被定义为_stdcall,是一种函数调用习惯,关系到参数进入到堆栈的次序,以及处理堆栈的责任归属。WinMain的四个参数由操作系统传递进来。

 

2RegisterClass

一开始,Windows程序必须做些初始化工作,为的是产生应用程序的工作舞台——窗口。但在窗口产生之前,必须设定好窗口的属性(WNDCLASS对象),包括窗口的外貌(风格)和行为(窗口函数)等。RegisterClass是一个API函数,通过它就可以设定窗口的属性,这一步操作被称为注册窗口类。

 

3CreateWindow

在窗口属性设定好了以后,就可以用API函数CreateWindow创建窗口。注意,CreateWindow只产生窗口,并不显示窗口。

 

4ShowWindowUpdateWindow

在创建了窗口以后,利用ShowWindow将它显示在屏幕上。又,我们希望线传送一个WM_PAINT给窗口,以驱动窗口的绘图操作,所以调用UpdateWindow

 

5GetMessage

消息循环中的GetMessageWindows3.x 非强制性多任务的关键。如果消息队列上没有属于程序自己的消息,他就把机会让给其他程序。通过程序之间彼此协调让步的方式达到多任务能力。应用程序需要靠消息推动,需要通过GetMessage抓消息。

 

6TranslateMessageDispatchMessage

TranslateMessage是为了将键盘消息转化,DispatchMessage会将消息传给窗口函数去处理。在消息发生之际,操作系统已根据当时状态,为该消息标明所属窗口,而窗口所属的窗口类又已经明白标示了窗口函数,所以DispatchMessage自由脉络可寻。图中可以看出,DispatchMessage经过USER模块的协助,才能把消息交到窗口函数手中。

 

7)窗口函数WndProc

窗口函数通常先判断消息的种类,以决定处理方式。由于它是被Windows系统所调用(我们并没有在应用程序的任何地方显式调用此函数,DispatchMessagUSER模块的协助下,将消息送到窗口函数,然后由操作系统调用窗口函数)的,所以这是一种call back函数,意思是指在应用程序中被Windows系统调用的函数。这些函数虽然是我们自己设计,但是永远不会也不该被我们自己程序来调用,而是为Windows系统准备的。之所以这样,原因是除了我们自己程序需要调用窗口函数,很多时候操作系统也要调用我们的窗口函数,窗口函数设计为CallBack形式,才能开放出一个接口给操作系统调用。

 

8DefWindowProc

这是Windows内部默认的消息处理函数。

 
原创粉丝点击