Embedded CPropertySheet - CTabCtrl doesn't reflect EnableWindow(FALSE) 
Author Message
 Embedded CPropertySheet - CTabCtrl doesn't reflect EnableWindow(FALSE)

I have an embedded CPropertSheet within a dialog. Depending on some other
switch I want to disable the embedded sheet. So I got its CTabCtrl and do
the EnableWindow(FALSE).

That works fine, they are disabled and cannot be clicked with the mouse.

But - it doesn't looks like: The tabs' text is still black on gray and not
lightgray on gray.

How to change the text color on the tabs?



Tue, 05 Aug 2003 18:14:03 GMT  
 Embedded CPropertySheet - CTabCtrl doesn't reflect EnableWindow(FALSE)
Hi, Louis!

The only way I know to do this is to subclass and ownerdraw the tab control. This in and of itself
is pretty easy to accomplish -- derive a class from CTabCtrl, override the PreSubclassWindow and
DrawItem functions...

    void CDisTabCtrl::PreSubclassWindow()
    {
        ModifyStyle(0, TCS_OWNERDRAWFIXED);
        CTabCtrl::PreSubclassWindow();
    }

    void CDisTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS)
    {
        TCHAR tsz[MAX_PATH];
        TCITEM tci;
        CDC dc;

        tci.cchTextMax = sizeof(tsz);
        tci.mask = TCIF_TEXT;
        tci.pszText = tsz;

        dc.Attach(lpDIS->hDC);

        if (GetItem(lpDIS->itemID, &tci))
        {
            CRect rc(lpDIS->rcItem);

            if (lpDIS->itemState & ODS_SELECTED)
            {
                dc.FillSolidRect(&rc, dc.GetBkColor());
                rc += CPoint(6,4);
            }
            else
            {
                rc += CPoint(4, 3);
            }

            UINT fFlags = DST_PREFIXTEXT;

            if (IsWindowEnabled())
                fFlags |= DSS_NORMAL;
            else
                fFlags |= DSS_DISABLED;

            dc.DrawState(rc.TopLeft(), rc.Size(), tsz, fFlags,
                TRUE, 0, (HBRUSH)NULL);
        }
        dc.Detach();
    }

And then add a handler for the WM_ENABLE message...

    void CDisTabCtrl::OnEnable(BOOL bEnable)
    {
        CTabCtrl::OnEnable(bEnable);
        Invalidate();
    }

Then all you have have to do is add a member variable of the CDisTabCtrl class to your
CPropertySheet derived class, and wire it up in an override of OnInitDialog...

    BOOL CSheetOne::OnInitDialog()
    {
        BOOL bResult = CPropertySheet::OnInitDialog();

        if (HWND hWndTab = (HWND)SendMessage(PSM_GETTABCONTROL))
            m_tabCtrl.SubclassWindow(hWndTab);

        return bResult;
    }

But there are still some problems left to solve: 1) The disabled pages can still be switched using
the CTRL+PAGE_UP\PAGE_DOWN\TAB key accelerators, 2) All of the controls on each page are left
enabled because they are child windows of the sheet not the tab. So...

To solve problem 1, add a member function to the CDisTabCtrl...

    BOOL CDisTabCtrl::TranslateAccelerator(LPMSG pMsg)
    {
        if (IsWindow(m_hWnd) && !IsWindowEnabled())
        {
            if ((pMsg->message == WM_KEYDOWN) &&
                (GetAsyncKeyState(VK_CONTROL) < 0))
            {
                switch (pMsg->wParam)
                {
                case VK_TAB:
                case VK_PRIOR:
                case VK_NEXT:
                    return TRUE;
                }
            }
        }
        return FALSE;
    }

And then override PreTranslateMessage in the CPropertySheet to call it...

    BOOL CSheetOne::PreTranslateMessage(MSG* pMsg)
    {
        return (m_tabCtrl.TranslateAccelerator(pMsg))
            ? TRUE : CPropertySheet::PreTranslateMessage(pMsg);
    }

Now, problem 2 is probably too much for my feeble mind to really solve, but here's my attempt at
it...

    BOOL CDisTabCtrl::EnumProc(HWND hWnd)
    {
        BOOL bEnabled = IsWindowEnabled();

        if (hWnd && IsWindow(hWnd) &&
            ::IsWindowVisible(hWnd) && (hWnd != m_hWnd))
        {
            CRect rc, rcChild;
            if (::GetWindowRect(hWnd, &rcChild))
            {
                GetWindowRect(&rc);
                if (rc.PtInRect(rcChild.TopLeft()))
                    ::EnableWindow(hWnd, bEnabled);
            }
        }
        return TRUE;
    }

    // static
    BOOL CALLBACK CDisTabCtrl::EnumHook(HWND hWnd, LPARAM lParam)
    {
        return ((CDisTabCtrl*)lParam)->EnumProc(hWnd);
    }

And then modify the WM_ENABLE handler from above like so...

    void CDisTabCtrl::OnEnable(BOOL bEnable)
    {
        CWnd* pWndFocus = GetFocus();
        if (IsWindow(m_hWnd))
        {
            CTabCtrl::OnEnable(bEnable);

            if (HWND hWndParent = ::GetParent(m_hWnd))
            {
                EnumChildWindows(
                    hWndParent,
                    EnumHook,
                    (LPARAM)this);

                if (!pWndFocus || !pWndFocus->IsWindowEnabled())
                    ::PostMessage(hWndParent, WM_NEXTDLGCTL, 0, 0);
            }
        }
        Invalidate();
    }

And that, FWIW, is all I know about it. Use with caution, test with zeal, and remember it's just a
sample.

HTH,

Jeff...
--
Please post all follow-ups to the newsgroup only.



Wed, 06 Aug 2003 13:19:42 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. browser address doesn't reflect current web form

2. Help/About doesn't reflect SP3

3. EnableWindow(FALSE) does not work for CStatic

4. EnableWindow(false);

5. EnableWindow(FALSE) with Black text color

6. EnableWindow(FALSE) with Black text color 2.

7. Button with EnableWindow(FALSE) still receives Button Click

8. UpdateRegistryAll(FALSE) doesn't unregister anything!

9. SetRedraw(FALSE) doesn't work with CListCtrl ???

10. CRichEditView in CTabCtrl doesn't work

11. CPropertySheet::OnOK - doesn't exist

12. Embedded Object menu hook doesn't work

 

 
Powered by phpBB® Forum Software