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

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


One instance

SIT/CS -- tangst@nyp.ac.sg
Wednesday, April 03, 1996


I am working on MFC 2.5 on MS Windows 3.11

I want to restrict my application to one instance only. If there is previous 
instance exist, the previous window is activated.

I read the FAQ, the answer is seem for MFC 4.0. It provides the following:
const char * MyMainWndClassName = "MyScribble";
BOOL CMyApp::InitApplication() {
     ...
     ::GetClassInfo(AfxGetInstanceHandle(), "AfxFrameOrView", &wndcls);
     wndcls.lpszClassName = MyMainWndClassName
     return ::RegisterClass(&wndcls);
}

I did the same thing in my application. However, the WinMain in MFC 2.5 
 performed the following:
int PASCAL WinMain(...)
{
     ...
     // App global initializations (rare)
     if (hPrevInstance == NULL && !AfxGetApp()->InitApplication())
          goto InitFailure;
     ...
}

Since hPrevInstance is not NULL, the AfxF=GetApp()->InitApplication() never 
get executed. Therefore, the wndcls.lpszClassName does not get changed to 
"MyScribble".

In MyApp::InitInstance(), I am unable to find the window of the previous 
instance using FindWindow(MyMainWndClassName, NULL) because 
MyMainWndClassName is not initialized.

Does anyone have a solution to restricting application to one instance in 
MFC 2.5?

Appreciate any help.

Thanks
Tang S. T.



David W. Gillett -- DGILLETT@expertedge.com
Thursday, April 04, 1996

[Mini-digest: 2 responses]

> I am working on MFC 2.5 on MS Windows 3.11
> 
> I want to restrict my application to one instance only. If there
> is previous instance exist, the previous window is activated. 

  Absolutely the easiest way to do this is to build your app using 
the "large" memory model and turn on the "extern and uninitialized 
data 'far'" option.  You might, just possibly, still need to 
specifically designate some global/static variable as 'far', but most 
likely not.
  What we're trying to do here is force the linker to create an 
executable with two or more data segments.  16-bit Windows can't run 
multiple instances of such an .EXE, and when the user tries to start 
a second instance, Windows will instead activate the instance already 
running and bring it to the front.  And that's what you want.

  There might be some reason why you don't want to take the easy way. 
If hPrevInstance is non-zero, you know that there's already an 
instance running.  The problem is to activate that instance's window 
and bring it to the foreground.
  The documented/recommended approach is to use FindWindow().  It 
has looked to me like it should also be possible to make it work with 
GetInstanceData(), but I have never actually gotten that to work....

  [Matt Pietrek has covered this question extensively in articles for 
MSJ which are on the MSDN CD-ROM....]

Dave

-----From: "VARughese GEOrge" 

hi,

try to use this code in the beginig of InitInstace.

BOOL CMyApp::InitInstance()
{
	
   // Do not run the second Instance
   HWND hFirsthWnd, hFirstChildhWnd; 
   if (m_hPrevInstance != NULL)
   { 
      ::GetInstanceData(m_hPrevInstance, (unsigned char *)&FirsthWnd,2);  
       if (hFirsthWnd )
       {
	hFirstChildhWnd = ::GetLastActivePopup(hFirsthWnd);
     	::BringWindowToTop(hFirsthWnd);      // Bring main window to top.
 	if (hFirsthWnd != hFirstChildhWnd)
	::BringWindowToTop(hFirstChildhWnd);//A pop-up is active so bring it to the 
to top too.
	return (FALSE);                // Do not run second instance.
	}
    }
   // go with the first instance...
  ......

}

hopw this helps
thanx
vargeo
http://www.ramco.com/vargeo.htm



Chong Zhang -- cz@dana.ucc.nau.edu
Friday, April 05, 1996

We used to have problem of making our MFC-based application multiple 
instance one. In Win3.11, your application will be single instanced if it 
has multiple data segment. So if you declare DATA MULTIPLE in your .DEF 
file, it do the trick. Or you can declare some global objects, such as a 
CString object
  CString myGlobalText;
then the linker will treat your application as one with multiple DATA 
segments and your application will be single instanced.

On Wed, 3 Apr 1996, Tang Siong Tiing, SIT/CS wrote:

> 
> I am working on MFC 2.5 on MS Windows 3.11
> 
> I want to restrict my application to one instance only. If there is previous 
> instance exist, the previous window is activated.
> 
> I read the FAQ, the answer is seem for MFC 4.0. It provides the following:
> const char * MyMainWndClassName = "MyScribble";
> BOOL CMyApp::InitApplication() {
>      ...
>      ::GetClassInfo(AfxGetInstanceHandle(), "AfxFrameOrView", &wndcls);
>      wndcls.lpszClassName = MyMainWndClassName
>      return ::RegisterClass(&wndcls);
> }
> 
> I did the same thing in my application. However, the WinMain in MFC 2.5 
>  performed the following:
> int PASCAL WinMain(...)
> {
>      ...
>      // App global initializations (rare)
>      if (hPrevInstance == NULL && !AfxGetApp()->InitApplication())
>           goto InitFailure;
>      ...
> }
> 
> Since hPrevInstance is not NULL, the AfxF=GetApp()->InitApplication() never 
> get executed. Therefore, the wndcls.lpszClassName does not get changed to 
> "MyScribble".
> 
> In MyApp::InitInstance(), I am unable to find the window of the previous 
> instance using FindWindow(MyMainWndClassName, NULL) because 
> MyMainWndClassName is not initialized.
> 
> Does anyone have a solution to restricting application to one instance in 
> MFC 2.5?
> 
> Appreciate any help.
> 
> Thanks
> Tang S. T.
> 



Crucial Software -- crucial@ix.netcom.com
Friday, April 05, 1996


------ =_NextPart_000_01BB23C0.F18C0900
Content-Type: text/plain; charset="us-ascii"



David W. Gillett -- DGILLETT@expertedge.com
Monday, April 08, 1996

> >>  What we're trying to do here is force the linker to create an 
> >> executable with two or more data segments.  16-bit Windows can't run 
> >> multiple instances of such an .EXE, and when the user tries to start 
> >> a second instance, Windows will instead activate the instance already 
> >> running and bring it to the front.  And that's what you want.
> 
> Windows does _NOT_ do this.  If you try and run a 16-bit application with
> multiple, writable data segments, WinExec() will fail with the appropriate
> error code (there is one indicating this).  Program Manager displays an
> error message box indicating the problem.

  I do not get any such message from Program Manager -- I get the 
running instance activated and brought to the front.  Same thing from 
File Manager. 

  According to MSJ's "Windows Q and A" column, 1994 - number 6, the 
magic to activate the first instance in this case is in the 
ShellExecute() function.  So it appears that perhaps the missing key 
is simply to use ShellExecute() instead of calling WinExec() directly.

Dave





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