MFC的SDI程序,重载CMainFrame类的OnCreateClient函数,使用一个标签视:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
if(!m_wndTab.Create(WS_BORDER | WS_CHILD | WS_VISIBLE | TCS_TABS | TCS_HOTTRACK,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST))
{
TRACE0("Failed to create TabContainer!\n");
return FALSE;
}
//m_wndTab.ModifyStyleEx(0, WS_EX_CLIENTEDGE);

m_wndTab.AddView(_T("标签页1"), pContext->m_pNewViewClass, pContext, -1);

return TRUE;
}
m_wndTab为一CTabCtrl派生类的实例:
.h文件内容为:
class CTabViewContainer : public CTabCtrl
{
DECLARE_DYNCREATE(CTabViewContainer)public:
CTabViewContainer();
virtual ~CTabViewContainer(); BOOL AddView(LPCTSTR pszText, CRuntimeClass *pRT, CCreateContext *pContext = NULL, int nImage = -1);
void ChangeView(int nIndex);
CWnd * GetSelView(void);protected:
DECLARE_MESSAGE_MAP()public:
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTcnSelchange(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnTcnSelchanging(NMHDR *pNMHDR, LRESULT *pResult);
};
.c文件内容为:
IMPLEMENT_DYNCREATE(CTabViewContainer, CTabCtrl)
CTabViewContainer::CTabViewContainer()
{
}CTabViewContainer::~CTabViewContainer()
{
}
BEGIN_MESSAGE_MAP(CTabViewContainer, CTabCtrl)
ON_WM_SIZE()
ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnTcnSelchange)
ON_NOTIFY_REFLECT(TCN_SELCHANGING, OnTcnSelchanging)
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()// CTabViewContainer 消息处理程序// 添加一个视图页
BOOL CTabViewContainer::AddView(LPCTSTR pszText, CRuntimeClass *pRT, CCreateContext *pContext, int nImage)
{
int nIndex = this->GetItemCount();
CSize sz(40, 20);
this->SetItemSize(sz); TCITEM tci;
tci.mask = TCIF_TEXT | TCIF_PARAM;
if (nImage != -1)
tci.mask |= TCIF_IMAGE; CWnd *pView = (CWnd *)pRT->CreateObject();
pView->CreateEx(WS_EX_CLIENTEDGE, NULL, NULL, WS_CHILD | WS_VISIBLE,
CRect(0, 0, 0, 0), this, nIndex, pContext); tci.pszText = (char *)pszText;
tci.lParam = (LPARAM)pView;
tci.iImage = nImage; this->InsertItem(nIndex, &tci);
return TRUE;
}// 切换视图
void CTabViewContainer::ChangeView(int nIndex)
{
ASSERT(nIndex>=0);
int nCount=GetItemCount();
ASSERT(nIndex<nCount); int nSel=GetCurSel();
TCITEM tci;
CRect rc;
tci.mask = TCIF_PARAM;
if(nSel!=nIndex)
{
this->GetItem(nSel, &tci);
CWnd *pView = (CWnd *)tci.lParam;
pView->SetWindowPos(NULL, 0, 0, 10, 10, SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOACTIVATE);
}
this->GetItem(nIndex, &tci);
CWnd *pView = (CWnd *)tci.lParam;
this->GetClientRect(&rc);
rc.top = 24;
pView->SetWindowPos(&CWnd::wndTop, 0, 24, rc.right, rc.bottom - 24, SWP_SHOWWINDOW);
SetCurSel(nIndex);
}// 得到当前选中的视图索引
CWnd * CTabViewContainer::GetSelView(void)
{
int nSel = GetCurSel();
TCITEM tci;
CRect rc;
tci.mask = TCIF_PARAM;
GetItem(nSel, &tci);
return ((CWnd *)tci.lParam);
}// 改变尺寸时,需要挪动子窗口
void CTabViewContainer::OnSize(UINT nType, int cx, int cy)
{
CTabCtrl::OnSize(nType, cx, cy);
CRect rc(0, 24, cx, cy);
int nSel = this->GetCurSel();
if (nSel >= 0)
{
TCITEM tci;
tci.mask = TCIF_PARAM;
this->GetItem(nSel, &tci);
CWnd *pView = (CWnd *)tci.lParam;
pView->MoveWindow(&rc);
}
}void CTabViewContainer::OnTcnSelchange(NMHDR *pNMHDR, LRESULT *pResult)
{
int nSel = this->GetCurSel();
ChangeView(nSel);
*pResult = 0;
}void CTabViewContainer::OnTcnSelchanging(NMHDR *pNMHDR, LRESULT *pResult)
{
int nSel = this->GetCurSel();
TCITEM tci;
tci.mask = TCIF_PARAM;
this->GetItem(nSel, &tci);
CWnd *pView = (CWnd *)tci.lParam;
pView->SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOACTIVATE);
*pResult = 0;
}问题在于使用标签视后,在Doc和View类中新添加的菜单消息处理命令是灰色的,只能在MainFrame类中添加有效。更奇怪的是在View中只要鼠标左单击一下,Doc和View类中新添加的菜单消息处理命令就有效了。
请各位高手帮忙解决这个问题,高分重谢!!解决后开贴另加分。

解决方案 »

  1.   

    编译环境是windows2000,vc++.net2002
      

  2.   

    在view中添加命令响应,当然需要视图处于激活状态了
      

  3.   

    而Doc类中的命令响应,也需要视图处于激活状态下吗?我看过同样的一个使用这个TabContainer类的程序,虽然是VC6的,但里面没有找到关于激活视图状态的程序行。
      

  4.   

    我在CTabViewContainer类的AddView函数中加入了pView->SetFocus();还是不行,看来好像不是输入焦点的问题吧?为什么在View类的客户区点击一下鼠标,菜单就由灰色变成有效了?
      

  5.   

    在CTabViewContainer类的AddView函数中加入了pView->SetFocus()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    这又有什么用呢?首先pView是局部变量,连成员变量都不是
      

  6.   

    你跟踪一下CFrameWnd::OnCreateClient(lpcs, pContext)就知道了:
    不过也是调用了CreateView(pContext, AFX_IDW_PANE_FIRST);
    函数中也只是这两句:
    CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
    pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0), this, nID, pContext)
    pView也不过是局部变量。
      

  7.   

    用classwizard映射消息时
    从ClassInfo标签选择MessageFilter的类型
      

  8.   

    我刚才试了一下,我只在CMainFrame::OnCreateClient中改动一点就好使了
    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
    {
    // TODO: Add your specialized code here and/or call the base class
      if(!m_tabWnd.Create(WS_BORDER | WS_CHILD | WS_VISIBLE | TCS_TABS | TCS_HOTTRACK,
    CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST))
      {
    TRACE0("Failed to create TabContainer!\n");
    return FALSE;
      }
      m_tabWnd.AddView(_T("标签页1");  SetActiveView((CView*)m_tabWnd.GetSelView(),FALSE); /*****addition******/
      return TRUE;
    // return CFrameWnd::OnCreateClient(lpcs, pContext);
    }
    你也试试,看怎么样??
      

  9.   

    笔误
    应该是:m_tabWnd.AddView(_T("标签页1"), pContext->m_pNewViewClass, pContext, -1);
      

  10.   

    调试通过,感谢ing!!!!
    不过我还是奇怪我手头相关的另一个程序,也是用了同样的一个类,但我找遍了也没有找到关于setactiveview的语句,不知道它是怎么回事就一直没有我这样的状况,好晕!