Board index » cppbuilder » Sharing data between two applications

Sharing data between two applications


2005-10-23 05:59:14 AM
cppbuilder86
Dear programers,
I have two application (i.e. App1.exe and App2.exe). The App1.exe has one
parent window - Form1, and two childs: Form2 and Form3. There is a one Label
on the Form2. A question is: how can I get a Caption from the Label situated
on the Form2 from App2.exe? Is this possible? Obviously, both application
are running in the same time.
Thanks for help
Regards
Przemo
 
 

Re:Sharing data between two applications

"Przemo B." <baan/no_spam/@onet.pl>wrote:
Quote

[...] how can I get a Caption from the Label situated on the
Form2 from App2.exe?
You'd need to use SendMessage to tell Form2 to send it to
App2. Then Form2 needs to use WM_COPYDATA to send the
Caption's text to App2.
~ JD
 

Re:Sharing data between two applications

Quote
You'd need to use SendMessage to tell Form2 to send it to
App2. Then Form2 needs to use WM_COPYDATA to send the
Caption's text to App2.

~ JD

This solution is good, but...the problem I described in previous was
trivial. Realy, I need to get more data from App1 (i.e. some data from
ListViews controls), but the App2 *must* choose which one. I used a WinAPI
call: FindWindow and I obtained a handle (I thought this way is useful):
// from App2:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HWND BCBHandle = FindWindow(NULL, "App1");
if (BCBHandle)
{
HDC dc = GetWindowDC(BCBHandle);
...
...
ReleaseDC(BCBHandle, dc);
}
}
Nevertheless, in this point my knowledge is not enough. So, I repeat: Label1
is placed on child Form2 in App1.exe. App2 has to obtain Caption from Label1
(sometimes App2 has to obtain Caption from Label2 or Label3 etc., but
decision which one, must come only from App2).
Regards
Przemo
 

{smallsort}

Re:Sharing data between two applications

"Przemo B." <baan/no_spam/@onet.pl>wrote:
Quote

[...] the problem I described in previous was trivial.
Realy, I need to get more data from App1
The solution remains the same.
Quote
I used a WinAPI call: FindWindow and I obtained a handle
That would be correct.
Quote
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HWND BCBHandle = FindWindow(NULL, "App1");
if (BCBHandle)
{
HDC dc = GetWindowDC(BCBHandle);
Getting the HDC is not useful.
Quote
[...] sometimes App2 has to obtain Caption from Label2 or
Label3 etc., but decision which one, must come only from
App2).
Then App2 needs to tell App1 what it wants and App1 needs to
tell App2 what it is sending. To tell App1 what it want's,
App2 can use the win32 API SendMessage with a custom message
and fill the WParam and/or the LParam with a code to indicate
what information that it wants. That's about 8 billion
different possible requests.
To begin, each application's main form should have a unique
name to ensure that FindWindow finds the correct window. IOW,
if the names are not unique, you could end up trying to
exchange data with the wrong windows. Do not presume that no
other windows have or do not have a specific class name.
In addition, you need to ensure that only one instance of
App1 and App2 are allowed to be running at any one time.
If you fail to do this, there is no guarantee that FindWindow
will find the window that you want. To prevent multiple
instances of an application, look here:
groups.google.com/group/borland.public.cppbuilder.students/msg/2f40b8c199575b9f&
Assuming that you incorporate the above into your applications,
you will have named your main form class to some thing like:
TCompanyNameApplication1Name
and
TCompanyNameApplication2Name
now you can use FindWindow with the application's main form
class name safely. Of course, you could target Form2 directly
but that would require a bit more work than what's absolutely
needed but that's a design choice that you have to make.
I would suggest that both applications use FindWindow to
locate each other and that all messages are sent to the main
form's HWND. To recieve and process the messages, you need to
override both application's main form's WndProc method. For
example:
//--- in the header -------------------------------------------
protected: // User declarations
virtual void __fastcall WndProc( TMessage &Message );
//--- in the unit ---------------------------------------------
void __fastcall TCompanyNameApplicationXName::WndProc( TMessage &Message )
{
// test Message.Msg to see if you need to act
TForm::WndProc( Message );
}
//-------------------------------------------------------------
How you process the messages in each application will differ.
In App1, you'll want to listen for a custom message that App2
will send to request data. For example:
#define UWM_DATAREQUEST (WM_USER + 100)
//-------------------------------------------------------------
void __fastcall TCompanyNameApplication1Name::WndProc( TMessage &Message )
{
if( Message.Msg == UWM_DATAREQUEST )
{
// send App2 the requested data using WM_COPYDATA
}
TForm::WndProc( Message );
}
//-------------------------------------------------------------
Then, App2's WndProc would look like:
//-------------------------------------------------------------
void __fastcall TCompanyNameApplication2Name::WndProc( TMessage &Message )
{
if( Message.Msg == WM_COPYDATA )
{
// extract the data and use it
}
TForm::WndProc( Message );
}
//-------------------------------------------------------------
~ JD
 

Re:Sharing data between two applications

"JD" < XXXX@XXXXX.COM >wrote:
Quote

Then App2 needs to tell App1 what it wants and App1 needs to
tell App2 what it is sending.
Actually ... App1 doesn't need to tell App2 what it's sending
because of how SendMessage works. From the win32.hlp file:
"[...] The function calls the window procedure for the
specified window and does not return until the window
procedure has processed the message. [...]"
So, using SendMessage can be thought of the same as if you were
calling a function in the other application. When App1
recieves the message, it in turn uses SendMessage to send the
requested data back. So ... you can do something like:
int Code = some code for the data that you want;
HWND hHandle = ::FindWindow( "TCompanyNameApp2Name", NULL );
if( hHandle )
{
::SendMessage( hHandle, UWM_REQUESTDATA, (WPARAM)Code, (LPARAM)Handle );
}
else
{
// couldn't find the window
}
// execution won't get to here until *after* you have
// received and processed WM_COPYDATA. That means that
// when you process WM_COPYDATA, you can use the value of
// Code to know what data is incoming as long as you
// define Code accordingly.
Note that you need to use FindWindow each time you request
data because there are many things that can cause the form's
underlying HWND (it's Handle) to be recreated. If you only
call it once and reuse the HWND, there is a chance that at
some point, your saved HWND is no longer valid and your code
will break.
Quote
[...] and fill the WParam and/or the LParam with a code
I would now suggest that you use only one of them to indicate
what App2 wants and save the other Param for the HWND of the
requesting window.
Quote
To begin, each application's main form should have a unique
name to ensure that FindWindow finds the correct window. [...]
This is still true for any window that you will be using
FindWindow for (App1) but if you pass the requesting HWND
as a parameter, then you don't need it for App2 and it will
now work with multiple instances of App2 because App2 will
uniquely identify itself.
~ JD