|
#ifndef _TC_ATL_HELPER
#define _TC_ATL_HELPER
// RELEASE_TRACE
#ifndef RELEASE_TRACE
#ifdef _USE_RELEASE_TRACE
#define RELEASE_TRACE AtlTrace
#else
#define RELEASE_TRACE 1 ? (void)0 : AtlTrace
#endif
#endif
// Template Class to derive from, for deleting modeless dialogs
// Behaves like delete this in MFC-Dialogs in PostNcDestroy
template <class T>
class CSelfDeleteAtlDlg
{
public:
CSelfDeleteAtlDlg() {m_szDbgClassName = _T("Unknown");}
// Call this method to destroy a modeless ATL-Dialog
BOOL DestroyWindowAndDeleteThis()
{
static_cast<T*>(this)->m_thunk.Init( DestroyWindowProc, static_cast<T*>(this));
if (0 == WM_ATLDESTROY_MODELESS)
{
WM_ATLDESTROY_MODELESS = RegisterWindowMessage( _T("DestroyModelessAtlWindow"));
}
static_cast<T*>(this)->PostMessage( WM_ATLDESTROY_MODELESS);
return TRUE;
}
private:
static LRESULT CALLBACK DestroyWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = 0L;
try
{
T* pThis = reinterpret_cast<T*>( hWnd);
if (WM_ATLDESTROY_MODELESS == uMsg)
{
::DestroyWindow( pThis->m_hWnd);
RELEASE_TRACE("Deleting Pointer(%s) %08x", pThis->m_szDbgClassName, pThis);
delete pThis;
}
else
{
lResult = pThis->DialogProc( hWnd, uMsg, wParam, lParam);
}
}
catch(...)
{
ATLASSERT(false); // Hopefully never happenes
}
return lResult;
}
protected:
LPCTSTR m_szDbgClassName;
};
__declspec(selectany) UINT WM_ATLDESTROY_MODELESS = 0;
// This class installs a message hook to filter the WM_QUIT
// message. A derived class will be informed to do some clean up stuff
class CProcessWatcherThread
{
public:
CProcessWatcherThread()
{
m_hThread = NULL;
m_WaitHandles.hWatchProcess = NULL;
m_WaitHandles.hEventStopWatch = NULL;
m_pProcessWatcherThread = this;
}
~CProcessWatcherThread()
{
StopWatch();
m_pProcessWatcherThread = NULL;
}
// This method is called if the process is shutting down
virtual void OnProcessShutdown() = 0;
void StartWatch()
{
if (m_hThread) // allready running
return;
// Hook into applications main message loop
m_hOriginalHook = SetWindowsHookEx(WH_GETMESSAGE, ProcessGetMessageHook, 0, GetCurrentThreadId());
// Create two events, one that indicates normal exit (hEventStopWatch)
// and another which indicated Porcess is goiing down (hWatchProcess)
m_WaitHandles.hEventStopWatch = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_WaitHandles.hWatchProcess = ::CreateEvent(NULL, FALSE, FALSE, NULL);
// Create a thread which is supervising the events
m_hThread = ::CreateThread(NULL, NULL, StartThread, this, 0, &m_dwThreadID);
}
void StopWatch()
{
StopWatch(m_WaitHandles.hEventStopWatch); // Signal normal exit and unhook
}
private:
void StopWatch(HANDLE hStop, bool bUnhook = true)
{
if (!m_WaitHandles.hEventStopWatch) return;
::SetEvent(hStop);
::WaitForSingleObject(m_hThread, 2000);
CloseHandle(m_WaitHandles.hEventStopWatch);
CloseHandle(m_hThread);
CloseHandle(m_WaitHandles.hWatchProcess);
m_WaitHandles.hEventStopWatch = NULL;
m_WaitHandles.hWatchProcess = NULL;
m_hThread = NULL;
if (bUnhook)
{
UnhookWindowsHookEx(m_hOriginalHook);
m_hOriginalHook = NULL;
}
}
static DWORD WINAPI StartThread(LPVOID lpParameter)
{
CProcessWatcherThread* m_pProcessWatcherThread = (CProcessWatcherThread*) lpParameter;
m_pProcessWatcherThread->Watch();
return 0;
};
void Watch()
{
DWORD dwWait = ::WaitForMultipleObjects( sizeof(m_WaitHandles) / sizeof(HANDLE), &m_WaitHandles.hWatchProcess , FALSE, INFINITE);
if (dwWait == WAIT_OBJECT_0) // Process is terminated !!
{
RELEASE_TRACE("CProcessWatcherThread: Process terminated.. calling OnProcessShutdown");
OnProcessShutdown();
}
else if (dwWait == WAIT_OBJECT_0 + 1) // thread is terminated !!
{
RELEASE_TRACE("CProcessWatcherThread: Normal exit");
}
else
{
RELEASE_TRACE("CProcessWatcherThread: oops");
}
}
static LRESULT CALLBACK ProcessGetMessageHook(int code, WPARAM wParam, LPARAM lParam)
{
MSG* pMsg = (MSG*) (lParam);
HHOOK hookCall = m_hOriginalHook;
if (pMsg->message == WM_QUIT)
{
m_pProcessWatcherThread->StopWatch(m_pProcessWatcherThread->m_WaitHandles.hWatchProcess, false);
LRESULT lres = CallNextHookEx(hookCall, code, wParam, lParam);
UnhookWindowsHookEx(m_hOriginalHook);
m_hOriginalHook = NULL;
return lres;
}
return CallNextHookEx(hookCall, code, wParam, lParam);
}
DWORD m_dwThreadID;
HANDLE m_hThread;
static HHOOK m_hOriginalHook;
static CProcessWatcherThread* m_pProcessWatcherThread;
#pragma pack( push, 1 )
struct
{
HANDLE hWatchProcess;
HANDLE hEventStopWatch;
} m_WaitHandles;
#pragma pack( pop )
};
__declspec(selectany) HHOOK CProcessWatcherThread::m_hOriginalHook = NULL;
__declspec(selectany) CProcessWatcherThread* CProcessWatcherThread::m_pProcessWatcherThread = NULL;
#endif _TC_ATL_HELPER
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I'm a (paid) software-developer since about 1995. All started in 1983 with hacking assembly code on a commodore 64. I'm using the one and only Language "C++" since 1996. I know others like VB Java TCL/TK (Sometime I was forced to use them) but they can't be compared to the power and mystic of C++.