Solved

accessing component property from another app

Posted on 1998-04-28
11
175 Views
Last Modified: 2010-04-06
I have written a non-visual component derived from TComponent, If placed in two different applications (not forms), how can I access a property in one app from the other app and vise versa? As well as within the same app?
It cannot use messages or Client/Server. I'm trying to keep it small.

NOTE: I'm using WIN95 and D3.
0
Comment
Question by:zolic
  • 5
  • 5
11 Comments
 
LVL 1

Expert Comment

by:pjdb
ID: 1338702
Can you map some memory to allow the two applications to read/write the same block of memory? If so, just create the component at runtime in a map area. The first launch application will create the block and the second will obtain access to it.

JDB
0
 

Author Comment

by:zolic
ID: 1338703
That's my problem, If I map the memory, how does the component in the other app find it. Keep in mind, these are different apps, so how do I find the component and the mapped memory? Also, The last apps' component needs to free the memory as well even if it didn't create it.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1338704
Hi Zolic

Would CreateFileMapping work (along with MapViewOfFile)?  You call CreateFileMapping with a unique name and it creates a shared area of memory which can be accessed by 2/more apps.  Each app accesses the memory area through the unique name you use.

(You can look at http://www.experts-exchange.com/topics/comp/lang/delphi/Q.10050013 to see my comments on how to use CreateFileMapping and MapViewOfFile if you're unsure.)

JB
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 1

Expert Comment

by:pjdb
ID: 1338705
Try the following :

type
  PMyComponent=^TMyComponent;
  TMyComponent=class(Tcomponent)
    {your stuff}
  end;

{.......}

procedure Tform1.FormCreate(Sender: TObject);

0
 
LVL 1

Expert Comment

by:pjdb
ID: 1338706
What you proposed looked like it might have merit, but I tried every way possible and still could not get the unit to work. Besides each component needs its own property.
Perhaps more information would be of some help.
Here is what I am trying to do:

The component looks for a previous instance of itself from another app OR from the same app.
If not found, it creates itself. If found, it gives all of the other components the pointer of its FReceived property.

Any component can transmit data to any or all other components.

Using a thread, when a components' FReceived property is changed, an OnChange event kicks in.

Perhaps Mutexes or semaphores?

0
 

Author Comment

by:zolic
ID: 1338707
The points go up every day until I can get this up and running.

0
 

Author Comment

by:zolic
ID: 1338708
I've try the code, and after correcting some mistakes i've found that i can't share objects..... I've modify the solution in order to share the data and not the all component. Now you have a MyRecord which is the data from the component, MyComponent the component itself and MyMap the structure of the share memory. The code gets more complex, but it seems to work (I've test with 2 instance of the same program and they are able to share data).

If you prefer, give your Email, i will send you the test program

JDB

Unit Unit1;

Interface

Uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

Type
  TForm1 = class(TForm)
    Edit1: TEdit; {area to test the data sharing}
    Button1: TButton; {display to memory}
    Button2: TButton; {memory to display}
    procedure FormClose(Sender: TObject; Var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  Private
    { Private declarations }
  Public
    { Public declarations }
  End;

Var
  Form1: TForm1;

Implementation

Uses
      Unit2;

{$R *.DFM}

Var
  MyComponent:TMyComponent;

Procedure TForm1.FormShow(Sender: TObject);
{Display the form}
Begin
      MyComponent:=TMyComponent.Create(Application);                          {Create the component}
      DoFileMapBegin;                                                                                                                              {map the common memory}
  MyComponent.data:=@MyMap^.Data;                                         {Put the pointor on the shared memory in the component}
  form1.caption:='Instance #' + IntToStr(MyMap.instance); {Change the title of the form to know which intance it is (usefull only for debuging)}
End;

Procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
{closing the form}
Begin
      MyComponent.data:=nil;      {Remove reference on the shared memory (Needed incase a component method start)}
      DoFileMapEnd;                                    {unmap the shared component}
  MyComponent.Free;       {Destroy the component}
End;

Procedure TForm1.Button1Click(Sender: TObject);
{get data from the Shared memory}
Begin
      Edit1.Text:=MyComponent.data^.Text;
End;

Procedure TForm1.Button2Click(Sender: TObject);
{put data to the shared memory}
Begin
      MyComponent.data^.Text:=Edit1.Text;
End;

End.      {Unit1}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Unit Unit2;

Interface

Uses
      Classes;

Type
      {Declaration of the data type of the component to be shared}
      PMyRecord=^TMyRecord;
      TMyRecord=record
        {put your stuff. I've put just a string to test it}
        text:ShortString;
  end;
  {Declaration of the component it self}
      TMyComponent=Class(TComponent)
            data:PMyRecord;
      End;
  {Declaration of the share memory type}
      PMyMap=^TMyMap;
      TMyMap=Record
            Instance:Byte;
            data:TMyRecord;
      End;

Procedure DoFileMapBegin;
procedure DoFileMapEnd;

Var
      MyMap:PMyMap;      {Pointor on the shared memory (you'd better use MyComponent.data^)}

implementation

Uses
      Forms, Windows;

var
  HMapping: THandle;

procedure DoFileMapBegin;
{map the common memory}
var
  llInit: Boolean;
  lInt: Integer;
begin
      {Map the memory}
      try
        HMapping:=CreateFileMapping($FFFFFFFF, nil, page_readwrite, 0, sizeof(TMyMap), pchar('hook memory share'));
        llInit:=(GetLastError()<>error_already_exists);
        if (hMapping=0) then
        begin
                  {Can''t Create Memory Map}
          Application.Terminate;
          exit;
        end;
        MyMap:=MapViewOfFile(HMapping, file_map_all_access, 0, 0, 0);
        if MyMap=nil then
        begin
                  {Can''t View Memory Map}
          CloseHandle(HMapping);
          Application.Terminate;
          exit;
        end;
      except
  end;
      Inc(MyMap^.Instance);      {Count the numbver of instances}
end;      {DoFileMapBegin}

procedure DoFileMapEnd;
{unmap the common memory}
begin
      Dec(MyMap^.Instance);      {Decount the instance}
  {Release memory}
  try
        if MyMap<>nil then
          UnMapViewOfFile(MyMap);
    if HMapping <> 0 then
          CloseHandle(HMapping);
  except
  end;
end;      {DoFileMapEnd}

End.      {Unit2}

0
 
LVL 1

Accepted Solution

by:
pjdb earned 210 total points
ID: 1338709
I've looked over your code. I receive the error in Unit2:

Published field 'data' not a class nor interface type

{Declaration of the component it self}
TMyComponent=Class(TComponent)
  data:PMyRecord;        <--------- ERROR
End;

My Email is nospam@pdq.net

I'll keep playing with it and if it works, I'll wait till tomorrow to grade you and give you 5 more points.

Thanks for the help. This one is over my head.

0
 

Author Comment

by:zolic
ID: 1338710
I got the app to work, and its almost what I want.
It works with one common property. I beleive I can design personal properties around it though. The last part is that all other apps need to know when the property changes. AND protection from collisions.
I think I can do this. I'll grade you tomorrow. Thanks.

BTW What's you email?

0
 

Author Comment

by:zolic
ID: 1338711
My Email is JeanDitBailleulP@usa.net

I think that the way to synchronize the apps is to use the SendMessage function from API.

JDB

0
 
LVL 1

Expert Comment

by:pjdb
ID: 1338712
Thank you pJDB, your answer will work out just fine. I gave you an A.
0

Featured Post

Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question