VC++学习日志 MFC基础

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函数前使用::为了和类扩展函数区别 
  直接就可以调:)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值