IE瀏覽器的多標(biāo)簽?zāi)J揭讶遮呎紦?jù)瀏覽器市場(chǎng)的主流模式?;貞汭E6.0時(shí)代的單文檔多實(shí)例年代,那瀏覽多網(wǎng)頁是何等的痛苦。原本有限的空間就要被那些煩瑣的網(wǎng)頁所占據(jù),要從這些煩瑣的網(wǎng)頁中切換到自己目的網(wǎng)頁更是何等的不便?,F(xiàn)在很多第三方IE瀏覽器對(duì)IE瀏覽器所顯示出來的弊病虎視眈眈許久,多標(biāo)簽瀏覽器也應(yīng)運(yùn)而生。遨游、世界之窗、TT等如今都是拜多標(biāo)簽瀏覽器之福,早早占領(lǐng)了市場(chǎng),占據(jù)了一席之地。而如今微軟也知道自己瀏覽器帝國(guó)的根基也岌岌可危,其怎可示弱,IE7.0也就相繼問世。
IE多標(biāo)簽欄的主要特點(diǎn)是:?jiǎn)螌?shí)例多文檔模式,文檔間的切換是通過標(biāo)簽實(shí)現(xiàn)。一個(gè)實(shí)例就可以包容多個(gè)文檔,察看網(wǎng)頁是何其的方便。
構(gòu)成IE多標(biāo)簽欄的界面要素包括工具欄和標(biāo)簽。工具欄采用CDialogBar做為標(biāo)簽的容器,標(biāo)簽采用自繪按鈕來實(shí)現(xiàn),CtabCtrl做標(biāo)簽不容易實(shí)現(xiàn)自繪(自繪的時(shí)候有灰色的border出現(xiàn))。
在CDialogBar的寬度發(fā)生改變的時(shí)候,其上面的按鈕標(biāo)簽應(yīng)做適當(dāng)?shù)恼{(diào)整。當(dāng)然在足夠容納按鈕標(biāo)簽的時(shí),可以給一個(gè)設(shè)定值。若空間有限的話,則就適當(dāng)縮小標(biāo)簽的大小,其上的內(nèi)容通過提示框提示。所以只要響應(yīng)CdialogBar的WM_SIZE來調(diào)整標(biāo)簽的擺放方式。至于標(biāo)簽欄的自繪通過響應(yīng)WM_PAINT消息就可以做到。
void CTabBar::OnSize(UINT nType, int cx, int cy)
{
CDialogBar::OnSize(nType, cx, cy);
CRect rcClient;
GetClientRect(rcClient);
int nBarWidth = rcClient.Width();
int nTabWidth = nBarWidth-120;
int nCount = m_ptrArray.GetCount();
if(nCount*m_nWidth>nTabWidth)
{
//平均分配位置
int nAveWidth = nTabWidth*1.0/nCount;
for(int i=0; i {
CRect rcBtn;
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
pTabInfo->pTabButton->GetClientRect(&rcBtn);
pTabInfo->pTabButton->MoveWindow(nAveWidth*i,
(rcClient.Height()-rcBtn.Height())/2,
nAveWidth,
m_nHeight,
FALSE);
}
}
else
{
//固定大小
for(int i=0; i {
CRect rcBtn;
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
pTabInfo->pTabButton->GetClientRect(&rcBtn);
pTabInfo->pTabButton->MoveWindow(m_nWidth*i,
(rcClient.Height()-rcBtn.Height())/2,
m_nWidth, m_nHeight, FALSE);
}
}
Invalidate();
}當(dāng)選中標(biāo)簽后,鼠標(biāo)移動(dòng)到標(biāo)簽右邊的時(shí)候,則會(huì)出現(xiàn)一個(gè)關(guān)閉按鈕,用來關(guān)閉文檔。所以這個(gè)里面涉及到按鈕的自繪原理,這樣的文章比較多,這里就不多做說明。不過俺想提個(gè)問題,對(duì)于按鈕的0nDrawItem與DrawItem,是否有什么區(qū)別,如果將下面換成OnDrawItem消息響應(yīng)函數(shù)是否可以?實(shí)在不懂得的話可以去跟蹤C(jī)Button的源代碼,就知道了。void CTabButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
CRect rcItem=lpDrawItemStruct->rcItem;
HWND hWnd=lpDrawItemStruct->hwndItem;
UINT nState=lpDrawItemStruct->itemState;
HDC hDC=lpDrawItemStruct->hDC;
CDC dc;
dc.Attach(hDC);
dc.SetBkMode(TRANSPARENT);
CString strTitle;
GetWindowText(strTitle);
if (m_bSel)
{
if(!m_bmpBmpBkgnd.IsNull())
{
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(0,0,10, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*2, 0, m_bmpBmpBkgnd.GetWidth()/4*2+10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(4,0,rcItem.right-10, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*2+10, 0, m_bmpBmpBkgnd.GetWidth()/4*3-10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(rcItem.right-10,0,rcItem.right, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*3-10, 0, m_bmpBmpBkgnd.GetWidth()/4*3, m_bmpBmpBkgnd.GetHeight()));
}
if(!m_bmpIcon.IsNull())
{
m_bmpIcon.Draw(dc.m_hDC, CRect(4, 4, 4+m_bmpIcon.GetWidth(), 4+m_bmpIcon.GetHeight()), CRect(0,0,m_bmpIcon.GetWidth(), m_bmpIcon.GetHeight()));
}
CRect rcLabel;
rcLabel.left = rcItem.left+4*2+16;
rcLabel.top = rcItem.top;
rcLabel.right = rcItem.right - (4*2+16);
rcLabel.bottom = rcItem.bottom;
dc.SetTextColor(RGB(0xff,0xff,0xff));
dc.DrawText(strTitle, &rcLabel, DT_SINGLELINE | DT_VCENTER | DT_WORD_ELLIPSIS);
if(m_bOverCloseButton)
{
if(!m_bmpClose.IsNull())
{
m_bmpClose.Draw(dc.m_hDC,
CRect(rcItem.Width()-m_bmpClose.GetWidth()/3-5,
(rcItem.Height()-m_bmpClose.GetHeight())/2,rcItem.Width()-2,
(rcItem.Height()-m_bmpClose.GetHeight())/2+m_bmpClose.GetHeight()),
CRect(m_bmpClose.GetWidth()/3, 0, m_bmpClose.GetWidth()/3*2, m_bmpClose.GetHeight()));
}
}
else
{
if(!m_bmpClose.IsNull())
{
m_bmpClose.Draw(dc.m_hDC, CRect(rcItem.Width()-m_bmpClose.GetWidth()/3-5,
(rcItem.Height()-m_bmpClose.GetHeight())/2,rcItem.Width()-2,
(rcItem.Height()-m_bmpClose.GetHeight())/2+m_bmpClose.GetHeight()),
CRect(0, 0, m_bmpClose.GetWidth()/3, m_bmpClose.GetHeight()));
}
}
} else
{
if(!m_bmpBmpBkgnd.IsNull())
{
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(0,0,10, m_bmpBmpBkgnd.GetHeight()),
CRect(0, 0, 10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(10,0,rcItem.right-10, m_bmpBmpBkgnd.GetHeight()),
CRect(10, 0, m_bmpBmpBkgnd.GetWidth()/4-10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(rcItem.right-10,0,rcItem.right, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4-10, 0, m_bmpBmpBkgnd.GetWidth()/4, m_bmpBmpBkgnd.GetHeight()));
}
if(!m_bmpIcon.IsNull())
{
m_bmpIcon.Draw(dc.m_hDC, CRect(4, 4, 4+m_bmpIcon.GetWidth(), 4+m_bmpIcon.GetHeight()), CRect(0,0,m_bmpIcon.GetWidth(), m_bmpIcon.GetHeight()));
}
CRect rcLabel;
rcLabel.left = rcItem.left + 4*2+16;
rcLabel.top = rcItem.top;
rcLabel.right = rcItem.right - (4*2+16);
rcLabel.bottom = rcItem.bottom;
dc.SetTextColor(RGB(0xff,0xff,0xff));
dc.DrawText(strTitle, &rcLabel, DT_SINGLELINE | DT_VCENTER | DT_WORD_ELLIPSIS);
}
dc.Detach();
}值得注意的是,CdialogBar的按鈕命令消息是先發(fā)給主框架窗口處理,如果主框架窗口沒有為其提供相應(yīng)的響應(yīng)函數(shù),則命令的消息路由就中斷,按鈕則會(huì)出現(xiàn)disabled狀態(tài)?;蛘吣阋部梢垣@取到這個(gè)命令消息后,重載OnCmdMsg再將這個(gè)命令消息發(fā)往其他窗口。然后就可以通過按鈕的消息反射機(jī)制,使按鈕能夠自己處理自己的事件,比較貼近面向?qū)ο蟮脑O(shè)計(jì)。由于命令消息響應(yīng)函數(shù)里面沒有將發(fā)命令消息的對(duì)象傳到CtabBar中,這樣CtabBar如果靠按鈕ID來設(shè)置主鍵標(biāo)志一個(gè)標(biāo)簽按鈕的話,那那就會(huì)占用很多的ID。本設(shè)計(jì)并沒有這么做,在給ctabbar提供相的相關(guān)通知,是在里面發(fā)送一個(gè)通知消息到ctabbar的,其中LPARAM就可以保存按鈕標(biāo)簽對(duì)象。這樣標(biāo)簽欄就可以實(shí)現(xiàn)對(duì)底下標(biāo)簽的操作。以下就是按鈕發(fā)送通知消息給標(biāo)簽欄的實(shí)現(xiàn)細(xì)節(jié)。#define NM_TBSEL WM_USER+1
void CTabButton::OnBnClicked()
{
CTabBar* pTabBar = (CTabBar*)GetParent();
pTabBar->SendMessage(NM_TBSEL, 0, (LPARAM)this);
}
HRESULT CTabBar::OnNmTbSel(WPARAM wParam, LPARAM lParam)
{
CTabButton* pTabButton = (CTabButton*)lParam;
SetCurSel(pTabButton);
CChildFrame* pChildFrame = GetChildFrameByTabButton(pTabButton);
pChildFrame->MDIActivate();
pChildFrame->MDIMaximize();
return TRUE;
}總體的設(shè)計(jì)思想是:標(biāo)簽欄應(yīng)該用一個(gè)數(shù)組來存放標(biāo)簽,但由于一個(gè)標(biāo)簽又是跟一個(gè)CchildFrame一一對(duì)應(yīng)起來,兩者應(yīng)該可以相互訪問,效率比較高的話可以用cmap映射來實(shí)現(xiàn)。本設(shè)計(jì)采用一個(gè)結(jié)構(gòu)體來存儲(chǔ)這兩個(gè)關(guān)鍵要素。typedef struct _TABINFO
{
CChildFrame* pChildFrame;
CTabButton* pTabButton;
}TABINFO, *PTABINFO;這個(gè)標(biāo)簽欄就可以通過一個(gè)數(shù)組維護(hù)這樣的結(jié)構(gòu)。至于CchildFrame和CtabButton的對(duì)應(yīng)關(guān)系可以通過下面來實(shí)現(xiàn),不過是個(gè)輪詢過程,的確很浪費(fèi)時(shí)間。CTabButton*CTabBar::GetTabButtonByChildFrame(CChildFrame* pChildFrame)
{
int nCount = m_ptrArray.GetCount();
for(int i=0; i {
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
if(pTabInfo->pChildFrame==pChildFrame)
{
return pTabInfo->pTabButton;
}
else
{
continue;
}
}
return NULL;
}
CChildFrame*CTabBar::GetChildFrameByTabButton(CTabButton* pTabButton)
{
int nCount = m_ptrArray.GetCount();
for(int i=0; i {
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
if(pTabInfo->pTabButton==pTabButton)
{
return pTabInfo->pChildFrame;
}
else
{
continue;
}
}
return NULL;
}
IE多標(biāo)簽欄的主要特點(diǎn)是:?jiǎn)螌?shí)例多文檔模式,文檔間的切換是通過標(biāo)簽實(shí)現(xiàn)。一個(gè)實(shí)例就可以包容多個(gè)文檔,察看網(wǎng)頁是何其的方便。
構(gòu)成IE多標(biāo)簽欄的界面要素包括工具欄和標(biāo)簽。工具欄采用CDialogBar做為標(biāo)簽的容器,標(biāo)簽采用自繪按鈕來實(shí)現(xiàn),CtabCtrl做標(biāo)簽不容易實(shí)現(xiàn)自繪(自繪的時(shí)候有灰色的border出現(xiàn))。
在CDialogBar的寬度發(fā)生改變的時(shí)候,其上面的按鈕標(biāo)簽應(yīng)做適當(dāng)?shù)恼{(diào)整。當(dāng)然在足夠容納按鈕標(biāo)簽的時(shí),可以給一個(gè)設(shè)定值。若空間有限的話,則就適當(dāng)縮小標(biāo)簽的大小,其上的內(nèi)容通過提示框提示。所以只要響應(yīng)CdialogBar的WM_SIZE來調(diào)整標(biāo)簽的擺放方式。至于標(biāo)簽欄的自繪通過響應(yīng)WM_PAINT消息就可以做到。
void CTabBar::OnSize(UINT nType, int cx, int cy)
{
CDialogBar::OnSize(nType, cx, cy);
CRect rcClient;
GetClientRect(rcClient);
int nBarWidth = rcClient.Width();
int nTabWidth = nBarWidth-120;
int nCount = m_ptrArray.GetCount();
if(nCount*m_nWidth>nTabWidth)
{
//平均分配位置
int nAveWidth = nTabWidth*1.0/nCount;
for(int i=0; i
CRect rcBtn;
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
pTabInfo->pTabButton->GetClientRect(&rcBtn);
pTabInfo->pTabButton->MoveWindow(nAveWidth*i,
(rcClient.Height()-rcBtn.Height())/2,
nAveWidth,
m_nHeight,
FALSE);
}
}
else
{
//固定大小
for(int i=0; i
CRect rcBtn;
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
pTabInfo->pTabButton->GetClientRect(&rcBtn);
pTabInfo->pTabButton->MoveWindow(m_nWidth*i,
(rcClient.Height()-rcBtn.Height())/2,
m_nWidth, m_nHeight, FALSE);
}
}
Invalidate();
}當(dāng)選中標(biāo)簽后,鼠標(biāo)移動(dòng)到標(biāo)簽右邊的時(shí)候,則會(huì)出現(xiàn)一個(gè)關(guān)閉按鈕,用來關(guān)閉文檔。所以這個(gè)里面涉及到按鈕的自繪原理,這樣的文章比較多,這里就不多做說明。不過俺想提個(gè)問題,對(duì)于按鈕的0nDrawItem與DrawItem,是否有什么區(qū)別,如果將下面換成OnDrawItem消息響應(yīng)函數(shù)是否可以?實(shí)在不懂得的話可以去跟蹤C(jī)Button的源代碼,就知道了。void CTabButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
CRect rcItem=lpDrawItemStruct->rcItem;
HWND hWnd=lpDrawItemStruct->hwndItem;
UINT nState=lpDrawItemStruct->itemState;
HDC hDC=lpDrawItemStruct->hDC;
CDC dc;
dc.Attach(hDC);
dc.SetBkMode(TRANSPARENT);
CString strTitle;
GetWindowText(strTitle);
if (m_bSel)
{
if(!m_bmpBmpBkgnd.IsNull())
{
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(0,0,10, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*2, 0, m_bmpBmpBkgnd.GetWidth()/4*2+10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(4,0,rcItem.right-10, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*2+10, 0, m_bmpBmpBkgnd.GetWidth()/4*3-10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(rcItem.right-10,0,rcItem.right, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4*3-10, 0, m_bmpBmpBkgnd.GetWidth()/4*3, m_bmpBmpBkgnd.GetHeight()));
}
if(!m_bmpIcon.IsNull())
{
m_bmpIcon.Draw(dc.m_hDC, CRect(4, 4, 4+m_bmpIcon.GetWidth(), 4+m_bmpIcon.GetHeight()), CRect(0,0,m_bmpIcon.GetWidth(), m_bmpIcon.GetHeight()));
}
CRect rcLabel;
rcLabel.left = rcItem.left+4*2+16;
rcLabel.top = rcItem.top;
rcLabel.right = rcItem.right - (4*2+16);
rcLabel.bottom = rcItem.bottom;
dc.SetTextColor(RGB(0xff,0xff,0xff));
dc.DrawText(strTitle, &rcLabel, DT_SINGLELINE | DT_VCENTER | DT_WORD_ELLIPSIS);
if(m_bOverCloseButton)
{
if(!m_bmpClose.IsNull())
{
m_bmpClose.Draw(dc.m_hDC,
CRect(rcItem.Width()-m_bmpClose.GetWidth()/3-5,
(rcItem.Height()-m_bmpClose.GetHeight())/2,rcItem.Width()-2,
(rcItem.Height()-m_bmpClose.GetHeight())/2+m_bmpClose.GetHeight()),
CRect(m_bmpClose.GetWidth()/3, 0, m_bmpClose.GetWidth()/3*2, m_bmpClose.GetHeight()));
}
}
else
{
if(!m_bmpClose.IsNull())
{
m_bmpClose.Draw(dc.m_hDC, CRect(rcItem.Width()-m_bmpClose.GetWidth()/3-5,
(rcItem.Height()-m_bmpClose.GetHeight())/2,rcItem.Width()-2,
(rcItem.Height()-m_bmpClose.GetHeight())/2+m_bmpClose.GetHeight()),
CRect(0, 0, m_bmpClose.GetWidth()/3, m_bmpClose.GetHeight()));
}
}
} else
{
if(!m_bmpBmpBkgnd.IsNull())
{
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(0,0,10, m_bmpBmpBkgnd.GetHeight()),
CRect(0, 0, 10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(10,0,rcItem.right-10, m_bmpBmpBkgnd.GetHeight()),
CRect(10, 0, m_bmpBmpBkgnd.GetWidth()/4-10, m_bmpBmpBkgnd.GetHeight()));
m_bmpBmpBkgnd.Draw(dc.m_hDC, CRect(rcItem.right-10,0,rcItem.right, m_bmpBmpBkgnd.GetHeight()),
CRect(m_bmpBmpBkgnd.GetWidth()/4-10, 0, m_bmpBmpBkgnd.GetWidth()/4, m_bmpBmpBkgnd.GetHeight()));
}
if(!m_bmpIcon.IsNull())
{
m_bmpIcon.Draw(dc.m_hDC, CRect(4, 4, 4+m_bmpIcon.GetWidth(), 4+m_bmpIcon.GetHeight()), CRect(0,0,m_bmpIcon.GetWidth(), m_bmpIcon.GetHeight()));
}
CRect rcLabel;
rcLabel.left = rcItem.left + 4*2+16;
rcLabel.top = rcItem.top;
rcLabel.right = rcItem.right - (4*2+16);
rcLabel.bottom = rcItem.bottom;
dc.SetTextColor(RGB(0xff,0xff,0xff));
dc.DrawText(strTitle, &rcLabel, DT_SINGLELINE | DT_VCENTER | DT_WORD_ELLIPSIS);
}
dc.Detach();
}值得注意的是,CdialogBar的按鈕命令消息是先發(fā)給主框架窗口處理,如果主框架窗口沒有為其提供相應(yīng)的響應(yīng)函數(shù),則命令的消息路由就中斷,按鈕則會(huì)出現(xiàn)disabled狀態(tài)?;蛘吣阋部梢垣@取到這個(gè)命令消息后,重載OnCmdMsg再將這個(gè)命令消息發(fā)往其他窗口。然后就可以通過按鈕的消息反射機(jī)制,使按鈕能夠自己處理自己的事件,比較貼近面向?qū)ο蟮脑O(shè)計(jì)。由于命令消息響應(yīng)函數(shù)里面沒有將發(fā)命令消息的對(duì)象傳到CtabBar中,這樣CtabBar如果靠按鈕ID來設(shè)置主鍵標(biāo)志一個(gè)標(biāo)簽按鈕的話,那那就會(huì)占用很多的ID。本設(shè)計(jì)并沒有這么做,在給ctabbar提供相的相關(guān)通知,是在里面發(fā)送一個(gè)通知消息到ctabbar的,其中LPARAM就可以保存按鈕標(biāo)簽對(duì)象。這樣標(biāo)簽欄就可以實(shí)現(xiàn)對(duì)底下標(biāo)簽的操作。以下就是按鈕發(fā)送通知消息給標(biāo)簽欄的實(shí)現(xiàn)細(xì)節(jié)。#define NM_TBSEL WM_USER+1
void CTabButton::OnBnClicked()
{
CTabBar* pTabBar = (CTabBar*)GetParent();
pTabBar->SendMessage(NM_TBSEL, 0, (LPARAM)this);
}
HRESULT CTabBar::OnNmTbSel(WPARAM wParam, LPARAM lParam)
{
CTabButton* pTabButton = (CTabButton*)lParam;
SetCurSel(pTabButton);
CChildFrame* pChildFrame = GetChildFrameByTabButton(pTabButton);
pChildFrame->MDIActivate();
pChildFrame->MDIMaximize();
return TRUE;
}總體的設(shè)計(jì)思想是:標(biāo)簽欄應(yīng)該用一個(gè)數(shù)組來存放標(biāo)簽,但由于一個(gè)標(biāo)簽又是跟一個(gè)CchildFrame一一對(duì)應(yīng)起來,兩者應(yīng)該可以相互訪問,效率比較高的話可以用cmap映射來實(shí)現(xiàn)。本設(shè)計(jì)采用一個(gè)結(jié)構(gòu)體來存儲(chǔ)這兩個(gè)關(guān)鍵要素。typedef struct _TABINFO
{
CChildFrame* pChildFrame;
CTabButton* pTabButton;
}TABINFO, *PTABINFO;這個(gè)標(biāo)簽欄就可以通過一個(gè)數(shù)組維護(hù)這樣的結(jié)構(gòu)。至于CchildFrame和CtabButton的對(duì)應(yīng)關(guān)系可以通過下面來實(shí)現(xiàn),不過是個(gè)輪詢過程,的確很浪費(fèi)時(shí)間。CTabButton*CTabBar::GetTabButtonByChildFrame(CChildFrame* pChildFrame)
{
int nCount = m_ptrArray.GetCount();
for(int i=0; i
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
if(pTabInfo->pChildFrame==pChildFrame)
{
return pTabInfo->pTabButton;
}
else
{
continue;
}
}
return NULL;
}
CChildFrame*CTabBar::GetChildFrameByTabButton(CTabButton* pTabButton)
{
int nCount = m_ptrArray.GetCount();
for(int i=0; i
TABINFO* pTabInfo = (TABINFO*)m_ptrArray.GetAt(i);
if(pTabInfo->pTabButton==pTabButton)
{
return pTabInfo->pChildFrame;
}
else
{
continue;
}
}
return NULL;
}