在不移动鼠标的前提下,怎样控制鼠标在屏幕上移动?(100分)

  • 主题发起人 主题发起人 hbzh1014
  • 开始时间 开始时间
H

hbzh1014

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样用程序模拟手工操作鼠标,需要移动和按键。
 
两个API:
SetCursorPos
mouse_event
 
SendInput
The SendInput function synthesizes keystrokes, mouse motions, and
button clicks.

UINT SendInput(
UINT nInputs, // count of input events
LPINPUT pInputs, // array of input events to insert
int cbSize // size of an INPUT structure
);

INPUT
The INPUT structure is used by SendInput to synthesize keystrokes,
mouse motions, and button clicks.

typedef struct tagINPUT {
DWORD type;
union
{
MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
} INPUT, *PINPUT, FAR* LPINPUT;

QuickInfo
Windows NT: Requires version 4.0 SP3 or later.
Windows: Requires Windows 98 or later.
Windows CE: Unsupported.
Header: Declared in winuser.h.
mouse_event是一个专门用于模拟鼠标动作的Api函数,用它肯定可以达到你的要求
的。与此相应还有个Keybd_event用于模拟键盘动作.
 
// Recorder
//
// cyamon software
// place de l'H魌el-de-Ville 8
// 1040 Echallens
// Switzerland
// www.cyamon.com

// Demo program for TRecorder

unit main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Spin, Recorder, Menus
;

type
TForm1 = class(TForm)
BTNPlay: TButton;
BTNRecord: TButton;
GRPSpeed: TGroupBox;
SpinEdit1: TSpinEdit;
BTNStop: TButton;
BTNSave: TButton;
BTNLoad: TButton;
OpenDialog: TOpenDialog;
SaveDialog: TSaveDialog;
Label1: TLabel;
procedure BTNRecordClick(Sender: TObject);
procedure BTNStopClick(Sender: TObject);
procedure BTNPlayClick(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BTNLoadClick(Sender: TObject);
procedure BTNSaveClick(Sender: TObject);
private
{ Private declarations }
procedure OnRecorderStateChange(NewState : TRecorderState);
procedure HandleMessage(var Msg: TMsg; var Handled: Boolean);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation
uses
IniFiles;

const
ApplicationName = 'recorder';
var
ApplicationDir_ : array [0..255] of char;
PrivateProfileFileName_ : string;

{$R *.DFM}
{~t}
(**************)
(* ExecDialog *)
(**************)

function ExecDialog(D : TOpenDialog; const Key : string) : boolean;
var
IniFile : TIniFile;
begin
IniFile := TIniFile.Create(PrivateProfileFileName_);
try
if D.FileName = '' then
D.FileName := IniFile.ReadString('LastFile',Key,'');
Result := D.Execute;
if Result then
IniFile.WriteString('LastFile',Key,D.FileName);
finally
IniFile.Free;
end {try};
end {ExecDialog};


(***********************)
(* TForm1.BTNLoadClick *)
(***********************)

procedure TForm1.BTNLoadClick(Sender: TObject);
var
F : TFileStream;
begin
if ExecDialog(OpenDialog, '1') then begin
F := TFileStream.Create(OpenDialog.FileName, fmOpenRead);
try
TheRecorder.Stream.Size := 0;
TheRecorder.Stream.CopyFrom(F, F.Size);
OnRecorderStateChange(rsIdle);
finally
F.Free;
end;
end {if};
end {TForm1.BTNLoadClick};


(***********************)
(* TForm1.BTNPlayClick *)
(***********************)

procedure TForm1.BTNPlayClick(Sender: TObject);
begin
TheRecorder.DoStop;
TheRecorder.DoPlay;
end {TForm1.BTNPlayClick};


(*************************)
(* TForm1.BTNRecordClick *)
(*************************)

procedure TForm1.BTNRecordClick(Sender: TObject);
begin
TheRecorder.DoStop;
TheRecorder.DoRecord(false)
end {TForm1.BTNRecordClick};


(***********************)
(* TForm1.BTNSaveClick *)
(***********************)

procedure TForm1.BTNSaveClick(Sender: TObject);
var
F : TFileStream;
begin
if ExecDialog(SaveDialog, '1') then begin
F := TFileStream.Create(SaveDialog.FileName, fmCreate);
try
TheRecorder.Stream.Seek(0, soFromBeginning);
F.CopyFrom(TheRecorder.Stream, TheRecorder.Stream.Size);
finally
F.Free;
end;
end {if};
end {TForm1.BTNSaveClick};


(***********************)
(* TForm1.BTNStopClick *)
(***********************)

procedure TForm1.BTNStopClick(Sender: TObject);
begin
TheRecorder.DoStop;
end {TForm1.BTNStopClick};


(*********************)
(* TForm1.FormCreate *)
(*********************)

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := HandleMessage;
TheRecorder.OnStateChange := OnRecorderStateChange;
SpinEdit1.Value := TheRecorder.SpeedFactor;
OnRecorderStateChange(rsIdle);
end {TForm1.FormCreate};


(************************)
(* TForm1.HandleMessage *)
(************************)

procedure TForm1.HandleMessage(var Msg: TMsg; var Handled: Boolean);
begin
if Msg.Message = WM_CANCELJOURNAL then
TheRecorder.DoStop;
end {TForm1.HandleMessage};


(********************************)
(* TForm1.OnRecorderStateChange *)
(********************************)

procedure TForm1.OnRecorderStateChange(NewState: TRecorderState);
begin
case NewState of
rsIdle : Caption := 'Idle';
rsRecording : Caption := 'Recording';
rsPlaying : Caption := 'Playing'
end {case};
BTNPlay.Enabled := (NewState in [rsIdle]) and (TheRecorder.Stream.Size > 0);
BTNRecord.Enabled := NewState in [rsIdle];
BTNStop.Enabled := NewState in [rsRecording];
BTNSave.Enabled := (NewState in [rsIdle]) and (TheRecorder.Stream.Size > 0);
BTNLoad.Enabled := NewState in [rsIdle];
end {TForm1.OnRecorderStateChange};


(**************************)
(* TForm1.SpinEdit1Change *)
(**************************)

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
TheRecorder.SpeedFactor := SpinEdit1.Value;
end {TForm1.SpinEdit1Change};


{~b}

initialization
GetModuleFileName(hInstance,ApplicationDir_,SizeOf(ApplicationDir_));
StrPCopy(ApplicationDir_,ExtractFilePath(StrPas(ApplicationDir_)));
PrivateProfileFileName_ := StrPas(ApplicationDir_)+ApplicationName+'.ini';
end.

=============================================================================================
// TRecorder
//
// cyamon software
// place de l'H魌el-de-Ville 8
// 1040 Echallens
// Switzerland
// www.cyamon.com

// 11/99

// This unit is a freeware. You may change it, use it in your applications
// at your own risks.

// The recorder is an object that allows to record and play back mouse and
// keyboard events. The recorder is not a component, it is instead a singleton
// that is created and destroyed automatically in the initialization and
// finalization parts of this unit. The recorded information is saved into a
// memory stream.

// The recorder exports the following properties and methods:

// property State (Read only) is the recorder's state (idle, recording or playing).

// property SpeedFactor is the factor (in %) by which the playback speed is modified.
// Values < 100 accelerate, and values > 100 slowdown.

// property OnStateChange is an event that is fired when the state changes.

// procedure DoRecord(Append : boolean);
// Starts recording. When "Append" is true the new recorded information is appended
// to information already stored in the local stream. Otherwise, the local stream is
// clared before recording.

// procedure DoPlay;
// Plays the recorded information

// procedure DoStop;
// Stops recording and/or to playing

unit Recorder;

interface
uses
Classes, Windows;

type
TRecorderState = (rsIdle, rsRecording, rsPlaying);
TStateChangeEvent = procedure(NewState : TRecorderState) of object;

TRecorder = class(TObject)
private
EventMsg : TEVENTMSG;
FState : TRecorderState;
FStream : TStream;
HookHandle : THandle;
BaseTime : integer;
FSpeedFactor : integer;
FOnStateChange : TStateChangeEvent;
procedure SetSpeedFactor(const Value: integer);
constructor Create;
destructor Destroy; override;
procedure SetState(const Value: TRecorderState);
public
procedure DoPlay;
procedure DoRecord(Append : boolean);
procedure DoStop;
property SpeedFactor : integer read FSpeedFactor write SetSpeedFactor;
property OnStateChange : TStateChangeEvent read FOnStateChange write FOnStateChange;
property State : TRecorderState read FState;
property Stream : TStream read FStream;
end;

var
TheRecorder : TRecorder;

implementation
uses
SysUtils, Messages;
{~t}
(************)
(* PlayProc *)
(************)

function PlayProc(Code : integer; Undefined : WPARAM; P : LPARAM) : LRESULT; stdcall;
begin
if Code < 0 then
Result := CallNextHookEx(TheRecorder.HookHandle, Code, Undefined, P)
else begin
case Code of
HC_SKIP: begin
if TheRecorder.FStream.Position < TheRecorder.FStream.Size then begin
TheRecorder.FStream.Read(TheRecorder.EventMsg, SizeOf(EventMsg));
TheRecorder.EventMsg.Time := TheRecorder.SpeedFactor*(TheRecorder.EventMsg.Time div 100);
TheRecorder.EventMsg.Time := TheRecorder.EventMsg.Time + TheRecorder.BaseTime;
end else
TheRecorder.SetState(rsIdle);
end;

HC_GETNEXT: begin
Result := TheRecorder.EventMsg.Time - GetTickCount();
if Result < 0 then
Result := 0;
PEVENTMSG(P)^ := TheRecorder.EventMsg;
end;
else
PEVENTMSG(P)^ := TheRecorder.EventMsg;
Result := CallNextHookEx(TheRecorder.HookHandle, Code, Undefined, P)
end {case};
end {if};
end {PlayProc};


(**************)
(* RecordProc *)
(**************)

function RecordProc(Code : integer; Undefined : WPARAM; P : LPARAM) : LRESULT; stdcall;
begin
if Code < 0 then
Result := CallNextHookEx(TheRecorder.HookHandle, Code, Undefined, P)
else begin
case Code of
HC_ACTION: begin
TheRecorder.EventMsg := PEVENTMSG(P)^;
TheRecorder.EventMsg.Time := TheRecorder.EventMsg.Time-TheRecorder.BaseTime;
if (TheRecorder.EventMsg.Message >= WM_KEYFIRST) and (TheRecorder.EventMsg.Message <= WM_KEYLAST) and
(LoByte(TheRecorder.EventMsg.ParamL) = VK_CANCEL) then begin
// Recording aborted by ctrl-Break
TheRecorder.SetState(rsIdle);
end {if};
TheRecorder.FStream.Write(TheRecorder.EventMsg, sizeOf(TheRecorder.EventMsg));
end;
HC_SYSMODALON:;
HC_SYSMODALOFF:
end {case};
end {if};
end {RecordProc};


(********************)
(* TRecorder.Create *)
(********************)

constructor TRecorder.Create;
begin
if TheRecorder = nil then begin
FStream := TMemoryStream.Create;
FSpeedFactor := 100;
end else
Fail;
end {TRecorder.Create};


(*********************)
(* TRecorder.Destroy *)
(*********************)

destructor TRecorder.Destroy;
begin
DoStop;
FStream.Free;
inherited;
end {TRecorder.Destroy};


(********************)
(* TRecorder.DoPlay *)
(********************)

procedure TRecorder.DoPlay;
begin
if State <> rsIdle then
raise Exception.Create('Recorder: Not ready to play.')
else if FStream.Size = 0 then
raise Exception.Create('Recorder: Nothing to play')
else begin
FStream.Seek(0,0);
FStream.Read(EventMsg, SizeOf(EventMsg));
HookHandle := SetWindowsHookEx(WH_JOURNALPLAYBACK, @PlayProc, hInstance, 0);
if HookHandle = 0 then
raise Exception.Create('Playback hook cannot be created')
else begin
BaseTime := GetTickCount();
SetState(rsPlaying);
end {if};
end {if};
end {TRecorder.DoPlay};


(**********************)
(* TRecorder.DoRecord *)
(**********************)

procedure TRecorder.DoRecord(Append : boolean);
begin
if State <> rsIdle then
raise Exception.Create('Recorder: NotReady to record.')
else begin
if not Append then begin
FStream.Size := 0;
BaseTime := GetTickCount();
end else begin
EventMsg.Time := 0;
if FStream.Size > 0 then begin
FStream.Seek(-SizeOf(EventMsg),soFromCurrent);
FStream.Read(TheRecorder.EventMsg, SizeOf(EventMsg));
end {if};
BaseTime := GetTickCount() - EventMsg.Time;
end {if};
HookHandle := SetWindowsHookEx(WH_JOURNALRECORD, @RecordProc, hInstance, 0);
if HookHandle = 0 then
raise Exception.Create('JournalHook cannot be created')
else begin
SetState(rsRecording);
end {if};
end {if};
end {TRecorder.DoRecord};


(********************)
(* TRecorder.DoStop *)
(********************)

procedure TRecorder.DoStop;
begin
SetState(rsIdle);
end {TRecorder.DoStop};


(****************************)
(* TRecorder.SetSpeedFactor *)
(****************************)

procedure TRecorder.SetSpeedFactor(const Value: integer);
begin
if Value > 0 then
FSpeedFactor := Value;
end {TRecorder.SetSpeedFactor};


(**********************)
(* TRecorder.SetState *)
(**********************)

procedure TRecorder.SetState(const Value: TRecorderState);
begin
if (Value = rsIdle) and (HookHandle <> THandle(0)) then begin
UnhookWindowsHookEx(HookHandle);
HookHandle := THandle(0);
end {if};
if Value <> FState then begin
FState := Value;
if Assigned(FOnStateChange) then
FOnStateChange(FState)
end {if};
end {TRecorder.SetState};


{~b}
initialization
TheRecorder := nil;
TheRecorder := TRecorder.Create;
finalization
TheRecorder.Free;
end.
 
以前问过好几次了。

模拟鼠标

鼠标移动(移动量dx,dy)
mouse_event(MOUSEEVENTF_MOVE,dx,dy,0,0);
鼠标在(x,y)处按下或释放
setcursorpos(x,y);
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
鼠标双击由两次按下与释放来模拟

键盘模拟

一般虚拟键值(VK_)由KeyDown或keyup事件得到
特殊键值
Tab--9
Shift--16
Ctrl--17
Alt--18
CapsLock--20
Esc--27
Win--91,92
NumLock--144
ScrollLock--145

按下键
keybd_event(key,MapVirtualKey(key,0),KEYEVENTF_KEYUP,0);
释放键
keybd_event(key,MapVirtualKey(key,0),0,0);
 
要是还不明白留下EMAIL我发原程序给你
 
Mouse.CursorPos := Point(0, 0);
 
procedure TForm1.FormClick(Sender: TObject);
begin
// 运行该程序桌面上不能有其它的窗口,才能出效果
// 移动到桌面的我的电脑处
SetCursorPos(41,41); // 举个例子

//在当前鼠标双击左键,例如在桌面下运行该程序,可以打开我得电脑
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
Application.ProcessMessages;
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

//在当前鼠标位置按左键
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Application.ProcessMessages;
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

//在当前鼠标位置按右键
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
Application.ProcessMessages;
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
end;
 
如果要使用中键功能的话用MOUSEEVENTF_MIDDLEDOWN和MOUSEEVENTF_MIDDLEUP消息,如:
mouse_event(MOUSEEVENTF_MIDDLEDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_MIDDLEUP,0,0,0,0);
Application.ProcessMessages;
 
调用api函数setcursorpos就可以设置鼠标位置
 
谢谢大家
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部