剖析MFC窗口类框架应用程序

关于向导

工程---文件---MFC AppWizarad.exe:取工程名和存放目录

AppWizard 辅助生成代码工具,可以创建三类应用程序:单文档、多文档、对话框

比如生成Test单文档应用程序,帮助生成五各类:

CAboutDlgCMainFrameCTestAppCTestDoc、CTestView   

蓝色表示继承CWND


关于winmain函数

所在路径:VC98--MFC--SRC---APPMODUL.cpp

extern "C" int WINAPI

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

_tWinMain 是宏   #define  _tWinMian  WinMain  goto defination 可以看到

 

CTestAppCWinApp继承,表示应用程序类,每个应用程序都有这个类,该类定义一个全局对象CTestApp theApp 入口程序执行前首先为全局对象分配空间,初始化工作由CWinApp类完成  该类在APPCORE实现

pModuleState->m_pCurrentWinApp = this;  //子类继承,便是子类对象地址


CTestApp::CTestApp()

CWinApp::CWinApp(LPCTSTR lpszAppName)

CTestApp()没有显式调用CWinAppLPCTSTR lpszAppName)

原因:CWinApp定义已经有缺省值CWinApp(LPCTSTR lpszAppName = NULL);


Winmain调用了AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)

它在WinMain.cpp文件中

CWinThread* pThread = AfxGetThread();  //亦是this指针

CWinApp* pApp = AfxGetApp();  //获得this指针,即子类CTestApp ::theApp对象地址

 

if (pApp != NULL && !pApp->InitApplication())  //内部初始化管理

goto InitFailure;

 

// Perform specific initializations

if (!pThread->InitInstance())//是虚函数,所以调用还是CTestAppInitialInstance()

设置断点可以验证

nReturnCode = pThread->Run();//完成消息循环

 

设计窗口类:AfxEndDefeRegisterClass()  wincore.cpp

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

fToRegister &= ~pModuleState->m_fRegisteredClasses;

if (fToRegister == 0)

return TRUE;

 

LONG fRegisteredClasses = 0;

 

// common initialization

WNDCLASS wndcls;

memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults

wndcls.lpfnWndProc = DefWindowProc;

wndcls.hInstance = AfxGetInstanceHandle();

wndcls.hCursor = afxData.hcurArrow;

 

    //内部已经预先定义一些窗口类,根据不同的选择创建串口

// work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

if (fToRegister & AFX_WND_REG)

{

// Child windows - no brush, no icon, safest default class styles

wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.lpszClassName = _afxWnd;

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WND_REG;

}

if (fToRegister & AFX_WNDOLECONTROL_REG)

{

// OLE Control windows - use parent DC for speed

wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.lpszClassName = _afxWndOleControl;

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WNDOLECONTROL_REG;

}

if (fToRegister & AFX_WNDCONTROLBAR_REG)

{

// Control bar windows

wndcls.style = 0;   // control bars don't handle double click

wndcls.lpszClassName = _afxWndControlBar;

wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;

}

if (fToRegister & AFX_WNDMDIFRAME_REG)

{

// MDI Frame window (also used for splitter window)

wndcls.style = CS_DBLCLKS;

wndcls.hbrBackground = NULL;

if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))

fRegisteredClasses |= AFX_WNDMDIFRAME_REG;

}

if (fToRegister & AFX_WNDFRAMEORVIEW_REG)

{

// SDI Frame or MDI Child windows or views - normal colors

wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))

fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;

}

....

注册先于CFramWnd::PreCreateWindow(),涉及单文档管理,PreCreateWindow根据是否注册,如果没有注册直接返回,有的话可以其修改类型

 

设计和注册框架窗口CFramWnd和子窗口CVIEW

::都是由Cwnd派生出来的

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)  

{

if( !CFrameWnd::PreCreateWindow(cs) )   //调用框架基类的PreCreateWindow()

return FALSE;

// TODO: Modify the Window class or styles here by modifying

//  the CREATESTRUCT cs

 

return TRUE;

}

 

此函数在winfrm.cpp,创建窗口之前可以修改窗口类属性和类型

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

if (cs.lpszClass == NULL)

{

       //检查是否注册窗口,如果没有就注册一个AFX_WNDFRAMEORVIEW_REG

        //绿色标识的函数实际上还是在AFXIMPL.H定义的宏,实际调用还是//AfxEndDeferRegisterClass()

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background

}

 

if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)

cs.style |= FWS_PREFIXTITLE;

 

if (afxData.bWin4)

cs.dwExStyle |= WS_EX_CLIENTEDGE;

 

return TRUE;

}

创建窗口

CWnd::Create()调用CreateEx(),它又调用重载的CreateEx(),这个函数又调用了PreCreateWindow(CS),这样修改的窗口CS在执行::CreateWindowEx(CS.XXX,...)将会生效

---------------------------------

CTestApp::InitInstance()调用ProcessShellCommand()将完成窗口的创建,调用以上类成员函数

同时有

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();

完成窗口的显示和更新

 

对于CView类,它是框架类的子窗口,是覆盖在主框架之上的,它一般用来数据显示和修改,句柄是m_hwnd

对于CDocument文档类,它继承CCmdTarget派生出来的,基类是CObject,它一般用来存储和加载数据

对于CAboutDlg,它由CWnd派生出来,属于窗口

消息循环

CWinThread::run()

内部有这段代码

do

{

// pump message, but quit on WM_QUIT

if (!PumpMessage())     //完成装换和路由

return ExitInstance();

 

// reset "no idle" state after pumping "normal" message

if (IsIdleMessage(&m_msgCur))

{

bIdle = TRUE;

lIdleCount = 0;

}

 

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));

 

BOOL CWinThread::PumpMessage()

 

调用::GetMessage()

if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))

{

::TranslateMessage(&m_msgCur);

::DispatchMessage(&m_msgCur);

}//完成转换和路由,os路由的消息不全是交给默认消息处理函数处理,采用了消息映射机制找到对应函数处理

 

关于CMainFramCDocumentCView类的组织

在CTestAppInitInstance()

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CTestDoc),

RUNTIME_CLASS(CMainFrame),       // main SDI frame window

RUNTIME_CLASS(CTestView));

 

关于窗口对象和窗口的关系

窗口销毁并不代表其对象销毁,句柄的生命周期并不一定意味着结束,对象销毁意味着窗口销毁,因为资源被回收。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值