如何通过VB.NET编程实现从记事本复制文本并粘贴到应用指定文本框
问题原因
你当前的实现方案存在多个不稳定因素,是导致复制内容错乱的核心原因:
- 固定坐标模拟点击的方式强依赖记事本窗口的位置、大小、系统缩放设置,只要窗口位置变动就会点击到错误位置
- 双击选行的逻辑不可靠,若行首有空格、行内容过长折行都会导致选中范围错误
- 模拟按键+剪切板操作没有等待剪切板内容更新完成,经常复用之前的剪切板内容
- 窗口激活时序不稳定,
SendKeys可能没有发送到记事本窗口而是发送到了自身程序
最优解决方案
直接通过系统API读取记事本的内容,完全不需要模拟点击、模拟按键这类不稳定的操作,实现逻辑如下:
- 找到正在运行的记事本窗口句柄
- 获取记事本中编辑控件的全部内容
- 按换行符拆分内容为数组,直接对应填充到你的文本框中
实现代码
Imports System.Runtime.InteropServices Imports System.Text Public Class Form1 ' 系统API声明 <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr End Function <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, ByVal lclassName As String, ByVal windowTitle As String) As IntPtr End Function <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As StringBuilder) As IntPtr End Function Private Const WM_GETTEXT As UInteger = &HD Private Const WM_GETTEXTLENGTH As UInteger = &HE Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click ' 第一步:找到记事本窗口,若同时运行多个记事本,第二个参数填对应窗口的完整标题即可,比如"测试.txt - 记事本" Dim notepadHandle As IntPtr = FindWindow("Notepad", Nothing) If notepadHandle = IntPtr.Zero Then MessageBox.Show("未找到运行中的记事本程序") Return End If ' 第二步:找到记事本里的编辑控件句柄 Dim editHandle As IntPtr = FindWindowEx(notepadHandle, IntPtr.Zero, "Edit", Nothing) If editHandle = IntPtr.Zero Then MessageBox.Show("读取记事本内容失败") Return End If ' 第三步:获取记事本内容长度 Dim textLength As Integer = SendMessage(editHandle, WM_GETTEXTLENGTH, IntPtr.Zero, Nothing).ToInt32() + 1 Dim sb As New StringBuilder(textLength) ' 第四步:读取全部内容 SendMessage(editHandle, WM_GETTEXT, CType(sb.Capacity, IntPtr), sb) Dim allLines As String() = sb.ToString().Split({vbCrLf, vbLf}, StringSplitOptions.None) ' 第五步:对应填充文本框 Dim textBoxList As New List(Of TextBox) From {TextBox2, TextBox3, TextBox4, TextBox5, TextBox6} For i = 0 To Math.Min(textBoxList.Count - 1, allLines.Length - 1) textBoxList(i).Text = allLines(i).Trim() Next End Sub ' 清空按钮逻辑保持不变即可 Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click TextBox2.Clear() TextBox3.Clear() TextBox4.Clear() TextBox5.Clear() TextBox6.Clear() End Sub End Class
方案优势
- 完全不依赖窗口位置、鼠标操作,100%准确读取内容
- 不需要操作剪切板,不会出现内容复用的问题
- 执行效率极高,点击按钮瞬间完成填充,不需要等待数秒
- 不需要保留原来的Button1~Button5的逻辑,只需要一个批量填充按钮即可完成全部操作
内容的提问来源于stack exchange,提问作者Βασιλης Τακατουκας
相关产品推荐
相关产品推荐

