Solved

Data Exchange Between Two Apps

Posted on 1998-09-15
30
271 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 5

Expert Comment

by:inter
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 5

Expert Comment

by:inter
Comment Utility
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
Comment Utility
Inter,

That worked beautifully.  Thanks mate!!

Stu.
0
 
LVL 5

Expert Comment

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

Author Comment

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

Stu.
0
 
LVL 5

Expert Comment

by:JimBob091197
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
thanks, nice to work with all of you :-)
0
 
LVL 5

Accepted Solution

by:
JimBob091197 earned 100 total points
Comment Utility
Here be the answer then...

JB
0
 
LVL 6

Author Comment

by:Stuart_Johnson
Comment Utility
Well, here by the grade then! :)

Thanks again guys!  Very very happy!

Stu
0
 
LVL 5

Expert Comment

by:JimBob091197
Comment Utility
:-)
As always, a pleasure!

Dave
0
 
LVL 6

Author Comment

by:Stuart_Johnson
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

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 I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

763 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now