15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Multiple Instance..

Sandeep Khamesra -- sandeep@novell.com
Wednesday, April 10, 1996

VC++ 4.0
W95

I have seen the FAQ. Got the sample code
tried but not working..
Here is the code...
My application does not come if I use this
method..


Hi.. 

CAn u tell me how to avoid Multiple Instance
of an application using FindWindow Method.

I have wrote the following code but it is not
working..

BOOL COnetimeApp::InitApplication()
{
 
  // Base class version actually does nothing.
  CWinApp::InitApplication();
 
  WNDCLASS wndcls;
 
  // Start with NULL defaults.
  memset(&wndcls, 0, sizeof(WNDCLASS));
 
  // Retrieve WNDCLASS structure for
default window class.
 
::GetClassInfo(AfxGetInstanceHandle(),"AfxFrameOrView",&wndcls);
 
  // Give new class a unique name.
  wndcls.lpszClassName = "MyNewClass";
 
  // Register new class and return result from
::RegisterClass().
  return ::RegisterClass(&wndcls);
 
}
 
2. Override CWinApp::InitInstance() to check
for (and activate) any
   previous instance of the application:
 
Sample Code
-----------
 
BOOL COnetimeApp::InitInstance()
{
 
  // If this isn't the first instance, return
FALSE
  // immediately. FirstInstance() will have
already
  // activated the previous instance.
 
  if (!FirstInstance())
    return FALSE;
 
  SetDialogBkColor(); // Set dialog box
background color to gray.
     .
     . // Continue with normal InitInstance
code...
     .
}
 
3. Add a member function to your
CWinApp-derived class that actually does
   the work of checking for and activating a
previous instance:
 
Sample Code
-----------
 
BOOL COnetimeApp::FirstInstance()
{
  CWnd *PrevCWnd, *ChildCWnd;
 
  // Determine if another window with our
class name exists...
  if (PrevCWnd =
CWnd::FindWindow("MyNewClass",NULL))
  {
    // if so, does it have any popups?
   
ChildCWnd=PrevCWnd->GetLastActivePopup();
 
    // Bring the main window to the top.
    PrevCWnd->BringWindowToTop();
 
    // If iconic, restore the main window.
    if (PrevCWnd->IsIconic())
      
PrevCWnd->ShowWindow(SW_RESTORE);
 
    // If there was an active popup, bring it
along too!
    if (PrevCWnd != ChildCWnd)
       ChildCWnd->BringWindowToTop();
 
    // Return FALSE. This isn't the first
instance
    // and we are done activating the previous
one.
    return FALSE;
  }
  else
    return TRUE;  // First instance. Proceed
as normal.
}
 
4. Override
CFrameWnd::PreCreateWindow() to use
your window class instead
   of the one registered automatically by
MFC:
 
Sample Code
-----------
 
BOOL
CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
  cs.lpszClass = "MyNewClass";
  return TRUE;

}

My application is not coming only..

Any clues..
Sandy





Michael Potter -- mpotter@ezl.com
Friday, April 12, 1996

[Mini-digest: 5 responses]

Sandeep Khamesra wrote:
> 
> VC++ 4.0
> W95
> 
> I have seen the FAQ. Got the sample code
> tried but not working..
> Here is the code...
> My application does not come if I use this
> method..
> 
> Hi..
> 
> CAn u tell me how to avoid Multiple Instance
> of an application using FindWindow Method.
> Sandy

I use a mutex to test of multiple instances and EnumWindows to 
count and/or ativate previous instances.  I have some free code 
NTClass v1.4 on my home page that you can use as you see fit.

Essentially, I create a named mutex when my program begins.  If 
I cannot create it, it must already exist (previous instance). I 
then can use EnumWindows (FindWindow should work to) to locate 
the previous instances and do what I will with the HWND's.

-- 
*==============================*
* Mike Potter                  *
* QZ Technolgies               *
* http://www.ezl.com/~mpotter  *
*==============================*
-----From: Mario Contestabile 

Since you state your MFC version is 4.0 make sure you get the latest FAQ (4.0).

This is what you should do in your InitInstance()

 // Allow only one instance
 BOOL bFound = FALSE;
 HANDLE hMutexOneInstance = NULL;

 #ifdef _WIN32
  hMutexOneInstance = CreateMutex(NULL,TRUE,_T("PreventSecondInstanceACOM"));
  if(GetLastError() == ERROR_ALREADY_EXISTS)
   bFound = TRUE;
 #else
  if(m_hPrevInstance != NULL)
   bFound = TRUE;
 #endif

 if(bFound){
  CWnd* pFirstWnd;
  if( (pFirstWnd = CWnd::FindWindow(NULL,m_pszAppName)) ){
   if(pFirstWnd->IsIconic())
    pFirstWnd->ShowWindow(SW_SHOWNORMAL);
   pFirstWnd->BringWindowToTop();
   pFirstWnd->GetLastActivePopup()->BringWindowToTop();
  }
  return FALSE; // Exit this instance
 }

 #ifdef _WIN32
  if(hMutexOneInstance) ReleaseMutex(hMutexOneInstance);
 #endif 

 .
 .
 .

 return (bFound == TRUE) ? FALSE : TRUE;

mcontest@universal.com


-----From: kpandya@harbinger.net (Kanir Pandya)

Remove following line from your code and it will work fine.

::GetClassInfo(AfxGetInstanceHandle(),"AfxFrameOrView",&wndcls);

Microsoft used to register class AfxFrameOrView in version earlier 
than 4.0. They do not preregister this class any more. In fact do the 
following in your InitInstance.

BOOL CAskerApp::InitApplication() 
{									   
  // Base class version actually does nothing.
  CWinApp::InitApplication();
 
  WNDCLASS wndcls;
 
  // Start with NULL defaults.
  memset(&wndcls, 0, sizeof(WNDCLASS));

  wndcls.style=CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  HICON hIcon = LoadIcon (IDR_MAINFRAMETYPE);
  wndcls.hIcon = hIcon;
  wndcls.hInstance = AfxGetInstanceHandle();
  wndcls.lpfnWndProc=AfxWndProc;
 
  // Retrieve WNDCLASS structure for default window class.
  //::GetClassInfo(AfxGetInstanceHandle(),"AfxFrameOrView",&wndcls);
 
  // Give new class a unique name.
  wndcls.lpszClassName = "MyClass";
 
  // Register new class and return result from ::RegisterClass().
  return ::RegisterClass(&wndcls);
}


Kanir Pandya
Sr. Software Enggineer
Harbinger Net services
1055, Lenox Park Blvd.
Atlanta, GA-30319
Phone : (404) 841-4324 x3152
-----From: erik.heuer@ks-t.no (Erik Heuer)

There might be a better method for you than using FindWindow.  

Try using the EnumWindows and EnumChildWindows functions.  These
allows you to find your window (with your unique class name) anywhere
in the windows z-order (hierachy).  It is more time consuming than
FindWindow, but it definitely works because ALL child windows are
interrogated.

For example:

//////////////////////////////////////////////////////////////
// NB! This example is not multi-thread-safe 
//////////////////////////////////////////////////////////////
static HWND foundWnd = NULL;
static HWND foundTopWnd = NULL;

// This is called for each child window by EnumChildWindows.
BOOL CALLBACK EnumChildWindowProc(HWND hWnd, LPARAM lParam)
{
    char szClassName[64];

    foundWnd = NULL;
    LPCTSTR lpszClass = (LPCTSTR)lParam;
    if (GetClassName(hWnd, szClassName, sizeof(szClassName))) {
        if (!strnicmp(szClassName, lpszClass, sizeof(szClassName))) {
            foundWnd = hWnd;
            return FALSE;
        }
    }
    return TRUE;
}

// This is called for each top level window by EnumWindows
BOOL CALLBACK EnumWindowProc(HWND hWnd, LPARAM lParam)
{
    foundTopWnd = hWnd;
    EnumChildWindows(hWnd, EnumChildWindowProc, lParam);
    return !foundWnd;
}

// This function returns a CWnd pointer to the first window
// in the windows hiearchy with the given class name, or NULL
// if no window could be located.  
// Use the returned (top level) window to raise the already 
// running instance
CWnd *FindWindowWithClass(LPCTSTR lpszClass)
{
    EnumWindows(EnumWindowProc, (LPARAM)lpszClass);
    if (foundWnd) 
        return CWnd::FromHandle(foundTopWnd);
    return NULL;
}
//////////////////////////////////////////////////////////////
// End of example
//////////////////////////////////////////////////////////////

You should also avoid using the "AfxFrameOrView" class name
which I believe is not created when using MFC4.0. (It is now
called "AfxFrameOrView40").  Also the "AfxFrameOrView" class
name will not be available if your app is dialog based.  
You should register your own uniquely named class from scratch 
instead of using ::GetClassInfo on "AfxFrameOrView".  
Thereby you're not using "undocumented" features of 
MFC which may break in future versions.
Erik Heuer, Kongsberg Simulation & Training, 3600 Kongsberg, Norway
E-mail: erik.heuer@ks-t.no  Phone:(+47) 32735766 Fax:(+47) 32736965

-----From: Richard Burke 

I'm currently using this code (minus the comments) in a MFC 4.0 application.

BOOL CWlinkApp::PrevInstance()
{
	HWND hWnd;
	if(hWnd = (HWND)::FindWindow(NULL"", ""))
	{
		if(::IsWindow((HWND)hWnd) && 			::IsWindowVisible((HWND)hWnd))
		{
			// if minimized, restore the window
			int nShow = ::IsZoomed((HWND)hWnd) ? SW_SHOW 					: SW_RESTORE;
			::BringWindowToTop((HWND)hWnd);
			::ShowWindow((HWND)hWnd, nShow);
			return TRUE;
		}
	}	
	return FALSE;		
}

Good luck,

Rick





| Вернуться в корень Архива |