Browse Source

handle getting the currently focused window better

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@454 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 16 years ago
parent
commit
08797adad1

BIN
Addins/OutlookExpress/Release/OutlookExpress.dll


+ 51 - 63
CP_Main.cpp

@@ -356,78 +356,68 @@ void CCP_MainApp::BeforeMainClose()
 	StopCopyThread();
 }
 
-/*
-Re: Targeting the previous focus window
-
-We usually gain focus after the following messages:
-keyboard: WM_KEYUP(0x0101),WM_CHAR(0x0102),WM_HOTKEY(0x0312)
-mouse: WM_MOUSEFIRST(0x0200),WM_MOUSEMOVE(0x0200),WM_LBUTTONDOWN(0x0201)
-
-CMainFrame::PreTranslateMessage is used to intercept messages before
-they are processed (before we are actually given focus) in order to
-save the previous window that had focus.
-- It currently just handles "activating" mouse messages when showing.
-
-ShowQPasteWnd also has a call to "TargetActiveWindow" which handles
-finding the Target on hotkey activation.
-
-This works well for most window switching (mouse or hotkey), but does
-not work well for <Alt>-<Tab> or other window switching applications
-(e.g. the taskbar tray), since the previous window was only a means to
-switching and not the target itself.
-- one solution might be to always monitor the current foreground
-window using system hooks or a short (e.g. 1 sec) timer... though this
-*might* be cpu intensive (slow).  I'm currently looking into using
-WH_CBT system hooks in a separate dll (see: robpitt's
-http://website.lineone.net/~codebox/focuslog.zip).
-*/
 bool CCP_MainApp::TargetActiveWindow()
 {
-	if(g_Opt.m_bUseHookDllForFocus)
-		return true;
-
-	HWND hOld = m_hTargetWnd;
-	GUITHREADINFO guiThreadInfo;
-	guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
-	HWND hNew = ::GetForegroundWindow();
-	DWORD OtherThreadID = GetWindowThreadProcessId(hNew, NULL);
-	if(GetGUIThreadInfo(OtherThreadID, &guiThreadInfo))
+	HWND newActive = ::GetForegroundWindow();
+	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), TRUE);
+	HWND newFocus = GetFocus();
+	AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), FALSE);
+
+	if(newFocus == 0 && newActive != 0)
 	{
-		if(guiThreadInfo.hwndFocus != NULL)
-		{
-			hNew = guiThreadInfo.hwndFocus;
-		}
+		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(hNew == m_hTargetWnd || !::IsWindow(hNew) || IsAppWnd(hNew))
-		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;
 
-	m_hTargetWnd = hNew;
-	
 	if(QPasteWnd())
 		QPasteWnd()->UpdateStatus(true);
 
-	// Tracking / Debugging
-	//Log( StrF(
-	//	_T("Target Changed") \
-	//	_T("\n\tOld = 0x%08x: \"%s\"") \
-	//	_T("\n\tNew = 0x%08x:  \"%s\"\n"),
-	//		hOld, (LPCTSTR) GetWndText(hOld),
-	//		hNew, (LPCTSTR) GetWndText(hNew) ) );
+	Log(StrF(_T("TargetActiveWindow Active: %d Focus: %d"), m_ActiveWnd, m_FocusWnd));
 	
 	return true;
 }
 
 bool CCP_MainApp::ActivateTarget()
 {
-	if (m_hTargetWnd != NULL) 
-	{
-		SetForegroundWindow(m_hTargetWnd);
+	SetForegroundWindow(m_ActiveWnd);
 
-		AttachThreadInput(GetWindowThreadProcessId(m_hTargetWnd, NULL), GetCurrentThreadId(), TRUE);
-		SetFocus(m_hTargetWnd);
-		AttachThreadInput(GetWindowThreadProcessId(m_hTargetWnd, NULL), GetCurrentThreadId(), FALSE);
-	}
+	AttachThreadInput(GetWindowThreadProcessId(m_ActiveWnd, NULL), GetCurrentThreadId(), TRUE);
+	SetFocus(m_FocusWnd);
+	AttachThreadInput(GetWindowThreadProcessId(m_ActiveWnd, NULL), GetCurrentThreadId(), FALSE);
 
 	return true;
 }
@@ -445,18 +435,16 @@ void CCP_MainApp::SendPaste(bool bActivateTarget)
 	CSendKeys send;
 	send.AllKeysUp();
 
-	CString csPasteToApp = GetProcessName(m_hTargetWnd);
+	CString csPasteToApp = GetProcessName(m_ActiveWnd);
 	CString csPasteString = g_Opt.GetPasteString(csPasteToApp);
 	DWORD delay = g_Opt.SendKeysDelay();
 
-	Sleep(delay);
-
 	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));
@@ -474,7 +462,7 @@ void CCP_MainApp::SendCopy()
 	CSendKeys send;
 	send.AllKeysUp();
 
-	CString csToApp = GetProcessName(m_hTargetWnd);
+	CString csToApp = GetProcessName(m_ActiveWnd);
 	CString csString = g_Opt.GetCopyString(csToApp);
 	DWORD delay = g_Opt.SendKeysDelay();
 
@@ -497,7 +485,7 @@ void CCP_MainApp::SendCut()
 	CSendKeys send;
 	send.AllKeysUp();
 
-	CString csToApp = GetProcessName(m_hTargetWnd);
+	CString csToApp = GetProcessName(m_ActiveWnd);
 	CString csString = g_Opt.GetCopyString(csToApp);
 	DWORD delay = g_Opt.SendKeysDelay();
 
@@ -908,7 +896,7 @@ BOOL CCP_MainApp::OnIdle(LONG lCount)
 CString CCP_MainApp::GetTargetName() 
 {
 	TCHAR cWindowText[200];
-	HWND hParent = m_hTargetWnd;
+	HWND hParent = m_ActiveWnd;
 
 	::GetWindowText(hParent, cWindowText, 100);
 

+ 2 - 1
CP_Main.h

@@ -82,7 +82,8 @@ public:
 	CHotKey		*m_pCutBuffer3;
 
 // Focus Tracking
-	HWND m_hTargetWnd;
+	HWND m_ActiveWnd;
+	HWND m_FocusWnd;
 	bool TargetActiveWindow();
 	bool ActivateTarget();
 	bool ReleaseFocus(); // activate the target only if we are the active window

+ 5 - 2
DittoSetup/DittoSetup.iss

@@ -3,8 +3,8 @@
 
 [Setup]
 AppName=Ditto
-AppVerName=Ditto 3.16.2.0
-OutputBaseFilename=DittoSetup_3_16_2_0
+AppVerName=Ditto 3.16.3.0
+OutputBaseFilename=DittoSetup_3_16_3_0
 AppPublisher=Scott Brogden
 AppPublisherURL=ditto-cp.sourceforge.net
 AppSupportURL=ditto-cp.sourceforge.net
@@ -35,6 +35,7 @@ Name: Turkish; MessagesFile: Turkish.isl
 Name: Japanese; MessagesFile: Japanese.isl
 Name: Chinese; MessagesFile: ChineseSimp.isl
 Name: Romanian; MessagesFile: Romanian.isl
+Name: Korean; MessagesFile: Korean.isl
 
 
 [Tasks]
@@ -93,6 +94,8 @@ 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

BIN
EncryptDecrypt.lib


+ 6 - 79
MainFrm.cpp

@@ -293,7 +293,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 				if(m_ToolTipPoint.x < 0 || m_ToolTipPoint.y < 0)
 				{
 					CRect cr;
-					::GetWindowRect(theApp.m_hTargetWnd, cr);
+					::GetWindowRect(theApp.m_FocusWnd, cr);
 					m_ToolTipPoint = cr.CenterPoint();
 				}
 				m_ToolTipPoint.Offset(-15, 15);
@@ -327,7 +327,7 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 				if(m_ToolTipPoint.x < 0 || m_ToolTipPoint.y < 0)
 				{
 					CRect cr;
-					::GetWindowRect(theApp.m_hTargetWnd, cr);
+					::GetWindowRect(theApp.m_FocusWnd, cr);
 					m_ToolTipPoint = cr.CenterPoint();
 				}
 				m_ToolTipPoint.Offset(-15, 15);
@@ -686,7 +686,9 @@ BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
 	// target before mouse messages change the focus
 	if( theApp.m_bShowingQuickPaste &&
 		WM_MOUSEFIRST <= pMsg->message && pMsg->message <= WM_MOUSELAST )
-	{	theApp.TargetActiveWindow(); }
+	{	
+		theApp.TargetActiveWindow(); 
+	}
 
 	return CFrameWnd::PreTranslateMessage(pMsg);
 }
@@ -901,82 +903,7 @@ LRESULT CMainFrame::OnFocusChanged(WPARAM wParam, LPARAM lParam)
 	if(g_Opt.m_bUseHookDllForFocus == FALSE)
 		return TRUE;
 	
-	HWND hFocus = (HWND)wParam;
-	HWND hParent = hFocus;
-	HWND hLastGoodParent = hParent;
-	static DWORD dLastDittoHasFocusTick = 0;
-
-	//Sometimes when we bring ditto up there will come a null focus 
-	//rite after that
-	if(hFocus == NULL && (GetTickCount() - dLastDittoHasFocusTick < 500))
-	{
-		Log(_T("NULL focus within 500 ticks of bringing up ditto"));
-		return TRUE;
-	}
-	else if(hFocus == NULL)
-	{
-		Log(_T("NULL focus received"));
-	}
-
-	//only proceed if something changed
-	if(theApp.m_hTargetWnd == hFocus)
-		return TRUE;
-
-	TCHAR cWindowText[100];
-	::GetWindowText(hFocus, cWindowText, 100);
-
-	HWND hTray = ::FindWindow(_T("Shell_TrayWnd"), _T(""));
-
-	//Log(StrF(_T("Focus = %d"), hFocus));
-
-	int nCount = 0;
-	while(true)
-	{
-		hParent = ::GetParent(hParent);
-		if(hParent == NULL)
-			break;
-
-		//Log(StrF(_T("Focus2 = %d"), hParent));
-
-		//allow focus on edit window
-		if(m_pEditFrameWnd && hParent == m_pEditFrameWnd->GetSafeHwnd())
-		{
-			break;
-		}		
-
-		hLastGoodParent = hParent;  
-
-		nCount++;
-		if(nCount > 100)
-		{
-			Log(_T("OnFocusChanged reached maximum search depth of 100"));
-			break;
-		}
-	}
-
-	
-	//If the parent is ditto or the tray icon then don't set focus to that window
-	if(hLastGoodParent == m_hWnd || hLastGoodParent == hTray)
-	{
-		Log(_T("Ditto Has Focus"));
-		theApp.m_bDittoHasFocus = true;
-		dLastDittoHasFocusTick = GetTickCount();   
-	}
-	else if(IsWindow(hFocus) == FALSE)
-	{
-		Log( StrF(_T("Invalid focus window 0x%08x"), hFocus));
-		theApp.m_bDittoHasFocus = false;
-	}
-	else
-	{
-		//Log( StrF(_T("SetTarget 0x%08x: \"%s\""), hFocus, GetWndText(hFocus)));
-
-		theApp.m_bDittoHasFocus = false;
-
-		theApp.m_hTargetWnd = hFocus;
-		if(theApp.QPasteWnd() )
-			theApp.QPasteWnd()->UpdateStatus(true);
-	}
+	theApp.TargetActiveWindow();
 
 	return TRUE;
 }

+ 3 - 3
Misc.cpp

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

+ 1 - 1
Options.cpp

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

+ 1 - 1
QPasteWnd.cpp

@@ -801,7 +801,7 @@ void CQPasteWnd::UpdateStatus(bool bRepaintImmediately)
 		title += " - ";
 	}
 	
-	if( ::IsWindow(theApp.m_hTargetWnd) )
+	if( ::IsWindow(theApp.m_ActiveWnd) )
 		title += theApp.GetTargetName();
 	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_hTargetWnd, cr);
+		::GetWindowRect(theApp.m_FocusWnd, cr);
 		if(cr.PtInRect(ptCaret) == FALSE)
 		{
 			ptCaret = cr.CenterPoint();

BIN
Release/focus.lib


BIN
UEncryptDecrypt.lib


BIN
focusdll/Release/focus.dll


BIN
focusdll/Release/focus.lib