admin管理员组文章数量:1621912
关于向导
工程---文件---MFC AppWizarad.exe:取工程名和存放目录
AppWizard 辅助生成代码工具,可以创建三类应用程序:单文档、多文档、对话框
比如生成Test单文档应用程序,帮助生成五各类:
CAboutDlg、CMainFrame、CTestApp、CTestDoc、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 可以看到
CTestApp由CWinApp继承,表示应用程序类,每个应用程序都有这个类,该类定义一个全局对象CTestApp theApp 入口程序执行前首先为全局对象分配空间,初始化工作由CWinApp类完成 该类在APPCORE实现
pModuleState->m_pCurrentWinApp = this; //子类继承,便是子类对象地址
CTestApp::CTestApp()
CWinApp::CWinApp(LPCTSTR lpszAppName)
CTestApp()没有显式调用CWinApp(LPCTSTR 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())//是虚函数,所以调用还是CTestApp的InitialInstance()
设置断点可以验证
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路由的消息不全是交给默认消息处理函数处理,采用了消息映射机制找到对应函数处理
关于CMainFram、CDocument、CView类的组织
在CTestApp的InitInstance()
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CTestView));
关于窗口对象和窗口的关系
窗口销毁并不代表其对象销毁,句柄的生命周期并不一定意味着结束,对象销毁意味着窗口销毁,因为资源被回收。
版权声明:本文标题:剖析MFC窗口类框架应用程序 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1728851900a1176777.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论