情况是这样的!
我用勾子拦截了按钮的消息,主要目的是对按钮进行外观上绘制,如下:
case WM_PAINT:
{
pButton->OnPaint(hWnd);
break;
}
case WM_LBUTTONDOWN:
{
::InvalidateRect(hWnd,NULL,true);
break;
}
case WM_LBUTTONUP:
{
::InvalidateRect(hWnd,NULL,true);
break;
}
通过上面代码,达到了绘制目的,可是在后来的测试中发现出现了问题,描述如下:
当我把鼠标按住按钮时,鼠标不放开,然后再把鼠标移出按钮外部,当鼠标移刚好移出按钮外部时(事实上,如果我不在WM_LBUTTONDOWN加上InvalidateRect的话,在按下鼠标的时候外观就变了),发现按钮的外观变成了MFC默认的灰色绘制效果,再把鼠标移入按钮内部,按钮的外观还是MFC默认的灰色,直到我放开鼠标才会恢复我的自绘制效果。我想了很多办法来解决这个问题,如果,在case WM_MOUSEMOVE:内加上OnPaint()函数啦等等,最终都没办法解决;
后来发现:原来MFC在WM_LBUTTONDOWN内对鼠标进行了捕获,直到WM_LBUTTONUP才释放,所以我在按下鼠标后,这中间的消息如WM_MOUSEMOVE都没能拦截到,被MFC做了默认的处理,所以我们看到,当鼠标在移动时,MFC做了它的灰色绘制处理,而我在WM_MOUSEMOVE所做的绘制都没能得到执行!
既然MFC把这段时间的消息捕获了,我显得无能为力,没办法,我了照它的样,也来捕获鼠标,所以我在case WM_LBUTTONDOWN:也进行了如下的鼠捕获代码如下:case WM_LBUTTONDOWN:
{
pButton->mPress=true;
pButton->OnPaint(hWnd);
if (::GetCapture() == NULL)
{
SetCapture(hWnd);
ASSERT(hWnd == GetCapture());
AfxLockTempMaps();
for (;;)
{
MSG msg;
VERIFY(::GetMessage(&msg, NULL, 0, 0));
if (::GetCapture() != hWnd) break;
switch (msg.message)
{
case WM_LBUTTONUP:
{
pButton->mPress=false;
pButton->OnPaint(hWnd);
}
goto ExitLoop2;
case WM_KEYDOWN:
if (msg.wParam != VK_ESCAPE)
break;
default:
DispatchMessage(&msg);
break;
}
}
ExitLoop2:
ReleaseCapture();
AfxUnlockTempMaps(FALSE);
}
经过以上处理发现,其内部
case WM_LBUTTONUP:
{
pButton->mPress=false;
pButton->OnPaint(hWnd);
}
这段代码并未得到执行!因为在按钮上按下鼠标再放开时,鼠标同样变成MFC默认绘制效果,且在放开鼠标后发现按钮还保持对鼠标的捕获,所以导致了对按扭的单击事件也无法得到执行!
我该怎么办?请高手们帮忙看看指点指点!
我用勾子拦截了按钮的消息,主要目的是对按钮进行外观上绘制,如下:
case WM_PAINT:
{
pButton->OnPaint(hWnd);
break;
}
case WM_LBUTTONDOWN:
{
::InvalidateRect(hWnd,NULL,true);
break;
}
case WM_LBUTTONUP:
{
::InvalidateRect(hWnd,NULL,true);
break;
}
通过上面代码,达到了绘制目的,可是在后来的测试中发现出现了问题,描述如下:
当我把鼠标按住按钮时,鼠标不放开,然后再把鼠标移出按钮外部,当鼠标移刚好移出按钮外部时(事实上,如果我不在WM_LBUTTONDOWN加上InvalidateRect的话,在按下鼠标的时候外观就变了),发现按钮的外观变成了MFC默认的灰色绘制效果,再把鼠标移入按钮内部,按钮的外观还是MFC默认的灰色,直到我放开鼠标才会恢复我的自绘制效果。我想了很多办法来解决这个问题,如果,在case WM_MOUSEMOVE:内加上OnPaint()函数啦等等,最终都没办法解决;
后来发现:原来MFC在WM_LBUTTONDOWN内对鼠标进行了捕获,直到WM_LBUTTONUP才释放,所以我在按下鼠标后,这中间的消息如WM_MOUSEMOVE都没能拦截到,被MFC做了默认的处理,所以我们看到,当鼠标在移动时,MFC做了它的灰色绘制处理,而我在WM_MOUSEMOVE所做的绘制都没能得到执行!
既然MFC把这段时间的消息捕获了,我显得无能为力,没办法,我了照它的样,也来捕获鼠标,所以我在case WM_LBUTTONDOWN:也进行了如下的鼠捕获代码如下:case WM_LBUTTONDOWN:
{
pButton->mPress=true;
pButton->OnPaint(hWnd);
if (::GetCapture() == NULL)
{
SetCapture(hWnd);
ASSERT(hWnd == GetCapture());
AfxLockTempMaps();
for (;;)
{
MSG msg;
VERIFY(::GetMessage(&msg, NULL, 0, 0));
if (::GetCapture() != hWnd) break;
switch (msg.message)
{
case WM_LBUTTONUP:
{
pButton->mPress=false;
pButton->OnPaint(hWnd);
}
goto ExitLoop2;
case WM_KEYDOWN:
if (msg.wParam != VK_ESCAPE)
break;
default:
DispatchMessage(&msg);
break;
}
}
ExitLoop2:
ReleaseCapture();
AfxUnlockTempMaps(FALSE);
}
经过以上处理发现,其内部
case WM_LBUTTONUP:
{
pButton->mPress=false;
pButton->OnPaint(hWnd);
}
这段代码并未得到执行!因为在按钮上按下鼠标再放开时,鼠标同样变成MFC默认绘制效果,且在放开鼠标后发现按钮还保持对鼠标的捕获,所以导致了对按扭的单击事件也无法得到执行!
我该怎么办?请高手们帮忙看看指点指点!
解决方案 »
- ■■■修改了ListView表头高度,但是数据行被头遮住了,如何解决?
- 如何设置CCombBox中的内容
- 求助,在线等,谢谢,关于鼠标进入对话框的问题。
- 在程序中调用“时间、日期属性”对话框
- DLL嵌套调用的问题
- 如何防止主键的重复?
- 怎么分别处理按钮的按下和弹起两个消息?
- 求助:哪里有OpenGL在VC++里编程的实例下载,分不够再加
- 请教vc高手,关于编译时找不到头文件的问题!在线等
- 请问Windows把我的邮件放在什么文件里呀?有什么办法可以直接恢复吗?
- 关于m_hdcBottom=::CreateCompatibleDC(hDC);内存泄露的问题
- 高手帮忙看看CWebBrowser2的Navigate代码有什么问题
ReleaseCapture();
AfxUnlockTempMaps(FALSE);
}
经过以上处理发现,其内部
case WM_LBUTTONUP:
{
pButton->mPress=false;
pButton->OnPaint(hWnd);
}
这段代码并未得到执行!因为在按钮上按下鼠标再放开时,鼠标同样变成MFC默认绘制效果,且在放开鼠标后发现按钮还保持对鼠标的捕获,所以导致了对按扭的单击事件也无法得到执行!
我该怎么办?请高手们帮忙看看指点指点!
////////////////////////////////////////////////
我在放开鼠标时,会产生WM_LBUTTONUP消息,然后该消息应该会送到捕获鼠标的代码WM_LBUTTONUP内执行,也即最终会让程序运行到下面代码处:
ExitLoop2:
ReleaseCapture();
AfxUnlockTempMaps(FALSE);
释放鼠标捕获,可问题是,我放开鼠标后,并没有释放鼠标捕获,且导致鼠标的单击事件都无法得到执行。针对以上问题,我在想,MFC本身就在WM_LBUTTONDOWN内进行了鼠标捕获,而我也是在该消息内进行鼠标捕获,难道这样会有冲突?应该是我捕获鼠标后,那么MFC默认对鼠标的捕获就应该被释放了而不对会我的捕获产生干扰嘛!
如果你非要这样实现,建议你按最开始的方法做,只处理WM_PAINT,WM_LBUTTONDOWN,WM_LBUTTONUP消息,另外多处理一下WM_ERASBKGND消息,直接返回TRUE。应该就不会出现你所说的离开就变成默认按钮的情形了。
最好还是通过重载CButton,这也是比较标准的OOP方法。WM_DRAWITEM这个消息是虚拟的,背后有MFC的消息反射机制,你必须重载CButton后,才可以处理这个。而且原始的Windows编程中,Button之类是没有消息循环的,它的消息是父窗口处理的,也用不到鼠标捕获。你也你在父窗口里做的消息处理,注意处理反射消息,在父窗口绘制Button也是可能的。
可以用FindWindowEx或EnumChildWindows遍历所有控件,根据类名来区分,逐一子类化。实际上只要把每个按钮的风格都改成BS_OWNERDRAW,然后在父窗口响应WM_DRAWITEM消息即可。