通常windows应用程序都有相似的特征:控件、菜单、工具条、状态栏等等。每次我们开始作一个新的windows应用程序时都是以相同的事情开始:建立项目,添加控件和事件处理器。如果我们有一个模板,那么我们就可以节约大量的时间了。
在介绍如何建立模板的过程中,将涉及大量的微软.net framework类库的基本知识。如果你没有使用集成开发环境那么本文介绍的模板对你将非常有用,如果你使用了visual studio.net这样的集成开发环境你也可以从中了解控件的工作方式,这对你也是很有用的。
写一个windows应用程序总是从下面的几个步骤开始:
1、创建一个窗体
2、给窗体添加控件
3、添加菜单和菜单项,并绑定到窗体上
4、创建工具条
5、添加状态栏
6、添加事件处理器
在windows应用程序开发中,你不可能完全跳过这些步骤,你可以对他作些修改,但不可能完全跳过。
创建窗体
在.net framework程序设计中,窗体总是system.windows.forms.form类的子类,他继承聊着各类的全部特征,你甚至不用添加任何一行代码就可以创建window窗体了。现在我们创建一个form类的子类myapp,需要注意的是在说明继承时使用冒号:。
using system.windows.forms;
public class mywinapp: form {
}
与其他程序相似,我们需要一个main()的主方法作为应用程序的入口。在main()中使用system.windows.forms的run方法来开始应用程序和显示窗体。run方法有三种重载方式,对于windows应用程序,我们采取重载一个窗体对象的方式:
public static void main() {
mywinapp form = new mywinapp();
application.run(form);
}
作为选择,可以在main()方法中将两行代码写成一行:
public static void main() {
application.run(new mywinapp());
}
设置属性
一旦有了窗体,就可以设置它的属性(象高度、宽度、标题等)并指定一个象图1那样的图标,可以通过代码或从构造器重调用一个方法来完成这个设置。在list1中有一个方法initializecomponent,可以将初始化代码写入其中。
使用width和height属性设置宽度和高度
this.width = 400;
this.height = 300;
使用窗体的text属性设置标题
this.text = "my windows application";
设置图标
如果未作说明,windows应用程序将显示一个缺省图标,可以修改这个图标,方法是设置窗体的icon属性,这个属性接受一个system.drawing.icon对象。icon类有几个可以用于初始化icon对象的构造函数,需要说明的是最好提供.ico文件的完全路径。
this.icon = new icon(imagefolder + "applicationlogo.ico");
这里 imagefolder是一个静态域,用于指示icon文件的目录,imagefolder的定义如下:
static string imagefolder = "images" +
path.directoryseparatorchar.tostring();
这告诉应用程序icon文件在应用程序的image目录下,这里使用了system.io.path 类的directoryseparatorchar属性获得操作系统用于分隔目录和父目录的分隔符,在这里没有使用"/",这是因为对于windows操作系统这是正确的,但对于linux和unix则不然。这也是为了证明模板对于其他操作系统也是方便的。
窗体的位置
使窗体居中时非常有用的,要达到这个目的,需要使用startposition属性,并将formstartposition 的一个成员赋给他。
this.startposition = formstartposition.centerscreen;
当然也可以用form类的centertoscreen方法是窗体居中,但这个方法不能直接使用。
this.centertoscreen();
form类还有其他一些让人感兴趣的属性和方法,这里列出了其中的部分:
1、设置opacity 属性创建一个透明或半透明的窗体
2、设置modal属性使窗体为模式的或非模式的
3、通过backcolor属性改变窗体的背景颜色
4、将topmost属性设置为true,以确定窗体在其他所有非最顶部窗体之上
给窗体添加控件
windows控件均继承自system.windows.forms.control类,control类处理用户输入、安全等,他给窗体的控件提供了一个windows句柄,以及一些重要的属性,如name, enabled, text, backcolor, left, top, size, location, visible, width, 和 height。
system.windows.forms名称空间提供了12个控件,每一个控件都有它自己的属性和特征,所以在篇文章中我们不可能全部讨论。给窗体添加控减非常容易,下面的代码给窗体添加了三个控件,分别是:label, button, 和treeview。
label label;
button button;
treeview tree;
为了简便,可以在声明的同时实例化这些对象。
label label = new label();
button button = new button();
treeview tree = new treeview();
然后在initializecomponent方法中设置这些控件的属性,尤其是设置控件的大小和在窗体中的位置,对于大小可以使用width和height属性,比如treeview控件的大小可以使用下面的属性:
tree.width = 100;
tree.height = 100;
确定控件的位置可以使用控件的left和top属性,这两个属性决定了控件的左上角的位置,就像下面的语句决定了treeview的位置:
tree.top = 40;
tree.left = 20;
当然你也可以使用更简单的location属性,将system.drawing.point结构的实例赋给他。我们用这种方法确定label和button的位置。
label.location = new point(220, 40);
button.location = new point(220, 80);
下一步就是要使控件在窗体上可见。使用form.controlcollection类的add方法将每个控件添加到窗体的controlcollection中,controlcollection可以使用窗体的控件属性访问。
this.controls.add(label);
this.controls.add(button);
this.controls.add(tree);
添加菜单和菜单项
要找到没有菜单的windows应用程序非常困难,菜单使访问应用程序的功能变得很简单,在大多数环境下可以最小的使用控件。菜单比控件占用更少的空间,同时使应用程序显得更有组织。
在system.windows.forms名称空间中,所有与菜单相关的控件都是menu类的子类。menu是一个抽象类,你不能直接实例化,menu类有三个子类:
contextmenu
mainmenu
menuitem
contextmenu类表示快捷菜单,在控件或窗体区域点击鼠标右键时显示。快捷菜单常用于组合窗体mainmenu类的菜单项给出应用程序的上下文,这对于用户时非常有用的。
mainmenu表示传统的位于窗体顶部的菜单,你可以把它看成窗体菜单结构的容器。一个菜单是由menuitem表示的菜单项组成的,对于应用程序而言每一个菜单项是一个命令或其它子菜单项的父菜单。form类都有一个menu属性,采用将mainmenu对象赋给menu属性的方式将mainmenu对象绑定到窗体。
在这个模板中,我们没有使用contextmenu类,但我们示范了如何使用mainmenu和menuitem类。我们首先需要在窗体中添加一个菜单,给窗体添加一个mainmenu对象。
mainmenu mainmenu = new mainmenu();
现在mainmenu对象中什么都没有,下面我们给他添加一个menuitem对象。在list1中主菜单称为filemenuitem,它的text属性是&file,&表示他后面的字母带下划线,是该菜单的快捷键。通过使用menu对象的menuitemcollection的add方法为mainmenu添加一个或几个menuitem,这个集合可以通过menu类的menuitems属性访问。
menuitem filemenuitem = new menuitem();
mainmenu.menuitems.add(filemenuitem);
我们在filemenuitem 菜单项中还添加了其它menuitem,这些menuitem是filemenuitem的子菜单。你也可以给子菜单添加子菜单。图2显示了菜单的等级结构。
---------图2---------
菜单项的声明如下:
menuitem filenewmenuitem;
menuitem fileopenmenuitem;
menuitem filesavemenuitem;
menuitem filesaveasmenuitem;
menuitem filemenuwithsubmenu;
menuitem submenumenuitem;
menuitem fileexitmenuitem;
menuitem类有几个构造函数,使用这些构造函数实例化你的 menuitem对象,并添加一个事件处理器。
// the following constructor is the same as:
// menuitem filenewmenuitem = new menuitem();
// filenewmenuitem.text = "&new";
// filenewmenuitem.shortcut = shortcut.ctrln;
// filenewmenuitem.click += new
// system.eventhandler(this.filenewmenuitem_click);
filenewmenuitem = new menuitem("&new",
new system.eventhandler(this.filenewmenuitem_click), shortcut.ctrln);
fileopenmenuitem = new menuitem("&open",
new system.eventhandler(this.fileopenmenuitem_click), shortcut.ctrlo);
filesavemenuitem = new menuitem("&save",
new system.eventhandler(this.filesavemenuitem_click), shortcut.ctrls);
filesaveasmenuitem = new menuitem("save &as",
new system.eventhandler(this.filesaveasmenuitem_click));
filemenuwithsubmenu = new menuitem("&with submenu");
submenumenuitem = new menuitem("su&bmenu",
new system.eventhandler(this.submenumenuitem_click));
fileexitmenuitem = new menuitem("e&xit",
new system.eventhandler(this.fileexitmenuitem_click));
event handling is discussed further in the section "adding event handlers."
as mentioned, the menu items are added to the filemenuitem control.
filemenuitem.menuitems.add(filenewmenuitem);
filemenuitem.menuitems.add(fileopenmenuitem);
filemenuitem.menuitems.add(filesavemenuitem);
filemenuitem.menuitems.add(filesaveasmenuitem);
filemenuitem.menuitems.add(filemenuwithsubmenu);
filemenuwithsubmenu.menuitems.add(submenumenuitem);
filemenuitem.menuitems.add("-"); // add a separator
filemenuitem.menuitems.add(fileexitmenuitem);
注意在菜单项之间可以创建一个分隔符,方法是使用menu类的menuitems集合的add方法。上面的例子中使用的分隔符是"-"。
创建工具条
为了使应用程序的界面更友好,可以在窗体中添加一个工具条。工具条由system.windows.forms.toolbar类描述。窗体中可有多个工具条,工具条中包含了一个或多个toolbarbutton类描述的按钮,可以在每个按钮中插入图像或图标,要达到这个目的你需要一个imagelist控件作为图像容器。
imagelist imagelist = new imagelist();
对于每个图像文件首先要实例化为image对象,然后将这些图像添加到imagelist控件中,image和bitmap类可以在system.drawing名称空间中找到。
image newfileimage = new bitmap(imagefolder + "newfile.bmp");
image openfileimage = new bitmap(imagefolder + "openfile.gif");
image savefileimage = new bitmap(imagefolder + "savefile.bmp");
image printimage = new bitmap(imagefolder + "print.gif");
.
.
.
imagelist.images.add(newfileimage);
imagelist.images.add(openfileimage);
imagelist.images.add(savefileimage);
imagelist.images.add(printimage);
注意你可以使用images集合的add方法将image对象加入到imagelist控件中。现在为将这些图加入到控件中,必须将imagelist控件赋给toolbar的imagelist属性。
toolbar.imagelist = imagelist;
然后将imagelist控件中的图像赋给工具按钮的imageindex属性。
newtoolbarbutton.imageindex = 0;
opentoolbarbutton.imageindex = 1;
savetoolbarbutton.imageindex = 2;
printtoolbarbutton.imageindex = 3;
象菜单项一样,现在必须把工具按钮加入到工具条中。
toolbar.buttons.add(separatortoolbarbutton);
toolbar.buttons.add(newtoolbarbutton);
toolbar.buttons.add(opentoolbarbutton);
toolbar.buttons.add(savetoolbarbutton);
toolbar.buttons.add(separatortoolbarbutton);
toolbar.buttons.add(printtoolbarbutton);
最后将工具条加入到窗体中。
this.controls.add(toolbar);
添加状态条
状态条由system.windows.forms.statusbar描述,它提供了定制控件的外观的属性,状态条由statusbarpanel对象组成,在我们的模板中状态条有两个嵌套板:
statusbar statusbar = new statusbar();
statusbarpanel statusbarpanel1 = new statusbarpanel();
statusbarpanel statusbarpanel2 = new statusbarpanel();
状态条和状态跳上的嵌套板由下面的代码设置:
statusbarpanel1.borderstyle = statusbarpanelborderstyle.sunken;
statusbarpanel1.text = "press f1 for help";
statusbarpanel1.autosize = statusbarpanelautosize.spring;
statusbarpanel2.borderstyle = statusbarpanelborderstyle.raised;
statusbarpanel2.tooltiptext = system.datetime.now.toshorttimestring();
statusbarpanel2.text = system.datetime.today.tolongdatestring();
statusbarpanel2.autosize = statusbarpanelautosize.contents;
statusbar.showpanels = true;
statusbar.panels.add(statusbarpanel1);
statusbar.panels.add(statusbarpanel2);
同样我们需要将状态条添加到窗体中:
this.controls.add(statusbar);
事件处理器
在windows程序设计中添加事件处理器是最重要的任务。事件处理器保证了程序与用户交互,同时完成其他重要的功能。在c#中你可以给控件和菜单事件添加事件处理器以俘获你想处理的事件,下面的代码给button控件的click事件设计了一个事件处理器:
button.click += new system.eventhandler(this.button_click);
button_click事件处理器必须被处理:
private void button_click(object sender, system.eventargs e) {
messagebox.show("thank you.", "the event information");
}
menuitem 对象在实例化的同时可以给赋以一个事件处理器:
filenewmenuitem = new menuitem("&new",
new system.eventhandler(this.filenewmenuitem_click), shortcut.ctrln);
fileopenmenuitem = new menuitem("&open",
new system.eventhandler(this.fileopenmenuitem_click), shortcut.ctrlo);
filesavemenuitem = new menuitem("&save",
new system.eventhandler(this.filesavemenuitem_click), shortcut.ctrls);
filesaveasmenuitem = new menuitem("save &as",
new system.eventhandler(this.filesaveasmenuitem_click));
filemenuwithsubmenu = new menuitem("&with submenu");
submenumenuitem = new menuitem("su&bmenu",
new system.eventhandler(this.submenumenuitem_click));
fileexitmenuitem = new menuitem("e&xit",
new system.eventhandler(this.fileexitmenuitem_click));
你不能给工具按钮指派一个事件处理器,但可以给工具条指派一个事件处理器:
toolbar.buttonclick += new
toolbarbuttonclickeventhandler(this.toolbar_buttonclick);
protected void toolbar_buttonclick(object sender, toolbarbuttonclickeventargs
e) {
// evaluate the button property to determine which button was clicked.
switch (toolbar.buttons.indexof(e.button)) {
case 1:
messagebox.show("second button.", "the event information");
break;
case 2:
messagebox.show("third button", "the event information");
break;
case 3:
messagebox.show("fourth button.", "the event information");
break;
}
}
例子中也给窗体的close事件设计了一个事件处理器,通过重载onclosing方法你可以接收用户点击窗体的x按钮,这样你可以取消关闭事件:
protected override void onclosing(canceleventargs e) {
messagebox.show("exit now.", "the event information");
}
现在我们的模板就完成了,你可以使用他开始你的windows应用程序设计。
附录 listing 1. c# windows 应用程序模板
/*
to compile this source file, type
csc mywinapp.cs
*/
using system;
using system.windows.forms;
using system.drawing;
using system.io;
using system.componentmodel;
public class mywinapp: form {
label label = new label();
button button = new button();
treeview tree = new treeview();
imagelist imagelist = new imagelist();
static string imagefolder = "images" +
path.directoryseparatorchar.tostring();
// -------------- images declarations ------------------------------------
image newfileimage = new bitmap(imagefolder + "newfile.bmp");
image openfileimage = new bitmap(imagefolder + "openfile.gif");
image savefileimage = new bitmap(imagefolder + "savefile.bmp");
image printimage = new bitmap(imagefolder + "print.gif");
// -------------- end of images declaration
------------------------------------
// -------------- menu ------------------------------------
mainmenu mainmenu = new mainmenu();
menuitem filemenuitem = new menuitem();
menuitem filenewmenuitem;
menuitem fileopenmenuitem;
menuitem filesavemenuitem;
menuitem filesaveasmenuitem;
menuitem filemenuwithsubmenu;
menuitem submenumenuitem;
menuitem fileexitmenuitem;
// -------------- end of menu ------------------------------------
// -------------- toolbar ------------------------------------
toolbar toolbar = new toolbar();
toolbarbutton separatortoolbarbutton = new toolbarbutton();
toolbarbutton newtoolbarbutton = new toolbarbutton();
toolbarbutton opentoolbarbutton = new toolbarbutton();
toolbarbutton savetoolbarbutton = new toolbarbutton();
toolbarbutton printtoolbarbutton = new toolbarbutton();
// -------------- end of toolbar ------------------------------------
// -------------- statusbar ------------------------------------
statusbar statusbar = new statusbar();
statusbarpanel statusbarpanel1 = new statusbarpanel();
statusbarpanel statusbarpanel2 = new statusbarpanel();
// -------------- end of statusbar ------------------------------------
public mywinapp() {
initializecomponent();
}
private void initializecomponent() {
this.text = "my windows application";
this.icon = new icon(imagefolder + "applicationlogo.ico");
this.width = 400;
this.height = 300;
this.startposition = formstartposition.centerscreen;
imagelist.images.add(newfileimage);
imagelist.images.add(openfileimage);
imagelist.images.add(savefileimage);
imagelist.images.add(printimage);
// menu
filemenuitem.text = "&file";
// the following constructor is the same as:
// menuitem filenewmenuitem = new menuitem();
// filenewmenuitem.text = "&new";
// filenewmenuitem.shortcut = shortcut.ctrln;
// filenewmenuitem.click += new
system.eventhandler(this.filenewmenuitem_click);
filenewmenuitem = new menuitem("&new",
new system.eventhandler(this.filenewmenuitem_click), shortcut.ctrln);
fileopenmenuitem = new menuitem("&open",
new system.eventhandler(this.fileopenmenuitem_click), shortcut.ctrlo);
filesavemenuitem = new menuitem("&save",
new system.eventhandler(this.filesavemenuitem_click), shortcut.ctrls);
filesaveasmenuitem = new menuitem("save &as",
new system.eventhandler(this.filesaveasmenuitem_click));
filemenuwithsubmenu = new menuitem("&with submenu");
submenumenuitem = new menuitem("su&bmenu",
new system.eventhandler(this.submenumenuitem_click));
fileexitmenuitem = new menuitem("e&xit",
new system.eventhandler(this.fileexitmenuitem_click));
mainmenu.menuitems.add(filemenuitem);
fileopenmenuitem.checked = true;
filemenuitem.menuitems.add(filenewmenuitem);
filemenuitem.menuitems.add(fileopenmenuitem);
filemenuitem.menuitems.add(filesavemenuitem);
filemenuitem.menuitems.add(filesaveasmenuitem);
filemenuitem.menuitems.add(filemenuwithsubmenu);
filemenuwithsubmenu.menuitems.add(submenumenuitem);
filemenuitem.menuitems.add("-"); // add a separator
filemenuitem.menuitems.add(fileexitmenuitem);
toolbar.appearance = toolbarappearance.normal;
//toolbar.appearance = toolbarappearance.flat;
toolbar.imagelist = imagelist;
toolbar.buttonsize = new size(14, 6);
separatortoolbarbutton.style = toolbarbuttonstyle.separator;
newtoolbarbutton.tooltiptext = "new document";
newtoolbarbutton.imageindex = 0;
opentoolbarbutton.tooltiptext = "open document";
opentoolbarbutton.imageindex = 1;
savetoolbarbutton.tooltiptext = "save";
savetoolbarbutton.imageindex = 2;
printtoolbarbutton.tooltiptext = "print";
printtoolbarbutton.imageindex = 3;
toolbar.buttonclick += new
toolbarbuttonclickeventhandler(this.toolbar_buttonclick);
toolbar.buttons.add(separatortoolbarbutton);
toolbar.buttons.add(newtoolbarbutton);
toolbar.buttons.add(opentoolbarbutton);
toolbar.buttons.add(savetoolbarbutton);
toolbar.buttons.add(separatortoolbarbutton);
toolbar.buttons.add(printtoolbarbutton);
tree.top = 40;
tree.left = 20;
tree.width = 100;
tree.height = 100;
label.location = new point(220, 40);
label.size = new size(160, 30);
label.text = "yes, click the button";
button.location = new point(220, 80);
button.size = new size(100, 30);
button.text = "click this";
button.click += new system.eventhandler(this.button_click);
statusbarpanel1.borderstyle = statusbarpanelborderstyle.sunken;
statusbarpanel1.text = "press f1 for help";
statusbarpanel1.autosize = statusbarpanelautosize.spring;
statusbarpanel2.borderstyle = statusbarpanelborderstyle.raised;
statusbarpanel2.tooltiptext = system.datetime.now.toshorttimestring();
statusbarpanel2.text = system.datetime.today.tolongdatestring();
statusbarpanel2.autosize = statusbarpanelautosize.contents;
statusbar.showpanels = true;
statusbar.panels.add(statusbarpanel1);
statusbar.panels.add(statusbarpanel2);
this.menu = mainmenu;
this.controls.add(toolbar);
this.controls.add(tree);
this.controls.add(label);
this.controls.add(button);
this.controls.add(statusbar);
}
// -------------- event handlers --------------------------
private void filenewmenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the file -- new menu.", "the event
information");
}
private void fileopenmenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the file -- open menu.", "the event
information");
}
private void filesavemenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the file -- save menu.", "the event
information");
}
private void filesaveasmenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the file -- save as menu.", "the event
information");
}
private void fileexitmenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the file -- exit as menu.", "the event
information");
}
private void submenumenuitem_click(object sender, eventargs e) {
messagebox.show("you clicked the submenu.", "the event information");
}
protected void toolbar_buttonclick(object sender,
toolbarbuttonclickeventargs e) {
// evaluate the button property to determine which button was clicked.
switch (toolbar.buttons.indexof(e.button)) {
case 1:
messagebox.show("second button.", "the event information");
break;
case 2:
messagebox.show("third button", "the event information");
break;
case 3:
messagebox.show("fourth button.", "the event information");
break;
}
}
protected override void onclosing(canceleventargs e) {
messagebox.show("exit now.", "the event information");
}
private void button_click(object sender, system.eventargs e) {
messagebox.show("thank you.", "the event information");
}
// -------------- end of event handlers -------------------
public static void main() {
mywinapp form = new mywinapp();
application.run(form);
}
}
新闻热点
疑难解答