Article View: borland.public.cppbuilder.nativeapi
Article #4274Re: Continuing problem with SendMessage and WM_CCOPYDATA
From: JD
Date: Tue, 28 Feb 2006 14:35
Date: Tue, 28 Feb 2006 14:35
154 lines
7086 bytes
7086 bytes
"Dennis Jones" <nospam@nospam.com> wrote:
>
> [...] if all you want to do is prevent a second instance
> from running and instead just bring the first instance to
> the foreground, you don't need to use SendMessage to do that.
Where were you when I was working on my TSingleInstance? I
posted many times because I couldn't correctly detect the main
form's window state because all API's incorrectly reported the
state (unless it's ExStyle had WS_APP_WINDOW applied) when it
was minimized.
The only solution was to have the component hook into the main
form's WndProc and internally keep track of the window state
and then have the second instance send a custom message because
only the component knew the real state so it had to decide to
restore or not prior to bringing it to front.
> HWND MainFormHWnd = FindWindow( "TMyApplicationMainForm", NULL );
I have a problem with this line because you could get the
wrong instance.
> HWND hAppWnd = (HWND)GetWindowLong( MainFormHWnd, GWL_HWNDPARENT );
With this line, I was able to solve my problem with knowing
the state and reduce the component code and complexity:
//-------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//-------------------------------------------------------------
#include <Classes.hpp>
//-------------------------------------------------------------
#define UWM_INITIALIZE (WM_USER + 100)
//-------------------------------------------------------------
class TSingleInstance : public TComponent
{
private:
HANDLE hMutex;
HWND hFirstInstance;
HWND hSecondInstance;
HWND FHandle;
TForm *FParentForm;
protected:
virtual void __fastcall WndProc( TMessage &Message );
static bool __stdcall EnumWindowsCallBack( HWND hWnd, LPARAM lParam );
public:
__fastcall TSingleInstance(TComponent* Owner);
__fastcall ~TSingleInstance();
};
//-------------------------------------------------------------
#endif
//-------------------------------------------------------------
#include <vcl.h>
#include <basepch.h>
//-------------------------------------------------------------
#pragma hdrstop
//-------------------------------------------------------------
#include "Unit2.h"
#pragma package(smart_init)
//-------------------------------------------------------------
TSingleInstance *ThisSingleInstance = NULL;
//-------------------------------------------------------------
__fastcall TSingleInstance::TSingleInstance(TComponent* Owner) : TComponent(Owner)
{
if( !Owner ) throw Exception("TSingleInstance : You must assign an Owner.");
FParentForm = dynamic_cast<TForm*>( Owner );
if( !FParentForm ) throw Exception("TSingleInstance : The Owner must be a TForm.");
if( ThisSingleInstance ) throw Exception("TSingleInstance : Only one instance of TSingleInstance is allowed per application.");
hMutex = NULL;
FHandle = NULL;
ThisSingleInstance = this;
if( !ComponentState.Contains(csDesigning) )
{
char ThisClassName[ 256 ] = { 0 };
::GetClassName( FParentForm->Handle, ThisClassName, 255 );
hMutex = ::CreateMutex( NULL, TRUE, ThisClassName );
if( GetLastError() == ERROR_ALREADY_EXISTS )
{
::ShowWindow( Application->Handle, SW_HIDE );
Application->ShowMainForm = false;
hFirstInstance = hSecondInstance = NULL;
::EnumWindows( (WNDENUMPROC)EnumWindowsCallBack, (LPARAM)ThisClassName );
if( hFirstInstance == FParentForm->Handle ) hFirstInstance = hSecondInstance;
HWND hWnd = reinterpret_cast<HWND>( ::GetWindowLong(hFirstInstance, GWL_HWNDPARENT) );
if( IsIconic(hWnd) ) ::ShowWindow( hWnd, SW_RESTORE );
::SetForegroundWindow( hWnd );
Application->Terminate();
}
else
{
// Still need some final initialization but it needs to be delayed until Application::MainForm is valid.
FHandle = AllocateHWnd( WndProc );
if( !FHandle )
{
throw Exception("TSingleInstance : AllocateHWnd failed.");
}
::PostMessage( FHandle, UWM_INITIALIZE, 0, 0 );
}
}
}
//-------------------------------------------------------------
__fastcall TSingleInstance::~TSingleInstance()
{
if( FHandle ) DeallocateHWnd( FHandle );
if( hMutex ) ::CloseHandle( hMutex );
ThisSingleInstance = NULL;
}
//-------------------------------------------------------------
void __fastcall TSingleInstance::WndProc( TMessage &Message )
{
if( Message.Msg == UWM_INITIALIZE )
{
if( FParentForm != Application->MainForm )
{
MessageDlg("TSingleInstance : Object can only be placed on the Main Form.", mtError, TMsgDlgButtons() << mbOK, 0);
Application->Terminate();
}
}
Message.Result = DefWindowProc( FHandle, Message.Msg, Message.WParam, Message.LParam );
}
//-------------------------------------------------------------
bool __stdcall TSingleInstance::EnumWindowsCallBack( HWND hWnd, LPARAM lParam )
{
char WindowClassName[256] = { 0 };
if( ::GetClassName(hWnd, WindowClassName, 255) )
{
if( stricmp(WindowClassName, (char*)lParam) == 0 )
{
if( ThisSingleInstance->hFirstInstance )
{
ThisSingleInstance->hSecondInstance = hWnd;
return FALSE;
}
else ThisSingleInstance->hFirstInstance = hWnd;
}
}
return TRUE;
}
//-------------------------------------------------------------
Alot of people looked at this, including Gambit and at least
2 other TeamB members commented and even though we all knew
that TApplication has a hidden window, none of us thought of
it being important.
~ JD
Technical Details
Message-ID:
<44046dac$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailReferences:
<44021981$1@newsgroups.borland.com> <44024219$1@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,6afbc9bf5041d787 X-Google-Attributes: gid10cc67,public X-Google-Language: ENGLISH,ASCII-7-bit From: "JD" <nospam@nospam.com> Sender: "JD" <nospam@nospam.com> Reply-To: "JD" <nospam@nospam.com> Subject: Re: Continuing problem with SendMessage and WM_CCOPYDATA Newsgroups: borland.public.cppbuilder.nativeapi X-User-Info: 152.163.100.201 X-Forwarded-For: 172.155.204.15 References: <44021981$1@newsgroups.borland.com> <44024219$1@newsgroups.borland.com> NNTP-Posting-Host: 207.105.83.66 Message-ID: <44046dac$1@newsgroups.borland.com> Date: 28 Feb 2006 07:35:08 -0700 X-Trace: newsgroups.borland.com 1141140908 207.105.83.66 (28 Feb 2006 07:35:08 -0700) Lines: 155 Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail