C++ Builder 5 模拟键盘按键 自动输入文字

模拟键盘按键 自动输入文字

  键盘对于每个操作电脑的人员来说是最熟悉不过的了。键盘上的按键可分为两类: 按下后会在电脑的输入窗口上出现对应字符的按键,如字母键和数字键等,我们称之为字符键;按下后虽然看不到字符但会产生控制作用的按键,如回车键、光标键等,我们称之为控制键。
  对于程序员来说,键盘上的每个按键都一样,无非是不同按键产生的键盘扫描码不同。在不同的操作系统下,键盘扫描码常常被转换为不同的编码以方便应用程序调用,比如在DOS系统下的ASCII码,在Windows系统下的虚拟键盘码等等。

  有时我们希望能以程序的方式模拟键盘按键,以达到自动输入文字或者控制操作的目的。在DOS系统下通常使用中断调用,产生键盘的扫描码的方法来实现。在Windows 系统下,由于Windows本身的一些限制和特点,一般不直接使用中断调用。
  了解一点Windows编程的朋友应该知道, Windows系统是通过消息的传递(或称事件的发生)来控制各个应用程序的执行和数据通信的。例如:应用程序打开和关闭会产生相应的窗口消息,鼠标的移动、点击动作会产生相应的鼠标消息,同样键盘的按下、弹起也会产生相应的键盘消息。那么如果用程序产生键盘消息,也就达到了模拟键盘按键的目的。

  有了这样的思路,我们现在就来实验一下。
  首先要知道在Windows系统中与键盘按键相关的消息有:WM_KEYDOWN、WM_KEYUP、 WM_SYSKEYDOWN、WM_SYSKEYUP、WM_CHAR等。其中,WM_KEYDOWN为键按下,WM_KEYUP为键弹起,WM_SYSKEYDOWN为系统键按下,WM_SYSKEYUP为系统键弹起,WM_CHAR为按键对应的字符。
  要模拟键盘产生键盘消息,我们就发送一条键盘消息给指定窗口。比如要模拟一个字母键“A”,可以这样:PostMessage(hWnd, WM_CHAR, ''A'', 0); 模拟按一个回车:PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0)。这里的关键问题是要确定窗口句柄(hWnd),使用GetFocus()函数可以得到键盘光标所在窗口句柄,但该函数只能得到当前进程内的窗口句柄。
  如果要得到其他应用程序的键盘光标所在窗口句柄,需要调用 AttachThreadInput()函数。该函数的作用就是将其他窗口线程的输入附加到本窗口线程的输入操作中,这样就可以调用GetFocus()函数得到其他窗口的句柄了。
  与2001年第24期程序谷刊登的《如何写一个聊天辅助程序》一文中作者使用ChildWindowFromPointEx的方法相比,使用AttachThreadInput似乎更能够使键盘模拟具有通用性。

AttachThreadInput()函数的原形如下:

BOOL AttachThreadInput(

DWORD idAttach, // 需要附加的线程ID

DWORD idAttachTo, // 附加到的线程ID

BOOL fAttach // true 附加 false 取消

);

函数使用的过程大致如下:


HWND hWnd;

hWnd = GetForegroundWindow(); // 得到当前窗口

if (hWnd == Form1->Handle) return; // 排除程序本身的窗口

DWORD FormThreadID = GetCurrentThreadId(); // 本程序的线程ID

// 当前窗口的线程ID

DWORD CWndThreadID = GetWindowThreadProcessId(hWnd, NULL);

// 附加输入线程

AttachThreadInput(CWndThreadID, FormThreadID, true);

// 得到当前键盘光标所在的窗口

hWnd = GetFocus();

// 取消附加的输入线程

AttachThreadInput(CWndThreadID, FormThreadID, false);

  hWnd就是当前键盘光标所在的窗口句柄。另外,经过测试发现,在Windows2000系统下发送字符消息(WM_CHAR)时,如果字符是一个汉字,则该字符对应的虚拟键盘码高位不为0,这样得到的字符就不正确。解决办法是做一个“与”运算: ch & 0xFF就可以了。
下面又到了给出例程的时间了。例程“刷刷刷”能够在键盘光标所在的文本输入框中自动输入文字(中文、英文、数字),程序使用C++ Builder 5开发。首先运行C++ Builder并新建工程。接着,将窗体Form1的边框样式(BorderStyle)改为对话框(bsDialog),并放置相应控件如图所示,其中SS_Text是一个用于输入文本的TComboBox控件,当然,你可以在设计阶段预先向控件中输入一些常用文本,以便程序运行后可以直接选用; txtTimes和txtDelay为TEdit控件,分别用于控制发送文本的次数和间隔时间;chkAutoWrap和chkAutoNumber为TCheckBox控件,决定是否在每一行发送文本后面自动回车或自动加记数编号; 以上控件包含在Panel1(TPanel控件)中; Timer1用于控制循环发送和时间间隔。

下面是程序清单:

//--------------------------------------------

#include

#pragma hdrstop

#include "Unit1.h"

//--------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"


int nTotalTimes, // 发送本文的总次数

nTimes; // 已经发送的次数

TForm1 *Form1;

//--------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//--------------------------------------------

void __fastcall TForm1::btnStartClick(TObject *Sender) // 开始刷屏

{ if (SS_Text->Text.IsEmpty())

{

// 文本不能为空

ShowMessage("请输入刷刷文本!");

SS_Text->SetFocus();

return;

}

__try

{

// Timer1->Interval取值为n秒(最小为50毫秒)

int Interval = StrToInt(txtDelay->Text);

Timer1->Interval = (Interval > 0) ? Interval * 1000 : 50;

// nTotalTimes取值为n次(最小为0次)

nTotalTimes = StrToInt(txtTimes->Text);

if (nTotalTimes < 0)

nTotalTimes = 0;

nTimes = 0;

Timer1->Enabled = true;

}

__except(EXCEPTION_EXECUTE_HANDLER)

{

ShowMessage("请输入数值类型数据!");

return;

}

btnStart->Enabled = false;

btnStop->Enabled = true;

Panel1->Enabled = false;

Application->Minimize(); // 最小化刷刷窗口

}

//--------------------------------------------
void __fastcall TForm1::btnStopClick(TObject *Sender)// 停止刷屏

{

Timer1->Enabled = false;

btnStart->Enabled = true;

btnStop->Enabled = false;

Panel1->Enabled = true;

}

//--------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

// 现刷屏nTimes次,到nTotalTimes次后完成。

if (nTimes == nTotalTimes)

{

btnStopClick(Sender);

return;

}


HWND hWnd;

hWnd = GetForegroundWindow(); // 得到当前窗口

if (hWnd == Form1->Handle) return; // 不需要程序本身的窗口


DWORD FormThreadID = GetCurrentThreadId();

DWORD CWndThreadID = GetWindowThreadProcessId(hWnd, NULL);


// 附加输入线程

AttachThreadInput(CWndThreadID, FormThreadID, true);

hWnd = GetFocus(); // 得到当前键盘光标所在的窗口

AttachThreadInput(CWndThreadID, FormThreadID, false); // 取消

if (hWnd == NULL) return;


nTimes++;

for (int i = 1; i <= SS_Text->Text.Length(); i++)

{ // 模拟键盘按键输入文本

PostMessage(hWnd, WM_CHAR, (WPARAM)(SS_Text->Text[i] & 0xFF), 0);

}


if (chkAutoNumber->Checked)

{ // 自动编号

AnsiString Lines = IntToStr(nTimes);

for (int j = 1; j <= Lines.Length(); j++)

PostMessage(hWnd, WM_CHAR, (WPARAM)(Lines[j]), 0);

}


if (chkAutoWrap->Checked) // 自动回车

PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);

}

//---------------------------------------------

本程序在Windows 2000 + C++ Builder 5下编译通过。源程序下载地址是:http://www.cfan.net.cn/qikan/ cxg/0206mnj.zip。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C Builder 5 是一个集成开发环境(IDE)和界面设计工具,用于创建 Windows 应用程序的编程工具。它采用了组件化的开发方式,允许开发者通过拖放组件来快速构建用户界面。 在 C Builder 5 中,布局是指组件在窗体上的排列方式。C Builder 5 提供了多种布局选项,使开发者可以根据需求自由选择合适的布局方式。下面是几种常用的布局方式: 1. TFlowPanel:Flow Panel 是一种自动布局的容器组件。它可以根据组件的大小自动调整位置,使得组件按照行或列的方式排列。 2. TGridPanel:Grid Panel 是一个网格布局的容器组件。它可以创建一个二维网格,并根据行列位置来放置组件。开发者可以通过属性设置来定义行列的数量和大小。 3. TPageControl:Page Control 是一个选项卡布局的容器组件。它可以将多个页面组织在同一个窗体中,每个页面都可以放置不同的组件。用户可以通过选项卡来切换页面,实现多页签的效果。 4. TPanel:Panel 是一个基本的容器组件,可以用于嵌套布局。开发者可以在 Panel 上添加其他组件,并通过调整 Panel 的大小和位置来实现自定义布局。 除了上述布局组件外,C Builder 5 还提供了一些辅助布局的组件,如 TGroupBox, TSplitter 等,用于帮助开发者更好地控制布局效果。 总的来说,C Builder 5 提供了多种布局选项,使开发者能够快速创建丰富多样的用户界面。同时,它还支持自定义布局,使得开发者可以根据具体需求来灵活调整界面的设计。 ### 回答2: C Builder 5 是一个开发工具,用于创建和设计Windows应用程序的用户界面。它提供了一种可视化的布局方法,使开发人员能够轻松地设计和调整应用程序界面的布局。 在C Builder 5中,布局是通过使用容器控件和布局管理器来实现的。容器控件可以是窗体、面板或任何可以容纳其他控件的容器。布局管理器是用来指定控件在容器中的位置和大小的工具。 在布局过程中,可以将控件拖放到容器中,并使用布局管理器的属性进行调整。常见的布局管理器包括Flow布局、Grid布局和Anchor布局。 Flow布局允许控件按照顺序自动排列,当控件的大小发生改变时,它们会自动调整位置。Grid布局将控件放置在网格中,可以指定每个控件在网格中的行列位置。Anchor布局允许控件通过设置锚点来自动调整大小和位置,当容器的大小改变时,控件会自动适应容器的大小。 通过使用这些布局管理器,开发人员可以轻松地创建复杂和灵活的用户界面。布局管理器还提供了很多属性和方法,用于调整布局的细节,如控件的边距、行列间距以及居中对齐等。 总之,C Builder 5 提供了一种方便和灵活的布局设计方法,使开发人员能够快速创建出美观和用户友好的应用程序界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值