自绘位图按钮,频繁点击按钮好像反应不过来

windywater 2009-08-21 08:41:08
自绘一个位图按钮,重载了DrawItem,设置了按钮在普通状态和按下状态的不同的样式。但是我发现在快速点击按钮的时候,它的按下和弹起反应不是很即时。我用了一下CButtonST,它的好像没有这个问题。这是怎么造成的呢?
...全文
249 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluesky395 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 jameshooo 的回复:]
绘制消息属于低优先级消息,只有线程空闲才处理绘制,在其它消息(鼠标键盘)没有处理完之前,绘制消息只能在队列中排队,而且队列中的多个绘制消息会合并成一个。

如果快速点击鼠标,各种鼠标消息将优先处理,按钮状态不停改变,等到绘制消息有机会处理的时候,按钮的状态已经回到了原始状态,所以绘制的还是原始状态。如果发生这种情况,说明鼠标消息的响应函数过于耗时才导致线程没机会进入空闲状态,绘制消息不会立即发生。如果希望见到立即改变,可以在每个鼠标消息处理完之后立即调用RedrawWindow,它会立即进入绘制过程。
[/Quote]

学习。。。
jameshooo 2009-08-21
  • 打赏
  • 举报
回复
绘制消息属于低优先级消息,只有线程空闲才处理绘制,在其它消息(鼠标键盘)没有处理完之前,绘制消息只能在队列中排队,而且队列中的多个绘制消息会合并成一个。

如果快速点击鼠标,各种鼠标消息将优先处理,按钮状态不停改变,等到绘制消息有机会处理的时候,按钮的状态已经回到了原始状态,所以绘制的还是原始状态。如果发生这种情况,说明鼠标消息的响应函数过于耗时才导致线程没机会进入空闲状态,绘制消息不会立即发生。如果希望见到立即改变,可以在每个鼠标消息处理完之后立即调用RedrawWindow,它会立即进入绘制过程。
「已注销」 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 bluesky395 的回复:]
CButtonST貌似是重载了按钮的PreTranslateMessage,如果是鼠标双击消息WM_LBUTTONDBLCLK时,则替换为鼠标单击消息WM_LBUTTONDOWN。。。

[/Quote]

果然如此!一会结贴。
雪影 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 windywater 的回复:]
引用 10 楼 tttyd 的回复:
CButtonST屏蔽了双击消息,

我响应了OnLButtonDblClk,里面什么也不做。也响应了OnBnClicked,里面做Invalidate(),还是没效果。
[/Quote]
不能这样,你点击太快就成了双击了,就不会刷新按钮
LRESULT CXXButton::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_LBUTTONDBLCLK)
{
message = WM_LBUTTONDOWN; //在这里屏蔽双击消息
}
return CButton::DefWindowProc(message, wParam, lParam);
} // End of DefWindowProc
zlmzhuanjia 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 tttyd 的回复:]
引用 5 楼 windywater 的回复:
不知道是不是双击造成的影响,因为我发现鼠标定在一个点上不动,快速点击,它会反应不过来。但是点击的过程中鼠标一边慢慢移动,反应是即时的。我用了下CButtonST的Demo,它确实解决了这个问题啊,但不知是怎么做到的。

CButton屏蔽了双击消息,


引用 8 楼 windywater 的回复:
引用 4 楼 dirdirdir3 的回复:
drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了

我把DrawItem全部注释掉了,这样只能看到灰色的一片,可我点击的时候它还是反应不过来啊!

是不是没有按钮没有刷新?
你有没有响应BN_CLICKED消息,在内部调用Invalidate
[/Quote]

up 这个试试
「已注销」 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 tttyd 的回复:]
CButtonST屏蔽了双击消息,
[/Quote]
我响应了OnLButtonDblClk,里面什么也不做。也响应了OnBnClicked,里面做Invalidate(),还是没效果。
bluesky395 2009-08-21
  • 打赏
  • 举报
回复
CButtonST貌似是重载了按钮的PreTranslateMessage,如果是鼠标双击消息WM_LBUTTONDBLCLK时,则替换为鼠标单击消息WM_LBUTTONDOWN。。。
churenxh 2009-08-21
  • 打赏
  • 举报
回复
笔者编写了一个小演示程序,简单模拟电器开关功能。它有两个位图按钮和一个用作状态显示屏的编辑控制框。当鼠标位于位图按钮之上时,状态显示屏均显示"鼠标的光标在位图按钮上"。电源开关开时,按“喇叭”位图按钮则会发声;否则“喇叭”位图按钮变灰,不起作用。

void CBmpDlg::OnMouseMove(UINT nFlags, CPoint point)

{

CWnd * pWnd;

HCURSOR MyCursor;

CRgn m_regionPower; //Region of POWER Button

CRgn m_regionPlay; //Region of PLAY Button

//建立位图按钮的矩形区域

m_regionPower.CreateEllipticRgnIndirect(CRect(27,56,72,92));

m_regionPlay.CreateEllipticRgnIndirect(CRect(78,56,120,92));

CString ShowString0 = "鼠标的光标在位图按钮上!!!";

… … … …

m_bPlay = FALSE;

m_bPower= FALSE;

if (m_regionPower.PtInRegion(point)) //鼠标落在位图按钮之上

{

m_bPower = TRUE;

//将位图按钮设置成获得输入状态

pWnd= GetDlgItem(IDC_BUTTON_POWER);

pWnd->SetFocus();

SetCapture();

InputEdit().SetWindowText(ShowString0);

InputEdit().ShowWindow(TRUE);

//将鼠标光标变成小手形状

MyCursor = AfxGetApp()->LoadCursor(IDC_MYCURSOR);

::SetCursor(MyCursor);

VERIFY(m_Play.LoadBitmaps("PLAYU","PLAYD","PLAYF","PLAYX"));

m_bPressedPlay = FALSE;

return;

}

if (m_regionPlay.PtInRegion(point)) //鼠标落在位图按钮之上

{

if (m_bPowerOn) { //如果电源已被开启

m_bPlay = TRUE;

pWnd= GetDlgItem(IDC_BUTTON_PLAY);

pWnd->SetFocus();

SetCapture();

InputEdit().SetWindowText(ShowString0);

InputEdit().ShowWindow(TRUE);

MyCursor = AfxGetApp()->LoadCursor(IDC_MYCURSOR);

::SetCursor(MyCursor);

VERIFY(m_Power.LoadBitmaps("POWERONU","POWEROND","POWERONF"));

}

else { //如果电源已被关闭

ReleaseCapture();

InputEdit().SetWindowText(ShowString0+ShowString2);

InputEdit().ShowWindow(TRUE);

VERIFY(m_Power.LoadBitmaps("POWEROFU","POWEROFD","POWEROFF"));

}

m_bPressedPower= FALSE;

return;

}

//鼠标落在所有的位图按钮之外

ReleaseCapture();

InputEdit().SetWindowText(ShowString1);

InputEdit().ShowWindow(TRUE);

pWnd= GetDlgItem(IDOK);

pWnd->SetFocus();

VERIFY(m_Play.LoadBitmaps("PLAYU","PLAYD","PLAYF","PLAYX"));

if (m_bPowerOn)

VERIFY(m_Power.LoadBitmaps("POWERONU","POWEROND","POWERONF"));

else

VERIFY(m_Power.LoadBitmaps("POWEROFU","POWEROFD","POWEROFF"));

m_bPressedPlay = FALSE;

m_bPressedPower= FALSE;

CDialog::OnMouseMove(nFlags, point);

}

void CBmpDlg::OnLButtonDown(UINT nFlags, CPoint point)

{

CWnd *pWnd;

if (m_bPlay && m_bPowerOn) {

// Change Focus so as to Change the bitmap of m_Play

pWnd= GetDlgItem(IDOK);

pWnd->SetFocus();

VERIFY(m_Play.LoadBitmaps("PLAYD"));

m_Play.UpdateWindow();

m_Play.Invalidate(TRUE);

OnButtonPlay();

m_bPressedPlay = TRUE;

}

if (m_bPower== TRUE) {

// Change Focus so as to Change the bitmap of m_Power

pWnd= GetDlgItem(IDOK);

pWnd->SetFocus();

if (m_bPowerOn)

VERIFY(m_Power.LoadBitmaps("POWEROND"));

else

VERIFY(m_Power.LoadBitmaps("POWEROFD"));

m_Power.UpdateWindow();

m_Power.Invalidate(TRUE);

OnButtonPower();

m_bPressedPower = TRUE;

}

CDialog::OnLButtonDown(nFlags, point);

}

 

void CBmpDlg::OnLButtonUp(UINT nFlags, CPoint point)

{

CWnd * pWnd;

if (m_bPressedPlay == TRUE) {

pWnd= GetDlgItem(IDOK);

pWnd->SetFocus();

VERIFY(m_Play.LoadBitmaps("PLAYF"));

m_Play.UpdateWindow();

m_Play.Invalidate(TRUE);

m_bPressedPlay = FALSE;

}

if (m_bPressedPower == TRUE) {

pWnd= GetDlgItem(IDOK);

pWnd->SetFocus();

if (m_bPowerOn)

VERIFY(m_Power.LoadBitmaps("POWERONF"));

else

VERIFY(m_Power.LoadBitmaps("POWEROFF"));

m_Power.UpdateWindow();

m_Power.Invalidate(TRUE);

m_bPressedPower = FALSE;

}

CDialog::OnLButtonUp(nFlags, point);

}

你可以参照一下
healer_kx 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jennyvenus 的回复:]
我好像看每个自绘的都反应不过来呢。

[/Quote]
我能说什么呢? 哈哈,lz,你就将就了吧!
雪影 2009-08-21
  • 打赏
  • 举报
回复
CButtonST屏蔽了双击消息,
雪影 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 windywater 的回复:]
不知道是不是双击造成的影响,因为我发现鼠标定在一个点上不动,快速点击,它会反应不过来。但是点击的过程中鼠标一边慢慢移动,反应是即时的。我用了下CButtonST的Demo,它确实解决了这个问题啊,但不知是怎么做到的。
[/Quote]
CButton屏蔽了双击消息,


[Quote=引用 8 楼 windywater 的回复:]
引用 4 楼 dirdirdir3 的回复:
drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了

我把DrawItem全部注释掉了,这样只能看到灰色的一片,可我点击的时候它还是反应不过来啊!
[/Quote]
是不是没有按钮没有刷新?
你有没有响应BN_CLICKED消息,在内部调用Invalidate
「已注销」 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 dirdirdir3 的回复:]
drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了
[/Quote]

我把DrawItem全部注释掉了,这样只能看到灰色的一片,可我点击的时候它还是反应不过来啊!
fishion 2009-08-21
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 dirdirdir3 的回复:]
drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了
[/Quote]
应该就是这个原因了
jyh_baoding 2009-08-21
  • 打赏
  • 举报
回复
看一下CPU占用和内存占用,确认问题的响应造成
「已注销」 2009-08-21
  • 打赏
  • 举报
回复
不知道是不是双击造成的影响,因为我发现鼠标定在一个点上不动,快速点击,它会反应不过来。但是点击的过程中鼠标一边慢慢移动,反应是即时的。我用了下CButtonST的Demo,它确实解决了这个问题啊,但不知是怎么做到的。
dirdirdir3 2009-08-21
  • 打赏
  • 举报
回复
drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了
雪影 2009-08-21
  • 打赏
  • 举报
回复
1.那你先参考一下CButtonST的代码,和你的有什么不同,会不会就是这这不同造成的呢?
2.另外不仅仅是重载DrawItem就可以的,你还得响应BN_CLICKED消息,在内部调用Invalidate,刷新按钮
job82824 2009-08-21
  • 打赏
  • 举报
回复
是不是你只重载了DrawItem,而没有重载鼠标消息响应函数LBUTTONDOWN LBUTTONUP呢?
用户 昵称 2009-08-21
  • 打赏
  • 举报
回复
我好像看每个自绘的都反应不过来呢。

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧