按键单双多击、长按、多按知识层
这个主题解决什么问题
按键单双多击、长按、多按解决的是“同一个按键输入在时间和组合关系上表达不同含义”的问题。
普通按键只关心按下瞬间;复杂按键需要进一步识别:
-
多个键是否同时按下
-
某个键按住了多久
-
某个键在时间窗口内点击了几次
-
长按和单击、双击是否需要互斥
因此它的核心不是多写几个 if,而是理解按键状态、边沿、持续时间、时间窗口之间的关系。
按键状态的三种基础信号
复杂按键识别通常依赖三类基础信号:
-
key_val:当前正在按住的键值,表示持续状态 -
key_down:本轮新按下的键,表示按下边沿 -
key_up:本轮刚松开的键,表示释放边沿
三者职责不同:
-
判断“是否正在长按”时看
key_val -
判断“一次按下动作发生了”时看
key_down -
判断“一次完整点击结束了”时看
key_up
原始笔记中长按计时使用 key_val == 32,而不是 key_down == 32,这点很关键。key_down 只会在按下边沿出现一次,不能表示持续按住。
多按的知识点
多按本质上是按键值的组合判断。
例如原始笔记中:
if (key_down == 48)
{
num--;
}
这里的 48 不是魔法数,而是两个按键的组合值。若 S8 和 S9 分别对应 16 和 32,同时按下时组合结果就是 16 + 32 = 48。
多按的稳定知识是:
-
按键底层返回值通常是位掩码或组合码
-
同时按下多个键时,结果会表现为多个按键值叠加
-
调试显示
key_val可以反推出组合值
长按的知识点
长按识别由两个动作组成:
-
按住期间持续计时
-
松手时根据累计时间决定是短按还是长按
原始笔记中的核心关系是:
if (key_val == 32)
{
key_val_32_time++;
}
if (key_up == 32)
{
if (key_val_32_time > 1000)
{
num--;
}
else
{
num++;
}
key_val_32_time = 0;
}
这里的稳定知识是:
-
长按计时应绑定“当前按住状态”
-
动作执行应放在松手边沿,避免按住期间反复触发
-
计时变量在松手后必须清零
如果 1ms 调用一次计时逻辑,1000 就约等于 1s。若计时逻辑不在 1ms 基准下运行,阈值含义会改变。
多击的知识点
多击识别依赖一个“等待窗口”。
每次松手后:
-
点击次数加 1
-
重置一个倒计时窗口,例如 300ms
当 300ms 窗口归零,并且点击次数大于 0 时,再统一判断单击、双击、三击等动作。
原始笔记中的核心关系是:
if (key_up == 32)
{
key_32_click_cnt++;
key_32_click_time300ms = 300;
}
if ((key_32_click_time300ms == 0) && (key_32_click_cnt > 0))
{
/* 根据 click_cnt 执行动作 */
key_32_click_cnt = 0;
}
这背后的稳定知识是:
-
多击不能在第一次松手时立刻判定单击
-
必须等待一个时间窗口,确认后面没有第二击或第三击
-
click_cnt > 0是防止没有点击时误执行逻辑 -
执行动作后必须把点击次数清零
长按和多击共存的关系
长按和多击共存时,最关键的是互斥。
原始笔记中的逻辑是:
-
松手时先判断是否超过长按阈值
-
如果是长按,直接执行长按动作
-
如果不是长按,才纳入点击次数统计
这说明:
-
长按不应该再被当成一次单击
-
单击、双击、三击属于短按序列
-
长按计时变量和点击计数变量都需要在合适时机回正
依赖的前置知识
要稳定使用复杂按键,需要先理解:
-
矩阵键盘或独立按键的基础扫描结果
-
key_val / key_down / key_up三类信号的区别 -
1ms 系统节拍和减速计数
-
位掩码或组合键值的含义
其中最容易混淆的是:按住计时看 key_val,动作结算多看 key_up。
常见错误
-
用
key_down做长按计时,导致只加一次计数 -
松手后忘记清零长按计时变量,下一次短按被误判为长按
-
多击动作不等待窗口归零,导致双击先触发一次单击
-
执行多击动作后忘记清零
click_cnt -
长按和单击没有互斥,长按松手后又被算作一次点击
-
只记住组合键数值,不理解它来自按键位值叠加
这份知识层的边界
这份笔记只说明复杂按键识别中的状态、边沿、计时窗口和互斥关系。
暂时不展开:
-
每个按键的可复用结构体封装
-
多个按键同时支持长按和多击的通用框架
-
比赛现场如何根据题意选择短按、长按或双击
-
完整执行层代码模板
这些内容后续应继续放到:
-
03-决策层 -
04-执行层 -
05-练习层
超短复习卡
-
key_val看持续按住,key_down看按下边沿,key_up看松手边沿 -
多按 = 按键组合值,常通过调试显示确认
-
长按 = 按住计时,松手结算,结算后清零
-
多击 = 松手计数,等待窗口归零后统一判定
-
长按和多击共存时,长按优先,短按才进入点击计数