1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/snglinst.cpp
3 // Purpose: implements wxSingleInstanceChecker class for Win32 using
5 // Author: Vadim Zeitlin
9 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // License: wxWindows license
11 ///////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
22 #pragma implementation "snglinst.h"
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
32 #if wxUSE_SNGLINST_CHECKER && defined(__WIN32__)
35 #include "wx/string.h"
39 #include "wx/snglinst.h"
41 #include "wx/msw/private.h"
43 //variables held in common by the callback and wxSingleInstanceCheckerImpl
44 static HWND FirsthWnd
;
45 static wxString s_Title
;
47 // callback to look for windows whose titles include the search string
48 // BCC (at least) does not like the callback to be part of the class :-((
49 bool CALLBACK
EnumWindowsProc ( HWND hwnd
, LPARAM lParam
)
51 // Get the title of this window
52 int iTitleLen
= ::GetWindowTextLength(hwnd
);
53 // possible UNICODE/ANSI bug here, see SDK documentation,
54 // so allow extra space
55 char * cTitle
= new char [iTitleLen
*2+10] ;
56 ::GetWindowText(hwnd
, cTitle
, iTitleLen
*2+10);
58 bool bSuccess
= wxString(cTitle
).Contains(s_Title
) ;
74 // ----------------------------------------------------------------------------
75 // wxSingleInstanceCheckerImpl: the real implementation class
76 // ----------------------------------------------------------------------------
78 class WXDLLEXPORT wxSingleInstanceCheckerImpl
81 wxSingleInstanceCheckerImpl()
83 // we don't care about m_wasOpened, it can't be accessed before being
88 bool Create(const wxString
& name
)
90 m_hMutex
= ::CreateMutex(NULL
, FALSE
, name
);
93 wxLogLastError(_T("CreateMutex"));
98 // mutex was either created or opened - see what really happened
99 m_wasOpened
= ::GetLastError() == ERROR_ALREADY_EXISTS
;
104 bool WasOpened() const
106 wxCHECK_MSG( m_hMutex
, FALSE
,
107 _T("can't be called if mutex creation failed") );
114 // Activates Previous Instance if a window matching Title is found
115 bool ActivatePrevInstance(const wxString
& sSearch
)
117 //store search text and window handle for use by callback
121 EnumWindows (WNDENUMPROC(&EnumWindowsProc
), 0L);
124 //no matching window found
128 if (::IsIconic(FirsthWnd
))
130 ::ShowWindow(FirsthWnd
, SW_SHOWDEFAULT
);
132 ::SetForegroundWindow(FirsthWnd
);
134 // now try to deal with any active children
135 // Handles to child of previous instance
138 FirstChildhWnd
= ::GetLastActivePopup(FirsthWnd
);
139 if (FirsthWnd
!= FirstChildhWnd
)
141 // A pop-up is active so bring it to the top too.
142 ::BringWindowToTop(FirstChildhWnd
);
147 // Activates Previous Instance and passes CommandLine to wxCommandLineEvent
148 // if a window matching Title is found
149 bool PassCommandLineToPrevInstance(const wxString
& sTitle
, const wxString
& sCmdLine
)
151 // this stores a string of up to 255 bytes
152 //ATOM myAtom = GlobalAddAtom ( sCmdLine );
154 // this would create a call to wxWindow::OnCommandLine(wxCommandLineEvent & event)
155 // which should retrieve the commandline, and then delete the atom, GlobalDeleteAtom( myAtom );
156 //::SendMessage (FirsthWnd, wxCOMMANDLINE_MESSAGE, 0, myAtom) ;
160 ~wxSingleInstanceCheckerImpl()
164 if ( !::CloseHandle(m_hMutex
) )
166 wxLogLastError(_T("CloseHandle(mutex)"));
172 // the result of the CreateMutex() call
175 // the mutex handle, may be NULL
180 // ============================================================================
181 // wxSingleInstanceChecker implementation
182 // ============================================================================
184 bool wxSingleInstanceChecker::Create(const wxString
& name
,
185 const wxString
& WXUNUSED(path
))
187 wxASSERT_MSG( !m_impl
,
188 _T("calling wxSingleInstanceChecker::Create() twice?") );
190 // creating unnamed mutex doesn't have the same semantics!
191 wxASSERT_MSG( !name
.empty(), _T("mutex name can't be empty") );
193 m_impl
= new wxSingleInstanceCheckerImpl
;
195 return m_impl
->Create(name
);
198 bool wxSingleInstanceChecker::IsAnotherRunning() const
200 wxCHECK_MSG( m_impl
, FALSE
, _T("must call Create() first") );
202 // if the mutex had been opened, another instance is running - otherwise we
203 // would have created it
204 return m_impl
->WasOpened();
207 // Activates Previous Instance if a window whose Title contains the search string is found
208 bool wxSingleInstanceChecker::ActivatePrevInstance(const wxString
& sSearch
)
210 if (!IsAnotherRunning())
214 return m_impl
->ActivatePrevInstance(sSearch
) ;
217 // Activates Previous Instance and passes CommandLine to wxCommandLineEvent
218 // if a window matching Title is found
219 bool wxSingleInstanceChecker::PassCommandLineToPrevInstance(const wxString
& sSearch
, const wxString
& sCmdLine
)
221 if (!ActivatePrevInstance(sSearch
))
225 return m_impl
->PassCommandLineToPrevInstance(sSearch
, sCmdLine
);
228 wxSingleInstanceChecker::~wxSingleInstanceChecker()
233 #endif // wxUSE_SNGLINST_CHECKER