//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999. // // File: watch.hxx // // Contents: // // History: 15 Aug 1996 DLee Created // //-------------------------------------------------------------------------- #pragma once #include const unsigned cmsNotifySpacing = 1000; const unsigned cmsStartSpacing = 100; const unsigned cmsBackoff = 100; const unsigned cmsSleep = 50; class CRowsetNotifyWatch : public IRowsetWatchNotify { public: CRowsetNotifyWatch(HWND hwnd) : _cRef(1), _hwndNotify(hwnd), _cmsTicks(GetTickCount() + cmsNotifySpacing), _cmsSpacing( cmsStartSpacing ), _fHoldNotifications( FALSE ), _fIgnore( FALSE ), _wnLast( 0 ) { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::Construct\n")); } ~CRowsetNotifyWatch() { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::~\n")); } // IUnknown methods. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppiuk) { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::QI\n")); *ppiuk = (void **) this; // hold our breath and jump AddRef(); return S_OK; } STDMETHOD_(ULONG, AddRef) (THIS) { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::AddRef\n")); return ++_cRef; } STDMETHOD_(ULONG, Release) (THIS) { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::Release\n")); ULONG tmp = --_cRef; if ( 0 == _cRef ) delete this; return tmp; } // IRowsetNotifyWatch method STDMETHOD( OnChange) (THIS_ IRowset* pRowset, DBWATCHNOTIFY changeType) { AddRef(); srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::OnChange Top\n")); if ( DBWATCHNOTIFY_QUERYDONE != changeType ) { while ( ( _fHoldNotifications ) || ( ( GetTickCount() - _cmsTicks ) < _cmsSpacing ) ) { if ( ( _fIgnore ) || ( 1 == _cRef ) ) // did we die in our sleep? break; Sleep( cmsSleep ); } } if ( ( !_fIgnore ) && ( _cRef > 1 ) ) // did we (the query) die in our sleep? { _wnLast = changeType; PostMessage( _hwndNotify, wmNotification, changeType, (LPARAM) pRowset ); _cmsTicks = GetTickCount(); _cmsSpacing = __min( cmsNotifySpacing, cmsBackoff + _cmsSpacing ); srchDebugOut(( DEB_TRACE, "CRowsetNotifyWatch::OnChange Blasted\n" )); } else { srchDebugOut((DEB_TRACE,"CRowsetNotifyWatch::OnChange die\n")); } Release(); return S_OK; } // private methods void HoldNotifications( BOOL f ) { _fHoldNotifications = f; _cmsTicks = GetTickCount(); } void IgnoreNotifications( BOOL fIgnore ) { _fIgnore = fIgnore; } private: ULONG _cRef; HWND _hwndNotify; ULONG _cmsTicks; ULONG _cmsSpacing; BOOL _fHoldNotifications; BOOL _fIgnore; DBWATCHNOTIFY _wnLast; }; class CSearchQuery; class CBookMark; class CWatchQuery { public: CWatchQuery (CSearchQuery* pSearch, IRowsetScroll* pRowset); ~CWatchQuery (); BOOL Ok () const { return _pRowsetWatch != 0; } void Notify (HWND hwndList, DBWATCHNOTIFY changeType); void NotifyComplete(); void RowsChanged (HWND hwnd); void Extend (HWATCHREGION hRegion); void Move (HWATCHREGION hRegion); void Shrink (HWATCHREGION hRegion, CBookMark& bmk, ULONG cRows); HWATCHREGION Handle() { return _hRegion; } void IgnoreNotifications( BOOL fIgnore ) { _pNotifyWatch->IgnoreNotifications( fIgnore ); } private: void ExecuteScript (HWND hwndList, ULONG cChanges, DBROWWATCHCHANGE* aScript); CSearchQuery* _pClient; BOOL _fEverGotARowsChanged; DBWATCHNOTIFY _wnLast; IConnectionPointContainer *_pContainer; IConnectionPoint * _pPoint; DWORD _dwAdviseID; CRowsetNotifyWatch * _pNotifyWatch; IRowsetWatchRegion* _pRowsetWatch; HWATCHREGION _hRegion; DWORD _mode; };