介绍 我需要一个自动重复按钮。当用户按下按钮时,它会发出多个BN_CLICKED 通知。我搜索了一下,发现了Joseph M. Newcomer的文章“自动重复按钮类”。虽然文章中的代码和广告中的完全一样,但它有一个主要的缺陷。当用户按下空格键时,它不工作,它只与鼠标左键工作。文章后附的评论提供了一些如何修复它的想法,但没有一个是理想的。我采纳了这篇文章中提出的想法和一些评论,编写了我在这里分享的代码。 使用的代码 让按钮控件做我需要它做的事情的最好方法是子类化cbuttoncontrol并覆盖它的OnLButtonDown、OnLButtonUp、OnKeyDown和onkeyupmessage处理器。我添加了4个bool 成员变量,作为标志来控制在使用控件时发生了什么以及接下来必须发生什么。前两个变量是keypress&和mousepress&which控制是鼠标按钮还是空格键启动计时器。下一个是TimerActive 防止计时器被重新启动时,按键自动重复。最后一个是控制按钮被释放时是否发送消息的messagesent。 隐藏,收缩,复制Code
void CAutoRepeatButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if (!MousePress) // Only if not already activated by the mouse { if (VK_SPACE == nChar && !TimerActive) { SetTimer(TIMERID, InitialTime, NULL); TimerActive = true; KeyPress = true; } CButton::OnKeyDown(nChar, nRepCnt, nFlags); } } void CAutoRepeatButton::OnLButtonDown(UINT nFlags, CPoint point) { if (!KeyPress) // Only if not already activated with the space bar { if (!TimerActive) { SetTimer(TIMERID, InitialTime, NULL); TimerActive = true; MousePress = true; } CButton::OnLButtonDown(nFlags, point); } }
当用鼠标左键或空格键按下按钮时,我们首先检查该按钮是否已被另一个按钮激活。然后我们检查计时器是否还没有启动,如果没有启动,则用初始延迟时间启动它。最后,调用基类处理程序来执行默认处理程序,该处理程序捕获鼠标并将按钮绘制为按下按钮。 隐藏,复制Code
void CAutoRepeatButton::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent == TIMERID) { if (BST_PUSHED == (BST_PUSHED & GetState())) { if (!MessageSent) { SetTimer(TIMERID, RepeatTime, NULL); MessageSent = true; } Parent->SendMessage(WM_COMMAND, MAKELPARAM(GetDlgCtrlID(), BN_CLICKED), (WPARAM)m_hWnd); } } else { CButton::OnTimer(nIDEvent); } }
当定时器触发时,我们首先检查按钮的状态。如果鼠标被用来开始定时器,然后它被移离按钮,按钮将不再被按下,所以我们将不希望消息被发送。但我们希望当鼠标移动到按钮上时它们继续。在初始时间延迟之后,定时器被重置为重复时间,a 被发送消息。 隐藏,收缩,复制Code
void CAutoRepeatButton::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (VK_SPACE == nChar && KeyPress) { KillTimer(TIMERID); if (MessageSent) { ReleaseCapture(); // CButton::OnKeyDown captures the mouse SetState(0); // Redraw button as not pushed } else { CButton::OnKeyUp(nChar, nRepCnt, nFlags); } TimerActive = false; KeyPress = false; MessageSent = false; } } void CAutoRepeatButton::OnLButtonUp(UINT nFlags, CPoint point) { if (MousePress) { KillTimer(TIMERID); if (MessageSent) { ReleaseCapture(); SetState(0); } else { CButton::OnLButtonUp(nFlags, point); } TimerActive = false; MousePress = false; MessageSent = false; } }
当按钮被释放时,计时器停止。然后,根据按钮是否被长时间按住以生成BN_CLICKED 消息,我们要么简单地释放鼠标捕获并绘制按钮作为未按下,或者我们调用基类处理程序来发射BN_CLICKED 消息。然后在下一次按下按钮时重新设置标志。 隐藏,复制Code
void CAutoRepeatButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
最后要处理的是用户双击按钮后按住按钮。我只是调用onlbuttondown来将双击视为第二次单击。如果不这样做,则计时器不会启动。 隐藏,复制Code
void CAutoRepeatButton::SetTimes(UINT Initial, UINT Repeat)
{
InitialTime = Initial;
RepeatTime = Repeat;
}
最后,作为一个方便的函数,我添加了设置初始和重复延迟时间间隔的功能。 历史 2017年4月13日——发表在CodeProject上 本文转载于:http://www.diyabc.com/frontweb/news359.html