我正在开发一个窗口应用程序来读取C#
在屏幕上的任何应用程序上输入的文本。
我使用的是Win32 API
,如下所示 - 我在Google上找到的解决方案:
private const int WM_GETTEXTLENGTH = 0x000E;
private const int WM_GETTEXT = 0x000D;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
public Terminal()
{
InitializeComponent();
IntPtr pFoundWindow = GetForegroundWindow();
IntPtr notepad = FindWindow("notepad", null);
IntPtr editx = FindWindowEx(notepad, IntPtr.Zero, "edit", null);
int length = SendMessage(editx, WM_GETTEXTLENGTH, 0, 0);
StringBuilder text = new StringBuilder(length);
int hr = SendMessage(editx, WM_GETTEXT, length, text);
Console.WriteLine(text);
}
但这只是从记事本中读取现有文本。 在任何程序,任何窗口上打字时,我该如何阅读文字?
答案 0 :(得分:3)
示例中的以下代码
IntPtr notepad = FindWindow("notepad", null);
这意味着获取一个名为notepad
的流程句柄。
以下一个
IntPtr editx = FindWindowEx(notepad, IntPtr.Zero, "edit", null);
也表示您尝试从记事本中找到窗口句柄,窗口标题为edit
。 edit
窗口是记事本的可编辑区域。
如果您要使您的应用程序适合任何过程,则无法声明您的目标是源代码。换句话说,您需要另一种方法来指定要获取文本的窗口。
我的建议是:您需要以下Windows API才能在运行时获取目标窗口。
例如,您可以使用SetWindowsHookEx
在应用程序外部获取鼠标事件,然后在用户单击目标窗口时触发回调。接下来,触发回调函数,您可以使用GetCursorPos
获取鼠标位置,并使用WindowFromPoint
获取您想要读取其文本的窗口。
<强>更新强>
我提供了我的其他项目的示例代码,并为您挑选了一些有用的部分。
/// <summary>
/// A hook handle for grabbing mouse click, used to get the position of target window.
/// </summary>
private IntPtr _hook = IntPtr.Zero;
//button click event
private void selectWindow_Click(object sender, EventArgs e)
{
if (_hook != IntPtr.Zero)
return;
using (Process p = Process.GetCurrentProcess())
{
using (ProcessModule m = p.MainModule)
{
_hook = SafeNativeMethods.SetWindowsHookEx(SafeNativeMethods.WH_MOUSE_LL, hookCallback, SafeNativeMethods.GetModuleHandle(m.ModuleName), 0);
}
}
}
/// <summary>
/// Callback method of mouse hook.
/// </summary>
private IntPtr hookCallback(int code, IntPtr w, IntPtr l)
{
if (code >= 0 && (WMessages)w == WMessages.WM_LBUTTONDOWN)
{
CPoint pt;
SafeNativeMethods.GetCursorPos(out pt);
//hey man! the _windowHandle is what you need
_windowHandle = SafeNativeMethods.WindowFromPoint(pt);
SafeNativeMethods.UnhookWindowsHookEx(_hook);
_hook = IntPtr.Zero;
//...and do your stuff here!
}
return SafeNativeMethods.CallNextHookEx(_hook, code, w, l);
}
而def。 Windows API
/// <summary>
/// Window Hook ID 14 - Low level mouse proc.
/// </summary>
internal const int WH_MOUSE_LL = 14;
/// <summary>
/// Get the window handle from a specified point.
/// </summary>
/// <param name="point">Specified point</param>
/// <returns>Window handle</returns>
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr WindowFromPoint(CPoint point);
/// <summary>
/// Register a hook.
/// </summary>
/// <param name="idHook">Hook type</param>
/// <param name="lpfn">Function pointer</param>
/// <param name="hMod">Module ID</param>
/// <param name="dwThreadId">Thread ID</param>
/// <returns>Hook handle</returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
/// <summary>
/// Unregister a hook.
/// </summary>
/// <param name="hhk">Hook handle</param>
/// <returns>Successful</returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool UnhookWindowsHookEx(IntPtr hhk);
/// <summary>
/// Call next hook (if needed).
/// </summary>
/// <param name="hhk">Hook handle</param>
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
/// <summary>
/// Get moudle handle by module name.
/// </summary>
/// <param name="lpModuleName">Module name</param>
/// <returns>Module handle</returns>
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr GetModuleHandle(string lpModuleName);
/// <summary>
/// Get current cursor position.
/// </summary>
/// <param name="lpPoint">Output position</param>
/// <returns>Successful</returns>
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(out CPoint lpPoint);
更新2
我忘记了CPoint struct lol。
/// <summary>
/// Win32 POINT structure.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct CPoint
{
public int x;
public int y;
}