Solved

Dlg app finds another copy of itself running and does SetForegroundWindow

Posted on 2002-04-27
5
298 Views
Last Modified: 2013-11-20
Dlg app finds another copy of itself running and does SetForegroundWindow

I'm preparing an Mfc dialog application. I want to be able to find and invoke a previously invoked instance of this application ... i.e., I don't want two instances running at the same time.  The second instance should detect this and bring the previously started instance to the foreground before exiting.

I'm using a mutex to determine if another instance is already running.  This works fine.  However, I'm having trouble finding the other instance in order to foreground it. I've seen several examples of using SetProp and GetProp, but these don't seem to work with a CWinApp dialog based app.  In the code below, I suspect I'm not using the proper hWnd in the calls to SetProp and GetProp.

I was going to use another technique involving FindWindow of a registered class, but I understand this involves changing the window class name from "#32770" to another name.  I was trying to do this in PreCreateWindow, but oddly, my overridden PreCreateWindow isn't called. My app dynamically modifies the title bar, so I don't think I can do a FindWindow of the window name itself.

My question(s): Is there a generally accepted technique for an Mfc dialog based app to find and foreground a previously invoked instance of itself?  If this involves PreCreateWindow, how is it set up so that PreCreateWindow is called by the Mfc framework? If this involves SetProp, how is this done with an Mfc dialog based app so the corresponding GetProp works ok?

TIA

CMyDialogApp::InitInstance()
{
  ::CreateMutex(NULL, TRUE, m_pszExeName);
  if (GetLastError() == ERROR_ALREADY_EXISTS) {
    CWnd* pPrevWnd = CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);
    while (pPrevWnd) {
      HANDLE h = ::GetProp(pPrevWnd->GetSafeHwnd(), m_pszExeName);
      if (h != 0) {
        if (pPrevWnd->IsIconic()) {
          pPrevWnd->ShowWindow(SW_RESTORE);
        }
        pPrevWnd->SetForegroundWindow();
        pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
        return FALSE;
      }
      pPrevWnd = pPrevWnd->GetWindow(GW_HWNDNEXT);
    }
    TRACE("Could not find previous instance main window!\n");
    return FALSE;
  }
  ...
  BOOL flag = ::SetProp(m_pMainWnd->GetSafeHwnd(), m_pszExeName, (HANDLE)1);
  ...
}
 
0
Comment
Question by:ee-user
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 4

Accepted Solution

by:
mblat earned 100 total points
ID: 6973533
Honestly at first glance I didn't find anything wrong here,
so look at this link, it has freeware that does exactly what you are looking for.  I've used it in number of my apps, so I know it works.

http://www.naughter.com/sinstance.html

Hope it helps
0
 
LVL 1

Expert Comment

by:kosolobov
ID: 6973674
I propose you to place property directly on desktop window with data handle carrying first instance HWND.
Something like this:

CMyDialogApp::InitInstance()
{
 ::CreateMutex(NULL, TRUE, m_pszExeName);
 if (GetLastError() == ERROR_ALREADY_EXISTS) {
     HWND h = ::GetProp(CWnd::GetDesktopWindow()->GetSafeHwnd(),    
m_pszExeName);
if (h) {
     CWnd* pPrevWnd = CWnd::FromHandle(h);
     if (h != 0) {
       if (pPrevWnd->IsIconic()) {
         pPrevWnd->ShowWindow(SW_RESTORE);
       }
       pPrevWnd->SetForegroundWindow();
       pPrevWnd->GetLastActivePopup()->SetForegroundWindow();
       return FALSE;
     }
     pPrevWnd = pPrevWnd->GetWindow(GW_HWNDNEXT);
   }
   TRACE("Could not find previous instance main window!\n");
   return FALSE;
 }
 ...
 BOOL flag = ::SetProp(CWnd::GetDesktopWindow()->GetSafeHwnd(), m_pszExeName, (HANDLE)m_pMainWnd->GetSafeHwnd());
 ...
}

ps. this source is not tested - i place it here for just general idea.
0
 

Author Comment

by:ee-user
ID: 6973743
mblat: This looks promising ... I'm evaluating it.

kosolobov: Your reply looks very close.  I had to do some casting to get HWND h to compile with GetProp and FromHandle. However, the SetProp/GetProp doesn't seem to be working.  The flag indicates success from SetProp, but h is always 0 from the GetProp.  I tried putting the SetProp in several places, with the same result.  My impression is that it shouldn't make any difference where the ::SetProp is put.

The documentation for GetDesktopWindow indicates it returns a temporary pointer that might be invalid later. I wonder if this is involved.

0
 
LVL 1

Expert Comment

by:kosolobov
ID: 6973795
MFC version of GetDesktopWindow will return temp pointer on CWnd object, while HWND handle carring there will be good.
About place to make SetProp: if you use m_pMainWnd to access m_hWnd - then be sure to use it after initialization.
For MFC Dialog projects it must be in App::InitInstance()

0
 

Author Comment

by:ee-user
ID: 6977227
I'm accepting mblat's reply. This works great and is what I'm using in my project.  Thanks!

I really like the direction of kosolobov's reply, but I couldn't get it to work after some tries. I may look at it later. Because it more directly addresses my question (and I appreciate the time and effort), I'm going to make a 50 point question, "For kosolobov".
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
not able to insert into temp table 68 174
Tab names are off by one 5 54
ffmpeg - "rtsp://...... Operation not permitted" 4 89
isEverywhere  challenge 19 85
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question