Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / WTL

WTL 7.0 CMDICommandBarCtr Bug and Fix

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
13 May 20021 min read 53K   21   3
WTL 7.0 CMDICommandBarCtr small fixes
In this article, you will find fixes for two small problems in the implementation of full MDI support in WTL 7.0.

Introduction

After downloading WTL 7.0, I have seen that Microsoft has implemented full MDI support. But I found two small problems in this implementation. First, the MDI child window icon looks terrible on command bar (when child window is maximized). Second, if the application has few types of children and active MDI child is maximized, if you try to switch to child window of different type (i.e., that has different icon), the icon displayed on command bar remains the same.

The Fix

To fix these small bugs was very simple: I changed a little bit of the function OnAllHookMessages in the template (original code line 3396, file atlctrlw.h). First problem occurs, because if the child window returns NULL when command bar sends message WM_GETICON (and standard CMDIChildWindowImpl does it), in the code, it uses hIcon member of WNDCLASSEX, and the big icon after interpolation looks ugly. It is actually supposed to use hIconSm member, to retrieve small icon from WNDCLASSEX. To solve the second problem is also very simple: just to check, if new icon handle is equal to old, and if not, force command bar to redraw itself. Here is the code:

C++
    LRESULT OnAllHookMessages(UINT uMsg, WPARAM /*wParam*/, 
          LPARAM /*lParam*/, BOOL& bHandled)
    {
        bHandled = FALSE;
        if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU)
            return 1;

        BOOL bMaximized = FALSE;
        HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, 
              WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
        bool bMaxOld = m_bChildMaximized;

        bool bNeedRedraw = false; //declare variable to 
                                  // indicate whether we need redraw or not

        m_bChildMaximized = (hWndChild != NULL && bMaximized);

        if(m_bChildMaximized)
        {
            if(m_hWndChildMaximized != hWndChild)
            {
                CWindow wnd = m_hWndChildMaximized = hWndChild;
                HICON hOldIcon = m_hIconChildMaximized; 
                     //save old icon value

                m_hIconChildMaximized = wnd.GetIcon(FALSE);
                if(m_hIconChildMaximized == NULL)   
                     // no icon set with WM_SETICON, get the class one
                {
                    TCHAR szClass[200];
                    ::GetClassName(wnd, szClass, 
                         sizeof(szClass) / sizeof(TCHAR));
                    WNDCLASSEX wc;
                    wc.cbSize = sizeof(WNDCLASSEX);
                    // try process local class first
                    BOOL bRet = ::GetClassInfoEx(
                       _Module.GetModuleInstance(), szClass, &wc);
                    if(!bRet)    // try global class
                        bRet = ::GetClassInfoEx(NULL, szClass, &wc);
                    //if small icon is not NULL, use it, else use big icon

                    m_hIconChildMaximized = bRet ? 
                          (wc.hIconSm ? wc.hIconSm : wc.hIcon) : NULL;
                }
                //if we need to set new icon, we need to redraw command bar
                bNeedRedraw = (hOldIcon != m_hIconChildMaximized);
            }
        }
        else
        {
            m_hWndChildMaximized = NULL;
            m_hIconChildMaximized = NULL;
        }

        if(bMaxOld != m_bChildMaximized)
        {
#ifdef _CMDBAR_EXTRA_TRACE
            ATLTRACE2(atlTraceUI, 0, "MDI CmdBar - All messages "
                     "hook change: m_bChildMaximized = %s\n", 
m_bChildMaximized ? "true" : "false");
#endif
            // assuming we are in a rebar, change our size to
            // accommodate new state
            // we hope that if we are not in a rebar, nCount will be 0
            int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT,
                 0, 0L);
            int cxDiff = (m_bChildMaximized ? 1 : -1) * 
                 (m_cxLeft + m_cxRight);
            for(int i = 0; i < nCount; i++)
            { 
#if (_WIN32_IE >= 0x0500)
                REBARBANDINFO rbi = { sizeof(REBARBANDINFO), 
                   RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE
                   | RBBIM_STYLE };
                ::SendMessage(GetParent(), RB_GETBANDINFO, i, 
                      (LPARAM)&rbi);
                if(rbi.hwndChild == m_hWnd)
                {
                    if((rbi.fStyle & RBBS_USECHEVRON) != 0)
                    {
                        rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
                        rbi.cxMinChild += cxDiff;
                        rbi.cxIdeal += cxDiff;
                        ::SendMessage(GetParent(), RB_SETBANDINFO, 
                                i, (LPARAM)&rbi);
                    }
                    break;
                }
#else //!(_WIN32_IE >= 0x0500)
                REBARBANDINFO rbi = { sizeof(REBARBANDINFO), 
                   RBBIM_CHILD | RBBIM_CHILDSIZE };
                ::SendMessage(GetParent(), RB_GETBANDINFO, i, 
                   (LPARAM)&rbi);
                if(rbi.hwndChild == m_hWnd)
                {
                    rbi.fMask = RBBIM_CHILDSIZE;
                    rbi.cxMinChild += cxDiff;
                    ::SendMessage(GetParent(), RB_SETBANDINFO, i,
                         (LPARAM)&rbi);
                    break;
                }
#endif //!(_WIN32_IE >= 0x0500)
            }

            /*// force size change and redraw everything
            RECT rect;
            GetWindowRect(&rect);
            ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
            SetRedraw(FALSE);
            SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
            SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
            SetRedraw(TRUE);
            RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE 
                      | RDW_UPDATENOW);*/
                    //now we need to redraw
            bNeedRedraw = true;
        }

        if(bNeedRedraw)
        {
            // force size change and redraw everything
            RECT rect;
            GetWindowRect(&rect);
            ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
            SetRedraw(FALSE);
            SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
            SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
            SetRedraw(TRUE);
            RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE
                  | RDW_UPDATENOW);
        }

        return 1;
    } 

History

  • 14th May, 2002: Initial version

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralProblem in using SetWindowPos() Pin
mails2dhana8-Sep-05 3:30
mails2dhana8-Sep-05 3:30 
GeneralRe: Problem in using SetWindowPos() Pin
Alweit10-Sep-05 20:34
Alweit10-Sep-05 20:34 
GeneralRe: Problem in using SetWindowPos() Pin
mails2dhana13-Sep-05 16:09
mails2dhana13-Sep-05 16:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.