// SynchroWnd.cpp : implementation file // #include "IvyStdAfx.h" #include "IvySynchroWnd.h" #define WM_IVY_CB WM_USER + 1001 IvySynchroWnd* IvySynchroWnd::m_synchro = NULL; ///////////////////////////////////////////////////////////////////////////// // IvySynchroWnd IvySynchroWnd::IvySynchroWnd() { m_hWnd = NULL; //m_synchro = this; WNDCLASS wc; // Fill in the window class structure with parameters // that describe the main window. wc.style = 0; // noredraw if size changes wc.lpfnWndProc = WindowProc; // points to window procedure wc.cbClsExtra = 0; // no extra class memory wc.cbWndExtra = 0; // no extra window memory wc.hInstance = 0; // handle to instance wc.hIcon = NULL; // predefined app. icon wc.hCursor = NULL; // predefined arrow wc.hbrBackground = 0; // white background brush wc.lpszMenuName = NULL; // no menu wc.lpszClassName = TEXT("IvySynchroClass"); // name of window class // Register the window class. if ( ! RegisterClass(&wc) ) { TRACE("Warning: unable to create Ivy Synchro notify window!\n"); //AfxThrowResourceException(); } // Create the syncrho window. m_hWnd = CreateWindowEx(0, TEXT("IvySynchroClass"), TEXT("Ivy Synchro Notification Sink"), WS_OVERLAPPED, 0, 0, 0, 0, NULL , NULL, NULL, NULL); if (!m_hWnd) { TRACE("Warning: unable to create Ivy Synchro notify window!\n"); //AfxThrowResourceException(); } InitializeCriticalSection( &m_CritSection ); } IvySynchroWnd::~IvySynchroWnd() { } void IvySynchroWnd::Init(bool synchronous) { if ( synchronous && m_synchro == NULL ) m_synchro = new IvySynchroWnd(); } void IvySynchroWnd::Finish() { if ( m_synchro == NULL ) delete m_synchro; } LRESULT CALLBACK IvySynchroWnd::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_IVY_CB: m_synchro->OnIvyCB( wParam, lParam ); break; // // Process other messages. // default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } ///////////////////////////////////////////////////////////////////////////// // IvySynchroWnd message handlers LRESULT IvySynchroWnd::OnIvyCB(WPARAM wParam, LPARAM lParam) { IvySynchronousCallbackList::iterator iter; EnterCriticalSection( &m_CritSection ); for ( iter = callbacklist.begin(); iter != callbacklist.end(); ) { IvySynchronousCallback *param = *iter++; param->CallCallback(); delete param; } callbacklist.clear(); LeaveCriticalSection( &m_CritSection ); return 0L; } void IvySynchroWnd::PostIvyCB( IvySynchronousCallback *cb ) { BOOL doPost = FALSE; EnterCriticalSection( &m_CritSection ); doPost = callbacklist.empty(); callbacklist.push_back( cb ); LeaveCriticalSection( &m_CritSection ); if ( doPost ) ASSERT(PostMessage(m_hWnd, WM_IVY_CB, 0, 0 )); // give a change to process messages SwitchToThread(); } BOOL CALLBACK MyQuitWindows( HWND hwnd, LPARAM lParam ) { BOOL *posted = (BOOL*)lParam; DWORD dwTheardId; DWORD pid; DWORD mypid = GetCurrentProcessId(); dwTheardId = ::GetWindowThreadProcessId( hwnd,&pid); if ( pid == mypid ) { // give a change to User for closing application safely, save file etc... *posted = PostMessage( hwnd, WM_CLOSE, 0,0 ); } return TRUE; } void IvySynchroWnd::PostQuit() { BOOL posted = FALSE; BOOL canceled = FALSE; EnumWindows(MyQuitWindows, (LPARAM)&posted ); // give a change to process messages if ( !SwitchToThread() ) { Sleep( 200 ); } if ( !posted ) { PostQuitMessage( -1 ); // give a change to process messages if ( !SwitchToThread() ) { Sleep( 100 ); } // ultimate close exit(-1); } } //exit(-1); // // IvySynchronousMessageCallback::IvySynchronousMessageCallback( IvyMessageCallback *cb ) { target = cb; app = 0; argc = 0; argv = 0; } IvySynchronousMessageCallback::~IvySynchronousMessageCallback() { //delete target; for( int i = 0; i < argc ; i++ ) { delete argv[i]; } if ( argv ) delete argv; } void IvySynchronousMessageCallback::OnMessage(IvyApplication *app, int argc, const char **argv ) { // duplicate on the Message Queue IvySynchronousMessageCallback *param = new IvySynchronousMessageCallback(target); param->app = app; param->argc = argc; param->argv = new char*[argc]; for( int i = 0; i < argc ; i++ ) { #ifdef UNDER_CE param->argv[i] = _strdup( argv[i]); #else param->argv[i] = _strdup( argv[i]); #endif } #ifdef IVY_DEBUG TRACE( "IvySynchronousMessageCallback::OnMessage Push callback %s argc=%d\n",typeid( *target).name(), argc); #endif IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousMessageCallback::CallCallback() { #ifdef IVY_DEBUG TRACE( "IvySynchronousMessageCallback::OnMessage Real callback %s argc=%d\n",typeid( *target).name(), argc); #endif target->OnMessage( app, argc, (const char **) argv ); for( int i = 0; i < argc ; i++ ) delete argv[i]; delete argv; } IvySynchronousApplicationCallback::IvySynchronousApplicationCallback( IvyApplicationCallback *cb ) { target = cb; } void IvySynchronousApplicationCallback::OnApplicationConnected( IvyApplication *app) { // duplicate on the Message Queue IvySynchronousApplicationCallback *param = new IvySynchronousApplicationCallback(target); param->type = CONNECTED_CB; param->app = app; IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousApplicationCallback::OnApplicationDisconnected( IvyApplication *app) { // duplicate on the Message Queue IvySynchronousApplicationCallback *param = new IvySynchronousApplicationCallback(target); param->type = DISCONNECTED_CB; param->app = app; IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousApplicationCallback::CallCallback() { if ( !target ) return; switch ( type ) { case CONNECTED_CB: target->OnApplicationConnected( app ); break; case DISCONNECTED_CB: target->OnApplicationDisconnected( app ); break; } } IvySynchronousBindingCallback::IvySynchronousBindingCallback( IvyBindingCallback *cb ) { target = cb; } void IvySynchronousBindingCallback::OnAddBind( IvyApplication *app, int id, const char *regexp) { // duplicate on the Message Queue IvySynchronousBindingCallback *param = new IvySynchronousBindingCallback(target); param->type = ADD_CB; param->app = app; param->id = id; param->regexp = _strdup(regexp); IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousBindingCallback::OnRemoveBind( IvyApplication *app, int id, const char *regexp) { // duplicate on the Message Queue IvySynchronousBindingCallback *param = new IvySynchronousBindingCallback(target); param->type = REMOVE_CB; param->app = app; param->id = id; param->regexp = _strdup(regexp); IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousBindingCallback::OnFilterBind( IvyApplication *app, int id, const char *regexp) { // duplicate on the Message Queue IvySynchronousBindingCallback *param = new IvySynchronousBindingCallback(target); param->type = FILTER_CB; param->app = app; param->id = id; param->regexp = _strdup(regexp); IvySynchroWnd::m_synchro->PostIvyCB( param ); } void IvySynchronousBindingCallback::CallCallback() { if ( target ) { switch ( type ) { case ADD_CB: target->OnAddBind( app, id, regexp ); break; case REMOVE_CB: target->OnRemoveBind( app, id, regexp ); break; case FILTER_CB: target->OnFilterBind( app, id, regexp ); break; } } delete regexp; } IvySynchronousDieCallback::IvySynchronousDieCallback( IvyDieCallback *cb ) { target = cb; } bool IvySynchronousDieCallback::OnDie(IvyApplication *app, int id, const char *arg ) { static int msg_count = 0; // duplicate on the Message Queue IvySynchronousDieCallback *param = new IvySynchronousDieCallback(target); param->app = app; param->id = id; #ifdef UNDER_CE param->arg = _strdup( argv); #else param->arg = _strdup( arg); #endif // TRACE( "IvySynchronousMessageCallback::OnMessage msg count %d\n",wParam); IvySynchroWnd::m_synchro->PostIvyCB( param ); return FALSE; // do not exit now wait for Quit on MessageQueue } void IvySynchronousDieCallback::CallCallback() { // duplicate on the Message Queue if ( !target ) return; if ( target->OnDie ( app, id, arg ) ) { IvySynchroWnd::m_synchro->PostQuit(); } }