本示例创建一个简单的记事本程序,这个简单的记事本可以让用户选择并打开文本文件。同时,也演示了如何使用place,menubar,menu,textbox,msgbox以及filebox。
示例中的程序是基于 Nana 0.8和C++11,因此需要使用GCC4.7或VS2013。
开始
首先,这里会贴出完整代码,然后解析其中的函数。
#include
#include
#include
#include
#include
#include
using namespace nana;
class notepad_form
: public form
{
public:
notepad_form()
{
caption(L"Simple Notepad - Nana C++ Library");
menubar_.create(*this);
textbox_.create(*this);
textbox_.borderless(true);
API::effects_edge_nimbus(textbox_, effects::edge_nimbus::none);
textbox_.enable_dropfiles(true);
textbox_.events().mouse_dropfiles([this](const arg_dropfiles& arg) //感网友TANG Zhenhao指出arg_drppfiles的拼写错误。
{
if (arg.files.size() && _m_ask_save())
textbox_.load(arg.files.at(0).data());
});
_m_make_menus();
place_.bind(*this);
place_.div("vert");
place_.field("menubar") << menubar_;
place_.field("textbox") << textbox_;
place_.collocate();
events().unload([this](const arg_unload& arg){
if (!_m_ask_save())
arg.cancel = true;
});
}
private:
nana::string _m_pick_file(bool is_open) const
{
filebox fbox(*this, is_open);
fbox.add_filter(L"Text", L"*.txt");
fbox.add_filter(L"All Files", L"*.*");
return (fbox.show() ? fbox.file() : nana::string());
}
bool _m_ask_save()
{
if (textbox_.edited())
{
auto fs = textbox_.filename();
msgbox box(*this, L"Simple Notepad", msgbox::button_t::yes_no_cancel);
box << L"Do you want to save these changes?";
switch (box.show())
{
case msgbox::pick_yes:
if (fs.empty())
{
fs = _m_pick_file(false);
if (fs.empty())
break;
if (fs.find(L".txt") == fs.npos)
fs += L".txt";
}
textbox_.store(fs.data());
break;
case msgbox::pick_no:
break;
case msgbox::pick_cancel:
return false;
}
}
return true;
}
void _m_make_menus()
{
menubar_.push_back(L"&FILE");
menubar_.at(0).append(L"New", [this](menu::item_proxy& ip)
{
if(_m_ask_save())
textbox_.reset();
});
menubar_.at(0).append(L"Open", [this](menu::item_proxy& ip)
{
if (_m_ask_save())
{
auto fs = _m_pick_file(true);
if (fs.size())
textbox_.load(fs.data());
}
});
menubar_.at(0).append(L"Save", [this](menu::item_proxy&)
{
auto fs = textbox_.filename();
if (fs.empty())
{
fs = _m_pick_file(false);
if (fs.empty())
return;
}
textbox_.store(fs.data());
});
menubar_.push_back(L"F&ORMAT");
menubar_.at(1).append(L"Line Wrap", [this](menu::item_proxy& ip)
{
textbox_.line_wrapped(ip.checked());
});
menubar_.at(1).check_style(0, menu::checks::highlight);
}
private:
place place_;
menubar menubar_;
textbox textbox_;
};
int main()
{
notepad_form npform;
npform.show();
exec();
}
_m_pick_file()
我们以这个私有函数开始分析代码,该函数的作用是弹出文件选择框,让用户选择一个文件
return (fbox.show() ? fbox.file() : nana::string());
如果用户点击了 取消 按钮 或者 关闭文件选择框,fbox.show()就返回false表示没有选择文件。
_m_ask_save()
该函数会在关闭文本的时候询问用户用户是否保存到文件。
if(textbox_.edited())
判断文本是否被用户编辑过。如果被编辑过,那么
auto fs = textbox_.filename();
当编辑框打开或者保存文件的时候,文本编辑框会保留这个文件名。如果字符串fs为空,程序就会询问用户选中一个文件来保存文本。
_m_ask_save()函数有一个bool类型返回值,如果它返回false表示用户取消了选择。
notepad_form()
在默认构造函数中,我们需要创建菜单栏和文本框,然后为这些widget设置布局。
textbox_.borderless(true);
API::effects_edge_nimbus(textbox_, effects::edge_nimbus::none);
取消文本框的边框及效果
textbox_.enable_dropfiles(true);
textbox_.events().mouse_dropfiles([this](const arg_drppfiles& arg)
{
if (arg.files.size() && _m_ask_save())
textbox_.load(arg.files.at(0).data());
});
为文本框设置拖拽事件,这样用户就能将程序外面的文本文件拖入程序中。这里调用_m_ask_save()是为了询问用户将先前编辑的文本保存。
events().unload([this](const arg_unload& arg){
if (!_m_ask_save())
arg.cancel = true;
});
设置一个窗口关闭事件,它可以使程序在退出前询问用户是否保存编辑的文本,并且用户也可以取消关闭程序。
_m_make_menus()
为菜单栏设置菜单。
int main()
创建记事本的窗口。