请问什么叫模拟鼠标和键盘事件?什么叫捕捉鼠标和键盘事件呢?

whitetiger8 2002-10-16 04:55:38
我最不明白的是,怎么去模拟鼠标和键盘事件。这样的,要求做成控件形式,不可以去其它程序有影响。那模拟鼠标键盘还有什么呢?接口是怎么的呢。是不是给用户一下 接口,让他选择触发什么键,我就在系统中去触发一下呢?题意有点不懂,请大家指教。谁有代码和例子更为感激!!!
...全文
133 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
rlongriver 2002-10-16
  • 打赏
  • 举报
回复
接上:
---------------
const
{Array of keys that SendKeys recognizes.

If you add to this list, you must be sure to keep it sorted alphabetically
by Name because a binary search routine is used to scan it.}

MaxSendKeyRecs = 41;
SendKeyRecs : array[1..MaxSendKeyRecs] of TSendKey =
(
(Name:'BKSP'; VKey:VK_BACK),
(Name:'BS'; VKey:VK_BACK),
(Name:'BACKSPACE'; VKey:VK_BACK),
(Name:'BREAK'; VKey:VK_CANCEL),
(Name:'CAPSLOCK'; VKey:VK_CAPITAL),
(Name:'CLEAR'; VKey:VK_CLEAR),
(Name:'DEL'; VKey:VK_DELETE),
(Name:'DELETE'; VKey:VK_DELETE),
(Name:'DOWN'; VKey:VK_DOWN),
(Name:'END'; VKey:VK_END),
(Name:'ENTER'; VKey:VK_RETURN),
(Name:'ESC'; VKey:VK_ESCAPE),
(Name:'ESCAPE'; VKey:VK_ESCAPE),
(Name:'F1'; VKey:VK_F1),
(Name:'F10'; VKey:VK_F10),
(Name:'F11'; VKey:VK_F11),
(Name:'F12'; VKey:VK_F12),
(Name:'F13'; VKey:VK_F13),
(Name:'F14'; VKey:VK_F14),
(Name:'F15'; VKey:VK_F15),
(Name:'F16'; VKey:VK_F16),
(Name:'F2'; VKey:VK_F2),
(Name:'F3'; VKey:VK_F3),
(Name:'F4'; VKey:VK_F4),
(Name:'F5'; VKey:VK_F5),
(Name:'F6'; VKey:VK_F6),
(Name:'F7'; VKey:VK_F7),
(Name:'F8'; VKey:VK_F8),
(Name:'F9'; VKey:VK_F9),
(Name:'HELP'; VKey:VK_HELP),
(Name:'HOME'; VKey:VK_HOME),
(Name:'INS'; VKey:VK_INSERT),
(Name:'LEFT'; VKey:VK_LEFT),
(Name:'NUMLOCK'; VKey:VK_NUMLOCK),
(Name:'PGDN'; VKey:VK_NEXT),
(Name:'PGUP'; VKey:VK_PRIOR),
(Name:'PRTSC'; VKey:VK_PRINT),
(Name:'RIGHT'; VKey:VK_RIGHT),
(Name:'SCROLLLOCK'; VKey:VK_SCROLL),
(Name:'TAB'; VKey:VK_TAB),
(Name:'UP'; VKey:VK_UP)
);

{Extra VK constants missing from Delphi's Windows API interface}
VK_NULL=0;
VK_SemiColon=186;
VK_Equal=187;
VK_Comma=188;
VK_Minus=189;
VK_Period=190;
VK_Slash=191;
VK_BackQuote=192;
VK_LeftBracket=219;
VK_BackSlash=220;
VK_RightBracket=221;
VK_Quote=222;
VK_Last=VK_Quote;

ExtendedVKeys : set of byte =
[VK_Up,
VK_Down,
VK_Left,
VK_Right,
VK_Home,
VK_End,
VK_Prior, {PgUp}
VK_Next, {PgDn}
VK_Insert,
VK_Delete];

const
INVALIDKEY = $FFFF {Unsigned -1};
VKKEYSCANSHIFTON = $01;
VKKEYSCANCTRLON = $02;
VKKEYSCANALTON = $04;
UNITNAME = 'SendKeys';
var
UsingParens, ShiftDown, ControlDown, AltDown, FoundClose : Boolean;
PosSpace : Byte;
I, L : Integer;
NumTimes, MKey : Word;
KeyString : String[20];

procedure DisplayMessage(Message : PChar);
begin
MessageBox(0,Message,UNITNAME,0);
end;

function BitSet(BitTable, BitMask : Byte) : Boolean;
begin
Result:=ByteBool(BitTable and BitMask);
end;

procedure SetBit(var BitTable : Byte; BitMask : Byte);
begin
BitTable:=BitTable or Bitmask;
end;

Procedure KeyboardEvent(VKey, ScanCode : Byte; Flags : Longint);
var
KeyboardMsg : TMsg;
begin
keybd_event(VKey, ScanCode, Flags,0);
If (Wait) then While (PeekMessage(KeyboardMsg,0,WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) do begin
TranslateMessage(KeyboardMsg);
DispatchMessage(KeyboardMsg);
end;
end;

Procedure SendKeyDown(VKey: Byte; NumTimes : Word; GenUpMsg : Boolean);
var
Cnt : Word;
ScanCode : Byte;
NumState : Boolean;
KeyBoardState : TKeyboardState;
begin
If (VKey=VK_NUMLOCK) then begin
NumState:=ByteBool(GetKeyState(VK_NUMLOCK) and 1);
GetKeyBoardState(KeyBoardState);
If NumState then KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] and not 1)
else KeyBoardState[VK_NUMLOCK]:=(KeyBoardState[VK_NUMLOCK] or 1);
SetKeyBoardState(KeyBoardState);
exit;
end;

ScanCode:=Lo(MapVirtualKey(VKey,0));
For Cnt:=1 to NumTimes do
If (VKey in ExtendedVKeys)then begin
KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY);
If (GenUpMsg) then
KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP)
end else begin
KeyboardEvent(VKey, ScanCode, 0);
If (GenUpMsg) then KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
end;
end;

Procedure SendKeyUp(VKey: Byte);
var
ScanCode : Byte;
begin
ScanCode:=Lo(MapVirtualKey(VKey,0));
If (VKey in ExtendedVKeys)then
KeyboardEvent(VKey, ScanCode, KEYEVENTF_EXTENDEDKEY and KEYEVENTF_KEYUP)
else KeyboardEvent(VKey, ScanCode, KEYEVENTF_KEYUP);
end;

rlongriver 2002-10-16
  • 打赏
  • 举报
回复
-----------------------
(转)
---------------------------------
下面的代码是模拟Ctrl+C和Ctrl+V:
//Ctrl+C:
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), 0, 0);
keybd_event(Ord('C'), MapVirtualKey(Ord('C'), 0), KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0)

//Ctrl+V:
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), 0, 0);
keybd_event(Ord('V'), MapVirtualKey(Ord('V'), 0), KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0)
**************************
按下一个键最好用SendMessage,用sndkey32.pas无疑会增加程序尺寸。
组合键(超过两个以上)用sndkey32.pas就显出优势来了。

另一种解决方法,下例模拟按下Alt+Down,可参见Delphi SDK的帮助:
keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt down
keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key down
keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key up
keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up

让 WIN95 模拟按了一个按键,例如按下 ENTER或者 TAB 键?
PostMessage(Object.Handle, WM_KEYDOWN, VK_TAB, 0);

////////////////////////////////
unit Unit1;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
AppInst: THandle;
AppWind: THandle;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

uses ShellAPI;


procedure SendShift(H: HWnd; Down: Boolean);
var vKey, ScanCode, wParam: Word;
lParam: longint;
begin
vKey:= $10;
ScanCode:= MapVirtualKey(vKey, 0);
wParam:= vKey or ScanCode shl 8;
lParam:= longint(ScanCode) shl 16 or 1;
if not(Down) then lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYDOWN, vKey, lParam);
end;

procedure SendCtrl(H: HWnd; Down: Boolean);
var vKey, ScanCode, wParam: Word;
lParam: longint;
begin
vKey:= $11;
ScanCode:= MapVirtualKey(vKey, 0);
wParam:= vKey or ScanCode shl 8;
lParam:= longint(ScanCode) shl 16 or 1;
if not(Down) then lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYDOWN, vKey, lParam);
end;

procedure SendKey(H: Hwnd; Key: char);
var vKey, ScanCode, wParam: Word;
lParam, ConvKey: longint;
Shift, Ctrl: boolean;
begin
ConvKey:= OemKeyScan(ord(Key));
Shift:= (ConvKey and $00020000) <> 0;
Ctrl:= (ConvKey and $00040000) <> 0;
ScanCode:= ConvKey and $000000FF or $FF00;
vKey:= ord(Key);
wParam:= vKey;
lParam:= longint(ScanCode) shl 16 or 1;
if Shift then SendShift(H, true);
if Ctrl then SendCtrl(H, true);
SendMessage(H, WM_KEYDOWN, vKey, lParam);
SendMessage(H, WM_CHAR, vKey, lParam);
lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYUP, vKey, lParam);
if Shift then SendShift(H, false);
if Ctrl then SendCtrl(H, false);
end;

function EnumFunc(Handle: HWnd; TF: TForm1): Bool; Far;
begin
TF.AppWind:= 0;
if GetWindowWord(Handle, GWW_HINSTANCE) = TF.AppInst then
TF.AppWind:= Handle;
result:= (TF.AppWind = 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var Text: Array[0..255] of char;
begin
AppInst:= ShellExecute(Handle, 'open', 'notepad.exe', nil, '', SW_NORMAL);
EnumWindows(@EnumFunc, longint(self));
AppWind:= GetWindow(AppWind, GW_CHILD);
end;


procedure TForm1.Button2Click(Sender: TObject);
begin
SendKey(AppWind, 'T');
SendKey(AppWind, 'e');
SendKey(AppWind, 's');
SendKey(AppWind, 't');
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if AppWind <> 0 then SendKey(AppWind, Key);
end;

end.
///////////////////////////////////////////////////////////////////////
Ah,这个嘛......正好在《DELPHI新闻组学习笔记》上看到一篇:
How to send [Alt]+[Down]?--------------发出一个Alt+Down 组合键

Re:
Use the keybd_event API function to fake keyboard events. Note that each
key down event needs a matching key up or you mess up the key state array.

keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), 0 , 0 ); // Alt down
keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key down
keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key up
keybd_event( VK_MENU, MapVirtualKey( VK_MENU, 0 ), KEYEVENTF_KEYUP , 0 ); // Alt key up

经本人试验,确实可行,另加补充:
Ctrl: VK_CONTROL
SHIFT:VK_SHIFT
TAB: VK_TAB
'A': byte('A') (98-6-8 22:28)
/////////////////////////////////////////////////////////////
(*
Converts a string of characters and key names to keyboard events and
passes them to Windows.

Example syntax:

SendKeys('abc123{left}{left}{left}def{end}456{left 6}ghi{end}789', True);

*)

Function SendKeys(SendKeysString : PChar; Wait : Boolean) : Boolean;
type
WBytes = array[0..pred(SizeOf(Word))] of Byte;

TSendKey = record
Name : ShortString;
VKey : Byte;
end;

rlongriver 2002-10-16
  • 打赏
  • 举报
回复
看这个吧
--------------------------------
(转)
------------------------------------------
鼠标自动点击的例子,模拟鼠标点击
procedure TForm1.Button1Click(Sender: TObject);
var
x,y:integer;
begin
x:= form1.Left+button2.Left+25;
y:= top+button2.Top+27;
SetCursorPos(x,y);
Mouse_Event(MOUSEEVENTF_LEFTDOWN,X,Y,0,0);
Mouse_Event(MOUSEEVENTF_LEFTUP,X,Y,0,0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
showmessage('fksj');
end;
*************************************
// Set the mouse cursor to position x,y:
SetCursorPos(x, y);

// Simulate the left mouse button down
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

// Simulate the right mouse button down
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
PeakChen 2002-10-16
  • 打赏
  • 举报
回复
鼠标和键盘事件就是当点击它们时,window把响应传给应用程序,把这个响应
称为消息。
扑捉鼠标和键盘事件就是得到这个消息。
twkwang 2002-10-16
  • 打赏
  • 举报
回复
ONMOUSEDOWN,ONMOUSEUP,ONMOUSEMOVE,ONKEYDOWN,ONKEYUP,ONKEYPRESS
看OBJECT INPECTOR的EVENT就明白了
realist 2002-10-16
  • 打赏
  • 举报
回复
我也想知道!关注

5,379

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧