?
Solved

Only One Instance Based on Window Title

Posted on 2003-02-24
10
Medium Priority
?
283 Views
Last Modified: 2012-06-27
Hi:

Trying to get a prgram working which will allow only one instance based on the Window's Title, not the exe name. Two windows with the same title are not allowed. It will switch to the current open window if a another copy of the same app is started with the same window title. Before tring the following I tried: HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszAppName);

Then I tried:

bool CcdsgraphApp::FindLastInstance()
{
  char chBuff[1024];
  GetWindowText(hWndGraph, chBuff, 1024);
  if (hWndGraph != NULL) SendMessage(hWndGraph, WM_USER + 1, NULL, (LPARAM)chBuff);

   HANDLE hSem = CreateSemaphore(NULL, 1, 1, chBuff);

   if (GetLastError() == ERROR_ALREADY_EXISTS)
     {
          CloseHandle(hSem);
          HWND hWndPrevious = GetWindow(GetDesktopWindow(), GW_CHILD);

          while (IsWindow(hWndPrevious))
          {
         
               if (GetProp(hWndPrevious, chBuff))
               {
                    if (IsIconic(hWndPrevious))
                         ShowWindow(hWndPrevious, SW_RESTORE);

                    SetForegroundWindow(hWndPrevious);
                    SetForegroundWindow(GetLastActivePopup(hWndPrevious));
                    return true;
               }
               
               hWndPrevious = GetWindow(hWndPrevious, GW_HWNDNEXT);
          }
          return true;
     }
     return false;
}//FindLastInstance

Can someone plase help me here. Thanks very much.
Doug
0
Comment
Question by:DougC
[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
  • 5
  • 4
10 Comments
 
LVL 1

Expert Comment

by:imadjinn
ID: 8011544
There is a good deal of discussion about this topic as well as a few different implementations at http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_11003321.html

I use the CLimitSingleInstance class for this purpose because it is concise and quite usable.  Add the following header file to your project and then create an instance of it first thing in your application.  If there is another instance running just you just exit.

// LimitSingleInstance.h

#ifndef LimitSingleInstance_H
#define LimitSingleInstance_H

#include <windows.h>

class CLimitSingleInstance
{
protected:
  DWORD  m_dwLastError;
  HANDLE m_hMutex;
 
public:
  CLimitSingleInstance(TCHAR *strMutexName)
  {
    //be sure to use a name that is unique for this application otherwise
    //two apps may think they are the same if they are using same name for
    //3rd parm to CreateMutex
    m_hMutex = CreateMutex(NULL, FALSE, strMutexName); //do early
    m_dwLastError = GetLastError(); //save for use later...
  }
 
  ~CLimitSingleInstance()
  {
    if (m_hMutex)  //don't forget to close handles...
    {
      CloseHandle(m_hMutex); //do as late as possible
      m_hMutex = NULL; //good habit to be in
    }
  }
 
  BOOL IsAnotherInstanceRunning()
  {
    return (ERROR_ALREADY_EXISTS == m_dwLastError);
  }
};
#endif
0
 
LVL 1

Author Comment

by:DougC
ID: 8011643
Mode Detail:

I should have mentioned the reason that I wanted to use the Window title is that the title changes based on a slected object. I want only one instance of my app per object, but multiple instances if the object is different. That is why I wanted to use the title. I assume that I can use the title with Mutexes?

Thanks,
Doug
0
 
LVL 1

Expert Comment

by:imadjinn
ID: 8011712
Yes you can, although I would put some unusual application string before the title to ensure it is yours. (i.e. 'MyApPlIcAtIoN' + Title)  You would also need to create a rename function if the window title will change.  Something like:

void Rename(TCHAR *strMutexName)
{
  // Get rid of our old window title
  CloseHandle(m_hMutex);
  m_hMutex = NULL; //good habit to be in

  m_hMutex = CreateMutex(NULL, FALSE, strMutexName);
  m_dwLastError = GetLastError(); //save for use later...
}
0
Industry Leaders: 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!

 
LVL 1

Author Comment

by:DougC
ID: 8012631
Shouldn't this work? The title is unique. It does not seem to work.

bool CcdsgraphApp::FindLastInstance()
{
     char chBuff[128];
     GetWindowText(hWndGraph, chBuff, 128);
     CWnd *pWnd = CWnd::FindWindow(NULL, chBuff );
     if (pWnd)
     {
        // Graph Application already exists: activate it
        pWnd->SetForegroundWindow();
     return TRUE;
     }
     else
     {
     // Graph Application doesn't exist    
     return FALSE;
     }//FindLastInstance

Doug
0
 
LVL 1

Expert Comment

by:arkanes
ID: 8012831
That looks like it should work, assuming that the window title is actually 127 characters or less (in production code, use GetWindowTextLength() first).  Check your return values and GetLastError(), maybe that will tell you something.
0
 
LVL 1

Expert Comment

by:imadjinn
ID: 8012914
The reason why FindWindow does not always work is that it only examines top-level windows.  If your application is an MDI or creates child windows to handle different files they will not show up.

If you are using a MDI application or some similar architecture perhaps it would be better to limit it to a single instance of the application and store a set of the currently open windows at the application level.  Then you can manage the windows directly without having to make any API calls before creating new windows.
0
 
LVL 1

Author Comment

by:DougC
ID: 8013036
Still not working. Please Help. len is zero and chbuff is not correct.

MFC Application, .exe file. Only one window, the main app window.


HWND hWndGraph=0;

// CcdsgraphApp initialization

BOOL CcdsgraphApp::InitInstance()
{
     if (FindLastInstance()) return FALSE; //Only one instance allowed

     // Do it here....
return TRUE;
}

bool CcdsgraphApp::FindLastInstance()
{
     char chBuff[1024];
     int len=0;

     len = GetWindowTextLength(hWndGraph);
     GetWindowText(hWndGraph, chBuff, len);
     CWnd *pWnd = CWnd::FindWindow(NULL, chBuff );
     if (pWnd)
     {
    // Graph Application already exists: activate it
     pWnd->SetForegroundWindow();
      return TRUE;
     }
     else
     {
     // Graph Application doesn't exist    
     return FALSE;
     }//FindLastInstance
}
0
 
LVL 1

Author Comment

by:DougC
ID: 8013109
It seems to be using GetWindowText from winuser.h in \platform sdk\include. The afxwin.h version of GetWindowText only has 2 params.
0
 
LVL 1

Accepted Solution

by:
imadjinn earned 140 total points
ID: 8013156
A few things to note:

First, in the call to GetWindowText len should be the length of your buffer, you do not need to check for the length first.

Second, you set hWndGraph to 0.  This is equivalent to NULL.  You will always get an empty chBuff whenever you call the function like this.  It does not have window text yet because it has not been created yet.  Maybe you should generate the title based rather than trying to read it off of the window.
0
 
LVL 1

Author Comment

by:DougC
ID: 8044472
Thanks for all of yor help.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

800 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