Solved

Data Exchange Between Two Apps

Posted on 1998-09-15
30
277 Views
Last Modified: 2010-04-06
Hi All,

I need to be able to pass data from one program to another running on the same system.  I dont want to use drop files or UDP.  I dont mind using the registry, but the host application needs to be notifed when the registry is updated.

Is there any way I can do this?  DDE seems like a viable option, but Im stuffed if I can work out how to use it (manaul?  Not worth the paper its printed on!).

I know there is a message which you can post to the system when you update the registry, but I cant remember where I saw it.  THis could be another option.

Any help would be REALLY appreciated!!!

Stuart.
0
Comment
Question by:Stuart_Johnson
  • 13
  • 9
  • 7
  • +1
30 Comments
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339817
Oh!  I thought I better add this too - the data is just an integer - nothing more.  Its just an identifier.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339818
Hi Stu

Do you have the window handle of the second app?  If you do you can send a Windows message to the 2nd app.

E.g.
const  WM_MY_MSG =  WM_USER + 1234;

PostMessage(OtherAppHandle, WM_MY_MSG, YourInt, 0);

Cheers,
JB
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339819
Hi JB,

Thanks for the quick response.  No,  I dont have its handle.  Is there an easy way to retrieve the handle?

How do I get the posted message from within the host app?  Just watch for WM_MY_MSG???

Thanks again,

Stuart.
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 5

Expert Comment

by:inter
ID: 1339820
Hi all,
I want to extend what Jim suggested as follows

BroadcastSystemMessage(BSF_POSTMESSAGE, BSM_APPLICATIONS, WM_MY_MSG, YourInt1, YourInt2);

regards, igor
0
 
LVL 5

Expert Comment

by:inter
ID: 1339821
In your delphi help just search for OnMessage event of the TApplication and look its example, it is just you seek...
igor
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339822
Yes, it seems Inter has already provided my response.

TApplication's OnMessage has the following parameters:
    var Msg: TMsg; var Handled: Boolean

You would use Msg to see if Msg.Message = WM_MY_MSG then get the integer from Msg.WParam.

JB
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339823
Hi Inter,

I dont know if Im thick or not, but I just copied the BroadCastSystemMessage code into my app to see what I could come up with, and I cant compile it.  Its saying "Incompatible Types: Integer and PDWORD".  I have copied what you said exactly, and the help file says that BSM_APPLICATIONS is the recipients' parameter type.

Any ideas???

Im gunna be a pain in the butt and ask for some code here :)  I've never worked with messages, except for limiting the size of windows.  This is all totally new territory.

Stu.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1339824
I don't like BroadcastSystemMessage.   :-(
There's another possibility. The program that is to receive the message could write his main window handle to registry at initialization and delete it again at finalization. So the program that has to send the message could just read the handle from the registry and then address the message directly to the receiving window.

There are several disadvantages of the broadcast method:
(1) Broadcasting messages is a little bit slower.
(2) Broadcasting is a little bit dangerous because there could be another application that uses exactly this message number and make problems receiving your message.
(3) With broadcasting you can't wait for response (that means you can't use something like SendMessage).
(4) And because of that you can't use the message WM_COPYDATA which is quite useful if you need to transport more than just an integer.

Hope this help... Madshi.
0
 
LVL 5

Expert Comment

by:inter
ID: 1339825
Anyway I try to explain,
var
  Temp : DWord;
begin
  Temp := BSM_APPLICATIONS;
  //now
  BroadcastSystemMessage(BSM_POST, @Temp, etc.....)
end;
I hope this solves...
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339826
Inter.

I managed that bit just after I posted the message - sorry :)

So, how do I recieve it at the other end??? Do I use something like:

private
   Procedure WMDataSent(var Msg: TMessage); message WM_MY_MSG;

If so, what do I test for in the procedure??

Sorry to sound so dumb, but as I said, this is all new ground to me.

Stu
0
 
LVL 5

Expert Comment

by:inter
ID: 1339827
Just do the following(modified from delphi help). Add AppMessage to your public part as
  TForm1 = class(TForm)
  ....
  public:
   procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  end;

then in implementation

procedure TForm1.FormCreate(Sender: TObject);

begin
  Application.OnMessage := AppMessage;
end;

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if Msg.message = WM_MY_MSG then
  begin
    //your ints are in Msg.wparam and Msg.lparam
   // do what you want here
   
    // we handle only this message so others are processed normally
    Handled := True;
  end;
  { for all other messages, Handled remains False }
  { so that other message handlers can respond }
end;
igor
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339828
Me again :)

Ok..  I have that in the code.  Still no luck. Heres what Im doing (cut down form)..
  public
     procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
    { Public declarations }
  end;

var
  Form1: TForm1;

Const
   WM_MY_MSG = WM_USER+1234;


implementation

{$R *.DFM}

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
   if Msg.message = WM_MY_MSG then begin
      Handled := True;
      ShowMessage(IntToStr(Msg.wParam));
      ShowMessage(IntToStr(Msg.lParam));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var P: DWord;
    Int1,
    Int2: Integer;

begin
   P := BSM_APPLICATIONS;
   Int1 := 0;
   Int2 := 1;
   BroadcastSystemMessage(BSF_POSTMESSAGE, @P, WM_MY_MSG, Int1, Int2);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMessage;
end;

What have I dont wrong???

Thanks,

Stu.
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339829
Me again :)

Ok..  I have that in the code.  Still no luck. Heres what Im doing (cut down form)..
  public
     procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
    { Public declarations }
  end;

var
  Form1: TForm1;

Const
   WM_MY_MSG = WM_USER+1234;


implementation

{$R *.DFM}

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
   if Msg.message = WM_MY_MSG then begin
      Handled := True;
      ShowMessage(IntToStr(Msg.wParam));
      ShowMessage(IntToStr(Msg.lParam));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var P: DWord;
    Int1,
    Int2: Integer;

begin
   P := BSM_APPLICATIONS;
   Int1 := 0;
   Int2 := 1;
   BroadcastSystemMessage(BSF_POSTMESSAGE, @P, WM_MY_MSG, Int1, Int2);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMessage;
end;

What have I dont wrong???

Thanks,

Stu.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339830
Oops, you can't broadcast msgs > WM_USER.

Try setting WM_MY_MSG to WM_USER - 1 and it should work.  Of course this is dangerous...

It might be an idea to use the FindWindow API to find the 2nd app and use PostMessage to send a msg directly to that app.
E.g.
hApp := FindWindow(PChar('TForm1'), PChar('App Caption'));
if (hApp > 0) then
  PostMessage(hApp, WM_MY_MSG, MyInt1, MyInt2);

Cheers,
JB

0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339831
Fabulous!!  Worked that time.

Hay, any reason why it processes the message twice?  I noticed when I click the button, it seems to send the message twice, or not clear the message queue.  Is this correct??

Regardless, it works like a charm!!  Thanks fellas..

Who wants the points?  Or do you want to do a split 50/50?

Stu.
0
 
LVL 5

Expert Comment

by:inter
ID: 1339832
Yes, Jim is right
(if you have a difficulty in FindWindow, give your form a weird class name and just call
FindWindow('TMyWeirdForm',nil); )
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339833
Inter,

That worked beautifully.  Thanks mate!!

Stu.
0
 
LVL 5

Expert Comment

by:inter
ID: 1339834
This is JimBob's turn, I have already interrupt several of his solutios by mistake ;-)
igor
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339835
Wow!   Generosity!  Well done.  Im happy to give you half each if you like.

Stu.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339836
Hi Stu

If you change the app msg thing to the following:  (I.e. get rid of Application.OnMessage.)

In form
  TForm1 = class(TForm)
  public
    procedure WndProc(var Msg: TMessage); override;
  end;

procedure TForm1.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_MY_MSG:
      ShowMessage('WndProc: ' + IntToStr(Msg.wParam));
  end;
  inherited;
end;

Then you can use "PostMessage(HWND_BROADCAST, WM_MY_MSG, Int1, Int2);" instead of BroadcastSystemMessage and the 2nd app will only get the msg once.

JB

0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339837
Inter - thanks, but I don't hold any grudges from the other "mistakes".  As I said - these things happen.

Stu - when you're happy I'll answer the Q.

JB

0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339838
Mate, Im stoked!!!  Post an answer whenever your ready!

Thanks guys! You have made this job bloody easy!!  I really appreciate how quick you responded.

Stu

0
 
LVL 5

Expert Comment

by:inter
ID: 1339839
thanks, nice to work with all of you :-)
0
 
LVL 5

Accepted Solution

by:
JimBob091197 earned 100 total points
ID: 1339840
Here be the answer then...

JB
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339841
Well, here by the grade then! :)

Thanks again guys!  Very very happy!

Stu
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339842
:-)
As always, a pleasure!

Dave
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339843
Dave,

A question regarding this.  For some reason, if this application has been sent to the tray, it is ignoring all my messages.  It works fine when its in a normal state.

Any suggestions at all?

Stuart.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339844
Which method are you using?  BroadcastSystemMessage or PostMessage(HWND_BROADCAST...)?

I haven't tried with a tray app, but I'll have a look now for you.

Dave
0
 
LVL 6

Author Comment

by:Stuart_Johnson
ID: 1339845
Hi Dave,

Im using PostMessage(hApp, WM_MY_MSG, Int1, Int2).  Its working fine if it the app is not sent to the tray.


Stu.
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1339846
Hi Stu

This is odd.  I have written a small test app (well 2 actually, a tray app & a caller app).
And it seems to work, even when the tray app is "in the tray".

My caller app's "Send Msg to Tray App" button click looks like this: (My tray app's main form is "TfrmTest".)

var
  hTrayApp: THandle;
begin
  hTrayApp := FindWindow('TfrmTest', 'Test');
  if (hTrayApp > 0) then
    SendMessage(hTrayApp, WM_USER + 1234, 1, 2);
end;

My tray app's WndProc looks like this:

procedure TfrmTest.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_USER + 1234:
      ShowMessage(IntToStr(Msg.WParam) + ', ' + IntToStr(Msg.LParam));
  end;
  inherited;
end;

The following works even after I have run the following code to send the tray app to the aforementioned tray:

procedure TfrmTest.Button1Click(Sender: TObject);
begin
  // Show tray icon.
  // "trayTest" is my TTray component on the main form.
  trayTest.Enabled := True;

  // Hide main app window.
  ShowWindow(Application.Handle, SW_HIDE);

  // Hide the tray app's main form.
  Self.Hide;
end;

After all this the tray app still responds to the caller app's PostMessage.
Dave

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

820 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