How do I set the "default button"

本文介绍了两种设置默认按钮的方法:一种是通过设置键盘等效键,另一种是通过窗口设置默认按钮单元格。推荐使用第二种方法,因为它更加灵活且不会导致按钮颜色变暗的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

How do I set the "default button"(activated when the user presses RETURN), OR:My buttons which used to be default turn dark grey.

----------------------------------------------------------------------

There are two ways to set the "default" button,A. [myButton setKeyEquivalent:@"\r"];B. [myWindow setDefaultButtonCell:[myButton cell]];Version 'B' is better, since, with Version A, if you turn off thekeyEquivalent (i.e. set it to the empty string or something) then thebutton will end up a dark-grey color, depending on how dark the bluepulsing was when the switch occurred.

这是我的button.h和button.c文件 /** * @File: flexible_button.h * @Author: MurphyZhao * @Date: 2018-09-29 * * Copyright (c) 2018-2019 MurphyZhao <d2014zjt@163.com> * https://github.com/murphyzhao * All rights reserved. * License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Change logs: * Date Author Notes * 2018-09-29 MurphyZhao First add * 2019-08-02 MurphyZhao Migrate code to github.com/murphyzhao account * 2019-12-26 MurphyZhao Refactor code and implement multiple clicks * */ #ifndef __BUTTON_H__ #define __BUTTON_H__ #include "stdint.h" #include "key_app.h" #include "KEY.h" #define FLEX_BTN_SCAN_FREQ_HZ 50 // How often flex_button_scan () is called #define FLEX_MS_TO_SCAN_CNT(ms) (ms / (1000 / FLEX_BTN_SCAN_FREQ_HZ)) /* Multiple clicks interval, default 300ms */ #define MAX_MULTIPLE_CLICKS_INTERVAL (FLEX_MS_TO_SCAN_CNT(300)) /** * @brief 按钮事件枚举类型 * * 定义了各种按钮触发事件类型,包括: * - 按下(FLEX_BTN_PRESS_DOWN) * - 单击(FLEX_BTN_PRESS_CLICK) * - 双击(FLEX_BTN_PRESS_DOUBLE_CLICK) * - 重复点击(FLEX_BTN_PRESS_REPEAT_CLICK) * - 短按开始(FLEX_BTN_PRESS_SHORT_START) * - 短按抬起(FLEX_BTN_PRESS_SHORT_UP) * - 长按开始(FLEX_BTN_PRESS_LONG_START) * - 长按抬起(FLEX_BTN_PRESS_LONG_UP) * - 长按保持(FLEX_BTN_PRESS_LONG_HOLD) * - 长按保持后抬起(FLEX_BTN_PRESS_LONG_HOLD_UP) * - 最大值(FLEX_BTN_PRESS_MAX) * - 无事件(FLEX_BTN_PRESS_NONE) */ typedef enum { FLEX_BTN_PRESS_DOWN = 0, FLEX_BTN_PRESS_CLICK, FLEX_BTN_PRESS_DOUBLE_CLICK, FLEX_BTN_PRESS_REPEAT_CLICK, FLEX_BTN_PRESS_SHORT_START, FLEX_BTN_PRESS_SHORT_UP, FLEX_BTN_PRESS_LONG_START, FLEX_BTN_PRESS_LONG_UP, FLEX_BTN_PRESS_LONG_HOLD, FLEX_BTN_PRESS_LONG_HOLD_UP, FLEX_BTN_PRESS_MAX, FLEX_BTN_PRESS_NONE, } flex_button_event_t; /** * flex_button_t * * @brief Button data structure * Below are members that need to user init before scan. * * @member next * Internal use. * One-way linked list, pointing to the next button. * * @member usr_button_read * User function is used to read button vaule. * * @member cb * Button event callback function. * * @member scan_cnt * Internal use, user read-only. * Number of scans, counted when the button is pressed, plus one per scan cycle. * * @member click_cnt * Internal use, user read-only. * Number of button clicks * * @member max_multiple_clicks_interval * Multiple click interval. Default 'MAX_MULTIPLE_CLICKS_INTERVAL'. * Need to use FLEX_MS_TO_SCAN_CNT to convert milliseconds into scan cnts. * * @member debounce_tick * Debounce. Not used yet. * Need to use FLEX_MS_TO_SCAN_CNT to convert milliseconds into scan cnts. * * @member short_press_start_tick * Short press start time. Requires user configuration. * Need to use FLEX_MS_TO_SCAN_CNT to convert milliseconds into scan cnts. * * @member long_press_start_tick * Long press start time. Requires user configuration. * Need to use FLEX_MS_TO_SCAN_CNT to convert milliseconds into scan cnts. * * @member long_hold_start_tick * Long hold press start time. Requires user configuration. * * @member id * Button id. Requires user configuration. * When multiple buttons use the same button callback function, * they are used to distinguish the buttons. * Each button id must be unique. * * @member pressed_logic_level * Requires user configuration. * The logic level of the button pressed, each bit represents a button. * * @member event * Internal use, users can call 'flex_button_event_read' to get current button event. * Used to record the current button event. * * @member status * Internal use, user unavailable. * Used to record the current state of buttons. * */ typedef struct flex_button { struct flex_button* next; uint8_t (*usr_button_read)(void *); flex_button_response_callback cb; uint16_t scan_cnt; uint16_t click_cnt; uint16_t max_multiple_clicks_interval; uint16_t debounce_tick; uint16_t short_press_start_tick; uint16_t long_press_start_tick; uint16_t long_hold_start_tick; uint8_t id; uint8_t pressed_logic_level : 1; uint8_t event : 4; uint8_t status : 3; } flex_button_t; #ifdef __cplusplus extern "C" { #endif int32_t flex_button_register(flex_button_t *button); flex_button_event_t flex_button_event_read(flex_button_t* button); uint8_t flex_button_scan(void); void user_button_init(void); #ifdef __cplusplus } #endif #endif /* __FLEXIBLE_BUTTON_H__ */ /** * @File: flexible_button.c * @Author: MurphyZhao * @Date: 2018-09-29 * * Copyright (c) 2018-2019 MurphyZhao <d2014zjt@163.com> * https://github.com/murphyzhao * All rights reserved. * License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Change logs: * Date Author Notes * 2018-09-29 MurphyZhao First add * 2019-08-02 MurphyZhao Migrate code to github.com/murphyzhao account * 2019-12-26 MurphyZhao Refactor code and implement multiple clicks * */ #include "button.h" #include "KEY.h" #include "string.h" #include "key_app.h" typedef enum { USER_BUTTON_UP = 0, // 对应 IoT Board 开发板的 PIN_KEY0 USER_BUTTON_LEFT, // 对应 IoT Board 开发板的 PIN_KEY1 USER_BUTTON_RIGHT, // 对应 IoT Board 开发板的 PIN_KEY2 USER_BUTTON_DOWN, USER_BUTTON_MID, // 对应 IoT Board 开发板的 PIN_WK_UP USER_BUTTON_MAX } user_button_t; static flex_button_t user_button[USER_BUTTON_MAX]; static uint8_t common_btn_read(void *arg) { uint8_t value = 0; flex_button_t *btn = (flex_button_t *)arg; switch (btn->id) { case USER_BUTTON_UP: value = key_scan().up; break; case USER_BUTTON_LEFT: value = key_scan().left; break; case USER_BUTTON_RIGHT: value =key_scan().right; break; case USER_BUTTON_DOWN: value = key_scan().down; break; case USER_BUTTON_MID: value = key_scan().mid; break; } return value; } // 配置项 说明 // id 按键编号 // usr_button_read 设置按键读值回调函数 // cb 设置按键事件回调函数 // pressed_logic_level 设置按键按下时的逻辑电平 // short_press_start_tick 短按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数 // long_press_start_tick 长按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数 // long_hold_start_tick 超长按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数 // 注意,short_press_start_tick、long_press_start_tick 和 long_hold_start_tick 必须使用 FLEX_MS_TO_SCAN_CNT 将毫秒时间转化为扫描次数。 // user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500); 表示按键按下开始计时,1500 ms 后按键依旧是按下状态的话,就断定为短按开始。 //--------------------------------------------------改到这里了----------------------------- void user_button_init(void) { int i; memset(&user_button[0], 0x0, sizeof(user_button)); user_button[USER_BUTTON_UP].cb = up_btn_evt_cb; user_button[USER_BUTTON_LEFT].cb = left_btn_evt_cb; user_button[USER_BUTTON_RIGHT].cb = right_btn_evt_cb; user_button[USER_BUTTON_DOWN].cb = down_btn_evt_cb; user_button[USER_BUTTON_MID].cb = mid_btn_evt_cb; for (i = 0; i < USER_BUTTON_MAX; i ++) { user_button[i].id = i; user_button[i].usr_button_read = common_btn_read; user_button[i].pressed_logic_level = 0; user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500); user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(3000); user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(4500); flex_button_register(&user_button[i]); } } #ifndef NULL #define NULL 0 #endif #define EVENT_SET_AND_EXEC_CB(btn, evt) \ do \ { \ btn->event = evt; \ if(btn->cb) \ btn->cb((flex_button_t*)btn); \ } while(0) /** * BTN_IS_PRESSED * * 1: is pressed * 0: is not pressed */ #define BTN_IS_PRESSED(i) (g_btn_status_reg & (1 << i)) enum FLEX_BTN_STAGE { FLEX_BTN_STAGE_DEFAULT = 0, FLEX_BTN_STAGE_DOWN = 1, FLEX_BTN_STAGE_MULTIPLE_CLICK = 2 }; typedef uint32_t btn_type_t; static flex_button_t *btn_head = NULL; /** * g_logic_level * * The logic level of the button pressed, * Each bit represents a button. * * First registered button, the logic level of the button pressed is * at the low bit of g_logic_level. */ btn_type_t g_logic_level = (btn_type_t)0; /** * g_btn_status_reg * * The status register of all button, each bit records the pressing state of a button. * * First registered button, the pressing state of the button is * at the low bit of g_btn_status_reg. */ btn_type_t g_btn_status_reg = (btn_type_t)0; static uint8_t button_cnt = 0; /** * @brief Register a user button * * @param button: button structure instance * @return Number of keys that have been registered, or -1 when error */ int32_t flex_button_register(flex_button_t *button) { flex_button_t *curr = btn_head; if (!button || (button_cnt > sizeof(btn_type_t) * 8)) { return -1; } while (curr) { if(curr == button) { return -1; /* already exist. */ } curr = curr->next; } /** * First registered button is at the end of the 'linked list'. * btn_head points to the head of the 'linked list'. */ button->next = btn_head; button->status = FLEX_BTN_STAGE_DEFAULT; button->event = FLEX_BTN_PRESS_NONE; button->scan_cnt = 0; button->click_cnt = 0; button->max_multiple_clicks_interval = MAX_MULTIPLE_CLICKS_INTERVAL; btn_head = button; /** * First registered button, the logic level of the button pressed is * at the low bit of g_logic_level. */ g_logic_level |= (button->pressed_logic_level << button_cnt); button_cnt ++; return button_cnt; } /** * @brief Read all key values in one scan cycle * * @param void * @return none */ static void flex_button_read(void) { uint8_t i; flex_button_t* target; /* The button that was registered first, the button value is in the low position of raw_data */ btn_type_t raw_data = 0; for(target = btn_head, i = button_cnt - 1; (target != NULL) && (target->usr_button_read != NULL); target = target->next, i--) { raw_data = raw_data | ((target->usr_button_read)(target) << i); } g_btn_status_reg = (~raw_data) ^ g_logic_level; } /** * @brief Handle all key events in one scan cycle. * Must be used after 'flex_button_read' API * * @param void * @return Activated button count */ static uint8_t flex_button_process(void) { uint8_t i; uint8_t active_btn_cnt = 0; flex_button_t* target; for (target = btn_head, i = button_cnt - 1; target != NULL; target = target->next, i--) { if (target->status > FLEX_BTN_STAGE_DEFAULT) { target->scan_cnt ++; if (target->scan_cnt >= ((1 << (sizeof(target->scan_cnt) * 8)) - 1)) { target->scan_cnt = target->long_hold_start_tick; } } switch (target->status) { case FLEX_BTN_STAGE_DEFAULT: /* stage: default(button up) */ if (BTN_IS_PRESSED(i)) /* is pressed */ { target->scan_cnt = 0; target->click_cnt = 0; EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_DOWN); /* swtich to button down stage */ target->status = FLEX_BTN_STAGE_DOWN; } else { target->event = FLEX_BTN_PRESS_NONE; } break; case FLEX_BTN_STAGE_DOWN: /* stage: button down */ if (BTN_IS_PRESSED(i)) /* is pressed */ { if (target->click_cnt > 0) /* multiple click */ { if (target->scan_cnt > target->max_multiple_clicks_interval) { EVENT_SET_AND_EXEC_CB(target, target->click_cnt < FLEX_BTN_PRESS_REPEAT_CLICK ? target->click_cnt : FLEX_BTN_PRESS_REPEAT_CLICK); /* swtich to button down stage */ target->status = FLEX_BTN_STAGE_DOWN; target->scan_cnt = 0; target->click_cnt = 0; } } else if (target->scan_cnt >= target->long_hold_start_tick) { if (target->event != FLEX_BTN_PRESS_LONG_HOLD) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_LONG_HOLD); } } else if (target->scan_cnt >= target->long_press_start_tick) { if (target->event != FLEX_BTN_PRESS_LONG_START) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_LONG_START); } } else if (target->scan_cnt >= target->short_press_start_tick) { if (target->event != FLEX_BTN_PRESS_SHORT_START) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_SHORT_START); } } } else /* button up */ { if (target->scan_cnt >= target->long_hold_start_tick) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_LONG_HOLD_UP); target->status = FLEX_BTN_STAGE_DEFAULT; } else if (target->scan_cnt >= target->long_press_start_tick) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_LONG_UP); target->status = FLEX_BTN_STAGE_DEFAULT; } else if (target->scan_cnt >= target->short_press_start_tick) { EVENT_SET_AND_EXEC_CB(target, FLEX_BTN_PRESS_SHORT_UP); target->status = FLEX_BTN_STAGE_DEFAULT; } else { /* swtich to multiple click stage */ target->status = FLEX_BTN_STAGE_MULTIPLE_CLICK; target->click_cnt ++; } } break; case FLEX_BTN_STAGE_MULTIPLE_CLICK: /* stage: multiple click */ if (BTN_IS_PRESSED(i)) /* is pressed */ { /* swtich to button down stage */ target->status = FLEX_BTN_STAGE_DOWN; target->scan_cnt = 0; } else { if (target->scan_cnt > target->max_multiple_clicks_interval) { EVENT_SET_AND_EXEC_CB(target, target->click_cnt < FLEX_BTN_PRESS_REPEAT_CLICK ? target->click_cnt : FLEX_BTN_PRESS_REPEAT_CLICK); /* swtich to default stage */ target->status = FLEX_BTN_STAGE_DEFAULT; } } break; } if (target->status > FLEX_BTN_STAGE_DEFAULT) { active_btn_cnt ++; } } return active_btn_cnt; } /** * flex_button_event_read * * @brief Get the button event of the specified button. * * @param button: button structure instance * @return button event */ flex_button_event_t flex_button_event_read(flex_button_t* button) { return (flex_button_event_t)(button->event); } /** * flex_button_scan * * @brief Start key scan. * Need to be called cyclically within the specified period. * Sample cycle: 5 - 20ms * * @param void * @return Activated button count */ uint8_t flex_button_scan(void) { flex_button_read(); return flex_button_process(); }
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值