RealMessengerUnit.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:101k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit RealMessengerUnit;
  2. interface
  3. uses
  4.   Classes,ComCtrls,Messages, Gauges,StdCtrls,StrUtils, ExtCtrls, SysUtils, Controls,Contnrs,
  5.   Windows, Registry,Graphics, Math, Forms,Global,Dialogs,MSHtml,md5,UrlMon,ChatingFrm,MMSystem,WinSock,
  6.   MMregs,MMUtils,VFW,JPeg,ShlObj,ShDocVw,WNDES,NB30,VideoConsts,ShellAPI,XMLDoc,Color,MySocket,bsSkinCtrls;
  7. type
  8.   TTransmitFileCategory = (tfSend,tfGet);
  9.   TTransmitFile = class
  10.     public
  11.       FileName,
  12.       SaveFileName      :String;
  13.       FileSize          :Int64;
  14.       FileHashCode      :String;
  15.       FileStream        :TFileStream;
  16.       SenderID          :Integer;
  17.       SenderName        :String;
  18.       ReceiverID        :Integer;
  19.       ReceiverName      :String;
  20.       Category          :TTransmitFileCategory;
  21.       IsAccepted,                      
  22.       IsComleted        :Boolean;      
  23.       CurentSize        :Int64;        
  24.       Errors            :Integer;
  25.       StartTime         :Cardinal;     
  26.       OldUsedTime       :Cardinal;     
  27.       UsedTime          :Cardinal;     
  28.       ChatingForm       :TChatingForm; 
  29.       ImageID,
  30.       PercentID,                       
  31.       CompletedID,                     
  32.       UndoneID,                        
  33.       ActionID          :String;       
  34.       BaseID            :String;       
  35.       Employee          :PEmployee;    
  36.       IsScreen          :Boolean;      
  37.       SendFileThread    :TThread;      
  38.       FileTable         :TList;        
  39.       Speed             :Integer;      
  40.       ResumedSize       :Integer;
  41.       OnMovingFile      :Boolean;
  42.       MySocket          :TMySocket;
  43.       SleepValue        :Real;
  44.       LastGetOrResultTicket:Cardinal;
  45.       Constructor Create(vCategory   :TTransmitFileCategory;
  46.                        vSenderID     :Integer;
  47.                        vSenderName   :String;
  48.                        vReceiverID   :Integer;
  49.                        vReceiverName :String;
  50.                        vFileName     :String;
  51.                        vChatingForm  :TChatingForm;
  52.                        ReceiverLocalIP:String;
  53.                        ReceiverLocalPort:Integer;
  54.                        ReceiverIP:String;
  55.                        ReceiverPort:Integer;
  56.                        vFileSize     :Int64=0;
  57.                        vFileHashCode :String='';
  58.                        vBaseID       :String='';
  59.                        vIsScreen     :Boolean=False
  60.                        );
  61.       Destructor Destroy();Override;
  62.       procedure CreateHTML();
  63.       procedure Cancel();
  64.       procedure Error();
  65.       procedure Decline();
  66.       procedure Accept();
  67.       procedure Stop(StopID:Integer);
  68.       procedure Send(AcceptedSize:Int64);
  69.       procedure Get(SendTicket:Int64);
  70.       procedure ShowProgress();
  71.       procedure ShowComplete();
  72.       procedure Close();
  73.       procedure Logout();
  74.   end;
  75.   TSendFile = class(TThread)      
  76.     private
  77.       procedure CopyFileTable;    
  78.       procedure ShowCompleted;    
  79.       procedure ShowError;        
  80.     protected
  81.       procedure Execute; override;
  82.     public
  83.       ReceiverID:Integer;         
  84.       BaseID:String;              
  85.       FileStream:TFileStream;     
  86.       FileTable:TList;            
  87.       TransmitFile:TTransmitFile;
  88.       constructor Create(vReceiverID:Integer;vBaseID:String;vFileStream:TFileStream;vTransmitFile:TTransmitFile);
  89.       destructor Destroy;override;
  90.   end;
  91.   TMoveFile = class(TThread)
  92.     private
  93.       procedure ShowCompleted;   
  94.       procedure ShowMoving;
  95.     protected
  96.       procedure Execute; override;
  97.     public
  98.       TransmitFile:TTransmitFile;
  99.       constructor Create(vTransmitFile:TTransmitFile);
  100.   end;
  101.   TSendVideo = class(TThread)
  102.     private
  103.       KeyFrame: Boolean;
  104.       SendBuffer:Array[1..2048]of char;
  105.       procedure SendVideoBuffer;
  106.     protected
  107.       procedure Execute; override;
  108.     public
  109.   end;
  110.   PFileTableUnit = ^TFileTableUnit;
  111.   TFileTableUnit = record
  112.     IsAccepted:char;
  113.   end;
  114.   TAudioHandShakeCategory = (ahRequest,ahResponse);
  115.   TAudioHandShake = class
  116.     public
  117.       Category    :TAudioHandShakeCategory;
  118.       ID          :Integer;      
  119.       Name        :String;       
  120.       ChatingForm :TChatingForm;
  121.       ImageID,
  122.       ActionID,
  123.       BaseID      :String;
  124.       IsAccepted  :Boolean;
  125.       MySocket    :TMySocket;
  126.       LastGetTicket:Cardinal;
  127.       Constructor Create(vCategory:TAudioHandShakeCategory;
  128.                          vID:Integer;
  129.                          vName:String;
  130.                          vChatingForm:TChatingForm;
  131.                          ReceiverLocalIP:String;
  132.                          ReceiverLocalPort:Integer;
  133.                          ReceiverIP:String;
  134.                          ReceiverPort:Integer
  135.                          );
  136.       Destructor Destroy();Override;
  137.       procedure CreateHTML();
  138.       procedure Cancel();
  139.       procedure Decline();
  140.       procedure Accept();
  141.       procedure Stop(StopID:Integer);
  142.       procedure Close();
  143.       procedure Logout();
  144.   end;
  145.   TVideoHandShakeCategory = (vhRequest,vhResponse);
  146.   TVideoHandShake = class
  147.     public
  148.       Category    :TVideoHandShakeCategory;
  149.       ID          :Integer;      
  150.       Name        :String;       
  151.       ChatingForm :TChatingForm;
  152.       ImageID,
  153.       ActionID,
  154.       BaseID      :String;
  155.       IsAccepted  :Boolean;
  156.       VideoData   :TVideoDataInfo;
  157.       GetedData   :Int64;
  158.       GetedFrame  :Int64;
  159.       StartTicket :Int64;
  160.       PDC         :HDC;
  161.       SendVideo   :TSendVideo;
  162.       AMySocket   :TMySocket;
  163.       VMySocket   :TMySocket;
  164.       ALastGetTicket:Cardinal;
  165.       VLastGetTicket:Cardinal;
  166.       Constructor Create(vCategory:TVideoHandShakeCategory;
  167.                          vID:Integer;
  168.                          vName:String;
  169.                          vChatingForm:TChatingForm;
  170.                          AReceiverLocalIP:String;
  171.                          AReceiverLocalPort:Integer;
  172.                          AReceiverIP:String;
  173.                          AReceiverPort:Integer;
  174.                          VReceiverLocalIP:String;
  175.                          VReceiverLocalPort:Integer;
  176.                          VReceiverIP:String;
  177.                          VReceiverPort:Integer
  178.                          );
  179.       Destructor Destroy();Override;
  180.       procedure CreateHTML();
  181.       procedure Cancel();
  182.       procedure Decline();
  183.       procedure Accept();
  184.       procedure Stop(StopID:Integer);
  185.       procedure Close();
  186.       procedure Logout();
  187.   end;
  188.   PReceivedMsgID = ^TReceivedMsgID;
  189.   TReceivedMsgID = record
  190.     Sender,
  191.     SendTicket:Cardinal;
  192.   end;
  193.   TProxyCategory = (pcNone,pcSocks4,pcSocks4A,pcSocks5,pcHTTP);
  194.   TZoomAction = (zaMinimize, zaMaximize);
  195.   procedure ZoomEffect(theForm: TForm; theOperation: TZoomAction);
  196.   function  OpenChatingForm(Room:ChatRoom;OpenNew:Boolean = True):TChatingForm;
  197.   function  FindEmployeeByID(ID:Integer):PEmployee;
  198.   function  FilterHTMLCode(HTML:String):String;
  199.   function  FindTransmitFileByBaseID(BaseID:String):TTransmitFile;
  200.   function  FindAudioHandShakeByBaseID(BaseID:String):TAudioHandShake;
  201.   function  FindAudioHandShakeByID(ID:Integer):TAudioHandShake;
  202.   function  FindVideoHandShakeByBaseID(BaseID:String):TVideoHandShake;
  203.   function  FindVideoHandShakeByID(ID:Integer):TVideoHandShake;
  204.   procedure PlayEventSound(FileName:string);
  205.   procedure FocusForm(form:TForm);
  206.   function  GetHostIP(HostName: String): String;
  207.   function  ACMBuildWaveHeader:PGSM610WaveFormat;
  208.   function  GetSpecialFolderDir(const folderid:integer):string;
  209.   procedure SaveHistory(CBMessage:TCBMessage);
  210.   procedure InsertHTML(ChatingForm:TChatingForm;IE:TWebbrowser;HTML:String);
  211.   procedure ShowMsg(ChatingForm:TChatingForm;IE:TWebbrowser;SenderName:String;CBMessage:TCBMessage;Save:Boolean=True);
  212.   function jfForceForeGroundWindow(hwnd: THandle): boolean;
  213.   function GetNetBIOSAddress: string;
  214.   function HostToIP(Name: string; var Ip: string): Boolean;
  215.   procedure ChangeAllColor(CustColor:TColor);
  216.   procedure ChangeChatingFormColor(ChatingForm:TChatingForm;CustColor:TColor);
  217.   procedure FillBitmapStruc;
  218.   procedure CompareFrame(lpVHdr: PVIDEOHDR);
  219.   procedure InitCompressor;
  220.   procedure UnInitCompressor;
  221. var
  222.   A_FCV: TCOMPVARS;
  223.   A_FInInfo: TBitmapInfo;
  224.   A_FOutInfo: TBitmapInfo;
  225.   FCV: TCOMPVARS;
  226.   FInInfo: TBitmapInfo;
  227.   FOutInfo: TBitmapInfo;
  228.   FCaptureHandle: THandle;
  229.   FSampleNum: DWORD;
  230.   FOutActSize: DWORD;
  231.   FOutFormatSize: DWORD;
  232.   FOutBufferSize: DWORD;
  233.   
  234.   FOutBuf: PByte;
  235.   FOutBufSize: DWORD;
  236.   A_FOutFormatSize: DWORD;
  237.   AudioLastRestartTime:Cardinal;
  238.   
  239.   OnlineNode,
  240.   OfflineNode       :TTreeNode;
  241.   ThreadHandle      :THandle;
  242.   wfx               :TWaveFormatEx;
  243.   LastReturnHartTick:Cardinal;
  244.   OldMousePoint,
  245.   OldCursorPoint    :TPoint;
  246.   Snoop             :Int64;
  247.   IsAutoState       :Boolean;
  248.   DESKEY            :String='NewRealMessenger';
  249.   MsgAlertQueue     :TList;                
  250.   MySockets,
  251.   ReceivedMessages,                        
  252.   MsgReturnCheck,                          
  253.   Branchs,                                 
  254.   Employees,                               
  255.   TransmitFiles,                           
  256.   AudioHandShakes,                         
  257.   VideoHandShakes,                         
  258.   lpVHdrs            :Classes.TThreadList; 
  259.   Me                 :PEmployee;           
  260.   LoginName          :String='';           
  261.   Password           :String='';           
  262.   LoginState         :String='联机';
  263.   HostName           :String='';
  264.   HostIP             :String='';           
  265.   ServerPort         :Integer=0;           
  266.   MsgSound           :String='Type.wav';   
  267.   DontPlaySound      :Boolean=False;       
  268.   AutoConnectInterval:Integer=180;         
  269.   DontAutoConnect    :Boolean=False;       
  270.   ProxyCategory      :TProxyCategory;
  271.   ProxyAddress       :String='';
  272.   ProxyPort          :Integer=0;           
  273.   ProxyUsername      :string='';           
  274.   ProxyPassword      :string='';
  275.   AppKey            :String='Softwareimp2p.Netim';
  276.   StartColor        :TColor = clWhite;     
  277.   EndColor          :TColor = 13816530;{12307877;}
  278.   DefaultColor      :TColor = 13816530;{12307877;}
  279.   SysTextColor      :String = '#545454';   
  280.   CssColor          :String='ButtonFace';  
  281.   MACNO             :String;               
  282.   ResPath,                                 
  283.   MyDocumentPath,                          
  284.   ApplicationPath,                         
  285.   CachePath,                               
  286.   HistoryPath,                             
  287.   SoundPath,                               
  288.   PicPath           :String;               
  289.   ActiveChatingForm :TChatingForm;
  290.   AudioReceiverID   :Integer=0;            
  291.   AudioMySocket     :TMySocket;            
  292.   VideoReceiverID   :Integer=0;            
  293.   VideoMySocket     :TMySocket;            
  294.   HaveAudioDevice,                         
  295.   HaveVideoDevice   :Boolean;              
  296.   pwfx              :PGSM610WaveFormat;    
  297.   ImgListMain       :TImageList;           
  298.   TVMain            :TBSSkinTreeView;      
  299.   ChatingFormList   :TList;                
  300.   performancefrequency_s :Int64;           
  301.   performancefrequency_ms:Single;
  302. implementation
  303. uses
  304.   SelFaceFrm,MsgFrm,ZLib,RealMessengerImpl,VideoFrm;
  305. {------------------------------------------------------------------------------}
  306. procedure TSendVideo.SendVideoBuffer;
  307. begin
  308.     VideoMySocket.SendBuffer(SendBuffer,SizeOf(TCBVideo)+1);
  309. end;
  310. {------------------------------------------------------------------------------}
  311. procedure TSendVideo.Execute;
  312. var
  313.   Buffer: PByte;
  314.   iLoop:Integer;
  315.   CBVideo:TCBVideo;
  316.   Position:Integer;
  317.   AllBuffer:Array[0..8180]of char;
  318.   lpVHdr: PVIDEOHDR;
  319. begin
  320.   FreeOnTerminate:=True;
  321.   while not Terminated do
  322.   begin
  323.     with lpVHdrs.LockList do
  324.     try
  325.       if Count>1 then
  326.       begin
  327.         lpVHdr:=Items[0];
  328.         Remove(lpVHdr);
  329.       end
  330.       else
  331.       begin
  332.         sleep(10);
  333.         continue;
  334.       end;
  335.     finally
  336.       lpVHdrs.UnlockList;
  337.     end;
  338.     
  339.     FOutActSize := FInInfo.bmiHeader.biSizeImage;
  340.     try
  341.       Application.ProcessMessages;
  342.       Buffer := ICSeqCompressFrame(@FCV, 0, lpVHdr^.lpData, @KeyFrame, @FOutActSize);
  343.     except
  344.       continue;
  345.     end;
  346.     if FOutActSize < 8180 then
  347.     begin
  348.       FillChar(CBVideo, SizeOf(TCBVideo), 0);
  349.       CBVideo.Sender:=Me.ID;
  350.       CBVideo.Receiver:=VideoReceiverID;
  351.       CBVideo.bKeyFrame := KeyFrame;
  352.       CBVideo.nSampleNum := FSampleNum;
  353.       CBVideo.nAllSize := FOutActSize;
  354.       FillChar(AllBuffer, SizeOf(AllBuffer), 0);
  355.       Move(Buffer^,AllBuffer,FOutActSize);
  356.       if FOutActSize mod SizeOf(CBVideo.Buf) = 0 then
  357.         CBVideo.PackCount:=FOutActSize div SizeOf(CBVideo.Buf)
  358.       else
  359.         CBVideo.PackCount:=FOutActSize div SizeOf(CBVideo.Buf)+1;
  360.       Position:=0;
  361.       for iLoop:=1 to CBVideo.PackCount do
  362.       begin
  363.         CBVideo.PackNO:=iLoop;
  364.         if FOutActSize - Position >= SizeOf(CBVideo.Buf) then
  365.         begin
  366.           CBVideo.bufLength:=SizeOf(CBVideo.Buf);
  367.           CopyMemory(@CBVideo.Buf[1],@AllBuffer[Position],SizeOf(CBVideo.Buf));
  368.         end
  369.         else
  370.         begin
  371.           CBVideo.bufLength:=FOutActSize - Position;
  372.           CopyMemory(@CBVideo.Buf[1],@AllBuffer[Position],FOutActSize - Position);
  373.         end;
  374.         Position:=Position+CBVideo.bufLength;
  375.         SendBuffer[1]:=skVideo;
  376.         CopyMemory(@SendBuffer[2],@CBVideo,SizeOf(CBVideo));
  377.         //Synchronize(SendVideoBuffer);
  378.         SendVideoBuffer;
  379.         Sleep(50);
  380.       end;
  381.       Inc(FSampleNum);
  382.     end;
  383.   end;//while
  384. end;
  385. procedure TSendFile.Execute;
  386. var
  387.   CBSendFilePackage:TCBSendFilePackage;
  388.   SendFileCompleted:TCBSendFileCompleted;
  389.   Buffer:Array[1..2048]of char;
  390.   AllIsSended:Boolean;
  391.   iLoop:Integer;
  392.   FileTableUnit:PFileTableUnit;
  393.   SendCount:Integer;
  394.   LastSpeed:Integer;
  395. Context: MD5Context;
  396.   performancecounter,performancecounter1,performancecounter2:Int64;
  397. begin
  398.   FreeOnTerminate:=True;
  399.   AllIsSended:=False;
  400.   SendCount:=0;
  401.   while (not AllIsSended) do
  402.   begin
  403.     if Terminated then exit;
  404.     if SendCount>20 then
  405.     begin
  406.       Synchronize(ShowError);
  407.       exit;
  408.     end;
  409.     AllIsSended:=True;
  410.     
  411.     Synchronize(CopyFileTable);
  412.     
  413.     with FileTable do
  414.     for iLoop:=0 to Count-1 do
  415.     begin
  416.       try
  417.         if Terminated then exit;
  418.         FileTableUnit:=Items[iLoop];
  419.         if FileTableUnit.IsAccepted='0' then
  420.         begin
  421.           AllIsSended:=False;
  422.           FileStream.Position:=iLoop*FilePackSize;
  423.           CBSendFilePackage.Position:=FileStream.Position;
  424.           if FileStream.Size - FileStream.Position  > FilePackSize then
  425.           begin
  426.             FileStream.Read(CBSendFilePackage.Package,FilePackSize);
  427.             CBSendFilePackage.Length:=FilePackSize;
  428.           end
  429.           else
  430.           begin
  431.             FileStream.Read(CBSendFilePackage.Package,FileStream.Size - CBSendFilePackage.Position);
  432.             CBSendFilePackage.Length:=FileStream.Size - CBSendFilePackage.Position;
  433.           end;
  434.           CBSendFilePackage.Receiver:=ReceiverID;
  435.           CBSendFilePackage.BaseID:=BaseID;
  436.         MD5Init(Context);
  437.         MD5Update(Context, PChar(@CBSendFilePackage.Package[1]), CBSendFilePackage.Length);
  438.         MD5Final(Context, CBSendFilePackage.MD5CODE);
  439.           queryperformancecounter(performancecounter);
  440.           CBSendFilePackage.SendTicket:=performancecounter;
  441.           Buffer[1]:=skSendFilePackage;
  442.           CopyMemory(@Buffer[2],@CBSendFilePackage,SizeOf(CBSendFilePackage));
  443.           TransmitFile.MySocket.SendBuffer(Buffer,SizeOf(CBSendFilePackage)+1);
  444.           if TransmitFile.SleepValue>0 then
  445.           begin
  446.             queryperformancecounter(performancecounter1);
  447.             repeat
  448.               if TransmitFile.SleepValue>performancefrequency_ms*2 then Sleep(1);
  449.               queryperformancecounter(performancecounter2);
  450.             until performancecounter2-performancecounter1>=TransmitFile.SleepValue;
  451.           end;
  452.         end;
  453.       except
  454.       end;
  455.     end;
  456.   end;
  457.   Synchronize(ShowCompleted);
  458. end;
  459. procedure TSendFile.CopyFileTable;
  460. var
  461.   iLoop:Integer;
  462.   FileTableUnit:PFileTableUnit;
  463. begin
  464.   for iLoop:=0 to FileTable.Count-1 do
  465.   begin
  466.     FileTableUnit:=FileTable.Items[iLoop];
  467.     FreeMem(FileTableUnit,SizeOf(TFileTableUnit));
  468.   end;
  469.   FileTable.Clear;
  470.   for iLoop:=0 to TransmitFile.FileTable.Count-1 do
  471.   begin
  472.     GetMem(FileTableUnit,SizeOf(TFileTableUnit));
  473.     FileTableUnit.IsAccepted:=PFileTableUnit(TransmitFile.FileTable.Items[iLoop]).IsAccepted;
  474.     FileTable.Add(FileTableUnit);
  475.   end;
  476. end;
  477. procedure TSendFile.ShowError;
  478. begin
  479.   TransmitFile.Error;
  480. end;
  481. procedure TSendFile.ShowCompleted;
  482. begin
  483.   TransmitFile.ShowComplete;
  484. end;
  485. destructor TSendFile.Destroy;
  486. var
  487.   iLoop:Integer;
  488.   FileTableUnit:PFileTableUnit;
  489. begin
  490.   inherited Destroy;
  491.   for iLoop:=0 to FileTable.Count-1 do
  492.   begin
  493.     FileTableUnit:=FileTable.Items[iLoop];
  494.     FreeMem(FileTableUnit,SizeOf(TFileTableUnit));
  495.   end;
  496.   FileTable.Clear;
  497.   FileTable.Free;
  498. end;
  499. constructor TSendFile.Create(vReceiverID:Integer;vBaseID:String;vFileStream:TFileStream;vTransmitFile:TTransmitFile);
  500. begin
  501.   inherited Create(True);
  502.   ReceiverID:=vReceiverID;
  503.   BaseID:=vBaseID;
  504.   FileStream:=vFileStream;
  505.   FileStream.Position:=0;
  506.   FileTable:=TList.Create;
  507.   TransmitFile:=vTransmitFile;
  508.   Resume;
  509. end;
  510. {------------------------------------------------------------------------------}
  511. constructor TMoveFile.Create(vTransmitFile:TTransmitFile);
  512. begin
  513.   inherited Create(True);
  514.   FreeOnTerminate:=True;
  515.   TransmitFile:=vTransmitFile;
  516.   if TransmitFile.OnMovingFile then
  517.   begin
  518.     Terminate;
  519.     Exit;
  520.   end;
  521.   TransmitFile.OnMovingFile:=True;
  522.   Resume;
  523. end;
  524. {------------------------------------------------------------------------------}
  525. procedure TMoveFile.ShowMoving;
  526. var
  527.   E:IHTMLElement;
  528. begin
  529.   with TransmitFile do
  530.   begin
  531.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(CompletedID,0) as IHTMLElement;
  532.     E.style.width:='100%';
  533.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(UndoneID,0) as IHTMLElement;
  534.     E.style.width:='0%';
  535.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  536.     E.innerHTML:='传输完毕(正在移动文件...)';
  537.   end;
  538. end;
  539. {------------------------------------------------------------------------------}
  540. procedure TMoveFile.Execute;
  541. var
  542.   Buffer:Array[1..FilePackSize] of char;
  543.   BufferSize:Integer;
  544.   iLoop:Integer;
  545.   SaveFileStream:TFileStream;
  546. begin
  547.     with TransmitFile do
  548.     if Category = tfGet then
  549.     begin
  550.       try
  551.         if not IsScreen then
  552.         begin
  553.           Synchronize(ShowMoving);
  554.           FileStream.Position:=FileTable.Count;
  555.         end
  556.         else
  557.           FileStream.Position:=0;
  558.         try
  559.           SaveFileStream:=TFileStream.Create(SaveFileName,fmCreate or fmShareDenyWrite);
  560.           for iLoop:=0 to FileTable.Count-1 do
  561.           begin
  562.             if FileStream.Size-FileStream.Position>SizeOf(Buffer) then
  563.               BufferSize:=SizeOf(Buffer)
  564.             else
  565.               BufferSize:=FileStream.Size-FileStream.Position;
  566.               
  567.             FileStream.Read(Buffer,BufferSize);
  568.             SaveFileStream.Write(Buffer,BufferSize);
  569.           end;
  570.         finally
  571.           SaveFileStream.Free;
  572.           SaveFileStream:=nil;
  573.           FileStream.Free;
  574.           FileStream:=nil;
  575.         end;
  576.         try
  577.           DeleteFile(PChar(CachePath+''+FileHashCode));
  578.         except
  579.         end;
  580.       except
  581.         on E: Exception do
  582.         begin
  583.           MessageBox(ChatingForm.handle,PChar(E.message),'错误',MB_ICONERROR);
  584.           exit;
  585.         end;
  586.       end;
  587.     end;
  588.     Synchronize(ShowCompleted);
  589. end;
  590. {------------------------------------------------------------------------------}
  591. procedure TMoveFile.ShowCompleted;
  592. begin
  593.   TransmitFile.ShowComplete;
  594. end;
  595. {------------------------------------------------------------------------------}
  596. procedure UnInitCompressor;
  597. begin
  598.   if FCV.hic <> 0 then
  599.   begin
  600.     ICSeqCompressFrameEnd(@FCV);
  601.     ICCompressorFree(@FCV);
  602.     ICClose(FCV.hic);
  603.   end;
  604. end;
  605.   
  606. {------------------------------------------------------------------------------}
  607. procedure FillBitmapStruc;
  608. begin
  609.   FillChar(FInInfo.bmiHeader, SizeOf(TBitmapInfoHeader), 0);
  610.   with FInInfo.bmiHeader do
  611.   begin
  612.     biBitCount := 24;
  613.     biCompression := BI_RGB;
  614.     biHeight := 120;
  615.     biPlanes := 1;
  616.     biSize := SizeOf(TBitmapInfoHeader);
  617.     biWidth := 160;
  618.   end;
  619. end;
  620. {------------------------------------------------------------------------------}
  621. procedure CompareFrame(lpVHdr: PVIDEOHDR);
  622. begin
  623.   lpVHdrs.Add(lpVHdr);
  624.   Application.ProcessMessages;
  625. end;
  626. {------------------------------------------------------------------------------}
  627. procedure InitCompressor;
  628. begin
  629.   FillChar(FCV, SizeOf(FCV), 0);
  630.   with FCV do
  631.   begin
  632.     dwFlags := ICMF_COMPVARS_VALID;
  633.     cbSize := SizeOf(FCV);
  634.     fccHandler := mmioFOURCC('d','i','v','4');
  635.     fccType := ICTYPE_VIDEO;
  636.     hic := ICOpen(ICTYPE_VIDEO, mmioFOURCC('d','i','v','4'), ICMODE_COMPRESS);
  637.     if hic=0 then
  638.     begin
  639.       fccHandler := mmioFOURCC('d','i','v','3');
  640.       fccType := ICTYPE_VIDEO;
  641.       hic := ICOpen(ICTYPE_VIDEO, mmioFOURCC('d','i','v','3'), ICMODE_COMPRESS);
  642.     end;
  643.     lDataRate := 780;
  644.     lKey := 15;
  645.     lQ := ICQUALITY_HIGH;
  646.     if hic <> 0 then
  647.     begin
  648.       FOutFormatSize := ICCompressGetFormatSize(hic, @FInInfo);
  649.       FillChar(FOutInfo, SizeOf(FOutInfo), 0);
  650.       ICCompressGetFormat(hic, @FInInfo, @FOutInfo);
  651.       FOutBufferSize := ICCompressGetSize(hic, @FInInfo, @FOutInfo);
  652.       ICSeqCompressFrameStart(@FCV, @FInInfo);
  653.     end
  654.     else
  655.     begin
  656.       MessageBox(RealMessengerX.handle,'点击 [确定] 开始安装MPEG4解码器','MPEG4',MB_ICONINFORMATION);
  657.       ShellExecute(RealMessengerX.handle, 'open', PChar(ApplicationPath+'INSTMPG4.EXE'), nil, nil, SW_SHOWNORMAL);
  658.     end;
  659.   end;
  660. end;
  661. {------------------------------------------------------------------------------}
  662. function  FindEmployeeByID(ID:Integer):PEmployee;
  663. var
  664.   iLoop:Integer;
  665.   PEmployeeData:PEmployee;
  666. begin
  667.   Result:=nil;
  668.   with Employees.LockList do
  669.   try
  670.     for iLoop:=0 to Count-1 do
  671.     begin
  672.       PEmployeeData:=Items[iLoop];
  673.       if PEmployeeData.ID = ID then
  674.       begin
  675.         Result:=PEmployeeData;
  676.         Exit;
  677.       end;
  678.     end;
  679.   finally
  680.     Employees.UnlockList;
  681.   end;
  682. end;
  683. {------------------------------------------------------------------------------}
  684. function GetNetBIOSAddress: string;
  685. var
  686.   ncb: TNCB;
  687.   status: TAdapterStatus;
  688.   lanenum: TLanaEnum;
  689.   procedure ResetAdapter(num: char);
  690.   begin
  691.     fillchar(ncb, sizeof(ncb), 0);
  692.     ncb.ncb_command := char(NCBRESET);
  693.     ncb.ncb_lana_num := num;
  694.     Netbios(@ncb);
  695.   end;
  696. var
  697.   lanNum: char;
  698.   address: record
  699.     part1: Longint;
  700.     part2: Word;                                            //Smallint;
  701.   end absolute status;
  702. begin
  703.   Result := '';
  704.   fillchar(ncb, sizeof(ncb), 0);
  705.   ncb.ncb_command := char(NCBENUM);
  706.   ncb.ncb_buffer := @lanenum;
  707.   ncb.ncb_length := sizeof(lanenum);
  708.   Netbios(@ncb);
  709.   if lanenum.length = #0 then exit;
  710.   lanNum := lanenum.lana[0];
  711.   ResetAdapter(lanNum);
  712.   fillchar(ncb, sizeof(ncb), 0);
  713.   ncb.ncb_command := char(NCBASTAT);
  714.   ncb.ncb_lana_num := lanNum;
  715.   ncb.ncb_callname[0] := '*';
  716.   ncb.ncb_buffer := @status;
  717.   ncb.ncb_length := sizeof(status);
  718.   Netbios(@ncb);
  719.   ResetAdapter(lanNum);
  720.   Result := Format('%x%x', [address.part1, address.part2]);
  721. end;
  722. {------------------------------------------------------------------------------}
  723. {窗口的动态效果}
  724. procedure ZoomEffect(theForm: TForm; theOperation: TZoomAction);
  725. var
  726.    rcStart: TRect; 
  727.    rcEnd: TRect; 
  728.    rcTray: TRect; 
  729.    hwndTray : hWnd; 
  730.    hwndChild: hWnd; 
  731. begin 
  732.      hwndTray := FindWindow('Shell_TrayWnd', nil);
  733.      hwndChild := FindWindowEx(hwndTray, 0, 'TrayNotifyWnd', nil); 
  734.      GetWindowRect(hwndChild, rcTray); 
  735.      { Check for minimize/maximize and swap start/end} 
  736.      if theOperation = zaMinimize then 
  737.         begin 
  738.              rcStart := theForm.BoundsRect; 
  739.              rcEnd := rcTray; 
  740.         end 
  741.      else 
  742.         begin 
  743.              rcEnd := theForm.BoundsRect; 
  744.              rcStart := rcTray; 
  745.         end; 
  746.      { Here the magic happens... } 
  747.      DrawAnimatedRects(theForm.Handle, IDANI_CAPTION, rcStart, rcEnd)
  748. end;  
  749. {------------------------------------------------------------------------------}
  750. procedure TVideoHandShake.Close();
  751. begin
  752.   if IsAccepted then
  753.     Stop(Me.ID)
  754.   else if Category = vhRequest then
  755.     Cancel
  756.   else
  757.     Decline;
  758. end;
  759. {------------------------------------------------------------------------------}
  760. procedure TVideoHandShake.Logout();
  761. begin
  762.   if IsAccepted then
  763.     Stop(ID)
  764.   else
  765.     Cancel;
  766. end;
  767. {------------------------------------------------------------------------------}
  768. Destructor TVideoHandShake.Destroy();
  769. begin
  770.   AMySocket.Free;
  771.   VMySocket.Free;
  772. end;
  773. {------------------------------------------------------------------------------}
  774. procedure TVideoHandShake.Stop(StopID:Integer);
  775. var
  776.   E:IHTMLElement;
  777.   HTML:String;
  778.   CBVideoStop:TCBVideoStop;
  779.   Buffer:Array[1..2048]of char;
  780. begin
  781.   try
  782.     VideoHandShakes.Remove(Self);
  783.     if VideoForm<>nil then
  784.     try
  785.       VideoForm.Close;
  786.     except
  787.     end;
  788.     if StopID <> Me.ID then
  789.     begin
  790.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesVideoClose.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 结束了视频对话。</div>';
  791.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  792.     end
  793.     else
  794.     begin
  795.       CBVideoStop.Receiver:=ID;
  796.       CBVideoStop.Sender:=Me.ID;
  797.       Buffer[1]:=skVideoStop;
  798.       CopyMemory(@Buffer[2],@CBVideoStop,SizeOf(CBVideoStop));
  799.       RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBVideoStop)+1);          {结束视频对话邀请}
  800.     end;
  801.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  802.     E.innerHTML:=E.innerText+'<font color="#990000">(已结束)</font>';
  803.     if Me.HaveVideoDevice then
  804.     begin
  805.       try
  806.         SendVideo.Terminate;
  807.       except
  808.       end;
  809.       lpVHdrs.Free;
  810.       VideoReceiverID:=0;
  811.       VideoMySocket:=nil;
  812.       ChatingForm.ImgArrow.Show;
  813.       ChatingForm.PnlMyCamera.Hide;
  814.       ChatingForm.PnlRightBottom.Show;
  815.       try
  816.         ChatingForm.VideoIsOn:=False;
  817.         ChatingForm.VideoCap.OnVideoStream:=nil;
  818.         ChatingForm.VideoCap.DriverIndex:=-1;
  819.         ChatingForm.VideoCap.VideoPreview:=False;
  820.         ChatingForm.VideoCap.StopCapture;
  821.       finally
  822.         UnInitCompressor;
  823.       end;
  824.     end;
  825.     if PEmployee(ChatingForm.TVUserList.Items.GetFirstNode.Data).HaveVideoDevice then
  826.     begin
  827.       if (ChatingForm.Width-ChatingForm.PnlLeftTop.Width>ChatingForm.PnlYourCamera.Width) then ChatingForm.PnlLeftTop.Width:=ChatingForm.PnlLeftTop.Width + ChatingForm.PnlYourCamera.Width + 3;
  828.       ChatingForm.PnlYourCamera.Hide;
  829.       if Assigned(FOutBuf) then
  830.         FreeMem(FOutBuf);
  831.       if A_FCV.hic <> 0 then
  832.       ICClose(A_FCV.hic);
  833.     end;
  834.     try
  835.       if Me.HaveAudioDevice then
  836.       begin
  837.         ChatingForm.AudioIsOn:=False;
  838.         ChatingForm.ImgSpk.Visible:=False;
  839.         ChatingForm.ImgMic.Visible:=False;
  840.         ChatingForm.ImgSpkDisabled.Visible:=False;
  841.         ChatingForm.ImgMicDisabled.Visible:=False;
  842.         ChatingForm.LblQuitAudio.Visible:=False;
  843.         ChatingForm.MMMixerSliderIn.Visible:=False;
  844.         ChatingForm.MMMixerSliderOut.Visible:=False;
  845.         AudioReceiverID:=0;
  846.         AudioMySocket:=nil;
  847.         ChatingForm.ACMWaveOut.Close;
  848.         ChatingForm.ACMWaveOut.Close;
  849.       end;
  850.     except
  851.     end;
  852.   finally
  853.     FreeAndNil(Self);
  854.   end;
  855. end;
  856. {------------------------------------------------------------------------------}
  857. procedure TVideoHandShake.Accept();
  858. var
  859.   iLoop:Integer;
  860.   E:IHTMLElement;
  861.   HTML:String;
  862.   CBVideoResponse:TCBVideoResponse;
  863.   CBSetBitmapInfo:TCBSetBitmapInfo;
  864.   CBSetCompvars:TCBSetCompvars;
  865.   Buffer:Array[1..2048]of char;
  866.   TempReg:TRegistry;
  867. begin
  868.   RealMessengerX.TestVideoDevice();
  869.   IsAccepted:=True;
  870.   ALastGetTicket:=GetTickCount;
  871.   VLastGetTicket:=GetTickCount;
  872.   RealMessengerX.TimeCheckAVError.Enabled:=True;
  873.   if Category = vhRequest then
  874.   begin
  875.     HTML:='<div style="color:#000099"><img src="'+ResPath+'ImagesVideo.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 接受了您的视频对话邀请。</div>';
  876.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  877.   end
  878.   else
  879.   begin
  880.     TempReg:=TRegistry.Create;
  881.     try
  882.       TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  883.       if not TempReg.KeyExists(AppKey+'AV') then
  884.       begin
  885.         RealMessengerX.MAVSetsClick(nil);
  886.       end;
  887.       if not TempReg.KeyExists(AppKey+'AV') then Decline;
  888.     finally
  889.       TempReg.Free;
  890.     end;
  891.     CBVideoResponse.Receiver:=ID;
  892.     CBVideoResponse.Sender:=Me.ID;
  893.     CBVideoResponse.isAcepted:=True;
  894.     CBVideoResponse.AIP       :=AMySocket.IP;
  895.     CBVideoResponse.APort     :=AMySocket.Port;
  896.     CBVideoResponse.ALocalIP  :=AMySocket.LocalIP;
  897.     CBVideoResponse.ALocalPort:=AMySocket.LocalPort;
  898.     CBVideoResponse.VIP       :=VMySocket.IP;
  899.     CBVideoResponse.VPort     :=VMySocket.Port;
  900.     CBVideoResponse.VLocalIP  :=VMySocket.LocalIP;
  901.     CBVideoResponse.VLocalPort:=VMySocket.LocalPort;
  902.     Buffer[1]:=skVideoResponse;
  903.     CopyMemory(@Buffer[2],@CBVideoResponse,SizeOf(CBVideoResponse));
  904.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBVideoResponse)+1);          {接受视频对话邀请}
  905.     Sleep(50);
  906.   end;
  907.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  908.   E.innerHTML:='正在与 '+FilterHtmlCode(Name)+' 进行视频对话... <a href="VHStop_'+BaseID+'" title="结束视频对话">结束</a> 。';
  909.   with VideoHandShakes.LockList do
  910.   try
  911.     for iLoop:=Count-1 downto 0 do
  912.       if TVideoHandShake(items[iLoop])<>Self then TVideoHandShake(items[iLoop]).Close;
  913.   finally
  914.     VideoHandShakes.UnlockList;
  915.   end;
  916.   if PEmployee(ChatingForm.TVUserList.Items.GetFirstNode.Data).HaveVideoDevice then
  917.   begin
  918.     if (ChatingForm.Width-ChatingForm.PnlLeftTop.Width<ChatingForm.PnlYourCamera.Width) then ChatingForm.PnlLeftTop.Width:=ChatingForm.PnlLeftTop.Width - ChatingForm.PnlYourCamera.Width - 3;
  919.     ChatingForm.PnlYourCamera.Show;
  920.     PDC:=GetDC(ChatingForm.AviPanelOut.Handle);
  921.     SetStretchBltMode(PDC,HALFTONE);
  922.     FOutBuf := nil;
  923.     FillChar(A_FCV, SizeOf(A_FCV), 0);
  924.     FillChar(A_FInInfo, SizeOf(A_FInInfo), 0);
  925.     FIllChar(A_FOutInfo, SizeOf(A_FOutInfo), 0);
  926.     FOutBufSize := 0;
  927.     A_FOutFormatSize := 0;
  928.   end;
  929.   if Me.HaveVideoDevice then
  930.   begin
  931.     lpVHdrs:=Classes.TThreadList.Create;
  932.     SendVideo:=TSendVideo.Create(False);
  933.     VideoReceiverID:=ID;
  934.     VideoMySocket:=VMySocket;
  935.     FSampleNum := 0;
  936.     FillBitmapStruc;
  937.     InitCompressor;
  938.     FillChar(CBSetBitmapInfo, SizeOf(CBSetBitmapInfo), 0);
  939.     CBSetBitmapInfo.Receiver:=ID;
  940.     Move(FOutInfo, CBSetBitmapInfo.Buf, SizeOf(FOutInfo));
  941.     Buffer[1]:=skSetBitmapInfo;
  942.     CopyMemory(@Buffer[2],@CBSetBitmapInfo,SizeOf(CBSetBitmapInfo));
  943.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBSetBitmapInfo)+1);
  944.     Sleep(30);
  945.     FillChar(CBSetCompvars, SizeOf(CBSetCompvars), 0);
  946.     CBSetCompvars.Receiver:=ID;
  947.     Move(FCV, CBSetCompvars.Buf, SizeOf(FCV));
  948.     Buffer[1]:=skSetCompvars;
  949.     CopyMemory(@Buffer[2],@CBSetCompvars,SizeOf(CBSetCompvars));
  950.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBSetCompvars)+1);
  951.     Sleep(30);
  952.     ChatingForm.VideoCap.OnVideoStream:=ChatingForm.VideoCapVideoStream;
  953.     TempReg:=TRegistry.Create;
  954.     try
  955.         TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  956.         if TempReg.OpenKey(AppKey+'AV',True) then
  957.         begin
  958.           if not TempReg.ValueExists('VideoDevice') then TempReg.WriteInteger('VideoDevice',0);
  959.           ChatingForm.VideoCap.DriverIndex:=TempReg.ReadInteger('VideoDevice');
  960.         end;
  961.     finally
  962.       TempReg.Free;
  963.     end;
  964.     try
  965.       ChatingForm.VideoCap.VideoPreview := true;
  966.       ChatingForm.VideoCap.SetBitmapInfo(@FInInfo,SizeOf(BITMAPINFO));
  967.       ChatingForm.VideoCap.StartCapture;
  968.       if (not ChatingForm.PnlRightBottom.Visible) then ChatingForm.ImgArrowClick(ChatingForm.ImgArrow);
  969.       ChatingForm.ImgArrow.Hide;
  970.       ChatingForm.PnlMyCamera.Show;
  971.       ChatingForm.PnlRightBottom.Hide;
  972.     except
  973.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesVideoClose.gif'+'" align="texttop"> 打开视频捕获设备时出错。</div>';
  974.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  975.     end;
  976.   end;
  977.   try
  978.     if Me.HaveAudioDevice and (ChatingForm.AudioIsOn=False)  then
  979.     begin
  980.       AudioReceiverID:=ID;
  981.       AudioMySocket:=AMySocket;
  982.       pwfx := ACMBuildWaveHeader;
  983.       AudioLastRestartTime:=GetTickCount;
  984.       TempReg:=TRegistry.Create;
  985.       try
  986.         TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  987.         if TempReg.OpenKey(AppKey+'AV',True) then
  988.         begin
  989.           if not TempReg.ValueExists('MicDevice') then TempReg.WriteInteger('MicDevice',0);
  990.           if not TempReg.ValueExists('SpeakerDevice') then TempReg.WriteInteger('SpeakerDevice',0);
  991.           ChatingForm.MMMixerDevice1.DeviceID:=TempReg.ReadInteger('MicDevice');
  992.           ChatingForm.MMMixerDevice2.DeviceID:=TempReg.ReadInteger('SpeakerDevice');
  993.         end;
  994.       finally
  995.         TempReg.Free;
  996.       end;
  997.       ChatingForm.ImgSpk.Visible:=True;
  998.       ChatingForm.ImgMic.Visible:=True;
  999.       ChatingForm.LblQuitAudio.Visible:=True;
  1000.       ChatingForm.MMMixerSliderIn.Visible:=True;
  1001.       ChatingForm.MMMixerSliderOut.Visible:=True;
  1002.       Sleep(200);
  1003.       try
  1004.         ChatingForm.ACMWaveIn.Open(PWaveFormatEx(pwfx),ChatingForm.MMMixerDevice1.DeviceID);
  1005.       except
  1006.         HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> 打开音频输入设备时出错。</div>';
  1007.         InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1008.       end;
  1009.       try
  1010.         ChatingForm.ACMWaveOut.Open(PWaveFormatEx(pwfx),ChatingForm.MMMixerDevice2.DeviceID);
  1011.       except
  1012.         HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> 打开音频输出设备时出错。</div>';
  1013.         InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1014.       end;
  1015.     end; //if
  1016.   except
  1017.   end;
  1018. end;
  1019. {------------------------------------------------------------------------------}
  1020. procedure TVideoHandShake.Decline();
  1021. var
  1022.   E:IHTMLElement;
  1023.   HTML:String;
  1024.   CBVideoResponse:TCBVideoResponse;
  1025.   Buffer:Array[1..2048]of char;
  1026. begin
  1027.   VideoHandShakes.Remove(Self);
  1028.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1029.   E.setAttribute('src',ResPath+'ImagesVideoClose.gif',0);
  1030.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1031.   if Category = vhRequest then
  1032.   begin
  1033.     E.innerHTML:=E.innerText+'<font color="#990000">(已被拒绝)</font>';
  1034.     HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesVideoClose.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 拒绝了您的视频对话邀请。</div>';
  1035.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1036.   end
  1037.   else
  1038.   begin
  1039.     CBVideoResponse.Receiver:=ID;
  1040.     CBVideoResponse.Sender:=Me.ID;
  1041.     CBVideoResponse.isAcepted:=False;
  1042.     Buffer[1]:=skVideoResponse;
  1043.     CopyMemory(@Buffer[2],@CBVideoResponse,SizeOf(CBVideoResponse));
  1044.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBVideoResponse)+1);          {拒绝视频对话邀请}
  1045.     E.innerHTML:=E.innerText+'<font color="#990000">(已拒绝)</font>';
  1046.   end;
  1047.   ChatingForm.VideoIsOn:=False;
  1048.   FreeAndNil(Self);
  1049. end;
  1050. {------------------------------------------------------------------------------}
  1051. procedure TVideoHandShake.Cancel();
  1052. var
  1053.   E:IHTMLElement;
  1054.   CBVideoCancel:TCBVideoCancel;
  1055.   Buffer:Array[1..2048]of char;
  1056. begin
  1057.   VideoHandShakes.Remove(Self);
  1058.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1059.   E.setAttribute('src',ResPath+'ImagesVideoClose.gif',0);
  1060.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1061.   E.innerHTML:=E.innerText+'<font color="#990000">(已取消)</font>';
  1062.   if Category = vhRequest then
  1063.   begin
  1064.     CBVideoCancel.Receiver:=ID;
  1065.     CBVideoCancel.Sender:=Me.ID;
  1066.     Buffer[1]:=skVideoCancel;
  1067.     CopyMemory(@Buffer[2],@CBVideoCancel,SizeOf(CBVideoCancel));
  1068.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBVideoCancel)+1);      {取消视频对话邀请}
  1069.   end;
  1070.   ChatingForm.VideoIsOn:=False;
  1071.   FreeAndNil(Self);
  1072. end;
  1073. {------------------------------------------------------------------------------}
  1074. procedure TVideoHandShake.CreateHTML();
  1075. var
  1076.   HTML:String;
  1077. begin
  1078.   HTML:='<table width="100%" style="font-size:9pt;border:1px solid #808080;background-color:#FFFFCE;padding:2px;Scolor:'+SysTextColor+';margin-top:2px;margin-bottom:5px;filter: alpha(opacity=80);"><tr><td>';
  1079.   ImageID:='Image_'+BaseID;
  1080.   HTML:=HTML+'<img id="'+ImageID+'" src="'+ResPath+'ImagesVideo.gif'+'" align="texttop"> ';
  1081.   ActionID:='Action'+BaseID;
  1082.   HTML:=HTML+'<span id="'+ActionID+'" style="color:'+SysTextColor+'">';
  1083.   if Category = vhRequest then
  1084.     HTML:=HTML+'您已邀请 '+FilterHtmlCode(Name)+' 开始视频对话,请等待回应或 <a href="VHCancel_'+BaseID+'" title="取消视频对话邀请">取消</a> 该邀请。'
  1085.   else
  1086.     HTML:=HTML+FilterHtmlCode(Name)+' 邀请您开始视频对话,您可以选择 <a href="VHAccept_'+BaseID+'" title="接受视频对话邀请">接受</a> 或 '+
  1087.                '<a href="VHdecline_'+BaseID+'" title="拒绝视频对话邀请">拒绝</a> 该邀请。';
  1088.   HTML:=HTML+'</span>';
  1089.   HTML:=HTML+'</td></tr></table>';
  1090.   InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1091. end;
  1092. {------------------------------------------------------------------------------}
  1093. Constructor TVideoHandShake.Create(vCategory:TVideoHandShakeCategory;
  1094.                    vID:Integer;
  1095.                    vName:String;
  1096.                    vChatingForm:TChatingForm;
  1097.                    AReceiverLocalIP:String;
  1098.                    AReceiverLocalPort:Integer;
  1099.                    AReceiverIP:String;
  1100.                    AReceiverPort:Integer;
  1101.                    VReceiverLocalIP:String;
  1102.                    VReceiverLocalPort:Integer;
  1103.                    VReceiverIP:String;
  1104.                    VReceiverPort:Integer
  1105.                    );
  1106. var
  1107.   iLoop:Integer;
  1108.   CBVideoRequest:TCBVideoRequest;
  1109.   Buffer:array[1..2048] of char;
  1110.   TempReg:TRegistry;
  1111.   StartTicket:Cardinal;
  1112. begin
  1113.   with VideoHandShakes.LockList do
  1114.   try
  1115.     for iLoop:=Count-1 downto 0 do
  1116.     if (TVideoHandShake(Items[iLoop]).ChatingForm = vChatingForm) then
  1117.     begin
  1118.       MessageBox(vChatingForm.Handle,'当前对话窗口已经打开了网络摄像机功能!','提示',MB_ICONINFORMATION);
  1119.       exit;
  1120.     end;
  1121.   finally
  1122.     VideoHandShakes.UnlockList;
  1123.   end;
  1124.   Inherited Create();
  1125.   Category:=vCategory;
  1126.   ID:=vID;
  1127.   Name:=vName;
  1128.   ChatingForm:=vChatingForm;
  1129.   BaseID:='V'+IntToStr(ID)+'_'+IntToStr(GetTickCount);
  1130.   //-------------------------------------------------------
  1131.   AMySocket:=TMySocket.Create(ID,RealMessengerX.ClientTCP);
  1132.   AMySocket.ReceiverLocalIP:=AReceiverLocalIP;
  1133.   AMySocket.ReceiverLocalPort:=AReceiverLocalPort;
  1134.   AMySocket.ReceiverIP:=AReceiverIP;
  1135.   AMySocket.ReceiverPort:=AReceiverPort;
  1136.   StartTicket:=0;
  1137.   while StartTicket<100 do
  1138.   begin
  1139.     if (AMySocket.IP<>'') and (AMySocket.Port<>0) then break;
  1140.     Inc(StartTicket);
  1141.     Application.ProcessMessages;
  1142.     Sleep(30);
  1143.   end;
  1144.   if Category = vhResponse then AMySocket.BeginGetHole;
  1145.   VMySocket:=TMySocket.Create(ID,RealMessengerX.ClientTCP);
  1146.   VMySocket.ReceiverLocalIP:=VReceiverLocalIP;
  1147.   VMySocket.ReceiverLocalPort:=VReceiverLocalPort;
  1148.   VMySocket.ReceiverIP:=VReceiverIP;
  1149.   VMySocket.ReceiverPort:=VReceiverPort;
  1150.   StartTicket:=0;
  1151.   while StartTicket<100 do
  1152.   begin
  1153.     if (VMySocket.IP<>'') and (VMySocket.Port<>0) then break;
  1154.     Inc(StartTicket);
  1155.     Application.ProcessMessages;
  1156.     Sleep(30);
  1157.   end;
  1158.   if Category = vhResponse then VMySocket.BeginGetHole;
  1159.   //------------------------------------------------------
  1160.   if Category = vhRequest then
  1161.   begin
  1162.       TempReg:=TRegistry.Create;
  1163.       try
  1164.         TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  1165.         if not TempReg.KeyExists(AppKey+'AV') then
  1166.         begin
  1167.           RealMessengerX.MAVSetsClick(nil);
  1168.         end;
  1169.         if not TempReg.KeyExists(AppKey+'AV') then Exit;
  1170.       finally
  1171.         TempReg.Free;
  1172.       end;
  1173.       CBVideoRequest.Sender   :=Me.ID;
  1174.       CBVideoRequest.Receiver :=ID;
  1175.       CBVideoRequest.Room     :=ChatingForm.RoomInfo;
  1176.       CBVideoRequest.AIP       :=AMySocket.IP;
  1177.       CBVideoRequest.APort     :=AMySocket.Port;
  1178.       CBVideoRequest.ALocalIP  :=AMySocket.LocalIP;
  1179.       CBVideoRequest.ALocalPort:=AMySocket.LocalPort;
  1180.       CBVideoRequest.VIP       :=VMySocket.IP;
  1181.       CBVideoRequest.VPort     :=VMySocket.Port;
  1182.       CBVideoRequest.VLocalIP  :=VMySocket.LocalIP;
  1183.       CBVideoRequest.VLocalPort:=VMySocket.LocalPort;
  1184.       Buffer[1]:=skVideoRequest;
  1185.       CopyMemory(@Buffer[2],@CBVideoRequest,SizeOf(CBVideoRequest));
  1186.       RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBVideoRequest)+1);      {发送视频对话邀请}
  1187.   end;
  1188.   CreateHTML();
  1189.   ChatingForm.VideoIsOn:=True;
  1190.   VideoHandShakes.Add(Self);
  1191. end;
  1192. {------------------------------------------------------------------------------}
  1193. function ACMBuildWaveHeader:PGSM610WaveFormat;
  1194. begin
  1195.    Result := GlobalAllocMem(sizeOf(TGSM610WaveFormat));
  1196.    with Result^ do
  1197.    begin
  1198.       wfx.wFormatTag     := $31;
  1199.       wfx.nChannels      := 1;
  1200.       wfx.nSamplesPerSec := 11025;
  1201.       wfx.wBitsPerSample := 0;
  1202.       wfx.nAvgBytesPerSec:= 0;
  1203.       wfx.nBlockAlign    := 65;
  1204.       wfx.cbSize         := 2;
  1205.       wfx.nAvgBytesPerSec:= 2239;
  1206.       wSamplesPerBlock   := 320;
  1207.    end;
  1208. end;
  1209. {------------------------------------------------------------------------------}
  1210. procedure TAudioHandShake.Close();
  1211. begin
  1212.   if IsAccepted then
  1213.     Stop(Me.ID)
  1214.   else if Category = ahRequest then
  1215.     Cancel
  1216.   else
  1217.     Decline;
  1218. end;
  1219. {------------------------------------------------------------------------------}
  1220. procedure TAudioHandShake.Logout();
  1221. begin
  1222.   if IsAccepted then
  1223.     Stop(ID)
  1224.   else
  1225.     Cancel;
  1226. end;
  1227. {------------------------------------------------------------------------------}
  1228. procedure TAudioHandShake.Accept();
  1229. var
  1230.   iLoop:Integer;
  1231.   E:IHTMLElement;
  1232.   HTML:String;
  1233.   CBAudioResponse:TCBAudioResponse;
  1234.   Buffer:Array[1..2048]of char;
  1235.   TempReg:TRegistry;
  1236. begin
  1237.   ChatingForm.ShowInputing(False);
  1238.   IsAccepted:=True;
  1239.   LastGetTicket:=GetTickCount;
  1240.   RealMessengerX.TimeCheckAVError.Enabled:=True;
  1241.   if Category = ahRequest then
  1242.   begin
  1243.     HTML:='<div style="color:#000099"><img src="'+ResPath+'ImagesAudio.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 接受了您的音频对话邀请。</div>';
  1244.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1245.   end
  1246.   else
  1247.   begin
  1248.     TempReg:=TRegistry.Create;
  1249.     try
  1250.       TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  1251.       if not TempReg.KeyExists(AppKey+'AV') then
  1252.       begin
  1253.         RealMessengerX.MAVSetsClick(nil);
  1254.       end;
  1255.       if not TempReg.KeyExists(AppKey+'AV') then Decline;
  1256.     finally
  1257.       TempReg.Free;
  1258.     end;
  1259.     CBAudioResponse.Receiver:=ID;
  1260.     CBAudioResponse.Sender:=Me.ID;
  1261.     CBAudioResponse.isAcepted:=True;
  1262.     CBAudioResponse.IP:=MySocket.IP;
  1263.     CBAudioResponse.Port:=MySocket.Port;
  1264.     CBAudioResponse.LocalIP:=MySocket.LocalIP;
  1265.     CBAudioResponse.LocalPort:=MySocket.LocalPort;
  1266.     
  1267.     Buffer[1]:=skAudioResponse;
  1268.     CopyMemory(@Buffer[2],@CBAudioResponse,SizeOf(CBAudioResponse));
  1269.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBAudioResponse)+1); {接受语音对话邀请}
  1270.   end;
  1271.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1272.   E.innerHTML:='正在与 '+FilterHtmlCode(Name)+' 进行音频对话... <a href="AHStop_'+BaseID+'" title="结束音频对话">结束</a> 。';
  1273.   with AudioHandShakes.LockList do
  1274.   try
  1275.     for iLoop:=Count-1 downto 0 do
  1276.       if TAudioHandShake(items[iLoop])<>Self then TAudioHandShake(items[iLoop]).Close;
  1277.   finally
  1278.     AudioHandShakes.UnlockList;
  1279.   end;
  1280.   AudioReceiverID:=ID;
  1281.   AudioMySocket:=MySocket;
  1282.   
  1283.   pwfx := ACMBuildWaveHeader;
  1284.   AudioLastRestartTime:=GetTickCount;
  1285.   TempReg:=TRegistry.Create;
  1286.   try
  1287.     TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  1288.     if TempReg.OpenKey(AppKey+'AV',True) then
  1289.     begin
  1290.       if not TempReg.ValueExists('MicDevice') then TempReg.WriteInteger('MicDevice',0);
  1291.       if not TempReg.ValueExists('SpeakerDevice') then TempReg.WriteInteger('SpeakerDevice',0);
  1292.       ChatingForm.MMMixerDevice1.DeviceID:=TempReg.ReadInteger('MicDevice');
  1293.       ChatingForm.MMMixerDevice2.DeviceID:=TempReg.ReadInteger('SpeakerDevice');
  1294.     end;
  1295.   finally
  1296.     TempReg.Free;
  1297.   end;
  1298.   ChatingForm.ImgSpk.Visible:=True;
  1299.   ChatingForm.ImgMic.Visible:=True;
  1300.   ChatingForm.LblQuitAudio.Visible:=True;
  1301.   ChatingForm.MMMixerSliderIn.Visible:=True;
  1302.   ChatingForm.MMMixerSliderOut.Visible:=True;
  1303.   Sleep(200);
  1304.   try
  1305.     ChatingForm.ACMWaveIn.Open(PWaveFormatEx(pwfx),ChatingForm.MMMixerDevice1.DeviceID);
  1306.   except
  1307.     HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> 打开音频输入设备时出错。</div>';
  1308.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1309.   end;
  1310.   
  1311.   try
  1312.     ChatingForm.ACMWaveOut.Open(PWaveFormatEx(pwfx),ChatingForm.MMMixerDevice2.DeviceID);
  1313.   except
  1314.     HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> 打开音频输出设备时出错。</div>';
  1315.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1316.   end;
  1317. end;
  1318. {------------------------------------------------------------------------------}
  1319. procedure TAudioHandShake.Stop(StopID:Integer);
  1320. var
  1321.   E:IHTMLElement;
  1322.   HTML:String;
  1323.   CBAudioStop:TCBAudioStop;
  1324.   Buffer:Array[1..2048]of char;
  1325. begin
  1326.   try
  1327.     AudioHandShakes.Remove(Self);
  1328.     if StopID <> Me.ID then
  1329.     begin
  1330.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 结束了音频对话。</div>';
  1331.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1332.     end
  1333.     else
  1334.     begin
  1335.       CBAudioStop.Receiver:=ID;
  1336.       CBAudioStop.Sender:=Me.ID;
  1337.       Buffer[1]:=skAudioStop;
  1338.       CopyMemory(@Buffer[2],@CBAudioStop,SizeOf(CBAudioStop));
  1339.       RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBAudioStop)+1);
  1340.     end;
  1341.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1342.     E.innerHTML:=E.innerText+'<font color="#990000">(已结束)</font>';
  1343.     ChatingForm.AudioIsOn:=False;
  1344.     ChatingForm.ImgSpk.Visible:=False;
  1345.     ChatingForm.ImgMic.Visible:=False;
  1346.     ChatingForm.ImgSpkDisabled.Visible:=False;
  1347.     ChatingForm.ImgMicDisabled.Visible:=False;
  1348.     ChatingForm.LblQuitAudio.Visible:=False;
  1349.     ChatingForm.MMMixerSliderIn.Visible:=False;
  1350.     ChatingForm.MMMixerSliderOut.Visible:=False;
  1351.     AudioReceiverID:=0;
  1352.     AudioMySocket:=nil;
  1353.     ChatingForm.ACMWaveIn.Close;
  1354.     ChatingForm.ACMWaveOut.Close;
  1355.   finally
  1356.       FreeAndNil(Self);
  1357.   end;
  1358. end;
  1359. {------------------------------------------------------------------------------}
  1360. procedure TAudioHandShake.Decline();
  1361. var
  1362.   E:IHTMLElement;
  1363.   HTML:String;
  1364.   CBAudioResponse:TCBAudioResponse;
  1365.   Buffer:Array[1..2048]of char;
  1366. begin
  1367.   AudioHandShakes.Remove(Self);
  1368.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1369.   E.setAttribute('src',ResPath+'ImagesAudioClose.gif',0);
  1370.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1371.   if Category = ahRequest then
  1372.   begin
  1373.     E.innerHTML:=E.innerText+'<font color="#990000">(已被拒绝)</font>';
  1374.     HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesAudioClose.gif'+'" align="texttop"> '+FilterHTMLCode(Name)+' 拒绝了您的音频对话邀请。</div>';
  1375.     InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1376.   end
  1377.   else
  1378.   begin
  1379.     CBAudioResponse.Receiver:=ID;
  1380.     CBAudioResponse.Sender:=Me.ID;
  1381.     CBAudioResponse.isAcepted:=False;
  1382.         
  1383.     Buffer[1]:=skAudioResponse;
  1384.     CopyMemory(@Buffer[2],@CBAudioResponse,SizeOf(CBAudioResponse));
  1385.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBAudioResponse)+1);          {拒绝语音对话邀请}
  1386.     E.innerHTML:=E.innerText+'<font color="#990000">(已拒绝)</font>';
  1387.   end;
  1388.   
  1389.   ChatingForm.AudioIsOn:=False;
  1390.   FreeAndNil(Self);
  1391. end;
  1392. {------------------------------------------------------------------------------}
  1393. procedure TAudioHandShake.Cancel();
  1394. var
  1395.   E:IHTMLElement;
  1396.   CBAudioCancel:TCBAudioCancel;
  1397.   Buffer:Array[1..2048]of char;
  1398. begin
  1399.   AudioHandShakes.Remove(Self);
  1400.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1401.   E.setAttribute('src',ResPath+'ImagesAudioClose.gif',0);
  1402.   E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1403.   E.innerHTML:=E.innerText+'<font color="#990000">(已取消)</font>';
  1404.   if Category = ahRequest then
  1405.   begin
  1406.     CBAudioCancel.Receiver:=ID;
  1407.     CBAudioCancel.Sender:=Me.ID;
  1408.     Buffer[1]:=skAudioCancel;
  1409.     CopyMemory(@Buffer[2],@CBAudioCancel,SizeOf(CBAudioCancel));
  1410.     RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBAudioCancel)+1);      {取消语音对话邀请}
  1411.   end;
  1412.   ChatingForm.AudioIsOn:=False;
  1413.   FreeAndNil(Self);
  1414. end;
  1415. {------------------------------------------------------------------------------}
  1416. procedure TAudioHandShake.CreateHTML();
  1417. var
  1418.   HTML:String;
  1419. begin
  1420.   HTML:='<table width="100%" style="font-size:9pt;border:1px solid #808080;background-color:#FFFFCE;padding:2px;Scolor:'+SysTextColor+';margin-top:2px;margin-bottom:5px;filter: alpha(opacity=80);"><tr><td>';
  1421.   ImageID:='Image_'+BaseID;
  1422.   HTML:=HTML+'<img id="'+ImageID+'" src="'+ResPath+'ImagesAudio.gif'+'" align="texttop"> ';
  1423.   ActionID:='Action'+BaseID;
  1424.   HTML:=HTML+'<span id="'+ActionID+'" style="color:'+SysTextColor+'">';
  1425.   if Category = ahRequest then
  1426.     HTML:=HTML+'您已邀请 '+FilterHtmlCode(Name)+' 开始音频对话,请等待回应或 <a href="AHCancel_'+BaseID+'" title="取消音频对话邀请">取消</a> 该邀请。'
  1427.   else
  1428.     HTML:=HTML+FilterHtmlCode(Name)+' 邀请您开始音频对话,您可以选择 <a href="AHAccept_'+BaseID+'" title="接受音频对话邀请">接受</a> 或 '+
  1429.                '<a href="AHdecline_'+BaseID+'" title="拒绝音频对话邀请">拒绝</a> 该邀请。';
  1430.   HTML:=HTML+'</span>';
  1431.   HTML:=HTML+'</td></tr></table>';
  1432.   InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1433. end;
  1434. {------------------------------------------------------------------------------}
  1435. Destructor TAudioHandShake.Destroy();
  1436. begin
  1437.   MySocket.Free;
  1438. end;
  1439. {------------------------------------------------------------------------------}
  1440. Constructor TAudioHandShake.Create(vCategory:TAudioHandShakeCategory;
  1441.                    vID:Integer;
  1442.                    vName:String;
  1443.                    vChatingForm:TChatingForm;
  1444.                    ReceiverLocalIP:String;
  1445.                    ReceiverLocalPort:Integer;
  1446.                    ReceiverIP:String;
  1447.                    ReceiverPort:Integer
  1448.                    );
  1449. var
  1450.   iLoop:Integer;
  1451.   CBAudioRequest:TCBAudioRequest;
  1452.   Buffer:array[1..2048] of char;
  1453.   TempReg:TRegistry;
  1454.   StartTicket:Cardinal;
  1455. begin
  1456.   with AudioHandShakes.LockList do
  1457.   try
  1458.     for iLoop:=Count-1 downto 0 do
  1459.     if (TAudioHandShake(Items[iLoop]).ChatingForm = vChatingForm) then
  1460.     begin
  1461.       MessageBox(vChatingForm.Handle,'当前对话窗口已经打开了音频对话功能!','提示',MB_ICONINFORMATION);
  1462.       exit;
  1463.     end;
  1464.   finally
  1465.     AudioHandShakes.UnlockList;
  1466.   end;
  1467.   with VideoHandShakes.LockList do
  1468.   try
  1469.     for iLoop:=Count-1 downto 0 do
  1470.     if (TVideoHandShake(Items[iLoop]).ChatingForm = vChatingForm) then
  1471.     begin
  1472.       MessageBox(vChatingForm.Handle,'当前对话窗口已经打开了音频视频对话功能!','提示',MB_ICONINFORMATION);
  1473.       exit;
  1474.     end;
  1475.   finally
  1476.     VideoHandShakes.UnlockList;
  1477.   end;
  1478.   Inherited Create();
  1479.   Category:=vCategory;
  1480.   ID:=vID;
  1481.   Name:=vName;
  1482.   ChatingForm:=vChatingForm;
  1483.   BaseID:='A'+IntToStr(ID)+'_'+IntToStr(GetTickCount);
  1484.   
  1485.   MySocket:=TMySocket.Create(ID,RealMessengerX.ClientTCP);
  1486.   MySocket.ReceiverLocalIP:=ReceiverLocalIP;
  1487.   MySocket.ReceiverLocalPort:=ReceiverLocalPort;
  1488.   MySocket.ReceiverIP:=ReceiverIP;
  1489.   MySocket.ReceiverPort:=ReceiverPort;
  1490.   StartTicket:=0;
  1491.   while StartTicket<100 do
  1492.   begin
  1493.     if (MySocket.IP<>'') and (MySocket.Port<>0) then break;
  1494.     Inc(StartTicket);
  1495.     Application.ProcessMessages;
  1496.     Sleep(30);
  1497.   end;
  1498.   if Category = ahResponse then MySocket.BeginGetHole;
  1499.   if Category = ahRequest then
  1500.   begin
  1501.       TempReg:=TRegistry.Create;
  1502.       try
  1503.         TempReg.RootKey:=HKEY_LOCAL_MACHINE;
  1504.         if not TempReg.KeyExists(AppKey+'AV') then
  1505.         begin
  1506.           RealMessengerX.MAVSetsClick(nil);
  1507.         end;
  1508.         if not TempReg.KeyExists(AppKey+'AV') then Exit;
  1509.       finally
  1510.         TempReg.Free;
  1511.       end;
  1512.       CBAudioRequest.Sender   :=Me.ID;
  1513.       CBAudioRequest.Receiver :=ID;
  1514.       CBAudioRequest.Room     :=ChatingForm.RoomInfo;
  1515.       CBAudioRequest.IP       :=MySocket.IP;
  1516.       CBAudioRequest.Port     :=MySocket.Port;
  1517.       CBAudioRequest.LocalIP  :=MySocket.LocalIP;
  1518.       CBAudioRequest.LocalPort:=MySocket.LocalPort;
  1519.       Buffer[1]:=skAudioRequest;
  1520.       CopyMemory(@Buffer[2],@CBAudioRequest,SizeOf(CBAudioRequest));
  1521.       RealMessengerX.ClientTCP.Socket.Send(Buffer,SizeOf(CBAudioRequest)+1);      {发送音频对话邀请}
  1522.   end;
  1523.   CreateHTML();
  1524.   ChatingForm.AudioIsOn:=True;
  1525.   AudioHandShakes.Add(Self);
  1526. end;
  1527. {------------------------------------------------------------------------------}
  1528. Constructor TTransmitFile.Create(vCategory     :TTransmitFileCategory;
  1529.                        vSenderID     :Integer;
  1530.                        vSenderName   :String;
  1531.                        vReceiverID   :Integer;
  1532.                        vReceiverName :String;
  1533.                        vFileName     :String;
  1534.                        vChatingForm  :TChatingForm;
  1535.                        ReceiverLocalIP:String;
  1536.                        ReceiverLocalPort:Integer;
  1537.                        ReceiverIP:String;
  1538.                        ReceiverPort:Integer;
  1539.                        vFileSize     :Int64=0;
  1540.                        vFileHashCode :String='';
  1541.                        vBaseID       :String='';
  1542.                        vIsScreen     :Boolean=False
  1543.                        );
  1544. var
  1545.   iLoop,PackCount,ID,StartTicket:Integer;
  1546.   MD5Code:MD5Digest;
  1547.   MD5Str:String;
  1548.   SendFileRequest:TCBSendFileRequest;
  1549.   TransmitFile:TTransmitFile;
  1550.   Buffer:array[1..2048] of char;
  1551.   FileTableUnit:PFileTableUnit;
  1552. begin
  1553.   SleepValue:=Round(100*performancefrequency_ms);
  1554.   
  1555.   with TransmitFiles.LockList do
  1556.   try
  1557.     for iLoop:=0 to Count - 1 do
  1558.     begin
  1559.       TransmitFile:=Items[iLoop];
  1560.       if (TransmitFile.SenderID = vSenderID) and (TransmitFile.ReceiverID = vReceiverID) and AnsiSameText(TransmitFile.FileName,vFileName) then
  1561.       begin
  1562.         messagebox(vChatingForm.Handle,'有一个相同的文件传输任务正在运行!','提示',MB_ICONINFORMATION);
  1563.         exit;
  1564.       end; 
  1565.     end;
  1566.   finally
  1567.     TransmitFiles.UnlockList;
  1568.   end;
  1569.   Inherited Create();
  1570.   Category:=vCategory;
  1571.   SenderID:=vSenderID;
  1572.   SenderName:=vSenderName;
  1573.   ReceiverID:=vReceiverID;
  1574.   ReceiverName:=vReceiverName;
  1575.   FileName:=vFileName;
  1576.   ChatingForm:=vChatingForm;
  1577.   FileSize:=vFileSize;
  1578.   FileHashCode:=vFileHashCode;
  1579.   BaseID:=vBaseID;
  1580.   IsScreen:=vIsScreen;
  1581.   if Category = tfGet then
  1582.     ID:=SenderID
  1583.   else
  1584.     ID:=ReceiverID;
  1585.   MySocket:=TMySocket.Create(ID,RealMessengerX.ClientTCP);
  1586.   MySocket.ReceiverLocalIP:=ReceiverLocalIP;
  1587.   MySocket.ReceiverLocalPort:=ReceiverLocalPort;
  1588.   MySocket.ReceiverIP:=ReceiverIP;
  1589.   MySocket.ReceiverPort:=ReceiverPort;
  1590.   StartTicket:=0;
  1591.   while StartTicket<100 do
  1592.   begin
  1593.     if (MySocket.IP<>'') and (MySocket.Port<>0) then break;
  1594.     Inc(StartTicket);
  1595.     Application.ProcessMessages;
  1596.     Sleep(30);
  1597.   end;
  1598.   if Category = tfGet then MySocket.BeginGetHole;
  1599.   if Category = tfSend then
  1600.   begin
  1601.       Employee:=FindEmployeeByID(ReceiverID);
  1602.       if Employee=nil then exit;
  1603.       FileStream  :=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
  1604.       FileSize    :=FileStream.Size;
  1605.       FileHashCode:='';
  1606.       MD5Code:=MD5String(ExtractFileName(FileName)+IntToStr(FileSize));
  1607.       for iLoop:=0 to SizeOf(MD5Digest)-1 do
  1608.         FileHashCode:=FileHashCode+IntToHex(MD5Code[iLoop],2);
  1609.       BaseID:=IntToStr(SenderID)+'_'+IntToStr(ReceiverID)+'_'+FileHashCode+'_'+IntToStr(GetTickCount);
  1610.       SendFileRequest.Sender        :=SenderID;
  1611.       SendFileRequest.Receiver      :=ReceiverID;
  1612.       SendFileRequest.FileID        :=FileHashCode;
  1613.       SendFileRequest.BaseID        :=BaseID;
  1614.       SendFileRequest.FileName      :=ExtractFileName(FileName);
  1615.       SendFileRequest.FileSize      :=FileSize;
  1616.       SendFileRequest.IsScreen      :=IsScreen;
  1617.       SendFileRequest.Room          :=ChatingForm.RoomInfo;
  1618.       SendFileRequest.IP            :=MySocket.IP;
  1619.       SendFileRequest.Port          :=MySocket.Port;
  1620.       SendFileRequest.LocalIP       :=MySocket.LocalIP;
  1621.       SendFileRequest.LocalPort     :=MySocket.LocalPort;
  1622.       Buffer[1]:=skSendFileRequest;
  1623.       CopyMemory(@Buffer[2],@SendFileRequest,SizeOf(SendFileRequest));
  1624.       MySocket.SendBuffer(Buffer,SizeOf(SendFileRequest)+1,True);      {发送文件传输请求}
  1625.   end
  1626.   else
  1627.   begin
  1628.       MD5Str:='';
  1629.       MD5Code:=MD5String(ExtractFileName(FileName)+IntToStr(FileSize));
  1630.       for iLoop:=0 to SizeOf(MD5Digest)-1 do
  1631.         MD5Str:=MD5Str+IntToHex(MD5Code[iLoop],2);
  1632.       if not AnsiSameText(MD5Str , FileHashCode) then exit;  {校验错误,退出}
  1633.   end;
  1634.   TransmitFiles.Add(Self);
  1635.   CreateHTML();
  1636.   
  1637.   if FileSize Mod FilePackSize=0 then
  1638.     PackCount:=FileSize div FilePackSize
  1639.   else
  1640.     PackCount:=(FileSize div FilePackSize)+1;
  1641.   FileTable:=TList.Create;
  1642.   for iLoop:=0 to PackCount-1 do
  1643.   begin
  1644.     GetMem(FileTableUnit,SizeOf(TFileTableUnit));
  1645.     FileTableUnit.IsAccepted:='0';
  1646.     FileTable.Add(FileTableUnit);
  1647.   end;
  1648.   ResumedSize:=0;
  1649. end;
  1650. Destructor TTransmitFile.Destroy();
  1651. var
  1652.   iLoop:Integer;
  1653.   FileTableUnit:PFileTableUnit;
  1654. begin
  1655.   Inherited Destroy;
  1656.   if FileStream<>nil then FileStream.Free;
  1657.   
  1658.   if FileTable<>nil then
  1659.   begin
  1660.     for iLoop:=0 to FileTable.Count-1 do
  1661.     begin
  1662.       FileTableUnit:=FileTable.Items[iLoop];
  1663.       FreeMem(FileTableUnit,SizeOf(TFileTableUnit));
  1664.     end;
  1665.     FileTable.Clear;
  1666.     FileTable.Free;
  1667.   end;
  1668. end;
  1669. {------------------------------------------------------------------------------}
  1670. procedure TTransmitFile.Stop(StopID:Integer);
  1671. var
  1672.   E:IHTMLElement;
  1673.   HTML:String;
  1674.   CBSendFileStop:TCBSendFileStop;
  1675.   Buffer:Array[1..2048]of char;
  1676. begin
  1677.   try
  1678.     TransmitFiles.Remove(Self);
  1679.     try
  1680.       FileStream.Free;
  1681.       FileStream:=nil;
  1682.       if Category = tfSend then (SendFileThread as TSendFile).Terminate;
  1683.     except
  1684.     end;
  1685.     if not IsScreen then
  1686.     begin
  1687.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1688.       E.setAttribute('src',ResPath+'ImagesFileClose.gif',0);
  1689.   
  1690.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1691.       if StopID = Me.ID then
  1692.         E.innerHTML:='您中断了此文件的传输'
  1693.       else
  1694.         E.innerHTML:='对方中断了此文件的传输';
  1695.     
  1696.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1697.       E.innerHTML:='<font color="#990000">已中断</font>';
  1698.   
  1699.       if StopID <> Me.ID then
  1700.       begin
  1701.         if StopID = SenderID then
  1702.           HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesFileClose.gif'+'" align="absbottom"> '+FilterHTMLCode(SenderName)+' 中断了传输文件:'+FilterHTMLCode(FileName)+'</div>'
  1703.         else
  1704.           HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesFileClose.gif'+'" align="absbottom"> '+FilterHTMLCode(ReceiverName)+' 中断了传输文件:'+FilterHTMLCode(FileName)+'</div>';
  1705.     
  1706.         InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1707.       end;
  1708.     end;
  1709.   
  1710.     if StopID = Me.ID then
  1711.     begin
  1712.       CBSendFileStop.Sender:=Me.ID;
  1713.       if Me.ID = SenderID then
  1714.         CBSendFileStop.Receiver:=ReceiverID
  1715.       else
  1716.         CBSendFileStop.Receiver:=SenderID;
  1717.       
  1718.       CBSendFileStop.BaseID:=BaseID;
  1719.       Buffer[1]:=skSendFileStop;
  1720.       CopyMemory(@Buffer[2],@CBSendFileStop,SizeOf(CBSendFileStop));
  1721.       MySocket.SendBuffer(Buffer,SizeOf(CBSendFileStop)+1,True);      {中断传输文件}
  1722.     end;
  1723.     FreeAndNil(Self);
  1724.   except
  1725.   end;
  1726. end;
  1727. {------------------------------------------------------------------------------}
  1728. procedure TTransmitFile.Cancel();
  1729. var
  1730.   E:IHTMLElement;
  1731.   HTML:String;
  1732.   CBSendFileCancle:TCBSendFileCancle;
  1733.   Buffer:Array[1..2048]of char;
  1734. begin
  1735.   TransmitFiles.Remove(Self);
  1736.   if not IsScreen then
  1737.   begin
  1738.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1739.     E.setAttribute('src',ResPath+'ImagesFileClose.gif',0);
  1740.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1741.     if Category = tfSend then
  1742.       E.innerHTML:='您已取消发送此文件'
  1743.     else
  1744.       E.innerHTML:='对方已取消发送此文件';
  1745.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1746.     E.innerHTML:='<font color="#990000">已取消</font>';
  1747.     if Category = tfGet then
  1748.     begin
  1749.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesFileClose.gif'+'" align="absbottom"> '+FilterHTMLCode(SenderName)+' 取消了发送文件:'+FilterHTMLCode(FileName)+'</div>';
  1750.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1751.     end;
  1752.   end;
  1753.   
  1754.   if Category = tfSend then
  1755.   begin
  1756.     CBSendFileCancle.Receiver:=ReceiverID;
  1757.     CBSendFileCancle.BaseID:=BaseID;
  1758.     Buffer[1]:=skSendFileCancle;
  1759.     CopyMemory(@Buffer[2],@CBSendFileCancle,SizeOf(CBSendFileCancle));
  1760.     MySocket.SendBuffer(Buffer,SizeOf(CBSendFileCancle)+1,True);      {取消发送文件}
  1761.   end;
  1762.   FreeAndNil(Self);
  1763. end;
  1764. {------------------------------------------------------------------------------}
  1765. procedure TTransmitFile.Error();
  1766. var
  1767.   E:IHTMLElement;
  1768.   HTML:String;
  1769. begin
  1770.   try
  1771.     TransmitFiles.Remove(Self);
  1772.   
  1773.     if not IsScreen then
  1774.     begin
  1775.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1776.       E.setAttribute('src',ResPath+'ImagesFileClose.gif',0);
  1777.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1778.       E.innerHTML:='传输过程中发生错误';
  1779.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1780.       E.innerHTML:='<font color="#990000">已停止</font>';
  1781.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesFileClose.gif'+'" align="absbottom"> 文件:'+FilterHTMLCode(FileName)+' 传输失败!</div>';
  1782.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1783.     end;
  1784.     
  1785.     FreeAndNil(Self);
  1786.   except
  1787.   end;
  1788. end;
  1789. {------------------------------------------------------------------------------}
  1790. procedure TTransmitFile.Decline();
  1791. var
  1792.   E:IHTMLElement;
  1793.   HTML:String;
  1794.   CBSendFileResponse:TCBSendFileResponse;
  1795.   Buffer:Array[1..2048]of char;
  1796. begin
  1797.   TransmitFiles.Remove(Self);
  1798.   
  1799.   if not IsScreen then
  1800.   begin
  1801.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  1802.     E.setAttribute('src',ResPath+'ImagesFileClose.gif',0);
  1803.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1804.     if Category = tfSend then
  1805.       E.innerHTML:='对方拒绝接受此文件'
  1806.     else
  1807.       E.innerHTML:='您已拒绝接受此文件';
  1808.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1809.     if Category = tfSend then
  1810.       E.innerHTML:='<font color="#990000">已被拒绝</font>'
  1811.     else
  1812.       E.innerHTML:='<font color="#990000">已拒绝</font>';
  1813.     if Category = tfSend then
  1814.     begin
  1815.       HTML:='<div style="color:#990000"><img src="'+ResPath+'ImagesFileClose.gif'+'" align="absbottom"> '+FilterHTMLCode(ReceiverName)+' 拒绝接受文件:'+FilterHTMLCode(FileName)+'</div>';
  1816.       InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  1817.     end;
  1818.   end;
  1819.   
  1820.   if Category = tfGet then
  1821.   begin
  1822.     CBSendFileResponse.IsAccept:=False;
  1823.     CBSendFileResponse.Receiver:=SenderID;
  1824.     CBSendFileResponse.BaseID:=BaseID;
  1825.     Buffer[1]:=skSendFileResponse;
  1826.     CopyMemory(@Buffer[2],@CBSendFileResponse,SizeOf(CBSendFileResponse));
  1827.     MySocket.SendBuffer(Buffer,SizeOf(CBSendFileResponse)+1,True);      {拒绝接受文件}
  1828.   end;
  1829.   FreeAndNil(Self);
  1830. end;
  1831. {------------------------------------------------------------------------------}
  1832. procedure TTransmitFile.Accept();
  1833. var
  1834.   E:IHTMLElement;
  1835.   CBSendFileResponse:TCBSendFileResponse;
  1836.   CBPleaseCallMe:TCBPleaseCallMe;
  1837.   Buffer:Array[1..2048]of char;
  1838.   iLoop:Integer;
  1839.   IsInSameNet:Boolean;
  1840.   Employee:PEmployee;
  1841.   TransmitFile:TTransmitFile;
  1842.   NullChar:char;
  1843.   SendFileResume:TCBSendFileResume;
  1844.   FileTableUnit:PFileTableUnit;
  1845.   Start,TFCount:Integer;
  1846. begin
  1847.   if Category = tfGet then
  1848.   begin
  1849.     TFCount:=0;
  1850.     with TransmitFiles.LockList do
  1851.     try
  1852.       for iLoop:=0 to Count - 1 do
  1853.       begin
  1854.         TransmitFile:=Items[iLoop];
  1855.         if (TransmitFile.SenderID = SenderID) and (TransmitFile.ReceiverID = ReceiverID) and (TransmitFile.IsAccepted=True) then
  1856.         begin
  1857.           Inc(TFCount);
  1858.           if TFCount>=3 then
  1859.           begin
  1860.             messagebox(ChatingForm.Handle,'在其它文件或图片发送完毕之前,您不能接受新的文件传输邀请!','提示',MB_ICONINFORMATION);
  1861.             exit;
  1862.           end;
  1863.         end;
  1864.       end;
  1865.     finally
  1866.       TransmitFiles.UnlockList;
  1867.     end;
  1868.     try
  1869.       if not IsScreen then
  1870.       begin
  1871.         ChatingForm.SaveDialog.FileName:=FileName;
  1872.         if ChatingForm.SaveDialog.Execute then
  1873.         begin
  1874.           SaveFileName := ChatingForm.SaveDialog.Files.Strings[0];
  1875.           if FileExists(SaveFileName) then DeleteFile(PChar(SaveFileName));
  1876.         end
  1877.         else
  1878.         begin
  1879.           exit;
  1880.         end;
  1881.       end
  1882.       else
  1883.       begin
  1884.         SaveFileName := ResPath+'Screens'+IntToStr(SenderID)+'R'+FileName;
  1885.         if not DirectoryExists(ExtractFilePath(SaveFileName)) then CreateDir(ExtractFilePath(SaveFileName));
  1886.       end;
  1887.       if FileExists(CachePath+''+FileHashCode) then
  1888.       begin
  1889.         if IsScreen or (MessageBox(ChatingForm.handle,'此文件在上次传输时被中断,是否使用断点续传方式接收?','提示',MB_ICONQUESTION or MB_YESNO) = ID_YES) then
  1890.         begin
  1891.           FileStream:=TFileStream.Create(CachePath+''+FileHashCode,fmOpenReadWrite or fmShareDenyWrite);
  1892.           try
  1893.             FileStream.Position:=0;
  1894.             Start:=0;
  1895.             E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1896.             E.innerHTML:='准备接收文件(正在发送断点续传信息)...';
  1897.             Application.ProcessMessages;
  1898.             ResumedSize:=0;
  1899.             while Start<FileTable.Count do
  1900.             begin
  1901.                 if FileTable.Count-Start>SizeOf(SendFileResume.ResumBuffer) then
  1902.                   SendFileResume.BufferLength:=SizeOf(SendFileResume.ResumBuffer)
  1903.                 else
  1904.                   SendFileResume.BufferLength:=FileTable.Count-Start;
  1905.                 
  1906.                 FileStream.Read(SendFileResume.ResumBuffer,SendFileResume.BufferLength);
  1907.                 SendFileResume.Start:=Start;
  1908.                 Start:=Start+SendFileResume.BufferLength;
  1909.                 for iLoop:=0 to SendFileResume.BufferLength-1 do
  1910.                 begin
  1911.                   PFileTableUnit(FileTable.Items[SendFileResume.Start+iLoop]).IsAccepted:=SendFileResume.ResumBuffer[iLoop+1];
  1912.                   if PFileTableUnit(FileTable.Items[SendFileResume.Start+iLoop]).IsAccepted='1' then ResumedSize:=ResumedSize+FilePackSize;
  1913.                 end;
  1914.                 SendFileResume.Sender:=Me.ID;
  1915.                 SendFileResume.Receiver:=SenderID;
  1916.                 SendFileResume.BaseID:=BaseID;
  1917.                 Buffer[1]:=skSendFileResume;
  1918.                 CopyMemory(@Buffer[2],@SendFileResume,SizeOf(SendFileResume));
  1919.                 MySocket.SendBuffer(Buffer,SizeOf(SendFileResume)+1,True); {发送续传位置信息}
  1920.                 Sleep(50);
  1921.                 Application.ProcessMessages;
  1922.             end;
  1923.           except
  1924.           end;
  1925.         end;
  1926.       end;
  1927.       if FileStream=nil then
  1928.       begin
  1929.         FileStream:=TFileStream.Create(CachePath+''+FileHashCode,fmCreate or fmShareDenyWrite);
  1930.         if not IsScreen then
  1931.         begin
  1932.           NullChar:='0';
  1933.           for iLoop:=0 to FileTable.Count-1 do FileStream.Write(NullChar,1);
  1934.         end;
  1935.       end;
  1936.     except
  1937.       on E: Exception do
  1938.       begin
  1939.         MessageBox(ChatingForm.handle,PChar(E.message),'错误',MB_ICONERROR);
  1940.         exit;
  1941.       end;
  1942.     end;
  1943.   end;
  1944.   IsAccepted:=True;
  1945.   StartTime:=GetTickcount;
  1946.   UsedTime:=0;
  1947.   LastGetOrResultTicket:=GetTickCount;
  1948.   RealMessengerX.TimeCheckTransmitFileError.Enabled:=True;
  1949.   if not IsScreen then
  1950.   begin
  1951.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  1952.     if Category = tfSend then
  1953.       E.innerHTML:='准备发送文件...'
  1954.     else
  1955.       E.innerHTML:='准备接受文件...';
  1956.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  1957.     E.innerHTML:='<a href="TFStop_'+BaseID+'" title="中断传输文件" >中断</a> ';
  1958.   end;
  1959.   if Category = tfGet then
  1960.   begin
  1961.     CBSendFileResponse.IsAccept :=True;
  1962.     CBSendFileResponse.Receiver :=SenderID;
  1963.     CBSendFileResponse.BaseID   :=BaseID;
  1964.     CBSendFileResponse.IP:=MySocket.IP;
  1965.     CBSendFileResponse.Port:=MySocket.Port;
  1966.     CBSendFileResponse.LocalIP:=MySocket.LocalIP;
  1967.     CBSendFileResponse.LocalPort:=MySocket.LocalPort;
  1968.     Buffer[1]:=skSendFileResponse;
  1969.     CopyMemory(@Buffer[2],@CBSendFileResponse,SizeOf(CBSendFileResponse));
  1970.     MySocket.SendBuffer(Buffer,SizeOf(CBSendFileResponse)+1,True);      {同意接受文件}
  1971.   end
  1972.   else
  1973.   begin
  1974.     SendFileThread:=TSendFile.Create(ReceiverID,BaseID,FileStream,Self);
  1975.   end;
  1976. end;
  1977. {------------------------------------------------------------------------------}
  1978. procedure TTransmitFile.Send(AcceptedSize:Int64);
  1979. begin
  1980.   UsedTime:=GetTickCount - StartTime;
  1981.   CurentSize:=AcceptedSize;
  1982.   if (UsedTime - OldUsedTime) > 250 then ShowProgress();   {显示进度}
  1983.   with FileTable do
  1984.   begin
  1985.     if CurentSize>=FileSize then
  1986.     begin
  1987.       PFileTableUnit(Items[Count-1]).IsAccepted:='1';
  1988.     end
  1989.     else
  1990.     begin
  1991.       PFileTableUnit(Items[(CurentSize div FilePackSize)-1]).IsAccepted:='1';
  1992.     end;
  1993.   end;
  1994. end;
  1995. {------------------------------------------------------------------------------}
  1996. procedure TTransmitFile.Get(SendTicket:Int64);
  1997. var
  1998.   CBSendFileResult:TCBSendFileResult;
  1999.   CBSendFileCompleted:TCBSendFileCompleted;
  2000.   Buffer:Array[1..2048]of char;
  2001.   AllIsSended:Boolean;
  2002.   iLoop:Integer;
  2003.   FileTableUnit:PFileTableUnit;
  2004.   ResumeChar:Char;
  2005. begin
  2006.   UsedTime:=GetTickCount - StartTime;
  2007.   if (UsedTime - OldUsedTime) > 250 then ShowProgress();   {显示进度}
  2008.   
  2009.   with FileTable do
  2010.   begin
  2011.     if CurentSize>=FileSize then
  2012.     begin
  2013.       PFileTableUnit(Items[Count-1]).IsAccepted:='1';
  2014.       if not IsScreen then
  2015.       begin
  2016.         ResumeChar:='1';
  2017.         FileStream.Position:=Count-1;
  2018.         FileStream.Write(ResumeChar,1);
  2019.       end;
  2020.     end
  2021.     else
  2022.     begin
  2023.       PFileTableUnit(Items[(CurentSize div FilePackSize)-1]).IsAccepted:='1';
  2024.       if not IsScreen then
  2025.       begin
  2026.         ResumeChar:='1';
  2027.         FileStream.Position:=(CurentSize div FilePackSize)-1;
  2028.         FileStream.Write(ResumeChar,1);
  2029.       end;
  2030.     end;
  2031.     AllIsSended:=True;
  2032.     with FileTable do
  2033.     begin
  2034.       for iLoop:=0 to Count-1 do
  2035.       begin
  2036.         FileTableUnit:=Items[iLoop];
  2037.         if FileTableUnit.IsAccepted='0' then
  2038.         begin
  2039.           AllIsSended:=False;
  2040.           break;
  2041.         end;
  2042.       end;
  2043.     end;
  2044.     if AllIsSended then
  2045.     begin
  2046.       IsComleted:=True;
  2047.       CBSendFileCompleted.Receiver:=SenderID;
  2048.       CBSendFileCompleted.BaseID:=BaseID;
  2049.       CBSendFileCompleted.Sender:=Me.ID;
  2050.       Buffer[1]:=skSendFileCompleted;
  2051.       CopyMemory(@Buffer[2],@CBSendFileCompleted,SizeOf(CBSendFileCompleted));
  2052.       MySocket.SendBuffer(Buffer,SizeOf(CBSendFileCompleted)+1,True);
  2053.       TMoveFile.Create(Self);
  2054.       Exit;
  2055.     end;
  2056.   end;
  2057.   CBSendFileResult.Receiver        :=SenderID;
  2058.   CBSendFileResult.BaseID          :=BaseID;
  2059.   CBSendFileResult.CurentSize      :=CurentSize;
  2060.   CBSendFileResult.SendTicket      :=SendTicket;
  2061.   Buffer[1]:=skSendFileResult;
  2062.   CopyMemory(@Buffer[2],@CBSendFileResult,SizeOf(CBSendFileResult));
  2063.   MySocket.SendBuffer(Buffer,SizeOf(CBSendFileResult)+1);  {告诉对方CurentSize位置处的文件已收到}
  2064. end;
  2065. {------------------------------------------------------------------------------}
  2066. procedure TTransmitFile.ShowComplete();
  2067. var
  2068.   E:IHTMLElement;
  2069.   HTML:String;
  2070.   SaveFileStream:TFileStream;
  2071.   Buffer:Array[1..FilePackSize] of char;
  2072.   BufferSize:Integer;
  2073.   iLoop:Integer;
  2074. begin
  2075.   try
  2076.     TransmitFiles.Remove(Self);
  2077.     try
  2078.       FileStream.Free;
  2079.       FileStream:=nil;
  2080.       if Category = tfSend then (SendFileThread as TSendFile).Terminate;
  2081.     except
  2082.     end;
  2083.     
  2084.     if not IsScreen then
  2085.     begin
  2086.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(CompletedID,0) as IHTMLElement;
  2087.       E.style.width:='100%';
  2088.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(UndoneID,0) as IHTMLElement;
  2089.       E.style.width:='0%';
  2090.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  2091.       E.innerHTML:='已完成';
  2092.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ActionID,0) as IHTMLElement;
  2093.       if Category = tfSend then
  2094.         E.innerHTML:='<font color="'+SysTextColor+'">文件发送完毕</font>'
  2095.       else
  2096.         E.innerHTML:='<font color="'+SysTextColor+'">文件接受完毕</font> <a href="about:blankFile://_'+ExtractFilePath(SaveFileName)+'" >打开所在文件夹</a>';
  2097.       if Category = tfGet then
  2098.       begin
  2099.         HTML:='<div style="color:'+SysTextColor+'"><img src="'+ResPath+'ImagesFile.gif'+'" align="absbottom"> 您成功的从 '+FilterHTMLCode(SenderName)+' 处接收了 <a href="about:blankFile://_'+SaveFileName+'" >'+FilterHTMLCode(SaveFileName)+'</a></div>';
  2100.         if not IsScreen then InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  2101.       end
  2102.       else
  2103.       begin
  2104.         HTML:='<div style="color:'+SysTextColor+'"><img src="'+ResPath+'ImagesFile.gif'+'" align="absbottom"> 文件 '+FilterHTMLCode(FileName)+' 发送完毕</div>';
  2105.         if not IsScreen then InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  2106.       end;
  2107.       
  2108.     end
  2109.     else if Category = tfGet then 
  2110.     begin
  2111.       E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(ImageID,0) as IHTMLElement;
  2112.       E.setAttribute('src',SaveFileName,0);
  2113.     end;
  2114.     FreeAndNil(Self);
  2115.   except
  2116.   end;
  2117. end;
  2118. {------------------------------------------------------------------------------}
  2119. procedure TTransmitFile.ShowProgress();
  2120. var
  2121.   E              :IHTMLElement;
  2122.   speedStr,
  2123.   CurentSizeStr,
  2124.   FileSizeStr    :string;
  2125.   iLoop,Completed      :Integer;
  2126.   TransmitedSize :Int64;
  2127. begin
  2128.   Application.ProcessMessages;
  2129.   
  2130.   if IsScreen then exit;
  2131.   if UsedTime=0 then exit;
  2132.   
  2133.   if FileSize > 0 then
  2134.   begin
  2135.     TransmitedSize:=0;
  2136.     with FileTable do
  2137.     begin
  2138.       for iLoop:=0 to Count-1 do
  2139.       begin
  2140.         if PFileTableUnit(Items[iLoop]).IsAccepted='1' then
  2141.         begin
  2142.           if iLoop<Count-1 then
  2143.             TransmitedSize:=TransmitedSize+FilePackSize
  2144.           else if FileSize mod FilePackSize=0 then
  2145.             TransmitedSize:=TransmitedSize+FilePackSize
  2146.           else
  2147.             TransmitedSize:=TransmitedSize+FileSize mod FilePackSize;
  2148.         end; 
  2149.       end;
  2150.     end;
  2151.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(CompletedID,0) as IHTMLElement;
  2152.     Completed:=TransmitedSize*100 div FileSize;
  2153.     E.style.width:=IntToStr(Completed)+'%';
  2154.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(UndoneID,0) as IHTMLElement;
  2155.     E.style.width:=IntToStr(100-Completed)+'%';
  2156.     
  2157.     speed:=Round((TransmitedSize-ResumedSize) / ((UsedTime-OldUsedTime) / 1000));
  2158.     OldUsedTime:=UsedTime;
  2159.     ResumedSize:=TransmitedSize;
  2160.     
  2161.     if speed > 1000*1000 then
  2162.       speedStr:=FloatToStr(StrToFloat(Copy(FloatToStr( speed / (1000*1000) ),1,3))) +'M/秒'
  2163.     else if speed > 1000 then
  2164.       speedStr:=FloatToStr(StrToFloat(Copy(FloatToStr( speed / 1000 ),1,3))) +'K/秒'
  2165.     else
  2166.       speedStr:=FloatToStr(StrToFloat(Copy(FloatToStr( speed ),1,3))) +'字节/秒';
  2167.     if (FileSize-CurentSize) > 1000 then
  2168.       FileSizeStr:=IntToStr((FileSize-TransmitedSize) div 1024) +' K'
  2169.     else
  2170.       FileSizeStr:=IntToStr((FileSize-TransmitedSize)) +' 字节';
  2171.     if CurentSize > 1000 then
  2172.       CurentSizeStr:=IntToStr(TransmitedSize div 1024) +' K'
  2173.     else
  2174.       CurentSizeStr:=IntToStr(TransmitedSize) +' 字节';
  2175.     E:=(ChatingForm.MsgContent.Document as IHTMLDocument2).all.item(PercentID,0) as IHTMLElement;
  2176.     E.innerHTML:='已传输 '+CurentSizeStr+',剩余 '+FileSizeStr+',速度 '+speedStr;
  2177.   end;
  2178. end;
  2179. {------------------------------------------------------------------------------}
  2180. procedure TTransmitFile.CreateHTML();
  2181. var
  2182.   HTML,FileSizeStr:String;
  2183. begin
  2184.   if not IsScreen then
  2185.   begin
  2186.     HTML:='<table width="100%" style="font-size:9pt;border:1px solid #808080;background-color:#FFFFCE;padding:2px;Scolor:'+SysTextColor+';margin-top:2px;margin-bottom:5px;filter: alpha(opacity=80);"><tr><td>';
  2187.     if FileSize > 1024 then
  2188.       FileSizeStr:=IntToStr(FileSize div 1024) +' K'
  2189.     else
  2190.       FileSizeStr:=IntToStr(FileSize) +' 字节';
  2191.     ImageID:='Image_'+BaseID;
  2192.     HTML:=HTML+'<img id="'+ImageID+'" src="'+ResPath+'ImagesFile.gif'+'" align="absbottom"> ';
  2193.     if Category = tfSend then
  2194.       HTML:=HTML+' 您要给 '+FilterHTMLCode(ReceiverName)+' 发送文件:'+FilterHTMLCode(FileName)+'('+FileSizeStr+')<br>'
  2195.     else
  2196.       HTML:=HTML+FilterHTMLCode(SenderName)+' 要给您发送文件:'+FilterHTMLCode(FileName)+'('+FileSizeStr+')<br>';
  2197.     PercentID:='Percent_'+BaseID;
  2198.     if Category = tfSend then
  2199.       HTML:=HTML+'<span id="'+PercentID+'" style="position:relative;top:18px;left:5px;">等待对方回应...</span><br>'
  2200.     else
  2201.       HTML:=HTML+'<span id="'+PercentID+'" style="position:relative;top:18px;left:5px;">等待您的回应...</span><br>';
  2202.     HTML:=HTML+'<table  width="288" border="0" cellpadding="0" cellspacing="1" bgcolor="#808080" style="margin-bottom:5px">'+
  2203.              '   <tr bgcolor="#FFFFCE">'+
  2204.              '     <td>'+
  2205.           '       <table width="288" border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFCE" height="18">'+
  2206.             '       <tr bgcolor="#FFFFCE">';
  2207.     CompletedID:='Completed_'+BaseID;
  2208.     HTML:=HTML+'<td id="'+CompletedID+'" width="0%" bgcolor="#5FFF3F"></td>';
  2209.   
  2210.     UndoneID:='Undone_'+BaseID;
  2211.     HTML:=HTML+'<td id="'+UndoneID+'" width="100%" ></td>';
  2212.     HTML:=HTML+'      </tr>'+
  2213.              '      </table>'+
  2214.              '    </td>'+
  2215.           '  </tr>'+
  2216.             '</table>';
  2217.              
  2218.     ActionID:='Action'+BaseID;
  2219.     HTML:=HTML+'<span id="'+ActionID+'">';
  2220.     if Category = tfSend then
  2221.       HTML:=HTML+'<a href="TFCancel_'+BaseID+'" title="取消发送此文件">取消</a> '
  2222.     else
  2223.       HTML:=HTML+'<a href="TFAccept_'+BaseID+'" title="接受此文件">接受</a> '+
  2224.                '<a href="TFdecline_'+BaseID+'" title="拒绝接受此文件">拒绝</a> ';
  2225.     HTML:=HTML+'</span>';
  2226.     HTML:=HTML+'</td></tr></table>';
  2227.   end
  2228.   else
  2229.   begin
  2230.     HTML:='<DIV style="padding-bottom:2px;color:'+SysTextColor+'">'+SenderName+' '+TimeToStr(Now)+' :<br> ';
  2231.     ImageID:='Image_'+BaseID;
  2232.     if Category = tfSend then
  2233.     begin
  2234.       HTML:=HTML+'<img id="'+ImageID+'" src="'+FileName+'" hspace="2" vspace="2"> ';
  2235.     end
  2236.     else
  2237.     begin
  2238.       HTML:=HTML+'<img id="'+ImageID+'" src="'+ResPath+'Imagesprogress.gif'+'" hspace="2" vspace="2"> ';
  2239.       Accept();
  2240.     end;
  2241.     HTML:=HTML+' </DIV>';
  2242.   end;
  2243.   InsertHTML(ChatingForm,ChatingForm.MsgContent,HTML);
  2244. end;
  2245. {------------------------------------------------------------------------------}
  2246. procedure TTransmitFile.Logout();
  2247. begin
  2248.   if IsAccepted then
  2249.     if SenderID = Me.ID then
  2250.       Stop(ReceiverID)
  2251.     else
  2252.       Stop(SenderID)
  2253.   else
  2254.     Cancel;
  2255. end;
  2256. {------------------------------------------------------------------------------}
  2257. {结束文件传输}
  2258. procedure TTransmitFile.Close();
  2259. begin
  2260.   if IsAccepted then
  2261.     Stop(Me.ID)
  2262.   else if Category = tfSend then
  2263.     Cancel
  2264.   else
  2265.     Decline;
  2266. end;
  2267. {------------------------------------------------------------------------------}
  2268. procedure ChangeAllColor(CustColor:TColor);
  2269. var
  2270.   iLoop:Integer;
  2271. begin
  2272.     RealMessengerX.PnlRoot.Color:=CustColor;
  2273.     ConvertBitmapToColor(RealMessengerX.ImgMyState.Picture.Bitmap,CustColor);
  2274.     ConvertBitmapToColor(RealMessengerX.ImgTitleLeft.Picture.Bitmap,CustColor);
  2275.     ConvertBitmapToColor(RealMessengerX.ImgTitle.Picture.Bitmap,CustColor);
  2276.     ConvertBitmapToColor(RealMessengerX.ImgTitleRight.Picture.Bitmap,CustColor);
  2277.     ConvertBitmapToColor(RealMessengerX.ImgToolbarLeft.Picture.Bitmap,CustColor);
  2278.     ConvertBitmapToColor(RealMessengerX.ImgToolbar.Picture.Bitmap,CustColor);
  2279.     ConvertBitmapToColor(RealMessengerX.ImgToolbarRight.Picture.Bitmap,CustColor);
  2280.     ConvertBitmapToColor(RealMessengerX.ImgBorderLeft.Picture.Bitmap,CustColor);
  2281.     ConvertBitmapToColor(RealMessengerX.ImgBorderRight.Picture.Bitmap,CustColor);
  2282.     ConvertBitmapToColor(RealMessengerX.ImgBottomLeft.Picture.Bitmap,CustColor);
  2283.     ConvertBitmapToColor(RealMessengerX.ImgBottom.Picture.Bitmap,CustColor);
  2284.     ConvertBitmapToColor(RealMessengerX.ImgBottomRight.Picture.Bitmap,CustColor);
  2285.     ConvertBitmapToColor(RealMessengerX.ImgMin.Picture.Bitmap,CustColor);
  2286.     ConvertBitmapToColor(RealMessengerX.ImgClosed.Picture.Bitmap,CustColor);
  2287.     ConvertBitmapToColor(RealMessengerX.ImgEmail.Picture.Bitmap,CustColor);
  2288.     RealMessengerX.Gauge.ForeColor:=CustColor;
  2289.     RealMessengerX.Repaint;
  2290.     RealMessengerX.TrevUserList.Repaint;
  2291.     for iLoop:=0 to ChatingFormList.Count -1 do ChangeChatingFormColor(ChatingFormList.Items[iLoop],CustColor);
  2292. end;
  2293. {------------------------------------------------------------------------------}
  2294. procedure ChangeChatingFormColor(ChatingForm:TChatingForm;CustColor:TColor);
  2295. begin
  2296.   ConvertBitmapToColor(ChatingForm.ImgOpenVideoForm.Picture.Bitmap,CustColor);
  2297.   ConvertBitmapToColor(ChatingForm.Image10.Picture.Bitmap,CustColor);
  2298.   ConvertBitmapToColor(ChatingForm.Image11.Picture.Bitmap,CustColor);
  2299.   ConvertBitmapToColor(ChatingForm.Image12.Picture.Bitmap,CustColor);
  2300.   ConvertBitmapToColor(ChatingForm.Image16.Picture.Bitmap,CustColor);
  2301.   ConvertBitmapToColor(ChatingForm.Image17.Picture.Bitmap,CustColor);
  2302.   ConvertBitmapToColor(ChatingForm.Image18.Picture.Bitmap,CustColor);
  2303.   ConvertBitmapToColor(ChatingForm.ImgArrow.Picture.Bitmap,CustColor);
  2304.   ConvertBitmapToColor(ChatingForm.Image32.Picture.Bitmap,CustColor);
  2305.   ConvertBitmapToColor(ChatingForm.Image33.Picture.Bitmap,CustColor);
  2306.   ConvertBitmapToColor(ChatingForm.Image34.Picture.Bitmap,CustColor);
  2307.   ConvertBitmapToColor(ChatingForm.ImgMic.Picture.Bitmap,CustColor);
  2308.   ConvertBitmapToColor(ChatingForm.ImgSpk.Picture.Bitmap,CustColor);
  2309.   ConvertBitmapToColor(ChatingForm.Image1.Picture.Bitmap,CustColor);
  2310.   ConvertBitmapToColor(ChatingForm.Image2.Picture.Bitmap,CustColor);
  2311.   ConvertBitmapToColor(ChatingForm.Image3.Picture.Bitmap,CustColor);
  2312.   ConvertBitmapToColor(ChatingForm.Image4.Picture.Bitmap,CustColor);
  2313.   ConvertBitmapToColor(ChatingForm.Image5.Picture.Bitmap,CustColor);
  2314.   ConvertBitmapToColor(ChatingForm.Image6.Picture.Bitmap,CustColor);
  2315.   ConvertBitmapToColor(ChatingForm.Image13.Picture.Bitmap,CustColor);
  2316.   ConvertBitmapToColor(ChatingForm.Image14.Picture.Bitmap,CustColor);
  2317.   ConvertBitmapToColor(ChatingForm.Image15.Picture.Bitmap,CustColor);
  2318.   ConvertBitmapToColor(ChatingForm.Image19.Picture.Bitmap,CustColor);
  2319.   ConvertBitmapToColor(ChatingForm.Image20.Picture.Bitmap,CustColor);
  2320.   ConvertBitmapToColor(ChatingForm.Image21.Picture.Bitmap,CustColor);
  2321.   ConvertBitmapToColor(ChatingForm.Image8.Picture.Bitmap,CustColor);
  2322.   ConvertBitmapToColor(ChatingForm.Image9.Picture.Bitmap,CustColor);
  2323.   ConvertBitmapToColor(ChatingForm.Image22.Picture.Bitmap,CustColor);
  2324.   ConvertBitmapToColor(ChatingForm.Image23.Picture.Bitmap,CustColor);
  2325.   ConvertBitmapToColor(ChatingForm.Image25.Picture.Bitmap,CustColor);
  2326.   ConvertBitmapToColor(ChatingForm.Image26.Picture.Bitmap,CustColor);
  2327.   ConvertBitmapToColor(ChatingForm.Image35.Picture.Bitmap,CustColor);
  2328.   ConvertBitmapToColor(ChatingForm.Image36.Picture.Bitmap,CustColor);
  2329.   ConvertBitmapToColor(ChatingForm.Image37.Picture.Bitmap,CustColor);
  2330.   ChatingForm.ImgListHistory.GetBitmap(0,ChatingForm.ImgHistory.Picture.Bitmap);
  2331.   ChatingForm.ImgListClose.GetBitmap(0,ChatingForm.ImgClose.Picture.Bitmap);
  2332.   ChatingForm.ImgListSend.GetBitmap(0,ChatingForm.ImgSend.Picture.Bitmap);
  2333.   ConvertBitmapToColor(ChatingForm.ImgHistory.Picture.Bitmap,CustColor);
  2334.   ConvertBitmapToColor(ChatingForm.ImgClose.Picture.Bitmap,CustColor);
  2335.   ConvertBitmapToColor(ChatingForm.ImgSend.Picture.Bitmap,CustColor);
  2336.   ConvertBitmapToColor(ChatingForm.ImgSendType.Picture.Bitmap,CustColor);
  2337.   ChatingForm.MMMixerSliderIn.ThumbColor:=CustColor;
  2338.   ChatingForm.MMMixerSliderInChange(ChatingForm.MMMixerSliderIn);
  2339.   ChatingForm.MMMixerSliderOut.ThumbColor:=CustColor;
  2340.   ChatingForm.MMMixerSliderInChange(ChatingForm.MMMixerSliderOut);
  2341.   try
  2342.     ChatingForm.SetBrowserStyle();
  2343.   except
  2344.   end;
  2345.   ChatingForm.Refresh;
  2346.   ChatingForm.PnlLeftTop.Refresh;
  2347.   ChatingForm.PnlLeftBottom.Refresh;
  2348.   ChatingForm.PnlRightBottom.Refresh;
  2349.   ChatingForm.TVUserList.Refresh;
  2350. end;
  2351. {------------------------------------------------------------------------------}
  2352. procedure FocusForm(form:TForm);
  2353. begin
  2354.   if (GetForegroundWindow<>form.Handle) then FlashWindow(form.Handle,True);
  2355. end;
  2356. procedure PlayEventSound(FileName:string);
  2357. begin
  2358.   try
  2359.     PlaySound(PChar(FileName),0,SND_ASYNC or SND_FILENAME);
  2360.   except
  2361.   end;
  2362. end;
  2363. {------------------------------------------------------------------------------}
  2364. function FindTransmitFileByBaseID(BaseID:String):TTransmitFile;
  2365. var
  2366.   iLoop:Integer;
  2367.   TransmitFile:TTransmitFile;
  2368. begin
  2369.   Result:=nil;
  2370.   with TransmitFiles.LockList do
  2371.   try
  2372.     for iLoop:=0 to Count - 1 do
  2373.     begin
  2374.       TransmitFile:=Items[iLoop];
  2375.       if AnsiSameText(TransmitFile.BaseID,BaseID) then
  2376.       begin
  2377.         Result:=TransmitFile;
  2378.         exit;
  2379.       end
  2380.     end;
  2381.   finally
  2382.     TransmitFiles.UnlockList;
  2383.   end;
  2384. end;
  2385. {------------------------------------------------------------------------------}
  2386. function FindVideoHandShakeByBaseID(BaseID:String):TVideoHandShake;
  2387. var
  2388.   iLoop:Integer;
  2389.   VideoHandShake:TVideoHandShake;
  2390. begin
  2391.   Result:=nil;
  2392.   with VideoHandShakes.LockList do
  2393.   try
  2394.     for iLoop:=0 to Count - 1 do
  2395.     begin
  2396.       VideoHandShake:=Items[iLoop];
  2397.       if AnsiSameText(VideoHandShake.BaseID,BaseID) then
  2398.       begin
  2399.         Result:=VideoHandShake;
  2400.         exit;
  2401.       end
  2402.     end;
  2403.   finally
  2404.     VideoHandShakes.UnlockList;
  2405.   end;
  2406. end;
  2407. {------------------------------------------------------------------------------}
  2408. function FindVideoHandShakeByID(ID:Integer):TVideoHandShake;
  2409. var
  2410.   iLoop:Integer;
  2411.   VideoHandShake:TVideoHandShake;
  2412. begin
  2413.   Result:=nil;
  2414.   with VideoHandShakes.LockList do
  2415.   try
  2416.     for iLoop:=0 to Count - 1 do
  2417.     begin
  2418.       VideoHandShake:=Items[iLoop];
  2419.       if VideoHandShake.ID=ID then
  2420.       begin
  2421.         Result:=VideoHandShake;
  2422.         exit;
  2423.       end
  2424.     end;
  2425.   finally
  2426.     VideoHandShakes.UnlockList;
  2427.   end;
  2428. end;
  2429. {------------------------------------------------------------------------------}
  2430. function FindAudioHandShakeByBaseID(BaseID:String):TAudioHandShake;
  2431. var
  2432.   iLoop:Integer;
  2433.   AudioHandShake:TAudioHandShake;
  2434. begin
  2435.   Result:=nil;
  2436.   with AudioHandShakes.LockList do
  2437.   try
  2438.     for iLoop:=0 to Count - 1 do
  2439.     begin
  2440.       AudioHandShake:=Items[iLoop];
  2441.       if AnsiSameText(AudioHandShake.BaseID,BaseID) then
  2442.       begin
  2443.         Result:=AudioHandShake;
  2444.         exit;
  2445.       end
  2446.     end;
  2447.   finally
  2448.     AudioHandShakes.UnlockList;
  2449.   end;
  2450. end;
  2451. {------------------------------------------------------------------------------}
  2452. function FindAudioHandShakeByID(ID:Integer):TAudioHandShake;
  2453. var
  2454.   iLoop:Integer;
  2455.   AudioHandShake:TAudioHandShake;
  2456. begin
  2457.   Result:=nil;
  2458.   with AudioHandShakes.LockList do
  2459.   try
  2460.     for iLoop:=0 to Count - 1 do
  2461.     begin
  2462.       AudioHandShake:=Items[iLoop];
  2463.       if AudioHandShake.ID=ID then
  2464.       begin
  2465.         Result:=AudioHandShake;
  2466.         exit;
  2467.       end
  2468.     end;
  2469.   finally
  2470.     AudioHandShakes.UnlockList;
  2471.   end;
  2472. end;
  2473. {------------------------------------------------------------------------------}
  2474. function FilterHTMLCode(HTML:String):String;
  2475. var
  2476.   jLoop:Integer;
  2477.   UrlStart,UrlEnd:Integer;
  2478.   TempStr:String;
  2479. begin
  2480.   HTML:=AnsiReplaceStr(HTML,'<','&lt;');
  2481.   HTML:=AnsiReplaceStr(HTML,'>','&gt;');
  2482.   HTML:=AnsiReplaceStr(HTML,#13,'&nbsp;<br>');
  2483.   HTML:=AnsiReplaceStr(HTML,#32,'&nbsp;');
  2484.   for jLoop:=1 to Length(Faces) do
  2485.     HTML:=AnsiReplaceStr(HTML,FacesChar[jLoop],'<img src="'+ResPath+'/Face/'+IntToStr(jLoop)+'.gif" align="absMiddle" hspace="1" >');
  2486.   TempStr:='';
  2487.   UrlStart:=AnsiPos('http://',HTML);
  2488.   while UrlStart>0 do
  2489.   begin
  2490.     TempStr:=TempStr+Copy(HTML,1,UrlStart-1);
  2491.     HTML:=Copy(HTML,UrlStart,Length(HTML));
  2492.     UrlEnd:=AnsiPos('&nbsp;',HTML);
  2493.     if UrlEnd<=0 then UrlEnd:=Length(HTML)+1;
  2494.     TempStr:=TempStr+'<a href="'+Copy(HTML,1,UrlEnd-1)+'" target="_blank"><font color="#0000ff">'+Copy(HTML,1,UrlEnd-1)+'</font></a>';
  2495.     HTML:=Copy(HTML,UrlEnd,Length(HTML));
  2496.     UrlStart:=AnsiPos('http://',HTML);
  2497.   end;
  2498.   TempStr:=TempStr+Copy(HTML,1,Length(HTML));
  2499.   Result:=TempStr;
  2500. end; 
  2501. {------------------------------------------------------------------------------}
  2502. function GetHostIP(HostName: String): String;
  2503. var
  2504.    buf:pChar;
  2505.    iWsaRet:Integer;
  2506.    Data:WSAData;
  2507.    hostent:PHostEnt;
  2508. begin
  2509.    Result := '';
  2510.    iWsaRet := WSAStartup($101,Data);
  2511.    if iWsaRet<>0 then
  2512.    begin
  2513.       ShowMessage('Socket initialize error!');
  2514.       Exit;
  2515.    end;
  2516.    buf := Allocmem(60);
  2517.    strcopy(buf,PChar(HostName));
  2518.    if Trim(buf)='' then
  2519.       gethostname(buf,60);
  2520.    hostent := gethostbyname(buf);
  2521.    Freemem(buf,60);
  2522.    if hostent=nil then
  2523.       Exit;
  2524.    Result  := inet_ntoa(pinAddr(hostent^.h_addr^)^);
  2525.    WSACleanup();
  2526. end;
  2527. {------------------------------------------------------------------------------}
  2528. function  OpenChatingForm(Room:ChatRoom;OpenNew:Boolean = True):TChatingForm;
  2529. var
  2530.   iLoop,i,j:Integer;
  2531.   ChatingForm: TChatingForm;
  2532.   Finded:Boolean;
  2533.   PEmployeeData:PEmployee;
  2534. begin
  2535.   Result:=nil;
  2536.   for iLoop:=1 to Room.UserCount do
  2537.   begin
  2538.     if Room.Users[iLoop]=Me.ID then continue;
  2539.     PEmployeeData:=FindEmployeeByID(Room.Users[iLoop]);
  2540.     if PEmployeeData=nil then continue;
  2541.     if PEmployeeData.MySocket=nil then PEmployeeData.MySocket:=TMySocket.Create(PEmployeeData.ID,RealMessengerX.ClientTCP,True);
  2542.   end;
  2543.   if (Room.UserCount<=0) or (Room.UserCount>16) then exit;
  2544.   
  2545.   for iLoop:=0 to ChatingFormList.Count - 1 do
  2546.   begin
  2547.     ChatingForm:=ChatingFormList.Items[iLoop];
  2548.     if (ChatingForm.RoomInfo.UserCount = Room.UserCount) then
  2549.     begin
  2550.       Finded:=False;
  2551.       
  2552.       for i:=1 to ChatingForm.RoomInfo.UserCount do
  2553.       begin
  2554.         Finded:=False;
  2555.         for j:=1 to Room.UserCount do
  2556.         begin
  2557.           if ChatingForm.RoomInfo.Users[i] = Room.Users[j] then
  2558.           begin
  2559.             Finded:=True;
  2560.             break;
  2561.           end;
  2562.         end;
  2563.         if not Finded then break;
  2564.       end;
  2565.       if Finded then
  2566.       begin
  2567.         Result:=ChatingForm;
  2568.         exit;
  2569.       end;
  2570.       
  2571.     end;
  2572.   end;
  2573.   if not OpenNew then
  2574.   begin
  2575.     Result:=nil;
  2576.     exit;
  2577.   end;
  2578.   ChatingForm:=TChatingForm.Create(RealMessengerX);
  2579.   ChangeChatingFormColor(ChatingForm,EndColor);
  2580.   ChatingForm.RoomInfo:=Room;
  2581.   ChatingFormList.Add(ChatingForm);
  2582.   Result:=ChatingForm;
  2583. end;
  2584. {------------------------------------------------------------------------------}
  2585. function GetSpecialFolderDir(const folderid:integer):string;
  2586. var
  2587.     pidl:pItemIDList;
  2588.     buffer:array [ 0..255 ] of char ;
  2589. begin
  2590.     SHGetSpecialFolderLocation( application.Handle , folderid, pidl);
  2591.     SHGetPathFromIDList(pidl, buffer);
  2592.     result:=strpas(buffer);
  2593. end;
  2594. {------------------------------------------------------------------------------}
  2595. procedure SaveHistory(CBMessage:TCBMessage);
  2596. var
  2597.   HistoryFile,MyHistoryPath:String;
  2598.   HistoryTextFile:TextFile;
  2599.   iLoop,FirstSessionID,LastSessionID:Integer;
  2600.   SenderName,ReceiverName:String;
  2601.   Xml:TXMLDocument;
  2602.   PEmployeeData:PEmployee;
  2603.   MsgContent,
  2604.   hexString,
  2605.   StyleText:String;
  2606. begin
  2607.   try
  2608.     MyHistoryPath:=HistoryPath+''+IntToStr(Me.ID);
  2609.     if not DirectoryExists(MyHistoryPath) then CreateDir(MyHistoryPath);
  2610.     FirstSessionID:=Me.ID;
  2611.     if CBMessage.Receiver=Me.ID then
  2612.     begin
  2613.       HistoryFile:=MyHistoryPath+''+IntToStr(CBMessage.Sender)+'.xml';
  2614.       LastSessionID:=CBMessage.Sender;
  2615.       ReceiverName:=Me.Name;
  2616.       with Employees.LockList do
  2617.       try
  2618.         for iLoop:=0 to Count-1 do
  2619.         begin
  2620.           PEmployeeData:=Items[iLoop];
  2621.           if PEmployeeData.ID=CBMessage.Sender then
  2622.           begin
  2623.             SenderName:=PEmployeeData.Name;
  2624.             break;
  2625.           end;
  2626.         end;
  2627.       finally
  2628.         Employees.UnlockList;
  2629.       end;
  2630.     end
  2631.     else
  2632.     begin
  2633.       HistoryFile:=MyHistoryPath+''+IntToStr(CBMessage.Receiver)+'.xml';
  2634.       LastSessionID:=CBMessage.Receiver;
  2635.       SenderName:=Me.Name;
  2636.       with Employees.LockList do
  2637.       try
  2638.         for iLoop:=0 to Count-1 do
  2639.         begin
  2640.           PEmployeeData:=Items[iLoop];
  2641.           if PEmployeeData.ID=CBMessage.Receiver then
  2642.           begin
  2643.             ReceiverName:=PEmployeeData.Name;
  2644.             break;
  2645.           end;
  2646.         end;
  2647.       finally
  2648.         Employees.UnlockList;
  2649.       end;
  2650.     end;
  2651.     AssignFile(HistoryTextFile,HistoryFile);
  2652.     if not FileExists(HistoryFile) then
  2653.     begin
  2654.       Rewrite(HistoryTextFile);
  2655.       try
  2656.         Writeln(HistoryTextFile,'<?xml version="1.0" encoding="gb2312"?>');
  2657.         Writeln(HistoryTextFile,'<?xml-stylesheet type=''text/xsl'' href=''../History.xsl''?>');
  2658.         Writeln(HistoryTextFile,'<Log FirstSessionID="'+IntToStr(FirstSessionID)+'" LastSessionID="'+IntToStr(LastSessionID)+'">');
  2659.         Writeln(HistoryTextFile,'</Log>');
  2660.       finally
  2661.         CloseFile(HistoryTextFile);
  2662.       end;
  2663.     end;
  2664.     StyleText:='font-family:'+CBMessage.Name;
  2665.     //设置字体
  2666.     hexString:=IntToHex(CBMessage.Color,6);   //获取颜色的16进制格式
  2667.     StyleText:=StyleText+';color:#'+Copy(hexString,5,2)+Copy(hexString,3,2)+Copy(hexString,1,2);  //将BGR颜色转换为RGB颜色
  2668.     StyleText:=StyleText+';font-size:'+IntToStr(CBMessage.Size)+'pt';
  2669.     if CBMessage.fsBold then StyleText:=StyleText+';font-weight:bold';
  2670.     if CBMessage.fsItalic then StyleText:=StyleText+';font-style:italic';
  2671.     StyleText:=StyleText+';text-decoration:';
  2672.     if CBMessage.fsUnderline then StyleText:=StyleText+' underline ';
  2673.     if CBMessage.fsStrikeOut then StyleText:=StyleText+' line-through ';
  2674.     
  2675.     MsgContent:=Copy(CBMessage.Content,1,CBMessage.Length);  //获得消息内容
  2676.     MsgContent:=DESryStr(MsgContent,DESKEY);
  2677.     MsgContent:=AnsiReplaceStr(MsgContent,'<','&lt;');
  2678.     MsgContent:=AnsiReplaceStr(MsgContent,'>','&gt;');
  2679.     Xml:= TXMLDocument.Create(nil);
  2680.     try
  2681.       Xml.LoadFromFile(HistoryFile);
  2682.       Xml.Active:=True;
  2683.       Xml.XML.Text:=Copy(Xml.XML.Text,1,Length(Xml.XML.Text)-8);
  2684.       Xml.XML.Text:=Xml.XML.Text+'<Message Date="'+DateToStr(CBMessage.SendDateTime)+'" Time="'+TimeToStr(CBMessage.SendDateTime)+'" DateTime="'+DateToStr(CBMessage.SendDateTime)+'T'+TimeToStr(CBMessage.SendDateTime)+'3Z" SessionID="'+IntToStr(CBMessage.Sender)+'">'+
  2685.                   '<From>'+
  2686.                   '<User FriendlyName="'+SenderName+'"/>'+
  2687.                   '</From>'+
  2688.                   '<To>'+
  2689.                   '<User FriendlyName="'+ReceiverName+'"/>'+
  2690.                   '</To>'+
  2691.                   '<Text Style="'+StyleText+'">'+MsgContent+'</Text>'+
  2692.                   '</Message>'+
  2693.                   '</Log>';
  2694.                   
  2695.       Rewrite(HistoryTextFile);
  2696.       Writeln(HistoryTextFile,Xml.XML.Text);
  2697.       Xml.Active:=False;
  2698.     finally
  2699.       Xml.Free;
  2700.       CloseFile(HistoryTextFile);
  2701.     end;
  2702.   except
  2703.   end;
  2704. end;
  2705. {------------------------------------------------------------------------------}
  2706. procedure InsertHTML(ChatingForm:TChatingForm;IE:TWebbrowser;HTML:String);
  2707. var
  2708.   DoC: IHTMLDocument2;
  2709. begin
  2710.   Doc := IE.Document as IHTMLDocument2;
  2711.   Doc.body.innerHTML:=Doc.body.innerHTML+HTML;
  2712.   sendMessage(GetWindow(GetWindow(IE.Handle,GW_CHILD),GW_CHILD), WM_VSCROLL, SB_BOTTOM, 0); 
  2713.   sendMessage(GetWindow(GetWindow(IE.Handle,GW_CHILD),GW_CHILD), WM_VSCROLL, SB_BOTTOM, 0); 
  2714.   sendMessage(GetWindow(GetWindow(IE.Handle,GW_CHILD),GW_CHILD), WM_VSCROLL, SB_BOTTOM, 0);
  2715.   if ChatingForm<>nil then
  2716.   begin
  2717.     with ChatingForm do
  2718.     begin
  2719.       if (not Focused) and (GetForegroundWindow<>Handle) and ((not Pushed and not Visible) or (Pushed and Visible)) and (not DontPlaySound) then
  2720.       begin
  2721.         PlayEventSound(MsgSound);
  2722.         FocusForm(ChatingForm);
  2723.       end;
  2724.     end
  2725.   end;
  2726. end;
  2727. {------------------------------------------------------------------------------}
  2728. procedure ShowMsg(ChatingForm:TChatingForm;IE:TWebbrowser;SenderName:String;CBMessage:TCBMessage;Save:Boolean=True);
  2729. var
  2730.   MsgContent,
  2731.   hexString,
  2732.   HTML:String;
  2733. begin
  2734.   MsgContent:='';
  2735.   MsgContent:=SenderName+' '+DateTimeToStr(CBMessage.SendDateTime)+' :';
  2736.   MsgContent:=FilterHTMLCode(MsgContent);
  2737.   HTML:='<DIV style="padding-bottom:2px;color:'+SysTextColor+'">'+MsgContent+'</DIV>';
  2738.   HTML:=HTML+'<DIV style="padding-left:9px;padding-bottom:2px;';
  2739.   HTML:=HTML+';font-family:'+CBMessage.Name;
  2740.   hexString:=IntToHex(CBMessage.Color,6);
  2741.   HTML:=HTML+';color:#'+Copy(hexString,5,2)+Copy(hexString,3,2)+Copy(hexString,1,2);
  2742.   HTML:=HTML+';font-size:'+IntToStr(CBMessage.Size)+'pt';
  2743.   if CBMessage.fsBold then HTML:=HTML+';font-weight:bold';
  2744.   if CBMessage.fsItalic then HTML:=HTML+';font-style:italic';
  2745.   HTML:=HTML+';text-decoration:';
  2746.   if CBMessage.fsUnderline then HTML:=HTML+' underline ';
  2747.   if CBMessage.fsStrikeOut then HTML:=HTML+' line-through ';
  2748.   MsgContent:=Copy(CBMessage.Content,1,CBMessage.Length);
  2749.   MsgContent:=DESryStr(MsgContent,DESKEY);
  2750.   MsgContent:=FilterHTMLCode(MsgContent);
  2751.   HTML:=HTML+'">'+MsgContent+' </DIV>';
  2752.   InsertHTML(ChatingForm,IE,HTML);
  2753.   if Save then SaveHistory(CBMessage);
  2754. end;
  2755. {------------------------------------------------------------------------------}
  2756. function jfForceForeGroundWindow(hwnd: THandle): boolean;
  2757. const
  2758.   SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
  2759.   SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
  2760. var
  2761.   ForegroundThreadID: DWORD;
  2762.   ThisThreadID : DWORD;
  2763.   timeout : DWORD;
  2764. begin
  2765.   if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE);  
  2766.   if GetForegroundWindow = hwnd then Result := true
  2767.   else begin
  2768.     if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4))
  2769.         or((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
  2770.              ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and
  2771.                     (Win32MinorVersion > 0)))) then
  2772.     begin
  2773.       Result := false;
  2774.       ForegroundThreadID :=
  2775.       GetWindowThreadProcessID(GetForegroundWindow,nil);
  2776.       ThisThreadID := GetWindowThreadPRocessId(hwnd,nil);
  2777.       if AttachThreadInput(ThisThreadID, ForegroundThreadID, true) then
  2778.       begin
  2779.         BringWindowToTop(hwnd);
  2780.         SetForegroundWindow(hwnd);
  2781.         AttachThreadInput(ThisThreadID, ForegroundThreadID, false);
  2782.         Result := (GetForegroundWindow = hwnd);
  2783.       end;
  2784.       if not Result then
  2785.       begin
  2786.         SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0);
  2787.         SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),SPIF_SENDCHANGE);
  2788.         BringWindowToTop(hwnd);
  2789.         SetForegroundWindow(hWnd);
  2790.         SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,TObject(timeout), SPIF_SENDCHANGE);
  2791.       end;
  2792.     end
  2793.     else begin
  2794.       BringWindowToTop(hwnd);
  2795.       SetForegroundWindow(hwnd);
  2796.     end;
  2797.       Result := (GetForegroundWindow = hwnd);
  2798.   end;
  2799. end;
  2800. {------------------------------------------------------------------------------}
  2801. {HostToIP}
  2802. function HostToIP(Name: string; var Ip: string): Boolean;
  2803. var
  2804.   wsdata : TWSAData;
  2805.   hostName : array [0..255] of char;
  2806.   hostEnt : PHostEnt;
  2807.   addr : PChar;
  2808. begin
  2809.   WSAStartup ($0101, wsdata);
  2810.   try
  2811.     gethostname (hostName, sizeof (hostName));
  2812.     StrPCopy(hostName, Name);
  2813.     hostEnt := gethostbyname (hostName);
  2814.     if Assigned (hostEnt) then
  2815.       if Assigned (hostEnt^.h_addr_list) then begin
  2816.         addr := hostEnt^.h_addr_list^;
  2817.         if Assigned (addr) then begin
  2818.           IP := Format ('%d.%d.%d.%d', [byte (addr [0]),
  2819.           byte (addr [1]), byte (addr [2]), byte (addr [3])]);
  2820.           Result := True;
  2821.         end
  2822.         else
  2823.           Result := False;
  2824.       end
  2825.       else
  2826.         Result := False
  2827.     else begin
  2828.       Result := False;
  2829.     end;
  2830.   finally
  2831.     WSACleanup;
  2832.   end
  2833. end;
  2834. end.