ExternalWindowTracker.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include "stdafx.h"
  2. #include "externalwindowtracker.h"
  3. #include "Misc.h"
  4. #include "SendKeys.h"
  5. #include "Options.h"
  6. #include "CP_Main.h"
  7. ExternalWindowTracker::ExternalWindowTracker(void)
  8. {
  9. m_activeWnd = NULL;
  10. m_focusWnd = NULL;
  11. m_dittoHasFocus = false;
  12. }
  13. ExternalWindowTracker::~ExternalWindowTracker(void)
  14. {
  15. }
  16. bool ExternalWindowTracker::TrackActiveWnd(HWND focus)
  17. {
  18. BOOL fromHook = true;
  19. HWND newFocus = focus;
  20. HWND newActive = ::GetForegroundWindow();
  21. if(newFocus == NULL)
  22. {
  23. AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), TRUE);
  24. newFocus = GetFocus();
  25. AttachThreadInput(GetWindowThreadProcessId(newActive, NULL), GetCurrentThreadId(), FALSE);
  26. fromHook = false;
  27. }
  28. if(newFocus == 0 && newActive != 0)
  29. {
  30. newFocus = newActive;
  31. }
  32. else if(newActive == 0 && newFocus != 0)
  33. {
  34. newActive = newFocus;
  35. }
  36. if(newFocus == 0 || !IsWindow(newFocus) || newActive == 0 || !IsWindow(newActive))
  37. {
  38. Log(_T("TargetActiveWindow values invalid"));
  39. return false;
  40. }
  41. if(newFocus == m_focusWnd)
  42. {
  43. // Log(_T("TargetActiveWindow window the same"));
  44. return false;
  45. }
  46. TCHAR className[50];
  47. GetClassName(newFocus, className, (sizeof(className) / sizeof(TCHAR)));
  48. if(STRCMP(className, _T("Shell_TrayWnd")) == 0)
  49. {
  50. Log(_T("TargetActiveWindow shell tray icon has focus"));
  51. return false;
  52. }
  53. GetClassName(newActive, className, (sizeof(className) / sizeof(TCHAR)));
  54. if(STRCMP(className, _T("Shell_TrayWnd")) == 0)
  55. {
  56. Log(_T("TargetActiveWindow shell tray icon has active"));
  57. return false;
  58. }
  59. if(IsAppWnd(newFocus))
  60. {
  61. m_dittoHasFocus = true;
  62. return false;
  63. }
  64. m_focusWnd = newFocus;
  65. m_activeWnd = newActive;
  66. m_dittoHasFocus = false;
  67. if(theApp.QPasteWnd())
  68. theApp.QPasteWnd()->UpdateStatus(true);
  69. Log(StrF(_T("TargetActiveWindow Active: %d, Focus: %d, FromHook %d"), m_activeWnd, m_focusWnd, fromHook));
  70. return true;
  71. }
  72. bool ExternalWindowTracker::WaitForActiveWnd(HWND activeWnd, int timeout)
  73. {
  74. DWORD start = GetTickCount();
  75. while(((int)(GetTickCount() - start)) < timeout)
  76. {
  77. if(::GetForegroundWindow() == activeWnd)
  78. {
  79. Log(StrF(_T("found focus wait %d"), GetTickCount()-start));
  80. return true;
  81. }
  82. Sleep(0);
  83. ActivateTarget();
  84. }
  85. Log(_T("Didn't find focus"));
  86. return false;
  87. }
  88. bool ExternalWindowTracker::ActivateTarget()
  89. {
  90. Log(StrF(_T("Activate Target - Active: %d Focus: %d"), m_activeWnd, m_focusWnd));
  91. SetForegroundWindow(m_activeWnd);
  92. AttachThreadInput(GetWindowThreadProcessId(m_activeWnd, NULL), GetCurrentThreadId(), TRUE);
  93. SetFocus(m_focusWnd);
  94. AttachThreadInput(GetWindowThreadProcessId(m_activeWnd, NULL), GetCurrentThreadId(), FALSE);
  95. return true;
  96. }
  97. void ExternalWindowTracker::SendPaste(bool activateTarget)
  98. {
  99. CSendKeys send;
  100. send.AllKeysUp();
  101. CString csPasteToApp = GetProcessName(m_activeWnd);
  102. CString csPasteString = g_Opt.GetPasteString(csPasteToApp);
  103. DWORD delay = g_Opt.SendKeysDelay();
  104. if(activateTarget)
  105. {
  106. ActivateTarget();
  107. theApp.PumpMessageEx();
  108. WaitForActiveWnd(m_activeWnd, max(25, g_Opt.WaitForActiveWndTimeout()));
  109. }
  110. else
  111. {
  112. theApp.PumpMessageEx();
  113. }
  114. m_dittoHasFocus = false;
  115. Log(StrF(_T("Sending paste to app %s key stroke: %s, SeDelay: %d"), csPasteToApp, csPasteString, delay));
  116. send.SetKeyDownDelay(max(50, delay));
  117. send.SendKeys(csPasteString, true);
  118. Log(_T("Post sending paste"));
  119. }
  120. void ExternalWindowTracker::SendCopy()
  121. {
  122. CSendKeys send;
  123. send.AllKeysUp();
  124. CString csToApp = GetProcessName(m_activeWnd);
  125. CString csString = g_Opt.GetCopyString(csToApp);
  126. DWORD delay = g_Opt.SendKeysDelay();
  127. Sleep(delay);
  128. theApp.PumpMessageEx();
  129. Log(StrF(_T("Sending copy to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
  130. //give the app some time to take focus before sending paste
  131. Sleep(delay);
  132. send.SetKeyDownDelay(max(50, delay));
  133. send.SendKeys(csString, true);
  134. Log(_T("Post sending copy"));
  135. }
  136. // sends Ctrl-X to the TargetWnd
  137. void ExternalWindowTracker::SendCut()
  138. {
  139. CSendKeys send;
  140. send.AllKeysUp();
  141. CString csToApp = GetProcessName(m_activeWnd);
  142. CString csString = g_Opt.GetCopyString(csToApp);
  143. DWORD delay = g_Opt.SendKeysDelay();
  144. Sleep(delay);
  145. theApp.PumpMessageEx();
  146. Log(StrF(_T("Sending cut to app %s key stroke: %s, Delay: %d"), csToApp, csString, delay));
  147. //give the app some time to take focus before sending paste
  148. Sleep(delay);
  149. send.SetKeyDownDelay(max(50, delay));
  150. send.SendKeys(csString, true);
  151. Log(_T("Post sending cut"));
  152. }
  153. CString ExternalWindowTracker::ActiveWndName()
  154. {
  155. TCHAR cWindowText[200];
  156. HWND hParent = m_activeWnd;
  157. ::GetWindowText(hParent, cWindowText, 100);
  158. int nCount = 0;
  159. while(STRLEN(cWindowText) <= 0)
  160. {
  161. hParent = ::GetParent(hParent);
  162. if(hParent == NULL)
  163. break;
  164. ::GetWindowText(hParent, cWindowText, 100);
  165. nCount++;
  166. if(nCount > 100)
  167. {
  168. Log(_T("GetTargetName reached maximum search depth of 100"));
  169. break;
  170. }
  171. }
  172. return cWindowText;
  173. }
  174. bool ExternalWindowTracker::ReleaseFocus()
  175. {
  176. if( IsAppWnd(::GetForegroundWindow()) )
  177. {
  178. return ActivateTarget();
  179. }
  180. return false;
  181. }
  182. CPoint ExternalWindowTracker::FocusCaret()
  183. {
  184. CPoint pt(-1, -1);
  185. if(m_activeWnd)
  186. {
  187. GUITHREADINFO guiThreadInfo;
  188. guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
  189. DWORD OtherThreadID = GetWindowThreadProcessId(m_activeWnd, NULL);
  190. if(GetGUIThreadInfo(OtherThreadID, &guiThreadInfo))
  191. {
  192. CRect rc(guiThreadInfo.rcCaret);
  193. if(rc.IsRectEmpty() == FALSE)
  194. {
  195. pt = rc.BottomRight();
  196. ::ClientToScreen(m_focusWnd, &pt);
  197. }
  198. }
  199. }
  200. return pt;
  201. }