基础综合 C++ Builder 显示与输入接口 页眉 基础综合 C++ Builder 显示与输入接口 窗口程序中,占最大部分的大概就是按钮跟一些输入框了。在这一章里面,我们详细的介绍各种卷标、按钮以及输入的VCL组件,进而介绍一些按钮轴的使用方法,以及类似笔记本的多行输入窗。
大纲 3-1. 标签的使用(Label) 3-2. 使用编辑框(Edit) 3-3. 屏蔽编辑框(MaskEdit) 页眉 大纲 3-1. 标签的使用(Label) 3-2. 使用编辑框(Edit) 3-3. 屏蔽编辑框(MaskEdit) 3-4. 标签编辑框(LabeledEdit) 3-5. StringGrid 3-6. ValueListEdit 3-7. RichEdit组件的使用 3-8. RichEdit组件的使用 本章习题
页眉 3-1. 标签的使用(Label) 卷标,简单来说就是窗口程序上的文字方块。标签的使用相当容易,也很直观,在之前的程序我们也已经用过Label了!我们将利用范例3-1来说明Label的详细用法。 Label这个VCL组件放在Standard Page上,选取后也是一样将光标移到Form上,并且在要放上Label的地方按一下鼠标左键就可以了,其实任何VCL组件都是这样子使用。
页眉 3-2. 使用编辑框(Edit) Edit也是窗口程序中很重要的一个组件,最常见的是将Label和Edit一起使用,因为这样可以让使用者很清楚的知道,这个编辑框要输入的东西是什么。 Edit这个组件也被放在Standard这一个页次中,我们将利用范例3-2和3-3把编辑框跟标签紧紧的结合起来,再配合上按钮,来完成我们的范例。
3-2. 使用编辑框(Edit) 利用编辑框实作密码输入 页眉 3-2. 使用编辑框(Edit) 利用编辑框实作密码输入 在很多场合我们需要输入密码之类的机密数据,我们通常不会直接让输入的数据出现在Edit上,这时候只要修改Edit一个属性就够了。 『PasswordChar』。原本这个属性的设定值是『#0』,我们将之改成我们希望它出现的字符,例如『*』,这样当我们再输入字符的时候,一率都是使用『*』来显示。我们将密码输入的实际范例放在范例3-3里。
页眉 3-3. 屏蔽编辑框(MaskEdit) 屏蔽编辑框跟编辑框的功能很相近,只是屏蔽编辑框可以先设定好输入的格式,所以当使用者在使用的时候,就可以限制使用者输入的文字。 例如我们希望使用者输入身分证字号,格式就是一个英文字母加上九个数字,但是有些使用者就会故意乱输入,这时后除非我们在程序中写入检查的程序代码,不然就只能任由使用者乱来了。 MaskEdit被放置在Additional这个页次内,将MaskEdit放在Form上跟Edit的外观几乎没有什么不同,但是MaskEdit主要是拥有一个Edit没有的属性,就是EditMask这个属性。
3-3. 屏蔽编辑框(MaskEdit) Mask中可以使用的符号 页眉 Mask位 代表意义 ! > 在这个符号后面的所有英文字母都会被强制转换为大写字母。直到“<”符号出现才恢复。 < 在这个符号之后的英文字母全部变成小写,直到“>”符号出现才恢复。 <> 不检查英文字母到底是大写或是小写 \ 显示特别字符,只需在要显示的字符前加上这个符号即可。 L 只可以输入英文字母,而且一定被要求输入,不分大小写。 l 只可以输入英文字母,但是不一定要输入。不分大小写。 A 可以输入英文字母和数字,而且一定要输入,英文字母不分大小写。
3-3. 屏蔽编辑框(MaskEdit) Mask中可以使用的符号 页眉 Mask位 代表意义 a 可以输入英文字母和数字,但是不一定要输入,英文字母不分大小写。 C 可以输入任何字符,不过一定要输入。 c 可以输入任何字符,但是不一定要输入。 只可以输入数字,而且一定要输入。 9 只可以输入数字,但是不一定要输入。 # 可以输入数字或是正负符号。 : 用来分隔时间中的时、分、秒。 / 用来分隔时间中的年、月、日。 ; 用来分隔mask的字段。 _ 空格符,输入时将会跳过这个字符。但是会在MaskEdit上出现这个位需要输入(有底线)。
页眉 3-3. 屏蔽编辑框(MaskEdit) 范例3-4的执行结果
3-4. 标签编辑框(LabeledEdit) 在前面我们介绍过Label跟Edit,也在范例中展现出Label跟Edit合作无间的功能。 页眉 3-4. 标签编辑框(LabeledEdit) 在前面我们介绍过Label跟Edit,也在范例中展现出Label跟Edit合作无间的功能。 在BCB 6里面,多了一个相当好用的组件,他叫做『LabeledEdit』,他将Label跟Edit合起来,我们不需要再拉两个VCL组件下来,只要拉一个LabeledEdit就等于拉了一个Label和Edit。
3-5. StringGrid StringGrid最主要的功能就是提供一个Grid可以让我们储存一堆相关的文字。 页眉 3-5. StringGrid StringGrid最主要的功能就是提供一个Grid可以让我们储存一堆相关的文字。 例如我们将在范例3-6实做的『九九表』就是一个好例子。 其余,像是很多需要填写的表格,或是工厂机台传出来的报表等等,都很适合用StringGrid来表现!
3-5. StringGrid 范例3-6:利用StringGrid实作九九表 StringGrid需要改变的属性 页眉 属性 设定说明 ColCount 就是设定Column的数目,在这边虽然九九表只需要九个Column,但是因为我们需要第一个Column,所以必须要设定成『10』 DefaultColWidth 设定每个Column的宽度,使该StringGrid不需要使用Scroll Bar RowCount 就是设定Row的数目,在这边虽然九九表只需要九个Row,但是因为我们需要第一个Row,所以必须要设定成『10』 DefaultRowHeight 设定每个Row的高度,使该StringGrid不需要使用Scroll Bar
3-5. StringGrid 范例3-6:利用StringGrid实作九九表 主要程序代码 页眉 void __fastcall TForm1::BitBtn1Click(TObject *Sender) { int i, j; //设定Row Header 以及Column Header的数字 for (i = 0 ; i <= 9 ; i++) { if (i == 0 ) { //设定StringGrid中最左上角那一小格的数据 StringGrid1->Cells[0][i] = "九九乘法"; } else { //设定Column Header的值..就是最上面那一排的数据 StringGrid1->Cells[i][0] = IntToStr(i); //设定Row Header的值..就是最左边那一排的数据 StringGrid1->Cells[0][i] = IntToStr(i); //计算九九表内的数据 for (i = 1 ; i <= 9 ; i++) for (j = 1 ; j <=9 ; j++) StringGrid1->Cells[i][j] = IntToStr(i * j);
页眉 3-5. StringGrid 范例3-6:利用StringGrid实作九九表 执行结果
3-5. StringGrid 动态产生StringGrid 页眉 3-5. StringGrid 动态产生StringGrid 在范例3-7中,主要是要设计一个可以动态产生StringGrid大小的程序。这样的好处在于我们不需要在设计程序的同时就固定住该StringGrid的大小,反而可以很弹性的由使用者给定之后再产生所需要的大小。 在这个范例中,main.h以及main.cpp都有动到,跟平常只有修改main.cpp有点不一样。
3-5. StringGrid 范例3-7:main.h class TForm1 : public TForm { 页眉 3-5. StringGrid 范例3-7:main.h class TForm1 : public TForm { __published: // IDE-managed Components //省略 private: // User declarations public: // User declarations //宣告一个StringGrid的指标 //让我们在等一下可以顺利的动态产生 TStringGrid *StringGrid; __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; #endif
3-5. StringGrid 范例3-7:main.cpp 页眉 3-5. StringGrid void __fastcall TForm1::BitBtn1Click(TObject *Sender) { //利用if来判断是不是四个LabeledEdit都有输入数据 //如果都有输入数据..就new一个TStringGrid出来 //并且对该StringGrid做一些属性的设定 //如果没有输入数据..就显示一个MessageBox通知使用者 if ((LabeledEdit1->Text.Length() != 0) && (LabeledEdit2->Text.Length() != 0) && \ (LabeledEdit3->Text.Length() != 0) && (LabeledEdit4->Text.Length() != 0)) { StringGrid = new TStringGrid(GroupBox2); //new一个StringGrid StringGrid->Parent = GroupBox2; //将StringGrid的parent设定为GroupBox2 StringGrid->Width = 577; //设定StringGrid的宽度 StringGrid->Height = 209; //设定StringGrid的高度 StringGrid->Top = 24; //设定StringGrid对于GroupBox2的上缘的距离 StringGrid->Left = 16; //设定StringGrid对于GroupBox2的左边界的距离 //设定该StringGrid的Cell个数的相关属性 StringGrid->ColCount = StrToInt(LabeledEdit1->Text); StringGrid->RowCount = StrToInt(LabeledEdit2->Text); StringGrid->FixedCols = StrToInt(LabeledEdit3->Text); StringGrid->FixedRows = StrToInt(LabeledEdit4->Text); StringGrid->Visible = true; //将该StringGrid的Visible设定为可看见 StringGrid->Enabled = true; //将该StringGrid设定成Enable } else { //显示应该输入完整的信息 //在这边会跳出一个MessageBox ShowMessage("请输入完整的信息"); 范例3-7:main.cpp
3-5. StringGrid 范例3-7:main.cpp 页眉 3-5. StringGrid 范例3-7:main.cpp void __fastcall TForm1::BitBtn2Click(TObject *Sender) { //如果StringGrid已经被new出来了,就可以扫过所有的Cells //并把所有的Cell的值都设定为空字符串,如此可以仿真出清除Grid数据的感觉 if (StringGrid != NULL) { for (int i = 0 ; i < StringGrid->ColCount ; i++) for (int j = 0 ; j < StringGrid->RowCount ; j++) StringGrid->Cells[i][j] = ""; } //--------------------------------------------------------------------------- void __fastcall TForm1::BitBtn3Click(TObject *Sender) //将已经new出来的StringGrid delete掉 //这个动作会完整的删除已经new出来的对象 delete StringGrid;
3-5. StringGrid 范例3-7:main.cpp 页眉 3-5. StringGrid 范例3-7:main.cpp void __fastcall TForm1::BitBtn4Click(TObject *Sender) { //宣告我们要设定Cell的colunm, row, 以及data的变量 int col, row; AnsiString data; //判断是不是我们需要的数据都具备了 if ((LabeledEdit5->Text.Length() != 0) && (LabeledEdit6->Text.Length() != 0) && \ (LabeledEdit7->Text.Length() != 0)) { //如果所需的信息都已经具备,就将这些信息写入我们刚刚宣告的变量中 col = LabeledEdit5->Text.ToInt(); row = LabeledEdit6->Text.ToInt(); data = LabeledEdit7->Text; StringGrid->Cells[col][row] = data; } else { ShowMessage("请输入完整的信息"); //显示应该输入完整的信息
页眉 3-5. StringGrid 范例3-7 执行结果
页眉 3-6. ValueListEdit ValueListEditor最主要的功能就是类似hash table,可以指定key以及value给这个Grid。 ValueListEditor也可以提供可视化的修改,不一定要像StringGrid只能由程控Cell的Value。 在key的部分,有四种Option可以选择,分别是『keyEdit』、『keyAdd』、『keyDelete』、以及『keyUnique』这四种。 Value部分,可以利用Insert或是Cell等不同的方法来设定,也可以设定是不是可以由可视化的组件修改等等。 范例3-8
页眉 3-7. RichEdit组件的使用 相信大家一定对笔记本相当不陌生,笔记本它有相当简单的接口,除了文字编辑区外就是一个主选单。我们现在所要介绍的就是这个文字编辑区,也就是BCB内所提供的RichEdit组件。 RichEdit组件放在BCB VCL面板的Standard Page上,放到Form上面感觉就像是一大块的白色方块,当然,你希望他不是白色的也可以,只需要改一下属性就好了。
页眉 3-7. RichEdit组件的使用 RichEdit他本身具有相当多的属性和方法可以使用,如果大家还记得我们在前面所提到程序编辑器的功能,应该还记得Code Completion这个功能吧! 因为在RichEdit或是下一小节我们要介绍的RichEdit中,有很多属性跟方法并不会在Object Inspector中出现,除了查询Help之外,就是Code Completion最好用了。在范例3-9中,我们将会简单的介绍一些RichEdit的范例,会让各位读者了解该如何对RichEdit内的数据做新增删除等动作。
页眉 3-7. RichEdit组件的使用 void __fastcall TForm1::BitBtn1Click(TObject *Sender) { //在RichEdit的最后一行加入字符串 if (LabeledEdit1->Text.Length() != 0) { RichEdit1->Lines->Append(LabeledEdit1->Text); //将字符串附加到RichEdit的最后 LabeledEdit1->Text = ""; //插入之后将该LabeledEdit清除 } //--------------------------------------------------------------------------- void __fastcall TForm1::BitBtn2Click(TObject *Sender) { //删除RichEdit的某一行的数据,RichEdit的行数由第"0"行开始算起 if (LabeledEdit2->Text.Length() != 0) { RichEdit1->Lines->Delete(LabeledEdit2->Text.ToInt()); //删除指定的行数 LabeledEdit2->Text = ""; //删除之后将输入的行数清除 void __fastcall TForm1::BitBtn3Click(TObject *Sender) { //在RichEdit的某一行插入字符串,插入字符串用的index也是从"0"算起 if ((LabeledEdit3->Text.Length() != 0) && (LabeledEdit4->Text.Length() != 0)) { //用index和Str储存我们将会使用到的数据 int index = LabeledEdit3->Text.ToInt(); AnsiString Str = LabeledEdit4->Text; RichEdit1->Lines->Insert(index, Str); //将资料插入到RichEdit中 LabeledEdit3->Text = ""; //清除输入的数据 LabeledEdit4->Text = ""; //清除输入的数据 范例3-9
页眉 3-8. RichEdit组件的使用 RichEdit跟RichEdit是很相近的两个组件,最大的差别大概就是在RichEdit它可以读写RTF文件! RichEdit被放在Win32这个页次中,将RichEdit放在Form上面的长相几乎跟RichEdit没有什么不同。 RichEdit的基本和RichEdit并没有什么差别,程序代码也差不多。
页眉 3-8. RichEdit组件的使用 void __fastcall TForm1::BitBtn1Click(TObject *Sender) { //在RichEdit的最后一行加入字符串 if (LabeledEdit1->Text.Length() != 0) { RichEdit1->Lines->Append(LabeledEdit1->Text); //将字符串附加到RichEdit的最后 LabeledEdit1->Text = ""; //插入之后将该LabeledEdit清除 } //--------------------------------------------------------------------------- void __fastcall TForm1::BitBtn2Click(TObject *Sender) { //删除RichEdit的某一行的数据,RichEdit的行数由第"0"行开始算起 if (LabeledEdit2->Text.Length() != 0) { RichEdit1->Lines->Delete(LabeledEdit2->Text.ToInt()); //删除指定的行数 LabeledEdit2->Text = ""; //删除之后将输入的行数清除 void __fastcall TForm1::BitBtn3Click(TObject *Sender) { //在RichEdit的某一行插入字符串,插入字符串用的index也是从"0"算起 if ((LabeledEdit3->Text.Length() != 0) && (LabeledEdit4->Text.Length() != 0)) { //用index和Str储存我们将会使用到的数据 int index = LabeledEdit3->Text.ToInt(); AnsiString Str = LabeledEdit4->Text; RichEdit1->Lines->Insert(index, Str); //将资料插入到RichEdit中 LabeledEdit3->Text = ""; //清除输入的数据 LabeledEdit4->Text = ""; //清除输入的数据 范例3-10
本章习题 自己开发一个密码输入对话窗,需包含有使用者名称、密码两栏,以及确定及取消两个按钮。 页眉 本章习题 自己开发一个密码输入对话窗,需包含有使用者名称、密码两栏,以及确定及取消两个按钮。 利用MaskEdit实作一个身分证字号检查程序,用来检查使用者输入的身分证字号是不是合法的。 上机作业: 制作一个对话框设置字体,字号和字型。