Parcourir la source

Ensure Connected to Clipboard Viewer Chain every minute

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@26 595ec19a-5cb4-439b-94a8-42fb3063c22c
ingenuus il y a 22 ans
Parent
commit
6636bbfaf7
17 fichiers modifiés avec 250 ajouts et 136 suppressions
  1. 39 17
      CP_Main.cpp
  2. 5 3
      CP_Main.h
  3. 18 0
      Changes.txt
  4. 34 9
      DataTable.cpp
  5. 2 0
      DataTable.h
  6. 5 4
      MainFrm.cpp
  7. 0 1
      MainFrm.h
  8. 7 7
      Misc.h
  9. 75 34
      ProcessCopy.cpp
  10. 12 6
      ProcessCopy.h
  11. 7 25
      ProcessPaste.cpp
  12. 3 4
      ProcessPaste.h
  13. 32 23
      QPasteWnd.cpp
  14. 4 2
      QPasteWnd.h
  15. 0 1
      QuickPaste.cpp
  16. 5 0
      WndEx.cpp
  17. 2 0
      WndEx.h

+ 39 - 17
CP_Main.cpp

@@ -150,24 +150,28 @@ window using system hooks or a short (e.g. 1 sec) timer... though this
 WH_CBT system hooks in a separate dll (see: robpitt's
 WH_CBT system hooks in a separate dll (see: robpitt's
 http://website.lineone.net/~codebox/focuslog.zip).
 http://website.lineone.net/~codebox/focuslog.zip).
 */
 */
-HWND CCP_MainApp::TargetActiveWindow()
+bool CCP_MainApp::TargetActiveWindow()
 {
 {
 HWND hOld = m_hTargetWnd;
 HWND hOld = m_hTargetWnd;
 HWND hNew = ::GetForegroundWindow();
 HWND hNew = ::GetForegroundWindow();
-	if( hNew != m_hTargetWnd && ::IsWindow(hNew) && !IsAppWnd(hNew) )
-	{
-		m_hTargetWnd = hNew;
-		// Tracking / Debugging
-		/*
-		LOG( StrF(
-			"Target Changed" \
-			"\n\tOld = 0x%08x: \"%s\"" \
-			"\n\tNew = 0x%08x:  \"%s\"\n",
-				hOld, (LPCTSTR) GetWndText(hOld),
-				hNew, (LPCTSTR) GetWndText(hNew) ) );
-		*/
-	}
-	return hOld;
+	if( hNew == m_hTargetWnd || !::IsWindow(hNew) || IsAppWnd(hNew) )
+		return false;
+
+	m_hTargetWnd = hNew;
+	
+	if( QPasteWnd() )
+		QPasteWnd()->UpdateStatus(true);
+
+	// Tracking / Debugging
+	/*
+	LOG( StrF(
+		"Target Changed" \
+		"\n\tOld = 0x%08x: \"%s\"" \
+		"\n\tNew = 0x%08x:  \"%s\"\n",
+			hOld, (LPCTSTR) GetWndText(hOld),
+			hNew, (LPCTSTR) GetWndText(hNew) ) );
+	*/
+	return true;
 }
 }
 
 
 bool CCP_MainApp::ActivateTarget()
 bool CCP_MainApp::ActivateTarget()
@@ -186,6 +190,24 @@ bool CCP_MainApp::ReleaseFocus()
 	return false;
 	return false;
 }
 }
 
 
+// sends Ctrl-V to the TargetWnd
+void CCP_MainApp::SendPaste()
+{
+	if( !ActivateTarget() )
+	{
+		SetStatus("SendPaste FAILED!");
+		return;
+	}
+
+	keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+	keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+
+	keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+	keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+}
+
+// CopyThread
+
 void CCP_MainApp::StartCopyThread()
 void CCP_MainApp::StartCopyThread()
 {
 {
 	ASSERT( m_MainhWnd );
 	ASSERT( m_MainhWnd );
@@ -299,11 +321,11 @@ void CCP_MainApp::OnCopyCompleted(long lLastID, int count)
 	ShowCopyProperties( lLastID );
 	ShowCopyProperties( lLastID );
 }
 }
 
 
-void CCP_MainApp::SetStatus( const char* status )
+void CCP_MainApp::SetStatus( const char* status, bool bRepaintImmediately )
 {
 {
 	m_Status = status;
 	m_Status = status;
 	if( QPasteWnd() )
 	if( QPasteWnd() )
-		QPasteWnd()->SetStatus( status );
+		QPasteWnd()->UpdateStatus( bRepaintImmediately );
 }
 }
 
 
 void CCP_MainApp::ShowPersistent( bool bVal )
 void CCP_MainApp::ShowPersistent( bool bVal )

+ 5 - 3
CP_Main.h

@@ -56,9 +56,11 @@ public:
 // Focus Tracking
 // Focus Tracking
 	HWND	m_hTargetWnd;
 	HWND	m_hTargetWnd;
 //	HWND	m_hTargetFocus;
 //	HWND	m_hTargetFocus;
-	HWND	TargetActiveWindow(); // returns the previously targeted window
+	bool	TargetActiveWindow();
 	bool ActivateTarget();
 	bool ActivateTarget();
-	bool ReleaseFocus(); // activate the target only if we are the foreground window
+	bool ReleaseFocus(); // activate the target only if we are the active window
+	CString GetTargetName() { return GetWndText( m_hTargetWnd ); }
+	void SendPaste(); // Activates the Target and sends Ctrl-V
 
 
 	CLIPFORMAT m_cfIgnoreClipboard; // used by CClip::LoadFromClipboard
 	CLIPFORMAT m_cfIgnoreClipboard; // used by CClip::LoadFromClipboard
 
 
@@ -89,7 +91,7 @@ public:
 
 
 	CString m_Status;
 	CString m_Status;
 	CQPasteWnd* QPasteWnd() { return m_pMainFrame->QuickPaste.m_pwndPaste; }
 	CQPasteWnd* QPasteWnd() { return m_pMainFrame->QuickPaste.m_pwndPaste; }
-	void SetStatus( const char* status = NULL );
+	void SetStatus( const char* status = NULL, bool bRepaintImmediately = false );
 
 
 	void ShowPersistent( bool bVal );
 	void ShowPersistent( bool bVal );
 
 

+ 18 - 0
Changes.txt

@@ -1,11 +1,29 @@
+03 Sept 8
+---------
+* Moved SendPaste to CCP_Main to implicitly use Target
+
++ static bool CDataTable::DeleteParent( long lParentID )
+  . Deletes all records in Data Table with the given "lParentID"
+  
++ Show Target Name in Status (TitleBar)
+
++ Ensure Connected to Clipboard Viewer Chain using dummy WM_DRAWCLIPBOARD
+  CClipboardViewer:
+  *	OnCreate: SetTimer(TIMER_ENSURE_VIEWER_IN_CHAIN, ONE_MINUTE, 0);
+  * WM_CV_RECONNECT - force reconnect if not in chain.
+	* WM_CV_IS_CONNECTED - performs a ping of chain.
+
+
 03 Sept 5
 03 Sept 5
 ---------
 ---------
 + Snap to window now works on multiple monitors
 + Snap to window now works on multiple monitors
 
 
+
 03 Sept 4
 03 Sept 4
 ---------
 ---------
 + Ditto window snaps to window sides
 + Ditto window snaps to window sides
 
 
+
 03 Sept 3
 03 Sept 3
 ---------
 ---------
 + Text Item Parser in CopyProperties - parses a CF_TEXT item into multiple
 + Text Item Parser in CopyProperties - parses a CF_TEXT item into multiple

+ 34 - 9
DataTable.cpp

@@ -71,9 +71,14 @@ void CDataTable::Dump(CDumpContext& dc) const
 // This should be faster than making a copy, but is this SAFE ?????
 // This should be faster than making a copy, but is this SAFE ?????
 HGLOBAL CDataTable::TakeData()
 HGLOBAL CDataTable::TakeData()
 {
 {
+	// if there is nothing to take
 	if( m_ooData.m_hData == 0 || m_ooData.m_dwDataLength == 0 )
 	if( m_ooData.m_hData == 0 || m_ooData.m_dwDataLength == 0 )
 		return 0;
 		return 0;
 
 
+	// Unlock the handle that was locked by DaoLongBinaryAllocCallback()
+	//  (through DFX_LongBinary()).
+	::GlobalUnlock( m_ooData.m_hData );
+
 	// we have to do a realloc in order to make the hGlobal m_dwDataLength
 	// we have to do a realloc in order to make the hGlobal m_dwDataLength
 	HGLOBAL hGlobal = ::GlobalReAlloc(m_ooData.m_hData, m_ooData.m_dwDataLength, GMEM_MOVEABLE );
 	HGLOBAL hGlobal = ::GlobalReAlloc(m_ooData.m_hData, m_ooData.m_dwDataLength, GMEM_MOVEABLE );
 	if( !hGlobal || ::GlobalSize(hGlobal) == 0 )
 	if( !hGlobal || ::GlobalSize(hGlobal) == 0 )
@@ -89,16 +94,14 @@ HGLOBAL CDataTable::TakeData()
 }
 }
 
 
 // this takes ownership of hgData, freeing m_ooData if necessary
 // this takes ownership of hgData, freeing m_ooData if necessary
-// This should be faster than making a copy, but is this SAFE ?????
+// This should be faster than making a copy, but is this SAFE?
+// looks like it is safe based upon:
+// http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q152/5/33.asp&NoWebContent=1
+// http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q119/7/65.asp&NoWebContent=1
 BOOL CDataTable::ReplaceData( HGLOBAL hgData, UINT len )
 BOOL CDataTable::ReplaceData( HGLOBAL hgData, UINT len )
 {
 {
-	if( m_ooData.m_hData && 
-		m_ooData.m_dwDataLength &&
-		(m_ooData.m_hData = ::GlobalFree( m_ooData.m_hData )) )
-	{
-		ASSERT(FALSE);
-		return FALSE;
-	}
+	if( m_ooData.m_hData )
+		::GlobalFree( m_ooData.m_hData );
 
 
 	m_ooData.m_hData = hgData;
 	m_ooData.m_hData = hgData;
 	m_ooData.m_dwDataLength = len;
 	m_ooData.m_dwDataLength = len;
@@ -138,7 +141,7 @@ HGLOBAL CDataTable::LoadData()
 HGLOBAL hGlobal;
 HGLOBAL hGlobal;
 ULONG ulBufLen = m_ooData.m_dwDataLength; //Retrieve size of array
 ULONG ulBufLen = m_ooData.m_dwDataLength; //Retrieve size of array
 
 
-	if(ulBufLen == 0)
+	if( ulBufLen == 0 || m_ooData.m_hData == 0 )
 		return 0;
 		return 0;
 
 
 	hGlobal = NewGlobalH( m_ooData.m_hData, ulBufLen );
 	hGlobal = NewGlobalH( m_ooData.m_hData, ulBufLen );
@@ -146,6 +149,28 @@ ULONG ulBufLen = m_ooData.m_dwDataLength; //Retrieve size of array
 	return hGlobal;
 	return hGlobal;
 }
 }
 
 
+bool CDataTable::DeleteParent( long lParentID )
+{
+CString csDataSQL;
+bool bRet = false;
+
+	csDataSQL.Format( "DELETE FROM Data WHERE lParentID = %d", lParentID );
+
+	try
+	{
+		theApp.EnsureOpenDB();
+		theApp.m_pDatabase->Execute(csDataSQL, dbFailOnError);
+		bRet = TRUE;
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+	}
+
+	return bRet;
+}
+
 BOOL CDataTable::DeleteAll()
 BOOL CDataTable::DeleteAll()
 {
 {
 	BOOL bRet = FALSE;
 	BOOL bRet = FALSE;

+ 2 - 0
DataTable.h

@@ -45,6 +45,8 @@ public:
 	void Open(LPCTSTR lpszFormat,...);
 	void Open(LPCTSTR lpszFormat,...);
 	BOOL DataEqual(HGLOBAL hgData);
 	BOOL DataEqual(HGLOBAL hgData);
 
 
+	static bool DeleteParent( long lParentID );
+
 // Implementation
 // Implementation
 #ifdef _DEBUG
 #ifdef _DEBUG
 	virtual void AssertValid() const;
 	virtual void AssertValid() const;

+ 5 - 4
MainFrm.cpp

@@ -39,8 +39,6 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 	//}}AFX_MSG_MAP
 	//}}AFX_MSG_MAP
 	ON_MESSAGE(WM_HOTKEY, OnHotKey)
 	ON_MESSAGE(WM_HOTKEY, OnHotKey)
 	ON_MESSAGE(WM_SHOW_TRAY_ICON, OnShowTrayIcon)
 	ON_MESSAGE(WM_SHOW_TRAY_ICON, OnShowTrayIcon)
-//	ON_MESSAGE(WM_RECONNECT_TO_COPY_CHAIN, OnReconnectToCopyChain)
-//	ON_MESSAGE(WM_IS_TOP_VIEWER, OnGetIsTopView)
 	ON_MESSAGE(WM_COPYPROPERTIES, OnCopyProperties)
 	ON_MESSAGE(WM_COPYPROPERTIES, OnCopyProperties)
 	ON_MESSAGE(WM_CLOSE_APP, OnShutDown)
 	ON_MESSAGE(WM_CLOSE_APP, OnShutDown)
 	ON_MESSAGE(WM_CLIPBOARD_COPIED, OnClipboardCopied)
 	ON_MESSAGE(WM_CLIPBOARD_COPIED, OnClipboardCopied)
@@ -172,13 +170,16 @@ void CMainFrame::OnFirstExit()
 }
 }
 
 
 LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
-{	
+{
 	if( wParam == theApp.m_pDittoHotKey->m_Atom )
 	if( wParam == theApp.m_pDittoHotKey->m_Atom )
 	{
 	{
+		theApp.TargetActiveWindow();
 		QuickPaste.ShowQPasteWnd(this);
 		QuickPaste.ShowQPasteWnd(this);
 	}
 	}
 	else if( wParam == theApp.m_pCopyHotKey->m_Atom )
 	else if( wParam == theApp.m_pCopyHotKey->m_Atom )
 	{
 	{
+		theApp.TargetActiveWindow();
+
 		theApp.m_bShowCopyProperties = true;
 		theApp.m_bShowCopyProperties = true;
 
 
 		//Simulate the Copy
 		//Simulate the Copy
@@ -270,7 +271,7 @@ void CMainFrame::OnFirstShowquickpaste()
 
 
 void CMainFrame::OnFirstReconnecttoclipboardchain() 
 void CMainFrame::OnFirstReconnecttoclipboardchain() 
 {
 {
-	::PostMessage( theApp.GetClipboardViewer(), WM_RECONNECT_TO_COPY_CHAIN, 0, 0 );
+	::PostMessage( theApp.GetClipboardViewer(), WM_CV_RECONNECT, 0, 0 );
 }
 }
 
 
 void CMainFrame::OnUpdateFirstReconnecttoclipboardchain(CCmdUI* pCmdUI) 
 void CMainFrame::OnUpdateFirstReconnecttoclipboardchain(CCmdUI* pCmdUI) 

+ 0 - 1
MainFrm.h

@@ -18,7 +18,6 @@
 #define REMOVE_OLD_ENTRIES_TIMER		3
 #define REMOVE_OLD_ENTRIES_TIMER		3
 #define CHECK_FOR_UPDATE				4
 #define CHECK_FOR_UPDATE				4
 #define CLOSE_APP						5
 #define CLOSE_APP						5
-#define TIMER_CHECK_TOP_LEVEL_VIEWER	6
 
 
 
 
 class CMainFrame : public CFrameWnd
 class CMainFrame : public CFrameWnd

+ 7 - 7
Misc.h

@@ -79,13 +79,13 @@ CString GetFilePath(CString csFullPath);
 #define POS_AT_PREVIOUS	3
 #define POS_AT_PREVIOUS	3
 
 
 //Message to the main window to show icon or not
 //Message to the main window to show icon or not
-#define WM_SHOW_TRAY_ICON			WM_USER + 200
-#define WM_RECONNECT_TO_COPY_CHAIN	WM_USER + 201
-#define WM_IS_TOP_VIEWER			WM_USER + 202  // Use theApp.IsClipboardViewerConnected()
-#define WM_COPYPROPERTIES			WM_USER + 203
-#define WM_CLOSE_APP				WM_USER + 204
-#define WM_REFRESH_VIEW				WM_USER + 205
-#define WM_CLIPBOARD_COPIED			WM_USER + 206
+#define WM_SHOW_TRAY_ICON		WM_USER + 200
+#define WM_CV_RECONNECT			WM_USER + 201
+#define WM_CV_IS_CONNECTED		WM_USER + 202
+#define WM_COPYPROPERTIES		WM_USER + 203
+#define WM_CLOSE_APP			WM_USER + 204
+#define WM_REFRESH_VIEW			WM_USER + 205
+#define WM_CLIPBOARD_COPIED		WM_USER + 206
 
 
 #define REG_PATH					"Software\\Ditto"
 #define REG_PATH					"Software\\Ditto"
 
 

+ 75 - 34
ProcessCopy.cpp

@@ -177,6 +177,10 @@ CClipTypes* pTypes = pClipTypes;
 	// m_Formats should be empty when this is called.
 	// m_Formats should be empty when this is called.
 	ASSERT( m_Formats.GetCount() == 0 );
 	ASSERT( m_Formats.GetCount() == 0 );
 
 
+	// If the data is supposed to be private, then return
+	if( ::IsClipboardFormatAvailable( theApp.m_cfIgnoreClipboard ) )
+		EXIT_LoadFromClipboard( false );
+
 	//Attach to the clipboard
 	//Attach to the clipboard
 	if( !oleData.AttachClipboard() )
 	if( !oleData.AttachClipboard() )
 	{
 	{
@@ -186,10 +190,6 @@ CClipTypes* pTypes = pClipTypes;
 
 
 	oleData.EnsureClipboardObject();
 	oleData.EnsureClipboardObject();
 
 
-	// If the data is supposed to be private, then return
-	if( oleData.IsDataAvailable( theApp.m_cfIgnoreClipboard ) )
-		EXIT_LoadFromClipboard( false );
-
 	// if no types were given, get only the first (most important) type.
 	// if no types were given, get only the first (most important) type.
 	//  (subsequent types could be synthetic due to automatic type conversions)
 	//  (subsequent types could be synthetic due to automatic type conversions)
 	if( pTypes == NULL || pTypes->GetCount() == 0 )
 	if( pTypes == NULL || pTypes->GetCount() == 0 )
@@ -715,7 +715,7 @@ bool bResult;
 	{
 	{
 		if( bShowStatus )
 		if( bShowStatus )
 		{
 		{
-			theApp.SetStatus( StrF("%d",nRemaining) );
+			theApp.SetStatus( StrF("%d",nRemaining), true );
 			nRemaining--;
 			nRemaining--;
 		}
 		}
 
 
@@ -731,7 +731,7 @@ bool bResult;
 	}
 	}
 
 
 	if( bShowStatus )
 	if( bShowStatus )
-		theApp.SetStatus();
+		theApp.SetStatus(NULL, true);
 
 
 	return savedCount;
 	return savedCount;
 }
 }
@@ -750,8 +750,8 @@ BEGIN_MESSAGE_MAP(CClipboardViewer, CWnd)
 	ON_WM_DRAWCLIPBOARD()
 	ON_WM_DRAWCLIPBOARD()
 	ON_WM_TIMER()
 	ON_WM_TIMER()
 	//}}AFX_MSG_MAP
 	//}}AFX_MSG_MAP
-	ON_MESSAGE(WM_RECONNECT_TO_COPY_CHAIN, OnReconnectToCopyChain)
-	ON_MESSAGE(WM_IS_TOP_VIEWER, OnGetIsTopViewer)
+	ON_MESSAGE(WM_CV_RECONNECT, OnCVReconnect)
+	ON_MESSAGE(WM_CV_IS_CONNECTED, OnCVIsConnected)
 	ON_WM_DESTROY()
 	ON_WM_DESTROY()
 END_MESSAGE_MAP()
 END_MESSAGE_MAP()
 
 
@@ -766,6 +766,8 @@ CClipboardViewer::CClipboardViewer( CCopyThread* pHandler )
 	m_bIsConnected = false;
 	m_bIsConnected = false;
 	m_pHandler = pHandler;
 	m_pHandler = pHandler;
 	ASSERT(m_pHandler);
 	ASSERT(m_pHandler);
+	m_bPinging = false;
+	m_bPingSuccess = false;
 }
 }
 
 
 CClipboardViewer::~CClipboardViewer()
 CClipboardViewer::~CClipboardViewer()
@@ -788,7 +790,7 @@ void CClipboardViewer::Connect()
 	m_bCalling_SetClipboardViewer = true;
 	m_bCalling_SetClipboardViewer = true;
 	m_hNextClipboardViewer = CWnd::SetClipboardViewer();
 	m_hNextClipboardViewer = CWnd::SetClipboardViewer();
 	m_bCalling_SetClipboardViewer = false;
 	m_bCalling_SetClipboardViewer = false;
-	m_bIsConnected = true;
+	m_bIsConnected = SendPing();
 }
 }
 
 
 // disconnects as a clipboard viewer
 // disconnects as a clipboard viewer
@@ -802,6 +804,45 @@ void CClipboardViewer::Disconnect()
 	m_bIsConnected = false;
 	m_bIsConnected = false;
 }
 }
 
 
+bool CClipboardViewer::SendPing()
+{
+HWND hWnd;
+bool bResult = false;
+
+	hWnd = ::GetClipboardViewer();
+	// if there is a chain
+	if( ::IsWindow(hWnd) )
+	{
+		m_bPingSuccess = false;
+		m_bPinging = true;
+		::SendMessage( hWnd, WM_DRAWCLIPBOARD, 0, 0 );
+		m_bPinging = false;
+		bResult = m_bPingSuccess;
+	}
+
+	m_bIsConnected = bResult;
+
+	return bResult;
+}
+
+bool CClipboardViewer::EnsureConnected()
+{
+	if( !SendPing() )
+		Connect();
+
+	return m_bIsConnected;
+}
+
+// puts format "Clipboard Viewer Ignore" on the clipboard
+void CClipboardViewer::SetCVIgnore()
+{
+	if( ::OpenClipboard( m_hWnd ) )
+	{
+		::SetClipboardData( theApp.m_cfIgnoreClipboard, NULL );
+		::CloseClipboard();
+	}
+}
+
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
 // CClipboardViewer message handlers
 // CClipboardViewer message handlers
 
 
@@ -810,8 +851,8 @@ int CClipboardViewer::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	if (CWnd::OnCreate(lpCreateStruct) == -1)
 	if (CWnd::OnCreate(lpCreateStruct) == -1)
 		return -1;
 		return -1;
 
 
-	// is it important for us to be the top viewer?
-//	SetTimer(TIMER_CHECK_TOP_LEVEL_VIEWER, ONE_MINUTE, 0);
+	// verify that we are in the chain every minute
+	SetTimer(TIMER_ENSURE_VIEWER_IN_CHAIN, ONE_MINUTE, 0);
 
 
 	//Set up the clip board viewer
 	//Set up the clip board viewer
 	Connect();
 	Connect();
@@ -843,9 +884,18 @@ void CClipboardViewer::OnChangeCbChain(HWND hWndRemove, HWND hWndAfter)
 //Message that the clipboard data has changed
 //Message that the clipboard data has changed
 void CClipboardViewer::OnDrawClipboard() 
 void CClipboardViewer::OnDrawClipboard() 
 {
 {
+	if( m_bPinging )
+	{
+		m_bPingSuccess = true;
+		return;
+	}
+
 	// don't process the event when we first attach
 	// don't process the event when we first attach
 	if( m_pHandler && !m_bCalling_SetClipboardViewer )
 	if( m_pHandler && !m_bCalling_SetClipboardViewer )
-		m_pHandler->OnClipboardChange();
+	{
+		if( !::IsClipboardFormatAvailable( theApp.m_cfIgnoreClipboard ) )
+			m_pHandler->OnClipboardChange();
+	}
 
 
 	// pass the event to the next Clipboard viewer in the chain
 	// pass the event to the next Clipboard viewer in the chain
 	if( m_hNextClipboardViewer != NULL )
 	if( m_hNextClipboardViewer != NULL )
@@ -856,37 +906,22 @@ void CClipboardViewer::OnTimer(UINT nIDEvent)
 {
 {
 	switch(nIDEvent)
 	switch(nIDEvent)
 	{
 	{
-	case TIMER_CHECK_TOP_LEVEL_VIEWER:
-		{
-			if( GetClipboardViewer() != this )
-			{
-				OnReconnectToCopyChain(0, 0);
-				m_lReconectCount++;
-
-				if(m_lReconectCount > 10)
-					KillTimer(TIMER_CHECK_TOP_LEVEL_VIEWER);
-			}
-			break;
-		}
+	case TIMER_ENSURE_VIEWER_IN_CHAIN:
+		EnsureConnected();
+		break;
 	}
 	}
 
 
 	CWnd::OnTimer(nIDEvent);
 	CWnd::OnTimer(nIDEvent);
 }
 }
 
 
-LRESULT CClipboardViewer::OnReconnectToCopyChain(WPARAM wParam, LPARAM lParam)
+LRESULT CClipboardViewer::OnCVReconnect(WPARAM wParam, LPARAM lParam)
 {
 {
-	if( GetClipboardViewer() != this )
-	{
-		Disconnect();
-		Connect();
-		return TRUE;
-	}
-	return FALSE;
+	return EnsureConnected();
 }
 }
 
 
-LRESULT CClipboardViewer::OnGetIsTopViewer(WPARAM wParam, LPARAM lParam)
+LRESULT CClipboardViewer::OnCVIsConnected(WPARAM wParam, LPARAM lParam)
 {
 {
-	return (GetClipboardViewer() == this);
+	return SendPing();
 }
 }
 
 
 /*----------------------------------------------------------------------------*\
 /*----------------------------------------------------------------------------*\
@@ -939,6 +974,12 @@ int CCopyThread::ExitInstance()
 	return CWinThread::ExitInstance();
 	return CWinThread::ExitInstance();
 }
 }
 
 
+bool CCopyThread::IsClipboardViewerConnected()
+{
+	ASSERT( m_pClipboardViewer && m_pClipboardViewer->m_hWnd );
+	return ::SendMessage( m_pClipboardViewer->m_hWnd, WM_CV_IS_CONNECTED, 0, 0 ) != FALSE;
+}
+
 // Called within Copy Thread:
 // Called within Copy Thread:
 void CCopyThread::OnClipboardChange()
 void CCopyThread::OnClipboardChange()
 {
 {

+ 12 - 6
ProcessCopy.h

@@ -131,7 +131,7 @@ public:
 	CClipboardViewer
 	CClipboardViewer
 \*----------------------------------------------------------------------------*/
 \*----------------------------------------------------------------------------*/
 
 
-#define TIMER_CHECK_TOP_LEVEL_VIEWER	6
+#define TIMER_ENSURE_VIEWER_IN_CHAIN	6
 
 
 class CClipboardViewer : public CWnd
 class CClipboardViewer : public CWnd
 {
 {
@@ -158,8 +158,14 @@ public:
 	// m_pHandler->OnClipboardChange is called when the clipboard changes.
 	// m_pHandler->OnClipboardChange is called when the clipboard changes.
 	CCopyThread*	m_pHandler;
 	CCopyThread*	m_pHandler;
 
 
-	void	Connect();    // connects as a clipboard viewer
-	void	Disconnect(); // disconnects as a clipboard viewer
+	void Connect();    // connects as a clipboard viewer
+	void Disconnect(); // disconnects as a clipboard viewer
+
+	bool	m_bPinging;
+	bool	m_bPingSuccess;
+	bool SendPing(); // returns true if we are in the chain
+	bool EnsureConnected();
+	void SetCVIgnore(); // puts format "Clipboard Viewer Ignore" on the clipboard
 
 
 // Generated message map functions
 // Generated message map functions
 protected:
 protected:
@@ -170,8 +176,8 @@ protected:
 	afx_msg void OnDrawClipboard();
 	afx_msg void OnDrawClipboard();
 	afx_msg void OnTimer(UINT nIDEvent);
 	afx_msg void OnTimer(UINT nIDEvent);
 	//}}AFX_MSG
 	//}}AFX_MSG
-	afx_msg LRESULT OnReconnectToCopyChain(WPARAM wParam, LPARAM lParam);
-	afx_msg LRESULT OnGetIsTopViewer(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnCVReconnect(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnCVIsConnected(WPARAM wParam, LPARAM lParam);
 	DECLARE_MESSAGE_MAP()
 	DECLARE_MESSAGE_MAP()
 };
 };
 
 
@@ -255,7 +261,7 @@ public:
 	CClipList*          m_pClips; // snapshots of the clipboard when it changed.
 	CClipList*          m_pClips; // snapshots of the clipboard when it changed.
 
 
 	// Called within Main thread:
 	// Called within Main thread:
-	bool IsClipboardViewerConnected() { return m_pClipboardViewer->m_bIsConnected; }
+	bool IsClipboardViewerConnected();
 	CClipList* GetClips(); // caller owns the returned CClipList
 	CClipList* GetClips(); // caller owns the returned CClipList
 	void SetSupportedTypes( CClipTypes* pTypes ); // CopyThread will own pTypes
 	void SetSupportedTypes( CClipTypes* pTypes ); // CopyThread will own pTypes
 	HWND SetClipHandler( HWND hWnd ); // returns previous value
 	HWND SetClipHandler( HWND hWnd ); // returns previous value

+ 7 - 25
ProcessPaste.cpp

@@ -12,28 +12,6 @@ static char THIS_FILE[]=__FILE__;
 	Globals
 	Globals
 \*------------------------------------------------------------------*/
 \*------------------------------------------------------------------*/
 
 
-void SendPaste(HWND hWnd)
-{
-	if(hWnd)
-	{
-		//Set a Control key down then a 'V' down then the ups
-		//To simulate a paste
-		::SetForegroundWindow(hWnd);
-		// Does SetFocus do anything?... since hWnd is not associated with
-		//	our thread's message queue?
-//		::SetFocus(hWnd);
-	
-		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
-		keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
-
-     
-		keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
-		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
-	}
-	else
-		ASSERT(FALSE);
-}
-
 BOOL MarkClipAsPasted(long lID)
 BOOL MarkClipAsPasted(long lID)
 {
 {
 	CGetSetOptions::SetTripPasteCount(-1);
 	CGetSetOptions::SetTripPasteCount(-1);
@@ -71,6 +49,11 @@ BOOL MarkClipAsPasted(long lID)
 /*------------------------------------------------------------------*\
 /*------------------------------------------------------------------*\
 	CClipIDs
 	CClipIDs
 \*------------------------------------------------------------------*/
 \*------------------------------------------------------------------*/
+
+//-------------------
+// PASTING FUNCTIONS
+//-------------------
+
 // allocate an HGLOBAL of the given Format Type representing these Clip IDs.
 // allocate an HGLOBAL of the given Format Type representing these Clip IDs.
 HGLOBAL CClipIDs::Render( UINT cfType )
 HGLOBAL CClipIDs::Render( UINT cfType )
 {
 {
@@ -238,8 +221,7 @@ BOOL COleClipSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlob
 	CProcessPaste
 	CProcessPaste
 \*------------------------------------------------------------------*/
 \*------------------------------------------------------------------*/
 
 
-CProcessPaste::CProcessPaste( HWND hWnd ) :
-	m_hWnd(hWnd), m_bDeleteOle(true)
+CProcessPaste::CProcessPaste() : m_bDeleteOle(true)
 {
 {
 	m_pOle = new COleClipSource;
 	m_pOle = new COleClipSource;
 }
 }
@@ -276,7 +258,7 @@ bool bOldState;
 		}
 		}
 
 
 		m_bDeleteOle = false; // m_pOle is managed by the OLE clipboard now
 		m_bDeleteOle = false; // m_pOle is managed by the OLE clipboard now
-		SendPaste(m_hWnd);
+		theApp.SendPaste();
 		MarkAsPasted();
 		MarkAsPasted();
 		return TRUE;
 		return TRUE;
 	}
 	}

+ 3 - 4
ProcessPaste.h

@@ -12,8 +12,6 @@
 #include "ArrayEx.h"
 #include "ArrayEx.h"
 #include "ProcessCopy.h"
 #include "ProcessCopy.h"
 
 
-// Sends Ctrl-V to hWnd
-void SendPaste(HWND hWnd);
 // Sets lID's lDate to GetCurrentTime() and updates paste stats
 // Sets lID's lDate to GetCurrentTime() and updates paste stats
 BOOL MarkClipAsPasted(long lID);
 BOOL MarkClipAsPasted(long lID);
 
 
@@ -23,6 +21,8 @@ BOOL MarkClipAsPasted(long lID);
 class CClipIDs : public ARRAY
 class CClipIDs : public ARRAY
 {
 {
 public:
 public:
+// PASTING FUNCTIONS
+
 	// allocate an HGLOBAL of the given Format Type representing the Clip IDs in this array.
 	// allocate an HGLOBAL of the given Format Type representing the Clip IDs in this array.
 	HGLOBAL	Render( UINT cfType );
 	HGLOBAL	Render( UINT cfType );
 	// Fills "types" with the Format Types corresponding to the Clip IDs in this array.
 	// Fills "types" with the Format Types corresponding to the Clip IDs in this array.
@@ -60,13 +60,12 @@ public:
 class CProcessPaste
 class CProcessPaste
 {
 {
 public:
 public:
-	HWND	m_hWnd; // window to paste to
 	// true if we should delete m_pOle,
 	// true if we should delete m_pOle,
 	// false if it will be automatically deleted
 	// false if it will be automatically deleted
 	bool	m_bDeleteOle;
 	bool	m_bDeleteOle;
 	COleClipSource*	m_pOle;
 	COleClipSource*	m_pOle;
 
 
-	CProcessPaste( HWND hWnd = 0 );
+	CProcessPaste();
 	~CProcessPaste();
 	~CProcessPaste();
 
 
 	CClipIDs& GetClipIDs() { return m_pOle->m_ClipIDs; }
 	CClipIDs& GetClipIDs() { return m_pOle->m_ClipIDs; }

+ 32 - 23
QPasteWnd.cpp

@@ -29,6 +29,7 @@ static char THIS_FILE[] = __FILE__;
 
 
 CQPasteWnd::CQPasteWnd()
 CQPasteWnd::CQPasteWnd()
 {	
 {	
+	m_Title = QPASTE_TITLE;
 	m_bHideWnd = true;
 	m_bHideWnd = true;
 	m_Recset.m_strSort = "lDate DESC";
 	m_Recset.m_strSort = "lDate DESC";
 }
 }
@@ -131,7 +132,7 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	m_lstHeader.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
 	m_lstHeader.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
 
 
 	// Create the columns
 	// Create the columns
-	if (m_lstHeader.InsertColumn(0, "", LVCFMT_LEFT, 0, 0) != 0)
+	if (m_lstHeader.InsertColumn(0, "", LVCFMT_LEFT, 2500, 0) != 0)
 	{
 	{
 		ASSERT(FALSE);
 		ASSERT(FALSE);
 		return -1;
 		return -1;
@@ -266,7 +267,7 @@ BOOL CQPasteWnd::ShowQPasteWindow(BOOL bFillList)
 	//Set the flag so we can't open this up again
 	//Set the flag so we can't open this up again
 	theApp.m_bShowingQuickPaste = true;
 	theApp.m_bShowingQuickPaste = true;
 	SetCaptionColorActive( !g_Opt.m_bShowPersistent );
 	SetCaptionColorActive( !g_Opt.m_bShowPersistent );
-	SetStatus( theApp.m_Status );
+	UpdateStatus();
 
 
 	m_lstHeader.DestroyAndCreateAccelerator(TRUE);
 	m_lstHeader.DestroyAndCreateAccelerator(TRUE);
 
 
@@ -322,7 +323,7 @@ bool CQPasteWnd::Add(const CString &csHeader, const CString &csText, int nID)
 
 
 LRESULT CQPasteWnd::OnListSelect_DB_ID(WPARAM wParam, LPARAM lParam)
 LRESULT CQPasteWnd::OnListSelect_DB_ID(WPARAM wParam, LPARAM lParam)
 {
 {
-	CProcessPaste paste(theApp.m_hTargetWnd);
+	CProcessPaste paste;
 	paste.GetClipIDs().Add(wParam);
 	paste.GetClipIDs().Add(wParam);
 	paste.DoPaste();
 	paste.DoPaste();
 	theApp.OnPasteCompleted();
 	theApp.OnPasteCompleted();
@@ -335,7 +336,7 @@ LRESULT CQPasteWnd::OnListSelect_Index(WPARAM wParam, LPARAM lParam)
 	if( (int) wParam >= m_lstHeader.GetItemCount() )
 	if( (int) wParam >= m_lstHeader.GetItemCount() )
 		return FALSE;
 		return FALSE;
 
 
-	CProcessPaste paste(theApp.m_hTargetWnd);
+	CProcessPaste paste;
 	paste.GetClipIDs().Add( m_lstHeader.GetItemData(wParam) );
 	paste.GetClipIDs().Add( m_lstHeader.GetItemData(wParam) );
 	paste.DoPaste();
 	paste.DoPaste();
 	theApp.OnPasteCompleted();
 	theApp.OnPasteCompleted();
@@ -351,7 +352,7 @@ LRESULT CQPasteWnd::OnListSelect(WPARAM wParam, LPARAM lParam)
 	if(nCount <= 0)
 	if(nCount <= 0)
 		return TRUE;
 		return TRUE;
 
 
-	CProcessPaste paste(theApp.m_hTargetWnd);
+	CProcessPaste paste;
 	m_lstHeader.GetSelectionItemData( paste.GetClipIDs() );
 	m_lstHeader.GetSelectionItemData( paste.GetClipIDs() );
 
 
 	paste.DoPaste();
 	paste.DoPaste();
@@ -379,27 +380,42 @@ LRESULT CQPasteWnd::OnRefreshView(WPARAM wParam, LPARAM lParam)
 	return TRUE;
 	return TRUE;
 }
 }
 
 
-void CQPasteWnd::RefreshNc()
+void CQPasteWnd::RefreshNc( bool bRepaintImmediately )
 {
 {
-	if( theApp.m_bShowingQuickPaste )
+	if( !theApp.m_bShowingQuickPaste )
+		return;
+
+	if( bRepaintImmediately )
 		OnNcPaint();
 		OnNcPaint();
+	else
+		InvalidateNc();
 }
 }
 
 
-void CQPasteWnd::SetStatus( const char* status )
+void CQPasteWnd::UpdateStatus( bool bRepaintImmediately )
 {
 {
-CString title( QPASTE_TITLE );
+CString title = m_Title;
 CString prev;
 CString prev;
-	if( status && *status != '\0' )
+
+	GetWindowText(prev);
+
+	if( theApp.m_Status != "" )
 	{
 	{
 		title += " [ ";
 		title += " [ ";
-		title += status;
-		title += " ]";
+		title += theApp.m_Status;
+		title += " ] - ";
 	}
 	}
-	GetWindowText(prev);
+	else
+		title += " - ";
+
+	if( ::IsWindow(theApp.m_hTargetWnd) )
+		title += theApp.GetTargetName();
+	else
+		title += "NO TARGET!";
+
 	if( title != prev )
 	if( title != prev )
 	{
 	{
 		SetWindowText( title );
 		SetWindowText( title );
-		RefreshNc();
+		RefreshNc( bRepaintImmediately );
 	}
 	}
 }
 }
 
 
@@ -412,14 +428,7 @@ BOOL CQPasteWnd::FillList(CString csSQLSearch/*=""*/)
 
 
 	CRect crRect;
 	CRect crRect;
 	GetClientRect(crRect);
 	GetClientRect(crRect);
-
-	// Create the columns
-	if(m_lstHeader.InsertColumn(0, "", LVCFMT_LEFT, 2500, 0) != 0)
-	{	
-		ASSERT(FALSE);	
-		return -1;	
-	}
-
+ 
 	CString csSQL;
 	CString csSQL;
 	if(csSQLSearch == "")
 	if(csSQLSearch == "")
 	{
 	{
@@ -689,7 +698,7 @@ void CQPasteWnd::OnMenuExitprogram()
 
 
 void CQPasteWnd::OnMenuReconnecttoclipboardchain() 
 void CQPasteWnd::OnMenuReconnecttoclipboardchain() 
 {
 {
-	::SendMessage(theApp.GetClipboardViewer(), WM_RECONNECT_TO_COPY_CHAIN, 0, 0);
+	::SendMessage(theApp.GetClipboardViewer(), WM_CV_RECONNECT, 0, 0);
 }
 }
 
 
 void CQPasteWnd::OnMenuProperties() 
 void CQPasteWnd::OnMenuProperties() 

+ 4 - 2
QPasteWnd.h

@@ -59,8 +59,10 @@ public:
 	bool			m_bHideWnd;
 	bool			m_bHideWnd;
 	CMainTable		m_Recset;
 	CMainTable		m_Recset;
 
 
-	void RefreshNc();
-	void SetStatus( const char* status = NULL );
+	CString			m_Title;
+
+	void RefreshNc( bool bRepaintImmediately = false );
+	void UpdateStatus( bool bRepaintImmediately = false );  // regenerates the status (caption) text
 	BOOL FillList(CString csSQLSearch = "");
 	BOOL FillList(CString csSQLSearch = "");
 	BOOL HideQPasteWindow();
 	BOOL HideQPasteWindow();
 	BOOL ShowQPasteWindow(BOOL bFillList = TRUE);
 	BOOL ShowQPasteWindow(BOOL bFillList = TRUE);

+ 0 - 1
QuickPaste.cpp

@@ -78,7 +78,6 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, BOOL bAtPrevPos)
 		}
 		}
 	}
 	}
 
 
-	theApp.TargetActiveWindow();
 
 
 	CPoint ptCaret;
 	CPoint ptCaret;
 	GetFocusWnd(&ptCaret); // get caret position relative to screen
 	GetFocusWnd(&ptCaret); // get caret position relative to screen

+ 5 - 0
WndEx.cpp

@@ -29,6 +29,11 @@ CWndEx::~CWndEx()
 {
 {
 }
 }
 
 
+void CWndEx::InvalidateNc()
+{
+	::RedrawWindow( m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_NOINTERNALPAINT );
+}
+
 bool CWndEx::SetCaptionColors( COLORREF left, COLORREF right )
 bool CWndEx::SetCaptionColors( COLORREF left, COLORREF right )
 {
 {
 	if( left == m_CaptionColorLeft || right == m_CaptionColorRight )
 	if( left == m_CaptionColorLeft || right == m_CaptionColorRight )

+ 2 - 0
WndEx.h

@@ -39,6 +39,8 @@ public:
 	bool	SetCaptionColors( COLORREF left, COLORREF right );
 	bool	SetCaptionColors( COLORREF left, COLORREF right );
 	bool	SetCaptionColorActive( bool bVal );
 	bool	SetCaptionColorActive( bool bVal );
 
 
+	void	InvalidateNc();
+
 protected:
 protected:
 	CFont			m_TitleFont;
 	CFont			m_TitleFont;
 	bool			m_bResizable;
 	bool			m_bResizable;