C#源代码修改我想让我这个程序Go这个如何让按钮不能点击控制游戏的开始

&>&C#拼图游戏源代码(完整版)
C#拼图游戏源代码(完整版)
上传大小:1.45MB
这是我在学校老师指导下花了一周写的一款游戏,功能比较完整,包括:
1. 鼠标/键盘操作
2. 显示/隐藏参考图
3. 记录移动次数与时间
4. 排行榜
5. 随机排列图片
6. 交换效果
综合评分:4
{%username%}回复{%com_username%}{%time%}\
/*点击出现回复框*/
$(".respond_btn").on("click", function (e) {
$(this).parents(".rightLi").children(".respond_box").show();
e.stopPropagation();
$(".cancel_res").on("click", function (e) {
$(this).parents(".res_b").siblings(".res_area").val("");
$(this).parents(".respond_box").hide();
e.stopPropagation();
/*删除评论*/
$(".del_comment_c").on("click", function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_invalid/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parents(".conLi").remove();
alert(data.msg);
$(".res_btn").click(function (e) {
var parentWrap = $(this).parents(".respond_box"),
q = parentWrap.find(".form1").serializeArray(),
resStr = $.trim(parentWrap.find(".res_area_r").val());
console.log(q);
//var res_area_r = $.trim($(".res_area_r").val());
if (resStr == '') {
$(".res_text").css({color: "red"});
$.post("/index.php/comment/do_comment_reply/", q,
function (data) {
if (data.succ == 1) {
var $target,
evt = e || window.
$target = $(evt.target || evt.srcElement);
var $dd = $target.parents('dd');
var $wrapReply = $dd.find('.respond_box');
console.log($wrapReply);
//var mess = $(".res_area_r").val();
var mess = resS
var str = str.replace(/{%header%}/g, data.header)
.replace(/{%href%}/g, 'http://' + window.location.host + '/user/' + data.username)
.replace(/{%username%}/g, data.username)
.replace(/{%com_username%}/g, data.com_username)
.replace(/{%time%}/g, data.time)
.replace(/{%id%}/g, data.id)
.replace(/{%mess%}/g, mess);
$dd.after(str);
$(".respond_box").hide();
$(".res_area_r").val("");
$(".res_area").val("");
$wrapReply.hide();
alert(data.msg);
}, "json");
/*删除回复*/
$(".rightLi").on("click", '.del_comment_r', function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_comment_del/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parent().parent().parent().parent().parent().remove();
$(e.target).parents('.res_list').remove()
alert(data.msg);
//填充回复
function KeyP(v) {
var parentWrap = $(v).parents(".respond_box");
parentWrap.find(".res_area_r").val($.trim(parentWrap.find(".res_area").val()));
评论共有53条
wwweeeeee怎么检测有病毒?
坑爹啊!!!下载出现404错误就扣分了,也不让下载了
有不少例子可以参考,目前正需要.
综合评分:
积分/C币:3
gattaca2011
综合评分:
积分/C币:3
VIP会员动态
CSDN下载频道资源及相关规则调整公告V11.10
下载频道用户反馈专区
下载频道积分规则调整V1710.18
spring mvc+mybatis+mysql+maven+bootstrap 整合实现增删查改简单实例.zip
资源所需积分/C币
当前拥有积分
当前拥有C币
输入下载码
为了良好体验,不建议使用迅雷下载
C#拼图游戏源代码(完整版)
会员到期时间:
剩余下载个数:
剩余积分:0
为了良好体验,不建议使用迅雷下载
积分不足!
资源所需积分/C币
当前拥有积分
您可以选择
程序员的必选
绿色安全资源
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
您的积分不足,将扣除 10 C币
为了良好体验,不建议使用迅雷下载
无法举报自己的资源
你当前的下载分为234。
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可返还被扣除的积分
被举报人:
SamuelFisher
举报的资源分:
请选择类型
资源无法下载 ( 404页面、下载失败、资源本身问题)
资源无法使用 (文件损坏、内容缺失、题文不符)
侵犯版权资源 (侵犯公司或个人版权)
虚假资源 (恶意欺诈、刷分资源)
含色情、危害国家安全内容
含广告、木马病毒资源
*详细原因:
C#拼图游戏源代码(完整版)当前位置: >>
Visual C#.NET程序设计 作业
3、在 C#中实现面向对象的概念目标? ? ?编写一个队列类的 C#程序。 this 关键字的使用。 构造函数的重载和普通函数的重载。第一部分 指导(50 分钟)练习 1:队列类的应用程序问题 在数据结构中已经学习了队列,请用 C#编写一个类实现队列的功能,并编写一个测试类测试该队列的功能。(参考.Net 的 类库中已经封装好了的队列类:System.Collections.Queue,可以将自己做好的类,和它进行比较) 指导教师讲解问题说明 队列是限定所有的插入操作在表的一端进行,而删除操作在表的另一端进行的线性表,具有先进先出的特性。确定该队列中 存储的值类型为整数类型。 分析 一个队列有入排和出排动作,可以编写两个函数分别命名为 EnQueue 和 DeQueue;还应该有一个属性 Length:判断队列中的 元素个数;一个打印的函数 Print:将队列中所有的值进行打印输出。 推荐步骤: (1)新建一个名为“QueueWithCSharp”的基于控制台应用程序的项目。 (2)添加一个类,名为:Queue,添加以下代码。 using S using System.Collections.G using System.T namespace QueueWithCSharp { public class Node { public Node prior, public Node() { prior = next = data = 0; } } public class Queue { Node head, public int Length { get { } } public Queue() { // // // head = rear = length = 0; } public void EnQueue(int data) { if (rear == null) { rear = new Node(); head = rear.data = length++; } else { rear.next = new Node(); rear.next.data = length++; rear = rear. } } public int DeQueue() { if (length &= 0) { rear = head = Console.WriteLine(&队列中没有元素&); return 0; //删除 // 追加 TODO: 在此处添加构造函数逻辑 } int data = head. head = head. length--; } public void Print() { string str = &&; Node current = while (current != null) { if (current == head) { str += current.data.ToString(); } else { str += & } current = current. }// } } } (3)在 Program.cs 类中调用 Queue 类,代码如下: using S using System.Collections.G using System.T namespace QueueWithCSharp { class Program { static void Main(string[] args) { //定义一个 队列类 Queue demQueue = new Queue(); //数据入排 demQueue.EnQueue(10); demQueue.EnQueue(19); demQueue.EnQueue(50); end while current Console.WriteLine(str); && + current.data.ToString(); //打印 demQueue.EnQueue(99); //数据出排 demQueue.DeQueue(); //打印队列中的数据 demQueue.Print(); } } } (4)生成项目。 (5)选择“调试” →“开始执行(不调试)”选项来执行此应用程序,输出结果如图 1.1 所示。图 1.1练习 1 的输出结果练习 2:this 关键字的使用问题 this 关键字的使用 指导教师讲解问题说明 this 引用有三种典型的使用方式。第一种方式是限定被参数掩藏的实例变量; public void Function1(int i) { This.i=i; } 第二种用法是把当前对象作为参数传给另一个方法; public void Method1() { OtherClass obj= new OtherClass(); obj.Method2(this); } 第三种方法与索引器有关。 public Class this[string title] { get { foreach(?) ? } } 分析 定义一个汽车类,这个类有多个构造函数,因为这些构造函数之间有部分功能是重叠的,所以可以进行相互调用。在进行构 造函数的互相调用时,this 关键字调用参数最匹配的那个构造函数。 推荐步骤: (1)使用 Visual Studio.NET 2005 新建一个基于控制台的项目“CallConstructor”。 (2)将“Program.cs”类文件重命名为“Car.cs”。 (3)将以下代码添加到“Car.cs”中。 using S using System.Collections.G using System.T namespace CallConstructor { public class Car { int petalCount = 0; string s = &null&; Car(int petalCount) { this.petalCount = petalC } Car(String s, int petals) : this(petals) { this.s = Console.WriteLine(&String & int args&); } Car(): this(&hi&,47) { Console.WriteLine(&default Constructor&); } static void Main(string[] args) { Car x = new Car(); //this 关键字调用参数最匹配的那个构造函数 //this 的第一种用法 Console.WriteLine(&Constructor w/int arg only,petalCount = & + petalCount); } } } (4)生成项目。 (5)选择“调试” →“开始执行(不调试)”选项来执行此应用程序。 此程序的输出结果如图 3.2 所示。图 3.2 练习 2 的输出结果 指导教师检查学生进度练习 3:构造函数的重载和普通函数的重载问题 构造函数的重载和普通函数的重载 指导教师讲解问题说明 方法的重载仅仅是根据方法的参数列表来决定是否两个同名的函数是不同的,而不包括方法的返回值。以下声明两个不同的 函数是非法的: Void f() {} int f() {} 分析 定义一个 Tree 类,该类对构造函数和 info 函数进行重载。最后在 main 函数中,采用不同的参数去实例 Tree 类对象和调用 info 方法。 推荐步骤: (1)创建一个名为“Overloading”的控制台应用程序。 (2)将以下代码添加到“Program.cs”中。 using S using System.Collections.G using System.T namespace Overloading { class Program { class Tree { public Tree() { Console.WriteLine(&Planting a seedling&); height = 0; } public Tree(int i) { Console.WriteLine(&Creating new Tree that is &+i+& feet tall&); height = } internal void info() { Console.WriteLine(&Tree is &+height+& feet tall&); } internal void info(string s) { Console.WriteLine(s+&:Tree is & + height + & feet tall&); } } static void Main(string[] args) { for (int i = 0; i & 5; i++) { Tree t = new Tree(i); t.info(); t.info(&overloaded method&); } new Tree(); } } } (3)生成并执行该程序。 此程序的输出结果如图 3.3 所示。 图 3.3练习3的输出结果第二部分练习(40 分钟)1.构建一个类 Point,它提供两个公有的构造函数,一个没有参数的 Point 构造函数和一个有两个 double 参数的构造函数。 另外在该类中提供一个静态方法计算两个点的直线距离,传入参数为两个 Point 类实例。然后设计一个测试类来对 Point 类进行 使用。 提示:先定义两个变量来存储 Point 点的 X,Y 坐标;无参的构造函数将 X,Y 坐标赋为 0;有参的构造函数将传入的参数分 别赋给 X,Y 坐标。 2.创建一个日期类,定义几个变量:年、月、日、小时、分钟、秒;构造函数的参数为 System.DateTime 类型,然后将值分 别赋给定义的变量;然后构造两个重载方法 SetTime,分别使用按值传递参数和按引用传递参数方式来对定义的变量进行计算。 然后定义一个方法 DisplayTime 将这些变量的值输出。最后使用这个类,查看变量在调用方法 SetTime(按引用传递参数方式) 前后值的变化情况,比较按值传递和按引用传递这两种方式的区别。 提示:方法采用两种方式来传递参数,默认按照值传递的方式,另一种为按引用传递。方法只能有一个返回值,当然这个返 回值可能是程序员定义的多个值集合的一个结构。当程序需要多于一个返回值时,如果只允许按值传递,会带来不便。而按引用 传递参数,使得可以将需要同时返回的几个值都作为参数传递给方法,被调用的方法在其程序的内部对这些值做了修改后,调用 者可以访问这些按引用传递的参数,来获取被调用方法计算的结果。指导教师检查学生进度 指导教师检查学生代码规范性第三部分指导教师布置作业作业1. 编写一个程序,用来模拟银行帐户的基本操作,如帐户开户的话,则最低存款额为 100、存取现金操作以及在使用任意修 改余额后都可以随时查看帐户余额。请使用重载的带参数的构造函数。 提示:要实现此问题的解决方案,请创建一个名为 Account 类。该类包含一个名为 saving 的成员变量。编写一个默认的构 造函数,使用值 100 初始化该成员变量(如果用户开户时的钱少于 100,则不能开户;也就是不能实例化该类。)。创建一个参 数化构造函数,它可以传递任何大于 100 的整数以初始化 saving 变量。 2.请采用面向对象的程序设计方法编写一个计算图形面积的类,程序应当能够计算并输出圆、矩形和三角形的面积。构造三 个重载方法,对每一种图形类型使用不同的输入参数来计算面积:圆形的计算方法用半径作输入参数,矩形的计算方法用长和宽 作输入参数,三角形的计算方法用三条边的长度作输入参数。可以将这些方法定义为静态类型。最后编写主控程序类来对该类进 行使用。6、数据库编程:连接数据库目标? ? ?使用 Command 和 Connection 对象。 多表查询的应用。 主从关系表指导教师讲解阶段目标 本阶段将实现用 ADO.NET 对数据库的操作。第一部分指导(45 分钟)练习 1:用 command 和 Connection 实现系统登录界面问题 一般的程序都需要登录后才能使用,登录时应提供用户名、密码和身份类型。 指导教师讲解问题说明 本程序采用 SqlServer 做为数据库。数据库中有一张表名为:recordInfo,用来记录注册用户的信息;表中有 3 个字段,分 别是 id(用户名),pwd(密码),type(类型)。 分析 首先使用以下命名空间: using System.D using System.Data. SqlC 用以下方式创建 Connection 和 Command 对象,以便在.NET 中操作 SqlServer 数据库。 // 创建 Connection 对象 string connString = &Data Source=.;Initial Catalog=MySUser ID=pwd=sa&; SqlConnection connection = new SqlConnection(connString); // 创建 Command 对象 SqlCommand command = new SqlCommand(sql, connection); 由于返回的是记录数,所以使用 Command 对象的 ExecuteScalar ()方法执行该命令。 解决方案: (1)在 SqlServer 中创建“MySchool”数据库。添加一个表名为 recordInfo 的新表,添加 3 列:id(用户名),pwd(密 码),type(类型)。 (2)向新表 recordInfo 中添加几行示例数据。 (3)打开 Visual Studio .NET 2005 IDE 并新建一个名为 ConnectStr 的 Windows 应用程序项目。 (4)将 Form1.cs 文件重命名为 LoginForm.cs。 (5)拖动工具箱中的控件,设计如图所示的窗体。窗体设计界面 (6)添加两个按钮的 Click 事件,程序代码如下: using S using System.Collections.G using System.ComponentM using System.D using System.D using System.T using System.Windows.F using System.Data.SqlC namespace ConnectStr { public partial class LoginForm : Form { public LoginForm() { InitializeComponent(); } private void btnLogIn_Click(object sender, EventArgs e) { bool isValidUser = if (ValidateInput()) { // 调用用户验证方法 isValidUser = ValidateUser( cboLogInType.Text, txtLogInId.Text, txtLogInPwd.Text); // 如果是合法用户,显示相应的窗体 if (isValidUser) { // 将输入的用户名保存到全局变量中 name = txtLogInId.T // 将选择的登录类型保存到全局变量中 type = cboLogInType.T ShowUserForm(); } } } // 验证用户是否进行了输入和选择 private bool ValidateInput() { if (txtLogInId.Text.Trim() == &&) { MessageBox.Show(&请输入用户名&, &输入提示&, MessageBoxButtons.OK, MessageBoxIcon.Information); txtLogInId.Focus(); } else if (txtLogInPwd.Text.Trim() == &&) { MessageBox.Show(&请输入密码&, &输入提示&, MessageBoxButtons.OK, MessageBoxIcon.Information); txtLogInPwd.Focus(); } else if (cboLogInType.Text.Trim() == &&) { MessageBox.Show(&请选择登录类型&, &输入提示&, MessageBoxButtons.OK, MessageBoxIcon.Information); // 显示相应用户的主窗体 // 标识是否为合法用户 // 如果验证通过,就显示相应的用户窗体,并将当前窗体设为不可见 cboLogInType.Focus(); } else { } } // 验证用户输入的用户名和密码是否正确 // 验证的结果有两种情况:通过和不通过,返回值为布尔型 // 不通过的原因可能有多种, 在方法的参数中的 message 字符串, 用以标识不通过的情况 public bool ValidateUser(string loginType, string loginId, string loginPwd) { // 创建 Connection 对象 string connString = &Data Source=.;Initial Catalog=MySUser ID=pwd=sa&; SqlConnection connection = new SqlConnection(connString); int num = 0; // 查询用的 SQL 语句 string sql = &SELECT COUNT(*) FROM recordInfo where id='& + loginId + &' and pwd='& + loginPwd + &' and type='& + loginType + &'&; bool isExist = try { connection.Open();// 打开数据库连接 // 创建 Command 对象 SqlCommand command = new SqlCommand(sql, connection); // 执行 SQL 查询 num = (int)command.ExecuteScalar(); if (num & 0) { isExist = } else { MessageBox.Show(&数据库中无此记录!&,&提示信息&, MessageBoxButtons.OK, MessageBoxIcon.Information); } } catch (Exception ex) { // 操作出错 MessageBox.Show(&连接数据库出错!&); } finally // 选员信息的数量 { // 关闭数据库连接 connection.Close(); } return isE } // 根据登录类型,显示相应的窗体 public void ShowUserForm() { MessageBox.Show(&欢迎使用该系统:& + type + name); } private void btnCancel_Click(object sender, EventArgs e) { Application.Exit(); } } } (7)保存并构建应用程序。执行应用程序,以验证其工作情况。运行效果如图所示:登录界面图练习 2:多表查询的应用问题 创建一个多表查询应用程序,通过编写代码实现数据库操作功能的一般方法。设已创建了一个名为员工工资的 Access 数据 库,其中包括表 employee(存放员工基本信息)和表 pay(存放员工工资信息)。 程序设计要求: 1) 要求分别从上述两表中取出一些字段组成多表关联。 2) 要求将“应发工资”字段排列在“奖金”字段之后,“扣税”字段之前。“实发工资”为最后一个字段。 3) 要求程序具有按部门进行筛选记录的功能。 指导教师讲解问题说明 分析 数据库中表的设计如下图所示:employee 表设计图pay 表设计图 程序运行结果如下图所示:显示全部员工工资情况 筛选属于“财务室”的员工工资情况 解决方案: (2)打开标题为&选择数据源&的 ComboBox 控件下拉列表,单击&添加项目数据源?& ,打开&数据源配置向导&对话框,选 中&数据库&,单击&下一步&按钮,打开下一个&数据源配置向导&对话框。可以选择已有的数据库连接,也可以建立新的数据库连 接。这里单击&新建连接(C)?&按钮,打开&添加连接&对话框。 (3)当向导提示选择数据库对象时可选择数据库中所有的表。 (4)在“数据源”窗格中右键单击数据源 employeeDataSet,在弹出的快捷菜单中执行“使用设计器编辑数据集”命令打开 设计器窗口,右键单击 employee 表下方的“employeeTableAdpter”在弹出的快捷菜单中执行“配置”命令,启动 TableAdapter 配置向导。界面如图所示:(1)建立一个新项目。放 DataGridView 控件到窗体。选中该控件,单击该控件右上角标题为一箭头的按钮,将打开一窗体。数据源视图 (5)修改 SQL 语句为如下内容: SELECT employee.编号, employee.姓名, employee.部门, pay.基本工资, pay.职务工资, pay.补贴, pay.奖金, pay.基本工资 + pay.职务工资 + pay.补贴 + pay.奖金 AS 应发工资, pay.扣税, pay.基本工资 + pay.职务工资 + pay.补贴 + pay.奖金 - pay. 扣税 AS 实发工资 FROM (employee INNER JOIN pay ON employee.编号 = pay.编号) (6)向窗体上添加 1 个标签控件,1 个文本框控件、3 个按钮控件切换到窗体设计窗口,设置标签 Label1、按钮 button1、 button2、button3 的 Text 属性分别为:“输入部门名称”、“查找”、“显示全部”和“退出”。添加相应的事件处理函数。 (7)程序代码如下: using S using System.Collections.G using System.ComponentM using System.D using System.D using System.T using System.Windows.F namespace MultiTableQuery { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // TODO: 这行代码将数据加载到表“employeeDataSet.employee”中。您可以根据需要移 动或移除它。 this.employeeTableAdapter.Fill(this.employeeDataSet.employee); } private void btnQuery_Click(object sender, EventArgs e) { // 定义变量 dvresult 为 DataView 类型,并为其赋值当前 DataSet 的缺省视图 DataView dvresult = employeeDataSet.employee.DefaultV // 设置 DataView 中的数据按部门列排序 dvresult.Sort = &部门&; // 设置过滤器,仅显示指定部门的行 dvresult.RowFilter = &部门='& + tbxDepartment.Text + &'&; // 设置行状态过滤器 dvresult.RowStateFilter = DataViewRowState.CurrentR // 指定 DataGridView 控件的新数据源为按部门过滤后的 DataView dataGridView1.DataSource = } private void btnAll_Click(object sender, EventArgs e) { DataView dvresult = employeeDataSet.employee.DefaultV dvresult.Sort = &部门&; dvresult.RowFilter = &&; // 取消行过滤器 dvresult.RowStateFilter = DataViewRowState.CurrentR dataGridView1.DataSource = } private void btnQuit_Click(object sender, EventArgs e) { Application.Exit(); } } } (8)保存并构建应用程序。执行应用程序,以验证其工作情况。第二部分问题练习(45 分钟)数据库中有两张表:employee 和 pay,两者通过员工的编号字段进行连接,形成主从关系。 指导教师讲解问题说明 在显示数据库员工工资的 employee 和 pay 表数据时,希望在 employee 表选中某个员工时,pay 表只显示此员工的工资报酬 情况,两个表的这种关系叫做主从关系。如下图所示:主从表关系图 程序的设计界面如下图所示: 程序设计界面图 指导教师检查学生代码规范性第三部分指导教师布置作业作业创建如下图所示的 WinForms 应用程序。这个“病人管理系统”应接受病人的详细信息,并将病人的记录插入 SQL 数据库中。 该数据库的结构见下表。 病人管理系统 病人管理系统的病人数据字典 列名称 病人编号 数据类型 varchar 长度 50 默认值 主键 是 空 外键 否 备注 病人编号要求 yyyymmdd_XXXX 格式,如 4 姓名 年龄 性别 医生 病症 类别 nvarchar int nchar varchar nText varchar 8 3 4 5 16 5 null Null 男 否 否 否 否 否 否 可 可 可 可 可 可 否 否 否 是 否 是 年龄建议不超过 200 男或女病人管理系统的医生数据字典 列名称 医生编号 姓名 性别 科室 数据类型 varchar nvchar nchar varchar 5 8 4 4 长度 是 否 否 否 Null 男 null 主键 默认值 否 否 否 是 外键 否 可 可 可 空病人管理系统的科室表数据字典 列名称 科室编号 数据类型 varchar 4 长度 是 主键 默认值 否 外键 否 空 科室名称Nvarcha10否null否可病人管理系统的类型表数据字典 列名称 类别编号 类别名称 数据类型 varchar Nvarchar 4 10 长度 是 否 轻微 主键 默认值 外键 否 否 否 否 类别有:轻微、一般、重症、紧 急 空 备注7、数据库编程:检索操作数据目标? ?熟练应用 BindingSource 和 BindingNavigator 控件。 熟练使用 DataAdapter 和 DataReader。指导教师讲解阶段目标第一部分指导(60 分钟)练习 1:使用 BindingSource 和 BindingNavigator 控件操作数据库问题 创建一个具有添加、删除、修改等功能的 SQL Server 数据库应用程序。 指导教师讲解问题说明 分析 指导教师讲解关键步骤 (1) 连接 SQL Server 数据库 启动数据源配置向导,在“选择您的数据连接”对话框中单击【新建数据连接】按钮,在“添加连接”对话框中若默认的连 接类型不正确,可单击【更改】按钮打开对话框,选择其中“Microsoft SQL Server”数据源类型,单击【确定】按钮。 (2)TableAdapter 配置向导 在程序窗体设计器下方可以看到由系统自动创建的 4 个对象:DataSet(数据集)、BindingSource(绑定到数据源)、 TableAdapter(表适配器)和 BindingNavigator(绑定到导航工具栏)。鼠标指向 DataSet 或 TableAdapter 单击右键,在弹出 的快捷菜单中执行“在数据集编辑器中编辑”命令打开对话框。右键单击表适配器,在弹出的快捷菜单中执行“配置”命令,启 动 TableAdapter 配置向导。 单击对话框中【高级设置】按钮,打开对话框。用户可根据程序的需要选择是否生成 Insert(插入)、Update(更新)和 Delete(删除)SQL 语句。 返回(Get)及用于将更新直接发送到数据库的方法。单击【下一步】按钮,在对话框中单击【完成】按钮结束 TableAdapter 配 置向导。单击 “输入 SQL 语句” 对话框中的 【下一步】 按钮, 打开对话框。 此处可以选择需要为 TableAdapter 生成哪些方法, 如填充 (Fill) 、 (3)完善程序界面和代码 通过使用数据源配置向导和 TableAdapter 配置向导,创建的 SQL Server 数据库应用程序已具有了要求的功能。但为了使程 序更加美观、更加人性化还需要进行一些简单的完善。设计界面如图所示:界面设计视图表可以采用两种方式进行显示: DataGridView 和详细信息。 如采用详细信息方式时, 列的显示方式就有多种选择, TextBox、 如 Label、ComboBox 等。 解决方案: (1)创建一个名为“ConnectExam”的基于 Windows 的应用程序。 (2)添加数据源。 (3)配置 TableAdapter。 (4)设计界面。 (5)完善代码。 用户单击保存按钮时执行的事件过程代码修改如下: private void studentBindingNavigatorSaveItem_Click(object sender, EventArgs e) { this.Validate(); this.studentBindingSource.EndEdit(); this.studentTableAdapter.Update(this.connectExampleDataSet.student); // 下列语句行用于显示提示信息,需要手工添加 MessageBox.Show(&更新成功!&, &系统提示&,MessageBoxButtons.OK, MessageBoxIcon.Information); } 添加用户关闭窗体时执行的事件过程代码如下: private void Form1_FormClosed(object sender, FormClosedEventArgs e) { // 声明变量用于存放信息框返回结果 DialogR // 用 HasChanges()方法判断数据集是否已被修改 if (connectExampleDataSet.HasChanges()) { // 若数据集已被修改则显示信息框提示用户 result = MessageBox.Show(&数据已被修改,是否保存? &, &系统提示&, MessageBoxButtons.YesNo, MessageBoxIcon.Information); // 若用户单击了信息框中的【是】按钮 if (result == DialogResult.Yes) { this.Validate(); this.studentBindingSource.EndEdit(); this.studentTableAdapter.Update(connectExampleDataSet.student); } } } 指导教师检查学生进度练习 2:在 SQL Server 数据库中存储图像问题 在 SQL Server 数据库中存储图像。 指导教师讲解问题说明 数据库 test.mdf 的 test 表包含 pic 字段,其数据类型为 image,是一幅图像,本例将 pic 字段绑定到 pictureBox 控件。 分析 设为自动增量字段,设为主键。创建字段“pic”,image 类型,允许为空。 指导教师分析解题思路 解决方案: (1)建立一个新项目。放 PictureBox 控件到窗体。 (2)单击菜单“数据(A)|添加新数据源(N)?”,打开“数据源配置向导”对话框,连接数据库 Test.mdf。 (3)在 PictureBox 控件属性 DataBindings.Image 后的下拉列表中将看到 pic 字段,选中 pic 字段将 PictureBox 控件绑定 到 pic 字段。 (4)放 BindingNavigator 控件到窗体,修改该控件 BindingSource 属性为 testBindingSource。 (5)放 Button 和 OpenFileDialog 控件到窗体,Button 控件的标题为&增加或修改图像&,按钮单击事件处理函数如下: private void button1_Click(object sender, EventArgs e) { if (openFileDialog1.ShowDialog(this) == DialogResult.OK) { Bitmap bits= bits = new Bitmap(openFileDialog1.FileName);//建立指定文件的新位图对象 pictureBox1.Image = } }创建数据库 Test.mdf,创建 Test 表,包含字段“ID”,int 类型;(是标志)=是;标志增量=1;标志种子=1,即将字段“ID” (6)放 Button 控件到窗体,标题为&保存图像到数据库&,单击事件处理函数如下: private void button2_Click(object sender, EventArgs e) { if (this.testDataSet.HasChanges())//如果 DataSet 中数据被修改 this.testTableAdapter.Update(this.testDataSet);//更新数据库 }//集中调试环境中不能保存所作的修改,脱离集中调试环境运行可以保存所作的修改。 (7)程序界面如图所示:程序设计界面 (8)编译运行,单击 BindingNavigator 控件标题为&+&按钮,为 Test 表增加一个记录,单击&增加或修改图像&按钮,可以 为该记录增加图像。也可为当前记录修改图像。第二部分 练习(30 分钟)使用 SqlDataReader 类读出数据,用 ListView 控件显示。运行效果图 提示: 增加语句 using System.Data.SqlClient; 放置视图控件 ListView 到窗体,属性 View=Detail。单击属性 Column 右侧标题为“?”的按钮,在弹出的“ColumnHeader 集合编辑器”对话框中添加 3 个列头,属性 Text 分别为:学生学号、学生姓名、学生性别。为 Form1 类增加变量:SqlCSqlCommand da;SqlDataReader dr。 指导教师检查学生进度 指导教师检查学生代码规范性第三部分 作业指导教师布置作业 为学生数据库增加一个查询男生或女生的存储过程,并设计应用程序使用该存储过程。 提示: 存储过程语句如下: ALTER PROCEDURE SelectManStudent(@Sex nchar(1)) AS SELECT StudentNum,StudentName,StudentSex FROM Student WHERE(StudentSex=@Sex) RETURN8、C#高级编程目标? ? ? ?单一继承 抽象类和抽象方法 使用委托和事件实现模拟闹铃。 飞机和客机类的多态程序第一部分指导(50 分钟)练习 1:单一继承问题 现实生活中,哺乳动物是动物界中一个分支;可以动物普遍具有的特征都可以在哺乳动物身上找到;但哺乳动物也有自己独 指导教师讲解问题说明 用 C#编写一个程序,使用 Animal 和 Mammal 两个类来说明一般动物和哺乳动物的继承关系。Animal 具有名称、所属门类等 属性,需要提供方法实现以接收和显示这些属性的值。 Mammal 类具有代表哺乳动物习性的属性,这些属性表明哺乳动物与其他类型动物的区别。同样地,需要提供方法实现以接收 和显示这些属性的值。特的习性。 因此可以将动物看成是哺乳动物的父亲。 编程实现上可以通过哺乳动物类继承一般动物类, 从而获得一般动物的特征。 分析 Animal 类是一个基类,它包含_name、_type 两个成员以及用于接收和显示信息的三个方法。名为 Mammal 的派生类包含 _temperature、_isViviparous 两个成员和用于接收和显示信息的两个方法。 为了检验创建的 Animal 和 Mammal 类,应实例化一个 Mammal 类对象,并调用基类和派生类的方法来存储和检索值。 推荐步骤: (1)新建一个名为“SingleInher”的基于控制台应用程序的项目。 (2)将以下代码添加到“Program.cs”中。 using S using System.Collections.G using System.T namespace SingleInher { //一般动物类 class Animal { protected string _ protected string _ //接收名称和门类 public void AcceptDetails() { Console.WriteLine(&请输入动物名称:&); this._name = Console.ReadLine(); Console.WriteLine(&请输入所属门类:&); this._type = Console.ReadLine(); } //显示动物的名称和所属门类 public void DisplayDetails() { Console.WriteLine(); Console.WriteLine(&{0} 动物的详细信息如下:&, this._name); Console.WriteLine(&姓名:{0}&, this._name); Console.WriteLine(&门类:{0}&, this._type); } } //哺乳动物类,继承一般动物类 class Mammal : Animal { private double _ private string _isV //接收哺乳动物的特征信息 public void AcceptCharacter() { Console.WriteLine(&请输入哺乳动物的恒定温度:&); //恒定温度值 //是否为胎生 //动物名称 //动物所属门类 try { _temperature = Convert.ToDouble(Console.ReadLine()); } catch //捕捉异常,例如:若输入字母,在转换成 Decimal 时会引发异常 { Console.WriteLine(&请为温度输入数字!&); } Console.WriteLine(&该哺乳动物是否胎生:&); _isViviparous = Console.ReadLine(); } //显示哺乳动物的特征信息 public void DisplayCharacter() { Console.WriteLine(); Console.WriteLine(&{0} 的特征包括:&, this._name); Console.WriteLine(&恒定温度:{0}&, _temperature.ToString()); Console.WriteLine(&是否胎生:{0}&, _isViviparous); } } class Program { static void Main(string[] args) { Mammal objM = new Mammal(); objM.AcceptDetails();//访问父类方法 objM.AcceptCharacter(); objM.DisplayDetails();//访问父类方法 objM.DisplayCharacter(); } } } (3)生成项目。 (4)选择“调试” →“开始执行(不调试)”选项来执行此应用程序,输出结果如图 1.1 所示。 图 1.1练习 1 的输出结果练习 2:使用抽象类和抽象方法计算不同形状的面积问题 编写一个程序,使用抽象类和抽象方法来计算不同形状的面积。 指导教师讲解问题说明 先定义一个抽象类,该抽象类有一名为计算面积的方法为抽象方法。 指导教师分析解题思路 定义好抽象类和抽象方法后,具体的类继承该抽象类,实现抽象方法。该问题中定义两个具体形状类:矩形和圆。 解决方案: (1)创建一个基于控制台的项目“AbstractClass”。 (2)建立一个抽象类,命名为“Figure”, 定义变量和抽象方法 Area()。 (3)定义两个具体类 Square 和 Circle 继承自 Figure 类,在各自类中分别实现 Area()方法。 (4)创建一个测试类,分别调用 Square 和 Circle 类。 (5)添加以下完整的代码 using S abstract class Figure//抽象类定义,表示一个抽象图形 { protected double x = 0, y = 0; public Figure(double a, double b) { x = y = } public abstract void Area(); } //抽象方法,无实现代码,抽象图形无法计算面积 class Square : Figure { public Square(double a, double b) : base(a, b) { } public override void Area() } class Circle : Figure { public Circle(double a) : base(a, a) { } public override void Area()//类 Square 定义,矩形类//不能使用 new,必须用 override //显示矩形面积{ Console.WriteLine(&矩形面积是:{0}&, x * y); }//类 Circle 定义,圆类{ Console.WriteLine(&圆面积是:{0}&, 3.14 * x * y); } } class Class1 { static void Main(string[] args) { Square s = new Square(20, 30); Circle c = new Circle(10); s.Area(); c.Area(); } } (6)选择“生成”→“生成解决方案”选项,以生成此项目。 (7)选择“调试” →“开始执行(不调试)”选项来执行此应用程序。 此程序的输出结果如图 2.1 所示。//显示圆的面积图 2.1 指导教师检查学生进度程序输出结果 练习 3:使用委托和事件实现模拟闹铃问题 编写一个模拟闹铃的程序,具有闹铃,继续闹铃,打会盹儿,停止闹铃的功能。 指导教师讲解问题说明 编写一个程序用来模拟闹钟闹起床流程,有一个闹钟类 AlarmClock,催促起床类 WakeMeUp,使用类 AlarmDriver。调用类引 发开始闹铃事件,闹钟类调用委托方法进行处理,催促起床类和用户进行交互。 指导教师分析解题思路 在此问题中,可以设计考试类来控制流程。闹钟类应该有一个可以引发开始闹铃的方法由使用类调用。这是一种常用的类设 计方式,就是建立一些实体类,这些实体类由控制流程的类来进行关联。 解决方案: (1)创建一个基于控制台的项目“EventSample”。 (2)建立一个类,命名为“AlarmEventArgs”, 定义事件参数类。 (3)声明自定义代理类型,它的事件参数的类型为 AlarmEventArgs。 (4)创建包含事件和触发事件方法的类:AlarmClock。 (5)创建包含事件处理方法的类:WakeMeUp。 (6)创建包含程序入口方法的类:AlarmDriver。 (7)添加以下完整的代码 using S using System.Collections.G using System.T namespace EventSample { // // 定义事件参数类 // public class AlarmEventArgs : EventArgs { private readonly bool snoozeP private //构造函数 public AlarmEventArgs(bool snoozePressed, int nrings) { this.snoozePressed = snoozeP this.nrings = } // 定义属性,私有字段 nrings public int NumRings { get { } } // 定义属性,返回私有字段 snoozePressed public bool SnoozePressed { get { return snoozeP } } // 下面的属性返回一个字符串 public string AlarmText { get { if (snoozePressed) { return (&别打打盹儿,快起床!&); } else { return (&起床!&); } } } } // 声明自定义代理类型,它的事件参数的类型为 AlarmEventArgs public delegate void AlarmEventHandler(object sender, AlarmEventArgs e); // 包含事件和触发事件方法的类 public class AlarmClock { private bool snoozePressed = private int nrings = 0; private bool stop = // 定义两个属性 public bool Stop { get { } set { stop = } } public bool SnoozePressed { get { return snoozeP } set { snoozePressed = } } // 声明事件,它所使用的代理类型为 AlarmEventHandler public event AlarmEventHandler A // 触发事件的方法 protected virtual void OnAlarm(AlarmEventArgs e) { if (Alarm != null) { // 通过代理调用事件处理方法 Alarm(this, e); } } // 在该方法中循环调用 OnAlarm 方法来触发事件,直到 // stop 字段的值为 true public void Start() { for (; ; ) { nrings++; if (stop) { } else if (snoozePressed) { // 程序暂停 1 秒钟 System.Threading.Thread.Sleep(1000); { // 创建事件参数对象实例 AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings); OnAlarm(e); // 触发事件,在事件处理方法中会 // 相应地设置 snoozePressed 和 stop // 字段的值(通过属性来设置) } } else { // 程序暂停 0.3 秒 System.Threading.Thread.Sleep(300); AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings); OnAlarm(e); } } } } // 包含事件处理方法的类 public class WakeMeUp { // 事件处理方法 // 触发事件 // 在该方法中根据用户的输入来通过事件参数 sender // 设置事件发送者属性, public void AlarmRang(object sender, AlarmEventArgs e) { Console.WriteLine(e.AlarmText + &\n&); if (!(e.SnoozePressed)) { if (e.NumRings % 10 == 0) { Console.WriteLine(&继续闹铃?输入 Y&); Console.WriteLine(&打会盹儿?输入 N&); Console.WriteLine(&停止闹铃?输入 Q&); String input = Console.ReadLine(); if (input.Equals(&Y&) || input.Equals(&y&)) else if (input.Equals(&N&) || input.Equals(&N&)) { // 通过事件参数 sender 来访问触发事件的对象 ((AlarmClock)sender).SnoozePressed = } else { ((AlarmClock)sender).Stop = } } } else { Console.WriteLine(& 继续闹铃?输入 Y&); Console.WriteLine(& 停止闹铃?输入 Q&); String input = Console.ReadLine(); if (input.Equals(&Y&) || input.Equals(&y&)) else { ((AlarmClock)sender).Stop = } } } } // 包含程序入口方法的类 public class AlarmDriver { // 入口方法 public static void Main(string[] args) { // 创建事件接收者对象实例 WakeMeUp w = new WakeMeUp(); // 创建事件发送者对象实例 AlarmClock clock = new AlarmClock(); // 把事件处理方法绑定到发送者的事件上 clock.Alarm += new AlarmEventHandler(w.AlarmRang); clock.Start(); } } } (8)选择“生成”→“生成解决方案”选项,以生成此项目。 (9)选择“调试” →“开始执行(不调试)”选项来执行此应用程序。 此程序的输出结果如图 3.1 所示。图 3.1 指导教师检查学生进度EventSample 的输出结果 第二部分练习(40分钟)练习1:多态(polymorphism)C#可以通过使用关键字 virtual 在基类中定义虚方法,用 override 在派生类重载虚方法实现多态。以飞机类和客机类的代 码来说明如何实现多态。 指导教师分析解题思路 分别创建类 Plane 和 Airliner 的实例 p 和 a,先调用类 Plane 的方法 Report,然后把 p 指向 a,再调用 Report 方法,此时 实际上调用了类 Airliner 被重载的方法 Report。 具体代码如下所示: using S using System.Collections.G using System.T namespace Polymorphism { class Plane //定义飞机类 { public Plane() { ; } public Plane(int w1, int w2) { wheels = w1; weight = w2; } //定义虚方法 public virtual void Report() { Console.WriteLine(&The plane's wheel number is {0},weight is {1}&,wheels,weight); } } class Airliner : Plane { { passengers = //客机乘客数量 public Airliner(int w1,int w2,int p):base(w1,w2) //定义客机类,从飞机类中继承 //飞机轮子数量 //飞机重量,是受保护的变量
} //重载父类中的方法 public override void Report() { Console.WriteLine(&The Airliner's wheel number is {0},weight is {1},passengers is {2}&, wheels, weight, passengers); } } class Program { static void Main(string[] args) { Plane p = new Plane(); Airliner a = new Airliner(2, 300, 100); p.Report(); p = p.Report(); } } } 指导教师检查学生进度 指导教师检查学生代码规范性第三部分指导教师布置作业 例如:作业定义一个接口,用于描述动物的生活习性,包含食性、捕食、分布区域、睡觉方式、群居方式等;接口里面包括属性和方法。interface IHabit { void CatchFood(); string food{} ?? } 然后定义猫、老虎、狮子、大象等几个动物类来实现该接口; 最后定义一个调用类,来运行程序,查看接口的使用情况。9、数组、集合对象和泛型 目标? ?使用 Hashtable 集合对象存储电脑信息 员工数据输入指导教师讲解阶段目标第一部分指导(60 分钟)练习 1:使用 Hashtable 对象存储数据项问题 编写一个电脑信息类:包括电脑的型号、价格和出厂日期。程序应根据用户输入的型号来显示相应的电脑信息。 要求使用 Hashtable 对象存储电脑信息,并且按照型号排列输出,可以输入一个型号,程序检查判断集合中是否存在该型号的电 脑,如果存在则显示具体信息。 分析 指导教师分析解题思路 可以创建一个包含电脑型号、价格和出厂日期的类 Computer,电脑的详细信息再作为一个元素存在 Hashtable 集合中 //创建 Hashtable 对象 Hashtable objComputers = new Hashtable(); //添加值 objComputers.Add(&lenovo2008&, new Computer(&lenovo.9f, new DateTime( ))); objComputers.Add(&HP1000&, new Computer(&HP1000&, 7020, new DateTime())); objComputers.Add(&Dell600&, new Computer(&Dell600&, 5240, new DateTime())); objComputers.Add(&Benq1800&, new Computer(&Benq1800&, 5620, new DateTime())); objComputers.Add(&Sony7120&, new Computer(&Sony7120&, 8620, new DateTime())); objComputers.Add(&Samsung076&, new Computer(&Samsung076&, 7623, new DateTime()));排列输出可以通过下面这种方式输出: ArrayList akeys = new ArrayList(objComputers.Keys); akeys.Sort(); foreach (string key in akeys) { Computer objComputer = (Computer)objComputers[key]; Console.WriteLine(&型号:&+objComputer.Model + &;价格:& + objComputer.Price.ToString() + &¥;& + &出厂日期:& + objComputer.CDate.ToLongDateString()); } 推荐步骤: (1)创建一个基于控制台的 C#应用程序,命名为“HashtableExm”。 (2)创建 Computer 类。 (3)完整的代码如下: using S using System.Collections.G using System.T using System.C namespace HashtableExm { //创建电脑类 public class Computer { private string _cM private float _ private DateTime _cD //获取电脑的型号 public string Model { get { return _cM } } //获取电脑的价格 public float Price { get { return _ } } //获取电脑的出厂日期 public DateTime CDate { get { return _cD } } //构造函数 public Computer(string cModel,float cPrice,DateTime cDate) { this._cModel = cM this._price = cP this._cDate = CD } } class Program { static void Main(string[] args) { //创建 Hashtable 对象 Hashtable objComputers = new Hashtable(); //添加值 objComputers.Add(&lenovo2008&, new Computer(&lenovo.9f, new DateTime ())); objComputers.Add(&HP1000&, new Computer(&HP1000&, 7020, new DateTime())); objComputers.Add(&Dell600&, new Computer(&Dell600&, 5240, new DateTime())); objComputers.Add(&Benq1800&, new Computer(&Benq1800&, 5620, new DateTime())); objComputers.Add(&Sony7120&, new Computer(&Sony7120&, 8620, new DateTime())); objComputers.Add(&Samsung076&, new Computer(&Samsung076&, 7623, new DateTime ())); ArrayList akeys = new ArrayList(objComputers.Keys); akeys.Sort(); foreach (string key in akeys) { Computer objComputer = (Computer)objComputers[key]; Console.WriteLine(&型号:&+objComputer.Model + &;价格:& + objComputer.Price.ToString() + &¥;& + &出厂日期:& + objComputer.CDate.ToLongDateString()); } Console.Write(&输入电脑的型号:&); string model = Console.ReadLine(); //检查是否存在该值 if (objComputers.ContainsKey(model)) { //搜索型号并从列表中获取对象 Computer objComputer = (Computer)objComputers[model]; Console.WriteLine(&该型号的价格:& + objComputer.Price.ToString() + &¥;& + &出厂日期:& + objComputer.CDate.ToLongDateString()); } else { Console.WriteLine(&该型号未找到!&); } Console.ReadLine(); } } } (4)通过从菜单中选择“生成”→“生成解决方案”,来生成该解决方案。 (5)通过从菜单中选择“调试” →“开始执行(不调试)”选项来执行此应用程序。程序运行效果图 指导教师检查学生进度练习2:员工数据输入问题 在一个公司的员工管理系统中,通常会通过窗体输入员工的信息,包括员工的编号,姓名,部门,工资等情况。现不使用数 据库技术,使用 SortedList 来存储不同员工的信息,并且,录入的员工都显示在一个列表框中,还可以删除列表框中的员工, 但是同时要删除 SortedList 对象中的员工,因此 SortedList 对象中的数据要与类表框的数据同步。 界面要求如图: 员工信息输入在左边的文本框中输入数据以后,单击“添加”按钮可以把数据添加到 SortedList 对象中,同时姓名添加到右边列表框中; 在右边的列表框中选择一个姓名信息,单击下方的“删除”按钮,可以把该员工删除,同时,SortedList 对象中的员工信息也被 删除。 推荐步骤: (1)先创建一个员工类 Employee 来保存员工属性。 (2)创建一个窗体,对照界面,添加相应的控件及其事件。 (3)窗体类完整的代码如下: using S using System.Collections.G using System.ComponentM using System.D using System.D using System.T using System.Windows.F using System.C namespace EmployeeList { public partial class Form1 : Form { SortedList employeeL public Form1() { InitializeComponent(); } private void btn_add_Click(object sender, EventArgs e) { if(tbx_ID.Text!=&&) { Employee objEmployee = new Employee(int.Parse(tbx_ID.Text), tbx_Name.Text, tbx_dpart.Text, double.Parse(tbx_pay.Text)); employeeList.Add(tbx_ID.Text, objEmployee); lbx_id.Items.Add(tbx_ID.Text); } } private void btn_del_Click(object sender, EventArgs e) { if (lbx_id.SelectedItem != null) { string id = lbx_id.SelectedItem.ToString().Trim(); employeeList.Remove(id); lbx_id.Items.Remove(lbx_id.SelectedItem); tbx_ID.Text = &&; tbx_Name.Text = &&; tbx_dpart.Text = &&; tbx_pay.Text = &&; } MessageBox.Show(&当前职工记录数为:&+employeeList.Count.ToString()); } private void btn_close_Click(object sender, EventArgs e) { this.Close(); } private void Form1_Load(object sender, EventArgs e) { employeeList = new SortedList(); employeeList.Add(&101&, new Employee(101, &李大宝&,&技术部&, 3999)); lbx_id.Items.Add(&101&); employeeList.Add(&202&, new Employee(202, &王小二&,&生成部&, 2009)); lbx_id.Items.Add(&202&); employeeList.Add(&215&, new Employee(215, &钱三&, &销售部&, 5999)); lbx_id.Items.Add(&215&); } private void lbx_id_SelectedIndexChanged(object sender, EventArgs e) { if(lbx_id.SelectedItem!=null) { string id = lbx_id.SelectedItem.ToString().Trim(); Employee objEmployee = (Employee)employeeList[id]; tbx_ID.Text = objEmployee.id.ToString(); tbx_Name.Text = objEmployee. tbx_dpart.Text = objEmployee. tbx_pay.Text = objEmployee.pay.ToString(); } } } } (4)生成和执行此应用程序,效果如下图所示:程序运行结果图第二部分 第三部分练习(30 分钟) 作业10、WinForms 高级编程目标? ?创建一个更改窗口的大小与颜色的应用程序。 创建一个单文档的文本编辑器应用程序。指导教师讲解阶段目标 第一部分指导(60 分钟)练习 1:使用菜单、工具栏来改变窗口的大小与颜色问题 主菜单、快捷菜单、工具栏和状态栏的应用实例 指导教师讲解问题说明 用户在窗体上单击右键,弹出图示的快捷菜单。执行其中的颜色命令可产生与主菜单中相应命令等效的结果。某命令执行时 菜单项左侧带有“? ”标记。再次执行该菜单命令取消相应的颜色及菜单项左侧的“? ”标记,将颜色恢复为背景色。执行快捷 菜单中的“红”命令,然后再次打开快捷菜单后,如图 1.2 所示。图 1.1 默认窗体背景色图 1.2 红色背景色 分析 指导教师分析解题思路 添加工具栏和状态栏后, 窗体的界面设计如图 1.3 所示。 主要用到了这些控件:MenuStrip, Context MenuStrip, ToolStrip, StatusStrip。图 1.3 窗体设计界面 推荐步骤: (1)创建 Windows 应用项目。 (2)按照设计界面添加相应的控件,并在主菜单和快捷菜单中添加相应的菜单项;并添加相应的点击处理事件函数。 (3)完整的代码如下: using S using System.Collections.G using System.ComponentM using System.D using System.D using System.T using System.Windows.F namespace menuToolStatus{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void MenuItem_default_Click(object sender, EventArgs e) { this.BackColor = Control.DefaultBackC MenuItem_default.CheckState = CheckState.I cMenuItem_default.CheckState = CheckState.I MenuItem_blue.Checked = MenuItem_green.Checked = MenuItem_red.Checked = cMenuItem_blue.Checked = cMenuItem_green.Checked = cMenuItem_red.Checked = StatusLabel3.Text = &默认颜色&; } private void cMenuItem_default_Click(object sender, EventArgs e) { MenuItem_default_Click(sender, e); } private void MenuItem_red_Click(object sender, EventArgs e) { MenuItem_red.Checked = !MenuItem_red.C if (MenuItem_red.Checked) { this.BackColor = Color.R MenuItem_red.CheckState = CheckState.I cMenuItem_red.CheckState = CheckState.I MenuItem_blue.Checked = MenuItem_green.Checked = MenuItem_default.Checked = cMenuItem_blue.Checked = cMenuItem_green.Checked = cMenuItem_default.Checked= StatusLabel3.Text = &红色&; } else { this.BackColor =Control.DefaultBackC MenuItem_default.CheckState = CheckState.I cMenuItem_default.CheckState = CheckState.I StatusLabel3.Text = &默认颜色&; } } private void cMenuItem_red_Click(object sender, EventArgs e) { MenuItem_red_Click(sender, e); } private void MenuItem_green_Click(object sender, EventArgs e) { MenuItem_green.Checked = !MenuItem_green.C if (MenuItem_green.Checked) { this.BackColor = Color.G MenuItem_green.CheckState = CheckState.I cMenuItem_green.CheckState = CheckState.I MenuItem_blue.Checked = MenuItem_red.Checked = MenuItem_default.Checked = cMenuItem_blue.Checked = cMenuItem_red.Checked = cMenuItem_default.Checked = StatusLabel3.Text = &绿色&; } else { this.BackColor = Control.DefaultBackC MenuItem_default.CheckState = CheckState.I cMenuItem_default.CheckState = CheckState.I StatusLabel3.Text = &默认颜色&; } } private void MenuItem_blue_Click(object sender, EventArgs e) { MenuItem_blue.Checked = !MenuItem_blue.C if (MenuItem_blue.Checked) { this.BackColor = Color.B MenuItem_blue.CheckState = CheckState.I cMenuItem_blue.CheckState = CheckState.I MenuItem_red.Checked = MenuItem_green.Checked = MenuItem_default.Checked = cMenuItem_red.Checked = cMenuItem_green.Checked = cMenuItem_default.Checked = StatusLabel3.Text = &蓝色&; } else { this.BackColor = Control.DefaultBackC MenuItem_default.CheckState = CheckState.I cMenuItem_default.CheckState = CheckState.I StatusLabel3.Text = &默认颜色&; } } private void cMenuItem_green_Click(object sender, EventArgs e) { MenuItem_green_Click(sender, e); } private void cMenuItem_blue_Click(object sender, EventArgs e) { MenuItem_blue_Click(sender, e); } private void MenuItem_unTran_Click(object sender, EventArgs e) { this.TransparencyKey = this.BackC this.Opacity =1.0; } private void MenuItem_transl_Click(object sender, EventArgs e) { this.TransparencyKey = this.BackC this.Opacity =0.5; } private void tsBtn_big_Click(object sender, EventArgs e) { this.Width = 800; this.Height = 600; StatusLabel1.Text = &800x600 像素&; } private void tsBtn_middle_Click(object sender, EventArgs e) { this.Width = 600; this.Height = 480; StatusLabel1.Text = &600x480 像素&; } private void tsBtn_small_Click(object sender, EventArgs e) { this.Width = 400; this.Height = 360; StatusLabel1.Text = &400x360 像素&; } } } (4)通过从菜单中选择“生成”→“生成解决方案”,来生成该解决方案。 (5)通过从菜单中选择“调试” →“开始执行(不调试)”选项来执行此应用程序。 程序运行效果图 指导教师检查学生进度练习 2:创建一个单文档的文本编辑器应用程序问题 请编写一个简单的单文档文本编辑器,一次只能打开一个文件,如果要打开另一个文件,必须关闭当前打开的文件,微软的 写字板程序就是单文档字处理程序。 指导教师讲解问题说明使用 RichTextBox 可以建立一个文本编辑器,它和 TextBox 的一些属性、事件和方法相同,其新增属性、事件和方法如下:? ? ? ? ? ? ? ? ? ? ? ? ?属性 Dock: 属性 SelectedText、 SelectionLength、SelectionStart: 属性 SelectionFont: 属性 SelectionColor: 属性 Lines: 属性 Modified: 事件 SelectionChange: 事件 TextChanged: 方法 Clear(): 方法 Copy()、Cut()、Paste(): 方法 SelectAll(): 方法 Find(): 方法 SaveFile()和 LoadFile(): ? ?方法 Undo(): 方法 Redo():分析 指导教师分析解题思路 该问题需要开发一个窗体,要求对用户的简历信息进行登记。该应用程序主要用到按钮、文本输入框、图片显示框、下拉列 表框和列表框等控件。 推荐步骤: (1)新建一个名为“TxtEditor”的基于 Windows 应用程序的项目。 (2)剪贴板功能:放 RichTextBox 控件到窗体。属性 Name=richTextBox1,Dock=Fill,Text=&&。 添加相应的菜单项,各 菜单项的事件处理函数如下: private void menuItemEditCut_Click(object sender, EventArgs e) { richTextBox1.Cut(); } private void menuItemEditCopy_Click(object sender, EventArgs e) { richTextBox1.Copy(); } private void menuItemEditPaste_Click(object sender, EventArgs e) { richTextBox1.Paste(); } private void menuItemEditUndo_Click(object sender, EventArgs e) { richTextBox1.Undo(); } private void menuItemEditRedo_Click(object sender, EventArgs e) { richTextBox1.Redo(); } //恢复 //撤销 //粘贴 //拷贝 //剪切(3)文本编辑器都应具有文件存取功能,菜单顶级菜单项“文件”的弹出菜单中一般包括如下菜单项:新建、打开、关闭、 保存和另存为等。 把 OpenFileDialog 和 SaveFileDialog 控件放到窗体中。为菜单增加顶级菜单项:文件,为其弹出菜单增加菜单项:新建、 menuItemFileSave、menuItemFileSaveAs、menuItemFileExit。 为 Form1 类中定义变量:string s_FileName=&&,记录当前编辑的文件名。 private void menuItemFileNew_Click(object sender, EventArgs e) { if (!IfSaveOldFile())//如果返回 false,本次操作取消打开...、 保存...、 另存为...、 退出。 修改这些菜单项的 Name 属性分别为: mainMenuFile、 menuItemFileNew、 menuItemFileOpen、
richTextBox1.Text = &&; s_FileName = &&; } private void menuItemFileOpen_Click(object sender, EventArgs e) { if (!IfSaveOldFile())//如果返回 false,本次操作取消 if (openFileDialog1.ShowDialog() == DialogResult.OK) { s_FileName = openFileDialog1.FileN richTextBox1.LoadFile(openFileDialog1.FileName, RichTextBoxStreamType.PlainText); } } private void menuItemFileSaveAs_Click(object sender, EventArgs e) { if (saveFileDialog1.ShowDialog() == DialogResult.OK) { s_FileName = saveFileDialog1.FileN richTextBox1.SaveFile saveFileDialog1.FileName,RichTextBoxStreamType.PlainText); bSave = } } private void menuItemFileSave_Click(object sender, EventArgs e) { if (s_FileName.Length != 0) { bSave = richTextBox1.SaveFile(s_FileName, RichTextBoxStreamType.PlainText); } else menuItemFileSaveAs_Click(sender, e); } private void menuItemFileExit_Click(object sender, EventArgs e) { Close(); } (4) 修改字体 为修改使用的字体,可打开字体对话框 FontDialog,选择指定字体。可以按两种方式修改字体,如果未选中文本,表示以后 键入的字符将按选定字体输入。如果选中文本,则仅修改选定文本的字体。修改字符颜色也根据同样原则。 放 FontDialog 控件到窗体,属性 Name=fontDialog1。为菜单增加顶级菜单项:格式,属性 Name 为 mainMenuModel,为其弹出菜 //调用另存为菜单项事件处理函数 //注意存取文件类型应一致。 //或 richTextBox1.Clear(); //新建文件没有文件名。 单增加菜单项:字体,属性 Name 为 menuItemModelFont,为菜单“格式|字体”菜单项增加单击事件处理函数如下: private void menuItemModelFont_Click(object sender, EventArgs e) { if (fontDialog1.ShowDialog() == DialogResult.OK) richTextBox1.SelectionFont = fontDialog1.F } (5)About 对话框 添加一个窗体, 修改 formAbout 窗体属性 StartPosition=CenterParent, 修改属性 MaximizeBox=False, MinimizeBox=False 属性 FormBorderStyle=FixedDialog,运行界面 如下:标题为“确定”按钮单击事件处理函数如下: private void button1_Click(object sender, EventArgs e) { Close(); } 为菜单增加顶级菜单项:帮助,为其弹出菜单增加标题为“关于?”的菜单项,属性 Name 为 menuItemAbout。菜单“帮助| 关于?”菜单项单击事件处理函数如下: private void menuItemAbout_Click(object sender, EventArgs e) { formAbout AboutDialog = new formAbout(); AboutDialog.ShowDialog(this);//打开模式对话框 //注意不能使用 Show()函数,它打开非模式对话框 } (6)文本编辑器查找替换功能 建立新窗体,窗体文件名称为 formFindReplace.cs,作为&查找替换&对话框。窗体类名也为 formFindReplace,为 FormBorderStyle=FixedDialog,Text=“查找和替换”,对话框界面如图:formFindReplace 类增加变量: Form1 MainForm1; 属性 StartPosition=CenterParent, MaximizeBox=False, MinimizeBox=False, 修改 formFindReplace 类构造函数如下,增加的参数 form1 是主窗体属性 Name 的值。 public formFindReplace(Form1 form1) { InitializeComponent(); MainForm1 = form1; } //有了 Form1 引用,可以在 formFindReplace 类中调用 Form1 类的公有方法 查找替换对话框中标题为“查找下一个”按钮单击事件函数如下: private void button1_Click(object sender, EventArgs e) { if (textBox1.Text.Length != 0)//如果查找字符串不为空,调用主窗体查找方法 MainForm1.FindRichTextBoxString(textBox1.Text); else MessageBox.Show(&查找字符串不能为空&, &提示&, MessageBoxButtons.OK); }查找替换对话框中标题为“替换查到字符”按钮单击事件函数如下: private void button2_Click(object sender, EventArgs e) { if (textBox2.Text.Length != 0)//如果替换字符串不为空,调用主窗体替换方法 MainForm1.ReplaceRichTextBoxString(textBox2.Text);//调用上步增加的替换方法 else MessageBox.Show(&替换字符串不能为空&, &提示&, MessageBoxButtons.OK); } 为 Form1 类增加变量:int FindPostion=0,该变量用来记录下一次查找的开始位置。为 Form1 窗体菜单的&编辑&顶级菜单 项的弹出菜单增加菜单项:查找和替换,属性 Name 为 menuItemFindReplace。&查找和替换&菜单项单击事件处理函数如下: private void menuItemFindReplace_Click(object sender, EventArgs e) { FindPostion=0;//下句中的 this 是 Form1 类对象引用 formFindReplace FindReplaceDialog = new formFindReplace(this); FindReplaceDialog.Show();//打开非模式对话框使用 Show()方法 } 定义 FindRichTextBoxString 方法: public void FindRichTextBoxString(string FindString)//查找方法 { if (FindPostion &= richTextBox1.Text.Length)//如已查到文本底部,提示用户 { MessageBox.Show(&已到文本底部,再次查找将从文本开始处查找&,&提示&, MessageBoxButtons.OK); FindPostion = 0;//下次查找的开始位置 }//用 Find 方法查找,返回找到的位置,返回-1,表示未找到,参数是要找的字符串 //参数是查找的开始位置,参数是查找的一些选项,如大小写是否匹配,查找方向等 FindPostion = richTextBox1.Find(FindString, FindPostion, RichTextBoxFinds.MatchCase); if (FindPostion == -1)//-1 表示未找到匹配字符串,提示用户 { MessageBox.Show(&未找到匹配字符串,再次查找将从文本开始处查找&,&提示&, MessageBoxButtons.OK); FindPostion = 0;//下次查找的开始位置 } else//找到匹配字符串 { richTextBox1.Focus();//主窗体成为注视窗口 FindPostion += FindString.L }//下次查找的开始位置在此次找到字符串之后 } 替换字符串的方法: public void ReplaceRichTextBoxString(string ReplaceString)//替换方法 { if (richTextBox1.SelectedText.Length != 0)//如果选定了被替换字符串 richTextBox1.SelectedText = ReplaceS//替换被选定的字符串 } (7)提示保存已被修改的文件 为 Form1 类增加一个 bool 变量 bSave=false 作为标记,用来跟踪控件 RichTextBox 中的文本内容是否被修改。在程序开始 运行、建立和打开一个新文件后,bSave=false,表示如果关闭当前文件,不必提示用户保存当前文件。当 RichTextBox 控件中 的文本被修改,将激活 RichTextBox 控件 TextChanged 事件,在该事件处理函数中,使 bSave=true,表示关闭当前文件前,要询 问用户是否保存当前已被修改的文件。 首先在主窗体 Form1 类中增加一个函数,其功能是如果检查到当前文件已被修改,用对话框询问用户是否保存当前文件,根 据用户的选择作相应的处理,该函数返回 true,表示继续操作,该函数返回 false,表示忽略此次操作。之所以要增加这个函数 是因为有三处要用到此函数。该函数定义如下: public bool IfSaveOldFile() { bool ReturnValue = if (bSave) { System.Windows.Forms.DialogR dr = MessageBox.Show(this, &要保存当前更改吗?&, &保存更改吗?&, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); switch (dr)//根据用户选择做相应处理 { case System.Windows.Forms.DialogResult.Yes://单击了 yes 按钮,保存修改 bSave =//保存文件后,应使 bSave 为 false if (s_FileName.Length != 0) richTextBox1.SaveFile(s_FileName, RichTextBoxStreamType.PlainText); else { SaveFileDialog saveFileDialog1 = new SaveFileDialog(); if (saveFileDialog1.ShowDialog() == DialogResult.OK) { s_FileName = saveFileDialog1.FileN richTextBox1.SaveFile(s_FileName, RichTextBoxStreamType.PlainText); } } ReturnValue =//返回 true,通知调用本方法的程序,本次操作继续 case System.Windows.Forms.DialogResult.No://单击了 no 按钮,不保存 bSave = ReturnValue = case System.Windows.Forms.DialogResult.Cancel://单击了 Cancel 按钮 ReturnValue =//返回 false,通知调用本方法的程序,本次操作取消 } } return ReturnV } 为 RichTextBox 控件 TextChanged 事件增加事件函数如下: private void richTextBox1_TextChanged(object sender, EventArgs e) { bSave = } 窗体 Form1 的 FormClosing 事件是在关闭窗口之前产生的事件,此时,窗体中的控件还存在,还可以保存修改的内容,也可 以不退出。增加 Closing 事件的事件处理函数如下: private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (!IfSaveOldFile()) e.Cancel = }(8)通过从菜单中选择“调试” →“开始执行(不调试)”选项来执行此应用程序。程序运行效果图 指导教师检查学生进度第二部分练习(30 分钟) 在第一部分的练习二程序的基础上,将程序修改为多文档文本编辑器,类似于 word 应用程序。该程序可以打开多个文档窗 口,并可对多个窗口进行排列和操作:水平并排、垂直并排、层叠排列、关闭所有子窗口。 (1)将做为父窗体的窗体的 IsMdiContainer 属性改为 true。 (2)将新生成的子窗体的 MdiParent 属性设置为步骤一中的父窗体对象。第三部分指导教师布置作业作业文件系统监视器:开发一个程序可以设置要监视的文件夹,该文件夹下的活动(如创建、删除、重命名等操作)都将触发相 应的事件,编写相应的处理函数,以文本的形式通知用户该文件夹进行修改的详细信息。11、三层结构数据库系统开发问题 本案例实现一个小型的电子相册。完成的功能:显示相册中的照片,用户可以向相册中添加照片、删除相册中的照片以及在 相册中查找照片,每张照片都有自己的一些属性,如照片名称、照相时间、描述信息等等,都可以在相册中进行编辑。 1.添加照片:照片可以来自计算机中的任意文件夹,在添加照片时,对照片进行一些描述,包括名称、照相时间、对照片的 描述信息等。 2.对照片进行分类:所有照片在相册中被分为好几个类,如:家庭、朋友、同事、风景、其他等,所有的照片分类存储在各 个“文件夹”下面,从而方便用户浏览和查找。 3.查找照片:一旦照片数码太多,我们在其中寻找起来就会比较麻烦,所以我们还提供查找功能。可以根据照片的各个属性 进行查找。 4.删除相片:不需要保留的照片可以方便的从电子相册中删去。 指导教师讲解问题说明 分析 根据电子相册的功能划分和实现的方便,我们将整个程序分为 8 个类:一个 Model 类、一个 Controller 类和 4 个 View 类: Picture、List、Search 和 Attribute,另外两个是 TreeItem 类和 Observer 类。 TreeItem 类用于在界面上一树状的形式显示图片列表, Observer 类是所有 View 类的父类, 定义它是为了便于用 Controller 来控制所有的 View。 Model 类负责对数据库进行操作,包括向表中插入数据、更新数据、查询数据和删除数据,它放映了整个系统的业务逻辑, 这个类可以同时对应若干种不同的 View,这些视图只是在数据显示上有区别,如界面的布局,窗口的大小,显示的形式等。 Controller 类负责把界面上的各种操作传达给 Model 类,并通知所有的 View 及时更新,也就是说,把 Model 类对数据的修改及 时地放映到界面上。 Picture、List、Search 和 Attribute 类都是对数据库中的数据的不同形式的放映。它们从不同的侧面将数据库里面的数据 显示在界面上。Picture 用于显示当前正在浏览的一张照片;List 负责将所有照片以一个树状图的形式显示出来;Search 专门用 于显示查找后得到的结果列表;而 Attribute 则是对描述照片的各种属性的显示。 数据库表的设计 整个数据只用到了一个 Photos 表,它记录了所有照片的信息。该表的主键是照片编号字段,在照片插入时有数据库自动生 成。Name 字段是照片名字字段,它是不能为空的,在添加到相册中后还可以改变。Desc 字段是用户对照片的描述信息,可以为 不能为空。对照片图片的存储有两种方案:一种存路径,另一种直接存照片本身。为了避免照片在计算机中移动了位置而导致相空。Category 字段是指照片种类,它是一个枚举类型的字段,为了简化,我们规定 5 种类型:家庭、朋友、同事、风景、其他, 册中的照片无法定位的问题,选择存储照片本身。字段名为 Photo,为 image 类型,不能为空。Time 字段描述照片的拍摄时间。图 1 Photos 表 系统定义了一个 sp_InsertPhoto 存储过程,它用于将照片信息添加到相册中。添加的照片必须属于相册中已经给出的某一 类型。存储过程的返回值是当前插入照片的 ID 好。脚本语言如下: CREATE PROC sp_GetPhotoAlbums AS SELECT Albums.[id] AS AlbumID, Albums.[name] AS Album, Albums.[desc] AS Album_Desc, Photos.[id] AS PhotoID, Photos.[name] AS Photo, Photos.photo, Photos.[desc] AS Photo_Desc FROM Albums INNER JOIN Photos ON Albums.[id] = Photos.album_id ORDER BY Albums.[id] GO CREATE PROCEDURE sp_InsertPhoto @name AS VARCHAR(50), @image AS IMAGE, @album AS INT AS INSERT INTO Photos ([name], RETURN @@identity GO CREATE PROCEDURE sp_NewAlbum @name AS VARCHAR(20) AS INSERT INTO Albums ([name]) VALUES (@name) RETURN @@identity GO 方案实现: Observer 类的实现 Observer 类是所有 View 类的父类,它的实现非常简单,只有一个 dataUpdate 方法,这个方法将在每个具体的 View 类中按 情况分别实现。有了这个类,模型类对视图类的更新就简单多了,每次通知视图类更新时只需要调用一次 dataUpdate 方法。 photo, category) VALUES (@name, @image, @album) using S namespace EAlbum { //一个接口类,是所有 View 类的父类,定义了方法 dataUpdate,用于界面的刷新 public interface Observer { void dataUpdate(Model model,string str,int npara); } } TreeItem 类的实现 TreeItem 类用于与区分两种不同的结点:类别结点和照片结点。不同类型的结点对应的操作是不同的。这个类中的方法将用 来为每个结点做一个记号(包括 Id 和 ItemType),以便区分这两种不同的结点。 using S namespace EAlbum { //定义了树上的两种结点类型(相夹和照片) public enum ItemType { Album, Photo }; public class TreeItem { private int m_nId = 0; private ItemType m_Type = ItemType.P public TreeItem(ItemType type, int nId) { m_Type = m_nId = nId; } //对每个结点(相夹和照片)都会给一个编号,用于标识结点的当前位置 public ItemType Type { get{ return m_T } } public int Id { get{ return m_nId; } } } } Model 的实现 模块类完成的工作是从数据库中读取数据,并对数据进行操作。使用 ArrayList 类对象来保存从数据库中取出的数据以及一 些辅助的操作信息,从而方便对数据的操作。 为了在模型中实现对所有视图的统一更新操作,在模型类中为每个视图类进行了注册。这样一来,对每个视图的更新操作只 要用到一个简单的 dataUpdate 方法就可以了。 模块类中实现了对数据库的 5 种操作方法:照片的选取、查找、删除、添加和照片属性的更新。 照片的选取完成的功能是当用户在界面左边的列表上选取某张照片的名称后,将那张照片取出来显示在 PictureBox 中,这 个方法要解决的关键问题是如何得到界面上选取照片的 ID,实现中是把所有照片的 ID 放在 idList 中,与从视图传过来的 ID 进 行比较,如果匹配成功,则从数据库中取出照片,放在 image 中,通知 picture 类进行更新。 照片的查询可以对 3 种属性进行查询:照片名称、照相时间和描述信息,所以首先要在程序中对这一点进行判断,然后把用 户输入的关键字和数据库中相应的属性信息进行匹配,从而找到需要的照片。 删除照片最关键的是得到照片的 ID 值,程序中是从 idList[ListIndex]中取出,然后对数据库进行操作,最后对程序中定义的列 表中的内容进行更新。 在操作中调用了 sp_InsertPhoto 存储过程。 更新照片属性,先把信息写入数据库,然后对程序中定义的用于存储数据库信息的列表进行更新。 using S using System.D using System.C using System.D using System.Data.SqlC namespace EAlbum { //模型类 public class Model { //定义了一系列的列表,用于存储从数据库中取出的数据 public ArrayList idList,categoryList,nameList, descList,searchMark,albumList,timeList, private SqlConnection sqlC //图片类型 public I //标识结点位置 public int ListI //析构函数,用于关闭与数据库的连接 ~Model() { if(sqlConn.State == ConnectionState.Open) sqlConn.Close(); } //构造函数,初始化、实例化 Model 类中的成员变量 public Model() { ListIndex=-1; observer = new ArrayList(); idList=new ArrayList(); albumList=new ArrayList();添加照片中用到了对文件的处理,先从一个 FileStream 中得到文件的信息,放在一个 buffer 中,然后对 buffer 进行操作。 categoryList=new ArrayList(); nameList=new ArrayList(); descList=new ArrayList(); searchMark=new ArrayList(); timeList=new ArrayList(); albumList.Add(&家庭&); albumList.Add(&朋友&); albumList.Add(&同事&); albumList.Add(&风景&); albumList.Add(&其他&); sqlConn=new SqlConnection(&data source=Linitial catalog=EAUser ID=Password=&); //连接数据库 if(sqlConn.State == ConnectionState.Closed) sqlConn.Open(); if(sqlConn.State == ConnectionState.Open) { SqlCommand sqlCmd = new SqlCommand(&SELECT category, [id] AS PhotoID, [name] AS Photo, [desc] AS Photo_Desc,[time] AS Photo_Time FROM Photos &, sqlConn); SqlDataReader sqlPhotoAlbum = sqlCmd.ExecuteReader(); //将除图片本身以外的数据库表 Photos 中的信息全部取出,放在事先定义的列表中 while( sqlPhotoAlbum.Read() ) { idList.Add((int)sqlPhotoAlbum[&PhotoID&]); nameList.Add(sqlPhotoAlbum[&Photo&].ToString()); descList.Add(sqlPhotoAlbum[&Photo_Desc&].ToString()); timeList.Add(sqlPhotoAlbum[&Photo_Time&].ToString()); categoryList.Add((int)sqlPhotoAlbum[&category&]); //每添加一项就给对应的项做一个标记,为查找作准备 searchMark.Add(0); } sqlPhotoAlbum.Close(); } } //用来向模型中登记观察者,o 是一个 view 的实例 public void registerObserver(Observer o) { observer.Add(o); } // 用来向模型中注销观察者. public void removeObserver(Observer o) { observer.Remove(o); } //通知视图进行更新操作,str 代表操作的类型,npara 为此操作的参数(只在添加时有用) private void dataUpdate(string str,int npara) { for(int i=0;i&observer.Ci++) { ((Observer)observer[i]).dataUpdate(this,str,npara); } } /*下面定义了一系列对数据的操作 * 包括照片的选取、查找、删除、添加和照片属性的更新 * 这里用数字 1、2、3、4、5 分别表示这相应的 5 种操作 * */ //选取,index 为此照片在数据库中的 ID――对应着 picture 的数据的改变(PictureBox) public void select(int index) { ListIndex=-1; image= //没有选取照片 if(index&0) { dataUpdate(&1&,0); } //将被选中的照片的 ID 和已经取出的所有照片相比, //如果匹配则记下它的索引值――ListIndex――在整个列表中的序号 for(int i=0;i&nameList.Ci++) { if (((int)idList[i])==index) { ListIndex=i; } } //从数据库中取出此照片,放在 image 中 string strCmd = String.Format(&SELECT photo FROM Photos WHERE id = {0}&, index); SqlCommand cmd = new SqlCommand(strCmd, sqlConn); byte[] b = (byte[])cmd.ExecuteScalar(); if(b.Length & 0) { System.IO.MemoryStream stream = new System.IO.MemoryStream(b, true); stream.Write(b, 0, b.Length); image=new Bitmap(stream); stream.Close(); } //更新 dataUpdate(&1&,0); } //查找,支持模糊查询,index 的可能值为 0、1、2 //分别代表在照片名称、照相时间和描述信息中查找 public void search(int index,string str) { //照片名称 if(index==0) { for(int i=0;i&nameList.Ci++) { //如果在 nameList 中匹配到用户输入的关键字则将这个纪录对应的 searchMark 置 为 1(初始化时是 0) if (((string)nameList[i]).IndexOf(str)&-1) searchMark[i]=1; else searchMark[i]=0; } } //照相时间 if(index==1) { for(int i=0;i&timeList.Ci++) { //如果在 timeList 中匹配到用户输入的关键字则将这个纪录对应的 searchMark 置 为 1(初始化时是 0) if (((string)timeList[i]).IndexOf(str)&-1) searchMark[i]=1; else searchMark[i]=0; } } //描述信息 if(index==2) { for(int i=0;i&descList.Ci++) { //如果在 descList 中匹配到用户输入的关键字则将这个纪录对应的 searchMark 置 为 1(初始化时是 0) if (((string)descList[i]).IndexOf(str)&-1) searchMark[i]=1; else searchMark[i]=0; } } dataUpdate(&2&,0); } //删除照片 public int deletephoto() { //没有选定照片或数据库中没有照片,不执行任何删除操作 if(ListIndex&0 || idList.Count==0) return ListI //取出照片的 ID,从数据库中删除 int index=(int)(idList[ListIndex]); string strCmd= String.Format(&DELETE FROM Photos WHERE id = {0}&, index); SqlCommand cmd = new SqlCommand(strCmd, sqlConn); cmd.ExecuteNonQuery(); //把所有列表中关于此照片的数据删除 idList.RemoveAt(ListIndex); nameList.RemoveAt(ListIndex); descList.RemoveAt(ListIndex); categoryList.RemoveAt(ListIndex); searchMark.RemoveAt(ListIndex); timeList.RemoveAt(ListIndex); image= int revalue=ListI //将“指针”指向被删除照片的前一张照片 ListIndex--; dataUpdate(&3&,ListIndex); } //添加照片,参数 file 为文件名,cateid 为照片属于的种类 public int addphoto(string file,int cateid) { //将文件名为 file 的文件读入到 buffer 中 System.IO.FileStream stream = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read); byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, (int)stream.Length); stream.Close(); string strName = System.IO.Path.GetFileNameWithoutExtension(file); //调用 sp_InsertPhoto 存储过程,添加照片 SqlCommand cmd = new SqlCommand(&sp_InsertPhoto&, sqlConn); cmd.CommandType = CommandType.StoredP SqlParameter param = cmd.Parameters.Add(&RETURN_VALUE&, SqlDbType.Int); param.Direction = ParameterDirection.ReturnV cmd.Parameters.Add(&@name&, SqlDbType.VarChar).Value = strN cmd.Parameters.Add(&@image&, SqlDbType.Image).Value = cmd.Parameters.Add(&@album&,

我要回帖

更多关于 让按钮不可点击 的文章

 

随机推荐