Solved

Data Exchange Between Two Apps

Posted on 1998-09-15
30
276 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
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
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…
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

776 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