学习笔记:第3课 MFC框架介绍

 

MFC库的类表记录在Hierarchy Chart

 

得到父类的指针用GetParent()

 

CWND封装了一些关于窗口操作的类,CWinAPP这个类是应用程序的类。

 

◇在安装目录下的VC98/MFC/SRC,这个目录下面就是MFC的原代码,WinMain函数的所在地方就是APPMODUL.CPP

 

AfxWinMain函数:以Afx开头的函数属于应用程序框架的函数,在这个函数里面,有相应获取的代码。其中AfxGetApp是一个全局的函数,也一方面说明了C++不是完全面向对象的。

 

CTheApp theApp;->CTestApp ::CTestApp(){}->_tWinMain(){}启动调用顺序。

CwindThread* pThread = AfxGetThread();

//pThreadpApp等价的,它完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。

CwinApp* pApp = AfxGetApp();

//初始化子类的函数,在父类中他是个虚函数

pThread-InitInstance();

pThread-Run();

AfxGetApp()获取一个指向CWinApp派生类对象(theApp)的指针。
pApp
调用三个函数,这三个函数完成设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环、消息处理函数。

 

      注册窗口:AfxEndDeferRegisterClass,在运行的时候注册,其实单文档的程序是比较例外的,一般都是在创建窗口之前注册窗口。

CframeWnd::PreCreateWindow(){

//再这里调用AfxEndDeferRegisterClass

}

      然后是创建窗口:创建窗口时的函数调用关系:
 Create() ->  CreateEx() -> PreCreateWindow() -> AfxEndDeferRegisterClass()
 Create()
函数由谁调用?是由LoadFrame()调用。

BOOL CWnd::CreateEx(...){
 ...
 if (!PreCreateWindow(cs))//
虚函数,如果子类有调用子类的。
 {
  PostNcDestroy();
  return FALSE;
 }
 ...
 HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
  cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

 ...
}

      HWND CreateWindowEx(
  DWORD dwExStyle,     
  LPCTSTR lpClassName, 
  LPCTSTR lpWindowName,
  DWORD dwStyle,       
  int x,               
  int y,               
  int nWidth,          
  int nHeight,         
  HWND hWndParent,     
  HMENU hMenu,         
  HINSTANCE hInstance, 
  LPVOID lpParam       
);

typedef struct tagCREATESTRUCT { // cs
        LPVOID    lpCreateParams;
        HINSTANCE hInstance;
        HMENU     hMenu;
        HWND      hwndParent;
    int       cy;
    int       cx;
    int       y;
    int       x;
     LONG      style;
     LPCTSTR   lpszName;
     LPCTSTR   lpszClass;
     DWORD     dwExStyle;
} CREATESTRUCT;

      CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前通过可PreCreateWindow(cs)修改CREATESTRUCT cs结构体成员来修改所要的窗口外观。

显示和更新窗口:
CTestApp
类,TestApp.cpp

// m_pMainWnd保存了框架窗口对象的指针
m_pMainWnd->ShowWindow(SW_SHOW);//
显示窗口,m_pMainWnd指向框架窗口
m_pMainWnd->UpdateWindow();//
更新窗口

 

      消息循环:由pThread->Run();完成。
int AFXAPI AfxWinMain()
{ ...
 if (!pThread->InitInstance()){...}
 //
完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
 nReturnCode = pThread->Run();
 //
继承基类Run()方法,调用CWinThread::Run()来完成消息循环
 ...
}

 

      CWinThread::Run()方法路径:MFC|SRC|THRDCORE.CPP
int CWinThread::Run()
{ ...
  // phase2: pump messages while available
  do//
消息循环
  {
   // pump message, but quit on WM_QUIT
   if (!PumpMessage())//
取消息并处理
    return ExitInstance();
   ...
  } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
 ...
}
然后始终都是在这个消息循环的内部进行了

 

      流程:全局对象的初始化,然后进入到WinMain函数,然后获取子类的指针,利用子类的指针我们去调用一个虚拟的函数(InitInstance),其中里面要做注册窗口,创建窗口,创建之前也要设置窗口的各个属性,然后启动窗口

 

      BOOL CWinThread::PumpMessage()
{
 ...
 if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//
取消息
 {...}
 ...
 // process this message
 if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
 {
  ::TranslateMessage(&m_msgCur);//
进行消息(如键盘消息)转换
  ::DispatchMessage(&m_msgCur);//
分派消息到窗口的回调函数处理(实际上分派的消息经过消息映射,交由消息响应函数进行处理。)
 }
 return TRUE;
}

 

      文档类,视类,框架类的有机结合:
CTestAppCTestApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。CsingleDocTemplate就是单文档的类
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
 IDR_MAINFRAME,
 RUNTIME_CLASS(CTEDoc),
 RUNTIME_CLASS(CMainFrame),       // main SDI frame window
 RUNTIME_CLASS(CTEView));
AddDocTemplate(pDocTemplate);//
增加到模板

 

      仿真窗口类的代码清单:

class  CWnd{
 public:
 BOOL CreateEx(
  DWORD dwExstyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x ,
  int y
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMWNU  hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam );
 BOOL ShowWindow(int nCmdShow);
 BOOL UpdateWindow();
 public:
  HWND m_hwnd; //m_hwnd
在构造函数中将其初始化为NULL
};


BOOL  CWnd::CreateEx(
  DWORD dwExstyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x ,
  int y
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMWNU  hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam );
{
 m_hWnd = ::CreateWindowEx(dwExstyle, lpClassName, dwStyle,
  x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
 if(m_hWnd != NULL )
  return TRUE;
 else
  return FALSE;
}//END CreateEx()

BOOL CWnd::ShowWindow (int nCmdShow)
{
 ::ShowWindow (m_hWnd,nCmdShow); //
在函数前面加上的含义表示使用的是全局函数,
 //
以前使用全局函数的时候可以直接写函数名就行了,现在加上“ :: ”是为了防止与 windows API 函数混淆
}

BOOL CWnd :: UpdateWindow()
{

//::代表的是全局的函数
 ::UpdateWindow ( m_hWnd);
}

nt WINAPI WinMain(
 HINSTANCE hInstance,
 HINSTANCE hPrevInstance,
 LPSTR  lpCmdLine,
 int  nCmdshow)
{

//设计窗口类
 WNDCLASS wndcls;
 wndcls.cbClsExtra = 0;
 wndcls.cbWndExtra = 0;
 .................

//注册窗口类
 RegisterClass (& wndcls);
 CWnd wnd; //wnd
并不等价于窗口,当窗口销毁之后,C++对象还可以存在,他是连接窗口的纽带
 wnd.CreateEx(dwExstyle, lpClassName, dwStyle,
  x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
 wnd.ShowWindow(SW_SHOWNUORMAL); //
注意这里不再需要传递hwnd句柄,因为wnd里面已经定义了句柄 m_hwnd
 wnd.UpdateWindow();
 
 
}//endof WinMain() 

 

      Button控件的产生:窗口创建之后创建Button,其中RECT是矩形区域,可以设定Button的大小。Cbutton在执行西构以后,会将Button的控件资源进行回收。MFC的类维护了窗口,一般的MFC类在析构函数中都会销毁窗口。所以,当MFC的类生命周期到的时候,窗口的生命周期就到了。但是,反过来,当窗口的生命周期到的时候,相应的类的生命周期就不一定了,类还是可以使用的。

      CButton m_btn;

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

。。。。

    m_btn.Create("维新",WS_CHILD | WS_VISIBLE | BS_AUTO3STATE,

        CRect(0,0,100,100),/*GetParent(),*/this,123);

    //m_btn.ShowWindow(SW_SHOWNORMAL);

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的横打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值