MFC程序和Win32程序的关系

来源:互联网 发布:网络推广部门管理制度 编辑:程序博客网 时间:2024/04/27 20:23

MFC程序和Win32程序的关系

 

以下是一个完整的Win32程序,该程序实现的功能是创建一个窗口,并在该窗口的响应键盘和鼠标信息:

  #include <windows.h>
  #include <stdio.h>

  LRESULT CALLBACK WinSunProc(
  
HWND hwnd,      // handle to window
  
UINT uMsg,      // message identifier
  
WPARAM wParam, // first message parameter
  
LPARAM lParam   // second message parameter
  );

  int WINAPI WinMain(
  
HINSTANCE hInstance,      // handle to current instance
  
HINSTANCE hPrevInstance, // handle to previous instance
  
LPSTR lpCmdLine,          // command line
  
int nCmdShow              // show state
  
)
  
{
    
WNDCLASS wndcls;
    
wndcls.cbClsExtra=0;
    
wndcls.cbWndExtra=0;
    
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
    
wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
    
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
    
wndcls.hInstance=hInstance;
    
wndcls.lpfnWndProc=WinSunProc;
    
wndcls.lpszClassName="Weixin2003";
    
wndcls.lpszMenuName=NULL;
    
wndcls.style=CS_HREDRAW | CS_VREDRAW;
     RegisterClass(&wndcls);

     HWND hwnd;

     hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,0,0,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 WinSunProc(
  
HWND hwnd,      // handle to window
  
UINT uMsg,      // message identifier
  
WPARAM wParam, // first message parameter
  
LPARAM lParam   // second message parameter
  
)
  
{
    
switch(uMsg)
    
{
    
case WM_CHAR:
      
char szChar[20];
      
sprintf(szChar,"char is %d",wParam);
      
MessageBox(hwnd,szChar,"weixin",0);
      
break;
    
case WM_LBUTTONDOWN:
      
MessageBox(hwnd,"mouse clicked","weixin",0);
      
HDC hdc;
      
hdc=GetDC(hwnd);
       TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训
"));
      
ReleaseDC(hwnd,hdc);
      
break;
    
case WM_PAINT:
      
HDC hDC;
      
PAINTSTRUCT ps;
      
hDC=BeginPaint(hwnd,&ps);
       TextOut(hDC,0,0,"维新培训",strlen("维新培训
"));
      
EndPaint(hwnd,&ps);
      
break;
    
case WM_CLOSE:
       if(IDYES==MessageBox(hwnd,"是否真的结束?
","weixin",MB_YESNO))
      
{
        
   DestroyWindow(hwnd);
      
}
      
break;
    
case WM_DESTROY:
      
PostQuitMessage(0);
      
break;
    
default:
      
return DefWindowProc(hwnd,uMsg,wParam,lParam);
    
}
    
return 0;
  }

  程序实现的步骤为:

  1WinMain函数的定义

    WinMain函数是Windows程序的入口点,与DOS程序的入口点函数main的作用相同;
  2、创建一个窗口

    要创建一个完整的窗口,需要经过下面几个步骤:  

    、设计一个窗口类

    、注册窗口类

    、创建窗口

    、显示及更新窗口
  3、进行消息循环

  4、编写窗口过程函数

 

2008-12-25 12:02

MFC把具有相当固定行为的WinMain内部操作封装在CWinApp中,把有着相当固定行为的WndProc内部操作封装在CFrameWnd中。

几乎可以说CWinApp用来取代WinMainSDK程序中的地位,CFrameWnd取代SDK程序中窗口函数的地位。

首先MFC程序需要下面函数库:

1 Windows C Runtime函数库:LIBC.LIB / MSVCRT.LIB / MSVCRTD.LIB

2 DLL Import函数库:GDI32.LIB / USER32.LIB / KERNEL32.LIB

3 MFC函数库(AFX函数库):MFC42.LIB / MFC42D.LIB……

同时,MFC程序需要下面头文件:

1 Stdafx.h:预编译头文件,其内只是载入其他的MFC头文件。

2 Afxwin.h:每个MFC程序都必须载入它,因为它以及它所载入的文件声明了所有的MFC类,此文件含有Afx.h,后者又载入Afxvver_.h,后者又载入Afxv_w32.h,后者又载入windows.hSDK程序必须要的头文件)。

3 Afxext.h:使用工具栏、状态栏的程序必须载入这个文件。

4 Afxdlgs.h:使用通用型对话框的MFC程序需要此文件,其内部载入COMMDLG.H

5 Afxcmn.h:使用Win9x新增的通用型控件的MFC程序必须载入此文件。

6 Afxcoll.h:使用Collections Classes的程序要此文件

7 Afxres.hMFC程序的RC文件必须载入此文件。

[解释]预编译头文件:所谓预编译头文件是指将 .H 文件第一次编译后的结果保存起来,第2次编译的时候就可以直接从磁盘上取出来用。

一个具体而微的MFC程序和Win32之间的关系:

MFC程序也是Windows程序,所以它应该有一个WinMain,但在程序进入点之前,还有一个全局对象theApp,这是所谓的应用程序对象。当操作系统将程序加载并激活的时候,这个全局对象获得配置,其构造函数会先执行,必WinMain更早。

CmyWinApp theApp

theApp是程序的应用程序对象,每一个MFC程序有且只有这么一个,当执行程序时,这个全局对象产生,于是构造函数执行起来。一般来说CwinApp的构造函数被执行。CwinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

theApp配置完成后,WinMain登场,我们并没有撰写WinMain程序代码,这是MFC早已准备好并由连接器直接加到应用程序代码中的。加入如下代码:

extern “C” int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

其中AfxWinMain定义如下:

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

int nReturnCode = -1;

CwinApp *pApp = AfxGetApp();

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pApp->InitInstance();

nReturnCode = pApp->Run();

AfxWinTerm();

Return nReturnCode;

}

关于AfxWinMain的四个主要操作说明:

1 AfxWinInit——AFX内部初始化操作。它是继CwinApp构造函数之后的第一个操作。在这函数内对theApp的某些成员初始化,而且还调用了AfxInitThread函数,把消息队列尽量加大到96

2 CwinApp::InitApplicationInitApplicationCwinApp的一个虚函数,一般情况下不需要改写它。在此函数中的操作都是MFC为了内部管理而作的(DocManager相关)。

3 CmyWinApp::InitInstance。每个MFC程序都应该改写CwinApp::InitInstance这个函数,因为它在CwinApp中只是一个空函数。在这个函数里面,代码如下:

BOOL CmyWinApp::InitInstance()

{

m_pMainWnd = new CmyFrameWnd();

m_pMainWnd->ShowWindow(m_nCmdShow);

m_pMainWnd->UpdateWindow();

return TRUE;

}

其中一开始就new了一个CmyFrameWnd对象,准备用作主框窗口的C++对象,引发了CmyFrameWnd的构造函数:

CmyFrameWnd::CmyFrameWnd

{

Create(NULL,”hello MFC”, WS_OVERLAPPEDWINDOW, rectDefault, NULL,”MainMenu”);

}

CreateCframeWnd的成员函数,CmyFrameWnd中并没有改写它。由于Create的第一个参数指定WNDCLASS窗口类名字,现在为NULL表示以MFC内建的窗口类产生一个标准的外框窗口。

CframeWnd::Create(…)函数中,调用了CreateEx函数,由于CframeWnd中并没有改写CreateEx函数,所以实际上调用的是CWnd::CreateEx。在CreateEx这个函数中,调用了PreCreateWindowCreateWindowEx这两个函数。由于CframeWnd中改写了PreCreateWindow,所以这里调用的是CframeWnd::PreCreateWindow。在PreCreateWindow里面,调用了AfxDeferRegisterClass宏,该宏的定义如下:

#define AfxDeferRegisterClass(fClass) / ((afxRegisteredClasses & fClass) TRUE : AfxEndDeferRegisterClass(fclass))

如果变量afxRegisteredClasses的值显示系统已经注册了fclass这种窗口类,MFC就啥也不做,否则就调用AfxEndDeferRegisterClass(fclass),准备注册之。AfxEndDeferRegisterClass函数中终于声明了WNDCLASS对象,并且调用了相应的MFC窗口类,并通过AfxRegisterClass(WNDCLASS*)RegisterWithIcon这两个函数来注册窗口类。MFC内置6种窗口类。RegisterWithIcon中用到AfxRegisterClass函数,而AfxRegisterClass函数里面又调用了RegisterClass函数来注册窗口类。不同类的PreCreateWindow成员函数都是在窗口产生之前一刻被调用,准备用来注册窗口类的,如果我们指定窗口类为NULL,那么就是用系统默认类(MFC内置)

当创建完窗口以后,程序流程又回到CmyWinApp::InitInstance,于是调用ShowWindow函数令窗口显示出来,并调用UpdateWindow函数令程序送出WM_PAINT消息。

4 CwinApp::Run,由于在CmyWinApp中没有改写Run(大部分情况下都不用改写),所以调用的是CwinApp::Run。在该函数中又调用了CwinThread::RunCwinThread::Run中调用了PumpMesage()函数,而PumpMessage函数中依次调用GetMessage / TranslateMessag / DispatchMessage函数。程序通过调用DispatchMessage函数,把消息丢给窗口函数。

5) 程序根据消息映射表来判断消息,从而做出相应的消息处理。

至此,MFC程序和Win32程序的关系总算弄明白。

MFC把具有相当固定行为的WinMain内部操作封装在CWinApp中,把有着相当固定行为的WndProc内部操作封装在CFrameWnd中。

几乎可以说CWinApp用来取代WinMainSDK程序中的地位,CFrameWnd取代SDK程序中窗口函数的地位。

首先MFC程序需要下面函数库:

1 Windows C Runtime函数库:LIBC.LIB / MSVCRT.LIB / MSVCRTD.LIB

2 DLL Import函数库:GDI32.LIB / USER32.LIB / KERNEL32.LIB

3 MFC函数库(AFX函数库):MFC42.LIB / MFC42D.LIB……

同时,MFC程序需要下面头文件:

1 Stdafx.h:预编译头文件,其内只是载入其他的MFC头文件。

2 Afxwin.h:每个MFC程序都必须载入它,因为它以及它所载入的文件声明了所有的MFC类,此文件含有Afx.h,后者又载入Afxvver_.h,后者又载入Afxv_w32.h,后者又载入windows.hSDK程序必须要的头文件)。

3 Afxext.h:使用工具栏、状态栏的程序必须载入这个文件。

4 Afxdlgs.h:使用通用型对话框的MFC程序需要此文件,其内部载入COMMDLG.H

5 Afxcmn.h:使用Win9x新增的通用型控件的MFC程序必须载入此文件。

6 Afxcoll.h:使用Collections Classes的程序要此文件

7 Afxres.hMFC程序的RC文件必须载入此文件。

[解释]预编译头文件:所谓预编译头文件是指将 .H 文件第一次编译后的结果保存起来,第2次编译的时候就可以直接从磁盘上取出来用。

一个具体而微的MFC程序和Win32之间的关系:

MFC程序也是Windows程序,所以它应该有一个WinMain,但在程序进入点之前,还有一个全局对象theApp,这是所谓的应用程序对象。当操作系统将程序加载并激活的时候,这个全局对象获得配置,其构造函数会先执行,必WinMain更早。

CmyWinApp theApp

theApp是程序的应用程序对象,每一个MFC程序有且只有这么一个,当执行程序时,这个全局对象产生,于是构造函数执行起来。一般来说CwinApp的构造函数被执行。CwinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

theApp配置完成后,WinMain登场,我们并没有撰写WinMain程序代码,这是MFC早已准备好并由连接器直接加到应用程序代码中的。加入如下代码:

extern “C” int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

其中AfxWinMain定义如下:

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

int nReturnCode = -1;

CwinApp *pApp = AfxGetApp();

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pApp->InitInstance();

nReturnCode = pApp->Run();

AfxWinTerm();

Return nReturnCode;

}

关于AfxWinMain的四个主要操作说明:

1 AfxWinInit——AFX内部初始化操作。它是继CwinApp构造函数之后的第一个操作。在这函数内对theApp的某些成员初始化,而且还调用了AfxInitThread函数,把消息队列尽量加大到96

2 CwinApp::InitApplicationInitApplicationCwinApp的一个虚函数,一般情况下不需要改写它。在此函数中的操作都是MFC为了内部管理而作的(DocManager相关)。

3 CmyWinApp::InitInstance。每个MFC程序都应该改写CwinApp::InitInstance这个函数,因为它在CwinApp中只是一个空函数。在这个函数里面,代码如下:

BOOL CmyWinApp::InitInstance()

{

m_pMainWnd = new CmyFrameWnd();

m_pMainWnd->ShowWindow(m_nCmdShow);

m_pMainWnd->UpdateWindow();

return TRUE;

}

其中一开始就new了一个CmyFrameWnd对象,准备用作主框窗口的C++对象,引发了CmyFrameWnd的构造函数:

CmyFrameWnd::CmyFrameWnd

{

Create(NULL,”hello MFC”, WS_OVERLAPPEDWINDOW, rectDefault, NULL,”MainMenu”);

}

CreateCframeWnd的成员函数,CmyFrameWnd中并没有改写它。由于Create的第一个参数指定WNDCLASS窗口类名字,现在为NULL表示以MFC内建的窗口类产生一个标准的外框窗口。

CframeWnd::Create(…)函数中,调用了CreateEx函数,由于CframeWnd中并没有改写CreateEx函数,所以实际上调用的是CWnd::CreateEx。在CreateEx这个函数中,调用了PreCreateWindowCreateWindowEx这两个函数。由于CframeWnd中改写了PreCreateWindow,所以这里调用的是CframeWnd::PreCreateWindow。在PreCreateWindow里面,调用了AfxDeferRegisterClass宏,该宏的定义如下:

#define AfxDeferRegisterClass(fClass) / ((afxRegisteredClasses & fClass) TRUE : AfxEndDeferRegisterClass(fclass))

如果变量afxRegisteredClasses的值显示系统已经注册了fclass这种窗口类,MFC就啥也不做,否则就调用AfxEndDeferRegisterClass(fclass),准备注册之。AfxEndDeferRegisterClass函数中终于声明了WNDCLASS对象,并且调用了相应的MFC窗口类,并通过AfxRegisterClass(WNDCLASS*)RegisterWithIcon这两个函数来注册窗口类。MFC内置6种窗口类。RegisterWithIcon中用到AfxRegisterClass函数,而AfxRegisterClass函数里面又调用了RegisterClass函数来注册窗口类。不同类的PreCreateWindow成员函数都是在窗口产生之前一刻被调用,准备用来注册窗口类的,如果我们指定窗口类为NULL,那么就是用系统默认类(MFC内置)

当创建完窗口以后,程序流程又回到CmyWinApp::InitInstance,于是调用ShowWindow函数令窗口显示出来,并调用UpdateWindow函数令程序送出WM_PAINT消息。

4 CwinApp::Run,由于在CmyWinApp中没有改写Run(大部分情况下都不用改写),所以调用的是CwinApp::Run。在该函数中又调用了CwinThread::RunCwinThread::Run中调用了PumpMesage()函数,而PumpMessage函数中依次调用GetMessage / TranslateMessag / DispatchMessage函数。程序通过调用DispatchMessage函数,把消息丢给窗口函数。

5) 程序根据消息映射表来判断消息,从而做出相应的消息处理。

至此,MFC程序和Win32程序的关系总算弄明白。

MFC把具有相当固定行为的WinMain内部操作封装在CWinApp中,把有着相当固定行为的WndProc内部操作封装在CFrameWnd中。

几乎可以说CWinApp用来取代WinMainSDK程序中的地位,CFrameWnd取代SDK程序中窗口函数的地位。

首先MFC程序需要下面函数库:

1 Windows C Runtime函数库:LIBC.LIB / MSVCRT.LIB / MSVCRTD.LIB

2 DLL Import函数库:GDI32.LIB / USER32.LIB / KERNEL32.LIB

3 MFC函数库(AFX函数库):MFC42.LIB / MFC42D.LIB……

同时,MFC程序需要下面头文件:

1 Stdafx.h:预编译头文件,其内只是载入其他的MFC头文件。

2 Afxwin.h:每个MFC程序都必须载入它,因为它以及它所载入的文件声明了所有的MFC类,此文件含有Afx.h,后者又载入Afxvver_.h,后者又载入Afxv_w32.h,后者又载入windows.hSDK程序必须要的头文件)。

3 Afxext.h:使用工具栏、状态栏的程序必须载入这个文件。

4 Afxdlgs.h:使用通用型对话框的MFC程序需要此文件,其内部载入COMMDLG.H

5 Afxcmn.h:使用Win9x新增的通用型控件的MFC程序必须载入此文件。

6 Afxcoll.h:使用Collections Classes的程序要此文件

7 Afxres.hMFC程序的RC文件必须载入此文件。

[解释]预编译头文件:所谓预编译头文件是指将 .H 文件第一次编译后的结果保存起来,第2次编译的时候就可以直接从磁盘上取出来用。

一个具体而微的MFC程序和Win32之间的关系:

MFC程序也是Windows程序,所以它应该有一个WinMain,但在程序进入点之前,还有一个全局对象theApp,这是所谓的应用程序对象。当操作系统将程序加载并激活的时候,这个全局对象获得配置,其构造函数会先执行,必WinMain更早。

CmyWinApp theApp

theApp是程序的应用程序对象,每一个MFC程序有且只有这么一个,当执行程序时,这个全局对象产生,于是构造函数执行起来。一般来说CwinApp的构造函数被执行。CwinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

theApp配置完成后,WinMain登场,我们并没有撰写WinMain程序代码,这是MFC早已准备好并由连接器直接加到应用程序代码中的。加入如下代码:

extern “C” int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

其中AfxWinMain定义如下:

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

int nReturnCode = -1;

CwinApp *pApp = AfxGetApp();

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pApp->InitInstance();

nReturnCode = pApp->Run();

AfxWinTerm();

Return nReturnCode;

}

关于AfxWinMain的四个主要操作说明:

1 AfxWinInit——AFX内部初始化操作。它是继CwinApp构造函数之后的第一个操作。在这函数内对theApp的某些成员初始化,而且还调用了AfxInitThread函数,把消息队列尽量加大到96

2 CwinApp::InitApplicationInitApplicationCwinApp的一个虚函数,一般情况下不需要改写它。在此函数中的操作都是MFC为了内部管理而作的(DocManager相关)。

3 CmyWinApp::InitInstance。每个MFC程序都应该改写CwinApp::InitInstance这个函数,因为它在CwinApp中只是一个空函数。在这个函数里面,代码如下:

BOOL CmyWinApp::InitInstance()

{

m_pMainWnd = new CmyFrameWnd();

m_pMainWnd->ShowWindow(m_nCmdShow);

m_pMainWnd->UpdateWindow();

return TRUE;

}

其中一开始就new了一个CmyFrameWnd对象,准备用作主框窗口的C++对象,引发了CmyFrameWnd的构造函数:

CmyFrameWnd::CmyFrameWnd

{

Create(NULL,”hello MFC”, WS_OVERLAPPEDWINDOW, rectDefault, NULL,”MainMenu”);

}

CreateCframeWnd的成员函数,CmyFrameWnd中并没有改写它。由于Create的第一个参数指定WNDCLASS窗口类名字,现在为NULL表示以MFC内建的窗口类产生一个标准的外框窗口。

CframeWnd::Create(…)函数中,调用了CreateEx函数,由于CframeWnd中并没有改写CreateEx函数,所以实际上调用的是CWnd::CreateEx。在CreateEx这个函数中,调用了PreCreateWindowCreateWindowEx这两个函数。由于CframeWnd中改写了PreCreateWindow,所以这里调用的是CframeWnd::PreCreateWindow。在PreCreateWindow里面,调用了AfxDeferRegisterClass宏,该宏的定义如下:

#define AfxDeferRegisterClass(fClass) / ((afxRegisteredClasses & fClass) TRUE : AfxEndDeferRegisterClass(fclass))

如果变量afxRegisteredClasses的值显示系统已经注册了fclass这种窗口类,MFC就啥也不做,否则就调用AfxEndDeferRegisterClass(fclass),准备注册之。AfxEndDeferRegisterClass函数中终于声明了WNDCLASS对象,并且调用了相应的MFC窗口类,并通过AfxRegisterClass(WNDCLASS*)RegisterWithIcon这两个函数来注册窗口类。MFC内置6种窗口类。RegisterWithIcon中用到AfxRegisterClass函数,而AfxRegisterClass函数里面又调用了RegisterClass函数来注册窗口类。不同类的PreCreateWindow成员函数都是在窗口产生之前一刻被调用,准备用来注册窗口类的,如果我们指定窗口类为NULL,那么就是用系统默认类(MFC内置)

当创建完窗口以后,程序流程又回到CmyWinApp::InitInstance,于是调用ShowWindow函数令窗口显示出来,并调用UpdateWindow函数令程序送出WM_PAINT消息。

4 CwinApp::Run,由于在CmyWinApp中没有改写Run(大部分情况下都不用改写),所以调用的是CwinApp::Run。在该函数中又调用了CwinThread::RunCwinThread::Run中调用了PumpMesage()函数,而PumpMessage函数中依次调用GetMessage / TranslateMessag / DispatchMessage函数。程序通过调用DispatchMessage函数,把消息丢给窗口函数。

5) 程序根据消息映射表来判断消息,从而做出相应的消息处理。

 

 

原创粉丝点击