CButton子类化了,关重写了BN_CLICKED事件了,为何在父窗口里得不到BN_CLICKED事件了呢?

时间:2022-05-10 17:46:28
如题,我子类化了复选框,并重绘了它。因为逻辑上需要用到单击事件来切换状态,效果是实现了,但出了另一个问题就是父窗口里复选框的单击事件无效了。
是不是消息流通不对????

15 个解决方案

#1


mark...........

#2


CButton在处理完点击消息之后,
再向父窗口发送点击消息就行了。

#3



LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRet = 0;
bool bHover = IsHoverMode();
if(!bHover)
lRet = DefWindowProc(uMsg, wParam, lParam);
if(::GetCapture() == m_hWnd)
{
if(bHover && m_fPressed == 1)
::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
::ReleaseCapture();
}
return lRet;
}

#4


引用 3 楼 hurryboylqs 的回复:
C/C++ code

    LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
    {
        LRESULT lRet = 0;
        bool bHover = IsHoverMode();
        if(!bHover)
   ……


用你的SendMessage怎么没效果呀?
父窗口还是没有收到单击事件

#5


你的父窗口是的消息映射是怎样的?
是否将对于的按钮ID与响应函数在BEGIN_MESSAGE_MAP、END_MESSAGE_MAP做了映射关联?

#6


可以在子类的函数里再调用父类的按钮函数,这样就可以让父类也收到单击事件了。

#7


子类化不影响BN_CLICKED消息的。

是不是实现了 映射到自身类(按钮)里的单击事件(向导里为=BN_CLICKED)?这样的话是不会再到父窗口了。(MFC这样处理发往父窗口的BN_CLICKED消息:先去调用按钮类的消息处理函数,如果没有,再继续去调用父窗口的消息处理函数)

可以在WM_LBUTTONUP消息里 进行切换状态。自身类里不要去映射单击事件消息。这样就不会影响BN_CLICKED消息发往父窗口了。

#8


MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消息(参考MSDN中BN_CLICKED的说明)来做相应的处理,而不添加=BN_CLICKED的映射。

#9


BOOL CButtonEx::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
LRESULT* pResult)
{
int nCode = HIWORD(wParam);
if(nCode == BN_CLICKED)
{
CWnd::OnChildNotify(message, wParam, lParam, pResult);
return FALSE;
}
if (message != WM_DRAWITEM)
return CWnd::OnChildNotify(message, wParam, lParam, pResult);

ASSERT(pResult == NULL);       // no return value expected
UNUSED(pResult); // unused in release builds
DrawItem((LPDRAWITEMSTRUCT)lParam);
return TRUE;
}

#10


nCode == BN_CLICKED时 return FALSE就可以了

#11


引用 8 楼 cnzdgs 的回复:
MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消……

up

#12


来关注下。

#13


引用 8 楼 cnzdgs 的回复:
MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消息……

我按照你说的做了,但发现还是有问题,就是我没有单击按钮,为何nCode == BN_CLICKED???
这是为何???????

#14


引用楼主 sunmz_wjxy 的回复:
如题,我子类化了复选框,并重绘了它。因为逻辑上需要用到单击事件来切换状态,效果是实现了,但出了另一个问题就是父窗口里复选框的单击事件无效了。
是不是消息流通不对????

你子类化了CButton,在其中处理=BN_CLICKED消息以后,你的父窗口就不再处理BN_CLICKED了。。。

#15


引用 13 楼 sunmz_wjxy 的回复:
我按照你说的做了,但发现还是有问题,就是我没有单击按钮,为何nCode == BN_CLICKED???
这是为何???????

BOOL CMyButton::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED)
{
// OnBnClicked();
}

return CButton::OnChildNotify(message, wParam, lParam, pLResult);
}

#1


mark...........

#2


CButton在处理完点击消息之后,
再向父窗口发送点击消息就行了。

#3



LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRet = 0;
bool bHover = IsHoverMode();
if(!bHover)
lRet = DefWindowProc(uMsg, wParam, lParam);
if(::GetCapture() == m_hWnd)
{
if(bHover && m_fPressed == 1)
::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
::ReleaseCapture();
}
return lRet;
}

#4


引用 3 楼 hurryboylqs 的回复:
C/C++ code

    LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
    {
        LRESULT lRet = 0;
        bool bHover = IsHoverMode();
        if(!bHover)
   ……


用你的SendMessage怎么没效果呀?
父窗口还是没有收到单击事件

#5


你的父窗口是的消息映射是怎样的?
是否将对于的按钮ID与响应函数在BEGIN_MESSAGE_MAP、END_MESSAGE_MAP做了映射关联?

#6


可以在子类的函数里再调用父类的按钮函数,这样就可以让父类也收到单击事件了。

#7


子类化不影响BN_CLICKED消息的。

是不是实现了 映射到自身类(按钮)里的单击事件(向导里为=BN_CLICKED)?这样的话是不会再到父窗口了。(MFC这样处理发往父窗口的BN_CLICKED消息:先去调用按钮类的消息处理函数,如果没有,再继续去调用父窗口的消息处理函数)

可以在WM_LBUTTONUP消息里 进行切换状态。自身类里不要去映射单击事件消息。这样就不会影响BN_CLICKED消息发往父窗口了。

#8


MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消息(参考MSDN中BN_CLICKED的说明)来做相应的处理,而不添加=BN_CLICKED的映射。

#9


BOOL CButtonEx::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
LRESULT* pResult)
{
int nCode = HIWORD(wParam);
if(nCode == BN_CLICKED)
{
CWnd::OnChildNotify(message, wParam, lParam, pResult);
return FALSE;
}
if (message != WM_DRAWITEM)
return CWnd::OnChildNotify(message, wParam, lParam, pResult);

ASSERT(pResult == NULL);       // no return value expected
UNUSED(pResult); // unused in release builds
DrawItem((LPDRAWITEMSTRUCT)lParam);
return TRUE;
}

#10


nCode == BN_CLICKED时 return FALSE就可以了

#11


引用 8 楼 cnzdgs 的回复:
MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消……

up

#12


来关注下。

#13


引用 8 楼 cnzdgs 的回复:
MFC对控件通知事件响应的大概过程是:父窗口收到通知消息后首先将消息反射给控件(调用控件的OnChildNotify)函数,如果控件响应了该消息(根据OnChildNotify的返回值来判断),则直接返回不做处理;如果控件没有响应该消息,则在本类中匹配消息映射。
因为你在控件中响应了该消息的反射,所以父窗口不会响应该消息。可以改成在控件类中重载OnChildNotify函数,根据函数参数判断消息……

我按照你说的做了,但发现还是有问题,就是我没有单击按钮,为何nCode == BN_CLICKED???
这是为何???????

#14


引用楼主 sunmz_wjxy 的回复:
如题,我子类化了复选框,并重绘了它。因为逻辑上需要用到单击事件来切换状态,效果是实现了,但出了另一个问题就是父窗口里复选框的单击事件无效了。
是不是消息流通不对????

你子类化了CButton,在其中处理=BN_CLICKED消息以后,你的父窗口就不再处理BN_CLICKED了。。。

#15


引用 13 楼 sunmz_wjxy 的回复:
我按照你说的做了,但发现还是有问题,就是我没有单击按钮,为何nCode == BN_CLICKED???
这是为何???????

BOOL CMyButton::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED)
{
// OnBnClicked();
}

return CButton::OnChildNotify(message, wParam, lParam, pLResult);
}