Browse Source

moved methods for tracking active window to seperate class.

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@455 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 16 years ago
parent
commit
87e6be5371
18 changed files with 337 additions and 239 deletions
  1. 1 181
      CP_Main.cpp
  2. 3 13
      CP_Main.h
  3. 8 2
      CP_Main.vcproj
  4. 2 2
      DittoCopyBuffer.cpp
  5. 0 2
      DittoSetup/DittoSetup.iss
  6. 227 0
      ExternalWindowTracker.cpp
  7. 31 0
      ExternalWindowTracker.h
  8. 15 6
      MainFrm.cpp
  9. 1 0
      MainFrm.h
  10. 3 3
      Misc.cpp
  11. 6 1
      Options.cpp
  12. 1 0
      Options.h
  13. 2 2
      ProcessPaste.cpp
  14. 6 6
      QPasteWnd.cpp
  15. 1 1
      QuickPaste.cpp
  16. 26 15
      SendKeys.cpp
  17. 3 3
      SendKeys.h
  18. 1 2
      WndEx.cpp

+ 1 - 181
CP_Main.cpp

@@ -129,7 +129,6 @@ CCP_MainApp::CCP_MainApp()
 
 	m_QuickPasteMode = NONE_QUICK_PASTE;
 	m_pQuickPasteClip = NULL;
-	m_bDittoHasFocus = false;
 }
 
 CCP_MainApp::~CCP_MainApp()
@@ -255,16 +254,12 @@ BOOL CCP_MainApp::InitInstance()
 	CMainFrame* pFrame = new CMainFrame;
 	m_pMainWnd = m_pMainFrame = pFrame;
 
-	// prevent no one having focus on startup
-	TargetActiveWindow();
+	m_activeWnd.TrackActiveWnd();
 
 	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
 	pFrame->ShowWindow(SW_SHOW);
 	pFrame->UpdateWindow();
 
-	// prevent no one having focus on startup
-	ReleaseFocus();
-
 	m_Addins.LoadAll();
 
 	return TRUE;
@@ -356,152 +351,6 @@ void CCP_MainApp::BeforeMainClose()
 	StopCopyThread();
 }
 
-bool CCP_MainApp::TargetActiveWindow()
-{
-	HWND newActive = ::GetForegroundWindow();
-	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), TRUE);
-	HWND newFocus = GetFocus();
-	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), FALSE);
-
-	if(newFocus == 0 && newActive != 0)
-	{
-		newFocus = newActive;
-	}
-	else if(newActive == 0 && newFocus != 0)
-	{
-		newActive = newFocus;
-	}
-
-	if(newFocus == 0 || !IsWindow(newFocus) || newActive == 0 || !IsWindow(newActive))
-	{
-		Log(_T("TargetActiveWindow values invalid"));
-		return false;
-	}
-
-	if(newFocus == m_FocusWnd)
-	{
-//		Log(_T("TargetActiveWindow window the same"));
-		return false;
-	}
-
-	TCHAR className[50];
-	GetClassName(newFocus, className, sizeof(className));
-	if(STRCMP(className, _T("Shell_TrayWnd")) == 0)
-	{
-		Log(_T("TargetActiveWindow shell tray icon has focus"));
-		m_bDittoHasFocus = true;
-		return false;
-	}
-
-	if(IsAppWnd(newFocus))
-	{
-		Log(_T("TargetActiveWindow Ditto Has Focus"));
-		m_bDittoHasFocus = true;
-		return false;
-	}
-
-	m_FocusWnd = newFocus;
-	m_ActiveWnd = newActive;
-
-	if(QPasteWnd())
-		QPasteWnd()->UpdateStatus(true);
-
-	Log(StrF(_T("TargetActiveWindow Active: %d Focus: %d"), m_ActiveWnd, m_FocusWnd));
-	
-	return true;
-}
-
-bool CCP_MainApp::ActivateTarget()
-{
-	SetForegroundWindow(m_ActiveWnd);
-
-	AttachThreadInput(GetWindowThreadProcessId(m_ActiveWnd, NULL), GetCurrentThreadId(), TRUE);
-	SetFocus(m_FocusWnd);
-	AttachThreadInput(GetWindowThreadProcessId(m_ActiveWnd, NULL), GetCurrentThreadId(), FALSE);
-
-	return true;
-}
-
-bool CCP_MainApp::ReleaseFocus()
-{
-	if( IsAppWnd(::GetForegroundWindow()) )
-		return ActivateTarget();
-	return false;
-}
-
-// sends Ctrl-V to the TargetWnd
-void CCP_MainApp::SendPaste(bool bActivateTarget)
-{
-	CSendKeys send;
-	send.AllKeysUp();
-
-	CString csPasteToApp = GetProcessName(m_ActiveWnd);
-	CString csPasteString = g_Opt.GetPasteString(csPasteToApp);
-	DWORD delay = g_Opt.SendKeysDelay();
-
-	if(bActivateTarget && !ActivateTarget())
-	{
-		SetStatus(_T("SendPaste FAILED!"), TRUE);
-		return;
-	}
-	
-	PumpMessageEx();
-
-	Log(StrF(_T("Sending paste to app %s key stroke: %s, Delay: %d"), csPasteToApp, csPasteString, delay));
-
-	//give the app some time to take focus before sending paste
-	Sleep(delay);
-	send.SetKeyDownUpDelay(delay);
-	
-	send.SendKeys(csPasteString);
-}
-
-// sends Ctrl-V to the TargetWnd
-void CCP_MainApp::SendCopy()
-{
-	CSendKeys send;
-	send.AllKeysUp();
-
-	CString csToApp = GetProcessName(m_ActiveWnd);
-	CString csString = g_Opt.GetCopyString(csToApp);
-	DWORD delay = g_Opt.SendKeysDelay();
-
-	Sleep(delay);
-
-	PumpMessageEx();
-
-	Log(StrF(_T("Sending copy to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
-
-	//give the app some time to take focus before sending paste
-	Sleep(delay);
-	send.SetKeyDownUpDelay(delay);
-
-	send.SendKeys(csString);
-}
-
-// sends Ctrl-X to the TargetWnd
-void CCP_MainApp::SendCut()
-{
-	CSendKeys send;
-	send.AllKeysUp();
-
-	CString csToApp = GetProcessName(m_ActiveWnd);
-	CString csString = g_Opt.GetCopyString(csToApp);
-	DWORD delay = g_Opt.SendKeysDelay();
-
-	Sleep(delay);
-
-	PumpMessageEx();
-
-	Log(StrF(_T("Sending cut to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
-
-	//give the app some time to take focus before sending paste
-	Sleep(delay);
-	send.SetKeyDownUpDelay(delay);
-
-	send.SendKeys(csString);
-}
-
 void CCP_MainApp::StartCopyThread()
 {
 	ASSERT( m_MainhWnd );
@@ -893,34 +742,6 @@ BOOL CCP_MainApp::OnIdle(LONG lCount)
 	return FALSE;
 }
 
-CString CCP_MainApp::GetTargetName() 
-{
-	TCHAR cWindowText[200];
-	HWND hParent = m_ActiveWnd;
-
-	::GetWindowText(hParent, cWindowText, 100);
-
-	int nCount = 0;
-	
-	while(STRLEN(cWindowText) <= 0)
-	{
-		hParent = ::GetParent(hParent);
-		if(hParent == NULL)
-			break;
-
-		::GetWindowText(hParent, cWindowText, 100);
-
-		nCount++;
-		if(nCount > 100)
-		{
-			Log(_T("GetTargetName reached maximum search depth of 100"));
-			break;
-		}
-	}
-
-	return cWindowText; 
-}
-
 void CCP_MainApp::SetConnectCV(bool bConnect)
 { 
 	m_CopyThread.SetConnectCV(bConnect); 
@@ -945,7 +766,6 @@ void CCP_MainApp::OnDeleteID(long lID)
 	}
 }
 
-
 bool CCP_MainApp::ImportClips(HWND hWnd)
 {
 	OPENFILENAME	FileName;

+ 3 - 13
CP_Main.h

@@ -26,6 +26,7 @@
 #include "DittoCopyBuffer.h"
 #include "sqlite\CppSQLite3.h"
 #include "DittoAddins.h"
+#include "externalwindowtracker.h"
 
 //#define GET_APP ((CMainWnd*)theApp)
 extern class CCP_MainApp theApp;
@@ -81,17 +82,8 @@ public:
 	CHotKey		*m_pPasteBuffer3;
 	CHotKey		*m_pCutBuffer3;
 
-// Focus Tracking
-	HWND m_ActiveWnd;
-	HWND m_FocusWnd;
-	bool TargetActiveWindow();
-	bool ActivateTarget();
-	bool ReleaseFocus(); // activate the target only if we are the active window
-	CString GetTargetName();
-	void SendPaste(bool bActivateTarget); // Activates the Target and sends Ctrl-V
-	void SendCopy();
-	void SendCut();
-
+	ExternalWindowTracker m_activeWnd;
+	
 // CopyThread and ClipViewer (Copy and Paste Management)
 	CCopyThread	m_CopyThread;
 	void StartCopyThread();
@@ -188,8 +180,6 @@ public:
 
 	eQuickPasteMode m_QuickPasteMode;
 	CClipList* m_pQuickPasteClip;
-	
-	bool m_bDittoHasFocus;
 
 	CDittoCopyBuffer m_CopyBuffer;
 	void PumpMessageEx(HWND hWnd = NULL);

+ 8 - 2
CP_Main.vcproj

@@ -849,6 +849,9 @@
 			<File
 				RelativePath=".\EditWnd.cpp">
 			</File>
+			<File
+				RelativePath=".\ExternalWindowTracker.cpp">
+			</File>
 			<File
 				RelativePath="FileTransferProgressDlg.cpp">
 				<FileConfiguration
@@ -2723,6 +2726,9 @@
 			<File
 				RelativePath=".\EditWnd.h">
 			</File>
+			<File
+				RelativePath=".\ExternalWindowTracker.h">
+			</File>
 			<File
 				RelativePath="FileTransferProgressDlg.h">
 			</File>
@@ -2996,7 +3002,7 @@
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="Release\focus.dll">
+				RelativePath="Debug\focus.dll">
 				<FileConfiguration
 					Name="Release|Win32"
 					ExcludedFromBuild="TRUE">
@@ -3023,7 +3029,7 @@
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="Debug\focus.dll">
+				RelativePath="Release\focus.dll">
 				<FileConfiguration
 					Name="Release|Win32"
 					ExcludedFromBuild="TRUE">

+ 2 - 2
DittoCopyBuffer.cpp

@@ -31,11 +31,11 @@ bool CDittoCopyBuffer::StartCopy(long lCopyBuffer, bool bCut)
 	{
 		if(bCut)
 		{
-			theApp.SendCut();
+			theApp.m_activeWnd.SendCut();
 		}
 		else
 		{
-			theApp.SendCopy();
+			theApp.m_activeWnd.SendCopy();
 		}
 
 		//Create a thread to track if they have copied anything, if thread has exited before they have

+ 0 - 2
DittoSetup/DittoSetup.iss

@@ -94,8 +94,6 @@ Root: HKCU; Subkey: Software\Ditto\CutStrings; ValueType: string; ValueName: gvi
 Root: HKCU; Subkey: Software\Ditto\PasteStrings; ValueType: string; ValueName: cmd.exe; ValueData: % {{Delay100}ep
 Root: HKCU; Subkey: Software\Ditto\CopyStrings; ValueType: string; ValueName: cmd.exe; ValueData: % {{Delay100}ey
 
-Root: HKCU; Subkey: Software\Ditto\PasteStrings; ValueType: string; ValueName: opera.exe; ValueData: {{Delay100}^v
-
 ;associate .dto with Ditto
 Root: HKCR; Subkey: .dto; ValueType: string; ValueName: ; ValueData: Ditto; Flags: uninsdeletevalue
 Root: HKCR; Subkey: Ditto; ValueType: string; ValueName: ; ValueData: Ditto; Flags: uninsdeletekey

+ 227 - 0
ExternalWindowTracker.cpp

@@ -0,0 +1,227 @@
+#include "stdafx.h"
+#include "externalwindowtracker.h"
+#include "Misc.h"
+#include "SendKeys.h"
+#include "Options.h"
+#include "CP_Main.h"
+
+ExternalWindowTracker::ExternalWindowTracker(void)
+{
+	m_activeWnd = NULL;
+	m_focusWnd = NULL;
+	m_dittoHasFocus = false;
+}
+
+ExternalWindowTracker::~ExternalWindowTracker(void)
+{
+}
+
+bool ExternalWindowTracker::TrackActiveWnd()
+{
+	HWND newActive = ::GetForegroundWindow();
+	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), TRUE);
+	HWND newFocus = GetFocus();
+	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), FALSE);
+
+	if(newFocus == 0 && newActive != 0)
+	{
+		newFocus = newActive;
+	}
+	else if(newActive == 0 && newFocus != 0)
+	{
+		newActive = newFocus;
+	}
+
+	if(newFocus == 0 || !IsWindow(newFocus) || newActive == 0 || !IsWindow(newActive))
+	{
+		Log(_T("TargetActiveWindow values invalid"));
+		return false;
+	}
+
+	if(newFocus == m_focusWnd)
+	{
+//			Log(_T("TargetActiveWindow window the same"));
+		return false;
+	}
+
+	TCHAR className[50];
+	GetClassName(newFocus, className, (sizeof(className) / sizeof(TCHAR)));
+	if(STRCMP(className, _T("Shell_TrayWnd")) == 0)
+	{
+		Log(_T("TargetActiveWindow shell tray icon has focus"));
+		return false;
+	}
+
+	GetClassName(newActive, className, (sizeof(className) / sizeof(TCHAR)));
+	if(STRCMP(className, _T("Shell_TrayWnd")) == 0)
+	{
+		Log(_T("TargetActiveWindow shell tray icon has active"));
+		return false;
+	}
+
+	if(IsAppWnd(newFocus))
+	{
+		m_dittoHasFocus = true;
+		return false;
+	}
+
+	m_focusWnd = newFocus;
+	m_activeWnd = newActive;
+	m_dittoHasFocus = false;
+
+	if(theApp.QPasteWnd())
+		theApp.QPasteWnd()->UpdateStatus(true);
+
+	Log(StrF(_T("TargetActiveWindow Active: %d Focus: %d"), m_activeWnd, m_focusWnd));
+
+	return true;
+}
+
+bool ExternalWindowTracker::WaitForFocus(HWND focusWnd, int timeout)
+{
+	DWORD start = GetTickCount();
+	while(((int)(GetTickCount() - start)) < timeout)
+	{
+		if(::GetForegroundWindow() == focusWnd)
+		{
+			Log(StrF(_T("found focus wait %d"), GetTickCount()-start));
+			return true;
+		}
+
+		Sleep(0);
+		ActivateTarget();
+	}
+
+	Log(_T("Didn't find focus"));
+	return false;
+}
+
+bool ExternalWindowTracker::ActivateTarget()
+{
+	Log(StrF(_T("Activate Target - Active: %d Focus: %d"), m_activeWnd, m_focusWnd));
+
+	SetForegroundWindow(m_activeWnd);
+
+	AttachThreadInput(GetWindowThreadProcessId(m_activeWnd, NULL), GetCurrentThreadId(), TRUE);
+	SetFocus(m_focusWnd);
+	AttachThreadInput(GetWindowThreadProcessId(m_activeWnd, NULL), GetCurrentThreadId(), FALSE);
+
+	return true;
+}
+
+void ExternalWindowTracker::SendPaste(bool activateTarget)
+{
+	CSendKeys send;
+	send.AllKeysUp();
+
+	CString csPasteToApp = GetProcessName(m_activeWnd);
+	CString csPasteString = g_Opt.GetPasteString(csPasteToApp);
+	DWORD delay = g_Opt.SendKeysDelay();
+
+	if(activateTarget)
+	{
+		ActivateTarget();
+		theApp.PumpMessageEx();
+		WaitForFocus(m_activeWnd, max(25, g_Opt.WaitForFocusTimeout()));
+	}
+	else
+	{
+		theApp.PumpMessageEx();
+	}
+
+	m_dittoHasFocus = false;
+	Log(StrF(_T("Sending paste to app %s key stroke: %s, SeDelay: %d"), csPasteToApp, csPasteString, delay));
+
+	send.SetKeyDownDelay(max(50, delay));
+
+	send.SendKeys(csPasteString, true);
+
+	Log(_T("Post sending paste"));
+}
+
+void ExternalWindowTracker::SendCopy()
+{
+	CSendKeys send;
+	send.AllKeysUp();
+
+	CString csToApp = GetProcessName(m_activeWnd);
+	CString csString = g_Opt.GetCopyString(csToApp);
+	DWORD delay = g_Opt.SendKeysDelay();
+
+	Sleep(delay);
+
+	theApp.PumpMessageEx();
+
+	Log(StrF(_T("Sending copy to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
+
+	//give the app some time to take focus before sending paste
+	Sleep(delay);
+	send.SetKeyDownDelay(max(50, delay));
+
+	send.SendKeys(csString, true);
+
+	Log(_T("Post sending copy"));
+}
+
+// sends Ctrl-X to the TargetWnd
+void ExternalWindowTracker::SendCut()
+{
+	CSendKeys send;
+	send.AllKeysUp();
+
+	CString csToApp = GetProcessName(m_activeWnd);
+	CString csString = g_Opt.GetCopyString(csToApp);
+	DWORD delay = g_Opt.SendKeysDelay();
+
+	Sleep(delay);
+
+	theApp.PumpMessageEx();
+
+	Log(StrF(_T("Sending cut to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
+
+	//give the app some time to take focus before sending paste
+	Sleep(delay);
+	send.SetKeyDownDelay(max(50, delay));
+
+	send.SendKeys(csString, true);
+
+	Log(_T("Post sending cut"));
+}
+
+CString ExternalWindowTracker::ActiveWndName() 
+{
+	TCHAR cWindowText[200];
+	HWND hParent = m_activeWnd;
+
+	::GetWindowText(hParent, cWindowText, 100);
+
+	int nCount = 0;
+
+	while(STRLEN(cWindowText) <= 0)
+	{
+		hParent = ::GetParent(hParent);
+		if(hParent == NULL)
+			break;
+
+		::GetWindowText(hParent, cWindowText, 100);
+
+		nCount++;
+		if(nCount > 100)
+		{
+			Log(_T("GetTargetName reached maximum search depth of 100"));
+			break;
+		}
+	}
+
+	return cWindowText; 
+}
+
+bool ExternalWindowTracker::ReleaseFocus()
+{
+	if( IsAppWnd(::GetForegroundWindow()) )
+	{
+		return ActivateTarget();
+	}
+
+	return false;
+}

+ 31 - 0
ExternalWindowTracker.h

@@ -0,0 +1,31 @@
+#pragma once
+
+class ExternalWindowTracker
+{
+public:
+	ExternalWindowTracker(void);
+	~ExternalWindowTracker(void);
+
+	HWND ActiveWnd() const { return m_activeWnd; }
+	HWND FocusWnd() const { return m_focusWnd; }
+	bool DittoHasFocus() const { return m_dittoHasFocus; }
+
+	CString ActiveWndName();
+	bool TrackActiveWnd();
+	bool ActivateTarget();
+	bool ReleaseFocus();
+
+	void SendPaste(bool activateTarget);
+	void SendCut();
+	void SendCopy();
+
+	
+
+protected:
+	HWND m_activeWnd;
+	HWND m_focusWnd;
+	bool m_dittoHasFocus;
+	
+protected:
+	bool WaitForFocus(HWND hwndToHaveFocus, int timeout);
+};

+ 15 - 6
MainFrm.cpp

@@ -126,7 +126,13 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	SetWindowText(_T(""));
 
 	if(g_Opt.m_bUseHookDllForFocus)
+	{
 		MonitorFocusChanges(m_hWnd, WM_FOCUS_CHANGED);
+	}
+	else
+	{
+		SetTimer(ACTIVE_WINDOW_TIMER, 5000, 0);
+	}
 	
 	SetWindowText(_T("Ditto"));
 
@@ -265,7 +271,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 			m_startKeyStateTime = GetTickCount();
 			m_keyStateModifiers = GetKeyStateModifiers();
 			SetTimer(KEY_STATE_MODIFIERS, 50, NULL);
-			theApp.TargetActiveWindow();
+			theApp.m_activeWnd.TrackActiveWnd();
 			QuickPaste.ShowQPasteWnd(this, false, true, FALSE);
 		}		
 	}
@@ -277,7 +283,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 			{
 				theApp.m_QuickPasteMode = CCP_MainApp::ADDING_QUICK_PASTE;
 
-				theApp.SendCopy();
+				theApp.m_activeWnd.SendCopy();
 
 				m_pTypingToolTip = new CToolTipEx;
 				m_pTypingToolTip->Create(this);
@@ -293,7 +299,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 				if(m_ToolTipPoint.x < 0 || m_ToolTipPoint.y < 0)
 				{
 					CRect cr;
-					::GetWindowRect(theApp.m_FocusWnd, cr);
+					::GetWindowRect(theApp.m_activeWnd.FocusWnd(), cr);
 					m_ToolTipPoint = cr.CenterPoint();
 				}
 				m_ToolTipPoint.Offset(-15, 15);
@@ -327,7 +333,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 				if(m_ToolTipPoint.x < 0 || m_ToolTipPoint.y < 0)
 				{
 					CRect cr;
-					::GetWindowRect(theApp.m_FocusWnd, cr);
+					::GetWindowRect(theApp.m_activeWnd.FocusWnd(), cr);
 					m_ToolTipPoint = cr.CenterPoint();
 				}
 				m_ToolTipPoint.Offset(-15, 15);
@@ -587,6 +593,9 @@ void CMainFrame::OnTimer(UINT nIDEvent)
 			KillTimer(KEY_STATE_MODIFIERS);
 		}
 		break;
+	case ACTIVE_WINDOW_TIMER:
+		theApp.m_activeWnd.TrackActiveWnd();
+		break;
 	}
 
 	CFrameWnd::OnTimer(nIDEvent);
@@ -687,7 +696,7 @@ BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
 	if( theApp.m_bShowingQuickPaste &&
 		WM_MOUSEFIRST <= pMsg->message && pMsg->message <= WM_MOUSELAST )
 	{	
-		theApp.TargetActiveWindow(); 
+		theApp.m_activeWnd.TrackActiveWnd();
 	}
 
 	return CFrameWnd::PreTranslateMessage(pMsg);
@@ -903,7 +912,7 @@ LRESULT CMainFrame::OnFocusChanged(WPARAM wParam, LPARAM lParam)
 	if(g_Opt.m_bUseHookDllForFocus == FALSE)
 		return TRUE;
 	
-	theApp.TargetActiveWindow();
+	theApp.m_activeWnd.TrackActiveWnd();
 
 	return TRUE;
 }

+ 1 - 0
MainFrm.h

@@ -25,6 +25,7 @@
 #define REMOVE_OLD_REMOTE_COPIES		9
 #define END_DITTO_BUFFER_CLIPBOARD_TIMER	10
 #define KEY_STATE_MODIFIERS				11
+#define ACTIVE_WINDOW_TIMER				12
 
 class CMainFrame : public CFrameWnd
 {

+ 3 - 3
Misc.cpp

@@ -207,18 +207,18 @@ CPoint GetFocusedCaretPos()
 {
 	CPoint pt(-1, -1);
 
-	if(theApp.m_ActiveWnd)
+	if(theApp.m_activeWnd.ActiveWnd())
 	{
 		GUITHREADINFO guiThreadInfo;
 		guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
-		DWORD OtherThreadID = GetWindowThreadProcessId(theApp.m_ActiveWnd, NULL);
+		DWORD OtherThreadID = GetWindowThreadProcessId(theApp.m_activeWnd.ActiveWnd(), NULL);
 		if(GetGUIThreadInfo(OtherThreadID, &guiThreadInfo))
 		{
 			CRect rc(guiThreadInfo.rcCaret);
 			if(rc.IsRectEmpty() == FALSE)
 			{
 				pt = rc.BottomRight();
-				::ClientToScreen(theApp.m_FocusWnd, &pt);
+				::ClientToScreen(theApp.m_activeWnd.FocusWnd(), &pt);
 			}
 		}
 	}

+ 6 - 1
Options.cpp

@@ -1875,5 +1875,10 @@ DWORD CGetSetOptions::GetDittoHotKey()
 
 DWORD CGetSetOptions::SendKeysDelay()
 {
-	return (DWORD)GetProfileLong(_T("SendKeysDelay"), 100);
+	return (DWORD)GetProfileLong(_T("SendKeysDelay"), 50);
 }
+
+DWORD CGetSetOptions::WaitForFocusTimeout()
+{
+	return (DWORD)GetProfileLong(_T("WaitForFocusTimeout"), 100);
+}

+ 1 - 0
Options.h

@@ -384,6 +384,7 @@ public:
 
 	static DWORD	GetDittoHotKey();
 	static DWORD	SendKeysDelay();
+	static DWORD	WaitForFocusTimeout();
 };
 
 // global for easy access and for initialization of fast access variables

+ 2 - 2
ProcessPaste.cpp

@@ -59,12 +59,12 @@ BOOL CProcessPaste::DoPaste()
 //#ifndef _DEBUG
 		if(m_bSendPaste)
 		{
-			theApp.SendPaste(m_bActivateTarget);
+			theApp.m_activeWnd.SendPaste(m_bActivateTarget);
 		}
 //#else
 		if(m_bActivateTarget)
 		{
-			theApp.ActivateTarget();
+			theApp.m_activeWnd.ActivateTarget();
 		}
 //#endif
 		return TRUE;

+ 6 - 6
QPasteWnd.cpp

@@ -428,9 +428,9 @@ BOOL CQPasteWnd::HideQPasteWindow()
 		m_bStopQuery = true;
 	m_CritSection.Unlock();
 
-	//Reset the flag
+	//Reset the flagShell_TrayWnd
 	theApp.m_bShowingQuickPaste = false;
-	theApp.ReleaseFocus();
+	theApp.m_activeWnd.ReleaseFocus();
 	
 	SetEvent(m_Events[THREAD_DESTROY_ACCELERATORS]);
 //	m_lstHeader.DestroyAndCreateAccelerator(FALSE);
@@ -584,7 +584,7 @@ BOOL CQPasteWnd::OpenID(long lID, bool bOnlyLoad_CF_TEXT, bool bPasteHTMLAs_CF_T
 	theApp.OnPasteCompleted();
 
 	if(g_Opt.m_bSendPasteMessageAfterSelection == FALSE)
-		theApp.ActivateTarget();
+		theApp.m_activeWnd.ActivateTarget();
 
 	if(g_Opt.m_bShowPersistent && g_Opt.GetAutoHide())
 		MinMaxWindow(FORCE_MIN);
@@ -621,7 +621,7 @@ BOOL CQPasteWnd::OpenSelection(bool bOnlyLoad_CF_TEXT, bool bPasteHTMLAs_CF_TEXT
 	theApp.OnPasteCompleted();
 
 	if(g_Opt.m_bSendPasteMessageAfterSelection == FALSE)
-		theApp.ActivateTarget();
+		theApp.m_activeWnd.ActivateTarget();
 
 	if(g_Opt.m_bShowPersistent && g_Opt.GetAutoHide())
 		MinMaxWindow(FORCE_MIN);
@@ -801,8 +801,8 @@ void CQPasteWnd::UpdateStatus(bool bRepaintImmediately)
 		title += " - ";
 	}
 	
-	if( ::IsWindow(theApp.m_ActiveWnd) )
-		title += theApp.GetTargetName();
+	if(::IsWindow(theApp.m_activeWnd.ActiveWnd()))
+		title += theApp.m_activeWnd.ActiveWndName();
 	else
 		title += theApp.m_Language.GetString("No_Target", "No target");
 	

+ 1 - 1
QuickPaste.cpp

@@ -132,7 +132,7 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 	if(ptCaret.x <= 0 || ptCaret.y <= 0)
 	{
 		CRect cr;
-		::GetWindowRect(theApp.m_FocusWnd, cr);
+		::GetWindowRect(theApp.m_activeWnd.FocusWnd(), cr);
 		if(cr.PtInRect(ptCaret) == FALSE)
 		{
 			ptCaret = cr.CenterPoint();

+ 26 - 15
SendKeys.cpp

@@ -76,12 +76,14 @@ const BYTE CSendKeys::ExtendedVKeys[MaxExtendedVKeys] =
     VK_PRIOR, // PgUp
     VK_NEXT,  //  PgDn
     VK_INSERT,
-    VK_DELETE
+    VK_DELETE,
+	VK_CONTROL,
+	VK_SHIFT,
 };
 
 CSendKeys::CSendKeys()
 {
-  m_nDelayNow = m_nDelayAlways = 0;
+  m_nDelayNow = m_nDelayAlways = m_keyDownDelay = 0;
 }
 
 // Delphi port regexps:
@@ -168,21 +170,21 @@ CSendKeys::key_desc_t CSendKeys::KeyNames[CSendKeys::MaxSendKeysRecs] =
 };
 
 
+
 // calls keybd_event() and waits, if needed, till the sent input is processed
 void CSendKeys::KeyboardEvent(BYTE VKey, BYTE ScanCode, LONG Flags)
 {
-  MSG KeyboardMsg;
-
-  keybd_event(VKey, ScanCode, Flags, 0);
+	keybd_event(VKey, ScanCode, Flags, 0);
 
-  if (m_bWait)
-  {
-    while (::PeekMessage(&KeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
-    {
-      ::TranslateMessage(&KeyboardMsg);
-      ::DispatchMessage(&KeyboardMsg);
-    }
-  }
+	if (m_bWait)
+	{
+		MSG KeyboardMsg;
+		while (::PeekMessage(&KeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
+		{
+			::TranslateMessage(&KeyboardMsg);
+			::DispatchMessage(&KeyboardMsg);
+		}
+	}
 }
 
 // Checks whether the specified VKey is an extended key or not
@@ -282,9 +284,9 @@ void CSendKeys::SendKeyDown(BYTE VKey, WORD NumTimes, bool GenUpMsg, bool bDelay
 
     KeyboardEvent(VKey, ScanCode, IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0);
     
-	if(m_keyDowUpDelay > 0)
+	if(m_keyDownDelay > 0)
 	{
-		Sleep(m_keyDowUpDelay);
+		Sleep(m_keyDownDelay);
 	}
 
 	if (GenUpMsg)
@@ -367,13 +369,22 @@ void CSendKeys::PopUpShiftKeys()
   if (!m_bUsingParens)
   {
     if (m_bShiftDown)
+	{
       SendKeyUp(VK_SHIFT);
+	}
     if (m_bControlDown)
+	{
       SendKeyUp(VK_CONTROL);
+	}
     if (m_bAltDown)
+	{
       SendKeyUp(VK_MENU);
+	}
     if (m_bWinDown)
+	{
       SendKeyUp(VK_LWIN);
+	}
+
     m_bWinDown = m_bShiftDown = m_bControlDown = m_bAltDown = false;
   }
 }

+ 3 - 3
SendKeys.h

@@ -9,7 +9,7 @@ class CSendKeys
 {
 private:
   bool m_bWait, m_bUsingParens, m_bShiftDown, m_bAltDown, m_bControlDown, m_bWinDown;
-  DWORD  m_nDelayAlways, m_nDelayNow, m_keyDowUpDelay;
+  DWORD  m_nDelayAlways, m_nDelayNow, m_keyDownDelay;
 
   static BOOL CALLBACK enumwindowsProc(HWND hwnd, LPARAM lParam);
   void   CarryDelay();
@@ -31,7 +31,7 @@ private:
   enum
   {
     MaxSendKeysRecs  = 71,
-    MaxExtendedVKeys = 10
+    MaxExtendedVKeys = 12
   };
 
   /*
@@ -72,7 +72,7 @@ public:
   static bool AppActivate(HWND wnd);
   static bool AppActivate(LPCTSTR WindowTitle, LPCTSTR WindowClass = 0);
   void SetDelay(const DWORD delay) { m_nDelayAlways = delay; }
-  void SetKeyDownUpDelay(const DWORD delay) { m_keyDowUpDelay = delay; }
+  void SetKeyDownDelay(const DWORD delay) { m_keyDownDelay = delay; }
   CSendKeys();
 };
 

+ 1 - 2
WndEx.cpp

@@ -374,11 +374,10 @@ void CWndEx::OnTimer(UINT nIDEvent)
 			
 			if(cr.PtInRect(cp) == false)        
 			{
-				//theApp.m_bDittoHasFocus is only set when we are using the 
 				//hook dll
 				if(g_Opt.m_bUseHookDllForFocus)
 				{
-					if(theApp.m_bDittoHasFocus == false)
+					if(theApp.m_activeWnd.DittoHasFocus() == false)
 					{
 						MinMaxWindow(FORCE_MIN);
 					}