Nana 1.0是Beta阶段的第一个版本。
接口变更
1, 移除 nana::color_t 类型,加入新的 nana::color 类
color_t 的主要问题是无法表示无效的颜色值,因为 color_t 就是unsigned类型的别名。color 类还提供了一些有用的接口,from_rgb()/from_hsl()用来赋值颜色,blend()混合两个颜色,还定义了一些用于初始化颜色的辅助类型。
using namespace nana;
//nana::colors 定义了一些颜色的名称.
//参考 http://www.w3.org/TR/2011/REC-css3-color-20110607/
//4.3. Extended color keywords参看具体的名称 .
color col0{colors::silver};
//nana::color_rgb将整数解释为颜色
color col1{static_cast(0x112233)}; //red=0x11,green=0x22,blue=0x33
//nana::color_argb/nana::color_rgba 将整数解释为带透明通道的颜色.
color col2{static_cast(0xff112233)}; //alpha=0xff,red=0x11,green=0x22,blue=0x33
color col3{static_cast(0x112233ff)}; //red=0x11,green=0x22,blue=0x33,alpha=0xff
2,接口变更
一些接口命名的变更。
API::background/foreground变更为API:;bgcolor/fgcolor
widget::background/foreground变更为widget::bgcolor/fgcolor
一些graphics类的成员函数变更。
函数名(int x, int y)变更为 函数名(const nana::point& pos);
函数名(int x, int y, unsigned width, unsigned height) 变更为 函数名(const nana::rectangle& r);
新特性
1,widget的颜色方案
颜色方案是一个用于个性化显示widget的子系统。Nana库基本上提供了用于修改widget背景色和前景色的接口,但是这对一个复杂复合型的widget来说,例如listbox,这两个接口是不够的。通过颜色方案,就可以实现修改listbox的顶栏颜色。
//nana::listbox lsbox;
lsbox.scheme().header_bgcolor = nana::colors::yellow;
lsbox.scheme().header_grabbed = nana::colors::chocolate;
nana::API::refresh_window(lsbox); //应用这些修改
2,多显示器的支持
类screen用于查询显示器的信息,以确定将widget放置到合适的显示器中。老的API::screen_size()被移除。
感谢beru提出该功能的需求,并提供了Nana项目的第一笔捐款。
3,Textbox高亮化
Textbox添加了一组新的接口,用于定义一组高亮化显示。简单易用。
using namespace nana;
//textbox tb;
tb.set_highlight("sqlrev", colors::dark_blue, colors::yellow);
tb.set_keywords("sqlrev", false, true, { "select", "from", "where"});
tb.set_highlight("table-name", colors::red, {});
tb.set_keywords("table-name", false, true, { "studentbase" });
tb.set_highlight("field", colors::deep_sky_blue, {});
tb.set_keywords("field", false, true, { "score" });
set_highlight() 定义一个高亮化方案。
set_keywords()将一组字符串以指定方案高亮化显示,这里2个bool类型的参数分别表示“大小写敏感”和“全字匹配”。
4,窗口Draw-through
Draw-through表示直接在系统窗口上进行绘制。利用该功能,可以实现通过OpenGL/DX来绘制窗口表面。
#include
#include
#include
#include
#include
void EnableOpenGL(HDC hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof pfd);
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
auto iFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, iFormat, &pfd);
*hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, *hRC);
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
using namespace nana;
form fm;
nested_form nfm(fm, rectangle{ 10, 10, 100, 20 }, form::appear::bald<>());
nfm.show();
button btn(nfm, rectangle{ 0, 0, 100, 20 });
btn.caption(L"Exit");
btn.events().click([&fm]{
fm.close();
});
HGLRC hRC;
auto hwnd = reinterpret_cast(fm.native_handle());
HDC hDC = ::GetDC(hwnd);
EnableOpenGL(hDC, &hRC);
float theta = 0.0f;
//Define a opengl rendering function
fm.draw_through([hDC, theta]() mutable
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(theta, 0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.87f, -0.5f);
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(-0.87f, -0.5f);
glEnd();
glPopMatrix();
SwapBuffers(hDC);
glFinish();
theta += 1.0f;
});
fm.events().destroy([hwnd, hDC, hRC]
{
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(hRC);
ReleaseDC(hwnd, hDC);
});
timer tmr;
tmr.elapse([hwnd]{
RECT r;
::GetClientRect(hwnd, &r);
::InvalidateRect(hwnd, &r, FALSE);
});
tmr.interval(20);
tmr.start();
fm.show();
exec();
return 0;
}
5,Spinbox
Spinbox是一个新的widget,它可以让用户在一个可选范围内选择一个值。这些值可以是一组整数,浮点数和文本文字。
#include
#include
int main()
{
using namespace nana;
form fm;
spinbox spbox(fm, rectangle{10, 10, 100, 30});
spbox.range(0, 100, 1); //Set the range of integers
fm.show();
exec();
}
/// 设置数字值.
void range(int begin, int last, int step);
void range(double begin, double last, double step);
/// 设置文本值.
void range(std::initializer_list steps_utf8);
void range(std::initializer_list steps);
Inputbox提供了一个简单方便,用于用户输入的对话框。它可以让用户输入一个值或者多个值。
using namespace nana;
form fm;
fm.events().click([&fm]
{
//将这些单词翻译成中文.
internationalization i18n;
i18n.set("OK", L"确定");
i18n.set("Cancel", L"取消");
i18n.set("February", L"二月");
//定义一个inputbox.
inputbox ibox(fm, L"description hello this is a long description.", L"title");
//定义用户输入的内容.
//获取一个整数
inputbox::integer integer{L"标签", 15, -10, 100, 1};
//获取一个浮点数
inputbox::real real{ L"输入一个浮点数", 15, -10, 100, 1.5 };
//获取一个指定范围中的字符串.
inputbox::text text0( L"combox text", { L"Hello", L"Nana", L"C++", L"Library" } );
//获取任意输入的文本.
inputbox::text text1{ L"textbox text" };
//获取一个日期.
inputbox::date date{L"日期"};
//显示inputbox,当用户点击了 确定 按钮,show()将返回true。
if (ibox.show(integer, real, text0, text1, date))
{
auto n = integer.value(); //int
auto r = real.value(); //double
auto t1 = text0.value(); //nana::string(std::wstring)
auto t2 = text1.value(); //nana::string
auto d1 = date.value(); //nana::string
auto year = date.year(); //int
auto month = date.month(); //int
auto day = date.day(); //int
}
});
7,终止事件传播
所有事件参数都包含一个名为stop_propagation()的方法。当该方法被调用之后,之后的可忽略的事件处理函数将不在被调用。
int main()
{
using namespace nana;
form fm;
fm.events().click([]{
//该处理函数会被调用,但是这并不是最先被调用的。
});
fm.events().click([](const arg_mouse& arg){
arg.stop_propagation();
});
fm.events().click([]{
//它不会被调用。
});
fm.events().click.connect_unignorable([]{
//会被调用,因为这是一个不可忽略的事件处理函数
});
fm.events().click.connect_front([]{
//这个最先被调用,因为它被放在事件链的最前面。
});
fm.show();
exec();
}
用于开启/关闭listbox单选的新方法。
void enable_single(bool for_selection, bool category_limited);
void disable_single(bool for_selection);
参数category_limited表示是否允许在每个列别中单选。如果该参数传入false,表示整个listbox只有一项可以被选中。