最近在做一个MFC项目,部分界面如下:
点击加号/减号,可以调整Edit框内数字大小,但是通过响应按键的click消息,每次点击只能加1/减1,如果我们要调整到一个较大的数字,需要多次点击。直觉告诉我,如果通过长按按键快速的变化数字,可以解决这一问题。
但是MFC button控件默认即没有与按键长按对应的消息,也没有按下和松开的消息,如图:
于是问题变得麻烦,以下是我的方法。
1、拦截鼠标左键按下和松开操作
2、判断1中操作的坐标是否为按键坐标
3、如果满足1、2则触发定时器循环执行按键click回调函数
实现代码:
1、在窗口类内添加成员函数
BOOL PreTranslateMessage(MSG* pMsg);
2、编写成员函数
BOOL Cdianji_kz_V11Dlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_LBUTTONDOWN)//拦截鼠标左键按下消息
{
if(pMsg->hwnd == GetDlgItem(IDC_BTN_PLUS)->m_hWnd)//判断按下的位置是否为目标button
{
btn_add_plus_flag=1;//表示加
btn_add_plus_first_flag=1;//表示按下
SetTimer(2,50,NULL);//触发定时器,按1秒加20
}
else if(pMsg->hwnd == GetDlgItem(IDC_BTN_SUB)->m_hWnd)
{
btn_add_plus_flag=2;//表示减
SetTimer(2,150,NULL);//按1秒减7
}
}
else if(pMsg->message == WM_LBUTTONUP)
{
if(pMsg->hwnd == GetDlgItem(IDC_BTN_PLUS)->m_hWnd)
{
btn_add_plus_flag=0;//清除标志
btn_add_plus_first_flag=0;//清除标志
KillTimer(2);//关闭定时器
}
else if(pMsg->hwnd == GetDlgItem(IDC_BTN_SUB)->m_hWnd)
{
btn_add_plus_flag=0;
KillTimer(2);
}
}
return CDialog::PreTranslateMessage(pMsg); //一定要有,其他消息系统默认处理
}
3、编写定时器回调函数
void Cdianji_kz_V11Dlg::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 2: ///处理ID为24的定时器
long_sub_add();
break;
}
CDialog::OnTimer(nIDEvent);
}
int Cdianji_kz_V11Dlg::long_sub_add(void)
{
if (btn_add_plus_first_flag==1)
{
Sleep(150);
btn_add_plus_first_flag=0;
}
else if (btn_add_plus_flag==1)
{
OnBnClickedBtnPlus(); //按钮“+”click消息对应的函数
}
else if(btn_add_plus_flag==2)
{
OnBnClickedBtnSub();//按钮“-” click消息对应的函数
}
return 0;
}
btn_add_plus_flag 标志位作用不难看出,因为点“+”和“-”按键触发的是同一个定时器,执行的是同一个定时器回调函数,所以用这个变量来区分两个按键,对应不同的操作。
btn_add_plus_first_flag 标志设置的原因,我们在程序中设置的是如果“+”按键被按下,则使能定期器2,“+”按键松开,关闭定时器,定时器2回调函数是以50ms为一个周期调用按键click回调函数(也就是说自动的一秒点击20次“+”按键)。也就是说定时器执行的总时间与我们按键按下的时间成正比,因此长按实现了循环的“+”的操作。
但这就存在一个问题,如果当我们想实现加1的操作时,点击一次按钮会有100ms左右的操作延时,因此即执行了原来的click回调函数,又会触发定时器函数,所以点一次按键可能加2或3。因此需要设置一个标志,延时执行定时器函数,避免想加1加过头的情况!