写在前面
之前用 FLTK 时候就注意到了 FLTK 生成的界面按一下ESC 就退出了, 虽然不是大问题, 但是还是不算好, 最近搜到了一篇论坛文章, 完美解决了这个问题, 这里其实就是对文章的一个翻译了.
Article #378: Why Does the Escape Key Close My Window? - Fast Light Toolkit (FLTK);
下面以一个简单的例子来说明回调函数的作用.
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Window.H>
int main(int argc, char *argv[]) {
Fl_Window *window;
Fl_Box *box;
window = new Fl_Window(300, 180);
window->label("HelloWorld!");
box = new Fl_Box(20, 40, 260, 100, "Hello World!");
box->box(FL_UP_BOX);
box->labelsize(36);
box->labelfont(FL_BOLD + FL_ITALIC);
box->labeltype(FL_SHADOW_LABEL);
window->end();
window->show(argc, argv);
return Fl::run();
}
来自官方的 helloworld 例子
2 - FLTK Basics; 下面是 Makefile
CXX = $(shell fltk-config --cxx) DEBUG = CXXFLAGS = $(shell fltk-config --cxxflags ) -I. LDFLAGS = $(shell fltk-config --ldflags ) TARGET = helloworld SRCS = main.cpp $(TARGET): $(SRCS) $(CXX) $(CXXFLAGS) $(LDFLAGS) $(DEBUG) -o $(TARGET) $< all: $(TARGET) clean: $(TARGET) rm -f $(TARGET) 2> /dev/null
大家可以试一下, 直接按 ESC 会发生什么
方法一: 使用全局事件控制器
这个方法比较容易, 但是会吞掉所有传入主窗口的快捷键, 如果不需要设置快捷键可以用这个, 我这里设置了 lambda 一行解决问题
// method 1: easy to set, but eat all shortcut keys
Fl::add_handler([](int event) -> int { return event == FL_SHORTCUT; });
其实这里执行了隐式类型转换, lambda 转换成参数和返回值都是 int 类型的函数指针.
方法二: 使用句柄函数
这个的定制型更强一些, 当然也要多写几行代码了
// method 2
window->callback(my_callback);
回调函数只针对当前窗口, 即
[[maybe_unused]] void my_callback(Fl_Widget *, void *) {
if (Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape)
return; // just ignore Escape
}
上面的回调意味着仅忽略 ESC 键的影响, 如果要在 ESC 或者按下关闭按钮两种情况下都弹出关闭确认对话框, 还需要下面的操作:
// #include <FL/Fl_File_Chooser.H> // fl_choice
if (!fl_choice(
"Are you really absolutely positively certain you want to quit?",
"yes", "no", 0))
exit(0);
上面的 fl_choice 的默认值是yes, 通过逻辑非变成 no.