最近闲来无事,重新学习了Indy10,顺手写了一段即时通讯代码。与上次写的笔记有不同之处,但差别不大。
未研究过TCP打洞技术,所以下面的代码采用的是 客户端--服务器--客户端 模式,也就是服务器端转发消息的模式。
客户端模仿了QQ,可以在屏幕四周停靠自动隐藏
本文也演示了在线程中操作VCL的两张方法:
1:向主线程发送消息
2:在线程中使用临界区
program Server; uses
Forms,
UntMain in 'UntMain.pas' {Form2},
Unit2 in 'Unit2.pas',
Unit4 in 'Unit4.pas'; {$R *.res} begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
服务器端:
unit UntMain; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdContext, IdScheduler, IdSchedulerOfThread, IdSchedulerOfThreadPool,
IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, ImgList,
CoolTrayIcon, ExtCtrls, RzPanel, Unit2, IdGlobal, StdCtrls, RzLstBox,
IdSchedulerOfThreadDefault, RzStatus, RzButton, RzEdit,SyncObjs; type
TForm2 = class(TForm)
CoolTrayIcon1: TCoolTrayIcon;
ImageList1: TImageList;
IdTCPServer1: TIdTCPServer;
RzStatusBar1: TRzStatusBar;
RzListBox1: TRzListBox;
IdSchedulerOfThreadDefault1: TIdSchedulerOfThreadDefault;
Button1: TButton;
RzStatusPane1: TRzStatusPane;
RzStatusPane2: TRzStatusPane;
RzMemo1: TRzMemo;
RzButton1: TRzButton;
RzMemo2: TRzMemo;
Timer1: TTimer;
procedure IdTCPServer1Execute(AContext: TIdContext);
procedure CustomMessage(var message: TMessage); message CustMsg;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure IdTCPServer1Disconnect(AContext: TIdContext);
procedure RzButton1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
private
{ Private declarations } public
{ Public declarations }
end;
//TIdServerContext 类继承自 TIdContext类
//IdCustomTCPServer 单元 第295行
TMyClass = class(TIdServerContext)
CltInfo: TCltInfo;
end; var
Form2: TForm2;
CriticalSection:TCriticalSection;
implementation {$R *.dfm}
uses
Unit4;
procedure TForm2.Button1Click(Sender: TObject);
begin
IdTCPServer1.Active := True;
if IdTCPServer1.Active then
begin
RzMemo1.Lines.Add('服务器开启成功...');
end;
end; procedure TForm2.CustomMessage(var message: TMessage);
var
i,n: Integer;
ss,ip,Nc,sNc: string;
buf:TDataPack;
list:Tlist;
FContext:TIdContext;
begin
FContext := TMyClass(message.LParam);
case message.WParam of
CltConnect:
begin
ss:='';
Nc := TMyClass(FContext).CltInfo.CltName;
ip:= TMyClass(FContext).CltInfo.CltIP;
RzListBox1.Items.Add(Nc);
RzMemo2.Lines.Add('【客户:】' + Nc + ' (' + ip +') 登陆'+'---'+DateTimeToStr(Now)); for i := 0 to RzListBox1.Items.Count - 1 do // 发送连线客户端列表
ss:=ss+form2.RzListBox1.ItemCaption(i)+'|';
sNc :=Encrystrings(ss);
FillChar(buf, SizeOf(TDataPack), '');
buf.Command := CltList;
StrCopy(@buf.Data, PChar(sNc));
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for I := 0 to n-1 do
begin
try TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
except
//
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
end; CltDisconnect:
begin
for i := 0 to RzListBox1.Items.Count - 1 do
begin
if RzListBox1.ItemCaption(i) = TMyClass(FContext).CltInfo.CltName then
begin RzListBox1.Items.Delete(i);
RzMemo2.Lines.Add('【用户:】 '+ string(TMyClass(FContext).CltInfo.CltName) +' 离开---'+DateTimeToStr(Now));
Break;
end;
end; FillChar(buf, SizeOf(TDataPack), '');
ss := ''; for i := 0 to RzListBox1.Items.Count - 1 do // 发送连线客户端列表
ss := ss + Form2.RzListBox1.ItemCaption(i) + '|';
ss:=Encrystrings(ss);
buf.Command := CltList;
StrCopy(@buf.Data, PChar(ss));
list:= IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
except
//
end;
finally
IdTCPServer1.Contexts.UnlockList;
end;
end;
CltSendMessage:
begin end;
end;
end; procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin RzListBox1.Clear;
IdTCPServer1.Active := False;
end; procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
List:TList;
i,n:Integer;
LContext: TMyClass;
buf:TDataPack;
begin
//当有客户端尚未断开连接时,服务器主动断开连接会导致异常
//所以,在服务器端退出之前,检查时候有客户端尚未断开
//若有,通知客户端主动断开连接
List:= IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
if n >0 then
begin
CanClose := False;
FillChar(buf,SizeOf(TdataPack),'');
buf.Command := SrvCloseQuery;
for I := 0 to n - 1 do
begin
LContext := TMyClass(List.Items[i]);
LContext.Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
end;
end else CanClose := True;
finally
IdTCPServer1.Contexts.UnlockList;
end;
end; procedure TForm2.FormCreate(Sender: TObject);
begin
//在IdCustomTCPServer 单元第302行,定义了类的指针:
//TIdServerContextClass = class of TIdServerContext;
//AContext不确定以 TIdServerContext类创建,所以定义了一个类的指针TIdServerContextClass,
//AContext将以TIdServerContextClass指针所指向的类来创建,重新赋值指针,将以新类创建实例 //这里重新赋值AContext 新类,当客户端连接后,AContext将以新类TMyClass的实例创捷
//AContext 被创建后,将包含TMyClass类的新属性 TCltInfo
//详见IdCustomTCPServer 单元第956行
//如果不重新赋值AContext新类,AContext 在IdCustomTCPServer初始化时(TIdCustomTCPServer.InitComponent方法),
//以默认类TIdServerContext创建
//详见 IdCustomTCPServer 单元第812行
//这里我们需要给AContext 添加新属性 TCltInfo 用来保存客户端信息
//所以,以TIdServerContext 为基类,我们扩展出 TMyClass 子类
//每个客户端连接后,AContext即被创建,并把每个AContext地址(对象指针)保存在IdTCPServer.Contexts属性中
//当服务器端需要与某个客户端回话时,可以遍历Contexts属性
IdTCPServer1.ContextClass := TMyClass;
IdTCPServer1.Active := True;
if IdTCPServer1.Active then
begin
RzMemo1.Lines.Add('服务器开启成功...('+ DateTimeToStr(Now) + ')');
end;
CriticalSection:=TCriticalSection.Create;
end; procedure TForm2.FormDestroy(Sender: TObject);
begin
CriticalSection.Free;
end; procedure TForm2.IdTCPServer1Disconnect(AContext: TIdContext);
begin
SendMessage(Handle,CustMsg,CltDisconnect,LongInt(AContext));
end; procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var
BByte: TIdBytes;
buf: TDataPack;
i,n: Integer;
s,ss,ds,nr,Nc,ip:string;
List:Tlist;
begin
FillChar(buf, SizeOf(TDataPack), '');
AContext.Connection.IOHandler.ReadBytes(BByte, SizeOf(TDataPack), False);
BytesToRaw(BByte, buf, SizeOf(TDataPack));
//---------------------------------------------------------------------------------------
case buf.Command of
CltConnect:
begin
ss:='';
s:= string(buf.CltInfo.CltName);
Nc :=Uncrystrings(s);
ip:=AContext.Binding.PeerIP;
StrCopy(@TMyClass(AContext).CltInfo.CltName,PChar(Nc)) ;
StrCopy(@TMyClass(AContext).CltInfo.CltIP,PChar(ip));
Nc :=Uncrystrings(s);
for i := 0 to RzListBox1.Items.Count - 1 do
begin
if RzListBox1.Items[i]=Nc then
begin
buf.Command := CltDisconnect;
AContext.Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
Exit;
end;
end;
SendMessage(Handle,CustMsg,CltConnect,LongInt(AContext));
end;
//------------------------------------------------------------------------------------------------
CltSendMessage:
begin
s:= Uncrystrings(string(buf.CltInfo.CltName));
ds:=Uncrystrings(string(buf.DstInfo.CltName));
nr:=Uncrystrings(string(buf.Data)) +#13+#10;
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
begin
if TMyClass(List.Items[i]).CltInfo.CltName = ds then
begin
try
CriticalSection.Enter;
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
RzMemo1.Lines.Add(s + '对 '+ds + ' 说:'+ nr);
finally
CriticalSection.Leave;
end;
except
buf.Command := SrvMessage;
AContext.Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
end;
Exit;
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
end;
//--------------------------------------------------------------------------------------------------------
CltTimer :
begin
AContext.Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
end;
//---------------------------------------------------------------------------------------------------------
CltClear :
begin
s:= Uncrystrings(string(buf.CltInfo.CltName));
ds:=Uncrystrings(string(buf.DstInfo.CltName));
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
begin
if TMyClass(List.Items[i]).CltInfo.CltName = ds then
begin
try
CriticalSection.Enter;
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
RzMemo1.Lines.Add(s + ' 清除了 '+ds + ' 的屏幕'+#13+#10);
finally
CriticalSection.Leave;
end;
except
//
end;
Exit;
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
end;
//-------------------------------------------------------------------------------------------------------
CltLockSrc:
begin
s:= Uncrystrings(string(buf.CltInfo.CltName));
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
begin
if TMyClass(List.Items[i]).CltInfo.CltName <> s then
begin
try
CriticalSection.Enter;
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
finally
CriticalSection.Leave;
end;
except
//
end;
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
RzMemo1.Lines.Add(s + ' 锁定了屏幕 '+#13+#10);
end;
//-------------------------------------------------------------------------------------------------------
CltUnlockSrc :
begin
s:= Uncrystrings(string(buf.CltInfo.CltName));
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
begin
if TMyClass(List.Items[i]).CltInfo.CltName <> s then
begin
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack)); except
//
end;
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
RzMemo1.Lines.Add(s + ' 解锁了屏幕 '+#13+#10);
end;
//---------------------------------------------------------------------------------------------------------------
CltMessage :
begin
ds:=Uncrystrings(string(buf.DstInfo.CltName));
List := form2.IdTCPServer1.Contexts.LockList;
n:= List.Count;
try
for i := 0 to n - 1 do
begin
if TMyClass(List.Items[i]).CltInfo.CltName = ds then
begin
try
TMyClass(List.Items[i]).Connection.IOHandler.Write(RawToBytes(buf, SizeOf(TDataPack)), SizeOf(TDataPack));
except
//
end;
Exit;
end;
end;
finally
form2.IdTCPServer1.Contexts.UnlockList;
end;
end;
//-----------------------------------------------------------------------------------------------------------------
end;
end; procedure TForm2.RzButton1Click(Sender: TObject);
begin
RzMemo1.Clear;
end; end.
客户端
program Project3; uses
Forms,
windows,
Unit3 in 'Unit3.pas' {Form3},
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas',
Unit4 in 'Unit4.pas'; {$R *.res} begin
Application.Initialize;
Application.MainFormOnTaskbar := False ;
Application.CreateForm(TForm3, Form3);
SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW); Application.Run;
end.
unit Unit3; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, RzLstBox, ExtCtrls, ShellAPI, ImgList, RzTray, IdGlobal,
Unit2,Clipbrd,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, RzButton,
RzRadChk, RzPanel, Mask, RzEdit, RzLabel, ComCtrls, Menus, RzBHints, RzSplit,
RzAnimtr, IdZLibCompressorBase, IdCompressorZLib,RxRichEd, RzListVw,Buttons,
RzSpnEdt ; type
TForm3 = class(TForm)
RzListBox1: TRzListBox;
Timer1: TTimer;
RzTrayIcon1: TRzTrayIcon;
ImageList1: TImageList;
IdTCPClient1: TIdTCPClient;
RzCheckBox1: TRzCheckBox;
RzPanel1: TRzPanel;
RzPanel2: TRzPanel;
RzMemo2: TRzMemo;
RzLabel1: TRzLabel;
RzEdit1: TRzEdit;
RzButton2: TRzButton;
RzLabel2: TRzLabel;
RzEdit2: TRzEdit;
Timer2: TTimer;
PopupMenu1: TPopupMenu;
N1: TMenuItem;
RzButton3: TRzButton;
BalloonHint1: TBalloonHint;
RzLabel5: TRzLabel;
RzEdit3: TRzEdit;
RzSplitter1: TRzSplitter;
RzSplitter2: TRzSplitter;
RzAnimator1: TRzAnimator;
ImageList2: TImageList;
RzToolButton1: TRzToolButton;
PopupMenu2: TPopupMenu;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
ImageList3: TImageList;
RzButton4: TRzButton;
RzButton5: TRzButton;
RxRichEdit1: TRxRichEdit;
LabeledEdit1: TLabeledEdit;
RzPanel3: TRzPanel;
Image01: TImage;
Image02: TImage;
Image03: TImage;
Image04: TImage;
Image05: TImage;
Image06: TImage;
Image07: TImage;
Image08: TImage;
Image09: TImage;
Image10: TImage;
Image11: TImage;
Image12: TImage;
Image13: TImage;
Image14: TImage;
Image15: TImage;
Image16: TImage;
Image17: TImage;
Image18: TImage;
Image19: TImage;
Image20: TImage;
Image21: TImage;
Image22: TImage;
Image23: TImage;
Image24: TImage;
Image25: TImage;
Image26: TImage;
Image27: TImage;
Image28: TImage;
Image29: TImage;
Image30: TImage;
Image31: TImage;
Image32: TImage;
Image33: TImage;
Image34: TImage;
Image35: TImage;
Image36: TImage;
Image37: TImage;
Image38: TImage;
Image39: TImage;
Image40: TImage;
Image41: TImage;
Image42: TImage;
Image43: TImage;
Image44: TImage;
Button1: TButton;
RzButton1: TRzButton;
ScrollBox1: TScrollBox;
Image1: TImage;
Image45: TImage;
Image46: TImage;
Image47: TImage;
Image48: TImage;
Image49: TImage;
Image50: TImage;
Image51: TImage;
Timer3: TTimer;
Image2: TImage;
FontDialog1: TFontDialog;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure WMMOVING(var Msg: TMessage); message WM_MOVING;
procedure wmsizing(var Msg: TMessage); message WM_SIZING;
procedure RevCustMsg(var Msg:TMessage);message CustMsg;
procedure SetBarHeight;
procedure RzListBox1DblClick(Sender: TObject);
procedure RzCheckBox1Click(Sender: TObject);
procedure IdTCPClient1Connected(Sender: TObject);
procedure IdTCPClient1Disconnected(Sender: TObject);
procedure RzButton1Click(Sender: TObject);
procedure RzButton2Click(Sender: TObject);
procedure RzMemo2KeyPress(Sender: TObject; var Key: Char);
procedure Timer2Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure RzTrayIcon1RestoreApp(Sender: TObject);
procedure RzTrayIcon1MinimizeApp(Sender: TObject);
procedure RzMemo2MouseEnter(Sender: TObject);
procedure FormMouseEnter(Sender: TObject);
function MousePosion:Boolean;
procedure RzListBox1MouseEnter(Sender: TObject);
procedure N1Click(Sender: TObject);
procedure RzButton3Click(Sender: TObject);
procedure LabeledEdit1KeyPress(Sender: TObject; var Key: Char);
procedure RzEdit3KeyPress(Sender: TObject; var Key: Char);
procedure RzEdit1KeyPress(Sender: TObject; var Key: Char);
procedure PopupMenu1Popup(Sender: TObject);
procedure N4Click(Sender: TObject);
procedure RzButton4Click(Sender: TObject);
procedure RzButton5Click(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure RxRichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image01Click(Sender: TObject);
procedure RzSpinButtons1DownLeftClick(Sender: TObject);
procedure RzSpinButtons1UpRightClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure RxRichEdit1URLClick(Sender: TObject; const URLText: string;
Button: TMouseButton);
procedure Image1Click(Sender: TObject);
function MouseInScrollBox:Boolean;
procedure Timer3Timer(Sender: TObject);
procedure Image2Click(Sender: TObject);
private
{ Private declarations }
FAnchors: TAnchors;
public
{ Public declarations }
end; TRevDataThread = class(TThread)
private
buf: TDataPack;
protected
procedure Execute; override;
procedure ShowMsg;
procedure AddCltList;
procedure DoDiscnt;
procedure ClearScr;
procedure AddMessage;
procedure CltMessageIn;
procedure DoSrvMessage;
procedure DoSrvCloseQuery;
end;
// HidePosKind = (hpTop, hpLeft, hpBottom, hpRight);
// THidePos = set of HidePosKind; var
Form3: TForm3;
Lst_Height: Integer; // 记录窗体隐藏前的高度
Lst_Width: Integer; // 记录窗体隐藏前的宽度
Rec_Position: Boolean; // 是否启动窗体宽高记录标志
Cur_Top, Cur_Bottom: Integer; // 隐藏后窗体的顶端和底部位置
RevDataThread:TRevDataThread;
BoolEnable:Boolean;
implementation uses Math, types, Unit1,StrUtils,Unit4;
{$R *.dfm} procedure TForm3.WMMOVING(var Msg: TMessage);
begin
inherited;
with PRect(Msg.LParam)^ do
begin
if (akLeft in FAnchors) or (akRight in FAnchors) then
begin
if (Left > 0) and (Right < Screen.Width) then
begin
if Rec_Position then
begin
Bottom := top + Lst_Height;
Right := Left + Lst_Width;
Height := Lst_Height;
Width := Lst_Width;
end;
end
else
begin
SetBarHeight;
top := Cur_Top;
Bottom := Cur_Bottom;
exit;
end;
end;
Left := Min(Max(0, Left), Screen.Width - Width);
top := Min(Max(0, top), Screen.Height - Height);
Right := Min(Max(Width, Right), Screen.Width);
Bottom := Min(Max(Height, Bottom), Screen.Height);
if not Rec_Position then
begin
Lst_Height := Form3.Height;
Lst_Width := Form3.Width;
end;
FAnchors := [];
if Left = 0 then
Include(FAnchors, akLeft);
if Right = Screen.Width then
Include(FAnchors, akRight);
if top = 0 then
Include(FAnchors, akTop);
if Bottom = Screen.Height then
Include(FAnchors, akBottom);
Timer1.Enabled := FAnchors <> [];
if (akLeft in FAnchors) or (akRight in FAnchors) then
begin
Rec_Position := True;
SetBarHeight;
top := Cur_Top;
Bottom := Cur_Bottom;
end
else
Rec_Position := False;
Timer1.Enabled := FAnchors <> []; end;
end; procedure TForm3.Button1Click(Sender: TObject);
var
c:TComponent;
s:string;
begin
s:='01';
c:= FindComponent('Image'+s);
Clipboard.Assign(TImage(c).Picture);
RxRichEdit1.PasteFromClipboard;
end; procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if Assigned(RevDataThread) then FreeAndNil(RevDataThread);
IdTCPClient1.Disconnect;
end; procedure TForm3.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := False;
RzButton3.Click;
end; procedure TForm3.FormCreate(Sender: TObject);
begin
Timer1.Enabled := False;
Timer1.Interval := 200;
//FormStyle := fsStayOnTop;
BoolEnable:= False;
RzListBox1.Clear;
UnLcokTimes :=0;
LockStatus := False;
RxRichEdit1.Paragraph.LineSpacingRule:=lsSpecified;
RxRichEdit1.Paragraph.LineSpacing:=20;
ScrollBox1.VertScrollBar.Position :=0;
end; procedure TForm3.FormMouseEnter(Sender: TObject);
begin
RzTrayIcon1.Animate := False;
RzTrayIcon1.IconIndex := 0;
end; procedure TForm3.Timer1Timer(Sender: TObject);
const
cOffset = 2;
begin
if MousePosion then
begin
if akLeft in FAnchors then
Left := 0;
if akTop in FAnchors then
top := 0;
if akRight in FAnchors then
Left := Screen.Width - Width;
if akBottom in FAnchors then
top := Screen.Height - Height;
end
else
begin
if akLeft in FAnchors then
begin
Left := -Width + cOffset;
SetBarHeight;
top := Cur_Top;
Height := Cur_Bottom;
end;
if akTop in FAnchors then
top := -Height + cOffset;
if akRight in FAnchors then
begin
Left := Screen.Width - cOffset;
SetBarHeight;
top := Cur_Top;
Height := Cur_Bottom;
end;
if akBottom in FAnchors then
top := Screen.Height - cOffset;
end; end; procedure TForm3.Timer2Timer(Sender: TObject);
var
buf:TDataPack;
bbyte:TIdBytes;
begin
FillChar(buf,SizeOf(TDataPack),'');
buf.Command := CltTimer;
BByte := RawToBytes(buf, SizeOf(TDataPack));
try
IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
except
Timer2.Enabled := False;
RzAnimator1.Animate := False;
RzAnimator1.ImageIndex :=1;
ShowMessage('与服务器断开连接');
end;
end; procedure TForm3.Timer3Timer(Sender: TObject);
begin
if not MouseInScrollBox then
begin
if ScrollBox1.Visible then ScrollBox1.Visible := False;
end;
Timer3.Enabled := ScrollBox1.Visible;
end; procedure TForm3.IdTCPClient1Connected(Sender: TObject);
//var
// BByte: TIdBytes;
// buf: TDataPack;
begin
// FillChar(buf, SizeOf(TDataPack), '');
// buf.Command := CltConnect;
// buf.CltInfo.CltName := 'ZZPC';
// BByte := RawToBytes(buf, SizeOf(TDataPack));
// IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
// if Assigned(RevDataThread) then RevDataThread.Terminate; end; procedure TForm3.IdTCPClient1Disconnected(Sender: TObject);
begin
if Assigned(RevDataThread) then RevDataThread.Terminate;
RzListBox1.Items.Clear;
RzEdit2.ReadOnly := False;
RzToolButton1.Enabled := False;
RzButton4.Enabled := False;
RzCheckBox1.Checked := False;
end; procedure TForm3.Image01Click(Sender: TObject);
var
s:String;
begin
s:=RightStr(TImage(Sender).Name,2);
RzMemo2.Text := '['+s+']';
ScrollBox1.Visible := False;
RzToolButton1.Click;
end; procedure TForm3.Image1Click(Sender: TObject);
begin
ScrollBox1.Visible := not ScrollBox1.Visible;
Timer3.Enabled := ScrollBox1.Visible;
end; procedure TForm3.Image2Click(Sender: TObject);
begin
if FontDialog1.Execute then RxRichEdit1.Font := FontDialog1.Font; end; procedure TForm3.LabeledEdit1KeyPress(Sender: TObject; var Key: Char);
begin
if ((Key = #13) and (((hi(GetKeyState(VK_CONTROL))) and $80) <> $80)) then
begin
Key :=#0;
RzButton3.Click;
end;
end; function TForm3.MouseInScrollBox: Boolean;
begin
Result := False;
if WindowFromPoint(Mouse.CursorPos) = ScrollBox1.Handle then Result := True;
end; function TForm3.MousePosion: Boolean;
begin
Result := False;
if (WindowFromPoint(Mouse.CursorPos) = Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzListBox1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzPanel1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzPanel2.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RxRichEdit1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzMemo2.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzCheckBox1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzEdit1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzEdit2.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzEdit3.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzAnimator1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzButton2.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzButton3.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzSplitter1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzSplitter2.Handle) or
(WindowFromPoint(Mouse.CursorPos) = LabeledEdit1.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzButton4.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzButton5.Handle) or
(WindowFromPoint(Mouse.CursorPos) = RzPanel3.Handle) or
(WindowFromPoint(Mouse.CursorPos) = ScrollBox1.Handle) then
Result := True;
end; procedure TForm3.N1Click(Sender: TObject);
begin
RzButton5.Click;
end; procedure TForm3.N4Click(Sender: TObject);
begin
RzButton3.Click;
end; procedure TForm3.PopupMenu1Popup(Sender: TObject);
begin
N3.Visible :=RzButton3.Caption = '锁定';
N4.Visible := RzButton3.Caption = '锁定';
end; procedure TForm3.RevCustMsg(var Msg: TMessage);
var
s:string;
buf:TDataPack;
begin
FillChar(buf,SizeOf(TDataPack),'');
s:=string(PDatapack(Pointer(msg.LParam))^.Data);
form1.RzMemo1.Lines.Add(s);
end; procedure TForm3.RxRichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if RzTrayIcon1.Animate then
begin
RzTrayIcon1.Animate := False;
RzTrayIcon1.IconIndex := 0;
end;
end; procedure TForm3.RxRichEdit1URLClick(Sender: TObject; const URLText: string;
Button: TMouseButton);
begin
ShellExecute(Application.Handle, nil, PChar(URLText), nil, nil, SW_SHOWNORMAL);
end; procedure TForm3.RzButton1Click(Sender: TObject);
var
buf:TDataPack;
Bbyte:TIdBytes;
s,tm,bm:string;
pt:TPoint;
ctl:TComponent;
begin
if Trim(RzMemo2.Text) <>'' then
begin
if RzListBox1.ItemIndex <> -1 then
begin
s:=RzListBox1.SelectedItem;
if s= form3.RzEdit2.Text then
begin
RzListBox1.CustomHint.Title :='提示';
RzListBox1.CustomHint.Description :='您不能跟自己聊天,那是欲魔行为!';
pt.X :=RzListBox1.Width div 2;
pt.Y :=RzListBox1.Height div 6;
RzListBox1.CustomHint.ImageIndex :=1;
RzListBox1.CustomHint.HideAfter :=5000;
RzListBox1.CustomHint.ShowHint(RzListBox1.ClientToScreen(pt));
Exit;
end; FillChar(buf, SizeOf(TDataPack), '');
buf.Command := CltSendMessage;
StrCopy(@buf.CltInfo.CltName, PChar(Encrystrings(form3.RzEdit2.Text)));
StrCopy(@buf.DstInfo.CltName, PChar(Encrystrings(s)));
tm:= RzMemo2.Text + ' (' +datetimetostr(Now)+ ')';
StrCopy(@buf.Data, PChar(Encrystrings(tm)));
BByte := RawToBytes(buf, SizeOf(TDataPack));
try
IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
if CheckBmp(tm) then
begin
bm := Copy(tm,2,2);
RxRichEdit1.Lines.Add('你对 ' +RzListBox1.SelectedItem + ' 说:');
ctl:= FindComponent('Image'+bm);
//ShowMessage(TImage(ctl).Name);
if ctl <> nil then
begin
Clipboard.Assign(TImage(ctl).Picture);
RxRichEdit1.PasteFromClipboard;
end;
end else RxRichEdit1.Lines.Add('你对 '+ RzListBox1.SelectedItem + '说: '+ tm);
PostMessage(RxRichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
RzMemo2.Clear;
except
// if not IdTCPClient1.IOHandler.Opened then
// begin
ShowMessage('已与服务器断开连接,消息发送不成功');
RzListBox1.Items.Clear;
RzEdit2.ReadOnly := False;
RzToolButton1.Enabled := False;
RzButton4.Enabled := False;
RzCheckBox1.Checked := False;
// end; end;
end else begin
RzListBox1.CustomHint.Title :='提示';
RzListBox1.CustomHint.Description :='请在这里选择一个聊天对象';
pt.X :=RzListBox1.Width div 2;
pt.Y :=RzListBox1.Height div 6;
RzListBox1.CustomHint.ImageIndex :=1;
RzListBox1.CustomHint.HideAfter :=3000;
RzListBox1.CustomHint.ShowHint(RzListBox1.ClientToScreen(pt));
end;
end else begin
RzMemo2.CustomHint.Title :='提示';
RzMemo2.CustomHint.Description :='不能发送空消息哦';
pt.X :=RzMemo2.Width div 2;
pt.Y :=RzMemo2.Height div 2;
RzMemo2.CustomHint.ImageIndex :=0;
RzMemo2.CustomHint.HideAfter :=2000;
RzMemo2.CustomHint.ShowHint(RzMemo2.ClientToScreen(pt));
end;
end; procedure TForm3.RzButton2Click(Sender: TObject);
begin
RxRichEdit1.Clear;
end; procedure TForm3.RzButton3Click(Sender: TObject);
var
pt:TPoint;
buf:TDataPack;
Bbyte:TIdBytes;
begin
if RzButton3.Caption = '锁定' then
begin
FillChar(buf, SizeOf(TDataPack), '');
buf.Command := CltLockSrc;
StrCopy(@buf.CltInfo.CltName, PChar(Encrystrings(form3.RzEdit2.Text)));
BByte := RawToBytes(buf, SizeOf(TDataPack));
try
try
IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
except
//
end;
finally
RxRichEdit1.Visible := False;
RzMemo2.Visible := False;
RzListBox1.Visible := False;
RzToolButton1.Visible := False;
RzButton4.Visible := False;
RzButton2.Visible := False;
RzCheckBox1.Visible := False;
RzLabel5.Visible := False;
RzEdit3.Visible := False;
RzTrayIcon1.MinimizeApp;
RzButton3.Caption :='解锁';
LabeledEdit1.Visible := True;
RzLabel1.Visible := False;
RzLabel2.Visible := False;
RzEdit1.Visible := False;
RzEdit2.Visible := False;
RzPanel3.Visible := False;
LabeledEdit1.SetFocus;
LockStatus :=True; //屏幕锁定状态
ScrollBox1.Visible := False;
end;
// except
// RzButton3.CustomHint.Title :='错误';
// RzButton3.CustomHint.Description :='锁屏失败,请重试';
// pt.X :=RzButton3.Width div 2;
// pt.Y :=RzButton3.Height div 2;
// RzButton3.CustomHint.ImageIndex :=1;
// RzButton3.CustomHint.HideAfter :=3000;
// RzButton3.CustomHint.ShowHint(RzButton3.ClientToScreen(pt));
// end;
end else begin
if LabeledEdit1.Text = UnLockString then
begin
FillChar(buf, SizeOf(TDataPack), '');
buf.Command := CltUnlockSrc;
StrCopy(@buf.CltInfo.CltName, PChar(Encrystrings(form3.RzEdit2.Text)));
BByte := RawToBytes(buf, SizeOf(TDataPack));
try
try
IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
except
//
end;
finally
UnLcokTimes :=0;
RxRichEdit1.Visible := True ;
RzMemo2.Visible := True ;
RzListBox1.Visible := True ;
RzToolButton1.Visible := True ;
RzButton4.Visible := True;
RzButton2.Visible := True ;
RzCheckBox1.Visible := True;
RzPanel3.Visible := True;
RzButton3.Caption :='锁定';
LabeledEdit1.Text :='';
LabeledEdit1.Visible := False;
if not RzCheckBox1.Checked then
begin
RzLabel5.Visible := True;
RzEdit3.Visible := True;
RzLabel1.Visible := True;
RzLabel2.Visible := True;
RzEdit1.Visible := True;
RzEdit2.Visible := True;
RzPanel3.Visible := False;
end;
LockStatus := False; //屏幕锁定状态
// RzButton3.CustomHint.Title :='错误';
// RzButton3.CustomHint.Description :='解锁失败,请重试';
// pt.X :=RzButton3.Width div 2;
// pt.Y :=RzButton3.Height div 2;
// RzButton3.CustomHint.ImageIndex :=1;
// RzButton3.CustomHint.HideAfter :=3000;
// RzButton3.CustomHint.ShowHint(RzButton3.ClientToScreen(pt));
end;
end else begin
UnLcokTimes := UnLcokTimes+1;
LabeledEdit1.Text :='';
LabeledEdit1.CustomHint.Title :='错误';
LabeledEdit1.CustomHint.Description :='解锁密码不正确';
pt.X :=LabeledEdit1.Width div 2;
pt.Y :=LabeledEdit1.Height div 2;
LabeledEdit1.CustomHint.ImageIndex :=0;
LabeledEdit1.CustomHint.HideAfter :=2000;
LabeledEdit1.CustomHint.ShowHint(LabeledEdit1.ClientToScreen(pt));
LabeledEdit1.SetFocus;
if UnLcokTimes >=3 then
begin
ShowMessage('解锁密码尝试3次均不正确,程序退出');
if IdTCPClient1.Connected then IdTCPClient1.Disconnect;
if Assigned(RevDataThread ) then RevDataThread.Terminate;
Close;
end;
end;
end;
end; procedure TForm3.RzButton4Click(Sender: TObject);
var
buf:TDataPack;
Bbyte:TIdBytes;
s:string;
pt:TPoint;
begin
if RzListBox1.ItemIndex <>-1 then
begin
FillChar(buf, SizeOf(TDataPack), '');
s:=RzListBox1.SelectedItem;
StrCopy(@buf.CltInfo.CltName, PChar(Encrystrings(form3.RzEdit2.Text)));
StrCopy(@buf.DstInfo.CltName, PChar(Encrystrings(s)));
buf.Command :=CltClear;
BByte := RawToBytes(buf, SizeOf(TDataPack));
try
IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
RxRichEdit1.CustomHint.Title :='提示';
RxRichEdit1.CustomHint.Description :='您已清除自己和对方聊天记录';
pt.X :=RxRichEdit1.Width div 2;
pt.Y :=RxRichEdit1.Height div 2;
RxRichEdit1.CustomHint.ImageIndex :=1;
RxRichEdit1.CustomHint.HideAfter :=8000;
RxRichEdit1.CustomHint.ShowHint(RxRichEdit1.ClientToScreen(pt));
RxRichEdit1.Clear;
except
ShowMessage('已与服务器断开连接,清除屏幕不成功');
RzListBox1.Items.Clear;
RzEdit2.ReadOnly := False;
RzToolButton1.Enabled := False;
RzButton4.Enabled := False;
RzCheckBox1.Checked := False;
end;
end else begin
RzListBox1.CustomHint.Title :='提示';
RzListBox1.CustomHint.Description :='请在这里选择一个清除屏幕对象';
pt.X :=RzListBox1.Width div 2;
pt.Y :=RzListBox1.Height div 6;
RzListBox1.CustomHint.ImageIndex :=1;
RzListBox1.CustomHint.HideAfter :=3000;
RzListBox1.CustomHint.ShowHint(RzListBox1.ClientToScreen(pt));
end; end; procedure TForm3.RzButton5Click(Sender: TObject);
begin
Application.Terminate;
end; procedure TForm3.RzCheckBox1Click(Sender: TObject);
var
pt:TPoint;
begin
IdTCPClient1.Host := RzEdit1.Text;
if RzEdit3.Text <>'' then IdTCPClient1.Port := StrToInt(RzEdit3.Text)
else begin
RzEdit3.CustomHint.Title :='提示';
RzEdit3.CustomHint.Description :='服务器端口不能为空';
pt.X :=RzEdit3.Width div 2;
pt.Y :=RzEdit3.Height div 2;
RzEdit3.CustomHint.ImageIndex :=0;
RzEdit3.CustomHint.HideAfter :=2000;
RzEdit3.CustomHint.ShowHint(RzEdit3.ClientToScreen(pt));
RzCheckBox1.Checked := False;
Exit;
end;
if (RzEdit2.Text ='') then
begin
RzEdit2.CustomHint.Title :='提示';
RzEdit2.CustomHint.Description :='聊天昵称不能为空';
pt.X :=RzEdit2.Width div 2;
pt.Y :=RzEdit2.Height div 2;
RzEdit2.CustomHint.ImageIndex :=0;
RzEdit2.CustomHint.HideAfter :=2000;
RzEdit2.CustomHint.ShowHint(RzEdit2.ClientToScreen(pt));
RzCheckBox1.Checked := False;
Exit;
end;
if Pos(' ',RzEdit2.Text)<>0 then
begin
RzEdit2.CustomHint.Title :='提示';
RzEdit2.CustomHint.Description :='聊天昵称中不能包含空格和 | 字符';
pt.X :=RzEdit2.Width div 2;
pt.Y :=RzEdit2.Height div 2;
RzEdit2.CustomHint.ImageIndex :=0;
RzEdit2.CustomHint.HideAfter :=2000;
RzEdit2.CustomHint.ShowHint(RzEdit2.ClientToScreen(pt));
RzCheckBox1.Checked := False;
Exit;
end;
if (RzEdit1.Text ='') then
begin
RzEdit1.CustomHint.Title :='提示';
RzEdit1.CustomHint.Description :='服务器地址不能为空';
pt.X :=RzEdit1.Width div 2;
pt.Y :=RzEdit1.Height div 2;
RzEdit1.CustomHint.ImageIndex :=0;
RzEdit1.CustomHint.HideAfter :=2000;
RzEdit1.CustomHint.ShowHint(RzEdit1.ClientToScreen(pt));
RzCheckBox1.Checked := False;
Exit;
end;
try
if RzCheckBox1.Checked then
begin
IdTCPClient1.Connect;
RevDataThread := TRevDataThread.Create(True);
RevDataThread.FreeOnTerminate := True;
RevDataThread.Start;
RzToolButton1.Enabled := True;
RzButton4.Enabled := True;
RzCheckBox1.Checked := True;
RzEdit2.ReadOnly := True;
Timer2.Enabled := True;
RzEdit3.Visible := False;
RzLabel5.Visible := False;
RzLabel1.Visible := False;
RzLabel2.Visible := False;
RzPanel3.Visible := True;
RzEdit1.Visible := False;
RzEdit2.Visible := False;
RzAnimator1.Animate := True;
end
else
begin
IdTCPClient1.Disconnect;
if Assigned(RevDataThread) then RevDataThread.Terminate;
RzCheckBox1.Checked := False;
RzToolButton1.Enabled :=False;
RzButton4.Enabled := False;
RzEdit2.ReadOnly := False;
Timer2.Enabled := False;
RzEdit3.Visible := True;
RzLabel5.Visible := True;
RzLabel1.Visible := True;
RzLabel2.Visible := True;
RzPanel3.Visible := False;
RzEdit1.Visible := True;
RzEdit2.Visible := True;
RzAnimator1.Animate := False;
RzAnimator1.ImageIndex :=1;
end;
except
RzEdit2.ReadOnly := False;
RzCheckBox1.Checked := False;
RzToolButton1.Enabled :=False;
RzButton4.Enabled := False;
if Assigned(RevDataThread) then RevDataThread.Terminate;
if IdTCPClient1.Connected then IdTCPClient1.Disconnect;
ShowMessage('连接服务器失败,请确认服务器地址是否正确');
end;
end; procedure TForm3.RzEdit1KeyPress(Sender: TObject; var Key: Char);
var
tmp: string;
begin
tmp := '0123456789.' + Char(VK_BACK) + Char(VK_DELETE);
if Pos(Key, tmp) = 0 then Key := #0;
end; procedure TForm3.RzEdit3KeyPress(Sender: TObject; var Key: Char);
var
tmp: string;
begin
tmp := '0123456789' + Char(VK_BACK) + Char(VK_DELETE);
if Pos(Key, tmp) = 0 then Key := #0;
end; procedure TForm3.RzListBox1DblClick(Sender: TObject);
begin
// form1.Show;
end; procedure TForm3.RzListBox1MouseEnter(Sender: TObject);
begin
if RzTrayIcon1.Animate then
begin
RzTrayIcon1.Animate := False;
RzTrayIcon1.IconIndex := 0;
end;
end; procedure TForm3.RzMemo2KeyPress(Sender: TObject; var Key: Char);
begin
if (Key = #13) then
begin
if (((hi(GetKeyState(VK_CONTROL))) and $80) <> $80) and n2.Checked then
begin
Key :=#0;
if RzToolButton1.Enabled then RzToolButton1.Click;
end;
end;
end; procedure TForm3.RzMemo2MouseEnter(Sender: TObject);
begin
if RzTrayIcon1.Animate then
begin
RzTrayIcon1.Animate := False;
RzTrayIcon1.IconIndex := 0;
end;
end; procedure TForm3.RzSpinButtons1DownLeftClick(Sender: TObject);
begin
if RzPanel3.Height > 40 then RzPanel3.Height := (RzPanel3.Height -4) div 3;
end; procedure TForm3.RzSpinButtons1UpRightClick(Sender: TObject);
begin
if RzPanel3.Height <40 then RzPanel3.Height := RzPanel3.Height *3 +4;
end; procedure TForm3.RzTrayIcon1MinimizeApp(Sender: TObject);
begin
BoolEnable:= True;
end; procedure TForm3.RzTrayIcon1RestoreApp(Sender: TObject);
begin
BoolEnable:= False;
RzTrayIcon1.Animate:= False;
RzTrayIcon1.IconIndex := 0;
end; procedure TForm3.SetBarHeight;
var
AppBarData: TAPPBARDATA;
begin
AppBarData.cbSize := SizeOf(AppBarData);
If SHAppBarMessage(ABM_GETSTATE, AppBarData) AND (ABS_AUTOHIDE) <> 0 then
begin
Cur_Top := 1;
Cur_Bottom := Screen.Height - 1;
end
else
begin
SHAppBarMessage(ABM_GETTASKBARPOS, AppBarData);
case AppBarData.uEdge of
ABE_TOP:
begin
Cur_Top := AppBarData.rc.Bottom + 1;
Cur_Bottom := Screen.Height - 1;
end;
ABE_LEFT:
begin
Cur_Top := 1;
Cur_Bottom := Screen.Height - 1;
end;
ABE_RIGHT:
begin
Cur_Top := 1;
Cur_Bottom := Screen.Height - 1;
end;
ABE_BOTTOM:
begin
Cur_Top := 1;
Cur_Bottom := Screen.Height -
(AppBarData.rc.Bottom - AppBarData.rc.top) - 1;
end;
end;
end;
end; procedure TForm3.wmsizing(var Msg: TMessage);
begin
inherited;
if (akRight in FAnchors) then
begin
with PRect(Msg.LParam)^ do
begin
Left := Screen.Width - Width;
top := Cur_Top;
Right := Screen.Width;
Bottom := Cur_Bottom
end;
end
else if (akLeft in FAnchors) then
begin
with PRect(Msg.LParam)^ do
begin
Left := 0;
top := Cur_Top;
Right := Width;
Bottom := Cur_Bottom;
end;
end;
end; { TRevDataThread } procedure TRevDataThread.AddCltList;
var
t,s:string;
List:TStringList;
OldCount,NewCount:Integer;
begin
list:= TStringList.Create;
OldCount := Form3.RzListBox1.Count;
Form3.RzListBox1.Clear;
t:= string(buf.Data);
// count:=0; // dak|dkej|dinna|
// for i:= 0 to strlen(pchar(s)) do if copy(s,i,1)='|' then count:=count+1; //计算字符串中包含几个分隔符 |
// for I := 0 to Count do
// begin
// ss:= LeftStr(s,Pos('|',s)-1);
// end;
s:= Uncrystrings(t);
s:=LeftStr(s,StrLen(PChar(s))-1);
List.Delimiter:='|';
List.DelimitedText:=s;
//Form3.RzTrayIcon1.Hint := List.Text;
Form3.RzListBox1.Items.Assign(list);
NewCount := form3.RzListBox1.Count;
List.Free;
if NewCount > OldCount then form3.RzTrayIcon1.ShowBalloonHint('提示','有用户登录',bhiInfo,10)
else if NewCount < OldCount then form3.RzTrayIcon1.ShowBalloonHint('提示','有用户下线',bhiInfo,10);
end; procedure TRevDataThread.AddMessage;
var
ss:string;
begin
ss:= DecryStr(UncrypKey(string(buf.CltInfo.CltName),TKey),mkey);
case buf.Command of
CltLockSrc: Form3.RxRichEdit1.Lines.Add(ss + ' 锁定了屏幕'); CltUnlockSrc : Form3.RxRichEdit1.Lines.Add(ss + ' 解锁了屏幕');
end;
PostMessage(Form3.RxRichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
end; procedure TRevDataThread.ClearScr;
var
pt:TPoint;
ss:string;
begin
Form3.RxRichEdit1.Clear;
ss:= Uncrystrings(string(buf.CltInfo.CltName));
Form3.RxRichEdit1.CustomHint.Title :='提示';
Form3.RxRichEdit1.CustomHint.Description := ss+' 清除了您的聊天记录';
pt.X :=Form3.RxRichEdit1.Width div 2;
pt.Y :=Form3.RxRichEdit1.Height div 2;
Form3.RxRichEdit1.CustomHint.ImageIndex :=1;
Form3.RxRichEdit1.CustomHint.HideAfter :=8000;
Form3.RxRichEdit1.CustomHint.ShowHint(Form3.RxRichEdit1.ClientToScreen(pt));
Form3.RxRichEdit1.Clear;
Form3.RxRichEdit1.Lines.Add(ss+' 清除了您的聊天记录');
end; procedure TRevDataThread.CltMessageIn;
var
s:string;
begin
s:= Uncrystrings(string(buf.CltInfo.CltName));
form3.RxRichEdit1.Lines.Add(s + ' 可能离开,TA的屏幕是锁定状态') ;
PostMessage(Form3.RxRichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
end; procedure TRevDataThread.DoDiscnt;
begin
form3.RzCheckBox1.Checked := False;
Form3.IdTCPClient1.Disconnect;
ShowMessage(Form3.RzEdit2.Text +' 已经存在,请更名重新登录');
end; procedure TRevDataThread.DoSrvCloseQuery;
begin
Form3.IdTCPClient1.Disconnect;
Form3.RzCheckBox1.Checked := False;
end; procedure TRevDataThread.DoSrvMessage;
var
nr,ds:string;
begin
nr:=Uncrystrings(string(buf.Data));
ds:= Uncrystrings(string(buf.DstInfo.CltName));
Form3.RxRichEdit1.Lines.Add('[服务器消息]:您发送给 ['+ ds +'] 的消息: “'+ nr +'",转发不成功,请重新发送');
PostMessage(Form3.RxRichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
end; procedure TRevDataThread.Execute;
var
BByte: TIdBytes;
Nc:string;
begin
inherited;
FillChar(buf, SizeOf(TDataPack), '');
buf.Command := CltConnect;
Nc := Encrystrings(form3.RzEdit2.Text);
StrCopy(@buf.CltInfo.CltName, PChar(Nc));
BByte := RawToBytes(buf, SizeOf(TDataPack));
Form3.IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
while (not Terminated) and (Form3.IdTCPClient1.Connected) do
begin
FillChar(buf, SizeOf(TDataPack), '');
Form3.IdTCPClient1.IOHandler.ReadBytes(BByte, SizeOf(TDataPack), False);
BytesToRaw(BByte, buf, SizeOf(TDataPack));
case buf.Command of
CltSendMessage:
begin
//SendMessage(Handle,CustMsg,CltSendMessage,Integer(PDataPack(buf)));
Synchronize(showmsg);
if LockStatus then
begin
buf.DstInfo.CltName := buf.CltInfo.CltName;
buf.Command := CltMessage;
StrCopy(@buf.CltInfo.CltName, PChar(Encrystrings(form3.RzEdit2.Text)));
BByte := RawToBytes(buf, SizeOf(TDataPack));
Form3.IdTCPClient1.IOHandler.Write(BByte, SizeOf(TDataPack));
end;
end;
CltList : Synchronize(AddCltList); CltDisconnect : Synchronize(DoDiscnt); CltTimer : ; CltClear : Synchronize(clearscr); CltLockSrc,CltUnlockSrc : Synchronize(Addmessage); CltMessage : Synchronize(cltmessageIn); SrvMessage : Synchronize(DoSrvMessage); SrvCloseQuery : Synchronize(DoSrvCloseQuery);
end;
end;
end; procedure TRevDataThread.ShowMsg;
var
s,ss,bm:string;
ctl:TComponent;
begin
s:=Uncrystrings(string(buf.Data));
ss:= Uncrystrings(string(buf.CltInfo.CltName));
if CheckBmp(s) then
begin
bm := Copy(s,2,2);
Form3.RxRichEdit1.Lines.Add(ss + ' 对你说:');
//Clipboard.Assign(form3.Image1.Picture);
ctl:= Form3.FindComponent('Image'+bm);
if ctl <> nil then
begin
Clipboard.Assign(TImage(ctl).Picture);
form3.RxRichEdit1.PasteFromClipboard;
end;
end else Form3.RxRichEdit1.Lines.Add(ss + ' 对你说:'+s );
PostMessage(Form3.RxRichEdit1.Handle, WM_VSCROLL, SB_BOTTOM, 0);
if BoolEnable or ((form3.Timer1.Enabled) and (not form3.MousePosion)) then
begin
if not Form3.RzTrayIcon1.Animate then Form3.RzTrayIcon1.Animate:=True;
end; end; end.
公共单元
unit Unit2; interface uses Windows,Messages,Classes,SysUtils,StrUtils; const CustMsg = WM_USER + 2110;
CltConnect = 1;
CltDisconnect =2;
CltSendMessage =3;
CltList=4;
CltTimer =5;
CltClear = 6;
CltLockSrc =7;
CltUnlockSrc = 8;
CltMessage = 9;
SrvMessage =10;
SrvTimer =11;
SrvCloseQuery =12;
DataSize = 1024 *5; //数据缓冲区大小
UnLockString = '123456';
type
TCltInfo = packed record
CltIP:array[0..14] of Char;
CltName:array[0..255] of Char;
end; TDataPack = record
CltInfo:TCltInfo;
DstInfo:TCltInfo;
Command:Integer;
Data:array[0..DataSize -1] of Char;
end; PDataPack = ^TDataPack;
function Encrystrings(str:string):string;
function Uncrystrings(str:string):string;
function EncrypKey(Src: String; Key: String): string;
function UncrypKey(Src: String; Key: String): string;
function GetTMkey:string;
function CheckBmp(Str:string):Boolean;
var
UnLcokTimes:Integer;
LockStatus:Boolean;
implementation
uses Unit4; function CheckBmp(Str:string):Boolean;
begin
Result := False;
if Length(Str) < 4 then Exit;
if (LeftStr(Str,1) ='[') and (Copy(Str,4,1) = ']') then Result :=True;
end;
function Encrystrings(str:string):string;
var
tmp:string;
begin
tmp := EncryStr(str,MKey);
Result := EncrypKey(tmp,TKey);
end; function Uncrystrings(str:string):string;
var
tmp:string;
begin
tmp:= UncrypKey(str,TKey);
Result := DecryStr(tmp,MKey);
end;
// 加密函数
function EncrypKey(Src: String; Key: String): string;
var
KeyLen: integer;
KeyPos: integer;
offset: integer;
dest: string;
SrcPos: integer;
SrcAsc: integer;
Range: integer;
begin
//此处省略,自己写
end; // 解密函数
function UncrypKey(Src: String; Key: String): string;
var
//idx: integer;
KeyLen: integer;
KeyPos: integer;
offset: integer;
dest: string;
SrcPos: integer;
SrcAsc: integer;
TmpSrcAsc: integer;
begin
//此处省略,自己写
end; function GetTMkey:string;
var
ss: string;
n: Integer;
begin
ss := '';
Randomize;
repeat
n := Random(127);
if n>=34 then ss := ss + char(n);
until (Length(ss)>=12);
Result := ss;
end;
end.