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
| Вернуться в корень Архива
|