返回首页

{A}
{S0}简介
有一个MFC的CToolBar类的错误,同时显示工具栏按钮的工具提示。当计算显示工具提示的是哪个按钮,工具栏按钮的位置移动1个像素的权利。因此,当鼠标光标指出的一个工具栏按钮的最左边的像素,其左侧的按钮的工具提示和状态栏提示的实际显示!
这是很容易重现此错误。创建一个MFC项目,无论是SDI或MDI,默认情况下,包括工具栏。保留所有其他项目的设置,其默认值。运行程序,并仔细将鼠标光标移动到"打开"工具栏按钮的最左边的像素。 CToolBar将显示"新建"按钮,在上面的图片显示,工具提示。这个错误是相当误导的。
一个众所周知的,基于MFC的软件件数受这个错误,包括间谍和。背景
挖成CToolBar源代码后,我发现这个bug的原因。当工具提示可能需要的工具栏,框架调用CToolBar::OnToolHitTest()来确定光标在哪个按钮。下面是这种方法的源代码,VC + + 6.0中复制。除非返回int类型改变成INT_PTR,几乎是不变的VC 8.0代码:

int CToolBar::OnToolHitTest(CPoint point, TOOLINFO* pTI) const

{

    ASSERT_VALID(this);

    ASSERT(::IsWindow(m_hWnd));



    // check child windows first by calling CControlBar

    int nHit = CControlBar::OnToolHitTest(point, pTI);

    if (nHit != -1)

        return nHit;



    // now hit test against CToolBar buttons

    CToolBar* pBar = (CToolBar*)this;

    int nButtons = (int)pBar->DefWindowProc(TB_BUTTONCOUNT, 0, 0);

    for (int i = 0; i < nButtons; i++)

    {

        CRect rect;

        TBBUTTON button;

        if (pBar->DefWindowProc(TB_GETITEMRECT, i, (LPARAM)&rect))

        {

            ++rect.bottom;    // Buggy line

            ++rect.right;    // Buggy Line

            if (rect.PtInRect(point) &&

                pBar->DefWindowProc(TB_GETBUTTON, i, (LPARAM)&button) &&

                !(button.fsStyle & TBSTYLE_SEP))

            {

                int nHit = GetItemID(i);

                if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))

                {

                    pTI->hwnd = m_hWnd;

                    pTI->rect = rect;

                    pTI->uId = nHit;

                    pTI->lpszText = LPSTR_TEXTCALLBACK;

                }

                // found matching rect, return the ID of the button

                return nHit != 0 ? nHit : -1;

            }

        }

    }

    return -1;

}

与缺陷所涉及的行说:"越野车线。"似乎没有理由增加1个像素,和MFC rect.bottom和rect.right,提供了这样做没有任何评论。这些行导致错误按钮的RECT要检索等错误的工具提示显示。 :(使用代码
修正错误,只需创建从CToolBar派生一个类,并覆盖了C​​ToolBar::OnToolHitTest()方法。原来实行的CToolBar::OnToolHitTest()复制和注释掉两个越野车线。然后更换新的类CToolBar无处不在,它是在项目中使用。所附CFixedToolBar就是一个例子。
还有一些事情要做。如果你编译新的类,现在你会得到一个错误,说,AFX_OLDTOOLINFO是不确定的。它实际上是指在LT afximpl.hgt; TOOLINFO兼容版本,所以通过英寸,而不是提供的AFX_OLDTOOLINFO定义,是为了确保代码,简单地改变SIZEOF(AFX_OLDTOOLINFO)40,即AFX_OLDTOOLINFO结构的大小,是足够的。现在一切都OK。享受。 :)历史2007年7月16日 - 原始版本发表于

回答

评论会员:flyingxu 时间:2011/12/14
?conditon你注意到了这个错误,我只是好奇
这两条线显然是MS的意向,但为什么呢?

我还发现一个按钮时,它的文本标签的工具栏的大小的错误,但我不能够dubug {S2}
评论会员:。明亮朱 时间:2011/12/14
对不起迟到。我是几天假期

我试图使所有者绘制的工具栏和测试按钮是否正确绘制。所以,我仔细检查按钮的行为,当鼠标指针围绕它们的边界,并注意到了这一点。

我想这些代码最初是在Windows的早期版本,需要一些"绝招",以达到一定的效果的书面
MFC的设计师也许只是想一些在工作中的"签名",所以MFC应用程序会很容易识别?
正如您可能已经注意到,MFC状态栏总是奇怪的几个像素比普通状态栏,这使我认识到很多MFC应用程序乍一看低:P

#26087;#26085;#37325;#26469;
评论会员:Panic2k3 时间:2011/12/14
你展示了如何解决这个问题,但所建议的解决方案不起作用...

pBar -> DefWindowProc()将试图访问受保护的成员函数的CWnd

/ / /弓:不要惊慌...
http://en.wikibooks.org/wiki/User:Panic2k4
评论会员:明亮朱 时间:2011/12/14
对不起,我没有在我的文章中提到这...
在前面的行:
CToolBar * pBar =(CToolBar *);
更改的工具栏类。
的名称"CToolBar"看来,这个陌生的行的唯一作用是使"这个"不是const

下载在我的文章开始重视代码也能工作。

感谢您的关注。享受

#26087;#26085;#37325;#26469;