外部调用接口不成功发现原来窗口还没创建(CTabCtrl开发记录2)

问题:在父窗口中调用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。

posted @ 2013-12-02 14:49  Tup  阅读(371)  评论(0编辑  收藏  举报