18.9 消息管理
消息管理是即时通信项目最重要的一个模块,其他模块都可以看作是这个模块的辅助部分。下面分4部分讲述Web QQ的消息管理模块,这4部分包括:主界面的消息管理、两人聊天的消息管理、群聊的消息管理、聊天记录和系统消息管理。
18.9.1 主界面的消息管理
在Web QQ主界面中,当有新消息到来时,发送消息者的头像将自动变为一个“小喇叭”形状,同时QQ菜单项下面显示一个“NEWS”字样的提示图标。运行效果如图18.29所示。
主界面消息管理的第二个任务就是维护联系人在线、离线的状态显示。在图18.29中,用户“趣查2”为在线状态,用户“1211”的头像暗了下来,是离线状态。主界面中必须根据用户的实际在线、离线状况,实时的把这种情况显示出来。
主界面消息管理的第三个任务就是动态更新系统消息数目。在个人头像的右边有一个“小信封”样式的图标,其中的数字就是当前未读的系统消息的数目。当有新的系统消息到来时,这个数目自动增加。新消息被阅读后,这个数目自动初始化为0。
以上3个任务是通过ASP.NET 2.0的CallBack机制来实现的。负责完成上面3个任务是right.aspx.cs,在right.aspx.cs中,实现了ICallbackEventHandler接口。right.aspx.cs的代码如下:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using MyChat;
public partial class frame_chat : System.Web.UI.Page, ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
rendercall(); //绘制客户端回调函数
if (!User.Identity.IsAuthenticated) return; //如果是未登录用户,返回
tools t = new tools();
bool havemsg; //是否有新消息
//构造显示联系人信息的脚本
string str = "document.getElementById('myfriend').innerHTML=\"" + t. LoadStr(0, out havemsg) + "\";";
str += "document.getElementById('myblack').innerHTML=\"" + t. LoadStr(1, out havemsg) + "\";";
str += "document.getElementById('mystranger').innerHTML=\"" + t. LoadStr(2, out havemsg) + "\";";
str += "document.getElementById('mygroup').innerHTML=\"" + t. LoadGroupStr() + "\";";
ClientScript.RegisterStartupScript(this.GetType(), "ii", str, true);
//注册脚本
}
}
//绘制客户端回调函数
public void rendercall()
{
ClientScriptManager m = Page.ClientScript; //客户端脚本管理对象
//得到callback引用
string str = m.GetCallbackEventReference(this, "args", "ReceiveOnlineData", "' '");
string strCallback = "function CallServer(args,context){ " + str + ";}";
//注册脚本
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", strCallback, true);
}
string str = ""; //callback返回的字符串
public string GetCallbackResult() //返回callback结果
{
return str;
}
public void RaiseCallbackEvent(string eventArgument) //调用callback事件
{
if (!User.Identity.IsAuthenticated) return; //未登录,返回
bool havemsg; //好友中是否有新消息
bool havemsg2; //黑名单中是否有新消息
bool havemsg3; //陌生人中是否有新消息
tools t = new tools();
tools.UpdateSelfTime(); //更新自己的最后上线时间
//构造返回的字符串
str = t.LoadStr(0, out havemsg) + "~" + (havemsg == true ? 1 : 0) + "~
" + t.LoadStr(1, out havemsg2) + "~" + t.LoadStr(2, out havemsg3) + "~
" + (havemsg == true ? 1 : 0) + "~" + t.LoadGroupStr();
str += "~ ";
//如果有最新消息,加上消息标志
if(havemsg == true || havemsg3 == true)
str += "1";
str += "~" + tools.GetSysMsgNum().ToString(); //加上系统消息数目
}
}
CallBack事件不能自动执行,在right.aspx页面文件中利用getmsg()函数调用CallBack事件。由上面的服务器端代码可以看出,CallBack执行成功后的回调函数是receiveOnlineData()方法。它负责解析服务器返回的结果,并把这个结果显示给用户。与主界面的消息管理相关的right.aspx中调用CallBack事件执行的客户端脚本代码如下:
//right.aspx中调用callback执行的代码。
<script language="JavaScript">
function getmsg() //查看是否有新消息
{
CallServer('getmsg;','');
}
setInterval('getmsg()',3000); //定时查看
</script>
//主界面接收用户的联系人信息与系统消息数目
function ReceiveOnlineData(args, context)
{
//分别用一个中转控件,用来传递内容
var s1 = document.getElementById("myfriend"); //好友
var s2= document.getElementById("myblack"); //黑名单
var s3 = document.getElementById("mystranger");//陌生人
var s4 = document.getElementById("mygroup"); //群
var t1 =document.getElementById("temp1"); //与好友对应的div
var t2 =document.getElementById("temp2"); //与黑名单对应的div
var t3 =document.getElementById("temp3"); //与陌生人对应的div
var t4 =document.getElementById("temp4"); //与群对应的div
var myarray = args.split("~"); //服务器返回的信息赋予对应的div
if(myarray[0]!=null) t1.innerHTML= myarray[0];
if(myarray[2]!=null) t2.innerHTML= myarray[2];
if(myarray[3]!=null) t3.innerHTML= myarray[3];
if(myarray[5]!=null) t4.innerHTML= myarray[5];
//如果返回的内容和现有的显示有区别,则更新显示
if(s1.innerHTML != t1.innerHTML)
{
s1.innerHTML = t1.innerHTML;
}
if(s2.innerHTML != t2.innerHTML)
{
s2.innerHTML = t2.innerHTML;
}
if(s3.innerHTML != t3.innerHTML)
{
s3.innerHTML = t3.innerHTML;
}
if(s4.innerHTML != t4.innerHTML)
{
s4.innerHTML = t4.innerHTML;
}
top.frames('chatqq').document.getElementById("Label2").innerHTML = myarray[7];
if(myarray[1] == 1) //好友中是否有新消息
document.getElementById("flag1").style.display = "block";
else
document.getElementById("flag1").style.display = "none";
if(myarray[4] == 1) //陌生人中是否有新消息
document.getElementById("flag2").style.display = "block";
else
document.getElementById("flag2").style.display = "none";
}
18.9.2 两人聊天页面Chat.aspx
两人聊天是聊天模式中最常见的一种,它的聊天窗口运行效果如图18.30所示。它的实现主要由Chat.aspx和js/chat.js程序来完成。

图18.30 两人聊天的窗口
Chat.aspx页面的主体是一个HTML编辑器。整个页面是以一张图片做背景,其他元素均采用绝对位置进行布局。页面详细代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="chat.aspx.cs" Inherits= "chat" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>聊天模式</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
.Hand_Off {
BACKGROUND-COLOR: #FFFFFFF;
Text-align: center;
}
.Hand_On {
background-color : #C6D3EF;
Text-align: center;
cursor: pointer;
}
</style>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/chat.js"></script>
</head>
<body style="background-image: url('images/chat.gif'); width: 410px; height: 412px;
background-repeat: no-repeat">
<form id="form1" runat="server">
<div title="关闭" onclick="top.frames('chatqq').closeInfoWnd('infoSys'+ top.frames('chatqq').wndNum);"
style="width: 38px; cursor: pointer; height: 24px; position: absolute; left: 369px;
top: 0px; z-index: 50000">
</div>
<div title="关闭" onclick="top.frames('chatqq').closeInfoWnd('infoSys'+ top.frames('chatqq').wndNum);"
style="width: 43px; cursor: pointer; height: 20px; position: absolute; left: 284px;
top: 386px;">
</div>
<div id="msgjilu" title="聊天记录" runat="server" style="width: 68px; height: 17px; cursor: pointer;
position: absolute; left: 21px; top: 385px;">
</div>
<div id="send" title="发送消息" onclick="sendmessage()" style="width: 42px; height: 12px;
position: absolute; cursor: pointer; left: 341px; top: 386px;">
</div>
<div id="config" onclick="showconfig();" title="发送消息配置" style="width: 10px; height: 10px;
position: absolute; cursor: pointer; left: 390px; top: 389px;">
</div>
<asp:Button ForeColor="#045371" ID="Button1" runat="server" BackColor= "#a3ddff" BorderColor="#E0E0E0"
BorderWidth="0px" Height="15px" OnClick="Button1_Click" OnClientClick=" clearInterval(isdog);return true;"
Style="vertical-align: middle; position: absolute; left: 249px; top: 41px;" Text="删除该好友"
Width="62px" />
<asp:Button ForeColor="#045371" BackColor="#a3ddff" Style="vertical-align: middle;
position: absolute; left: 324px; top: 40px;" ID="Button2" OnClick= "Button2_Click"
runat="server" Width="62px" Text="拉入黑名单" OnClientClick=" clear Interval(isdog);return true;"
Height="15px" BorderWidth="0px" BorderColor="#E0E0E0"></asp:Button>
<table style="position: absolute; left: 8px; width: 397px; top: 239px;">
<textarea name="content" id="content" style="display: none; width: 380px; word-bread: break-all;
word-wrap: break-word; scrollbar-face-color: #DBEBFE; scrollbar- shadow-color: #B8D6FA;
scrollbar-highlight-color: #FFFFFF; scrollbar-3dlight-color: #DBEBFE; scrollbar-darkshadow-color: #458CE4;
scrollbar-track-color: #FFFFFF; scrollbar-arrow-color: #458CE4"> </textarea>
<tr>
<td width="100">
<select name="font_name" style="width: 100" id="font_name" onchange="FontName(this.options[this.selectedIndex].value)">
<option class="heading" selected>字体</option>
<option value="宋体">宋体</option>
<option value="黑体">黑体</option>
<option value="楷体_GB2312" style="margin-top: 0px;">楷体</option>
<option value="仿宋_GB2312">仿宋</option>
<option value="隶书">隶书</option>
<option value="幼圆">幼圆</option>
<option value="新宋体">新宋体</option>
<option value="细明体">细明体</option>
<option value="Arial">Arial</option>
<option value="Arial Black">Arial Black</option>
<option value="Arial Narrow">Arial Narrow</option>
<option value="Bradley Hand ITC">Bradley Hand ITC</option>
<option value="Brush Script MT">Brush Script MT</option>
<option value="Century Gothic">Century Gothic</option>
<option value="Comic Sans MS">Comic Sans MS</option>
<option value="Courier">Courier</option>
<option value="Courier New">Courier New</option>
<option value="MS Sans Serif">MS Sans Serif</option>
<option value="Script">Script</option>
<option value="System">System</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Viner Hand ITC">Viner Hand ITC</option>
<option value="Verdana">Verdana</option>
<option value="Wide Latin">Wide Latin</option>
<option value="Wingdings">Wingdings</option>
</select>
</td>
<td width="60">
<select name="font_size" id="font_size" onchange="FontSize (this. options[this.selectedIndex].value)">
<option value="1">字号</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</td>
<td width="19" onclick="FontColor()" onmouseover="this.class Name='Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/fgcolor.gif" width="16" height="16" border="0" alt="字体颜色"></td>
<td width="21" onclick="BackColor()" onmouseover="this.class Name='Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/fbcolor.gif" width="16" height="16" border="0" alt="背景颜色"></td>
<td width="17" onclick="bold()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/bold.gif" width="16" height="16" border="0" alt="加粗"></td>
<td width="17" onclick="italic()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/italic.gif" width="16" height="16" border="0" alt="倾斜"></td>
<td width="18" onclick="underline()" onmouseover="this.class Name='Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/underline.gif" width="16" height= "16" border="0" alt="下划线"></td>
<td width="112" class='Hand_Off'>
</td>
</tr>
<tr>
<td colspan="9" style="width: 390px; height: 110px;">
<script type="text/javascript" language="JavaScript">
Editor(document.getElementById("content").value);//编辑器初始化
</script>
</td>
</tr>
</table>
<div style="width: 388px; height: 176px; overflow: auto; position: absolute; padding-bottom: 20px;
left: 10px; top: 60px; scrollbar-face-color: #DBEBFE; scrollbar-shadow- color: #B8D6FA;
scrollbar-highlight-color: #FFFFFF; scrollbar-3dlight-color: #DBEBFE; scrollbar-darkshadow-color: #458CE4;
scrollbar-track-color: #FFFFFF; scrollbar-arrow-color: #458CE4" id="abc">
<div style="width: 100%; word-bread: break-all; word-wrap: break-word; font-size: 12px;"
id="newmessage">
</div>
</div>
<input id="myte" name="myte" type="hidden" />
<script language="JavaScript" type="text/javascript">
var newmsg = document.getElementById ("newmessage");
var isdog = setInterval('getmsg()',500); //定期获得消息
document.getElementById('myte').value ='infoSys' +(top.frames('chatqq'). wndNum); //获得消息数目
</script>
<script type="text/javascript">
var mycookie;
mycookie =getCookieVal("sendchat"); //得到发送消息的配置,是按Enter键发送,//还是Ctrl+Enter组合键发送
oEditor.document.onkeyup= function aa() //在编辑器窗口挂载一个按键事件
{
if(mycookie=="") //默认是Ctrl+Enter组合键发送
{
if(oEditor.event.keyCode==13&&oEditor.event.ctrlKey)
{
sendmessage();
}
}
else //按Enter键发送
{
if(oEditor.event.keyCode==13)
{
sendmessage();
}
}
}
</script>
</form>
</body>
</html>
在chat.aspx.cs程序中的Page_Load()事件,是用来显示自身的头像和账号,并给客户端注册一些变量,以待使用。Page_Load()代码如下:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
string otherid = Request.QueryString["otherid"]; //聊天对方的id
string othername = Server.UrlDecode(Request.QueryString["othername"]);
//聊天对方的账号
msgjilu.Attributes.Add("onclick", "top.frames('chatqq').getsys(" +
othername + ")");//获得聊天记录
//定义客户端变量,利于客户端使用
Response.Write("<script type=\"text/javascript\" language=\"Java Script\">var receiverid = " + otherid + ";receivername='" + othername + "';var myname='" +User.Identity.Name + "';var myid =" + tools.GetUserId(User.Identity.Name) + ";</script>");
}
}
18.9.3 两人聊天相关脚本js/chat.js
与聊天(包括两人聊天和群聊天)相关的客户端脚本文件封装在js/chat.js中。它的方法主要包括:工具方法、发送、接收消息的方法、发送消息的配置方法等。
工具方法包括3个函数:trim()用于去掉首尾的空格、setCookieVal()用来设置cookie值、getCookieVal()用来获取cookie的值。
发送消息的配置方法是Showconfig(),它是用来显示发送消息的键盘配置窗口。默认情况下是Ctrl+Enter键发送消息,用户也可以选择Ctrl键发送消息。Showconfig()方法显示一个div层,供用户在消息发送方式中进行选择。客户端脚本封装后的文件Js/chat.js的代码如下:
//过滤字符串
String.prototype.trim = function() {
return this.replace(/^\s*|\s*$/g,"");
}
//设置cookie值
function setCookieVal(name, value, hours) {
var expire = ""; //过期时间
if (hours != null) {
expire = new Date((new Date()).getTime() + hours * 3600000);
} else {
expire = new Date((new Date()).getTime() + 1 * 3600000);
}
expire = "; expires=" + expire.toUTCString();
document.cookie = name + "=" + escape(value) + expire; //设置cookie
}
//得到某cookie的值
function getCookieVal(name) {
var cookieValue = ""; //cookie值
var search = name + "=";
if (document.cookie.length > 0) { //寻找这个cookie
offset = document.cookie.indexOf(search);
if(offset != -1) { //找到了这个cookie
offset += search.length;
end = document.cookie.indexOf(";", offset);
if (end == -1) {
end = document.cookie.length;
}
cookieValue = unescape(document.cookie.substring(offset, end)) //cookie值
}
}
return cookieValue;
}
//发送信息
function sendmessage(isgroup){
var str = getContent().trim(); //得到编辑器的内容
if(str.length ==0) //空消息不能发送
{
top.frames('chatqq').myAlert("不能发送空消息!");
return;
}
if (str.length >150) //消息太长不能发送
{
top.frames('chatqq').myAlert("你输入的字符太长,超过150个,请删除多余部分,或者分次发送!!");
return;
}
beforeSend( str ); //消息发送前进行一些处理
if(arguments.length==0) //两人聊天发送消息
Request.sendGET("message.ashx?str="+escape(str)+"&type=1&receiverid="+receiverid+"&receivername="+escape(receivername)+"&rnd="+10000*Math.random(),null,null,null,null);
Else //群聊天发送消息
Request.sendGET("groupmessage.ashx?str="+escape(str)+"&type=1&groupid="+groupi- d+"&rnd="+10000*Math.random(),null,null,null,null);
}
//发送消息前进行必要的处理
function beforeSend(str)
{
oEditor.document.body.innerHTML=""; //清空编辑器内容
str ="<b>"+ myname+":</b><br/>  "+str+"<br/>" //对内容赋予一定格式
newmsg.innerHTML = newmsg.innerHTML +str; //把发送的消息显示出来
//消息显示的div滚动到最新消息处
document.getElementById("abc").scrollTop = document.getElementById("abc").scrollHeight;
}
//发送后进行必要的处理
function afterSend(req,data)
{}
//发出接受消息的请求
function getmsg(isgroup)
{
if(arguments.length ==0) //接收两人聊天的消息
Request.sendGET("message.ashx?myid="+myid+"&senderid="+receiverid+"&sendername="+ escape(receivername)+"&rnd="+10000*Math.random(),ReceiveServerData,newmsg,null,null);
if(arguments.length ==1) //接收群聊的消息
Request.sendGET("groupmessage.ashx?myid="+myid+"&groupid="+groupid+"&rnd="+ 10000*Math.random(),ReceiveServerData,newmsg,null,null);
}
//接受到信息后进行页面显示的更改
function ReceiveServerData(req, data)
{
if(req.responseText != "nomessage") //有消息
{
data.innerHTML +=req.responseText; //显示消息
//消息显示的div滚动到最新消息处
document.getElementById("abc").scrollTop = document.getElementById("abc").scrollHeight;
}
}
function showconfig()
{
var mx = window.event.x; //x值
var my = window.event.y; //y值
var div = document.createElement("div"); //创建一个层,设置相应属性
div.style.fontSize="11px";
div.id = "templayer";
div.style.color ="blue";
div.style.backgroundColor="#B2D7F2";
//合成字符串
var html = "发送方式配置:<br/>\
<span style='align:right;cursor:pointer' onclick=\"setCookieVal('sendchat', '', 480);mycookie='';closeme('"+div.id;
html += "');\">CTR+ENTER(默认)</span></br>\
<span style='align:right;cursor:pointer' onclick=\"setCookieVal('sendchat', 'value', 480);mycookie='value';closeme('"+div.id;
html += "');\">ENTER</span><br/>";
div.innerHTML = html
div.style.position = "absolute"; //绝对位置
div.style.left = mx-100+"px";
div.style.top = my-45+"px";
document.body.appendChild(div); //添加元素
}
18.9.4 消息处理message.ashx
发送和接收消息的服务器处理页面文件是message.ashx。执行message.ashx时首先判断请求类型:发送消息还是接收消息。然后通过获得请求的相关参数,执行特定操作。代码如下:
<%@ WebHandler Language="C#" Class="message" %>
using System;
using System.Web;
using MyChat;
public class message : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
//发送聊天消息
if(context.Request.QueryString["type"] == "1")
{
string b = "0"; //操作成功与否的标志,0表示失败,1表示成功
int toid; //需要发送到的人的id
//消息内容
string str = context.Server.UrlDecode(context.Request.QueryString ["str"]);
//发送到的人的name
string toname = context.Server.HtmlDecode(context.Request.QueryString ["receivername"]);
if(int.TryParse(context.Request.QueryString["receiverid"], out toid) && str != null)
{
improve im = new improve();
im.SendMsg(context, toname, str);//发送
b = "1"; //发送成功标志
}
context.Response.Write(b);
context.Response.End();
}
else //接收聊天消息
{
string b = string.Empty ;//操作成功与否的标志,0表示失败,1表示成功
int senderid; //发送者id
int userid; //自己的id
string sendername; //发送者账号
if(int.TryParse(context.Request.QueryString["myid"], out userid)
&& int.TryParse(context.Request.QueryString["senderid"], out senderid))
{
//发送者姓名
sendername = context.Server.UrlDecode(context.Request.QueryString
["sendername"]);/
improve im = new improve();
//接收消息
MsgTable m = im.ReceiveMsg(context, sendername);
for(int i = 0; i < m.List.Count; i++) //构造消息格式
b += "<b>" + ((Msg)(m.List[i])).SenderName + ":</b><br/> "
+ ((Msg)(m.List[i])).Message + "</br>";
}
if (b == string.Empty ) b = "nomessage"; //没有消息,显示消息提示
context.Response.Write(b);
context.Response.End();
}
}
public bool IsReusable //不重用
{
get
{
return false;
}
}
}
18.9.5 群聊的页面Groupchat.aspx
群聊的消息界面和两人聊天的消息界面类似,如图18.31所示。

图18.31 群聊的窗口
群聊页面的布局和两人聊天也非常相似。用一张图片做背景,其他元素采用绝对位置进行定位。群聊页面文件Groupchat.aspx的代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="groupchat.aspx.cs" Inherits="groupchat2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>聊天模式</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
.Hand_Off {
BACKGROUND-COLOR: #FFFFFFF;
Text-align: center;
}
.Hand_On {
background-color : #C6D3EF;
Text-align: center;
cursor: pointer;
}
</style>
<script type="text/javascript" src="js/tools.js"></script>
<link href="face/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/chat.js"></script>
</head >
<body style =" background-image:url('images/chat2.gif'); width:490px; height: 410px;background-repeat:no-repeat">
<form id="form1" runat="server">
<div title="我的空间" id="person" style="width: 26px; height: 14px; position: absolute; left: 16px; top: 39px;"></div>
<div title="我的支付专家" id ="manager" style="width: 27px; height: 14px; position:absolute; left: 87px; top: 40px;"></div>
<div title="我的店铺" id ="shop" style="width: 24px; height: 14px; position: absolute; left: 52px; top: 40px;"> </div>
<div title ="关闭" onclick="top.frames('chatqq').closeInfoWnd('infoSys' +top.frames('chatqq').wndNum);" style="width: 30px;cursor:pointer ; height: 23px; position: absolute; left: 456px; top: 4px;z-index:50000"> </div>
<div title ="关闭" onclick="top.frames('chatqq').closeInfoWnd('infoSys'+ top.frames('chatqq').wndNum);" style="width: 43px;cursor:pointer ; height: 20px; position:absolute; left: 254px; top: 383px;"> </div>
<div id ="msgjilu" title="聊天记录" runat ="server" style="width: 68px; height: 17px;cursor:pointer ; position:absolute; left: 11px; top: 384px;"></div>
<div id ="send" title ="发送消息" onclick ="sendmessage('isgroup')" style= "width: 42px; height: 12px; position:absolute;cursor:pointer ; left: 307px; top: 386px;"> </div>
<div id ="config" onclick ="showconfig();" title ="发送消息配置" style="width: 10px; height: 10px; position:absolute;cursor:pointer ; left: 353px; top: 389px;"></div>
<table style="position: absolute; left: 8px; width: 357px; top: 239px; height: 91px;">
<textarea name="content" id="content" style="display: none; width: 344px; word-bread: break-all;
word-wrap: break-word;scrollbar-face-color: #DBEBFE; scrollbar- shadow-color: #B8D6FA; scrollbar-highlight-color: #FFFFFF; scrollbar-3dlight-color: #DBEBFE; scrollbar-darkshadow-color:#458CE4; scrollbar-track-color: #FFFFFF; scrollbar- arrow-color: #458CE4"></textarea>
<tr>
<td width="100">
<select name="font_name" style="width: 100" id="font_name" onchange="FontName(this.options[this.selectedIndex].value)">
<option class="heading" selected>字体</option>
<option value="宋体">宋体</option>
………
<option value="Wide Latin">Wide Latin</option>
<option value="Wingdings">Wingdings</option>
</select>
</td>
<td width="60">
<select name="font_size" id="font_size" style="70" onchange= "FontSize(this.options[this.selectedIndex].value)">
<option value="1">字号</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</td>
<td width="19" onclick="FontColor()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/fgcolor.gif" width="16" height="16" border="0" alt="字体颜色"></td>
<td width="21" onclick="BackColor()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/fbcolor.gif" width="16" height="16" border= "0" alt="背景颜色"></td>
<td width="17" onclick="bold()" onmouseover="this.className='Hand_ On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/bold.gif" width="16" height="16" border= "0" alt="加粗"></td>
<td width="17" onclick="italic()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/italic.gif" width="16" height="16" border= "0" alt="倾斜"></td>
<td width="18" onclick="underline()" onmouseover="this.className= 'Hand_On'" onmouseout="this.className='Hand_Off'"
class='Hand_Off'>
<img src="Editor/images/underline.gif" width="16" height="16" border="0" alt="下划线"></td>
<td width="112" class='Hand_Off'>
</td>
</tr>
<tr>
<td colspan="9" style="width: 359px; height:111px;">
<script type="text/javascript" language="JavaScript">Editor(document. getElementById("content").value);</script>
</td>
</tr>
</table>
<div style="width: 107px; position:absolute ; height: 160px; overflow: auto; padding-bottom: 20px; left: 372px; top: 60px;" id="def">
<div style="width: 100%; word-bread; text-align:center; word-wrap: break-word; font-size: 12px;" id="groupuser">
</div>
</div>
<div style="width:349px; height:175px; overflow:auto ; position:absolute ; padding-bottom:20px; left: 10px; top: 60px;
scrollbar-face-color: #DBEBFE; scrollbar-shadow-color: #B8D6FA; scrollbar-highlight- color: #FFFFFF; scrollbar-3dlight-color: #DBEBFE; scrollbar-darkshadow-color:#458CE4; scrollbar-track-color: #FFFFFF; scrollbar-arrow-color: #458CE4" id = "abc">
<div style="width:100%; word-bread:break-all;word-wrap:break-word ; font-size : 12px;" id="newmessage" ></div>
</div>
<input id="myte" name="myte" type="hidden" />
<asp:Button ID="Button2" style="position:absolute; left: 380px; top: 356px;" runat="server" Height="15px" OnClientClick =" clearInterval(isdog);return true;" Width="62px" BackColor="White" OnClick="Button1_Click" BorderColor="#E0E0E0" BorderWidth="0px" ForeColor="#044B9A" Enabled="False" />
<asp:Button ID="Button3" style="position:absolute; left: 380px; top: 326px;" runat="server" Height="15px" OnClientClick =" clearInterval(isdog);return true;" Width="71px" BackColor="White" OnClick="Button1_Click" BorderColor="#E0E0E0" BorderWidth="0px" ForeColor="#044B9A" Text="查看群资料" Visible="False" />
<asp:Button ID="Button4" style="position:absolute; left: 380px; top: 277px;" runat="server" Height="15px" OnClientClick ="top.frames('chatqq').create InviteWnd();return false;" Width="80px" BackColor="White" OnClick="Button1_Click" BorderColor="#E0E0E0" BorderWidth="0px" ForeColor="#044B9A" Text="邀请好友加入" />
<asp:Button ID="Button1" style="position:absolute; left: 381px; top: 303px;" runat="server" Height="15px" OnClientClick =" clearInterval(isdog);return true;" Text="退出该圈" Width="62px" BackColor="White" OnClick="Button1_Click" BorderColor= "#E0E0E0" BorderWidth="0px" ForeColor="#044B9A" />
<script type ="text/javascript" >
var newmsg = document.getElementById ("newmessage"); //定期获得消息
var isdog = setInterval('getmsg("isgroup")',500); //显示消息数目
document.getElementById('myte').value ='infoSys' +(top.frames('chatqq').wndNum);
var mycookie;
//得到发送消息的配置,是按Enter键发送,还是Ctrl+Enter组合键发送
mycookie =getCookieVal("sendchat");
oEditor.document.onkeyup= function aa() //在编辑器窗口挂载一个按键事件
{
if(mycookie=="") //默认是Ctrl+Enter组合键发送
{
if(oEditor.event.keyCode==13&&oEditor.event.ctrlKey)
{
sendmessage('isgroup');
}
}
else //按Enter键发送
{
if(oEditor.event.keyCode==13)
{
sendmessage('isgroup');
}
}
}
</script></form>
</body>
</html>
18.9.6 群聊的服务器端代码文件Groupchat.aspx.cs
Groupchat.aspx.cs中的Page_Load事件是用来获得群的ID并显示在标题中,然后注册用户ID、用户账号、群ID等客户端变量供脚本文件使用,最后在群用户列表中显示出所有加入这个群的用户。Page_Load事件的实现代码如下:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
string groupid = Request.QueryString["groupid"]; //群的id
//获得群消息
msgjilu.Attributes.Add("onclick", "top.frames('chatqq').getsys(" + groupid + ",true)");
Sql s = new Sql();
//获得群的名称
SqlDataReader r = s.GetReader("select username from group_user where groupid=" + groupid);
string str = "";
while (r.Read()) //有记录
{
Sql mys = new Sql();
SqlDataReader myr = mys.GetReader("select userid from userinfo where username ='" + r["username"].ToString() + "'");
myr.Read();
string idok = myr["userid"].ToString(); //用户id
myr.Close();//关闭连接
str += ("<span id='gp" + r["username"].ToString());//构造群的字符串
str += "' onMouseOver=this.className='face-1' onMouseOut=this. className='face' style='filter: Gray;height:22' onMouseDown=this.className='face-2' onMouseUp=this.className='face-1' class='FileListBig' onclick=top.frames('chatqq'). getdetail('";
str += idok + "')><span class='FileListTitle'>" + r["username"]. ToString() + "</span></span><br/>";
}
r.Close();
//生成客户端变量
Response.Write("<script type=\"text/javascript\" language=\"Java Script\">var groupid = " + groupid
+ ";var myname='" + User.Identity.Name + "';var myid =" + tools. GetUserId(User.Identity.Name) + ";</script>");
//群用户
string sc = "document.getElementById('groupuser').innerHTML +=\"" + str + "\"";
ClientScript.RegisterStartupScript(this.GetType(), "onlingroup", sc, true);
}
}
18.9.7 群聊的脚本文件js/chat.js
与群聊相关的脚本js/chat.js文件在18.9.3节已经介绍过。群消息的发送和接收同样是用脚本文件请求服务器端页面文件来完成。这个服务器端页面文件就是groupmessage.ashx。对它的理解可以参考message.ashx。groupmessage.ashx实现代码如下:
<%@ WebHandler Language="C#" Class="groupmessage" %>
using System;
using System.Web;
using MyChat;
public class groupmessage : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
//发送聊天消息
if(context.Request.QueryString["type"] == "1")
{
string b = "0"; //操作成功与否的标志,0表示失败,1表示成功
int toid; //需要发送到的人的id
//消息内容
string str = context.Server.UrlDecode(context.Request.QueryString["str"]);
if(int.TryParse(context.Request.QueryString["groupid"], out toid) && str != null)
{
improve im = new improve();
im.SendGroupMsg(toid.ToString(), str); //发送消息
b = "1"; //发送成功标志
}
context.Response.Write(b);
context.Response.End();
}
else //接收聊天消息
{
string b = ""; //操作成功与否的标志,0表示失败,1表示成功
int id; //群的id
if(int.TryParse(context.Request.QueryString["groupid"], out id))
{
improve im = new improve();
GroupMsgTable m = im.ReceiveGroupMsg(id.ToString());//接收群消息
for(int i = 0; i < m.List.Count; i++) //构造消息
b += "<b>" + ((BaseMsg)(m.List[i])).SenderName + ":</b><br/> " + ((BaseMsg)(m.List[i])).Message + "</br>";
}
if (b == "") b = "nomessage"; //没有消息
context.Response.Write(b);
context.Response.End();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
18.9.8 聊天记录和系统消息显示页面msgrecord.aspx
聊天历史记录(包括两人聊天和群聊)和系统消息显示页面的代码和表现形式大致相同,因此把它们集成到了一个页面文件msgrecord.aspx上。以两人聊天的历史记录显示为例,如自己和自己聊天后的聊天记录定行效果如图18.32所示。

图18.32 聊天记录显示页面
msgrecord.aspx页面中由一个GridView控件来显示数据信息,两个ImageButton按钮用来实现“上一页”和“下一页”的功能。其中的“关闭”按钮调用主界面的closeInfoWnd()方法,关闭页面。msgrecord.aspx的HTML代码如下:
//聊天消息显示页面msgrecord.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="msgrecord.aspx.cs" Inherits="msgrecord" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>趣查</title>
</head>
<body style="font-size: 9pt; margin: 0">
<form id="form1" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0" width="560" style= "height: 450">
<tr>
<td style="width: 534px" background="images/ziliao_r2_c12.gif">
<img id="ziliao_r2_c2" alt="" border="0" height="27" name= "ziliao_r2_c2" src="images/r2_c2.gif"
style="width: 104px" /></td>
<td style="text-align: left; width: 26px;" background="images/ ziliao_r2_c12.gif"
colspan="2">
<img height="16" src="images/ziliao_r3_c16.gif" width="16" onclick="top.frames('chatqq').closeInfoWnd('Sysmsg')" />
</td>
</tr>
<tr>
<td colspan="3" style="width: 560px;">
<table width="100%" border="0" cellpadding="0" cellspacing= "0" style="height: 379">
<tr>
<td rowspan="2">
<img id="ziliao_r3_c2" alt="" border="0" height= "379" name="ziliao_r3_c2" src="images/ziliao_r3_c2.gif"
width="3" /></td>
<td style="width: 553px; height: 349px">
<div style="width: 553px; height: 349px; overflow-x: none; overflow-y: auto">
<asp:GridView ID="GridView1" runat="server" Width= "552px" AutoGenerateColumns="False"
AllowPaging="True">
<Columns>
<asp:BoundField DataField="sendtime" HeaderText="时间">
<ItemStyle Width="20%" />
</asp:BoundField>
<asp:BoundField DataField="sendername" HeaderText="发送者">
<ItemStyle Width="10%" />
</asp:BoundField>
<asp:BoundField DataField="receivername" HeaderText="接收者">
<ItemStyle Width="10%" />
 

