Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2022年06月17日] [更新 2022年06月17日] Delphi サンプルプログラム集
649_TTetheringManager を使用してアプリ間でデータを共有
動作確認等 Windows 10 ビルド 19043 Pro 64 bit + Delphi 10.4 Community VCL-32
Delphi XE6 以降用
649_TTetheringManager.zip [7.1 MB] 2022年06月17日版 (EXE 同梱)







TTetheringManager を使用してアプリ間でデータを共有


他のアプリkへデータを送信したり、データを共有する方法として、WM_COPYDATA メッセージによる送信や、共有メモリを使用する方法があります。
本ページのサンプルは、テザリング用の TTetheringManager と TTetheringAppProfile コンポーネントを使用する方法です。これらのコンポーネントは、Delphi XE6 で実装されました。



TTetheringManager と TTetheringAppProfile コンポーネントを使用する方法では、これらのコンポーネントを、データを提供する側と受け取る側の両方のプロジェクトのフォームに配置して使用します。
これらのコンポーネントは、コンポーネントパレットの [Tethering] タブにあります。






01_共有リソースとしてデータを提供するプログラムを作成


共有データを提供する側のプログラムを作成します。このプログラムは、本ページの全てのサンプルの動作確認に使用します。
本プログラムでは、共有データとして、Integer 型の整数値と TMemoryStream を実装します。Integer 型の整数は、TPanel の背景色の設定に使用します。TMemroyStream には TBitmap の画像データを格納します。


図1
設計時の画面

フォーム上の TTetheringAppProfile コンポーネントを選択して、オブジェクトインスペクタでプロパティを設定します。下図の説明を参考にしてください。

Group の名前は任意です。この名前のプログラムだけが本プログラムが提供するデータを利用できます。Manager は、リストから TTetheringManager コンポを選択します。
Resouces はリソースのコレクションです。入力部分をダブルクリックするか、[...] をクリックして、リソースの編集ダイアログを表示します。



図2
TTetheringAppProfile コンポーネントのオブジェクトインスペクタ
  • Group (任意の文字列)
    ここでは CommResTest
  • Manager
    TTetheringManager コンポをリストから選択
  • Resouces
    入力部をダブルクリック。
    または、[...] をクリック

リソースの編集ダイアログを表示したら、[新規追加] ボタンをクリックしてリソースを追加します。本サンプルではリソースを 2 つ使用しますから、2 回クリックします。
最初のリソースを選択してプロパティを下図のように設定します。

共有データとしてデータを提供する場合は Kind プロパティを Shared にします。
Name はリソース名です。この名前でリソースにアクセスします。
Integer 等の標準データの場合は、ResType を Data にします。



図3
1 番目のリソースの設定
  • Kind
    Shared (デフォルト) をリストから選択
  • Name (任意の文字列)
    ここでは color
  • ResTypea
    リストから Data (デフォルト) を選択

2 番目のリソースを選択してプロパティを下図のように設定します。標準データ型(Boolean, Integer, Int64, Single, Double, String) 以外の場合は、ResType の値を Stream にします。


図4
2 番目のリソースの設定
  • Kind
    Shared (デフォルト) をリストから選択
  • Name (任意の文字列)
    ここでは image
  • ResTypea
    リストから Stream を選択

フォームのユニットのコードを以下のようにします。コンパイルして EXE を作成します。

本ページのサンプルでは、このプログラムを共有データの提供 (送信) 専用としています。データの提供 (送信) か受信かは、リソースの Kind プロパティで決まります。Kind プロパティの値を Mirror にすれは、他のアプリからのデータ受信用のリソースになります。提供 (送信) と受信用のリソースを実装すれば、同じ Group のアプリ間での双方向通信が可能になります。
同じリソース名のリソースを、提供 (送信) と受信兼用にはできません。



リスト1
共有リソースとしてデータを提供する側のプグラムのコード
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IPPeerClient, IPPeerServer,
  System.Tether.Manager, System.Tether.AppProfile, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Panel1: TPanel;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//  接続処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  TetheringManager1.AutoConnect(3000);
end;

//=============================================================================
//  [color 値のセット]
//  リソースの型は Integer
//  このボタンをクリックしてから他のアプリでデータを取得する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LColor : Integer;
begin
  LColor := RGB(Random(255), Random(255), Random(255));
  Panel1.ParentBackground := False;
  Panel1.Color := LColor;

  TetheringAppProfile1.Resources.FindByName('color').Value := LColor;
end;

//=============================================================================
//  [画像をセット]
//  このボタンをクリックしてから他のアプリでデータを取得する
//
//  標準データ型(Boolean, Integer, Int64, Single, Double, String) 以外は
//  メモリストリームを使用する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LStream : TMemoryStream;
  lBitmap : TBitmap;
begin
  Image1.Picture.Assign(nil);

  LStream := TMemoryStream.Create;
  lBitmap := TBitmap.Create;
  try
    LStream.Clear;
    lBitmap.LoadFromFile('HANDSHAK.BMP');
    lBitmap.SaveToStream(LStream);

    Image1.Canvas.Draw(0, 0, lBitmap);

    TetheringAppProfile1.Resources.FindByName('image').Value := LStream;
  finally
    FreeAndNil(lBitmap);
    FreeAndNil(LStream);
  end;
end;

//=============================================================================
//  [別画像をセット]
//  このボタンをクリックしてから他のアプリでデータを取得する
//
//  標準データ型(Boolean, Integer, Int64, Single, Double, String) 以外は
//  メモリストリームを使用する
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  LStream : TMemoryStream;
  lBitmap : TBitmap;
begin
  Image1.Picture.Assign(nil);

  LStream := TMemoryStream.Create;
  lBitmap := TBitmap.Create;
  try
    LStream.Clear;
    lBitmap.LoadFromFile('CHEMICAL.BMP');
    lBitmap.SaveToStream(LStream);

    Image1.Canvas.Draw(0, 0, lBitmap);

    TetheringAppProfile1.Resources.FindByName('image').Value := LStream;
  finally
    FreeAndNil(lBitmap);
    FreeAndNil(LStream);
  end;
end;

end.




02_Integer 型の共有リソースデータを取得するプログラム


Integer 型のリソースの値を受け取って処理するサンプルです。
本サンプルでは、Integer 型の値を TPanel の背景色の値として使用します。

フォームに TTetheringManager と TTetheringAppProfile を配置します。TTetheringAppProfile のプロパティを上のサンプルと同じにします。リソースを下図のように設定します。
共有データを受け取る側なので、Kind プロパティを Mirror にします。Name は、受け取るデータのリソース名です。


図5
リソースの設定
  • Kind
    リストから Mirror を選択
  • Name
    リソース名。color にする
  • ResType
    リストから Data を選択

[備考]
データの提供側と受け取る側でリソースのプロパティの値が異なるのは Kind プロパティだけです。このことから、最初のサンプルのフォームから、TTetheringManager と TTetheringAppProfile コンポーネントをコピーして使用する方が手っ取り早いと言えます。そうすれば、Kind プロパティの値を変更するだけの操作となります。



図の下がサンプルのコードです。コンパイルして EXE を作成します。
最初のサンプルの EXE を起動して [color 値をセット] をクリックします。次に、本サンプルの EXE を起動します。接続には、わずかですが時間がかかるので、一呼吸おいて [color 値を取得] ボタンをクリックします。本プログラムの TPanel の背景色が、共有データ提供元の TPanel の背景色と同じになることが確認できます。


図6
実行結果
  • 以下の順でクリック
    [color 値をセット]
    [color 値を取得]

リスト2
Integer 型の共有リソースデータを取得する
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IPPeerClient, IPPeerServer,
  System.Tether.Manager, System.Tether.AppProfile, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    Button1: TButton;
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//  接続処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  TetheringManager1.AutoConnect(3000);
end;

//=============================================================================
//  [取得]
//  リソースの型は Integer
//  リソース提供側でリソースにデータをセットしてからこのボタンをクリックする
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LColor : Integer;
begin
  if TetheringManager1.RemoteProfiles.Count = 0 then begin
     // 接続されていない場合
     Exit;
  end;

  LColor := TetheringAppProfile1.Resources.FindByName('color').Value.AsInteger;

  Panel1.ParentBackground := False;
  Panel1.Color := LColor;
end;

end.




03_画像の共有リソースデータを取得するプログラム


TBitmap のデータを取得して処理するサンプルです。
共有データの提供側では、TBitmap のデータをメモリストリームに格納しています。このメモリストリームから TBitmap のデータを取り出します。

フォームに TTetheringManager と TTetheringAppProfile を配置します。TTetheringAppProfile のプロパティを最初のサンプルと同じにします。リソースを下図のように設定します。
共有データを受け取る側なので、Kind プロパティを Mirror にします。Name は、受け取るデータのリソース名です。



図7
リソースの設定
  • Kind
    リストから Mirror を選択
  • Name
    リソース名。image にする
  • ResType
    リストから Stream を選択

図の下がサンプルのコードです。コンパイルして EXE を作成します。
最初のサンプルの EXE を起動して [画像をセット] をクリックします。次に、本サンプルの EXE を起動します。接続には、わずかですが時間がかかるので、一呼吸おいて [画像を取得] ボタンをクリックします。共有データ提供元の 画像と同じ画像が TImage に描画できることが確認できます。



図8
実行画面
  • 以下の順で操作
    [画像をセット]
    [画像を取得]

リスト3
画像の共有リソースデータを取得
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IPPeerClient, IPPeerServer,
  System.Tether.Manager, System.Tether.AppProfile, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    Button1: TButton;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//  接続処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  TetheringManager1.AutoConnect(3000);
end;

//=============================================================================
//  [取得]
//  データはメモリストリーム
//  リソース提供側でリソースにデータをセットしてからこのボタンをクリックする
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LStream : TMemoryStream;
  lBitmap : TBitmap;
begin
  Image1.Picture.Assign(nil);
  if TetheringManager1.RemoteProfiles.Count = 0 then begin
     // 接続されていない場合
     Exit;
  end;

  LStream := TMemoryStream.Create;
  lBitmap := TBitmap.Create;
  try
    if TetheringAppProfile1.Resources.FindByName('image').Value.AsStream = nil
      then Exit;
    LStream.LoadFromStream
      (TetheringAppProfile1.Resources.FindByName('image').Value.AsStream);

    LStream.Position := 0;
    lBitmap.LoadFromStream(LStream);
    Image1.Canvas.Draw(0, 0, lBitmap);
  finally
    FreeAndNil(lBitmap);
    FreeAndNil(LStream)
  end;
end;

end.




04_リソースのイベントを使用して共有データを自動受信


共有データの提供元でテータを設定したら、自動的にそのデータを受信するサンプルです。
ソースのイベントを利用します。

Integer 型のデータ取得のサンプルのリソースに以下のイベントを追加します。リソース名が color のリソースが対象です。ただし、本サンプルでは、元のサンプルから Button1 クリックのコードを削除しています。



図9
リソースにイベントを追加

下図が実行結果です。
共有データの提供側で [color 値をセット] をクリックすると、本サンプルの TPanel の背景色も変わり、同じ色になります。



図10
実行画面

リスト4
リソースのイベントを使用して共有データを自動受信
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IPPeerClient, IPPeerServer,
  System.Tether.Manager, System.Tether.AppProfile, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure TetheringAppProfile1Resources0ResourceReceived(
      const Sender: TObject; const AResource: TRemoteResource);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//  接続処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  TetheringManager1.AutoConnect(3000);
end;

//=============================================================================
//  共有リソースの提供側でリソースに値をセットすると発生するイベント
//  ここでは、リソース名 color の値が変更された時を検出
//
//  このイベントはリソース単位で発生する
//  このイベントを各リソースで共有すればリソースごとの処理が可能
//=============================================================================
procedure TForm1.TetheringAppProfile1Resources0ResourceReceived(
  const Sender: TObject; const AResource: TRemoteResource);
var
  LColor : Integer;
begin
  if AResource.Name = 'color' then begin
    LColor := AResource.Value.AsInteger;
    Panel1.ParentBackground := False;
    Panel1.Color := LColor;
  end;
end;

end.




05_[ Windows セキュリティの重要な警告 ] のダイアログ


本ページのサンプルの EXE を起動すると、下図のセキュリティの重要な警告のダイアログが現れます。今回は、[プライベートネットワーク ...] だけをチェックしてアクセスを許可しました。
これでファイアウォールが無効になって、次回からは下図のダイアログは現れません。


図11

添付の plSetAppFirewallState.exe を使用すると、ファイアウォールを有効にして、上のダイアログが現れるようにすることができます。
[EXE Path] の入力欄に EXE のフルパスを入力して、[Firewall ON] をクリックします。

[Application LIst] をクリックすると、ファイアウォールの設定ダイアログを表示します。そのダイアログで設定することもできます。[設定の変更] をクリックしてからプログラムを選択して [削除] ボタンをクリックします。EXE のフルパスは、[詳細] ボタンをクリックすると確認できます。
ファイアウォールを有効 (ON) にした EXE は、このリストから削除されています。



図12
ファイアウォールの設定
  • EXE 起動中も設定可能

下図の左のフォームは、最初のサンプルを起動して [別の画像をセット] しています。右のフォームは、バーチャルマシンの Windows 7 で、画像を取得するサンプルを起動して取得しています。
このように、上のダイアログでファイアウォールを無効にすれば、LAN 上の別のコンピュータのアプリにもデータを送信することができます。



図13




06_Socket エラーのダイアログ


本ページのサンプルのプロジェクトのコンパイルを開始すると、下図の Socket エラーが発生することがあります。これは、他のサンプルの EXE が起動している時に発生します。
この場合は、[継続] をクリックしてコンパイルをつ続けます。このダイアログは、複数回現れます。


図14