65.9K
CodeProject 正在变化。 阅读更多。
Home

WTL 7.0 CMDICommandBarCtr 错误及修复

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2002年5月14日

1分钟阅读

viewsIcon

53922

WTL 7.0 CMDICommandBarCtr 小修复

引言

下载 WTL 7.0 后,我发现 Microsoft 已经实现了完整的 MDI 支持。但我在这个实现中发现了两个小问题。首先,命令栏上的 MDI 子窗口图标在最大化时看起来很糟糕。其次,如果应用程序有几种类型的子窗口,并且激活的 MDI 子窗口被最大化,如果你尝试切换到不同类型(即具有不同图标)的子窗口,命令栏上显示的图标仍然相同。

修复方案

修复这些小错误非常简单:我稍微修改了模板中的 OnAllHookMessages 函数(原始代码第 3396 行,文件 atlctrlw.h)。第一个问题发生的原因是,当命令栏发送 WM_GETICON 消息时,子窗口返回 NULL (标准的 CMDIChildWindowImpl 就是这样做的),代码中会使用 WNDCLASSEXhIcon 成员,而经过插值后的大图标看起来很丑。实际上应该使用 hIconSm 成员,从 WNDCLASSEX 中获取小图标。解决第二个问题也很简单:只需检查新的图标句柄是否等于旧的图标句柄,如果不相等,就强制命令栏重新绘制自身。以下是代码:

    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;
    } 

历史

  • 2002年5月14日:初始版本

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.