Envoi et réception d'une capture d'écran par streams avec les composants tcp indy

Soyez le premier à donner votre avis sur cette source.

Vue 12 493 fois - Téléchargée 2 194 fois

Description

Je dispose de Delphi 7 et je voulais créer une application capable d'envoyer une capture de mon écran à un ordinateur distant. Après avoir chercher un peu parmi les sources disponibles et après avoir tester quelques un, je n'ai pas trouver de solution convenant à mes besoins. Il y'a bien une source qui présente comment faire une application du style VNC mais il n'est pas précisé k'il faut pour pouvoir compiler ce code disposer de composants fastnet qui ont malheureusement disparus de la palette Delphi 7. Je propose donc ici un moyen très simple d'envoyer une capture d'écran par streaming à l'aide des composants Indy (fournis avec Delphi 7). Le principe est simple, le logiciel client crée une capture d'écran, la converti en jpg, l'enregistre dans un stream et l'envois par TCP. De son côté le logiciel serveur réceptionne le stream et le charge dans un coposant Timage. Le code présente juste la maniere d'envoyer et recevoir le stream, libre a vous de vous en servir comme bon vous semble, il est tt à fait possible de se servir du code dans l'autre sens, c'est à dire d'envoyer le stream depuis le serveur jusqu'au client après que le serveur ait recu une requette lui demandant d'envoyer l'image (moyennant peu être quelques modifications pas insurmontables même pour débutant). Le programme client se présente de cette maniere : c'est une form avec 2 boutons, un pour démarrer l'envois et l'autre pour l'arreter. Il y'a aussi 2 edits, un où l'on doit mettre l'ip du serveur distant et l'autre où l'on indique l'intreval des envois de capture d'écran "en ms" (la valeure de l'intreval de répétion du timer). dans le cas de l'envois du stream depuis le serveur jusqu'au client après la réception d'une requette il est plus commode de ne pas utiliser de timer, simplement d'envoyer une nouvelle requette pour une capture lors de la réception de la précédente. Attention ce deuxieme cas n'est pas abordé ici car ce n'est pas de cette fonction que j'avais besoin mais je la posterai sans doute en complément plus tard. Sinon le logiciel serveur contient un composant tcp server Indy et un composant Timage, c'est tout. Je sais je parle trop mais que voulez vous, on se refait pas ;)

Source / Exemple :


// Sources du client :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient,jpeg, ExtCtrls;  //Ne pas oublier de déclarer la classe jpeg

type
  TForm1 = class(TForm)
    tcp: TIdTCPClient; //Composant tcp client de Indy
    Button1: TButton;
    Edit1: TEdit;
    Timer1: TTimer;
    Button2: TButton;
    Label1: TLabel;
    Edit2: TEdit;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure sendstr;
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.sendstr;  //Procedure de capture d'écran,conversion en jpg et envoi
var Img:TPicture;
MemStream:TMemoryStream; // Déclaration des variables
JPG:TJPEGImage;
Bmp :TBitMap;
Rect:TRect;

begin

   Img:=TPicture.Create;                         
   Bmp := TBitMap .Create; //Initialisation des variables qui doivent l'être
   MemStream:=TMemoryStream.Create;

     Img.Bitmap.Width:=Screen.Width;
       Img.Bitmap.Height:=Screen.Height;            
        BitBlt(Img.Bitmap.Canvas.Handle,0,0,Screen.Width,Screen.Height,GetDC(GetDesktopWindow),0,0,SrcCopy); //Capture de l'écran
                JPG:=TJPEGImage.Create;
             try
             JPG.Assign(Img.Bitmap);   //Conversion en jpg
             JPG.CompressionQuality:=15;
             Bmp.Width :=Jpg.Width -50;
             Bmp.Height :=Jpg.Height -50;
             Rect.Left :=0;
             Rect.Top :=0;
             Rect.Right :=Bmp.Width-1;
             Rect.Bottom:=Bmp.Height-1;
             Bmp.Canvas.StretchDraw(Rect,Jpg);
             Jpg.Assign(Bmp);
             jpg.savetostream(Memstream);//Chargement de l'image jpg dans le stream
             finally
             bmp.Free;
             img.free;
             JPG.Free;
        try
        with tcp do
        begin

        OpenWriteBuffer;
        WriteStream(memstream);//Envoi du stream
        CloseWriteBuffer;
        memstream.Free;
        disconnect; //Déconnexion
        end;
        except

        end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject); //Bouton pour démarrer l'envoi
begin
try
timer1.Interval:= strtoint(edit2.Text);//Définition de l'interval du timer
tcp.Host:= edit1.Text;  //Définition de l'hote (serveur)
timer1.Enabled:=true; //Démarrage du timer
except
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject); //Procedure que le timer execute celon l                                                                              //'interval donné
begin
try
tcp.Connect; //Connexion du client tcp
form1.sendstr; //Execution de la procédure définie plus haut
except
timer1.Enabled:= false;  //Si la connexion est impossible on arrete le timer
showmessage('connextion impossible'); //On affiche une boite de dialogue qui nous informe

end;

end;

procedure TForm1.Button2Click(Sender: TObject); //Bouton qui arrete l'envoi
begin
timer1.Enabled:= false; //On arrete tout simplement le timer
end;

end.

//Sources du serveur

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPServer, ExtCtrls,jpeg; //Pas oublier jpeg

type
  TForm1 = class(TForm)
    tcp: TIdTCPServer;//Composant serveur TCP Indy
    Image1: TImage;
    procedure tcpExecute(AThread: TIdPeerThread);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.tcpExecute(AThread: TIdPeerThread); //procedure appellée lors de la 
var stream : tmemorystream; //réception des données  
jpg : tjpegimage; //Définition des variables
begin

jpg:= tjpegimage.Create; //Initialisation de jpg et stream
stream:= tmemorystream.Create;
athread.Connection.ReadStream(stream, -1, true); //réception du stream du début à la fin
Stream.Seek(0, soFromBeginning);  //On reset la position du pointer pour la lecture 
                                                      // Peut être remplacer par stream.position:=0;
jpg.LoadFromStream(stream);  //Chargement du stream dans la variable jpg
image1.Picture.Graphic:= jpg;  //Affichage de l'image contenue dans jpg sur le Timage
stream.free; //Purge de la mémoire du stream

end;

end.

Conclusion :


Voilà, pour précision, le composant serveur doit être activé pour pouvoir recevoir des informations, celà peut être fait de la maniere suivante "nomduserveur.active:=true;". Ce n'est pas apparent dans la source car je l'ai définit comme activé dans l'inspecteur d'objet avant l'execution. De même le port de communication n'est pas apparent dans la source non plus car je lui ai attribué une valeure arbitrairement dans l'inspecteur d'objet également.
Si vous avez des commentaire je suis preneur, sauf si c'est pour me dire que le code n'a rien à faire ici parce que c'est trop simple où je ne sais quoi (j'ai observé ca ici). Comme je l'ai précisé j'ai chercher une solution dans les sources proposée et je n'ai pas trouvé de sujet traitant de cette maniere relativement facile le problème. mauvaises langues s'abstenir merci.
Les commentaires du codes paraitront surement inutiles et dérisoires pour les programmeurs confirmés mais je suis sure que certains débutants aprécieront. C'est bon je me tais, j'ai fini lol.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
13
Date d'inscription
mercredi 29 novembre 2006
Statut
Membre
Dernière intervention
14 mai 2009

Est il possible d'envoyer la capture sans fair de connexion/deconnexion, c'est a dire on se connecte une foi aprés c'est tout?

Repondez moi sil vou plait c'est important
Messages postés
106
Date d'inscription
mardi 18 juin 2002
Statut
Membre
Dernière intervention
13 janvier 2007

askil2000 tu dois "forwarder" le port du serveur oú le client va se connecter en accédant au config du routeur (souvent en te connectant sur son adresse ip)
a+
Messages postés
92
Date d'inscription
lundi 8 mars 2004
Statut
Membre
Dernière intervention
12 avril 2010

Salut à tous, je voulais tout dabor te remercier pour ta source qui traite simplement un sujet compliqué ;) cependant j'ai un petit problème que je pose à tous bien-entendu. Je voudrais tout simplement (c vite di lol) me connecter au server et lui transmettre les données, sachant que ce dernier se trouve derrière un routeur :(
si qq'un peut me dire comment on fait un route sur un programme ?
j'ai déja été confronté à ce problème plusieurs fois, sachant que j'ai biensure les 2 adresses IP Internet exemple : 220.125.18.102 et adresse locale : 192.168.0.2 je souhaite tout simplement passer le routeur en me connectant au server directement. Merci à tous et surtout bonne prog !!!
Messages postés
161
Date d'inscription
dimanche 16 janvier 2005
Statut
Membre
Dernière intervention
26 janvier 2009

J'ai essayer autre chose qui je pense marcherais mieux : au faite webcam c'est Image1.
procedure TForm1.Button5Click(Sender: TObject);

var
Img:TPicture;
MemStream:TMemoryStream; // Déclaration des variables
JPG:TJPEGImage;
Bmp :TBitMap;
Rect:TRect;

begin

Img:=TPicture.Create;
Bmp := TBitMap .Create; //Initialisation des variables qui doivent l'être
MemStream:=TMemoryStream.Create;

Img.Bitmap.Assign(webcam);


JPG:=TJPEGImage.Create;
try
JPG.Assign(Img.Bitmap); //Conversion en jpg
JPG.CompressionQuality:=15;
Bmp.Width :=Jpg.Width -50;
Bmp.Height :=Jpg.Height -50;
Rect.Left :=0;
Rect.Top :=0;
Rect.Right :=Bmp.Width-1;
Rect.Bottom:=Bmp.Height-1;
Bmp.Canvas.StretchDraw(Rect,Jpg);
Jpg.Assign(Bmp);
jpg.savetostream(Memstream);//Chargement de l'image jpg dans le stream
finally
bmp.Free;
img.free;
JPG.Free;
try
with IdTCPClient1 do
begin

OpenWriteBuffer;
WriteStream(memstream);//Envoi du stream
CloseWriteBuffer;
memstream.Free;
disconnect; //Déconnexion
end;
except

end;

end;
end;
Ensuite il y a une classe d'exception EConvertError avec le message impossible d'affecter TImage à TBitmap
Pourrais tu m'aider j'en ai grandement besoin!!!!
Messages postés
161
Date d'inscription
dimanche 16 janvier 2005
Statut
Membre
Dernière intervention
26 janvier 2009

J'ai modifier un peu ton code comme ceci :
procedure TForm1.Button5Click(Sender: TObject);

var
Img:TPicture;
MemStream:TMemoryStream; // Déclaration des variables
JPG:TJPEGImage;
Bmp :TBitMap;
Rect:TRect;

begin

Img:=TPicture.Create;
Bmp := TBitMap .Create; //Initialisation des variables qui doivent l'être
MemStream:=TMemoryStream.Create;

Img.Bitmap.Width:=webcam.Width;
Img.Bitmap.Height:=webcam.Height;

JPG:=TJPEGImage.Create;
try
JPG.Assign(webcam); //Conversion en jpg
JPG.CompressionQuality:=15;
Bmp.Width :=Jpg.Width -50;
Bmp.Height :=Jpg.Height -50;
Rect.Left :=0;
Rect.Top :=0;
Rect.Right :=Bmp.Width-1;
Rect.Bottom:=Bmp.Height-1;
Bmp.Canvas.StretchDraw(Rect,Jpg);
Jpg.Assign(Bmp);
jpg.savetostream(Memstream);//Chargement de l'image jpg dans le stream
finally
bmp.Free;
img.free;
JPG.Free;
try
with IdTCPClient1 do
begin

OpenWriteBuffer;
WriteStream(memstream);//Envoi du stream
CloseWriteBuffer;
memstream.Free;
disconnect; //Déconnexion
end;
except

end;

end;
end;
Et ils me disent qu'iol y a une excpetion : impossible d'affecter un TImge à un TBitmap.
Afficher les 23 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.