【问题标题】:BCN_HOTITEMCHANGE notification is not getting called with CMFCButton class没有使用 CMFCButton 类调用 BCN_HOTITEMCHANGE 通知
【发布时间】:2019-10-11 17:00:21
【问题描述】:

BCN_HOTITEMCHANGE 通知代码没有被 CMFCButton 类调用。

我正在使用 Visual Studio 2010

执行的步骤:

1) 从资源编辑器向我的对话框添加一个 CButton。

2) 使用我自己的派生类 CMFCButtonEx 派生自 CMFCButton 类(又派生自 CButton 类)。

3) 向我的对话框声明 CMFCButtonEx 'm_btn_ex' 实例变量。

4) 添加 DDX_Control(pDX, IDC_BUTTON_EX, m_btn_ex);

5) 当我单击此按钮时,派生类中的所有消息处理程序都会被调用,但与 OnButtonItemChange 函数关联的 BCN_HOTITEMCHANGE 通知除外。该函数中的断点永远不会命中。所有其他消息处理程序(OnMouseMove、OnMouseLeave 和 OnButtonClicked)都被正确调用,并且它们中的断点被命中。

请注意,如果我从 CButton 类通过 CMFCButtonEx 类派生,那么我可以在 OnButtonItemChange 函数中命中断点,即正确处理 BCN_HOTITEMCHANGE 通知代码

由于某种原因,CMFCButton 类没有正确处理我的 BCN_HOTITEMCHANGE 通知代码。我不明白我在这里做错了什么。我也尝试使用 TBN_HOTITEMCHANGE 通知代码而不是 BCN_HOTITEMCHANGE 但 OnButtonItemChange 函数中的断点从未命中。

谢谢!

CMFCButtonEx 类代码:

IMPLEMENT_DYNAMIC(CMFCButtonEx, CMFCButton)
CMFCButtonEx::CMFCButtonEx()
{   
     m_bMouseTracking = FALSE    
}

CMFCButtonEx::~CMFCButtonEx()
{
}

BEGIN_MESSAGE_MAP(CMFCButtonEx, CMFCButton)
    //{{AFX_MSG_MAP(CMFCButtonEx)
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSELEAVE()
    ON_NOTIFY_REFLECT_EX(BCN_HOTITEMCHANGE, OnButtonItemChange)
   //ON_NOTIFY_REFLECT_EX(TBN_HOTITEMCHANGE, OnButtonItemChange)
    ON_CONTROL_REFLECT_EX(BN_CLICKED, OnButtonClicked)  
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CMFCButtonEx::OnButtonClicked()
{
    AfxMessageBox("MFC Button Clicked");
    return FALSE;
}

BOOL CMFCButtonEx::OnButtonItemChange(NMHDR* pNMHDR, LRESULT* pResult)
{
    NMBCHOTITEM* pnmbchotitem = (NMBCHOTITEM*)pNMHDR;

    AfxMessageBox("MFC Button Item Change");

    *pResult = 0;
    return FALSE;
}

void CMFCButtonEx::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_bMouseTracking)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = this->m_hWnd;

        if (::_TrackMouseEvent(&tme))
        {
            m_bMouseTracking = TRUE;
            AfxMessageBox("MFC Button Mouse Move");
        }
    }
    CMFCButton::OnMouseMove(nFlags, point);
}

void CMFCButtonEx::OnMouseLeave()
{
    m_bMouseTracking = FALSE;
    AfxMessageBox("MFC Button Mouse Move");
    CMFCButton::OnMouseLeave();
}

【问题讨论】:

    标签: c++ visual-studio-2010 visual-c++ mfc


    【解决方案1】:

    BCN_HOTITEMCHANGE 不会为CMFCButton 或任何从CMFCButton 派生的类触发

    documentation 中所述,必须启用视觉样式,否则不会触发BCN_HOTITEMCHANGECMFCButton 依赖于所有者的绘制方法,因此该按钮的视觉样式被禁用。

    您可以从 CMFCButtonEx 类中删除 BS_OWNERDRAW。但不推荐这样做,因为CMFCButtonEx 依赖于BS_OWNERDRAW

    更好的解决方案是从CButton 派生您的类(并确保启用了视觉样式),使用自定义绘制而不是所有者绘制。你可能不需要OnMouseMoveOnMouseLeave

    class CMyButton : public CButton {}
    ...
    
    BOOL CMyButton::OnButtonItemChange(NMHDR* pNMHDR, LRESULT* pResult)
    {
        auto ptr = (NMBCHOTITEM*)pNMHDR;
        bool enter = ptr->dwFlags & HICF_ENTERING;
        if (enter)
            TRACE(L"CMyButton... enter\n");
        else
            TRACE(L"CMyButton... exit\n");
        *pResult = 0;
        return FALSE;
    }
    

    【讨论】:

    • 感谢您的回答。正如我在我的问题中提到的,从 CButton 派生但我必须使用 CMFCButton,因为我想使用 CMFCButton::m_nFlatStyle,当鼠标在按钮上时设置 BUTTONSTYLE_3D,当鼠标离开按钮时设置 BUTTONSTYLE_NOBORDERS。我可以使用 OnMouseMove 和 OnMouseLeave 和 TrackMouseEvent 来完成此操作。我不明白为什么 BCN_HOTITEMCHANGE 通知代码不能与 CMFCButton 一起使用。我猜 CMFCButton 永远不会与该通知一起使用,除非有办法在 CButton 对象上设置这些样式。
    • 如果您想要一个在悬停时变为 3-D 的平面按钮,请将 my_mfc_button.m_nFlatStyle = CMFCButton::BUTTONSTYLE_FLAT 放在 CDialog::OnInitDialog() 之后
    • 感谢您再次回复。我没试过 m_nFlatStyle = BUTTONSTYLE_FLAT。如果平面按钮要显示边框,那么它对我不起作用。就像当你将鼠标悬停在一个按钮上时,一个突出显示的矩形被绘制出来,当你离开按钮时没有边框,即矩形消失。以下是我正在做的事情,它可以很好地满足我的需求。我只是想使用 BCN_HOTITEMCHANGE 通知,而不是同时使用 OnMouseMove 和 OnMouseLeave。我认为这是不可能的,因为我的类是从 CMFCButton 派生的。除非有办法。
    • 在我的对话框的 OnInitDiaolog() 中,我设置了 m_nFlatStyle = BUTTONSTYLE_NOBORDERS。然后在 OnMouseMove() 中,我设置 m_nFlatStyle=BUTTONSTYLE_3D。在 OnMouseLeave() 中,我将其设置回无边界,即 m_nFlatStyle=BUTTONSTYLE_NOBORDERS。就像我说的那样,这就是我想要实现的目标,但是我不能使用 BCN_HOTITEMCHANGE,而必须使用鼠标通知。
    • 我会在星期二试试这个。但我之前尝试过扁平风格,但它并没有达到我想要的效果。当没有鼠标时,我根本不想要矩形,即我不希望它看起来像一个按钮。我可能会遵循我之前解释的逻辑,因为它工作正常。我只是想使用 BCN_HOTITEMCHANGE 而不是鼠标通知,但我发现我不能。
    猜你喜欢
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多