فهرست منبع

added hook to get focus for corrent window. Allows ditto to work when being activated by the mouse

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@82 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 21 سال پیش
والد
کامیت
b5f409a08b
15فایلهای تغییر یافته به همراه235 افزوده شده و 6 حذف شده
  1. 47 0
      CP_Main.cpp
  2. 7 3
      CP_Main.dsp
  3. 13 1
      CP_Main.dsw
  4. 7 1
      CP_Main.h
  5. BIN
      Debug/focus.dll
  6. BIN
      Debug/focus.lib
  7. 47 1
      MainFrm.cpp
  8. 1 0
      MainFrm.h
  9. 2 0
      Misc.cpp
  10. 4 0
      Misc.h
  11. BIN
      Release/focus.dll
  12. BIN
      Release/focus.lib
  13. 10 0
      focusdll/focus.dsp
  14. 76 0
      focusdll/focusdll.cpp
  15. 21 0
      focusdll/focusdll.h

+ 47 - 0
CP_Main.cpp

@@ -62,10 +62,18 @@ CCP_MainApp::CCP_MainApp()
 	m_bAsynchronousRefreshView = true;
 
 	::InitializeCriticalSection(&m_CriticalSection);
+
+	m_hHookDll = NULL;
+	m_MonitorFocusChanges = NULL;
+	m_StopMonitoringFocusChanges = NULL;
+	m_GetCurrentFocus = NULL;
 }
 
 CCP_MainApp::~CCP_MainApp()
 {
+	if(m_hHookDll)
+		FreeLibrary(m_hHookDll);
+
 	::DeleteCriticalSection(&m_CriticalSection);
 }
 
@@ -99,6 +107,23 @@ BOOL CCP_MainApp::InitInstance()
 
 	AfxOleInit();
 
+//	if(g_Opt.m_bUseHookDllForFocus)
+//	{
+//		m_hHookDll = LoadLibrary("focus.dll");
+//		if(m_hHookDll)
+//		{
+//			m_MonitorFocusChanges = (DWORD(*)(HWND,UINT))GetProcAddress(m_hHookDll, "_MonitorFocusChanges@8");
+//			m_StopMonitoringFocusChanges = (DWORD(*)())GetProcAddress(m_hHookDll, "_StopMonitoringFocusChanges@0");
+//			m_GetCurrentFocus = (HWND(*)())GetProcAddress(m_hHookDll, "_GetCurrentFocus@0");
+//		}
+//
+//		if(	m_hHookDll == NULL || m_MonitorFocusChanges == NULL || 
+//			m_StopMonitoringFocusChanges == NULL || m_GetCurrentFocus == NULL)
+//		{
+//			g_Opt.m_bUseHookDllForFocus = FALSE;
+//		}
+//	}
+
 //	if(DoCleanups() == FALSE)
 //		return TRUE;
 
@@ -187,6 +212,9 @@ http://website.lineone.net/~codebox/focuslog.zip).
 */
 bool CCP_MainApp::TargetActiveWindow()
 {
+	if(g_Opt.m_bUseHookDllForFocus)
+		return true;
+
 	HWND hOld = m_hTargetWnd;
 	HWND hNew = ::GetForegroundWindow();
 	if( hNew == m_hTargetWnd || !::IsWindow(hNew) || IsAppWnd(hNew) )
@@ -629,3 +657,22 @@ BOOL CCP_MainApp::OnIdle(LONG lCount)
 
 	return FALSE;
 }
+
+CString CCP_MainApp::GetTargetName() 
+{
+	char cWindowText[100];
+	HWND hParent = m_hTargetWnd;
+
+	::GetWindowText(hParent, cWindowText, 100);
+	
+	while(strlen(cWindowText) <= 0)
+	{
+		hParent = ::GetParent(hParent);
+		if(hParent == NULL)
+			break;
+
+		::GetWindowText(hParent, cWindowText, 100);
+	}
+
+	return cWindowText; 
+}

+ 7 - 3
CP_Main.dsp

@@ -55,7 +55,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
-# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto.exe"
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto.exe" /libpath:"focusdll\Release"
 
 !ELSEIF  "$(CFG)" == "CP_Main - Win32 Debug"
 
@@ -108,7 +108,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 /out:"Release/Ditto.exe"
-# ADD LINK32 /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto98.exe"
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto98.exe" /libpath:"focusdll\Release"
 
 !ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Debug"
 
@@ -135,7 +135,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto.exe" /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto_Pre2000.exe" /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto_Pre2000.exe" /pdbtype:sept /libpath:"focusdll\Release"
 
 !ENDIF 
 
@@ -588,5 +588,9 @@ SOURCE=.\ReadMe.txt
 
 SOURCE=.\Version.Lib
 # End Source File
+# Begin Source File
+
+SOURCE=.\focusdll\Release\focus.lib
+# End Source File
 # End Target
 # End Project

+ 13 - 1
CP_Main.dsw

@@ -3,7 +3,7 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
 
 ###############################################################################
 
-Project: "CP_Main"=.\CP_Main.dsp - Package Owner=<4>
+Project: "CP_Main"=".\CP_Main.dsp" - Package Owner=<4>
 
 Package=<5>
 {{{
@@ -19,6 +19,18 @@ Package=<4>
 
 ###############################################################################
 
+Project: "focus"=".\focusdll\focus.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
 Global:
 
 Package=<5>

+ 7 - 1
CP_Main.h

@@ -71,7 +71,7 @@ public:
 	bool	TargetActiveWindow();
 	bool ActivateTarget();
 	bool ReleaseFocus(); // activate the target only if we are the active window
-	CString GetTargetName() { return GetWndText( m_hTargetWnd ); }
+	CString GetTargetName();
 	void SendPaste(bool bActivateTarget); // Activates the Target and sends Ctrl-V
 
 	CLIPFORMAT m_cfIgnoreClipboard; // used by CClip::LoadFromClipboard
@@ -145,6 +145,12 @@ public:
 	CRITICAL_SECTION m_CriticalSection;
 	CPopup	 *m_pcpSendRecieveError;
 
+	HMODULE m_hHookDll;
+	DWORD (*m_MonitorFocusChanges)(HWND hWnd,UINT message);
+	DWORD (*m_StopMonitoringFocusChanges)();
+	HWND (*m_GetCurrentFocus)();
+
+
 
 
 // Overrides

BIN
Debug/focus.dll


BIN
Debug/focus.lib


+ 47 - 1
MainFrm.cpp

@@ -9,6 +9,7 @@
 #include "CopyProperties.h"
 #include "InternetUpdate.h"
 #include ".\mainfrm.h"
+#include "focusdll\focusdll.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -46,6 +47,7 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 	ON_MESSAGE(WM_ADD_TO_DATABASE_FROM_SOCKET, OnAddToDatabaseFromSocket)
 	ON_MESSAGE(WM_LOAD_FORMATS, OnLoadFormats)
 	ON_MESSAGE(WM_SEND_RECIEVE_ERROR, OnErrorOnSendRecieve)
+	ON_MESSAGE(WM_FOCUS_CHANGED, OnFocusChanged)
 END_MESSAGE_MAP()
 
 static UINT indicators[] =
@@ -65,6 +67,9 @@ CMainFrame::CMainFrame()
 
 CMainFrame::~CMainFrame()
 {
+	if(g_Opt.m_bUseHookDllForFocus)
+		StopMonitoringFocusChanges();
+	
 	CGetSetOptions::SetMainHWND(0);
 }
 
@@ -73,6 +78,9 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
 		return -1;
 
+	if(g_Opt.m_bUseHookDllForFocus)
+		MonitorFocusChanges(m_hWnd, WM_FOCUS_CHANGED);
+	
 	SetWindowText(MAIN_WND_TITLE);
 
 	HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
@@ -510,4 +518,42 @@ LRESULT CMainFrame::OnErrorOnSendRecieve(WPARAM wParam, LPARAM lParam)
 	SetTimer(HIDE_ERROR_POPUP, 6000, NULL);
 
 	return TRUE;
-}
+}
+
+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;
+
+	//only procede if something changed
+	if(theApp.m_hTargetWnd == hFocus)
+		return TRUE;
+
+	char cWindowText[100];
+	::GetWindowText(hFocus, cWindowText, 100);
+
+	HWND hTray = ::FindWindow("Shell_TrayWnd", "");
+
+	while(true)
+	{
+		hParent = ::GetParent(hParent);
+		if(hParent == NULL)
+			break;
+
+		hLastGoodParent = hParent;
+	}
+
+	//If the parent is ditto or the try icon then don't set focus to that window
+	if(hLastGoodParent != m_hWnd && hLastGoodParent != hTray)
+	{
+		theApp.m_hTargetWnd = hFocus;
+		if(theApp.QPasteWnd() )
+			theApp.QPasteWnd()->UpdateStatus(true);
+	}
+
+	return TRUE;
+}

+ 1 - 0
MainFrm.h

@@ -82,6 +82,7 @@ protected:
 	afx_msg LRESULT OnAddToDatabaseFromSocket(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnLoadFormats(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnErrorOnSendRecieve(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnFocusChanged(WPARAM wParam, LPARAM lParam);
 	DECLARE_MESSAGE_MAP()
 public:
 	virtual BOOL PreTranslateMessage(MSG* pMsg);

+ 2 - 0
Misc.cpp

@@ -467,6 +467,7 @@ CSendClients CGetSetOptions::m_SendClients[MAX_SEND_CLIENTS];
 long CGetSetOptions::m_lAutoSendClientCount;
 CString CGetSetOptions::m_csIPListToPutOnClipboard;
 BOOL CGetSetOptions::m_bLogSendReceiveErrors;
+BOOL CGetSetOptions::m_bUseHookDllForFocus;
 
 CGetSetOptions g_Opt;
 
@@ -487,6 +488,7 @@ CGetSetOptions::CGetSetOptions()
 	m_bSendPasteOnFirstTenHotKeys = GetSendPasteOnFirstTenHotKeys();
 	m_csIPListToPutOnClipboard = GetListToPutOnClipboard();
 	m_bLogSendReceiveErrors = GetLogSendReceiveErrors();
+	m_bUseHookDllForFocus = GetProfileLong("UseHookDllForFocus", TRUE);
 
 	for(int i = 0; i < MAX_SEND_CLIENTS; i++)
 	{

+ 4 - 0
Misc.h

@@ -98,6 +98,8 @@ CString GetFilePath(CString csFullPath);
 #define WM_ADD_TO_DATABASE_FROM_SOCKET		WM_USER + 207
 #define WM_LOAD_FORMATS			WM_USER + 208
 #define WM_SEND_RECIEVE_ERROR	WM_USER + 209
+#define WM_FOCUS_CHANGED		WM_USER + 210
+
 
 #define REG_PATH					"Software\\Ditto"
 
@@ -283,6 +285,8 @@ public:
 	static void		SetLogSendReceiveErrors(BOOL bOption);
 	static BOOL		GetLogSendReceiveErrors();
 
+	static BOOL		m_bUseHookDllForFocus;
+
 
 	/*
 	BOOL IsAutoRun();

BIN
Release/focus.dll


BIN
Release/focus.lib


+ 10 - 0
focusdll/focus.dsp

@@ -53,6 +53,11 @@ BSC32=bscmake.exe
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# Begin Special Build Tool
+OutDir=.\Release
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\*.lib ..\Release	copy $(OutDir)\*.dll ..\Release
+# End Special Build Tool
 
 !ELSEIF  "$(CFG)" == "focus - Win32 Debug"
 
@@ -78,6 +83,11 @@ BSC32=bscmake.exe
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# Begin Special Build Tool
+OutDir=.\Debug
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy $(OutDir)\*.lib ..\Debug	copy $(OutDir)\*.dll ..\Debug
+# End Special Build Tool
 
 !ENDIF 
 

+ 76 - 0
focusdll/focusdll.cpp

@@ -0,0 +1,76 @@
+#include <windows.h>
+#include <assert.h>
+#include "focusdll.h"
+
+#pragma data_seg (".shared")
+HHOOK hHook=NULL;       //
+HWND hFocusWnd=NULL;    // window that last gained the focus
+HWND hNotifyWnd=NULL;   // window to send message to when focus changes
+UINT uMessage=0;        // wm_message to send in the above case
+#pragma data_seg ()
+#pragma comment(linker, "/SECTION:.shared,RWS")
+
+HINSTANCE hDllInst;
+
+BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
+{
+    switch(dwReason)
+    {
+        case DLL_PROCESS_ATTACH:            
+            hDllInst = hInstance;
+        case DLL_THREAD_ATTACH:
+        case DLL_PROCESS_DETACH:
+        case DLL_THREAD_DETACH:
+            break;
+    }
+    
+    return TRUE;
+}
+
+static LRESULT WINAPI HookProc(int code, WPARAM wParam, LPARAM lParam)
+{
+    
+    if(code == HCBT_SETFOCUS)
+    {
+        //Focus has changed, record new focus window
+        hFocusWnd = (HWND)wParam;
+        
+        //And if notification requested, send a windows message.
+        if(hNotifyWnd)
+			SendMessage(hNotifyWnd, uMessage, wParam, lParam);
+    }
+ 
+    return CallNextHookEx(hHook,code,wParam,lParam);
+}
+
+DLLEXPORT DWORD WINAPI MonitorFocusChanges(HWND hWnd, UINT message)
+{    
+    if(hHook)
+		UnhookWindowsHookEx(hHook);
+
+    hHook = SetWindowsHookEx(WH_CBT,HookProc,hDllInst,0);
+
+    hNotifyWnd = hWnd;
+    uMessage = message;
+    
+    return TRUE;
+}
+
+DLLEXPORT DWORD WINAPI StopMonitoringFocusChanges()
+{
+    if(hHook) 
+		UnhookWindowsHookEx(hHook);
+
+    hHook = NULL;
+    hFocusWnd = NULL;
+
+    return TRUE;
+}
+
+DLLEXPORT HWND WINAPI GetCurrentFocus()
+{
+    return hFocusWnd;
+}
+
+
+

+ 21 - 0
focusdll/focusdll.h

@@ -0,0 +1,21 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef FOCUS_EXPORTS
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT __declspec(dllimport)
+#endif
+
+DLLEXPORT DWORD WINAPI MonitorFocusChanges(HWND hWnd,UINT message);
+
+DLLEXPORT DWORD WINAPI StopMonitoringFocusChanges();
+
+DLLEXPORT HWND  WINAPI GetCurrentFocus();
+
+
+#ifdef __cplusplus
+}
+#endif