Right here's what I have used to solve that; for the moment is working in all the tests I have done, but maybe you'll find some bugs (I'm not asking to solve them ); I post the code because maybe someone else can be interested in it:
Code:
HWND hwnd_dbl_inst_proc;
unsigned char CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
unsigned long ul,dw;
PROCESSENTRY32 *pe32=(PROCESSENTRY32*)lParam;//see the next function
GetWindowThreadProcessId(hwnd,&dw);
if(pe32->th32ProcessID==dw)//match the window
{
hwnd_dbl_inst_proc=hwnd;//store on the global variable
return 0;//and stop the EnumWindows function
}
return 1;
}
unsigned char instanciaUnica(char* np)//translation: instanceSingle, returns 1 for yes and 0 for no
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;//that needs to include tlhelp32.h
int ctd=0;
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,374837483);
pe32.dwSize=sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap,&pe32))//loop for all the procs
{
do
{
if(lstrcmpi(pe32.szExeFile,np)==0)//match program name
{
if(ctd==0)//match first
{
hwnd_dbl_inst_proc=NULL;
EnumWindows((WNDENUMPROC)EnumWindowsProc,(LPARAM)&pe32);//search the hwnd of the window
}
ctd++;
}
} while(Process32Next(hProcessSnap,&pe32));
}
CloseHandle(hProcessSnap);
return (ctd>1)?0:1;
}
The use is easy, just check for the existence of a previous instance of the application by:
Code:
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int ncs)
{
if(!instanciaUnica(applications_name_and_extension))
{
if(hwnd_dbl_inst_proc)
{
PostMessage(hwnd_dbl_inst_proc,...);//notify the situation to the first instace application
}
return 0;//quit the application
}
...//startup the application if you reach beyond last conditional
}
Here on the PostMesage I'm using a WM_USER+2 message althought I have seen in CBoard the use of MAXINTATOM+index to define user messages and the RegisterWindowMessage function. Something like that:
Code:
#define WM_MULTIPLE_INSTANCE WM_USER+2
PostMessage(hwnd_dbl_inst_proc,WM_MULTIPLE_INSTANCE,0,(LPARAM)"Test");
There is a note on the win32 manual about the PostMessage function:
Code:
If you send a message in the range below WM_USER to the asynchronous message functions (PostMessage,
SendNotifyMessage, and SendMessageCallback), make sure that the message parameters do not include pointers.
Otherwise, the functions will return before the receiving thread has had a chance to process the message and
the sender will free the memory before it is used.
... so since I want to send a char* using WM_USER+2 will work right.
The rest is simply check for the WM_MULTIPLE_INSTANCE message and respond in consequence. In my testing I simply showed the first instance window and show a MessageBox with the text passed as LPARAM.
Hope that can be useful for others.
Niara