2009年4月16日星期四

U++教程3:多语言支持

使用U++编程可以方便的支持多国语言,U++平台本身就带了许多国家与地区的语言包,其中就包括了中文。U++支持编译时语言支持与运行时语言支持两种方式。我们先来看看编译时语言支持。还是用我们的Hello World程序作例子,看看我们是如何让它支持中文的。首先将我们的程序代码改成下面这样,蓝色部分为新增加的:
#include <CtrlLib/CtrlLib.h>
#define TFILE <helloworld/helloworl.t> //定义编译时语言文件
#include <Core/t.h>                   //多语言支持头文件
using namespace Upp;

class HelloWindow:public TopWindow
{
 private:
 Button hellobtn;
 Button closebtn;
 public:
 void hellofn();
 void closefn();
 HelloWindow();
 typedef HelloWindow CLASSNAME;
};

void HelloWindow::hellofn()
{
 PromptOK(t_("Hello World")); //为需要翻译的文件添加t_()宏
}

void HelloWindow::closefn()
{
 Close();
}

HelloWindow::HelloWindow()
{
 Title(t_("Hello World!")).Sizeable().Zoomable();
 SetRect(0,0,300,150);
 Add(hellobtn.SetLabel(t_("Hello")).LeftPos(50,80).TopPos(50,30));
 Add(closebtn.SetLabel(t_("Close")).RightPos(50,80).TopPos(50,30));
 hellobtn<<=THISBACK(hellofn);
 closebtn<<=THISBACK(closefn);
}

GUI_APP_MAIN
{

    SetLanguage(GetSystemLNG()); //设定程序所用的语言
    HelloWindow().Run(); //为了使代码更紧凑,我们使用了匿名对象。
}

我们在源代码所在的目录下新建helloworl.t文件,此文件就为U++程序所用的编译时语言文件,内容如下:
T_("Hello World")
zhCN("世界你好")

T_("Hello World!")
zhCN("世界你好!")

T_("Hello")
zhCN("你好")

T_("Close")
zhCN("关闭")


编译后我们就得到了一个中文版的HelloWorld了。


2009年4月13日星期一

U++教程2:与U++交谈

教程1里我们已经了解了U++开发环境的基本用法,并写了一个小小的HelloWorld。
不过那真的算不上是一个程序,在这一节里,我们将让事情变的更象样一点,让我们的程序有点交互性。
U++程序与其它GUI框架一样,都需要一个主窗口来容纳各种各样的控件用来与用户进行交互。在U++中,这个主窗口是由TopWindow类来负责的,让我们来看看它是如何工作的。把教程1里的程序改成下面这样:


#include <ctrllib/ctrllib.h>
using namespace Upp;

GUI_APP_MAIN
{
TopWindow a;
a.Run();
}

编译运行一下,我们就得到了一个空白窗口:
不过这个窗口没有什么用处,它不包含任何可与用户进行交互的控件。下面我们就来看看如何让这个窗口变的生动起来。我们将在这个窗口中添加两个按钮,一个名为Hello,用来产生教程1里的Hello World对话框,一个名为Close用来退出程序。
为了向窗口添加控件,并让其可与用户交互,我们需要从TopWindow派生一个我们自己的主窗口类。类定义如下:
class HelloWindow:public TopWindow
{
private:
Button hellobtn; //建立两个按钮成员
Button closebtn;
public:
void hellofn(); //定义两个方法,将来我们要把它们与按钮联接
void closefn();
HelloWindow(); //构造函数
};

下面是HelloWindow类中成员函数的实现:
void HelloWindow::hellofn()
{
PromptOK("Hello World"); //显示对话框
}

void HelloWindow::closefn()
{
Close(); //退出程序
}

//下面是HelloWindow类的构造函数,控件的添加主要在这里进行
HelloWindow::HelloWindow()
{
Title("Hello World!").Sizeable().Zoomable(); 
SetRect(0,0,300,150);
Add(hellobtn.SetLabel("Hello").LeftPos(50,80).TopPos(50,30));
Add(closebtn.SetLabel("Close").RightPos(50,80).TopPos(50,30));
hellobtn<<=callback(this, &HelloWindow::hellofn);
closebtn<<=callback(this, &HelloWindow::closefn);
}

各种控件的添加及属性设置均在构造函数里完成,我们来详细看看这些语句的功能。
Title("Hello World!").Sizeable().Zoomable(); 
这一句用来对主程序窗口本身进行一些属性设置,在U++里这些属性的设置是可以串联进行了,因为它们在基类里的定义是返回控件本身的引用。这使得程序语句可以变得十分紧凑。在这一句里,Title用来设置主窗口的标题,Sizeable令窗口可以调整大小,Zoomable令主窗口具有最大最小化按钮。读者可以通过增减这几个属性来看看窗口的变化,以了解这些属性的实际意义。主窗口类还有许多其它的属性,这可以通过阅读U++编程手册来了解,现在我们先了解这些。

SetRect(0,0,300,150);
用来指定窗口的初始大小,要注意的是这里的窗口大小并不包括窗口的标题栏。

Add(hellobtn.SetLabel("Hello").LeftPos(50,80).TopPos(50,30));
向主窗口添加控件就通过Add方法来完成。其参数就是所要添加的控件,在这里是我们的Hello按钮。hellobtn.SetLabel("Hello")用来设置按钮上的文字,其后跟随的LeftPos与TopPos用来指定按钮在主窗口中的位置。LeftPos表示按钮与主窗口左边界的距离,TopPos则表示其与主窗口上边界的距离。这两个属性的第二个参数则是指定了按钮的大小。LeftPos(50,80)表示按钮距离主窗口左边界50个象素,按钮宽度80。TopPos(50,30)表示按钮距主窗口上边界50,按钮高度30。

hellobtn<<=callback(this, &HelloWindow::hellofn);
这一句用来指定按下按钮后要调用的函数。在u++中对事件的响应都是通过回调函数(callback)来完成的,所以在U++中 callback是一个很重要的概念,我们以后会对它进行更详细的介绍。

OK,到这里我们对主窗口的设定就基本完成了,我们只需要生成一个HelloWorld类的实例然后调用Run函数就可以了:
GUI_APP_MAIN
{
HelloWindow myapp;
myapp.Run();
}

编译运行一下试试,呵呵。我们得到了如下的界面:


点击一下按钮试试,然后再缩放一下窗口的大小看看会有什么变化。通过这些操作你会对U++如何管理界面有进一步的了解。
现在再来看一下我们的代码,噢,为按钮指定回调函数的语句显的有点太冗长了。让我们对代码进行一点调整。
首先我们在类定义中添加这条语句:
typedef HelloWindow CLASSNAME;

然后在构造函数中把指定回调函数的语句改成这样:
hellobtn<<=THISBACK(hellofn);
closebtn<<=THISBACK(closefn);

这样看上去就要简洁多了,THISBACK是u++定义的一个宏,它会自动扩展为:callback(this, &HelloWindow::hellofn)这种形式。

我们最终的代码如下:
#include <ctrllib/ctrllib.h>

using namespace Upp;

class HelloWindow:public TopWindow
{
private:
Button hellobtn;
Button closebtn;
public:
void hellofn();
void closefn();
HelloWindow();
typedef HelloWindow CLASSNAME;
};

void HelloWindow::hellofn()
{
PromptOK("Hello World");
}

void HelloWindow::closefn()
{
Close();
}

HelloWindow::HelloWindow()
{
Title("Hello World!").Sizeable().Zoomable();
SetRect(0,0,300,150);
Add(hellobtn.SetLabel("Hello").LeftPos(50,80).TopPos(50,30));
Add(closebtn.SetLabel("Close").RightPos(50,80).TopPos(50,30));
hellobtn<<=THISBACK(hellofn);
closebtn<<=THISBACK(closefn);
}

GUI_APP_MAIN
{
HelloWindow().Run(); //为了使代码更紧凑,我们使用了匿名对象。
}

OK,这篇教程就到这里了,赶快动手编译试试吧。
嗯?我听见有人说了,既然是中文教程,为啥程序界面上全是英文?呵呵,那是我为下一篇教程准备的,下一篇我们将讨论一下u++程序的国际化支持。

2009年4月11日星期六

U++教程1:第一印象

U++是一个非常完整的C++开发平台,包含了基本算法库,图形库,GUI库,数据库接口,富文本,脚本语言,图标编辑器等一系列开发工具。它有自己的集成开发环境名为theIDE,与U++框架无缝集成。theIDE是一款非常好用的IDE,具有相当完善的代码提示,自动完成,自动格式化等功能。仅这一点就远远好过其它开源的C++Framework。但它的问题在于操作方式与一般的IDE区别很大,有它自己的一套操作方式,初用会觉得有些不适应,这或许是它无法流行起来的原因。不过一旦你熟悉它就会觉得非常方便,这是我自己用下来的切身体会。好了,废话不多说,开始正题。


启动theIDE后,会出现如下对话框:
上图是theIDE的工程管理窗口,也是程序启动后的第一个界面。与一般的开发平台不同,U++的工程管理方式是基于Assembly的,你在对话框的Assembly栏里右击鼠标可得到一个右键菜单用来建立新的Assembly或是编辑、删除现有的Assembly。我为我们的教程新建了一个Assembly:

从上图中可以看出我为我们的教程Assembly取名为mytutorial。

随后我们在这个Assembly里建立我们的第一个项目,在U++中称为Package。我们先在Assembly栏里选中我们刚刚建立的mytutorial,由于我们还没有建立任何Package所以在右边的Package栏里是空白的。我们点击右下脚的New package 按钮就可以建立一个新Package了:



与所有入门教程一样,我们也来写一个Hello World! 在Package name里输入Package名称helloworld。在Template栏里选择Basic CtrlLib application。这时在右边会显示自动生成的代码模板。然后我们点击Create就会进入代码编辑界面。


我们可以看到IDE已经为我们自动生成了一些代码,我们将其改成如下代码:
#include <CtrlLib/CtrlLib.h> //U++ GUI库头文件

using namespace Upp; //使用U++名称空间

GUI_APP_MAIN //程序入口,这是一个macro,根据不同的平台
{ //会替换为相应的程序入口,比如Windows下的winmain。
PromptOK("Hello World");//这是我们添加的代码,用来显示一个提示对话框。
}

写完后按下快捷键Ctrl+F5,将会编译并运行程序。U++与一般的开发平台不同,它提供给你的库完全是源代码形式的,没有预编译的二进制文件,在你第一次编译程序时它会编译相应的库文件,所以第一次的编译时间比较长,在我的老P3 933的机器上这大概要用掉3分钟左右。不过第一次编译后再编译其它Package就不会再次编译库文件,编译速度就比较快了。
我们这第一个HelloWorld程序的运行结果如下:


呵呵,很小的一个程序,但它确实运行了。我们已经了解了U++基本的工程管理方式,知道了如何建立一个程序,一个良好的开始。在以后的章节中我们将继续去了解U++。

特立独行U++

呵呵,这个U++是一个开源的跨平台C++ RAD平台,作者从98年就开始开发,到今年持续了十一年了。U++一直都是一个非常非常小众的开发平台,几乎没什么人用,与当今火红的几个开源C++ Framewrok比如wxwidgets, QT等相比,它实在是被人冷落的可以。换做旁人早就歇菜了,在SourceForge上搜一下,能搜出一堆半路夭折的C++Framework。而U++却仍在不断的开发中,可算是特立独行,仅这一点就足以让我对作者肃然起敬了。
U++的作者是捷克人Mirek Fidler和Tomas Rylek,Mirek现在非常活跃,平台的开发及网站的维护主要是他在做。U++的用户也主要集中在东欧地区,象俄罗斯,罗马尼亚,波兰等且用户群很小。不过U++倒是提供了非常完整的国际化支持,它的语言包里囊括了很多国家及地区的语言,包括中文(简体,繁体都有)。不过中文语言包似乎很老,内容不是很完整。为此我提交了一个根据最新U++做的语言包。
我最初接触u++是在2003年,不过当时我正与人合作一个基于wxWidgets(当时还叫wxWindows)的项目,兴趣主要集中在wxWidgets上,对U++没有过多的了解。直到前几天我才又打开了U++的主页,看了几天觉得还是非常有意思的。是一个相当完整的开发平台,作者涉猎之广实在是让人佩服。钦佩之余决定为推广u++做点事,就象当初我对wxWidgets所做的那样。当初我是翻译了wxWidgets的一个教程,如今我不想仅做翻译了,因为老实说U++的文档做的不是特别好,这大概也是影响其普及程度的一个重要原因。我决定自己写一些U++的小教程,以让更多的人得以窥其一斑。
教程我会在这个BLog上慢慢的贴出,有兴趣的可随时关注我的Blog。
U++网站:http://www.ultimatepp.org