Cómo monetizar tus apps



Delphi nos lo pone fácil para monetizar las apps.
Nos ofrece un componente llamado tBannerAd para poner un banner con publicidad con una serie de propiedades y métodos que nos permiten abstraernos de toda la complejidad que conlleva.
Para utilizarlo simplemente colocamos el componente en nuestro form y lo llamamos de esta forma.

PROCEDURE TfOpciones.Publicidad(BannerAd1: TBannerAd);
BEGIN
  BannerAd1.AdUnitID := CODIGO_PUBLICIDAD;
  BannerAd1.LoadAd;
  BannerAd1.Visible := True;
END;

Los permisos que tenemos que activar son:
- Access network state 
- Internet


y además tenemos que marcar el check "Admob service" desde el menú Project-Options-Entitlement List.


Si os habéis fijado, en el código del procedimiento para utilizar el componente hay una constante llamada "CODIGO_PUBLICIDAD" ¿de dónde viene? os preguntaréis

Pues para obtenerla hay que abrir una cuenta en Admob "https://www.google.es/admob/". (Admob es una empresa que gestiona publicidad para apps y que por cierto ha sido comprada por Google).
A continuación hay que seleccionar una de las apps que has realizado, que deberá estar subida previamente a la Play Store de Google.



Una vez que la veas en tu panel de control de Admob tienes que añadir un bloque de anuncios.

Cada bloque de anuncios va identificado con un número de control, algo así como "ca-app-pub-XXXXXXXXXXXXXXX / XXXXXXX ", pues ése es el "código de publicidad" que tienes que poner.
Otro detalle,  para subir apps a la Play Store de Google tienes que abrir una cuenta de desarrollador y pagar 25€ en pago único para siempre, si lo quieres hacer para IOS tienes que pagar 100€ al año.

Una vez que lo tengas todo preparado Google te pagará cada vez que un usuario haga clic sobre el banner de publicidad (se acumulan los ingresos hasta que lleguen a 75€).







Comandos que desconocías de Windows 8

Monitor de confiabilidad


Si has notado que tu PC va lento o que de repente deja de estar estable, se cuelga con facilidad, etc., puedes utilizar el Monitor de Confiabilidad de Windows.

Continuamente Windows monitoriza todo lo que ocurre en tu PC y va creando un historial de absolutamente todos los errores que se producen (tanto de aquellos que notas inmediatamente porque se produce un mensaje de error, como de aquellos que silenciosamente se producen y dejan sólo un rastro en el log de eventos de Windows).

Para utilizarlo tienes que hacer clic sobre el botón de Inicio y en la pantalla siguiente, en la "lupa" buscar el término "confiabilidad".


Abajo te aparecerá el ítem "Ver historial de confiabilidad", haces clic sobre él y te verás el informe que te genera Windows (tendrás que esperar un poco hasta que se genere).



Diagnóstico de eficiencia energética

¿Sabías que Windows puede hacer un diagnóstico de la eficiencia energética de tu PC?

En el mismo te da detalles sobre tu configuración actual, las categorías que no funcionan bien o se han configurado de una forma incorrecta y su posible solución.

Para activarlo tienes que abrir un CMD (símbolo de sistema) con permisos de Administrador y teclear:

powercfg -energy


Después el sistema espera 60 segundos para monitorizar tu PC y a continuación te genera un documento llamado "energy-report.html" en el directorio c:\windows\system32  
Quizás te pueda interesar:

 




Guía de marketing para apps

Amigos, os comparto este infografía que muestra de una forma muy clara los pasos que se deben dar para promocionar una app.
Ya sabéis que con RAD STUDIO se pueden realizar aplicaciones de todo tipo para Android y para IOS, es lo que llamamos aplicaciones multidispositivo, tú programas 1 vez y tu código funciona en múltiples plataformas.
Además se tiene la opción de monetizarlas de varias maneras:
- Incluyendo un banner publicitario (utilizando el componente tBannerAd), con lo que obtenemos un rendimiento económico cada vez que los usuarios hagan clic sobre él.
- Activando la opción de compras dentro la app (componente tInAppPurchase).

Infografía: http://www.bluecaribu.com/marketing-apps/ 






Funciones para calcular el hash de strings y archivos

A continuación tienen una serie de funciones para calcular el hash (MD5, SHA1, SHA224, SHA256, SHA 384, SHA 512, BobJenkins) de strings y de archivos.
Probado en RAD Studio 10 - Tokyo.
Recordar que hay que añadir en el bloque "USES" la unit "system.hash"


function GetStrHashMD5(Str: String): String;
var
  HashMD5: THashMD5;
begin
    HashMD5 := THashMD5.Create;
    HashMD5.GetHashString(Str);
    result := HashMD5.GetHashString(Str);
end;
 
function GetStrHashSHA1(Str: String): String;
var
  HashSHA: THashSHA1;
begin
    HashSHA := THashSHA1.Create;
    HashSHA.GetHashString(Str);
    result := HashSHA.GetHashString(Str);
end;
 
function GetStrHashSHA224(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    result := HashSHA.GetHashString(Str,SHA224);
end;
 
function GetStrHashSHA256(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    result := HashSHA.GetHashString(Str,SHA256);
end;
 
function GetStrHashSHA384(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    result := HashSHA.GetHashString(Str,SHA384);
end;
 
function GetStrHashSHA512(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    Result := HashSHA.GetHashString(Str,SHA512);
end;
 
function GetStrHashSHA512_224(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    Result := HashSHA.GetHashString(Str,SHA512_224);
end;
 
function GetStrHashSHA512_256(Str: String): String;
var
  HashSHA: THashSHA2;
begin
    HashSHA := THashSHA2.Create;
    HashSHA.GetHashString(Str);
    Result := HashSHA.GetHashString(Str,SHA512_256);
end;
 
function GetStrHashBobJenkins(Str: String): String;
var
  Hash: THashBobJenkins;
begin
    Hash := THashBobJenkins.Create;
    Hash.GetHashString(Str);
    Result := Hash.GetHashString(Str);
end;
Ejemplos del cálculo de hash en archivos:
function GetFileHashMD5(FileName: WideString): String;
var
  HashMD5: THashMD5;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashMD5 := THashMD5.Create;
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashMD5.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashMD5.HashAsString;
end;
 
function GetFileHashSHA1(FileName: WideString): String;
var
  HashSHA: THashSHA1;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA1.Create;
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
 
function GetFileHashSHA224(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA224);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashSHA256(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA256);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashSHA384(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA384);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashSHA512(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA512);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashSHA512_224(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA512_224);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashSHA512_256(FileName: WideString): String;
var
  HashSHA: THashSHA2;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  HashSHA := THashSHA2.Create(SHA512_256);
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          HashSHA.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := HashSHA.HashAsString;
end;
 
function GetFileHashBobJenkins(FileName: WideString): String;
var
  Hash: THashBobJenkins;
  Stream: TStream;
  Readed: Integer;
  Buffer: PByte;
  BufLen: Integer;
begin
  Hash := THashBobJenkins.Create;
  BufLen := 16 * 1024;
  Buffer := AllocMem(BufLen);
  try
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      while Stream.Position < Stream.Size do
      begin
        Readed := Stream.Read(Buffer^, BufLen);
        if Readed > 0 then
        begin
          Hash.update(Buffer^, Readed);
        end;
      end;
    finally
      Stream.Free;
    end;
  finally
    FreeMem(Buffer)
  end;
  result := Hash.HashAsString;
end;


Compartir datos por medio de un fichero en memoria en Delphi

Hay varias maneras de hacerlo. 
En este truco, usaremos un fichero de memoria para poder compartir una zona de memoria, y poder así enviar datos de una aplicación a la otra. 

Crearemos dos aplicaciones, una la que escriba los datos y otra, la que los reciba. 
En concreto, haremos que el texto de un TEdit se vea el un Label de la otra aplicación.


Aplicacion que escribe los datos:




  • Crea una nueva aplicacion 
  • Pon un TEdit en la form (Edit1) 
  • Cambia el código de la unit de la form por éste: 

     unit Unit1;
    
     interface
    
     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       StdCtrls;
    
     type
       TForm1 = class(TForm)
         Edit1: TEdit;
         procedure FormCreate(Sender: TObject);
         procedure Edit1Change(Sender: TObject);
         procedure FormDestroy(Sender: TObject);
       private
         { Private declarations }
       public
         { Public declarations }
       end;
    
     type
      TCompartido = record
        Numero: Integer;
        Cadena: String[20];
      end;
      PCompartido   =^TCompartido;
    
     var
       Form1      : TForm1;
       Compartido : PCompartido;
       FicheroM   : THandle;
     implementation
    
     {$R *.DFM}
    
     procedure TForm1.FormCreate(Sender: TObject);
     begin
       Edit1.MaxLength:=20;
       {Creamos el fichero de memoria}
       FicheroM:=CreateFileMapping( $FFFFFFFF,
                                   nil,
                                   PAGE_READWRITE,
                                   0,
                                   SizeOf(TCompartido),
                                   'MiFichero');
        {Si no se creó el fichero, lo llenamos de ceros}
        if FicheroM=0 then
          raise Exception.Create( 'Error al crear el fichero'+
                                  '/Error while create file');
    
        {Direccionamos nuestra estructura al fichero de memoria}
        Compartido:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);
    
        {Escribimos datos en el fichero de memoria}
        Compartido^.Numero:=732;
        Compartido^.Cadena:=Edit1.text;
     end;
    
     procedure TForm1.Edit1Change(Sender: TObject);
     begin
       Compartido^.Cadena:=Edit1.Text;
     end;
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       {Cerramos la vista del fichero}
       UnmapViewOfFile(Compartido);
       {Cerramos el fichero}
       CloseHandle(FicheroM);
     end;
    
     end.
    




    Aplicacion que leera los datos:


  • Crea una nueva aplicacion 
  • Pon un TTimer (Timer1) y un TLabel (Label1) en tu form 
  • Desactiva el Timer1 (propiedad Enabled=FALSE); 
  • Cambia el código de la unit de la form por este: 

     unit Unit1;
    
     interface
    
     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       ExtCtrls, StdCtrls;
    
     type
       TForm1 = class(TForm)
         Label1: TLabel;
         Timer1: TTimer;
         procedure FormCreate(Sender: TObject);
         procedure Timer1Timer(Sender: TObject);
         procedure FormDestroy(Sender: TObject);
       private
         { Private declarations }
       public
         { Public declarations }
       end;
    
     type
      TCompartido = record
        Numero: Integer;
        Cadena: String[20];
      end;
      PCompartido   =^TCompartido;
    
     var
       Form1       : TForm1;
       Compartido  : PCompartido;
       FicheroM    : THandle;
    
     implementation
    
     {$R *.DFM}
    
     procedure TForm1.FormCreate(Sender: TObject);
     begin
       {Miramos si existe el fichero}
       FicheroM:=OpenFileMapping(FILE_MAP_READ,False,'MiFichero');
       {Si no existe, Error}
       if FicheroM=0 then
         raise Exception.Create('Error');
    
        Compartido:=MapViewOfFile(FicheroM,FILE_MAP_READ,0,0,0);
        Timer1.Enabled:=TRUE;
     end;
    
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       UnmapViewOfFile(Compartido);
       CloseHandle(FicheroM);
     end;
    
     procedure TForm1.Timer1Timer(Sender: TObject);
     begin
       Label1.Caption:=Compartido^.Cadena;
     end;
    
    
     end.
    



    Ahora compila y arranca la primera aplicacion y compila y arranca la segunda.
    Lo que escribas en el Edit de una aplicacion saldrá en el Label de la otra.

    El funcionamiento es el siguiente:

    En la primera aplicación, creamos un fichero de memoria mediante: 



       {Creamos el fichero de memoria}
       {Create the memory file}
       FicheroM:=CreateFileMapping( $FFFFFFFF,
                                   nil,
                                   PAGE_READWRITE,
                                   0,
                                   SizeOf(TCompartido),
                                   'MiFichero');
    



    que lo que hace es permitirnos compartir una zona de memoria.
    Para facilitarnos el acceso a esta zona de memoria, la manejaremos mediante una estructura que nos hemos creado a tal efecto: 




     type
      TCompartido = record
        Numero: Integer;
        Cadena: String[20];
      end;
      PCompartido   =^TCompartido;
    



    Aqui debes tener cuidado... la estructura debe tener un tamaño definido, esto quiere decir... que no podrías hacer una estructura de este tipo:



     type
      TCompartido = record
        Numero: Integer;
        Cadena: String;
      end;
      PCompartido   =^TCompartido;
    



    ya que la longitud de esta estructura dependería de la longitud de la string contenida en 'Cadena'.
    Una vez creado el fichero, direccionamos un puntero a la zona de memoria a la que apunta el fichero, para poder escribir los datos en nuestra estructura: 



     {Direccionamos nuestra estructura al fichero de memoria}
     {Addressing the memory zone with our structure}
     Compartido:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);
    



    De tal manera que todo lo que escribamos a través de nuestra estructura, se escribirá en la zona de memoria del fichero de memoria, y será accesible para otras aplicaciones que mapeen el mismo fichero: 


     {Escribimos datos en el fichero de memoria}
     {Wrire data in the memory file}
     Compartido^.Numero:=732;
     Compartido^.Cadena:=Edit1.text;
    





    Ahora veamos cómo leer estos datos desde otra aplicación Delphi:
    En este caso, en lugar de crear el fichero, lo abriremos para lectura. 



       {Miramos si existe el fichero}
       {Look for the file}
       FicheroM:=OpenFileMapping(FILE_MAP_READ,False,'MiFichero');
       {Si no existe, Error}
       {If don't exists... error}
       if FicheroM=0 then
         raise Exception.Create('Error');
    



    y generamos un error si no hemos sido capaces de abrirlo (por ejemplo porque no haya sido creado por la otra aplicación)

    Una vez que el fichero ha sido abierto, activamos el Timer1, para que cada x tiempo refresque el Label1 con la cadena recibida desde la otra aplicación a través del fichero de memoria: 



     procedure TForm1.Timer1Timer(Sender: TObject);
     begin
       Label1.Caption:=Compartido^.Cadena;
     end;
    



    Ah, por último, decir que debemos cerrar tanto la vista del fichero de memoria como el propio fichero de memoria cuando terminemos de usarlos. Por ejemplo, en el evento OnDestroy de la form: 


     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       UnmapViewOfFile(Compartido);
       CloseHandle(FicheroM);
     end;
    








    Aqui está un nuevo ejemplo, basado en el anterior pero que utiliza un mensaje propio para avisar a la otra aplicación de que hay nuevos datos:

    Enviado por: Arturo García (sArthur7@teleline.es) 


    Aplicacion que escribe los datos 




     unit Trans;
    
     interface
    
     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       StdCtrls;
    
     CONST
       WM_TRANSFER = WM_USER + 1;  // Definimos un mensaje
    
     type
      PCompartido =^TCompartido;
      TCompartido = record
        Manejador1: Cardinal;
        Manejador2: Cardinal;
        Numero    : Integer;
        Cadena    : String[20];
      end;
    
     (*  -------------------------------------- *)
    
     type
       TForm1 = class(TForm)
         Edit1: TEdit;
         procedure FormCreate(Sender: TObject);
         procedure Edit1Change(Sender: TObject);
         procedure FormDestroy(Sender: TObject);
         procedure Edit1KeyDown(Sender: TObject; var Key: Word;
           Shift: TShiftState);
       private
         Compartido : PCompartido;
         FicheroM   : THandle;
       public
         { Public declarations }
       end;
    
     var
       Form1: TForm1;
    
     implementation
    
     {$R *.DFM}
    
     procedure TForm1.FormCreate(Sender: TObject);
     begin
        Edit1.MaxLength:=20;
       {Creamos el fichero de memoria}
       FicheroM:=CreateFileMapping( $FFFFFFFF,nil,PAGE_READWRITE,0,
                                   SizeOf(TCompartido),'MiFichero');
        {Si no se creó el fichero, lo llenamos de ceros}
        if FicheroM=0 then
          raise Exception.Create( 'Error al crear el fichero'+
                                  '/Error while create file');
    
        {Direccionamos nuestra estructura al fichero de memoria}
        Compartido:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);
    
        {Escribimos datos en el fichero de memoria}
        Compartido^.Manejador1:=Handle;
        Compartido^.Numero:=777;
        Compartido^.Cadena:=Edit1.text;
     end;
    
     procedure TForm1.Edit1Change(Sender: TObject);
     begin
       Compartido^.Cadena:=Edit1.Text;
     end;
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
      {Cerramos la vista del fichero}
       UnmapViewOfFile(Compartido);
       {Cerramos el fichero}
       CloseHandle(FicheroM);
     end;
    
     procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
       Shift: TShiftState);
     begin
      if key = 13 then Begin
         if compartido^.Manejador2 <> 0 then
          PostMessage(Compartido^.Manejador2, WM_TRANSFER,0, 0);
      end;
     end;
    
     end.
    




    Aplicacion que leera los datos 




     unit Recep;
    
     interface
    
     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       StdCtrls;
    
     const
       WM_TRANSFER = WM_USER + 1;
    
     type
      PCompartido =^TCompartido;
      TCompartido = record
        Manejador1: Cardinal;
        Manejador2: Cardinal;
        Numero    : Integer;
        Cadena    : String[20];
      end;
    
     type
       TForm1 = class(TForm)
         Label1: TLabel;
         procedure FormCreate(Sender: TObject);
         procedure FormDestroy(Sender: TObject);
       private
         Compartido : PCompartido;
         FicheroM   : THandle;
         procedure Reciviendo(var Msg: TMessage); message WM_TRANSFER;
    
       public
         { Public declarations }
       end;
    
     var
       Form1: TForm1;
    
     implementation
    
     {$R *.DFM}
    
     procedure Tform1.Reciviendo(var Msg: TMessage);
     begin
      label1.Caption:=compartido^.Cadena;
     end;
    
     procedure TForm1.FormCreate(Sender: TObject);
     begin
       {Miramos si existe el fichero}
       FicheroM:=OpenFileMapping(FILE_MAP_READ,False,'MiFichero');
       {Si no existe, Error}
       if FicheroM=0 then
         raise Exception.Create('Error');
         Compartido:=MapViewOfFile(FicheroM,FILE_MAP_READ,0,0,0);
         compartido^.Manejador2:=Handle;
     end;
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       UnmapViewOfFile(Compartido);
       CloseHandle(FicheroM);
     end;
    
     end.
     
  • Ref: http://www.trucomania.org/trucomania/truco.cgi?381&esp



    También te puede interesar:

    App para mostrar moléculas en 3D