Delphi SendInput simulation using the mouse button

This article was originally published in the programming forum, the article addresses: http://programbbs.com/bbs/view12-17219-1.htm , relevant documents can be downloaded at the above address of the page. Please indicate the source reprinted.

Foreword

  Issued a "simulated using the Delphi WinIo mouse keyboard Explanation" ( http://programbbs.com/bbs/view12-17207-1.htm ), then send a program using the keyboard and mouse SendInput simulation, for comparison.

一、SendInput

  SendInput mouse and keyboard can be specified message into the system message queue so that the analog of the mouse and keyboard. There are many programs to SendInput been shielded, but not all. So here is what you use SendInput of. I have the main analog functions written in a unit file: SIMouseKeyboard.pas, call the unit file related functions to simulate mouse and keyboard can be achieved. Download see the end of the floor of the unit file. SendInput argument is very simple, there is a statement in Windows.pas function is as follows:

function SendInput(cInputs: UINT; var pInputs: TInput; cbSize: Integer): UINT; stdcall;

  cInputs: the number of elements in the array definition pInputs recorded. pInputs: a first type of recording element arrays TInput. Each element represents inserted into the system message queue keyboard or mouse events. cbSize: TInput defined size, typically SizeOf (TInput). Function returns the number of events in the system message queue insertion success, else return 0. Call SendInput key is to figure out the meaning of several of its record structure, in Windows.pas declared to TInput as follows:

tagINPUT = packed record
    Itype: DWORD;
    case Integer of
      0: (mi: TMouseInput);
      1: (ki: TKeybdInput);
      2: (hi: THardwareInput);
end;
TInput = tagINPUT;

  Wherein mi, ki, hi is a common type of three record structure, indicating the type of record structure IType used, which has three values. INPUT_MOUSE: mi indication record structure, ignoring ki and hi; INPUT_KEYBOARD: ki indication record structure, and ignoring mi hi.

Second, the keyboard emulation

  Statement TKeybdInput record structure is as follows:

tagKEYBDINPUT = packed record
    wVk: WORD;
    wScan: WORD;
    dwFlags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
end;
TKeybdInput = tagKEYBDINPUT;

  WVk wherein the key is to be operated virtual key code. wScan is a security code, generally do not. dwFlags designation operation performed by the keyboard, when a key is pressed represents 0, KEYEVENTF_KEYUP represents a key release. a time stamp, can use the API functions GetTickCount return value. dwExtraInfo is extension information, can use the API functions GetMessageExtraInfo return value. For example keystroke "A" of the procedure is as follows:

procedure KeyPressA;
var
    Inputs : array [0..1] of TInput;
begin
    Inputs[0].Itype:=INPUT_KEYBOARD;
    with Inputs[0].ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=0;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    Inputs[1].Itype:=INPUT_KEYBOARD;
    with Inputs[1].ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=KEYEVENTF_KEYUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(2,Inputs[0],SizeOf(TInput));
end;

  Note: Windows.pas unit does not declare virtual alphanumeric key code, I wrote SIMouseKeyboard.pas unit files were re-statement of all virtual key code, including letters, numbers and punctuation marks.

Third, mouse emulation

  Statement TMouseInput record structure is as follows:

tagMOUSEINPUT = packed record
    dx: Longint;
    dy: Longint;
    mouseData: DWORD;
    dwFlags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
end;
TMouseInput = tagMOUSEINPUT;

  Where dx, dy is the difference between the coordinates (in units of pixels not) when the mouse movement, the mouse is moved is valid. mouse wheel is mouseData value, effective when the mouse wheel. When scrolling down mouseData is less than 0, greater than 0 mouseData when scrolling up, the absolute value of mouseData generally set 120. dwFlags mouse designation operation performed, e.g., MOUSEEVENTF_MOVE represents move the mouse, MOUSEEVENTF_LEFTDOWN means press the left mouse button, MOUSEEVENTF_LEFTUP represents release the mouse button. a time stamp, can use the API functions GetTickCount return value. dwExtraInfo is extension information, can use the API functions GetMessageExtraInfo return value. For example, click the left mouse button procedure is as follows:

procedure MouseClick;
var
    Inputs : array [0..1] of TInput;
begin
    Inputs[0].Itype:=INPUT_MOUSE;
    with Inputs[0].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTDOWN;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    Inputs[1].Itype:=INPUT_MOUSE;
    with Inputs[1].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(2,Inputs[0],SizeOf(TInput));
end;

  Mouse movement is always cumbersome, above dx, dy not in pixels, but the amount of movement of the mouse device as a unit, they are affected by the ratio between the mouse moving speed setting. I have specific solutions "using the mouse and keyboard simulation WinIo explain under Delphi" a paper discussed at not repeated here. dwFlags MOUSEEVENTF_ABSOLUTE a flag may be provided, which makes it possible to use another method for moving the mouse. When dwFlags MOUSEEVENTF_ABSOLUTE flag is set, dx, dy to the screen coordinate value represents the mouse to move the position dx, dy of. But this is not the coordinate values ​​in units of pixels. The value range is 0 to 65535 ($ FFFF), represents the top left corner of the screen when dx is equal to 0, Dy equal to 0, when dx is equal to 65535, Dy represents the lower right corner of the screen is equal to 65535, corresponding to the screen width and height, respectively aliquot 65536. API function GetSystemMetrics (SM_CXSCREEN) can return to the width of the screen, the function GetSystemMetrics (SM_CYSCREEN) to return the screen height, width and height using a screen pixel coordinates can be converted into the corresponding dx, dy. NOTE: This 1-pixel conversion error occur most. For example: the mouse pointer to the program at coordinates 150,120 screen as follows:

procedure MouseMove;
var
    Input : TInput;
begin
    Input.Itype:=INPUT_MOUSE;
    with Input.mi do
    begin
        dx:=($FFFF div (GetSystemMetrics(SM_CXSCREEN)-1)) * 150;
        dy:=($FFFF div (GetSystemMetrics(SM_CYSCREEN)-1)) * 120;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(1,Input,SizeOf(TInput));
end;

Four SendInput and WInIo contrast,

  "With WinIo Detailed simulation of mouse and keyboard at Delphi" in an article I've said a lot of shortcomings WinIo, SendInput almost none of these drawbacks. SendInput simulation simpler than WinIo. Event is inserted directly into the message queue of the system, so it is faster than WinIo. The system will also ensure data integrity, data packets confusion does not occur. The use of "absolute movement" can move the mouse pointer to the exact location, compatibility is no problem with the configuration of the isolation of the mouse. SendInput disadvantages of the most deadly, it will be shielded some programs. So in the case of priority SendInput SendInput and WInIo can be used. Further SendInput WInIo may engage with use, some of the procedures sensitive to click the left mouse button, you can use the left mouse button click WinIo simulation, simulation operation by the other SendInput.

Five, SIMouseKeyboard.pas use

  I'm in SIMouseKeyboard.pas unit files for all virtual key code re-statement contains no statement of letters, numbers and punctuation marks Windows.pas unit. In the file unit SIMouseKeyboard.pas total of nine function, used as follows:

1, procedure SIKeyDown (Key: WORD );
  specified key is pressed. Key to the virtual key codes.

2, procedure SIKeyUp (Key: WORD );
  release the specified key. Key to the virtual key codes.

3, procedure SIKeyPress (Key: WORD ; Interval: Cardinal);
  press and release a specified key, Interval is the time interval between the press and release. Note: This function does not support repeated machine-printed, that regardless of how most of Interval set button only once.

4, procedure SIKeyInput (const Text: String; Interval: Cardinal);
  simulated keyboard input specified text and returns successful. Text only single-byte characters (# 32 ~ # 126), Tab (# 9) and enter key (# 13), i.e., characters can be input from the keyboard, can be characters, other characters are ignored . Interval is the time between pressing and releasing the key interval, in milliseconds.

The demonstration program, the following key combinations Ctrl + A:
SIKeyDown (VK_CONTROL); // press Ctrl
SIKeyPress (VK_A); // keystroke A
SIKeyUp (VK_CONTROL); // release the Ctrl

5, procedure SIMouseDown (Key: WORD );
  press the mouse button is specified. Key to the virtual key codes, the left mouse button VK_LBUTTON, right to VK_RBUTTON, the bond is VK_MBUTTON.

6, procedure SIMouseUp (Key: WORD );
  releasing the mouse button is specified. Key to the virtual key codes, the left mouse button VK_LBUTTON, right to VK_RBUTTON, the bond is VK_MBUTTON.

7, procedure SIMouseClick (Key: WORD ; Interval: Cardinal);
  click of the specified key, Interval is pressed and the time interval between the release. Click too fast may cause some programs not recognized, appropriate adjustments to the value of Interval can solve this problem.

8, procedure SIMouseWheel (dZ: Integer );
  scroll wheel of the mouse. When scrolling down dZ is less than 0, when scrolling up dZ greater than 0, the absolute value of dZ generally set 120.

9, procedure SIMouseMoveTo (X, Y : Integer; MaxMove: Integer; Interval: Cardinal);
  the mouse pointer to a specific position, return success. X and Y are pixel values, the range of values of X and Y can not exceed the screen, MaxMove dX and dY maximum value during movement, Interval is the time interval between two moving, some programs sensitive mouse motion speed, when the mouse moves too fast when not respond to the mouse, set the appropriate value MaxMove and Interval can solve this problem.

The demonstration program, and drop to the specified location as follows:
SIMouseDown (VK_LBUTTON); // press the left mouse button
SIMouseMoveTo (780,300); // moved to a specified position
SIMouseUp (VK_LBUTTON); // release the mouse button

Update (January 31, 2010):

  Update SIMouseKeyboard.pas file, a strange BUG. SIMouseKeyboard.pas SendInput analog keyboard and mouse mainly use the API function. Disposable SendInput allows multiple input, for example, the following code:

//模拟输入“a”
procedure KeyPressA;
var
    Inputs : array [0..1] of TInput;
begin
    Inputs[0].Itype:=INPUT_KEYBOARD;
    with Inputs[0].ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=0;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    //
    Inputs[1].Itype:=INPUT_KEYBOARD;
    with Inputs[1].ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=KEYEVENTF_KEYUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(2,Inputs[0],SizeOf(TInput));
end;

  A total of two inputs, press and release the key. But after recently I made a few patches to the system (Win2000), tried several input method program, found SendInput actually turned into does not support multiple input! The first argument must be 1, otherwise no reaction analog input. Previous tests obviously is normal, I do not know where the problems lie? The above procedures required by the following:

//模拟输入“a”
procedure KeyPressA;
var
    Input : TInput;
begin
    Input.Itype:=INPUT_KEYBOARD;
    with Input.ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=0;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(1,Input,SizeOf(TInput));
    //
    Input.Itype:=INPUT_KEYBOARD;
    with Input.ki do
    begin
        wVk:=VK_A;
        wScan:=0;
        dwFlags:=KEYEVENTF_KEYUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(1,Input,SizeOf(TInput));
end;

  Functions affected in SIMouseKeyboard.pas file is SIKeyInput, I've modified the function and tested successfully. Use the links below to download the updated text SIMouseKeyboard.pas

Reproduced in: https: //www.cnblogs.com/rogee/archive/2010/09/14/1827249.html

Guess you like

Origin blog.csdn.net/weixin_34343689/article/details/94680838