文書の過去の版を表示しています。
メニュー
Fl_Menu_クラス
Fl_Menu_クラスの名前に注意してください。 Fl_Class_Name_のように、末尾にアンダースコアがついているクラスはユーザーが直接そのクラスのインスタンスオブジェクトを作成して利用するためのものではありません。 継承によって派生クラスに共通の性質を提供するために存在しています。
Fl_Menu_クラスは抽象クラスであり、抽象クラスのオブジェクトを作成するような誤ったC++のコードはコンパイルされません。
#include <FL/Fl_Menu_.H>
...
auto m = new Fl_Menu_(...); // コンパイルエラー!
なお、名前にアンダースコアのついていないFl_Menuクラスは存在しないので、ご注意ください。 具体的な用途によって、Fl_Menu_Barクラス、Fl_Menu_Buttonクラス、Fl_Choiceクラスが派生クラスとして提供されています。
Fl_Menu_クラス前後の階層図
Fl_Menu_Barクラス
典型的なGUIアプリケーションで目にする、ウィンドウ最上部のメニューバーを実現するためのクラスです。 FLTKではメニューバーもやはりウィジェットです。 サイズや位置を設定することができるので、必ずしもウィンドウの最上部に配置しなければならないことはありません。 この自由度は一方であまり直感的とは言えない使い方が求められます。 例えば、次のようなことが考えられます。
- メニューバーの初期サイズにウィンドウのサイズと同じだけの幅とUIフォントのサイズを考慮した高さを与えることが必須である。
- ユーザーがマウスでウィンドウの枠をドラッグしてサイズを変更したときにメニューバーが縦に拡大されることを回避するよう配慮しないといけない。
次のサンプルプログラムでは、メニューバーの構築方法と、ウィンドウのサイズ変更に対して自然な振る舞いになるようにする方法を示しています。
#include <FL/Fl.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Window.H>
#include <FL/fl_ask.H>
#include <FL/Fl_File_Chooser.H>
#include <cstdio>
void file_open_cb(Fl_Widget *w, void *data) {
if (auto file_name = fl_file_chooser("select file", "*.cpp", "foo.cpp", 1)) {
printf("Chosen file: %s\n", file_name);
}
}
void file_quit_cb(Fl_Widget *w, void *data) {
if (fl_choice_n("Do you really want to quit?", "&No", "&Yes", nullptr) == 1) {
Fl::hide_all_windows();
}
}
void edit_undo_cb(Fl_Widget *w, void *data) { /* TODO */ }
void edit_redo_cb(Fl_Widget *w, void *data) { /* TODO */ }
void edit_cut_cb(Fl_Widget *w, void *data) { /* TODO */ }
void edit_copy_cb(Fl_Widget *w, void *data) { /* TODO */ }
void edit_paste_cb(Fl_Widget *w, void *data) { /* TODO */ }
void help_help_cb(Fl_Widget *w, void *data) {
fl_message("I'm sorry, but I cannot help you now.");
}
void help_about_cb(Fl_Widget *w, void *data) {
fl_message("The purpose of this program is to demonstrate how to use Fl_Menu_Bar.");
}
int main(int argc, char **argv) {
auto window = new Fl_Window{400, 400, "Menu demo"};
auto menu_bar = new Fl_Menu_Bar{0, 0, window->w(), 30, "Menu"};
menu_bar->add("ファイル(&F)/開く(&O)", FL_COMMAND + 'o', file_open_cb, nullptr, FL_MENU_DIVIDER);
menu_bar->add("ファイル(&F)/終了(&Q)", FL_COMMAND + 'q', file_quit_cb);
menu_bar->add("編集(&E)/元に戻す(&U)", "^z", edit_undo_cb);
menu_bar->add("編集(&E)/やり直し(&R)", "^Z", edit_redo_cb, nullptr, FL_MENU_DIVIDER);
menu_bar->add("編集(&E)/切り取り(&X)", "^x", edit_cut_cb);
menu_bar->add("編集(&E)/コピー(&C)", "^c", edit_copy_cb);
menu_bar->add("編集(&E)/貼り付け(&P)", "^v", edit_paste_cb);
menu_bar->add("編集(&E)/削除(&D)");
menu_bar->add("編集(&E)/すべて選択(&A)", "^a", edit_paste_cb);
menu_bar->add("ヘルプ(&H)/ヘルプ(&H)", FL_F + 1, help_help_cb);
menu_bar->add("ヘルプ(&H)/このアプリケーションについて...(&A)", FL_SHIFT + FL_F + 1, help_about_cb);
menu_bar->menu_end();
// マウスでドラッグしてウィンドウのサイズを変更できるようにする
// ただし、メニューバーの高さは変化しないようにする
// メニューバーの領域を含めないことがポイント
auto group = new Fl_Group{0, menu_bar->h(), window->w(), window->h() - menu_bar->h()};
group->end();
window->resizable(group);
window->end();
window->show(argc, argv);
// https://www.fltk.org/doc-1.4/classFl__Menu__.html#a8db18d83b2166eaba3b4b465ef0373a0
for (int t = 0; t < menu_bar->size(); t++) { // walk array of items
const Fl_Menu_Item &item = menu_bar->menu()[t]; // get each item
fprintf(stderr, "item #%d -- label=%s,\tvalue=%s,\ttype=%s\n", t,
item.label() ? item.label() : "(Null)", // menu terminators have NULL labels
(item.flags & FL_MENU_VALUE) ? "set" : "clear", // value of toggle or radio items
(item.flags & FL_SUBMENU) ? "Submenu" : "Item"); // see if item is a submenu or actual item
}
return Fl::run();
}
Fl_Menu_Buttonクラス
Fl_Menu_Buttonクラス前後の階層図
#include <FL/Fl.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Window.H>
#include <cstdio>
void the_cb(Fl_Widget *w, void *data) {}
void strange_cb(Fl_Widget *w, void *data) {}
void charm_cb(Fl_Widget *w, void *data) {}
void truth_cb(Fl_Widget *w, void *data) {}
void beauty_cb(Fl_Widget *w, void *data) {}
int main(int argc, char **argv) {
auto window = new Fl_Window{400, 400, "Menu demo"};
// https://www.fltk.org/doc-1.4/structFl__Menu__Item.html#details
Fl_Menu_Item popup[] = {{"&alpha", FL_ALT + 'a', the_cb, (void *)1},
{"&beta", FL_ALT + 'b', the_cb, (void *)2},
{"gamma", FL_ALT + 'c', the_cb, (void *)3, FL_MENU_DIVIDER},
{"&strange", 0, strange_cb},
{"&charm", 0, charm_cb},
{"&truth", 0, truth_cb},
{"b&eauty", 0, beauty_cb},
{"sub&menu", 0, 0, 0, FL_SUBMENU},
{"one"},
{"two"},
{"three"},
{0},
{"inactive", FL_ALT + 'i', 0, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER},
{"invisible", FL_ALT + 'i', 0, 0, FL_MENU_INVISIBLE},
{"check", FL_ALT + 'i', 0, 0, FL_MENU_TOGGLE | FL_MENU_VALUE},
{"box", FL_ALT + 'i', 0, 0, FL_MENU_TOGGLE},
{0}};
auto flex = new Fl_Flex{0, 0, window->w(), 30, Fl_Flex::HORIZONTAL};
auto menu_button = new Fl_Menu_Button{0, 0, 0, 0, "&Menu Button"};
menu_button->menu(popup);
flex->fixed(menu_button, 150);
flex->end();
auto group = new Fl_Group{0, flex->h(), window->w(), window->h() - flex->h()};
group->end();
window->resizable(group);
window->end();
window->show(argc, argv);
// https://www.fltk.org/doc-1.4/classFl__Menu__.html#a8db18d83b2166eaba3b4b465ef0373a0
for (int t = 0; t < menu_button->size(); t++) { // walk array of items
const Fl_Menu_Item &item = menu_button->menu()[t]; // get each item
fprintf(stderr, "item #%d -- label=%s,\tvalue=%s,\ttype=%s\n", t,
item.label() ? item.label() : "(Null)", // menu terminators have NULL labels
(item.flags & FL_MENU_VALUE) ? "set" : "clear", // value of toggle or radio items
(item.flags & FL_SUBMENU) ? "Submenu" : "Item"); // see if item is a submenu or actual item
}
return Fl::run();
}