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