www.pudn.com > 实景(图形)聊天室源代码(绝对高水 准,超酷).zip > chat.pas


{ *********************************************************************** } 
{                                                                         } 
{ Copular Chat Client v3.0 Source Code                                    } 
{ Chat Form Unit                                                          } 
{                                                                         } 
{ Copyright (c) 1998-2002 SAF Studio                                      } 
{                                                                         } 
{ Author  : Niu Yu Ping                                                   } 
{ Nickname: DecimalOX                                                     } 
{ Address : Jilin City China                                              } 
{                                                                         } 
{ QICQ    : 103106262                                                     } 
{ Homepage: www.safree.com                                                } 
{ EMail   : decimalox@sohu.com                                            } 
{                                                                         } 
{ *********************************************************************** } 
 
unit chat; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  DXClass, IniFiles, KsHooks, KsForms, KsSkinForms, ExtCtrls, AppEvnts, 
  ImgList, KsItems, EpIIItems, Menus, KsMenus, EpIIMenus, EpIIBitmaps, 
  ScktComp, DXSprite, DXInput, DXDraws, DxMap, ComCtrls, StdCtrls, 
  FatThings, KsCheckBoxs, KsSkinCheckBoxs, KsButtons, KsSkinButtons, 
  AHMTCommandLabel, KsControls, KsPanels, EpIIPanels, Sprite, IRCTags, 
  ShellApi, DIB; 
 
const 
  AUTHOR_NAME: string = 'decimalox'; 
  CLIENT_VERSION: string = 'Copular Chat v3.0.0.2'; 
 
  ERROR_MESSAGE_1: string='输入中包含有非法字符'; 
  ERROR_MESSAGE_2: string='请认真填写所有信息'; 
  ERROR_MESSAGE_3: string='昵称中不能包含有空格'; 
  ERROR_MESSAGE_4: string='两次输入的密码不一致'; 
  ERROR_MESSAGE_5: string='服务器拒绝请求'; 
  ERROR_MESSAGE_6: string='权限不够'; 
 
  ERROR_MAP_LOAD: string='地图文件已损坏,请重新下载'; 
 
  CLIENT_CONFIG_FILE: string='chat.cfg'; 
  CLIENT_DEFAULT_CONFIG_FILE: string='default.cfg'; 
  EMOTE_FILE: string = 'emote.dat'; 
 
  SYSTEM_INFO: string='[系统信息]'; 
  INTO_ROOM: string='满怀激情的加入了我们伟大的聊天事业'; 
  OUT_ROOM: string='带着无限的遗憾离我们而去'; 
  CLIENT_TIME_OUT: string='长时间没有发言,自动离开了聊天室'; 
 
  SYSTEM_INFO_TITLE_COLOR: DWORD=$0000FF; 
  SYSTEM_INFO_COLOR: DWORD=clGreen; 
 
type 
  TChatForm = class(TDXForm) 
    DxMap: TDxMap; 
    DXInput: TDXInput; 
    DXTimer: TDXTimer; 
    DXSpriteEngine: TDXSpriteEngine; 
    Panel1: TPanel; 
    Panel3: TPanel; 
    OnlineList: TListView; 
    Panel2: TPanel; 
    Panel5: TPanel; 
    DXDraw: TDXDraw; 
    Panel7: TPanel; 
    EpBitmapList1: TEpBitmapList; 
    EpPanel1: TEpPanel; 
    SpeakList: TFatMemo; 
    EpPanel2: TEpPanel; 
    Label1: TLabel; 
    TalkTo: TComboBox; 
    Sound: TLabel; 
    Label3: TLabel; 
    SpeakText: TComboBox; 
    DXImageList: TDXImageList; 
    Face: TLabel; 
    WebURL: TAHMCommandLabel; 
    FacePopMenu: TEpPopupMenu; 
    CustomItem1: TEpItem; 
    CustomItem2: TEpItem; 
    CustomItem3: TEpItem; 
    CustomItem4: TEpItem; 
    CustomItem5: TEpItem; 
    FaceList: TImageList; 
    ApplicationEvents1: TApplicationEvents; 
    Label6: TLabel; 
    Image1: TImage; 
    CustomItem6: TEpItem; 
    CustomItem7: TEpItem; 
    CustomItem8: TEpItem; 
    CustomItem9: TEpItem; 
    CustomItem10: TEpItem; 
    DXHeadList: TDXImageList; 
    TalkTimer: TTimer; 
    DXMapDraw: TDXDraw; 
    LogonBtn: TSeSkinButton; 
    AllSpeak: TSeSkinCheckBox; 
    AutoScroll: TSeSkinCheckBox; 
    SeSkinForm1: TSeSkinForm; 
    procedure DXDrawInitialize(Sender: TObject); 
    procedure DXDrawFinalize(Sender: TObject); 
    procedure DXTimerTimer(Sender: TObject; LagCount: Integer); 
    procedure DXDrawMouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure DXDrawMouseUp(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure FormDestroy(Sender: TObject); 
    procedure SpeakTextKeyPress(Sender: TObject; var Key: Char); 
    procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket); 
    procedure ClientConnect(Sender: TObject; Socket: TCustomWinSocket); 
    procedure ClientError(Sender: TObject; Socket: TCustomWinSocket; 
      ErrorEvent: TErrorEvent; var ErrorCode: Integer); 
    procedure LogonBtnClick(Sender: TObject); 
    procedure FaceClick(Sender: TObject); 
    procedure ApplicationEvents1Exception(Sender: TObject; E: Exception); 
    procedure SoundClick(Sender: TObject); 
    procedure OnlineListMouseUp(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure TalkToClick(Sender: TObject); 
    procedure ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); 
    procedure ClientConnecting(Sender: TObject; Socket: TCustomWinSocket); 
    procedure DXMapDrawMouseUp(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure CustomItem1Click(Sender: TObject); 
    procedure SpeakListLinkClick(Sender: TObject; Link: String); 
    procedure AllSpeakClick(Sender: TObject); 
    procedure TalkTimerTimer(Sender: TObject); 
    procedure DXMapDrawInitialize(Sender: TObject); 
    procedure DXMapDrawFinalize(Sender: TObject); 
    procedure DXMapDrawRestoreSurface(Sender: TObject); 
    procedure FormResize(Sender: TObject); 
    procedure FormShow(Sender: TObject); 
    procedure AutoScrollClick(Sender: TObject); 
  private 
    { Private declarations } 
    FMapName, //map name 
    CommandTeam: string; //command buffer 
    DefVer: Boolean; //default client version 
    AlreadyLogon: Boolean; 
    SelfName: string; 
 
    //self sprite 
    Me: TPlayerSprite; 
    Connected: Boolean; 
 
    //System message 
    SysText: string; 
 
    //face bitmap 
    FaceBmp: TBitmap; 
 
    CanSpeak: Boolean; 
 
    //radius of ellipse in the small map 
    EllipseR: Integer; 
 
    MapSurface: TDirectDrawSurface; 
 
    //work directory 
    WorkDir: string; 
 
    //small map name 
    LittleMapName: string; 
 
    //get a command string from buffer 
    function PopFromCommandTeam(var CommandTeam: string): string; 
 
    //search a sprite by caption from the online list 
    function FindOnline(ACaption: string): Integer; 
 
    //draw rectangle 
    procedure DrawRect(X, Y, Width, Height: Integer; Color: TColor); 
 
    //draw text into rectangle 
    procedure DrawText(X, Y: Integer; Text: string; TextColor, 
      BKColor: TColor; IsCaption: Boolean=False); 
 
    //logon to server 
    procedure Logon; 
 
    //send a command string to server 
    procedure SendCommand(CommandLine: string); 
 
    //draw a gradual ellipse on small map 
    procedure DrawEllipse(X, Y, MaxR, Speed: Integer); 
 
    //load map and necessary information from file 
    procedure LoadMap(MapName: string); 
  public 
    { Public declarations } 
    Client: TClientSocket; 
    Players: TPlayers; 
    constructor Create(AOwner: TComponent; MapName: string); reintroduce; 
  end; 
 
var 
  ChatForm: TChatForm; 
 
implementation 
 
uses 
  Logon, Main, Tools, Core; 
 
{$R *.DFM} 
 
procedure TChatForm.DXDrawInitialize(Sender: TObject); 
begin 
  //begin to refresh surface 
  DXTimer.Enabled:=True; 
end; 
 
procedure TChatForm.DXDrawFinalize(Sender: TObject); 
begin 
  //end refresh 
  DXTimer.Enabled:=False; 
end; 
 
procedure TChatForm.DXTimerTimer(Sender: TObject; LagCount: Integer); 
var 
  I, J: Integer; 
  TmpStr, TmpSound, TmpSend, TmpRece: string; 
  TmpSprite: TPlayerSprite; 
begin 
  if not DXDraw.CanDraw then 
    Exit; 
 
  //update DirectX components status and refresh 
  DXInput.Update; 
  DXSpriteEngine.Move(LagCount); 
  DXSpriteEngine.Dead; 
  DXDraw.Surface.Fill(0); 
  DXSpriteEngine.Draw; 
 
  with DXDraw.Surface.Canvas do 
  begin 
    //draw system message 
    Brush.Style:=bsClear; 
    Font.Name:='MS Sans Serif'; 
    Font.Charset:=GB2312_CHARSET; 
    Font.Size := 9; 
    Font.Color:=$00DEEFEF; 
    TextOut(5, 3, SysText); 
 
    //draw sprites' talk 
    for I:=0 to Players.Count-1 do 
      with Players.Items[I] do 
      begin 
        for J:=Talk.Count-1 downto 0 do 
        begin 
          if Talk.OnlyOne[J] then 
            TmpSound:='悄悄的' 
          else 
            TmpSound:=''; 
 
          if Talk.Send[J]=SelfName then 
            TmpSend:='你' 
          else 
            TmpSend:=Talk.Send[J]; 
 
          if Talk.Rece[J]=SelfName then 
            TmpRece:='你' 
          else 
            TmpRece:=Talk.Rece[J]; 
 
            TmpStr:=Format('%s%s对%s说:%s', [TmpSend, 
              TmpSound,  TmpRece, Talk.Items[J]]); 
 
          if TmpRece='你' then 
            DrawText(Trunc(WorldX-3-TextWidth(TmpStr) div 2)-8, Trunc(WorldY-30)-(Talk.Count-J)*20-3, 
               TmpStr, clNavy, TColor($57D1FF)) 
          else 
            DrawText(Trunc(WorldX-3-TextWidth(TmpStr) div 2)-8, Trunc(WorldY-30)-(Talk.Count-J)*20-3, 
               TmpStr, clNavy, clInfoBK); 
 
          //draw face 
          FaceList.GetBitmap(Talk.Face[J], FaceBmp); 
          Draw(Trunc(WorldX-3-TextWidth(TmpStr) div 2)-5,Trunc(WorldY-30)-(Talk.Count-J)*20-3, 
            FaceBmp); 
 
          Inc(Talk.Life[J]); 
          if Talk.Life[J]>=500 then 
            RollTalk; 
        end; 
        TmpSprite:=nil; 
 
        if IsMe then 
          TmpSprite:=Players.Items[I] 
        else 
          DrawText(Trunc(WorldX-3-TextWidth(Caption) div 2)-7, Trunc(WorldY-30)-3, 
             Caption, clBlack, TColor($00F3E3CF), True); 
 
        if TmpSprite<>nil then 
          DrawText(Trunc(WorldX-3-TextWidth(TmpSprite.Caption) div 2)-7, Trunc(WorldY-30)-3, 
             TmpSprite.Caption, clBlack, clYellow, True); 
      end; 
    Release; 
  end; 
  DXDraw.Flip; 
 
  //refresh small map 
  if not DXMapDraw.CanDraw then 
    Exit; 
 
  DXMapDraw.Surface.Fill(0); 
 
  DXMapDraw.Surface.Draw(0, 0, MapSurface.ClientRect, MapSurface, True); 
 
  for I:=0 to Players.Count-1 do 
    with Players.Items[I] do 
      with DXMapDraw.Surface.Canvas do 
      begin 
        Brush.Style:=bsClear; 
 
        if IsMe then 
        begin 
          Pen.Color:=clYellow; 
 
          Ellipse(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2)), 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2)), 
            Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2))+3, 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2))+3); 
 
          DrawEllipse(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2)), 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2)), DXMapDraw.Width, 2); 
        end 
        else 
        begin 
          Pen.Color:=clWhite; 
          MoveTo(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2))-FLAGSIZE, 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2))-FLAGSIZE); 
          LineTo(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2))+FLAGSIZE+1, 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2))+FLAGSIZE+1); 
 
          MoveTo(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2))+FLAGSIZE, 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2))-FLAGSIZE); 
 
          LineTo(Trunc((DXMapDraw.Width/MapW)*(X+MapW div 2))-FLAGSIZE-1, 
            Trunc((DXMapDraw.Height/MapH)*(Y+MapH div 2))+FLAGSIZE+1); 
        end; 
        Release; 
      end; 
 
  DXMapDraw.Flip; 
end; 
 
procedure TChatForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  if Me=nil then 
    Exit; 
  Me.AnchorX := X; 
  Me.AnchorY := Y; 
end; 
 
procedure TChatForm.DXDrawMouseUp(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
var 
  TmpStr: string; 
begin 
  if Me=nil then 
    Exit; 
 
  if Button = mbRight then 
    with Me do 
      SendCommand(CreateCommandLine(PLAYER_MOVE, 
        CreateParamLine([SelfName, FloatToStr(X+(AnchorX - worldx - width div 2)), 
        FloatToStr(Y+(AnchorY - worldy - height div 2))]))) 
  else 
    with Me do 
    begin 
      TmpStr:=Players.GetSpriteAt(X+(AnchorX - worldx - width div 2), 
            Y+(AnchorY - worldy - height div 2)); 
      if TmpStr<>'' then 
        TalkTo.ItemIndex:=TalkTo.Items.IndexOf(TmpStr); 
    end; 
end; 
 
procedure TChatForm.FormDestroy(Sender: TObject); 
begin 
  Me.Free; 
  Me:=nil; 
  FaceBmp.Free; 
  FaceBmp:=nil; 
  Players.Free; 
  Players:=nil; 
  Client.Free; 
  Client:=nil; 
end; 
 
procedure TChatForm.SpeakTextKeyPress(Sender: TObject; var Key: Char); 
begin 
  if Key=#13 then 
  begin 
    if not AlreadyLogon then 
      Exit; 
 
    if not CanSpeak then 
    begin 
      ErrorDlg(Handle, '发言太快,小心被踢出'); 
      Exit; 
    end; 
 
    if Length(SpeakText.Text)>80 then 
    begin 
      ErrorDlg(Handle, '发言太长,请尽量长话短说'); 
      Exit; 
    end; 
 
    if TalkTo.Text=SelfName then 
    begin 
      ErrorDlg(Handle, '不许自言自语'); 
      Exit; 
    end; 
 
    if (Sound.Caption='悄悄') and (TalkTo.Text='所有人') then 
    begin 
      ErrorDlg(Handle, '不能对所有人说悄悄话'); 
      Exit; 
    end; 
 
    if SpeakText.Text<>'' then 
    begin 
      SendCommand(CreateCommandLine(TALK, CreateParamLine([SelfName, 
        TalkTo.Text, IntToStr(Ord(Sound.Caption='悄悄')),  IntToStr(Face.Tag), 
        SpeakText.Text]))); 
 
      if SpeakText.Items.IndexOf(SpeakText.Text)=-1 then 
        SpeakText.Items.Add(SpeakText.Text); 
 
      SpeakText.Text:=''; 
 
      CanSpeak:=False; 
      //begin account the interval between two talks 
      TalkTimer.Enabled:=True; 
    end; 
  end; 
end; 
 
procedure TChatForm.ClientRead(Sender: TObject; Socket: TCustomWinSocket); 
var 
  I, J: Integer; 
  TmpCmdLn,TmpParam,TmpStr: string; 
  TmpCmd: DWORD; 
  L: TFatLine; 
begin 
  //update command buffer 
  CommandTeam:=CommandTeam+Socket.ReceiveText; 
 
  //get a piece of command 
  TmpCmdLn:=PopFromCommandTeam(CommandTeam); 
 
  while (TmpCmdLn<>NO_COMMAND_LINE) and (TmpCmdLn<>NO_COMMAND) do 
  begin 
    TmpCmd:=GetCommand(TmpCmdLn); 
    TmpParam:=GetParam(TmpCmdLn); 
 
    //do corresponding operation by command 
 
    if TmpCmd=CHECK_VERSION then 
    begin 
      DefVer:=not Boolean(StrToInt(GetParam(TmpCmdLn,1))); 
      if DefVer then 
      begin 
        ErrorDlg(Handle, '你使用的聊天室版本已经过期,可能无法正常使用,请到“甜不辣”网站升级'); 
        Close; 
      end 
      else 
      begin 
        Logon; 
      end; 
    end; 
 
    if TmpCmd=LOGON_SERVER_OK then 
    begin 
      if StrToInt(GetParam(TmpCmdLn,1))<>0 then 
        AlreadyLogon:=False; 
 
      case StrToInt(GetParam(TmpCmdLn,1)) of 
        0:begin 
          Top:=0; 
          SpeakText.SetFocus; 
        end; 
 
        1:begin 
            MainForm.UserName:=''; 
            MainForm.Password:=''; 
            ErrorDlg(Handle,'昵称不存在'); 
            Logon; 
        end; 
 
        2:begin 
            MainForm.UserName:=''; 
            MainForm.Password:=''; 
            ErrorDlg(Handle,'密码错误'); 
            Logon; 
        end; 
 
        3:begin 
            MainForm.UserName:=''; 
            MainForm.Password:=''; 
            ErrorDlg(Handle,'此昵称已经在聊天室中'); 
            Logon; 
        end; 
      end; 
    end; 
 
    if TmpCmd=GET_ONLINE_LIST_OK then 
    begin 
      OnlineList.Items.Clear; 
      TalkTo.Items.Clear; 
      Players.Clear; 
 
      TalkTo.Items.Add('所有人'); 
 
      with OnlineList.Items.Insert(0) do 
      begin 
        Caption:='所有人'; 
        SubItems.Add(' '); 
        SubItems.Add('用户'); 
      end; 
 
      I:=1; 
 
      while I<=StrToInt(GetParam(TmpCmdLn,1))*6 do 
      begin 
        J:=Players.Add(DXSpriteEngine.Engine, GetParam(TmpCmdLn,I+1), StrToIntDef(GetParam(TmpCmdLn,3),0)); 
 
        with Players.Items[J] do 
        begin 
          Image := DXHeadList.Items[StrToIntDef(GetParam(TmpCmdLn,I+4), 0)]; 
          AnimStart := 4; 
          AnimCount := 2; 
 
          PathInf.FObstacle:=Me.PathInf.FObstacle; 
          if LowerCase(Caption)=LowerCase(SelfName) then 
          begin 
            Me.Free; 
            Me:=Self.Players.Items[J]; 
            IsMe:=True; 
            Go(0, 0) 
          end 
          else 
            Go(StrToFloat(GetParam(TmpCmdLn, I+5)), StrToFloat(GetParam(TmpCmdLn, I+6))); 
        end; 
 
        TalkTo.Items.Add(GetParam(TmpCmdLn, I+1)); 
 
        with OnlineList.Items.Add do 
        begin 
          Caption:=GetParam(TmpCmdLn,I+1); 
 
          if GetParam(TmpCmdLn, I+2)='0' then 
            SubItems.Add('女') 
          else 
            SubItems.Add('男'); 
 
          if StrToIntDef(GetParam(TmpCmdLn, I+3), 0)>=150 then 
            SubItems.Add('管理员') 
          else 
            SubItems.Add('用户'); 
        end; 
        Inc(I,6); 
      end; 
 
      TalkTo.ItemIndex:=0; 
      I:=0; 
 
      while (ISelfName) do 
        Inc(I); 
    end; 
 
    if TmpCmd=LOGON_SERVER then 
    begin 
      if FindOnline(GetParam(TmpCmdLn,1))<>-1 then 
        Exit; 
 
      I:=Players.Add(DXSpriteEngine.Engine, GetParam(TmpCmdLn,1), StrToIntDef(GetParam(TmpCmdLn,3),0)); 
 
      with Players.Items[I] do 
      begin 
        Image := DXHeadList.Items[StrToIntDef(GetParam(TmpCmdLn,4), 0)]; 
        PathInf.FObstacle:=Me.PathInf.FObstacle; 
        if LowerCase(Caption)=LowerCase(SelfName) then 
        begin 
          Me:=Self.Players.Items[I]; 
          IsMe:=True; 
        end; 
        Go(0, 0); 
      end; 
 
      TalkTo.Items.Add(Players.Items[I].Caption); 
 
      with OnlineList.Items.Add do 
      begin 
        Caption:=Players.Items[I].Caption; 
 
        if GetParam(TmpCmdLn, 2)='0' then 
          SubItems.Add('女') 
        else 
          SubItems.Add('男'); 
 
        if StrToIntDef(GetParam(TmpCmdLn, 3), 0)>=150 then 
          SubItems.Add('管理员') 
        else 
          SubItems.Add('用户'); 
      end; 
    end; 
 
    if TmpCmd=LOGOUT_SERVER then 
    begin 
      I:=FindOnline(GetParam(TmpCmdLn,1)); 
      if I<>-1 then 
        OnlineList.Items.Delete(I); 
 
      I:=TalkTo.Items.IndexOf(GetParam(TmpCmdLn,1)); 
      if I<>-1 then 
        TalkTo.Items.Delete(I); 
 
      I:=Players.FindByCaption(GetParam(TmpCmdLn,1)); 
      if I<>-1 then 
        Players.Delete(I); 
    end; 
 
    if TmpCmd=PLAYER_MOVE then 
    begin 
      I:=Players.FindByCaption(GetParam(TmpCmdLn, 1)); 
      if I<>-1 then 
        Players.Items[I].Go(StrToFloat(GetParam(TmpCmdLn, 2)),StrToFloat(GetParam(TmpCmdLn, 3))); 
    end; 
 
    if TmpCmd=LOGOUT_SERVER_OK then 
      case StrToInt(GetParam(TmpCmdLn,1)) of 
 
        -1:ErrorDlg(Handle,ERROR_MESSAGE_5); 
 
        0:begin 
            OnlineList.Items.Clear; 
            AlreadyLogon:=False; 
            InfoDlg(Handle,'已经离开了聊天室'); 
        end; 
      end; 
 
    if TmpCmd=TALK  then 
    begin 
      I:=Players.FindByCaption(GetParam(TmpCmdLn, 1)); 
      if I<>-1 then 
      begin 
        Players.Items[I].Speak(GetParam(TmpCmdLn, 1),GetParam(TmpCmdLn, 2), GetParam(TmpCmdLn, 5), 
          StrToIntDef(GetParam(TmpCmdLn, 4), 0), Boolean(StrToIntDef(GetParam(TmpCmdLn, 3),0))); 
 
        with Players.Items[I].Talk do 
        begin 
          if (not AllSpeak.Checked) then 
            if (SelfName<>Send[Count-1]) and (SelfName<>Rece[Count-1]) then 
              Exit; 
 
          L:=SpeakList.Lines.AddNew; 
 
          if Send[Count-1]=SelfName then 
            TmpStr:=TAG_COLOR+'4'+TAG_BEGINLINK+TAG_UNDERLINE+Send[Count-1]+TAG_UNDERLINE+TAG_ENDLINK+TAG_COLOR 
          else 
            TmpStr:=TAG_COLOR+'12'+TAG_BEGINLINK+TAG_UNDERLINE+Send[Count-1]+TAG_UNDERLINE+TAG_ENDLINK+TAG_COLOR; 
 
          TmpStr:=TmpStr+TAG_COLOR+'1'+FacePopMenu.Items[Face[Count-1]].Caption+'的对'+TAG_COLOR; 
 
          if Rece[Count-1]=SelfName then 
            TmpStr:=TmpStr+TAG_COLOR+'4'+TAG_BEGINLINK+TAG_UNDERLINE+Rece[Count-1]+TAG_UNDERLINE+TAG_ENDLINK+TAG_COLOR 
          else 
            TmpStr:=TmpStr+TAG_COLOR+'12'+TAG_BEGINLINK+TAG_UNDERLINE+Rece[Count-1]+TAG_UNDERLINE+TAG_ENDLINK+TAG_COLOR; 
 
          if OnlyOne[Count-1] then 
            TmpStr:=TmpStr+TAG_COLOR+'1稍稍说:'+TAG_COLOR 
          else 
            TmpStr:=TmpStr+TAG_COLOR+'1说:'+TAG_COLOR; 
 
          if (SelfName=Send[Count-1]) or (SelfName=Rece[Count-1]) then 
            Tmpstr:=TmpStr+TAG_COLOR+'1 '+Items[Count-1]+TAG_COLOR 
          else 
            Tmpstr:=TmpStr+TAG_COLOR+'1 '+Items[Count-1]+TAG_COLOR; 
 
          L.AsIrcText:=TmpStr; 
        end; 
      end; 
    end; 
 
    if TmpCmd=ADVER_TEXT then 
    begin 
      SysText:=Format('系统信息:%s', [GetParam(TmpCmdLn,1)]); 
    end; 
 
    TmpCmdLn:=PopFromCommandTeam(CommandTeam); 
  end; 
end; 
 
function TChatForm.PopFromCommandTeam(var CommandTeam: string): string; 
var 
  I: Integer; 
begin 
  if Copy(CommandTeam,1,2)<>CMD_FLAG then 
  begin 
    I:=0; 
    repeat 
      Inc(I); 
    until 
      ((Copy(CommandTeam,I,2)=CMD_FLAG) and 
        (Copy(CommandTeam,I+2,2)<>CMD_FLAG)) or 
          (I>=Length(CommandTeam)); 
    if I>=Length(CommandTeam) then 
    begin 
      CommandTeam:=''; 
      Result:=NO_COMMAND_LINE; 
      Exit; 
    end 
    else 
      CommandTeam:=Copy(CommandTeam,I,Length(CommandTeam)-I+1); 
  end; 
 
  I:=2; 
  while (ICMD_FLAG) do 
    Inc(I); 
 
  if I>=Length(CommandTeam) then 
  begin 
    Result:=NO_COMMAND; 
    Exit; 
  end; 
 
  Result:=Copy(CommandTeam,1,I+1); 
  CommandTeam:=Copy(CommandTeam,I+2,Length(CommandTeam)-I-1); 
end; 
 
function TChatForm.FindOnline(ACaption: string): Integer; 
var 
  I: Integer; 
begin 
  Result:=-1; 
  for I:=0 to OnlineList.Items.Count-1 do 
    if OnlineList.Items[I].Caption=ACaption then 
    begin 
      Result:=I; 
      Exit; 
    end; 
end; 
 
procedure TChatForm.ClientConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  Connected:=True; 
  SysText:=Format('系统信息:%s', ['已连接服务器']); 
  SendCommand(CreateCommandLine(CHECK_VERSION,CLIENT_VERSION)); 
end; 
 
procedure TChatForm.ClientError(Sender: TObject; Socket: TCustomWinSocket; 
  ErrorEvent: TErrorEvent; var ErrorCode: Integer); 
begin 
  Connected:=False; 
  SysText:=Format('系统信息:%s', ['无法连接服务器']); 
  if MessageBox(Handle,'无法连接服务器,是否再次连接','错误', 
    MB_YESNO or MB_ICONQUESTION)=idYes then 
      Client.Open 
    else 
    begin 
      LogonBtn.Enabled:=False; 
      Close; 
    end; 
  ErrorCode:=0; 
end; 
 
procedure TChatForm.LogonBtnClick(Sender: TObject); 
begin 
  if not Connected then 
    Exit; 
 
  if AlreadyLogon then 
  begin 
    if MessageBox(Handle, '是否重新登录', '确认', MB_YESNO or MB_ICONQUESTION)=idNo then 
    begin 
      SpeakText.SetFocus; 
      Exit; 
    end; 
    MainForm.UserName:=''; 
    MainForm.Password:=''; 
    Client.Close; 
    Client.Open; 
  end 
  else 
    Logon; 
end; 
 
procedure TChatForm.FaceClick(Sender: TObject); 
begin 
  FacePopMenu.Popup(Mouse.CursorPos.x, Mouse.CursorPos.y); 
end; 
 
procedure TChatForm.DrawRect(X, Y: LongInt; Width, Height: LongInt; Color: TColor); 
var 
  RDC: TRect; 
begin 
  with DXDraw.Surface.Canvas do 
  begin 
    if Color=clNone then 
    begin 
      Brush.Style:=bsClear; 
      Pen.Style:=psClear; 
    end 
    else 
    begin 
      Brush.Color:=Color; 
      Pen.Color:=Color; 
    end; 
 
    Pie(X, Y, X+Height, Y+Height, X+Height, 50, X+Height, 150); 
    RDC.Left:=X+Height div 2; 
    RDC.Top:=Y; 
    RDC.Right:=X+Width; 
    RDC.Bottom:=Y+Height; 
    FillRect(RDC); 
    Pie(X+Width-Height div 2, Y, X+Width+Height div 2, Y+Height, X+Width+Height div 2, 0, X+Width+Height div 2,0); 
  end; 
end; 
 
procedure TChatForm.DrawText(X, Y: Integer; Text: string; TextColor, BKColor: TColor; 
  IsCaption:Boolean=False); 
begin 
  with DXDraw.Surface.Canvas do 
  begin 
    if IsCaption then 
      DrawRect(X, Y, TextWidth(Text)+10, TextHeight(Text)+4, BKColor) 
    else 
      DrawRect(X, Y, TextWidth(Text)+20, TextHeight(Text)+4, BKColor); 
    Font.Color:=TextColor; 
    if BKColor=crNone then 
      Font.Style:=[fsBold] 
    else 
      Font.Style:=[]; 
    if IsCaption then 
      TextOut(X+10, Y+2, Text) 
    else 
      TextOut(X+20, Y+2, Text); 
  end; 
end; 
 
procedure TChatForm.ApplicationEvents1Exception(Sender: TObject; 
  E: Exception); 
begin 
  try 
  except 
    on E:Exception do 
  end; 
end; 
 
procedure TChatForm.SoundClick(Sender: TObject); 
begin 
  if Sound.Caption='大声' then 
    Sound.Caption:='悄悄' 
  else 
    Sound.Caption:='大声'; 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.OnlineListMouseUp(Sender: TObject; 
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
var 
  TmpItem: TListItem; 
begin 
  TmpItem:=OnlineList.GetItemAt(X, Y); 
  if TmpItem<>nil then 
    TalkTo.ItemIndex:=TalkTo.Items.IndexOf(TmpItem.Caption); 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.TalkToClick(Sender: TObject); 
begin 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.ClientDisconnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  Connected:=False; 
  AlreadyLogon:=False; 
end; 
 
procedure TChatForm.Logon; 
begin 
  Screen.Cursor:=crHourGlass; 
  Me:=TPlayerSprite.Create(nil); 
  with Me do 
  begin 
    Image:=DXHeadList.Items[0]; 
    Caption:='Me'; 
    MakeMap(DXMap); 
  end; 
  if (MainForm.UserName<>'') and (MainForm.Password<>'') then 
  begin 
    SelfName:=MainForm.UserName; 
    SendCommand(CreateCommandLine(LOGON_SERVER, 
      CreateParamLine([LowerCase(MainForm.UserName),MainForm.Password]))); 
    AlreadyLogon:=True; 
  end 
  else 
    with TLogonForm.Create(Self) do 
      try 
        Screen.Cursor:=crDefault; 
        if ShowModal=mrOK then 
        begin 
          SelfName:=NickName.Text; 
          MainForm.UserName:=LowerCase(NickName.Text); 
          MainForm.Password:=Password.Text; 
          SendCommand(CreateCommandLine(LOGON_SERVER, 
            CreateParamLine([LowerCase(NickName.Text),Password.Text]))); 
          AlreadyLogon:=True; 
        end 
        else 
        begin 
          MainForm.UserName:=''; 
          MainForm.Password:=''; 
          Self.Close; 
        end; 
      finally 
        Free; 
        SpeakText.SetFocus; 
      end; 
  Screen.Cursor:=crDefault; 
end; 
 
procedure TChatForm.SendCommand(CommandLine: string); 
var 
  TmpCmd: DWORD; 
begin 
  TmpCmd:=GetCommand(CommandLine); 
 
  if (TmpCmd=CHECK_VERSION) or (TmpCmd=LOGON_SERVER) then 
    Client.Socket.SendText(CommandLine) 
  else 
    if AlreadyLogon then 
      Client.Socket.SendText(CommandLine); 
end; 
 
procedure TChatForm.ClientConnecting(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  SysText:=Format('系统信息:%s', ['正在连接服务器']); 
end; 
 
procedure TChatForm.DXMapDrawMouseUp(Sender: TObject; 
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
begin 
  if Me=nil then 
    Exit; 
 
  SendCommand(CreateCommandLine(PLAYER_MOVE, 
    CreateParamLine([SelfName, FloatToStr((x / (Sender as TDXDraw).width) * MapW-MapW div 2), 
    FloatToStr((y / (Sender as TDXDraw).height)*MapH- MapH div 2)]))); 
 
{  Me.Go((x / (Sender as TDXDraw).width) * MapW-MapW div 2, 
    (y / (Sender as TDXDraw).height)*MapH- MapH div 2);} 
end; 
 
procedure TChatForm.CustomItem1Click(Sender: TObject); 
begin 
  Face.Tag:=(Sender as TEPItem).ImageIndex; 
  Face.Caption:=(Sender as TEPItem).Caption; 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.SpeakListLinkClick(Sender: TObject; Link: String); 
begin 
  TalkTo.ItemIndex:=TalkTo.Items.IndexOf(Link); 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.AllSpeakClick(Sender: TObject); 
begin 
  SpeakText.SetFocus; 
end; 
 
procedure TChatForm.TalkTimerTimer(Sender: TObject); 
begin 
  CanSpeak:=True; 
  TalkTimer.Enabled:=False; 
end; 
 
procedure TChatForm.DXMapDrawInitialize(Sender: TObject); 
begin 
  MapSurface:=TDirectDrawSurface.Create(DXMapDraw.DDraw); 
end; 
 
procedure TChatForm.DXMapDrawFinalize(Sender: TObject); 
begin 
  Mapsurface.Free; 
  Mapsurface:=nil; 
end; 
 
procedure TChatForm.DXMapDrawRestoreSurface(Sender: TObject); 
begin 
  MapSurface.LoadFromGraphic(DXImageList.Items.Find(LittleMapName).Picture.Graphic); 
end; 
 
procedure TChatForm.DrawEllipse(X, Y, MaxR, Speed: Integer); 
begin 
  Inc(EllipseR); 
  if EllipseR>MaxR*Speed then 
    EllipseR:=0; 
 
  with DXMapDraw.Surface.Canvas do 
  begin 
    Brush.Style:=bsClear; 
    Pen.Color:=clYellow; 
    Ellipse(X-EllipseR+3, Y-EllipseR+3, X+EllipseR, Y+EllipseR); 
  end; 
end; 
 
procedure TChatForm.LoadMap(MapName: string); 
var 
  f: TIniFile; 
  TmpStr: string; 
begin 
  Screen.Cursor:=crHourGlass; 
  Client.Close; 
 
  FMapName:=MapName; 
 
  f:=TIniFile.Create(WorkDir+'\Maps\'+MapName+'.map'); 
 
  try 
    try 
      TmpStr:=f.ReadString('Map', 'Caption', ''); 
      Caption:=Format('Copular Chat v3.0 - %s', [TmpStr]); 
 
      TmpStr:=f.ReadString('Data', 'Resource', ''); 
      DXImageList.Items.LoadFromFile(WorkDir+'\Maps\'+TmpStr); 
 
      TmpStr:=f.ReadString('Data', 'MapFile', ''); 
      DXMap.DrawMap(WorkDir+'\Maps\'+TmpStr); 
 
      LittleMapName:=f.ReadString('Data', 'LittleMap', ''); 
 
      TmpStr:=f.ReadString('Server', 'Address', ''); 
      Client.Address:=TmpStr; 
 
      TmpStr:=f.ReadString('Server', 'Port', ''); 
      Client.Port:=StrToIntDef(TmpStr, 8064); 
    except 
      ErrorDlg(Handle, ERROR_MAP_LOAD); 
      Close; 
    end; 
  finally 
    F.Free; 
  end; 
  Screen.Cursor:=crDefault; 
  Client.Open; 
end; 
 
procedure TChatForm.FormResize(Sender: TObject); 
begin 
  if (Width<=320) or (Height<=280) then 
    Exit; 
 
  DXDraw.Finalize; 
  DXDraw.Initialize; 
 
  with DXSpriteEngine.Engine do 
  begin 
    X:=Width div 2; 
    Y:=Height div 2; 
  end; 
 
  DXSpriteEngine.Draw; 
 
  if Me<>nil then 
    Me.Go(Me.X+0.1, Me.Y+0.1); 
 
end; 
 
constructor TChatForm.Create(AOwner: TComponent; MapName: string); 
var 
  I: Integer; 
begin 
  inherited Create(AOwner); 
  Client:=TClientSocket.Create(Self); 
  Client.OnConnect:=ClientConnect; 
  Client.OnConnecting:=ClientConnecting; 
  Client.OnDisconnect:=ClientDisConnect; 
  Client.OnError:=ClientError; 
  Client.OnRead:=ClientRead; 
   
  Top:=Screen.Height; 
  Left:=0; 
  Width:=Screen.Width; 
  Height:=Screen.Height-30; 
 
  CanSpeak:=True; 
  SysText:='系统信息:'; 
  EllipseR:=0; 
  SpeakList.Lines.Clear; 
 
  Players:=TPlayers.Create(Self); 
 
  FaceBmp:=TBitmap.Create; 
  FaceBmp.TransparentColor:=clWhite; 
  FaceBmp.Transparent:=True; 
 
  DXImageList.Items.MakeColorTable; 
  DXDraw.ColorTable := DXImageList.Items.ColorTable; 
  DXDraw.DefColorTable := DXImageList.Items.ColorTable; 
  DXDraw.UpdatePalette; 
 
  WorkDir:=GetCurrentDir; 
  DXHeadList.Items.LoadFromFile(WorkDir+'\Res\Head.Res'); 
 
  with DXHeadList do 
    for I:=0 to Items.Count-1 do 
    begin 
      Items[I].Transparent:=True; 
      Items[I].TransparentColor:=TColor($522108); 
    end; 
 
  LoadMap(MapName); 
end; 
 
procedure TChatForm.FormShow(Sender: TObject); 
begin 
  AutoScroll.Refresh; 
end; 
 
procedure TChatForm.AutoScrollClick(Sender: TObject); 
begin 
  if AutoScroll.Checked then 
    SpeakList.StickText:=stBottom 
  else 
    SpeakList.StickText:=stNone; 
  SpeakText.SetFocus; 
end; 
 
end.