社区
界面
帖子详情
请问可停靠窗口怎么充满view类
zdcju
2013-08-06 08:15:36
我用的vs2008 生成单文档 visual stdio 样式的例子
就是有 类窗口 文件窗口 等4个窗口的那个列子
那四个窗口都可以拖拽 但是view类的背景还是能看到 怎么设置把view类遮挡住呀 谢谢
...全文
69
1
打赏
收藏
请问可停靠窗口怎么充满view类
我用的vs2008 生成单文档 visual stdio 样式的例子 就是有 类窗口 文件窗口 等4个窗口的那个列子 那四个窗口都可以拖拽 但是view类的背景还是能看到 怎么设置把view类遮挡住呀 谢谢
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
1 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
向立天
2013-09-07
打赏
举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了
疑难问题汇总帖
并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面
界面版关于版主结帖工作的具体办法
MFC视图中增加可
停靠
面板
本文档详细记录了,如何在MFC单文档环境下,添加一个CDockablePane面板,面板上加载一个对话框,可以实现对话框的自动隐藏。
QT-点云视窗
类
Cloud
View
er
1、点云 IO。常见点云格式文件(如 ply, pcd 和 obj)的读取、保存、删除清空及可视化。 2、点云的基本操作。设置点云颜色,合并多个点云,点云格式转换等。 3、可视化的基本操作。设置视图
窗口
背景颜色,设置点云的可视化尺寸,设置坐标系的显示,设置视图方位(Main
view
, Left
view
, Top
view
),网格面片显示,网格线框显示等。 4、模型生成。生成简单立方排布的点云以及基本三维模型,该功能主要用于测试。 5、软件界面基本功能。软件由: [1] 菜单栏、[2] 工具栏、[3] 资源管理树、[4] 属性管理器、[5] 输出
窗口
、[6] 状态栏、[7] 视图
窗口
以及 [8] RGB
窗口
组成。其中部分都是
停靠
窗口
,可以在菜单栏的视图选项设置是否显示,方便用户自定义软件界面。软件还提供 Windows 和 Darcula 两大主题,其中 Darcula 主题为默认主题,仿照 Visual Studio 和 Android Studio 相应
MFC的程序框架剖析
什么是句柄? 句柄,是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同
类
对象中的不同的实例,诸如,一个
窗口
,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不用在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows使用了大量的句柄来标志很多对象。 一、MFC AppWizard 1、MFC(Microsoft Foundation Class,微软基础
类
库)是微软为了简化程序员的开发工作所开发的一套C++
类
的集合,是一套面向对象的函数库,以
类
的方式提供给用户使用 2、MFC AppWizard是一个辅助我们生成源代码的向导工具,它可以帮助我们自动生成基于MFC框架的源代码 二、基于MFC的程序框架剖析 1、MFC程序的Class
View
标签页(图) 2、继承关系 (1)CMainFrame继承于CFrameWnd (2)CTestApp继承于CWinApp (3)CTestDoc继承于CDocument (4)CTest
View
继承于C
View
注:CFrameWnd和C
View
都继承于CWnd 3、CWnd
类
是MFC中一个非常重要的
类
,它封装了与
窗口
相关的操作 4、MFC
类
的简化组织结构图(图) 5、MFC程序也有一个WinMain函数,程序是在编译时,由链接器将它链接到程序中 6、MFC程序具有一个CTestApp
类
的全局对象theApp,在MFC程序运行时,程序执行的顺序为:theApp全局对象定义 处->CTestApp构造函数->WinMain函数 7、对于普通的VC++控制台程序,无论全局变量还是全局对象,程序运行时,在加载main函数之前,就已经为它们 分配了内存空间。对于一个全局对象来说,此时就会调用该对象的构造函数,构造该对象,并进行初始化操作 8、实例句柄与全局对象 (1)对于Win32 SDK程序,应用程序的实例是由实例句柄(WinMain函数的hInstance参数)来标识的 (2)对于MFC程序,应用程序的实例是由全局对象(每一个MFC程序有且仅有一个从应用程序
类
CWinApp派生的
类
, 如CTestApp,它实例化theApp全局对象)来标识的 9、基
类
构造函数中this指针的指向问题 在构造子
类
对象时,会自动调用父
类
的构造函数,此时在父
类
的构造函数中的this指针所指向的是子
类
对象地址 10、AfxWinMain函数 MFC程序的WinMain函数是通过调用AfxWinMain函数来完成它的功能的 注:Afx前缀的函数代表应用程序框架(Application Framework)函数,它们可以在程序的任何地方被调用 11、CTestApp::InitInstance函数 在AfxWinMain函数中,通过调用InitInstance函数来完成MFC内部管理方面的工作 12、AfxEndDeferRegisterClass函数 MFC提供了一些默认的标准
窗口
类
,我们只需要选择所需的
窗口
类
就行。然后,调用AfxEndDeferRegisterClass 函数来注册
窗口
类
13、CMainFrame::PreCreateWindow函数 MFC程序具有两个
窗口
(框架
窗口
和视
类
窗口
),在框架
窗口
产生之前会调用PreCreateWindow函数 14、CWnd::CreateEx函数 在MFC程序中,
窗口
的创建是由CreateEx函数实现的 15、CWnd::CreateWindowEx函数 主要作用是当修改了CreateEx函数的CREATESTRUCT参数时,CreateWindowEx函数会根据参数发生的相应变化来创 建一个符合我们要求的
窗口
注:MFC中后缀名为Ex的函数都是扩展函数 16、CMainFrame::ShowWindow函数和CMainFrame::UpdateWindow函数 用于显示应用程序框架
窗口
和更新这个
窗口
17、CWinThread::Run函数和CWinThread::PumpMessage函数 用于完成消息循环 18、DefWindowProc函数 默认的
窗口
过程,但MFC程序对消息的处理实际上是通过消息映射机制来完成的 19、MFC程序的运行过程 (1)首先利用全局应用程序对象theApp启动应用程序 (2)调用全局应用程序对象的构造函数,从而就会调用其基
类
CWinApp的构造函数,以完成应用程序的一些初始化 (3)进入WinMain函数 (4)进入消息循环 20、MFC程序的主要过程 theApp-> CTestApp::CTestApp构造函数-> CWinApp::CWinApp构造函数-> _tWinMain(WinMain函数的宏)-> AfxWinMain函数-> CTestApp::InitInstance函数-> AfxEndDeferRegisterClass函数-> CMainFrame::PreCreateWindow函数-> CFrameWnd::PreCreateWindow函数-> AfxDeferRegisterClass(AfxEndDeferRegisterClass函数的宏)-> CFrameWnd::Create函数-> CWnd::CreateEx函数-> CMainFrame::PreCreateWindow函数-> CWnd::CreateEx函数-> CMainFrame::ShowWindow函数-> CMainFrame::UpdateWindow函数-> CWinThread::Run函数-> CWinThread::PumpMessage函数 21、框架
窗口
(整个应用程序外框所包括的部分)是视
类
窗口
(框架
窗口
中空白的地方)的一个父
窗口
22、MFC提供了一个文档/视
类
的结构,文档是指CDocument
类
,视
类
是指C
View
类
。前者用于数据的存储和加载, 后者用于数据的显示和修改 23、框架对象、文档对象和视
类
对象是通过一个单文档模板指针来有机地组织在一起,并利用AddDocTemplate函数 把这个单文档模板添加到文档模板中,从而把这三个
类
组织成为一个整体 24、MFC程序的CAboutDlg
类
继承于CDialog
类
,用于为用户提供一些与程序相关的帮助信息 三、
窗口
类
、
窗口
类
对象与
窗口
1、以“::”开始的函数是一个全局函数,表示调用的是Platform SDK的函数 2、如果我们关闭了一个
窗口
,这个
窗口
就销毁了,那么该
窗口
对应的C++
窗口
类
对象销毁了吗? (1)当一个
窗口
销毁时,它会调用CWnd::DestroyWindow函数,该函数销毁
窗口
后,将CWnd::m_hWnd设为NULL (2)
窗口
的生命周期和C++
窗口
类
对象的声明周期不是一致的。当一个
窗口
销毁时,与C++
窗口
类
对象没有关系,它 们之间的纽带仅仅在于这个C++
窗口
类
内部的成员变量m_hWnd,该变量保存了与这个C++
窗口
类
对象相关的哪个
窗口
的句柄 (3)但是,当C++
窗口
类
对象销毁时,与之相关的
窗口
也将销毁,因为它们之间的纽带m_hWnd已经断了 3、示例---在
窗口
中显示按钮 (1)CButton按钮
类
继承于CWnd (2)对于一个CButton对象,在定义之后就可以使用了;但是,如果要显示这个按钮的话,还需调用 CButton::Create函数,把按钮
窗口
与CButton对象关联起来 (3)MFC程序的
窗口
创建时都会产生WM_CREATE消息,该消息通过OnCreate函数来捕获。对于框架
窗口
来说,MFC直 接把OnCreate函数提供到了CMainFrame中;而在视
类
窗口
中没有提供该函数,如需使用,要用户自行添加 (4)通常对MFC程序的操作,都是在CTest
View
视
类
窗口
中进行的 (5)在
窗口
创建之后,要显示该
窗口
可以通过调用ShowWindow函数或指定
窗口
风格为WS_VISIBLE来实现 (6)实现过程 A:在CTest
View
类
中,添加CButton
类
型的私有成员m_btn B:在CTest
View
类
中,添加WM_CREATE消息的OnCreate处理函数 C:在CTest
View
类
中,通过GetParent函数可以获得CMainFrame框架
窗口
对象的指针 D:实现一(在视
类
窗口
中通过ShowWindow函数显示按钮) int CTest
View
::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... m_btn.Create("按钮",WS_CHILD|BS_DEFPUSHBUTTON,CRect(0,0,100,100),this,123); m_btn.ShowWindow(SW_SHOWNORMAL); return 0: } E:实现二(在视
类
窗口
中通过WS_VISIBLE风格显示
窗口
) int CTest
View
::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... m_btn.Create("按钮",WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,CRect(0,0,100,100),this,123); return 0: } F:实现三(在框架
窗口
中显示按钮) int CTest
View
::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... m_btn.Create("按钮",WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,CRect(0,0,100,100),GetParent(),123); return 0: } 即便是基于MFC的应用程序,建立
窗口
类
也是会遵循如下的过程: 设计
窗口
类
->注册
窗口
类
->生成
窗口
->显示
窗口
->更新
窗口
->消息循环->消息路由到
窗口
过程函数处理。下面就剖析一下在MFC中是如何完成上述过程的。 (1)每个应用程序都有且仅有一个应用
类
的全局变量theApp,全局变量先于WinMain函数进行处理。 (2)WinMain函数体在APPMODUL.CPP文件中,定义如下: extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } 其中#define _tWinMain WinMain (3)AfxWinMain函数体在WINMAIN.CPP文件中,里面有如下两句话: CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp(); 其实这里得到的这两个指针都是指向全局的对象theApp的; 接下来有函数调用pThread->InitInstance(),根据多态性,会调用CXXXApp
类
中的InitInstance()函数。该函数很重要,在对该函数的调用中就会完成:设计
窗口
类
->注册
窗口
类
->生成
窗口
->显示
窗口
->更新
窗口
。 接下来,该函数中会继续调用pThread->Run(),这就完成了:消息循环->消息路由到
窗口
过程函数处理。 (4)进入CXXXApp::InitInstance()函数体中,对于单文档应用程序,调用ProcessShellCommand(cmdInfo),通过调用该函数就会完成:设计
窗口
类
->注册
窗口
类
->生成
窗口
。 再接下来就会调用m_pMainWnd->ShowWindow(SW_SHOW);m_pMainWnd->UpdateWindow();这就完成了:显示
窗口
->更新
窗口
。 (5)在函数CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo)中会进入到如下的case分支:case CCommandLineInfo::FileNew: if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)) (6)进入函数CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo),调用_AfxDispatchCmdMsg(this, nID, nCode, lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo); (7)进入函数AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode, AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo),调用 case AfxSig_vv: // normal command or control notification ASSERT(CN_COMMAND == 0); // CN_COMMAND same as BN_CLICKED ASSERT(pExtra == NULL); (pTarget->*mmf.pfn_COMMAND)(); (8)进入CWinApp::OnFileNew(),调用m_pDocManager->OnFileNew();这个函数很特殊,它本身是个消息响应函数,当我们点击ID为ID_FILE_NEW的菜单时,会产生一个命令消息,由于命令消息可以被CCmdTarget
类
及其派生
类
来捕获,而CWinApp是从CCmdTarget派生出来的,因此可以捕获这个消息。当应用程序创建完成并成功显示后,当我们点击文件菜单下的新建菜单项时,就会首先进入这个函数,然后再依次执行下去,最后就会执行到pDocument->OnNewDocument()中,往往我们会对这个函数不解,不知道它为什么会响应ID_FILE_NEW的命令消息,至此真相大白了。顺便说一句,为什么程序在刚启动的时候,我们并没有点击菜单项,为什么会自动的产生这个消息呢?这是因为在CXXXXApp::InitInstance()函数中有“CCommandLineInfo cmdInfo;”这个
类
的构造函数是这样的:CCommandLineInfo::CCommandLineInfo() { m_bShowSplash = TRUE; m_bRunEmbedded = FALSE; m_bRunAutomated = FALSE; m_nShellCommand = FileNew; },因此就会在第(5)步骤的时候进入到“case CCommandLineInfo::FileNew:”这个分支中,就相当于产生了这样一个FileNew的消息。同理对于ID为ID_FILE_OPEN(在CWinApp::OnFileOpen()中响应)、ID_FILE_SAVE(在CDocument::OnFileSave()中响应)等等在MFC向导为我们生成的单文档
类
中找不到消息响应的入口时,其实都是在基
类
CWinApp或者CDocument
类
中进行了响应。对于CXXXXDoc::Serialize(CArchive& ar)函数也是通过ID_FILE_SAVE和ID_FILE_OPEN产生命令消息后就行响应从而才调用该函数的。 (9)进入CDocManager::OnFileNew(),CDocManager
类
有一个成员变量是CPtrList m_templateList;该变量保存了一个文档模版链表指针,在CDocManager::OnFileNew()函数体中会调用CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();得到链表中的头,也就是第一个文档模版,后面就会用得到的这个指针去调用pTemplate->OpenDocumentFile(NULL);紧接着就会有一个判断,用来确定该链表中是否只有一项,如果链表中保存了多个文档模版,则会弹出一个对话框,来让我们选择到底是使用哪一套文档模版来构建应用程序,相信大家也都见到过这种情况吧。对了,还有一点要说明的是:pTemplate是一个CDocTemplate的指针,但接下来程序为什么会进入到CSingleDocTemplate::OpenDocumentFile的函数体内呢,这是因为CDocTemplate
类
中的OpenDocumentFile函数被定义为纯虚函数,而CSingleDocTemplate
类
又是从CDocTemplate
类
派生出来的,并且实现了该函数,因此就会进入到子
类
的函数体中了。 (10)进入CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible),先调用CreateNewDocument()创建文档
类
,再调用pFrame = CreateNewFrame(pDocument, NULL);创建框架
类
和视图
类
,从这里也可以看出MFC体系结构中文档、框架、视图“三位一体”的模式,在这一个函数中同时创建三个
类
;再会调用pDocument->OnNewDocument();因此就会进入到子
类
的文档
类
中的pDocument->OnNewDocument()中了。 (11)进入CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther),调用if (!pFrame->LoadFrame(m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame styles NULL, &context)) (12)进入BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext),调用VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEOR
VIEW
_REG)); (13)进入BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister),该函数内部就完成了:设计
窗口
类
->注册
窗口
类
。MFC通过给我们提供好一些已经订制好的
窗口
类
,我们不需要自己再设计
窗口
类
,只需要到那些订制好的
窗口
类
“仓库”中寻找一种适合我们需要的
窗口
类
就可以了,然后通过AfxRegisterClass函数注册
窗口
类
。还需要说明的是,再后续的跟踪过程中,我们会发现还会进入到AfxEndDeferRegisterClass函数中进行设计和注册
窗口
类
,这主要是因为单文档应用程序比较特殊,它提前通过这样的一种途径进行了
窗口
类
的设计和注册步骤,其实是应该在BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)函数的调用中完成
窗口
类
的设计和注册的,这一点我们要清楚,也就是说设计和注册
窗口
类
的正宗发源地应该是PreCreateWindow(CREATESTRUCT& cs)。此外,我们还会注意到在该函数体的前部分有一语句为“wndcls.lpfnWndProc = DefWindowProc;”因此所有
窗口
类
的
窗口
过程函数都是DefWindowProc,这一点在后面的跟踪中可以看到,每次生成
窗口
之后都会调用几次DefWindowProc函数。也就是说MFC都是让我们采用默认的
窗口
过程函数,这并不是说我们因此就不能使用自己的
窗口
过程函数实现个性化的消息处理了,MFC采用了一种基于消息映射的机制完成了消息个性化处理。 (14)回到BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)中,调用LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource); (15)进入LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource),调用PreCreateWindow(cs); (16)进入BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs),调用CFrameWnd::PreCreateWindow(cs) (17)进入BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs),调用VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEOR
VIEW
_REG));又一次设计和注册
窗口
类
(18)回到BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)中,调用if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext)) (19)进入BOOL CFrameWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, LPCTSTR lpszMenuName, DWORD dwExStyle, CCreateContext* pContext),调用if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)) (20)BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam),调用if (!PreCreateWindow(cs)) ,接下来调用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);好了,终于让我们找到生成
窗口
的地方了——函数::CreateWindowEx! (21)进入int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct),调用if (CFrameWnd::OnCreate(lpCreateStruct) == -1) (22)进入int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs),调用return OnCreateHelper(lpcs, pContext); (23)进入int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext),调用if (CWnd::OnCreate(lpcs) == -1) (24)进入_AFXWIN_INLINE int CWnd::OnCreate(LPCREATESTRUCT),调用return (int)Default(); (25)进入LRESULT CWnd::Default(),调用return DefWindowProc(pThreadState->m_lastSentMsg.message, pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam); (26)进入LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam),调用return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); (27)回到int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext),调用if (!OnCreateClient(lpcs, pContext)) (28)进入BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext),调用if (Create
View
(pContext, AFX_IDW_PANE_FIRST) == NULL) (29)进入CWnd* CFrameWnd::Create
View
(CCreateContext* pContext, UINT nID),调用if (!p
View
->Create(NULL, NULL, AFX_WS_DEFAULT_
VIEW
, CRect(0,0,0,0), this, nID, pContext)) (30)进入BOOL CWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext),调用return CreateEx(0, lpszClassName, lpszWindowName, dwStyle | WS_CHILD, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext); (31)进入BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam),重复生成框架
类
CMainFrame的过程来生成CXXX
View
,因为它也是一个
窗口
类
,因此也需要进行那一系列过程才能最终显示更新出来。 调用的顺序是这个样子的:PreCreateWindow(cs)->BOOL CXXX
View
::PreCreateWindow(CREATESTRUCT& cs)->C
View
::PreCreateWindow(cs)->VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEOR
VIEW
_REG));->::CreateWindowEx(...)->CWnd::DefWindowProc->::CallWindowProc(...)->...->CXXX
View
::OnCreate->C
View
::OnCreate->CWnd::OnCreate->... 写到这里,基本上就清楚了,中间的省略号表示的部分大多数都是在与
窗口
过程函数有关的,因为在生成
窗口
的时候需要响应一些消息,因此需要调用一些
窗口
过程函数,每次在调用::CreateWindowEx(...)函数后都会调用一些
窗口
过程函数,然后再去调用该
窗口
类
对应的OnCreate函数,其实在调用OnCreate函数之前调用CreateWindowEx只是生成了一个
窗口
,至于这个
窗口
里面要放置些什么东西,以及该如何装饰该
窗口
,则就需要由OnCreate来完成了,往往我们都会在OnCreate函数的后面(这样做是为了不影响
窗口
本身应该布置的格局)添加一些代码,创建我们自己的东西,比如我们通常会在CMainFrame
类
的OnCreate函数后面放置一些Create代码,来创建我们自己的可
停靠
的工具栏或者按钮之
类
的东西,当然我们也可以在CXXX
View
类
的OnCreate函数的后面添加一些代码,来创建我们需要的东西,比如按钮之
类
的东西。在完成了从设计、注册到生成
窗口
的过程之后,往往还需要显示更新,有些时候,我们不必要每次都显示的调用CWnd的ShowWindow和UpdateWindow两个函数,我们可以在创建的时候,给
窗口
风格中添加WS_VISIBLE即可,因此有些时候会跟踪不到ShowWindow和UpdateWindow两个函数这两个函数,因为
窗口
在创建的时候就可见了。 总的来说,先初始化应用
类
,然后注册生成框架
类
,然后再注册生成视图
类
,然后注册生成视图
类
OnCreate函数后面用户添加的、用Create来准备创建的
窗口
,然后再注册生成框架
类
的OnCreate函数后面需要生成的m_wndToolBar、m_wndStatusBar以及我们自己添加的要创建的
窗口
类
,最后在回到应用
类
的初始化的函数体中,调用框架
类
的显示和更新函数,然后再进入由框架
类
定义的
窗口
的消息循环中。 消息循环的过程是这个样子的: (1)调用int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)函数中的pThread->Run() (2)进入int CWinApp::Run(),调用return CWinThread::Run(); (3)进入int CWinThread::Run(),调用if (!PumpMessage()) (4)进入BOOL CWinThread::PumpMessage(),调用if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) (5)回到BOOL CWinThread::PumpMessage(),调用::TranslateMessage(&m_msgCur);::DispatchMessage(&m_msgCur); (6)回到int CWinThread::Run(),调用while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); (7)再重复(4)-(6)的步骤 下面给出int 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)); 这段代码其实本质上与我们基于Win32 SDK手写的代码: //消息循环 MSG msg; while(GetMessage(&msg,NULL,0,0)) { //简单的说,函数TranslateMessage就是把WM_KEYDOWN和WM_KEYUP翻译成WM_CHAR消息,没有该函数就不能产生WM_CHAR消息。 TranslateMessage(&msg); ::DispatchMessage(&msg); } 是一致的。 1,寻找WinMain人口: 在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。 路径:MFC|SRC|APPMODUL.CPP: _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } 注意:(#define _tWinMain WinMain) 2,对于全局对象或全局变量来说,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。 所以:CTEApp theApp;->CTEApp ::CTEApp(){}->_tWinMain(){} 说明:每一个MFC程序,有且只有一个从WinApp
类
派生的
类
(应用程序
类
),也只有一个从应用程序
类
所事例化的对象,表示应用程序本身。在WIN32程序当中,表示应用程序是通过WINMAIN入口函数来表示的(通过一个应用程序的一个事例号这一个标识来表示的)。在基于MFC应用程序中,是通过产生一个应用程序对象,用它来唯一的表示了应用程序。 3,通过构造应用程序对象过程中调用基
类
CWinApp的构造函数,在CWinApp的构造函数中对程序包括运行时一些初始化工作完成了。 CWinApp构造函数:MFC|SRC|APPCORE.CPP CWinApp::CWinApp(LPCTSTR lpszAppName){...}//带参数,而CTEApp构造函数没有显式向父
类
传参,难道CWinApp()有默认参数?见下: (在CWinApp
类
定义中, CWinApp(LPCTSTR lpszAppName = NULL); ) 注意:CWinApp()函数中: pThreadState->m_pCurrentWinThread = this; pModuleState->m_pCurrentWinApp = this (this指向的是派生
类
CTEApp对象,即theApp) 调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){} 4,_tWinMain函数中通过调用AfxWinMain()函数来完成它要完成的功能。(Afx*前缀代表这是应用程序框架函数,是一些全局函数,应用程序框架是一套辅助生成应用程序的框架模型,把一些
类
做一些有机的集成,我们可根据这些
类
函数来设计自己的应用程序)。 AfxWinMain()函数路径:MFC|SRC|WINMAIN.CPP: 在AfxWinMain()函数中: CWinApp* pApp = AfxGetApp(); 说明:pApp存储的是指向WinApp派生
类
对象(theApp)的指针。 //_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp() // { return afxCurrentWinApp; } 调用pThread->InitInstance() 说明:pThread也指向theApp,由于基
类
中virtual BOOL InitApplication()定义为虚函数,所以调用pThread->InitInstance()时候,调用的是派生
类
CTEApp的InitInstance()函数。 nReturnCode = pThread->Run(); 说明:pThread->Run()完成了消息循环。 5,注册
窗口
类
:AfxEndDeferRegisterClass(); AfxEndDeferRegisterClass()函数所在文件:MFC|SRC|APPCORE.CPP BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){...} 说明:设计
窗口
类
:在MFC中事先设计好了几种缺省的
窗口
类
,根据不同的应用程序的选择,调用AfxEndDeferRegisterClass()函数注册所选择的
窗口
类
。 调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}//进入程序 ->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父
类
InitInstance虚函数;->CTEApp::InitInstance()//子
类
实现函数;->AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的
窗口
类
(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建
窗口
阶段(以下再不做调试) 6,PreCreateWindow()://主要是注册
窗口
类
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; return TRUE; } 说明: CFrameWnd::PreCreateWindow()函数所在文件:MFC|SRC|WINFRM.CPP BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) { if (cs.lpszClass == NULL) { VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEOR
VIEW
_REG)); //判断AFX_WNDFRAMEOR
VIEW
_REG型号
窗口
类
是否注册,如果没有注册则注册 cs.lpszClass = _afxWndFrameOr
View
; // COLOR_WINDOW background //把注册后的
窗口
类
名赋给cs.lpszClass } if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4) cs.style |= FWS_PREFIXTITLE; if (afxData.bWin4) cs.dwExStyle |= WS_EX_CLIENTEDGE; return TRUE; } 其中: virtual BOOL PreCreateWindow(CREATESTRUCT& cs);//PreCreateWindow()是个虚函数,如果子
类
有则调用子
类
的。 #define VERIFY(f) ASSERT(f) #define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass) define AFX_WNDFRAMEOR
VIEW
_REG 0x00008 const TCHAR _afxWndFrameOr
View
[] = AFX_WNDFRAMEOR
VIEW
;//WINCORE.CPP文件中,定义为全局数组。 //#define AFX_WNDFRAMEOR
VIEW
AFX_WNDCLASS("FrameOr
View
") 7,创建
窗口
: Create()函数路径:MFC|SRC|WINFRM.CPP: CFrameWnd::Create(...){ ... CreateEx(...);//从父
类
继承来的,调用CWnd::CreateEx(). ... } CWnd::CreateEx()函数路径:MFC|SRC|WINCORE.CPP 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); ... } 说明:CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建
窗口
之前通过可PreCreateWindow(cs)修改cs结构体成员来修改所要的
窗口
外观。PreCreateWindow(cs))//是虚函数,如果子
类
有调用子
类
的。 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; 8,显示和更新
窗口
: CTEApp
类
,TEApp.cpp中 m_pMainWnd->ShowWindow(SW_SHOW);//显示
窗口
,m_pMainWnd指向框架
窗口
m_pMainWnd->UpdateWindow();//更新
窗口
说明: class CTEApp : public CWinApp{...} class CWinApp : public CWinThread{...} class CWinThread : public CCmdTarget { ... public: CWnd* m_pMainWnd; ... ... } 9,消息循环: int AFXAPI AfxWinMain() { ... // Perform specific initializations 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)); ... } 说明: BOOL PeekMessage(,,,,)函数说明 The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified structure. If a message is available, the return value is nonzero. If no messages are available, the return value is zero. ///////////////////////////////////////////////////////////// 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; } 9,文档与视结构: 可以认为
View
类
窗口
是CMainFram
类
窗口
的子
窗口
。 DOCument
类
是文档
类
。 DOC-
VIEW
结构将数据本身与它的显示分离开。 文档
类
:数据的存储,加载 视
类
:数据的显示,修改 10,文档
类
,视
类
,框架
类
的有机结合: 在CTEApp
类
CTEApp::InitInstance()函数中通过文档模板将文档
类
,视
类
,框架
类
的有机组织一起。 ... CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CTEDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CTE
View
)); AddDocTemplate(pDocTemplate);//增加到模板
QT高级编程
第1章 混合桌面/internet应用程序 1.1 internet相关
窗口
部件 1.2 webkit的使用 第2章 声音和视频 2.1 qsound和qmovie的使用 2.2 phonon多媒体框架 第3章 模型/视图表格模型 3.1 qt的模型/视图架构 3.2 用于表格的qstandarditemmodel 3.3 创建自定义表格模型 第4章 模型/视图树模型 4.1 用于树qstandarditemmodel的用法 4.2 创建自定义树模型 第5章 模型/视图委托 5.1 与数据
类
型相关的编辑器 5.2 与数据
类
型相关的委托 5.3 与模型相关的委托 第6章 模型/视图中的视图 6.1 qabstractitem
view
子
类
.6.2 与模型相关的可视化视图 第7章 用qtconcurrent实现线程处理 7.1 在线程中执行函数 7.2 线程中的过滤和映射 第8章 用qthread实现线程处理 8.1 独立项的处理 8.2 共享项的处理 第9章 创建富文本编辑器 9.1 qtextdocument简介 9.2 创建自定义的文本编辑器 9.3 一个单行的富文本编辑器 9.4 编辑多行的富文本 第10章 创建富文本文档 10.1 高质量地输出qtextdocument文件 10.2 创建qtextdocument 10.3 输出和打印文档 10.4 绘制页面 第11章 创建图形/视图
窗口
11.1 图形/视图架构 11.2 图形/视图
窗口
部件和布局 11.3 图形项简介 第12章 创建图形/视图场景 12.1 场景、项和动作 12.2 增强qgraphics
view
的功能 12.3 创建可
停靠
的工具箱
窗口
部件 12.4 创建自定义图形项 第13章 动画和状态机框架 13.1 动画框架简介 13.2 状态机框架简介 13.3 动画和状态机的结合 结束语 精选书目
QT高级编程(中文完整高清版带书签).rar
作 者(英)萨默菲尔德 著,白建平 等译 出 版 社电子工业出版社 出版时间2011-4-1 ISBN9787121131103 第1章 混合桌面/Internet应用程序 1.1 Internet相关
窗口
部件 1.2 WebKit的使用 第2章 声音和视频 2.1 QSound和QMovie的使用 2.2 Phonon多媒体框架第3章 模型/视图表格模型 3.1 Qt的模型/视图架构 3.2 用于表格的QStandardItemModel 3.3 创建自定义表格模型 第4章 模型/视图树模型 4.1 用于树QStandardItemModel的用法 4.2 创建自定义树模型 第5章 模型/视图委托 5.1 与数据
类
型相关的编辑器 5.2 与数据
类
型相关的委托 5.3 与模型相关的委托 第6章 模型/视图中的视图 6.1 QAbstractItem
View
子
类
6.2 与模型相关的可视化视图 第7章 用QtConcurrent实现线程处理 7.1 在线程中执行函数 7.2 线程中的过滤和映射 第8章 用QThread实现线程处理 8.1 独立项的处理 8.2 共享项的处理 第9章 创建富文本编辑器 9.1 QTextDocument简介 9.2 创建自定义的文本编辑器 9.3 一个单行的富文本编辑器 9.4 编辑多行的富文本 第10章 创建富文本文档 10.1高质量地输出QTextDocument文件 10.2 创建QTextDocument 10.3 输出和打印文档 10.4 绘制页面 第11章 创建图形/视图
窗口
11.1 图形/视图架构 11.2 图形/视图
窗口
部件和布局 11.3 图形项简介 第12章 创建图形/视图场景 12.1 场景、项和动作 12.2 增强QGraphics
View
的功能 12.3 创建可
停靠
的工具箱
窗口
部件 12.4 创建自定义图形项 第13章 动画和状态机框架 13.1 动画框架简介 13.2 状态机框架简介 13.3 动画和状态机的结合 结束语 精选书目
界面
15,979
社区成员
115,897
社区内容
发帖
与我相关
我的任务
界面
VC/MFC 界面
复制链接
扫一扫
分享
社区描述
VC/MFC 界面
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章