Click here to Skip to main content
Click here to Skip to main content

WTL 7.0 CMDICommandBarCtr bug and fix

, 13 May 2002
Rate this:
Please Sign up or sign in to vote.
WTL 7.0 CMDICommandBarCtr small fixes

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 application has few types of childs 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 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:

    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 do 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
            // accomodate 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;

    } 

Conclusion

Sorry for my English Smile | :)

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

Share

About the Author

Alweit
Web Developer
Israel Israel
No Biography provided

Comments and Discussions

 
GeneralProblem in using SetWindowPos() Pinmembermails2dhana8-Sep-05 3:30 
GeneralRe: Problem in using SetWindowPos() PinmemberAlweit10-Sep-05 20:34 
GeneralRe: Problem in using SetWindowPos() Pinsussmails2dhana( Dhananjayan )13-Sep-05 16:09 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.141015.1 | Last Updated 14 May 2002
Article Copyright 2002 by Alweit
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid