问题:在父窗口中调用CTabCtrl控件的接口SetItemSel()不起作用。
原因:调试发现,获取GetClientRect不起作用 因为窗口还没创建 要么说用CDialogImpl啊 有个OnInitDialog函数好办些
这个时候只能给一些成员变量 复制 而不能调用函数(例如GetClientRect) 而且就算使用CDialogImpl 也可能出现这种情况
解决方法:
把设置当前选中的item接口分为内部(SetItemSel)、外部(SetCurSelItem)两种。 内部还负责重绘之类的,外部只负责传值。然后再OnPaint里面最后再调用一下内部的SetItemSel即可。当然内部这个接口需要能够判断无效值的情形,例如如果传进来-1,那么None selected.
外部接口:
void CTabBtn::SetCurSelItem(int nItem)// for user to call { m_nCurSel = nItem; }
内部接口:
void CTabBtn::SetItemSel(int nItem, BOOL bSel)//internal interface { if(nItem < 0 || nItem >= m_arrItems.size()) { m_nCurSel = -1; //if nItem == -1, then none is selected. return; } if(m_nItemWidth <= 0 || m_nItemHeight <= 0) return; m_nCurSel = nItem; m_arrItems[m_nCurSel]->bDown = TRUE; if(m_nCurSel == m_nPrevSel) { ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); return; } else { ::SetCursor(::LoadCursor(NULL, IDC_HAND)); //redraw current selected item RECT rcItem; rcItem.left = m_nCurSel * m_nItemWidth; rcItem.right = (m_nCurSel + 1) * m_nItemWidth; rcItem.top = 0; rcItem.bottom = m_nItemHeight; m_arrItems[m_nCurSel]->bDown = (bSel==TRUE); ::PostMessage(GetMsgReceiver(), WM_TABBTN, 0, MAKELPARAM(m_nCurSel, 0)); ::InvalidateRect(m_hWnd, &rcItem, FALSE); //redraw previous selected item if(m_nPrevSel != -1) { rcItem.left = m_nPrevSel * m_nItemWidth; rcItem.right = (m_nPrevSel + 1) * m_nItemWidth; m_arrItems[m_nPrevSel]->bDown = FALSE; ::InvalidateRect(m_hWnd, &rcItem, FALSE); } } m_nPrevSel = m_nCurSel; }
关键一步,让外部传进来的值起作用:
void CTabBtn::DoPaint(CDCHandle dc) { RECT rect; GetClientRect(&rect); Graphics graphics(dc); DrawTabBtn(&graphics); //graphics.DrawRectangle(new Pen(Color::Green), rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top); HRGN hClientRgn = CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 20, 20); SetWindowRgn(hClientRgn, TRUE); SetItemSel(m_nCurSel, TRUE);//here }
最后需要注意的是:保证原子操作,此例中,要保证所有设置当前选中的功能都调用内部接口SetItemSel。