还记得过去用VC++创建一个窗体的过程么,它意味着相对不少的代码描述一个窗体类(或应用程序类)的对象,每个属性的设置都要对应着一行赋值语句。如果是用Windows API,需要自己书写主事件循环。至于图标、位图什么的还要作为资源去调用。想添加控件就比较麻烦了。首先,你要有一本MFC大全,照着它来添加各种控件类的实例,截取它用到的各种Windows消息……这些也就是对于VC++制作窗口程序,笔者没学下去的原因。
这两天鼓捣VC++.NET,才发现原来这里的VC++也可以使用窗口编辑器。笔者这就带着大家一起用它来创建一个窗口。我们还是从经典的“Hello,World”开始。
我们应该创建一个Windows Form Application(.NET)(Windows窗口应用程序)类型的工程。这里将它命名为HelloWorld。
单击“OK”确定,我们看到.NET为我们自动创建了一个主窗体Form1。可以看到左面的文件列表里,仍然是传统的源文件、头文件和资源,稍有一点变化的就是该Form1的头文件,笔者稍候会详细说明,其实我们以往要做的工作都被封装在这个头文件里。呈现在我们面前的已不再是VC++传统的代码编辑界面,而是一个窗口编辑界面。
读者的开发环境如果使用的是Visual C++6.0的界面风格的话,还看不到最重要的控件条(ToolBox),要在菜单项“视图(View)-〉工具箱(ToolBox)”中把它点开。我们看到了令人兴奋的一个个控件,你可以随意在上面画画控件爽几下,然后我们继续。托拽出一个Button和一个Label,我想这对你来说都应该不陌生。右键单击它们的任何一个,选择菜单的最后一项Properties把属性列表叫出来(应该就出现在文件列表的下面),你可以编辑它们的属性,再也不必去写语句了。试着给咱们的程序换个图标,不用再麻烦地调用资源了,很容易了不是?
保持良好的命名习惯,我将它俩命名为btnSay和lblShow。开始添加代码了,双击btnSay,进入代码界面,光标会自动跳转至按钮单击事件处,其他的东西可以一概不管,只需要在这里添加上代码
this->lblShow->Text = "Hello,the World!";
我想该做得也就这么多了(有点像VB了不是?)毕竟是C++,得编译。按Ctrl+F5编译链接运行,结果如图:
真正的C++程序员这时会思考代码是怎样被组织封装的。我们先来看看文件的组织形式。这里依然是使用资源的形式来用图标、菜单什么的,因此这里有同以往一样的*.rc和resource.h。工程的主体是Form1.h/cpp文件对,主程序也在里面。不过主程序似乎是一空壳,真正的窗体对象信息都在Form1.h里。它现在给我们呈现出一副可视化设计器的姿态,我们右键点击它,在弹出的对话框中选择第二项
终于揭开了它的神秘面纱,看到了隐藏在背后的代码。(有点故弄玄虚了,其实刚才你编写代码时就已经见到它了。这令我也很诧异,头文件里居然会有执行代码!)还有一点要说的,刚才你是不是找不到在那儿修改Form1对象的名字?在代码界面的属性列表里就能改了。我把它改称frmMain。
程序为你定义了一个命名空间HelloWorld,命名空间可以简单的理解为完成相似功能的类的集合。在这里,就是该空间里的类共同为程序"HelloWorld"“卖力气”。之后的一些using namespace xxx;语句表示将要使用到System空间里的这些类,都是已定义好的。之后的代码
public __gc class frmMain : public System::Windows::Forms::Form
{
public:
frmMain(void)
{
InitializeComponent();
}
protected:
void Dispose(Boolean disposing)
{
if (disposing && components)
{
components->Dispose();
}
__super::Dispose(disposing);
}
private: System::Windows::Forms::Button * btnSay;
private: System::Windows::Forms::Label * lblShow;
private:
///
/// Required designer variable.
///
System::ComponentModel::Container * components;
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
void InitializeComponent(void)
{
this->btnSay = new System::Windows::Forms::Button();
this->lblShow = new System::Windows::Forms::Label();
this->SuspendLayout();
//
// btnSay
//
this->btnSay->Location = System::Drawing::Point(72, 152);
this->btnSay->Name = S"btnSay";
this->btnSay->Size = System::Drawing::Size(144, 24);
this->btnSay->TabIndex = 0;
this->btnSay->Text = S"Say Hello";
this->btnSay->Click += new System::EventHandler(this, button1_Click);
//
// lblShow
//
this->lblShow->Font = new System::Drawing::Font(S"SimSun", 15, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, (System::Byte)134);
this->lblShow->ForeColor = System::Drawing::SystemColors::Desktop;
this->lblShow->Location = System::Drawing::Point(48, 56);
this->lblShow->Name = S"lblShow";
this->lblShow->Size = System::Drawing::Size(192, 24);
this->lblShow->TabIndex = 1;
//
// frmMain
//
this->AutoScaleBaseSize = System::Drawing::Size(6, 14);
this->ClientSize = System::Drawing::Size(292, 273);
this->Controls->Add(this->lblShow);
this->Controls->Add(this->btnSay);
this->Name = S"frmMain";
this->Text = S"Form1";
this->ResumeLayout(false);
}
private: System::Void button1_Click(System::Object * sender, System::EventArgs * e)
{
this->lblShow->Text = "Hello,the World!";
}
};
是对Form1类的完整定以及实现。可以看到,我们向窗体加进来的控件成为了它的成员变量,类型就是相应控件类的指针。因此在代码中引用控件时,要指明“this->”。窗体的构造函数中调用了void InitializeComponent(void),负责初始化所有的控件和主窗体。这些赋值语句就对应着设计界面上你在属性列表里做的修改动作,实际上这种在初始化时给属性赋值的做法同以往完全一样。你可以在这里直接修改某某控减的某某值。注意
this->btnSay->Click += new System::EventHandler(this, button1_Click);
btnSay->Click是指按钮的Click事件,button1_Click就是后面那个处理单击事件的成员函数的指针。这就如同传统的WindowProc()函数一样,系统截获事件后,会调用你指定的函数处理。这一行就是将该函数与系统预留的回调函数绑定。要处理控件的其他事件,以同样的方式将你的事件处理函数指针赋给Ctrl->Event(Ctrl代表任意控件,Event代表任意事件)。你会发现,当我们在设计界面双击某一控件时,会自动加入类似上面的代码,并等待你添加它的函数体,也就是事件处理过程,而自动添加的都是其默认事件,如按钮的Click,窗体的Load等。这样很类似于VB的工作方式。
上面笔者简单地将代码和设计联系了起来,下面说说更有意思的。有两件事一直是实现VC++窗体很头疼的,就是图片和菜单。现在有了熟悉的PictureBox控件,图形变得简单了一些。菜单的编辑更加简单。向窗体添加一个MainMenu控件,点击那个灰色的"TYPE HERE"输入菜单项,双击已编辑好的项目就可以编写菜单事件了,比起原来作为资源来添加,既直观又不容易错。我想你会大声高呼:“这就是个VB!”的确,我也这么想。
说了这么多,你会猜到程序设计变得如此方便的同时就会有什么东西作为代价了,对,那一定就是性能。C++在同类语言中一向是以性能著称的,正是因为C++程序员能够对整个程序进行灵活的控制,才使其具有高性能,不管是在类的设计、程序流程还是内存管理等等方面。因此有时候繁重的工作量是必需的。现在代码被封装了,方便的同时也存在降低性能的可能性。但对于一般的应用程序来说,这倒是不算什么问题。毕竟高效率的开发方式是很容易让人接受的。