Stuart_Johnson
asked on
Data Exchange Between Two Apps
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.
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.
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
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
Cheers,
JB
ASKER
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.
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.
Hi all,
I want to extend what Jim suggested as follows
BroadcastSystemMessage(BSF _POSTMESSA GE, BSM_APPLICATIONS, WM_MY_MSG, YourInt1, YourInt2);
regards, igor
I want to extend what Jim suggested as follows
BroadcastSystemMessage(BSF
regards, igor
In your delphi help just search for OnMessage event of the TApplication and look its example, it is just you seek...
igor
igor
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
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
ASKER
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.
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.
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.
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.
Anyway I try to explain,
var
Temp : DWord;
begin
Temp := BSM_APPLICATIONS;
//now
BroadcastSystemMessage(BSM _POST, @Temp, etc.....)
end;
I hope this solves...
var
Temp : DWord;
begin
Temp := BSM_APPLICATIONS;
//now
BroadcastSystemMessage(BSM
end;
I hope this solves...
ASKER
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
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
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
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
ASKER
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.w Param));
ShowMessage(IntToStr(Msg.l Param));
end;
end;
procedure TForm1.Button1Click(Sender : TObject);
var P: DWord;
Int1,
Int2: Integer;
begin
P := BSM_APPLICATIONS;
Int1 := 0;
Int2 := 1;
BroadcastSystemMessage(BSF _POSTMESSA GE, @P, WM_MY_MSG, Int1, Int2);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;
What have I dont wrong???
Thanks,
Stu.
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.w
ShowMessage(IntToStr(Msg.l
end;
end;
procedure TForm1.Button1Click(Sender
var P: DWord;
Int1,
Int2: Integer;
begin
P := BSM_APPLICATIONS;
Int1 := 0;
Int2 := 1;
BroadcastSystemMessage(BSF
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;
What have I dont wrong???
Thanks,
Stu.
ASKER
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.w Param));
ShowMessage(IntToStr(Msg.l Param));
end;
end;
procedure TForm1.Button1Click(Sender : TObject);
var P: DWord;
Int1,
Int2: Integer;
begin
P := BSM_APPLICATIONS;
Int1 := 0;
Int2 := 1;
BroadcastSystemMessage(BSF _POSTMESSA GE, @P, WM_MY_MSG, Int1, Int2);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;
What have I dont wrong???
Thanks,
Stu.
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.w
ShowMessage(IntToStr(Msg.l
end;
end;
procedure TForm1.Button1Click(Sender
var P: DWord;
Int1,
Int2: Integer;
begin
P := BSM_APPLICATIONS;
Int1 := 0;
Int2 := 1;
BroadcastSystemMessage(BSF
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;
What have I dont wrong???
Thanks,
Stu.
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
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')
if (hApp > 0) then
PostMessage(hApp, WM_MY_MSG, MyInt1, MyInt2);
Cheers,
JB
ASKER
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.
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.
Yes, Jim is right
(if you have a difficulty in FindWindow, give your form a weird class name and just call
FindWindow('TMyWeirdForm', nil); )
(if you have a difficulty in FindWindow, give your form a weird class name and just call
FindWindow('TMyWeirdForm',
ASKER
Inter,
That worked beautifully. Thanks mate!!
Stu.
That worked beautifully. Thanks mate!!
Stu.
This is JimBob's turn, I have already interrupt several of his solutios by mistake ;-)
igor
igor
ASKER
Wow! Generosity! Well done. Im happy to give you half each if you like.
Stu.
Stu.
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_BROADCAS T, WM_MY_MSG, Int1, Int2);" instead of BroadcastSystemMessage and the 2nd app will only get the msg once.
JB
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_BROADCAS
JB
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
Stu - when you're happy I'll answer the Q.
JB
ASKER
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
Thanks guys! You have made this job bloody easy!! I really appreciate how quick you responded.
Stu
thanks, nice to work with all of you :-)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Well, here by the grade then! :)
Thanks again guys! Very very happy!
Stu
Thanks again guys! Very very happy!
Stu
:-)
As always, a pleasure!
Dave
As always, a pleasure!
Dave
ASKER
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.
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.
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
I haven't tried with a tray app, but I'll have a look now for you.
Dave
ASKER
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.
Im using PostMessage(hApp, WM_MY_MSG, Int1, Int2). Its working fine if it the app is not sent to the tray.
Stu.
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.W Param) + ', ' + 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(Send er: TObject);
begin
// Show tray icon.
// "trayTest" is my TTray component on the main form.
trayTest.Enabled := True;
// Hide main app window.
ShowWindow(Application.Han dle, 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
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.W
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(Send
begin
// Show tray icon.
// "trayTest" is my TTray component on the main form.
trayTest.Enabled := True;
// Hide main app window.
ShowWindow(Application.Han
// 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
ASKER