Board index » cppbuilder » WM_COPYDATA problem

WM_COPYDATA problem


2007-09-03 09:37:13 AM
cppbuilder27
Hey guys
I am trying to create a 'once-only' app (only one instance can run).
When the user tries to run a second instance, it should pass its command
line to the first instance. I have been following the code at
bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm
(and also
www.bcbjournal.org/articles/vol3/9911/Using_file_associations.htm)
but I can't get it to work. I'm using C++Builder 6.
Here is the workings my code (slightly different from Kent's):
//---------------------------------------------------------------------------
// TFORMMAIN.CPP
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
WindowProc = MyWndProc;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::MyWndProc(Messages::TMessage &Message)
{
if (Message.Msg == WM_COPYDATA) {
Caption = "WM_COPYDATA";
}
else {
WndProc(Message);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// MUTEXTEST.CPP
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdLine, int)
{
try
{
CreateMutex(NULL, NULL, "the mutex of doom");
if (GetLastError())
{
Application->Title = "Something Else";
HWND hWnd = FindWindow("TApplication", "MutexTest");
if (IsIconic(hWnd)) {
ShowWindow(hWnd, SW_SHOWDEFAULT);
}
SetForegroundWindow(hWnd);
if (strlen(cmdLine) != 0)
{
COPYDATASTRUCT cds;
cds.cbData = strlen(cmdLine) + 1;
cds.lpData = cmdLine;
SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cds);
}
}
else
{
Application->Initialize();
Application->Title = "MutexTest";
Application->CreateForm(__classid(TFormMain), &FormMain);
Application->Run();
}
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
Now, the once-only aspect of the app works great. But my WM_COPYDATA
message isn't being picked up at all. If anyone can help at all it would
be fantastic. Thanks!
 
 

Re:WM_COPYDATA problem

Hey guys
I am trying to create a 'once-only' app (only one instance can run).
When the user tries to run a second instance, it should pass its command
line to the first instance. I have been following the code at
bcbjournal.org/articles/vol3/9911/Single-instance_applications.htm
(and also
www.bcbjournal.org/articles/vol3/9911/Using_file_associations.htm)
but I can't get it to work. I'm using C++Builder 6.
Here is the workings of my code (slightly different from Kent's):
//---------------------------------------------------------------------------
// TFORMMAIN.CPP
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner)
{
WindowProc = MyWndProc;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::MyWndProc(Messages::TMessage &Message)
{
if (Message.Msg == WM_COPYDATA) {
Caption = "WM_COPYDATA";
}
else {
WndProc(Message);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// MUTEXTEST.CPP
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdLine, int)
{
try
{
CreateMutex(NULL, NULL, "the mutex of doom");
if (GetLastError())
{
Application->Title = "Something Else";
HWND hWnd = FindWindow("TApplication", "MutexTest");
if (IsIconic(hWnd)) {
ShowWindow(hWnd, SW_SHOWDEFAULT);
}
SetForegroundWindow(hWnd);
if (strlen(cmdLine) != 0)
{
COPYDATASTRUCT cds;
cds.cbData = strlen(cmdLine) + 1;
cds.lpData = cmdLine;
SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cds);
}
}
else
{
Application->Initialize();
Application->Title = "MutexTest";
Application->CreateForm(__classid(TFormMain), &FormMain);
Application->Run();
}
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
Now, the once-only aspect of the app works great. But my WM_COPYDATA
message isn't being picked up at all. If anyone can help at all it would
be fantastic. Thanks!
 

Re:WM_COPYDATA problem

Hi,
You're catching the WM_COPYDATA in your TFormMain class, but you're
sending the message to the window whose handle is returned via the
following call...
HWND hWnd = FindWindow("TApplication", "MutexTest");
I don't believe the above call is returning the correct handle. You
should replace "TApplication" with "TFormMain" and adjust the second
parameter to the form's caption.
As a side note, there's no need to use the WindowProc property since you
can override the WndProc() method directly.
Cheers,
anon5 wrote:
Quote
Hey guys

I am trying to create a 'once-only' app (only one instance can run).
[snip 8<----]
Now, the once-only aspect of the app works great. But my WM_COPYDATA
message isn't being picked up at all. If anyone can help at all it would
be fantastic. Thanks!
 

{smallsort}

Re:WM_COPYDATA problem

Lol... I don't believe it... in a moment of tremendous stupidity I had
combined code with one tutorial with code from another, making a
complete pigs ear of it in the process!
We can all lol now.. at my expense.. hehe
Seriously though, thanks a lot!
Damon Chandler (TeamB) wrote:
Quote
Hi,

You're catching the WM_COPYDATA in your TFormMain class, but you're
sending the message to the window whose handle is returned via the
following call...

HWND hWnd = FindWindow("TApplication", "MutexTest");

I don't believe the above call is returning the correct handle. You
should replace "TApplication" with "TFormMain" and adjust the second
parameter to the form's caption.

As a side note, there's no need to use the WindowProc property since you
can override the WndProc() method directly.

Cheers,
--
Damon Chandler (TeamB)
C++Builder Developer's Journal
bcbjournal.com
bcbjournal.org

anon5 wrote:
>Hey guys
>
>I am trying to create a 'once-only' app (only one instance can run).
[snip 8<----]
>Now, the once-only aspect of the app works great. But my WM_COPYDATA
>message isn't being picked up at all. If anyone can help at all it
>would be fantastic. Thanks!
 

Re:WM_COPYDATA problem

Ok my app is now working correctly, many thanks.
I now have another problem however. The call to FindWindow() to get the
form's handle relies on the form's caption being a predefined value.
What if I want to change the caption at runtime? Is there any way around
this?
Damon Chandler (TeamB) wrote:
Quote
Hi,

You're catching the WM_COPYDATA in your TFormMain class, but you're
sending the message to the window whose handle is returned via the
following call...

HWND hWnd = FindWindow("TApplication", "MutexTest");

I don't believe the above call is returning the correct handle. You
should replace "TApplication" with "TFormMain" and adjust the second
parameter to the form's caption.

As a side note, there's no need to use the WindowProc property since you
can override the WndProc() method directly.

Cheers,
--
Damon Chandler (TeamB)
C++Builder Developer's Journal
bcbjournal.com
bcbjournal.org

anon5 wrote:
>Hey guys
>
>I am trying to create a 'once-only' app (only one instance can run).
[snip 8<----]
>Now, the once-only aspect of the app works great. But my WM_COPYDATA
>message isn't being picked up at all. If anyone can help at all it
>would be fantastic. Thanks!
 

Re:WM_COPYDATA problem

anon5 < XXXX@XXXXX.COM >wrote:
Quote

Please trim your posts.
Quote
Lol... I don't believe it... in a moment of tremendous
stupidity [...]
Join the club! New members are welcome!
~ JD
 

Re:WM_COPYDATA problem

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

Please trim your posts.
Ok I will thanks
 

Re:WM_COPYDATA problem

anon5 < XXXX@XXXXX.COM >wrote:
Quote

Please trim your posts.
Quote
[...] I now have another problem however. The call to
FindWindow() to get the form's handle relies on the form's
caption being a predefined value.
I would suggest that you give the MainForm a unique
name instead ... something like instead of TForm1,
TCompanyNameAppName. This will enable you to find the
HWND using it's class name instead of it's Caption.
For more, see my reply in the VCL.using group under
'SingleInst problem' or click here:
tinyurl.com/2b2n35
~ JD
 

Re:WM_COPYDATA problem

JD wrote:
Quote
I would suggest that you give the MainForm a unique
name instead ... something like instead of TForm1,
TCompanyNameAppName. This will enable you to find the
HWND using it's class name instead of it's Caption.
Thankyou!
 

Re:WM_COPYDATA problem

anon5 < XXXX@XXXXX.COM >wrote:
Quote

LOL!
That was you in the vcl.using group!
I don't usually look at who's asking but I just happened to
notice.
Glad I could help ... in both cases.
~ JD
 

Re:WM_COPYDATA problem

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

LOL!

That was you in the vcl.using group!
Lol
It was indeed :)