客户端计时器控件(clientTimer)的c#源码

设计一个在线考试系统,卷面计时是必须解决的一个问题,因为考试都有一个答题时间限制,时间一到,针对那些仍未交卷的考生,系统应该有强制收卷的功能。当然,对于一个在线考试系统,最重要的还应该是他的答案保存功能,这里不做讨论,只分析卷面计时问题,最终设计出一个运行在客户端、超时后可以调用服务器端方法的计时器控件。

问题分析

(1)考生打开装载试题的页面标志着考试的开始,所以应该从这一刻起开始计时。
(2)服务器只能在有客户端请求的时候才会提供数据,而不会主动向浏览器post信息,所以必须在客户端实现计时。
(3)强制交卷本质上就是保存答案并退出答题界面,需要回发数据,因而该操作应该是一个服务器端方法。
(4)应该有一个友好界面,提示考生还剩多少时间。
(5)为了防止某些考生以给考试界面抓图保存、退出系统后按图做题、然后回来填写答案的方式,开始答题的同时交卷时间确定。
(6)对于那些受网络掉线、死机等不确定性因素影响而在考试过程中意外退出答题界面的考生,因为无法准确判断他们和蓄意考生的区别,我找不到合适的解决方法,只能算他们倒霉,浪费掉那些等待时间。你要有办法,可以讨论一下大家。


提出方案

针对以上的分析,可以提出一个大概的解决方法。

在数据库方面,在考试信息表中应该包含考生标识(string,用考号就可以)、开始答题时间(DateTime)、答题结束时间(DateTime)、已交卷(bool)四个字段(当然还得有其他的必要字段,这里就不详细说明了,毕竟我要说的只是卷面计时问题)。

在客户端方面,答题页面onload的时候调用一个javascript函数开始计时,这个函数是循环执行的,以便随时保存已用时间,这里设置其循环周期为1分钟,在函数体内,首先需要判断是否已到限制时间,若是则强制交卷,若否则显示友好界面的计时信息,然后等待下一次调用,相关js代码如下:

< scriptlanguage = " JavaScript " >

var myTimeOut = 30 ; // 可用时间,单位为分钟
var myPassTime = 0 ; // 已用时间,单位为分钟
window.attachEvent( " onload " ,myTimer); // 绑定到onload事件
function myTimer() {
if(myPassTime<myTimeOut){//已用时间是否小于可用时间
myPassTime+=1;//保存客户端已用时间
//显示友好界面的计时信息这里先空着

}
else{
//执行强制交卷
//可以通过模拟点击一个linkbutton来实现,
//在服务器端把强制交卷的代码先在linkbutton的Click里就可以了
}

window.setTimeout(
"myTimer()",60000);//一分钟循环一次
}

</ script >


在服务器代码方面,Page_Load事件中对考试信息进行初始化:
if(根据标识检索到当前考生的考试信息){
if(已交卷){
反馈已交卷信息
} else {
if(当前时间<答题结束时间){
设置好已用时间,让考生继续答题
} else {
强制交卷
}
}
} else {
添加考生的考试信息
设置好开始答题时间(设为当前时间)、答题结束时间(当前时间加上总的可用时间)、已交卷为(false)
正常进入考场
}

考试页面放置一个linkbutton,在该控件的Click里编写强制交卷代码,以供js模拟点击的时候执行。


设计控件

为了方便以后使用,这里把计时相关的功能封装成一个自定义控件。

控件名称:clientTimer,从PlaceHolder继承,命名空间为myControl。

公开属性:

属性名:TimeOutUnits
类 型:TimeOutUnitsType
介 绍:计时单位,有秒、分钟、小时三种,默认为分钟。

属性名:TimeOutLength
类 型:int
介 绍:计时超时时间(单位与TimeOutUnits属性一致)。

属性名:PassTimeLength
类 型:int
介 绍:已用去的时间(单位与TimeOutUnits属性一致)。

属性名:TimerEnabled
类 型:bool
介 绍:是否启用计时器。

属性名:CountDown
类 型:bool
介 绍:是否以倒计时的方式显示友好界面,是则显示还剩多少时间,否则显示用了多少时间。


公开事件:

事件名:onTimeOut
介 绍:超时的时候执行,可以把强制交卷的代码放里头执行


控件源码:

using System;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace myControl
... {
/**//**//**////<summary>
///客户端计时器clientTimer控件
///在线考试系统中卷面计时所用,你可以自由修改
///丛兴滋(cncxz)2005-12-3
///</summary>

[Description("客户端计时器clientTimer")]
[Designer(
typeof(clientTimerDesigner))]
[ToolboxData(
"<{0}:clientTimerrunat=server></{0}:clientTimer>")]
publicclassclientTimer:System.Web.UI.WebControls.PlaceHolder
...{

publiconTimeOutEventHandleronTimeOut;//超时事件
privateLinkButtonmyLB;
privateLabelmyLabel;

"公共属性""公共属性"#region"公共属性"

[Browsable(
true),Category("计时相关"),DefaultValue(TimeOutUnitsType.Minute),Description("计时单位,有秒、分钟、小时三种,默认为分钟。")]
publicTimeOutUnitsTypeTimeOutUnits
...{
get
...{
objectobj=ViewState["TimeOutUnits"];
return(obj==null)?TimeOutUnitsType.Minute:(TimeOutUnitsType)obj;
}

set
...{
ViewState[
"TimeOutUnits"]=value;
}

}



[Browsable(
true),Category("计时相关"),DefaultValue(30),Description("计时超时时间(单位与TimeOutUnits属性一致)。")]
publicintTimeOutLength
...{
get
...{
objectobj=ViewState["TimeOutLength"];
return(obj==null)?30:int.Parse(obj.ToString());
}

set
...{
ViewState[
"TimeOutLength"]=value;
}

}



[Browsable(
true),Category("计时相关"),DefaultValue(0),Description("已用去的时间(单位与TimeOutUnits属性一致)。")]
publicintPassTimeLength
...{
get
...{
objectobj=ViewState["PassTimeLength"];
return(obj==null)?0:int.Parse(obj.ToString());
}

set
...{
ViewState[
"PassTimeLength"]=value;
}

}



[Browsable(
true),Category("行为"),DefaultValue(false),Description("是否以倒计时的方式显示友好界面,是则显示还剩多少时间,否则显示用了多少时间。")]
publicboolCountDown
...{
get
...{
objectobj=ViewState["CountDown"];
return(obj==null)?false:(bool)obj;
}

set
...{
ViewState[
"CountDown"]=value;
}

}


[Browsable(
true),Category("行为"),DefaultValue(true),Description("是否启用计时器")]
publicboolTimerEnabled
...{
get
...{
objectobj=ViewState["TimerEnabled"];
return(obj==null)?true:(bool)obj;
}

set
...{
ViewState[
"TimerEnabled"]=value;
}

}


#endregion



publicclientTimer()
...{
myLB
=newLinkButton();
myLB.Click
+=newEventHandler(myLB_Click);
myLabel
=newLabel();
}


privatevoidmyLB_Click(objectsender,System.EventArgse)...{
if(onTimeOut!=null)...{
onTimeOut();
}

}


protectedoverridevoidOnLoad(EventArgse)
...{
if(this.TimerEnabled)
...{
myLB.ID
=this.ClientID+"_LB_TimeOut";
myLB.Text
="";

myLabel.ID
=this.ClientID+"_Label_Msg";
myLabel.Text
="";

this.Controls.Add(myLB);
this.Controls.Add(myLabel);
}

base.OnLoad(e);

}


protectedoverridevoidRender(HtmlTextWriterwriter)
...{
if(this.TimerEnabled)
...{
switch(this.TimeOutUnits)
...{
caseTimeOutUnitsType.Second:
writer.Write(
this.strJS(1000,""));
break;
caseTimeOutUnitsType.Minute:
writer.Write(
this.strJS(60000,"分钟"));
break;
caseTimeOutUnitsType.Hour:
writer.Write(
this.strJS(3600000,"小时"));
break;
}

}

base.Render(writer);
}


privatestringstrJS(intintCycLength,stringstrUnits)...{

stringstrFunction=this.ClientID+"_Timer";
stringstrTimeOut=this.ClientID+"_TimeOut";
stringstrPassTime=this.ClientID+"_PassTime";

stringscriptString=" ";
scriptString
+=@"<scriptlanguage=""JavaScript"">"+" ";
scriptString
+=@"<!--"+" ";
scriptString
+="var"+strTimeOut+"="+this.TimeOutLength.ToString()+"; ";
scriptString
+="var"+strPassTime+"="+this.PassTimeLength.ToString()+"; ";
scriptString
+=@"window.attachEvent(""onload"","+strFunction+");"+"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值