CWnd类封装了所有与窗口操作相关的操作

WinMain函数,它是所有程序的入口函数,在MFC中找不到,但是在链接的时候编译器将他链接到我们的程序中,那么在程序中如何找到呢?
首先搜索(z):\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc(当然是你的anzhaung目录)
下面搜索文件中包含WinMain的文件,会找到appmodul.cpp,然后双击打开,可以使用VS打开,会找到WinMain函数。断点调试可以发现程序确实链接了:
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 __in LPTSTR lpCmdLine, int nCmdShow)
{
 // call shared/exported WinMain
 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
注意上面的_tWinMain是一个宏,展开还是wWinMain

CMainFrame类名称是不会变得。其他根据工程名加表示特征后缀。在MFC中所遇的类都以C开头。

打开CTestApp类,发现它是从CWinApp派生来的
,CWinApp表示一个应用程序类。在类试图中选中CTestApp类,在下面选择它的构造函数,如下:
CTestApp::CTestApp()
{
 // TODO: 在此处添加构造代码,
 // 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 CMFC2App 对象

CTestApp theApp;


可以设置断点,调试,发现程序会首先执行这里,然后在执行WinMain函数的断点处。因为设置了一个CTestApp的全局变量:theApp,可以设置断点调试,程序会首先执行CTestApp theApp;,然后进入构造函数,然后才进入WinMain函数。这点很重要!全局对象和变量都是在入口函数之前分配内存空间。
那么在这里CTestApp theApp;为什么要定义这样一个全局对象呢?在一个MFC程序中只能有一个从CWinApp派生来的类,也只能有一个该类的对象。它表示了应用程序本身。基于MFC的应用程序中,使用WinApp对象来表示一个唯一的应用程序。正因为定义了一个全局对象,所以在程序执行之前就要进行初始化CTestApp类的构造函数,要构造子类的构造函数,会激发父类的构造函数,所以导致了CWinApp的构造函数。因此把派生类和基类关联起来了。
同样,我们依然在刚才的路径下搜索“CWinApp”,会找到appcore.cpp,双击打开。
可以找到CWinApp的构造函数,
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
...............
}
注意:这里的构造函数包含一个参数,可是我们在子类中的定义并没有参数,原因我们可以将鼠标放到CWinApp上右键,转到定义,会发现:
CWinApp(LPCTSTR lpszAppName = NULL);
这样一个缺省值为NULL的定义。所以子类可以不用传递这个参数。

接下来看下完整的CWinApp构造函数:
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
 if (lpszAppName != NULL)
  m_pszAppName = _tcsdup(lpszAppName);
 else
  m_pszAppName = NULL;

 // initialize CWinThread state
 AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
 ENSURE(pModuleState);
 AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
 ENSURE(pThreadState);
 ASSERT(AfxGetThread() == NULL);
 pThreadState->m_pCurrentWinThread = this;
 ASSERT(AfxGetThread() == this);
 m_hThread = ::GetCurrentThread();
 m_nThreadID = ::GetCurrentThreadId();

 // initialize CWinApp state
 ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
 pModuleState->m_pCurrentWinApp = this;
 ASSERT(AfxGetApp() == this);

 // in non-running state until WinMain
 m_hInstance = NULL;
 m_hLangResourceDLL = NULL;
 m_pszHelpFilePath = NULL;
 m_pszProfileName = NULL;
 m_pszRegistryKey = NULL;
 m_pszExeName = NULL;
 m_pRecentFileList = NULL;
 m_pDocManager = NULL;
 m_atomApp = m_atomSystemTopic = NULL;
 m_lpCmdLine = NULL;
 m_pCmdInfo = NULL;

 // initialize wait cursor state
 m_nWaitCursorCount = 0;
 m_hcurWaitCursorRestore = NULL;

 // initialize current printer state
 m_hDevMode = NULL;
 m_hDevNames = NULL;
 m_nNumPreviewPages = 0;     // not specified (defaults to 1)

 // initialize DAO state
 m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

 // other initialization
 m_bHelpMode = FALSE;
 m_eHelpType = afxWinHelp;
 m_nSafetyPoolSize = 512;        // default size
}

来看这句:pThreadState->m_pCurrentWinThread = this;将this的值附给pThreadState指针的成员变量m_pCurrentWinThread,这里的this指针到底指向的是哪一个对像呢?是我们的CTestApp对像还是CWinApp的都像呢?它指向的是派生类CTestApp的对象。也就是刚才的theApp。

在看WinMain函数,实际上它是用了AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);函数来完成WinMain函数。Afx前缀是属于应用程序框架类的函数,Application FrameWork x(x这里没有什么意义).
依然是搜索这个函数AfxWinMain,找到winmain.cpp,打开看到:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 __in LPTSTR lpCmdLine, int nCmdShow)
{
 ...............
};
因为C++不是完全面向对象的语言,所以要定义一些全局函数,来组织类之间的关系,这些全局函数我们叫做应用程序框架类的一些函数,以Afx打头,在每一个类中都可以调用,因为是全局的。
CWinApp* pApp = AfxGetApp();
这里AfxGetApp();会获得一个指向CWinApp的指针,实际上这里获得的指针,就是刚才我们在CWinApp构造函数中附给的这个指针,也就是说这里pApp指针指向的是派生类CTestApp的theApp指针。

步骤:
设计窗口类
注册窗口类
创建窗口
显示窗口
更新窗口
消息循环
消息处理函数

首先效用了InitApplication(),主要是MFC内部管理所调用的函数。
if (pApp != NULL && !pApp->InitApplication())
  goto InitFailure;
  
  
  
  
  
  
做个划线的例子:
HDC hdc;   //生成一个HDC的对象
hdc=::GetDC(m_hWnd);  //这里注意:this是c++的关键字,表示这个类的当前实例,m_hwnd是一个成员变量,好象是定义在CWnd里面吧,他存放的是类的实例的句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,Null); //将点移动到具体的位置,API
LindTo(hdc,point.x,point.y); //划线,API
::ReleaseDC(m_hWnd,hdc); //释放HDC


关于m_hWnd的疑惑:
this是c++的关键字,表示这个类的当前实例,m_hwnd是一个成员变量,好象是定义在CWnd里面吧,他存放的是类的实例的句柄.、本窗口的句柄
m_hWnd 定义于 CWnd 类,其他类都是从它那里派生来的。



很简单常识,一些函数前的两个冒号::是什么意思,有什么用?
作用域标识符.
使用外部命名空间的函数或变量.当外部与模块内部函数或变量重名时,前面加::可以继续使用外部的函数或变量,当然,它们必须是可见的。
表明该函数为全局的而不是当前类的(当当前类中没有该函数时,不加   ::   也是一样的)

一般是系统API函数
这是调用系统的api函数    
  呵呵~~  
  不像vb那样还要声明  
  呵呵~~   
系统API函数前使用::为了和类扩展函数区别 
  直接就可以调:)

Posted on 2006-07-23 21:24  李通通  阅读(1378)  评论(0编辑  收藏  举报