1. 创建不同的子frame.

在文档视图程序中 CMainFrame(class CMainFrame : public CMDIFrameWndEx) 继承自 CMDIFrameWnd (CMDIFrameWndEx 为 CMDIFrameWnd子类). 因此可以将 m_pMainWnd 转为 CMDIFrameWnd 的指针, 再调用 CreateNewChild 创建一个子frame. 此时可根据传入的具体的类名, 强制转换为所需的对象.

    CMDIFrameWnd* pMdiFrmWnd = reinterpret_cast<CMDIFrameWnd*>(m_pMainWnd);m_pChildFrm= reinterpret_cast<CChildFrm*> (pMdiFrmWnd->CreateNewChild(RUNTIME_CLASS(CChildFrm), IDR_MAINFRAME));m_pChildFrm->ShowWindow(SW_SHOW);

2. CSplitterWnd 拆分窗口.

拆分窗口在 CMDIChildWnd 子类的 OnCreateClient 方法中进行. 首先使用 CreateStatic 可以将窗口进行拆分, 最大支持 16 x 16. 

然后 CreateView 对不同的区域设置不同的 CView, 完成之后使用 CSplitterWnd 对象的 GetPane 方法可以取得不同区域的CWnd指针, 将其强转为设置的 CView 子类即可.

注意: (1) CreateStatic 创建的每一个区域都必须使用 CreateView 设置一个 CView的子类, 或者使用另一个 CSplitterWnd 填充进行继续拆分.

        (2) CreateView 传入的必须是 CView 的子类, 不能使用Ctrl或Dialog, 对于控件如CEdit, 可以使用 CEditView 代替, 其它如CCtrlView类等. 对于使用资源的对话框类, 可以使用 CFormView.

BOOL CChildFrm::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext*pContext)
{//创建拆分窗口if (!m_wndSplitter.CreateStatic(this, 2, 1))returnFALSE;if (!m_wndSplitterTop.CreateStatic(&m_wndSplitter, 1, 3, WS_CHILD | WS_VISIBLE, m_wndSplitter.IdFromRowCol(0, 0))){returnFALSE;}if (!m_wndSplitterTop.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(0, 0), pContext)){returnFALSE;}if (!m_wndSplitterTop.CreateView(0, 1, RUNTIME_CLASS(CSpliteDemoView), CSize(0, 0), pContext)){returnFALSE;}if (!m_wndSplitterTop.CreateView(0, 2, RUNTIME_CLASS(CSpliteDemoView), CSize(0, 0), pContext)){returnFALSE;}if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CCtrlsView), CSize(0, 0), pContext)){returnFALSE;}m_pLeftView= reinterpret_cast<CLeftView*>(m_wndSplitterTop.GetPane(0, 0));m_pMidView= reinterpret_cast<CSpliteDemoView*>(m_wndSplitterTop.GetPane(0, 1));m_pRightView= reinterpret_cast<CSpliteDemoView*>(m_wndSplitterTop.GetPane(0, 2));m_pCtrls= reinterpret_cast<CCtrlsView*>(m_wndSplitter.GetPane(1, 0));returnTRUE;
}

3. CSplitterWnd 大小调整

窗口大小改变后会调用 OnSize 方法(需在消息映射表中添加ON_WM_SIZE()), 此时一般需要修改 splitter及各个子 view的大小和位置. 其中 splitter 调整后需要调用 SetRowInfo 和 SetColumnInfo 来重新设置分隔条的位置.

注意,初始化过程中 OnSize 方法会被多次调用, 部分窗口可能还没有创建, 因此需要作判断.

BEGIN_MESSAGE_MAP(CChildFrm, CMDIChildWndEx)ON_WM_SIZE()ON_MESSAGE(UM_INPUT_TEXT,&CChildFrm::OnInputText)
END_MESSAGE_MAP()void CChildFrm::OnSize(UINT nType, int cx, intcy)
{CMDIChildWndEx::OnSize(nType, cx, cy);if(::IsWindow(m_wndSplitterTop)){CRect rect;GetClientRect(rect);m_wndSplitter.MoveWindow(rect);int nHeight = rect.Height() - 50;if (nHeight < 0)nHeight= 0;m_wndSplitterTop.MoveWindow(rect.left, rect.top, rect.right, nHeight);m_wndSplitter.SetRowInfo(0, nHeight, 0);m_wndSplitter.RecalcLayout();m_wndSplitterTop.GetClientRect(rect);int nWidth = rect.Width() / 3;m_wndSplitterTop.GetPane(0, 0)->MoveWindow(rect.left, rect.top, nWidth, rect.bottom);m_wndSplitterTop.GetPane(0, 1)->MoveWindow(nWidth, rect.top, nWidth * 2, rect.bottom);m_wndSplitterTop.GetPane(0, 2)->MoveWindow(nWidth * 2, rect.top, rect.right, rect.bottom);m_wndSplitterTop.SetColumnInfo(0, nWidth, 0);m_wndSplitterTop.SetColumnInfo(1, nWidth, 0);m_wndSplitterTop.RecalcLayout();m_wndSplitter.GetClientRect(rect);m_pCtrls->OnSize(nType, cx, cy);}
}

4. Frame中的消息分发

一个 frame 中通常包含多个子 view. 某个子 view 的消息通常需要传递到其它的子 view 中, 亦或者某些耗时操作需要到子线程中处理后更新到界面, 此时都需要涉及消息处理.

某个子 view 通知到其它的子 view时, 通常时先传递到 frame中, 再进行分发处理. 然后其它感兴趣的子 view 再响应此消息.

对于子线程的处理结果, 最好是 PostMessage 返回一个 new 创建的对象, 由 frame 使用 SendMessage 通知到各个子 view 处理后, 再释放.

voidCCtrlsView::OnBnClickedButtonConfirm()
{CString* pStrText = newCString();CWnd* pWnd =GetDlgItem(IDC_EDIT);pWnd->GetWindowTextW(*pStrText);pWnd->SetWindowText(_T(""));GetParentFrame()->SendMessage(UM_ADD_TEXT, (WPARAM) pStrText, 0);
}LRESULT CChildFrm::OnInputText(WPARAM wParam, LPARAM lParam)
{m_pLeftView->SendMessage(UM_ADD_TEXT, wParam, lParam);m_pMidView->SendMessage(UM_ADD_TEXT, wParam, lParam);m_pRightView->SendMessage(UM_ADD_TEXT, wParam, lParam);CString* pStr = (CString*) wParam;if(pStr){deletepStr;pStr=NULL;}return 0;
}LRESULT CSpliteDemoView::OnInputText(WPARAM wParam, LPARAM lParam)
{CString str= *(CString*)(wParam);CListCtrl* pListCtrl = &GetListCtrl();pListCtrl->InsertItem(pListCtrl->GetItemCount(), str);return 0;
}

5. 工作线程的设计

  创建线程, 在需要此工作线程事件触发时创建即可.

voidCChildFrm::CreateWorkThread()
{if (!m_hWorkThread){m_hWorkThread= CreateThread(NULL, 0, WordThreadFun, this, 0, &m_dwWordThreadId);Sleep(10); //稍微等一下,切换一下线程,等待线程创建
}
}

  框架中, 创建一个事件用于等持线程退出. 在析构函数或其它不需要此工作线程的地方, 发送一个退出的消息.

CChildFrm::CChildFrm()
{m_hWorkThreadExit= ::CreateEvent(NULL, TRUE, TRUE, _T(""));CreateWorkThread();
}CChildFrm::~CChildFrm()
{if(m_hWorkThreadExit){::PostThreadMessage(m_dwWordThreadId, WM_QUIT,0, 0);WaitForSingleObject(m_hWorkThreadExit,2000);CloseHandle(m_hWorkThreadExit);m_hWorkThreadExit=NULL;}
}

  工作线程函数体中处理不同的消息, 其它线程使用 PostThreadMessage 通知工作线程工作. 工作线程退出时, 设置事件为有信号状态.

DWORD WINAPI CChildFrm::WordThreadFun(LPVOID lpParam)
{CChildFrm* pMain = (CChildFrm*)lpParam;::ResetEvent(pMain->m_hWorkThreadExit);BOOL isRun=TRUE;MSG msg= {0};::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);while(isRun){GetMessage(&msg, NULL, 0, 0);switch(msg.message){caseWM_QUIT:isRun=FALSE;break;caseWM_GETTIME:{SYSTEMTIME systime= {0};::GetLocalTime(&systime);CString* pStr = newCString();pStr->Format(_T("%04d-%02d-%02d %02d:%02d:%02d"), systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond);pMain->PostMessage(UM_ADD_TEXT, (WPARAM) pStr, 0);}break;default:break;}}if (pMain->m_hWorkThread){CloseHandle(pMain->m_hWorkThread);pMain->m_hWorkThread =NULL;}::SetEvent(pMain->m_hWorkThreadExit);return 0;
}

MFC单文档多视图程序设计与Splitter拆分窗口相关推荐

  1. 【整理】MFC单文档程序窗口大小的设置

    有时候根据实际需要,比如MFC单文档程序视图里内容少.空白一大半,需要调整MFC单文档程序窗口大小.限制单文档的最大最小尺寸. 1.  要控制一个框架的的最大最小尺寸,需要做两件事情,在CFrameW ...

  2. MFC单文档框架编程(二): SDI框架下的消息处理

    MFC单文档框架编程(一) ...................................................................................... ...

  3. 【数字图像处理】 二.MFC单文档分割窗口显示图片

    本文是讲述<数字图像处理>系列文章,继上篇讲述BMP格式图片和显示后,该篇讲述如何对单文档进行分割.主要是采用CSplitterWnd静态分割窗口显示图片等相关知识.本文主要结合自己的课程 ...

  4. MFC单文档之给主窗口添加背景图片

    MFC单文档之给主窗口添加背景图片 1.导入图片 选择一个bmp格式的图片,将其导入到res文件夹中,然后工程资源目录下导入此图,注意格式一定要确定是百分百bmp格式的,不然报错,有的图片很坑是假bm ...

  5. 从0开始创建一个MFC单文档工程

    MFC单文档快速入门教程 开发环境 win7+vs2019 如何创建一个新的MFC单文档项目 如何创建菜单添加点击事件 创建菜单我的->测试的菜单 修改测试的菜单ID为ID_MY_TEST如下 ...

  6. OCC-7.6.0 + MFC单文档应用入门教程

    OCC-7.6.0 + MFC单文档应用 入门教程 磨刀不误砍柴工,如果你对MFC没任何基础,请先读这篇MFC的入门基础,它会降低你对这篇文章的恐惧感 开发环境说明 win7+ opencascade ...

  7. MFC单文档中,增加,删除 工具栏图标

    mfc单文档中,增加,修改,删除 工具栏图标方法: 首先,说明下,在资源视图中,XXX.rc下有个Toolbar,双击打开,如图所示,toolbar中有IDR_MAINFRAME_256和IDR_MA ...

  8. MFC单文档项目动态绘制十字线

    MFC单文档项目动态绘制十字线 因为最近的一个项目涉及到了这方面的内容,所以基于自己已学的知识,在网上搜索了许多相关的资料,这些资料各有可取之处,但相对来说比较杂散,不够凝练.在经过一番整理及代码实践 ...

  9. VC6.0 MFC 单文档 五子棋游戏 基础入门

    五子棋游戏 一.整体思路 1.目的:通过五子棋,掌握面向对象的思想,这是我们的目的.提升分析问题.解决问题的能力,在做项目之前要有一个系统的思路,第一步干什么,第二步干什么-- 2.思路:拿到这个问题 ...

  10. MFC单文档及其简介

    MFC单文档及其简介 MFC 是一个编程框架 MFC 中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来 建立Windows 下的应用程序.MFC 框架定义了应用程序的轮廓,并 ...

最新文章

  1. java可以入侵电脑系统吗_如何通过tomcat入侵远程计算机系统
  2. mysql基础(一) 编译安装mysql5.5
  3. html一级二级菜单,纯JS添加一级二级菜单的代码
  4. 利用匈牙利算法Hopcroft-Karp算法解决二分图中的最大二分匹配问题 例poj 1469 COURSES...
  5. 给大家推荐一款高逼格的Linux磁盘信息查看工具
  6. c# DateTime常用用法
  7. 点云数据(point cloud)
  8. uniapp小程序生成海报图
  9. 电脑微信不显示好友头像和聊天表情
  10. Shopee虾皮怎么发货?虾皮物流
  11. Win11文件资源管理器有明显卡顿,微软承诺在2022年提高性能
  12. 共模电感 | 磁芯选型
  13. 打字的时候输入空格光标后面一个字被删除了?
  14. 修改ntoskrnl.exe的方法
  15. educoder实训平台python基础综合测试答案_智慧职教mooc2020Python程序设计基础章节测试答案...
  16. word表格跨页多出一根线(三线表)
  17. 【jzoj2182】羊羊吃草
  18. 大数据毕业设计选题推荐(二)
  19. IMMC2019(秋季赛)首批晋级国际赛队伍公布
  20. 通达+oa+php+文件+乱,通达OA 任意文件上传+文件包含导致RCE

热门文章

  1. springmvc02,使用注解
  2. 【mysql】join的用法和修改数据表
  3. 初尝Spring Cloud Config
  4. stl sort分析
  5. ubuntu11.04下如何发送文件到U盘如何添加发送文件到U盘的右键菜单
  6. 各种翻页的效果! FILTER: revealTrans使用说明
  7. flume http source示例讲解
  8. MySQL授权root
  9. mybatis整合spring,使用org.mybatis.spring.mapper.MapperScannerConfigurer扫描出现问题
  10. C#调用C++的DLL所有数据类型转换方式