Delphi本地网络应用程序
尝试学习如何制作服务器客户端应用程序之类的东西。我试图在所有客户机上画圆圈(鼠标点击),所以我就是这样做的。但它不工作-没有错误,但表单是空的。我需要修什么? 客户端代码Delphi本地网络应用程序,delphi,sockets,drawing,client-server,delphi-7,Delphi,Sockets,Drawing,Client Server,Delphi 7,尝试学习如何制作服务器客户端应用程序之类的东西。我试图在所有客户机上画圆圈(鼠标点击),所以我就是这样做的。但它不工作-没有错误,但表单是空的。我需要修什么? 客户端代码 unit Client; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {Figure, Ball,} IdBaseComp
unit Client;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, {Figure, Ball,} IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, ScktComp;
type
TForm1 = class(TForm)
Timer1: TTimer;
Button1: TButton;
ClientSocket: TClientSocket;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
public
{ Public declarations }
end;
var
Form1: TForm1;
f:boolean;
p:MyPoint;
s:MyPoint;
z:TCanvas;
obj: MyFigure;
pX, pY:Integer;
myBuf: array[1..32] of Integer;
dataBuf: array[1..32] of Integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled:=false;
Timer1.Interval:=5;
z:=Form1.Canvas;//TCanvas.Create;
Button1.Caption:='Пуск';
f:=false;
ClientSocket.Port:=1234;
ClientSocket.Active:= False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not f then
begin
Timer1.Enabled:=true;
Button1.Caption:='Стоп';
f:=not f;
end
else
begin
Timer1.Enabled:=false;
Button1.Caption:='Пуск';
ClientSocket.Active:= True;
f:=not f;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//z.Lock;
//z.Brush.Color:=ClWhite;
//z.FillRect(Canvas.ClipRect);
//obj.Draw(z);
if ClientSocket.Active then
ClientSocket.Socket.ReceiveBuf(dataBuf, 32);
z.Brush.Color:=ClRed;
z.Ellipse(dataBuf[1] + 10, dataBuf[2] + 10,dataBuf[1] - 10, dataBuf[2] - 10);
//z.Unlock;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ClientSocket.Active := false;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
myBuf[1]:=X;
myBuf[2]:=Y;
if ClientSocket.Active then
ClientSocket.Socket.SendBuf(myBuf, 32);
end;
end.
服务器
unit ServerProject;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientWrite(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
sBufer : array [1..32] of Integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Port:=1234;
ServerSocket1.Active := True;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ServerSocket1.Active := false;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
begin
with ServerSocket1.Socket.Connections[i] do
begin
ReceiveBuf(sBufer, 32);
end;
end;
end;
procedure TForm1.ServerSocket1ClientWrite(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
begin
with ServerSocket1.Socket.Connections[i] do
begin
SendBuf(sBufer, 32);
end;
end;
end;
end.
您的绘制代码位于错误的位置,并且绘制到错误的对象。在Windows程序中,您需要根据
WM_paint
消息进行绘制。你没有这样做。此外,您还必须在调用BeginPaint
提供的设备上下文上绘制
VCL为您包装了所有这些细节,但您仍然需要遵守规则。在您的情况下,我建议您在表单中添加tpainbox
组件。然后为绘制框实现一个OnPaint
事件处理程序。最后,每当您希望重新绘制绘制框时,例如在计时器上,调用绘制框的Invalidate
方法
我怀疑您希望在先前绘制的椭圆之外再绘制每个新椭圆。在这种情况下,最好先将它们绘制到屏幕外位图,然后在绘制框中绘制位图。关键是一个窗口需要能够整体地重新绘制自己。当您在屏幕设备上绘制时,您绘制的内容将在下次需要绘制该窗口时丢失。因此,如果需要,应用程序有责任在任何时候绘制其整个自我
更一般地说,我敦促您停止使用全局变量。他们会给你带来无尽的麻烦。尽可能选择局部变量。如果需要在不同的方法调用之间保持状态,请使用成员变量。指导原则是使用尽可能狭窄的范围
您当前的设计使用计时器轮询新数据。这是一个非常糟糕的方法。最有效的方法是使用同步阻塞通信。印地采取了这种做法。相反,Windows套接字组件倾向于以异步模式使用。不管这两种方法的相对优点如何,您都不应该使用计时器进行轮询。如果确实使用异步通信,则通过处理事件而不是轮询来响应新数据
您的程序目前正在尝试将GDI绘制和网络通信混合在一起。我建议您尝试一次一个地掌握这些概念。学习如何在没有沟通干扰的情况下画画。然后,当你已经破解了绘画,试着引入沟通方面。但如果我只写这样的
z.elope(X+10,Y+10,X-10,Y-10),就可以正确地绘制椭圆了
在过程中TForm1.FormMouseDown
好的,当我说你需要为WM\u paint
作画时,你不相信我。不,我相信你(但实际上我现在并没有正确理解所有事情,我的英语不太好)但据我所知,我在这里所做的只是从某个客户端阵列向服务器发送数据,然后从服务器向该阵列的所有客户端发送数据。如果像z.椭圆(X+10,Y+10,X-10,Y-10)
在这里工作(我检查了它)为什么不工作z.Ellipse(dataBuf[1]+10,dataBuf[2]+10,dataBuf[1]-10,dataBuf[2]-10)
我猜dataBuf
不包含您认为它包含的内容。在我看来,您的代码太混乱,无法取得真正的进展。你需要试着一次只学一件事。目前,您的代码有太多不同的方面设计得很糟糕,这些不同方面的问题将使您试图学习和理解的努力合二为一。首先,我要把绘画代码弄好。所以通讯不起作用。下一步是隔离程序的这一部分并找出原因。一次只关注一个方面。你已经建立了一个大程序,但很多都失败了。你不知道去哪里找。一次只构建一个部分,只有当每个部分都能独立工作时才能继续。