MDI中重新排列view视口(子窗口)

来源:互联网 发布:腾讯来电软件怎么回事 编辑:程序博客网 时间:2024/05/01 16:59

这几天的任务是:在一个MDI应用程序中打开多个view(子窗口),要求通过菜单实现子窗口的水平、垂直和重叠排列,在实现之前,先看一下效果图吧。


这个功能在VC++6.0中可以通过添加菜单项后将在菜单项的ID设置为指定ID,即可由系统自动实现这些功能,不需要添加事件处理函数(ID_WINDOW_CASCADE , ID_WINDOW_HORZ , ID_WINDOW_VERT),但是在VS2010中按照添加缺省ID的方法却无法实现这些功能。前几天一直在想怎么让系统自动实现这些功能,或者调用现成的API函数实现,但是都没研究出想要的效果,昨天又看了一下VC++6.0的实现效果,才想出一个简单的实现思路,其实水平排列和垂直排列也就是在重叠排列的基础上,重新设定一下窗口的大小和位置而已,我们可以用MoveWindow来实现这个功能,而由默认的排列方式变成重叠的排列方式,需要用到EnableMDITabbedGroups,将第一个参数设为FALSE即可,而从重叠的排列方式转换为默认的排列方式时,将第一个参数设置为TRUE就行。

另一个问题就是,在重叠的排列方式下如何遍历所有的子窗口,逐个设置各个子窗口的位置,这里主要用到连个函数,MDIGetactive和MDINext,获取活动子窗口,然后依次获取其他窗口,具体看下面的代码吧。


void CMainFrame::OnWindowTileHorz(){ArrangeChildwindow(TRUE);}void CMainFrame::OnWindowCascade(){// TODO: Add your command handler code here//先将窗口转换为重叠排列CMDITabInfo  params; EnableMDITabbedGroups(FALSE,params);//获取已打开view窗口个数int count = GetOpenedViewCount();CRect rectClient;GetClientRect(&rectClient);if (count){int temp = 0;CMDIFrameWnd* pFrame = (CMDIFrameWnd*)AfxGetMainWnd();if(pFrame){CMDIChildWnd* pOldChildFrame = pFrame->MDIGetActive();CMDIChildWnd* pChildFrame = pOldChildFrame;if(pChildFrame){do {MDIActivate(pChildFrame);::MoveWindow(pChildFrame->GetSafeHwnd(),rectClient.left +(count -temp-1)*rectClient.Width()*0.05,rectClient.top+(count -temp-1)*rectClient.Height()*0.05,rectClient.Width()*0.7,rectClient.Height()*0.7,TRUE);pFrame->MDINext();pChildFrame = pFrame->MDIGetActive();temp++;}while (pChildFrame != pOldChildFrame);}}}}void CMainFrame::OnWindowTileVer(){// TODO: Add your command handler code hereArrangeChildwindow(FALSE);}//“默认排列”菜单项的响应函数void CMainFrame::OnWindowRecoverry(){// TODO: Add your command handler code hereCMDITabInfo mdiTabParams;mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // set to FALSE to place close button at right of tab areamdiTabParams.m_bActiveTabCloseButton = /*FALSE*/TRUE;// set to TRUE to enable document icons on MDI tabamdiTabParams.m_bTabIcons = /*TRUE*/FALSE;    // set to FALSE to disable auto-coloring of MDI tabsmdiTabParams.m_bAutoColor = TRUE; // set to TRUE to enable the document menu at the right edge of the tab areamdiTabParams.m_bDocumentMenu = TRUE; //set to TRUE to enable the user to change the tabs positions by dragging the tabsmdiTabParams.m_bEnableTabSwap = TRUE;// set to TRUE to give each tab window has a flat framemdiTabParams.m_bFlatFrame = TRUE;// set to TRUE to enable each tab window to display the Close button on the right edge of the tab. mdiTabParams.m_bTabCloseButton = FALSE;// set to TRUE to enable the tabs to display tooltips.mdiTabParams.m_bTabCustomTooltips = TRUE;// Specifies that the tabs labels are located at the top of the pagemdiTabParams.m_tabLocation = CMFCTabCtrl::LOCATION_TOP;EnableMDITabbedGroups(TRUE, mdiTabParams);}void CMainFrame::ArrangeChildwindow(BOOL IsHoriz){//先将窗口转换为重叠排列CMDITabInfo  params; EnableMDITabbedGroups(FALSE,params);//获取已打开view窗口个数int count = GetOpenedViewCount();CRect rectClient;GetClientRect(&rectClient);if (count){int temp = 0;CMDIFrameWnd* pFrame = (CMDIFrameWnd*)AfxGetMainWnd();if(pFrame){CMDIChildWnd* pOldChildFrame = pFrame->MDIGetActive();CMDIChildWnd* pChildFrame = pOldChildFrame;if(pChildFrame){do {if (!IsHoriz)//窗口垂直排列{::MoveWindow(pChildFrame->GetSafeHwnd(),rectClient.left + temp * rectClient.Width()/count,rectClient.top,rectClient.Width()/count,rectClient.Height(),TRUE);}else//窗口水平排列{::MoveWindow(pChildFrame->GetSafeHwnd(),rectClient.left,rectClient.top + temp * rectClient.Height()/count,rectClient.Width(),rectClient.Height()/count,TRUE);}pFrame->MDINext();pChildFrame = pFrame->MDIGetActive();temp++;}while (pChildFrame != pOldChildFrame);}}}}int CMainFrame::GetOpenedViewCount(void){//计算子窗口个数int count = 0;CMDIFrameWnd* pFrame = (CMDIFrameWnd*)AfxGetMainWnd();if(pFrame){CMDIChildWnd* pOldChildFrame = pFrame->MDIGetActive();CMDIChildWnd* pChildFrame = pOldChildFrame;if(pChildFrame){do {pFrame->MDINext();pChildFrame = pFrame->MDIGetActive();count++;}while (pChildFrame != pOldChildFrame);}}return count;}
到这里,已经可以实现上面的功能了。

另外,在我们项目中,主框架客户区左右两边各有一个面板,是的我用上面的方法获取的rect总是不对,后来这么改了下就行了:

CMDIChildWnd *pWndChild = ((CMainFrame*)AfxGetMainWnd())->MDIGetActive();MDIMaximize(pWndChild);pWndChild->GetClientRect(&m_rectClient);MDIRestore(pWndChild);
(先将子窗口最大化,获取rect之后再还原回来)
代码里面可能有的地方写得有些古怪(比如MoveWindow里面的一些参数),但都是遇到问题后一步步改出来的,如果你有简单的方法,欢迎留言指教!

0 0
原创粉丝点击