1

以下のようなインターフェイスを使用して、リソース ファイルを使用せずに私の C++ アプリケーションでメニューを動的に実装しようとすると、問題が発生しました。

Menu menu_main__ = {
    Menu("File", {
        Menu("Save Configuration", {}),
        Menu("Save Configuration As...", {}),
        Menu(nullptr, {}),
        Menu("Something", {
            Menu("Yay!", {})
        })
    }),
    Keybutter::Menu("Help", {
        Menu("Contents", {}),
        Menu(nullptr, {}),
        Menu("About", {}),
    })
};

Menu-class のコンストラクタは次のとおりです。

Menu(Menu const& menu_) = default;
Menu(Menu&& menu_) = default;
Menu(std::initializer_list<Menu>&& menus_sub__);
Menu(std::nullptr_t const&, std::initializer_list<Menu>&& menus_sub_);
Menu(std::string&& name_, std::initializer_list<Menu>&& menus_sub_);

ここで、メニュー作成を実装する唯一の実行可能な方法は再帰を使用することだと考えました。次のように、ウィンドウクラス内でラムダ再帰を使用することになりました。

std::vector<Menu> menus;

static unsigned int id_menu_sub = 0;

std::function<void (HMENU const&, std::string const&, std::vector<Menu> const&)> create_menus_sub__;
create_menus_sub__ = [&](HMENU const& menu_, std::string const& name_menu_, std::vector<Menu> const& menu_sub_) -> void{
    if(menu_sub_.empty()){
        return;
    }
    else{
        HMENU&& menu_sub__ = CreatePopupMenu();
        for(unsigned int i__ = 0; i__ < menu_sub_.size(); ++i__){
            if(menu_sub_[i__].menus_sub().empty()){
                if(menu_sub_[i__].name.empty()){
                    AppendMenu(menu_sub__, MF_SEPARATOR, ++id_menu_sub, NULL);
                }
                else{
                    AppendMenu(menu_sub__, (menu_sub_[i__].menus_sub().empty()) ? MF_STRING : MF_POPUP | MF_STRING, ++id_menu_sub, menu_sub_[i__].name.c_str());
                }
            }
            else{
                create_menus_sub__(menu_, menu_sub_[i__].name, menu_sub_[i__].menus_sub());
            }
        }
        AppendMenu(menu_, MF_POPUP | MF_STRING, reinterpret_cast<UINT>(menu_sub__), name_menu_.c_str());
    }
};
for(unsigned int i__ = 0; i__ < menus.size(); ++i__){
    HMENU&& menu__ = CreateMenu();
    create_menus_sub__(menu__, menus[i__].name, menus[i__].menus_sub());
    SetMenu(handle_window, menu__);
}

期待どおりに機能しないことが判明しました。結果は次のとおりです。

ここに画像の説明を入力

「ファイル」のメニュー項目ではなく、「何か」が間違った場所に表示されるようになりました。これは、優れた、しかしやや疑わしい C++ インターフェイスを使用して動的にメニューを作成する私の試みでした。再帰を使用してメニューを再帰的に作成するにはどうすればよいですか? コードを修正するにはどうすればよいですか? 十分な情報を提供したことを願っています。

4

1 に答える 1

2

menu_ラムダを再帰的に呼び出すと、ではなくへのポインターが渡されます。menu_sub_つまり、サブメニューが現在のサブメニューではなくトップレベルに追加されます。

ところで、C++11 の機能を上手に活用しましょう! :)

于 2013-07-10T20:50:18.393 に答える