孙鑫vc++ 第三课 MFC AppWizard的原理与MFC程序框架的剖析

讲述MFC AppWizard的原理与MFC程序框架的剖析

又抽时间看了第三课,感觉收获挺大,当然同时也证明我真得很菜,呵呵,下面的笔记都是没有整理的

1、在普通mpc程序中是没有winmain函数的,它由编译器在程序编译是再连接进来,可以在vc98/mfc中找到它的定义文件
2、_tWinMain 实际上是一个宏  #define -twinmain winmain
3、winmain是如何与mfc的各个类组织起来的呢,是如何联系的呢

   1 程序一开始并不是从winmain开始操作,但是是从winmain开始运行
     一开始就得到操作的是全局变量,为其分配内存空间
     CPoint pt -> CPoint() -> main() 全局对象,对象的构造函数,main函数
  
   2 一个程序有且仅有一个theapp,全局实例对象,它代表程序实例本身
     CTestApp theApp -> CWinApp() -> CTestApp() -> WinMain
     CWinApp::CWinApp(LPCTSTR lpszAppName){...}
     为什么父类构造函数有参数,子类实例没有对其显式调用呢,因为父类头文件定义处有默认值
     class CWinApp : public CWinThread
     { .......
       public:
           CWinApp(LPCTSTR lpszAppName = NULL);
       .......
     }

4、Afx****() 全局函数,可以在任何类内任何地方调用

6、CTestApp theApp -> CWinApp() -> CTestApp() -> _tWinMain() ->CTestApp::InitInstance()
   -> AfxEndDeferRegisterClass() -> CMainFrame::PreCreateWindow() -> CMainFrame::CreateEx()
   -> CMainFrame::PreCreateWindow() -> CTestApp::PreCreateWindow()改外观,完成创建窗口
   其中 AfxEndDeferRegisterClass() 设计窗口类,注册窗口,窗口过程选择的是一个缺省的窗口过程Wndcls.lpfuWndProc = DefWindowProc;
    CMainFrame::PreCreateWindow() 调用 CFrameWnd::PreCreateWindow() 再注册一次

7、CTestApp::InitInstance() 用CMainFrame指针 n_pMainWnd -> ShowWindow(SW_WHUW);
                                             n_pMainWnd -> UpdateWindow();  显示窗口

   CTestApp::InitInstance() 在父类的配合下,事实上完成了窗口的设计类,注册,创建,显示,随后执行点回到CWinThread调用InitInstance()处,下面就是消息循环CWinThread::Run()了

8、AfxWinMain()中有pThread -> Run();完成了消息循环
   CWinThread::Run() -> CWinThread::PumpMessage() -> ::GetMessage() ::TranSDateMessage()     ::DispatchMessage()
   CWinThread::Run() 中有一个循环for(;;){do{PumpMessage()}while;}
   此后,程序就在这个循环中反复执行了

9、程序、窗口创建过程大致终结:
   CTestApp theApp 创建程序实例,使this指针有所指
   CTestApp::CTestApp() 构造函数产生theApp全局对象,函数为空,调用CWnd::CWndAPP()完成程序初始化工作,同时将子类的指针保存起来,随后进入winmain()
   _tWinMain() 获取子类指针,利用该指针调用 CTestApp::InitInstance()
   CTestApp::InitInstance() 完成程序初始化工作,包括窗口注册,创建,显示,更新
   CWinThread::Run() 进入循环

10、CTestView其实也是一个窗口,可以看作是CMainFrame框架窗口的一个子窗口,覆盖在CMainFrame之上

11、CTestDoc : CDocument : CCmdTarget : CObject 不是一个窗口
    数据存储、加载由CDocument类完成
    数据显示、修改由CView类完成

12、CMainFrame、CDocument、CView 是如何组织在一起的呢
    在CTestApp::InitInstance()中定义了一个单文挡指针CSingleDocTempLate* pDocTemplate将这三个类有机组织在一起了,然后用AddDocTemplate(pDocTemplate);载入文档模板

13、CAbout : CDialog : CWnd : CCmdTarget : CObject 是一个窗口

14、::ShowWindow(), ::表示你调用的是一个全局函数
    想调用全局函数,sdk函数,都可以用::来引用
    类内成员函数名与sdk函数名一致,可以用::区分

15、窗口类对象和窗口的关系
    窗口对象和程序对象不是一回事,窗口销毁了程序不一定就销毁了,程序销毁了,窗口就一定销毁了,和程序析构函数有关
    窗口与程序相联系的纽带是窗口句柄 HWND hwnd;
    也就是说,窗口销毁了,CMainFrame、CView 仍然存活,其内成员函数依然可以调用
    CWnd 中就定义有一个HWND结构 m_hwnd,用来保存窗口句柄

16、mfc中结构体也是一个类

17、CMainFrame::OnCreate()中定义一个按钮
    {
       CButton btn;
       btn.Create("test",WS_CHTID,CRect(0,0,100,100),this,12345);
                  "显示文本",显示类型,显示对角,归属窗口,按钮标志
    }
    不显示的原因有两个:
    1 这里btn是一个局部变量,走出OnCreate()右大括号的时候,对象被销毁了,于是窗口也销毁了
      也就是前面说的,窗口与对象的存活关系
    2 少了窗口显示过程btn.ShowWindow(),也可以在Create()中增加显示类型标志WS_VISIBLE省略该步
    类内用this指的就是类对象的句柄了
  Button 控件其实就是一个窗口,因此在Create()类型时,可以指定窗口类型同时指定按钮类型
  单选按钮控件、复选按钮控件,其实就是button的不同按钮类型
  继承于CWnd的button类,与CWnd同样定义有一个HWND结构 m_hwnd,用来保存button窗口句柄,因此一般不用显式地定义另一个HWND结构来保存button窗口句柄,需要就调用就行了

18、CMainFrame的客户区包括了工具栏部分
  可以看到代码执行结果是按钮把工具栏给遮住了
    CView的客户区就是空白部分
  如果要在CView的客户区中显示,可以把变量定义、代码放入CView类中

19、窗口显示在哪里并不是因为代码放在哪个窗口类代码中,而是看Create()中指定的归属窗口是哪个
  如果把原显示在CView客户区的代码Create()指定的归属窗口句柄this改为GetParent(), 按钮就显示在CMainFrame客户区中了
  GetParent() api函数,获取父窗口句柄

20、每个窗口类内都定义并维护着一个指向该窗口的句柄

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页