您的位置:首页 > 运维架构 > 网站架构

TabCtrl控件的使用一则——程序架构

2007-04-06 14:56 411 查看
传统地,Tab控件在切换Tab页时,需要切换页相对应的子窗体的隐藏与显示。单独对子窗体控制,略显繁杂。
本文采取如下思路: 将诸子窗体放到某个承载窗体(比如CWnd类型或者CDialog类型对象)上,在Tab切换时,操控承载窗体的显隐即可达到目的。
又传统地,程序需要维护一个对象数组,每个对象用于维护Tab和承载窗体或子窗体之间的关系;而本文采取如下方法:利用TCITEM结构体的lParam字段存储对应承载窗体的句柄。这样即可构建对应关系。
本例所需类:
1、CMainFrame
2、CChildView : public CWnd
3、CTabCtrl,此处亦作TabCtrl,因大部分属性对于Win32对象亦适用。
4、CDialog 作为承载窗体若干,用CDialog的好处在于,可以直接利用resource template,便于在工程rc中设计控件位置等。

步骤:
一、以VC的Application Wizard创建一个MFC exe-〉SDI-〉no Document/View,那么即具备以上1、2两对象,、
二、在2中定义一成员变量,类型为3、
三、在资源rc中画好对话框,并制定相应resource ID
四、重载2 (CChildView)的LRESULT CChildView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam),处理消息
WM_CREATE,创建TabCtrl、承载窗体,后者在此挂上资源;
WM_NOTIFY,遍历所有与TabCtrl相关的承载窗体,显示当前选中Tab对应的个体,其他个体隐藏;
WM_SIZE,调整TabCtrl的大小以适应CChildView,调整承载窗体的大小适应TabCtrl的Display Area


LRESULT CChildView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)




...{


CRect rt;


TCITEM item;


int j,i;


TCITEM ItemTemp;


// TODO: Add your specialized code here and/or call the base class


switch(message)




...{


case WM_CREATE:




if(!m_Tab.Create (/**//*TCS_OWNERDRAWFIXED|*/TCS_TABS|WS_CHILD|WS_VISIBLE, CRect(0,0,0,0),this,IDC_TABCTRL))




...{


MessageBox(_T("Tab creation failed!"),_T("Error"));


}




//FormView1.Create (IDD_FORMVIEW1,this);


//FormView0.Create (IDD_FORMVIEW,this);

FormView1.Create (IDD_FORMVIEW1,&m_Tab);//MUST like this, if do like above, will occur some problem described in comment1


FormView0.Create (IDD_FORMVIEW,&m_Tab);//一定要这么做,若如上面代码,则会引发评论一所述及的问题






item.mask = TCIF_TEXT|TCIF_PARAM ;




item.pszText=_T("第一个");


item.lParam =(LPARAM)FormView0.m_hWnd ;


m_Tab.InsertItem (0,&item);




item.pszText=_T("第二个");


item.lParam =(LPARAM)FormView1.m_hWnd ;


m_Tab.InsertItem (1,&item);




break;




case WM_NOTIFY:


if(IDC_TABCTRL == (int) wParam)




...{


LPNMHDR pnmh=(LPNMHDR) lParam;


if (pnmh->code ==TCN_SELCHANGE )




...{


j=m_Tab.GetCurSel ();


//if(ItemTemp.lParam!=NULL)


PointA: if(m_Tab.GetItem(j,&ItemTemp))


if(IsWindow((HWND)ItemTemp.lParam))




...{


::ShowWindow((HWND)ItemTemp.lParam,SW_SHOW);


Invalidate();//important!! Avoid some dialog unshowed!


PointB: }


for(i=0;i<m_Tab.GetItemCount ();i++)




...{


if(m_Tab.GetCurSel ()==i)


continue;




if(m_Tab.GetItem (i,&ItemTemp))


if(IsWindow((HWND)ItemTemp.lParam))


::ShowWindow((HWND)ItemTemp.lParam,SW_HIDE);


}
PointC:


}


}




break;




case WM_SIZE:


GetClientRect(rt);


rt.DeflateRect (100,100,100,100);


m_Tab.MoveWindow (rt);




m_Tab.GetWindowRect (rt);


ScreenToClient(rt);


m_Tab.AdjustRect (FALSE,rt);




for(i=0;i<m_Tab.GetItemCount ();i++)




...{




m_Tab.GetItem (/**//*m_Tab.GetCurSel ()*/i,&ItemTemp);


if(ItemTemp.lParam!=NULL && ::IsWindow ((HWND)ItemTemp.lParam))


::MoveWindow(((HWND)(ItemTemp.lParam)),rt.left ,rt.top ,rt.Width (),rt.Height(),FALSE);


}


break;




case WM_LBUTTONDBLCLK:




item.mask = TCIF_TEXT;


item.pszText=_T("第三个");


//item.lParam =;


m_Tab.InsertItem (m_Tab.GetItemCount (),&item);


break;




case WM_RBUTTONDBLCLK:


m_Tab.DeleteItem (m_Tab.GetItemCount ()-1);


break;


}


return CWnd ::WindowProc(message, wParam, lParam);


}



那么在模拟单击某个Tab页的动作,代码为:
m_wndView.m_Tab.SetCurSel(1);
NMHDR nh;
nh.hwndFrom=m_wndView.m_Tab.m_hWnd;
nh.idFrom=IDC_TABCTRL;
nh.code=TCN_SELCHANGE;
m_wndView.SendMessage(WM_NOTIFY,IDC_TABCTRL,(LPARAM)&nh);

假设动态地创建了多个Tab,其中一些可能对应某个Dialog派生类,那么如果需要查找某个特定的Dialog就必须仰赖MFC的RTTI和Dialog某甄别字段。如下例展示查找一个Dialog并将其杀掉,将界面切换至第1个(zero based index)Tab。
void CMainFrame::KillDialingPad(CString StrContactName)
{
CWnd* pWnd;
HWND hWnd;
TCITEM ItemTemp;
int i=0;
for (i=1;i<m_wndView.m_Tab.GetItemCount();i++)//start from 1, avoid searching from the CONTACT LIST
{
m_wndView.m_Tab.GetItem(i,&ItemTemp);
hWnd=(HWND)ItemTemp.lParam;
pWnd=CWnd::FromHandle(hWnd);//avoid to bring a new CWnd object;
if (pWnd->IsKindOf(RUNTIME_CLASS(CDialingBoxDlg)))
{
if(((CDialingBoxDlg *)pWnd)->m_StrContactName==StrContactName)
break;
}
}

if(i<m_wndView.m_Tab.GetItemCount())//found
{
pWnd->DestroyWindow();
delete pWnd;
pWnd=NULL;
m_wndView.m_Tab.DeleteItem(i);
}

m_wndView.m_Tab.SetCurSel(1);
NMHDR nh;
nh.hwndFrom=m_wndView.m_Tab.m_hWnd;
nh.idFrom=IDC_TABCTRL;
nh.code=TCN_SELCHANGE;
m_wndView.SendMessage(WM_NOTIFY,IDC_TABCTRL,(LPARAM)&nh);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: