游览 Nana 1.0

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

这些助手类型都表示32位整数,这将有助于将一组颜色数据初始化为color对象。


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); //应用这些修改

感谢网友qPCR4vir提出该功能的建议。


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来绘制窗口表面。

游览 Nana 1.0_第1张图片

#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;
}

感谢Tom分享了这方面的经验。


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();
}

spinbox::range()有4个重载版本,每个版本决定了用户输入值的类型。

/// 设置数字值.
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);

6,Inputbox

Inputbox提供了一个简单方便,用于用户输入的对话框。它可以让用户输入一个值或者多个值。

游览 Nana 1.0_第2张图片

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
    }
});

Inputbox提供了两个显示函数:show()和show_modal(),如它们名称那样,show()不会阻止用户与其它窗口的交互;show_modal()会阻止用户与其它窗口的交互,并直到inputbox被关闭,也就是模态对话框。


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();
}

8,单选Listbox

用于开启/关闭listbox单选的新方法。

void enable_single(bool for_selection, bool category_limited);
void disable_single(bool for_selection);

参数for_selection表示 选择或钩选模式,选择模式表示高亮某一项,钩选模式表示在某项开头的方框中打上钩。

参数category_limited表示是否允许在每个列别中单选。如果该参数传入false,表示整个listbox只有一项可以被选中。


你可能感兴趣的:(GUI,Nana,C++,Library,C++)