Using Winio to simulate the mouse keyboard in Delphi

Source: Internet
Author: User



Http://www.cnblogs.com/rogee/archive/2010/09/14/1827248.html






This article was first published in the Programming forum, the article address: http://programbbs.com/bbs/view12-17207-1.htm, the relevant documents can be downloaded from the above address page. Please indicate the source when reproduced.



Objective



One day found SendInput to a program incredibly ineffective, but began to study Winio. On the internet to check a lot of information, found about Winio simulation Mouse keyboard information is very few, and some are just words are not very detailed language, and most of the simulation of the keyboard. Wrote some of their own programs to study one side, experienced countless times the keyboard deadlock, mouse full screen random fly, reset restart, and finally small results. Now write the findings and share them with you. In addition, I have a limited level of the text where there is a mistake to welcome the root sticker discussion. (PS: About the use of SendInput can refer to my written another post, "Delphi using SendInput Simulation mouse Keyboard" http://programbbs.com/bbs/view12-17219-1.htm)



I have written the main simulation function in a single unit file: Mousekeyboard.pas, call the relevant function in the cell file to achieve the mouse keyboard simulation. Please refer to the content of the 2 floor for the download and use of the unit file. At the end of the building, there is a Chinese-English translation of the PS/2 Mouse Keyboard protocol download, this Protocol is useful for writing simulation mouse keyboard program. In addition I also provide a mouse movement Speed test program, a simple demonstration program using Mousekeyboard.pas download.



First. Introduction of Winio



Winio bypasses the protection mechanisms of Windows systems by loading a kernel-mode device driver and using several underlying programming techniques that enable Windows applications to access the I/O ports and physical memory directly. Winio contains 3 files: WinIo.dll, Winio.sys, and Winio.vxd, where Winio.vxd drivers are used on win95/98 systems, and Winio.sys drivers are used on WINNT/2000/XP systems. WinIo.dll provides a call to a function function. In WinIo.dll, there are two functions that are most important: Initializewinio is used to initialize the driver for Winio, it must be called before all other function functions are called, Shutdownwinio is used to unload the Winio driver, before aborting the application function, or no longer need to use Wini o when called. After initialization is complete, you can read and write the I/O port without illegal operation, this program is to use the keyboard hardware port to write data to simulate the operation of the mouse keyboard.



Because it is the underlying hardware port read and write, it is necessary to understand the hardware related protocols, the most important protocol for the mouse keyboard is the PS/2 Mouse Keyboard Protocol (hereinafter referred to as the PS/2 protocol). I am here to provide a PDF version of the PS/2 Mouse Keyboard protocol, in the first half of the protocol is mainly about the hardware of the electrical interface Protocol, but the latter part of the content for the simulation of the mouse keyboard is very useful. It was a deal I had been churning on the internet for a long time before I found it. The download of the agreement is at the end of this building.



Second, Intel 8042



The Intel 8042 or compatible microcontroller (hereinafter referred to as i8042) is used as a controller for a PC keyboard, although it is called a keyboard controller, but in fact the mouse is also controlled by it. The i8042 is generally integrated in the chipset. Sends the specified command and data to the i8042 to simulate the operation of the mouse keyboard. The i8042 contains the following four registers:



Input buffer of one byte: contains bytes read from the mouse or keyboard;
Output buffer of one byte: contains the bytes to be written to the mouse or keyboard;
Status register of one byte: 8 status Flags, read-only.
One-byte control register: 7 control flags, read and write.



The first three registers (input, output, status) can be accessed directly via the $64 port and the functions of read-write and $64 ports are as follows:



Port Read and write function
Read input buffer
$ Write Write output buffer
$64 read-read status register
$64 Write Send command



The write $64 port is not written to any particular register, but is interpreted as sending a command to i8042. If the command receives a parameter, the parameter is sent to the $ port. Similarly, any return structure of the command can be read out from the port. The status flag for i8042 is read from the $64 port. They contain error messages, status information, and an indication that there is no data in the input and output buffers. These flags are defined as follows:



Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
┌──┬──┬──┬──┬──┬──┬──┬──┐
│perr│to│mobf│inh│a2│sys│ibf│obf│
└──┴──┴──┴──┴──┴──┴──┴──┘



Where the flag bit OBF is the most important (refer to the PS/2 protocol for other flag bits), which indicates whether the output buffer is full and can be written to the output buffer. 0 indicates that the output buffer is empty and 1 indicates that the output buffer is full. So check to see if the flag bit has been set to 0 before writing the data to the port. Also check the flag bit before sending the command to the $64 port, ensuring that the last operation has been completed. The program that writes data to the specified port is as follows, which uses an inline assembly to manipulate the port. Note: The mouse keyboard is a slow device, each operation must have a certain delay:



Procedure SetByte (Por,cod:byte);
Begin
Sleep (1);
Asm
PUSH EAX
PUSH EDX
Wait status register flag bit OBF 0
@Loop:
In al,$64
and al,01b
JNZ @Loop
Write Data
MOV Al,cod
MOV Dl,por
MOV dh,0
Out Dx,al



POP EDX
POP EAX
End
End



Send command to i8042 is write $64 port. After the command is sent, the command arguments are written to the $ port. There are two commands used to simulate the mouse keyboard operation (refer to the PS/2 protocol for other commands):



$D 2: Write the keyboard buffer and write the parameters to the input buffer as if it were received from the keyboard.
$D 3: Write the mouse buffer and write the parameters to the input buffer as if it were received from the mouse.



For example: Press "A" key, using the above program can be written as "SetByte ($64, $D 2); SetByte ($60,$1E); ". Note: If the data sent to the $ port is not more than 1 bytes, then send a command before each byte, for example: Press the "Insert" key to the program as "SetByte ($64, $D 2); SetByte ($E 0); SetByte ($64, $D 2); SetByte ($60,$52); ", to call SetByte four times. Knowing how to send commands to i8042, you can simulate the mouse keyboard in detail below.



Third, keyboard simulation



The keyboard's processor scans or monitors the key matrix. If it finds that a key is pressed, released, or pressed, the keyboard sends a "scan code" packet to i8042. Scan code has two different types: "Pass Code" and "Broken Code", when a key is pressed or pressed to send a pass code; When a key is released, a code breaker is sent. Each key is assigned a unique pass-and-break code, so that i8042 can determine which button to use by finding a unique scan code. A complete set of pass-through codes for each key make up the "Scan code sets". There are three sets of standard scan code sets are the first set, the second set and the third set. The i8042 default supports the first set of scan codes.



A part of the key is the code is the maximum position 1, but not all the keys are like this, and many keys scan code is not only 1 bytes. So there is no simple formula to calculate the scan code. If you want to know the pass code and the code breaker for a particular key, you will have to check the table for it. For example: "A" key of the pass code is $1E, broken code is $9e, "Insert" key of the pass code is $e0,$52, broken code for $E0, $D 2, the program of the simulation key is as follows:



Press and release the "A" key
SetByte ($64, $D 2); SetByte ($60,$1E);
SetByte ($64, $D 2); SetByte ($60,$9e);



Press and release the "Insert" key
SetByte ($64, $D 2); SetByte ($E 0);
SetByte ($64, $D 2); SetByte ($60,$52);
SetByte ($64, $D 2); SetByte ($E 0);
SetByte ($64, $D 2); SetByte ($D 2);



Special in the PS/2 agreement said in the first second set of scan code, there is no "pause/break" key to break code. When this key is pressed, the pass code is sent, and when it is released, nothing is sent. The pass code of the pause key in the first scan code is up to 6 bytes long: $E 1,$1d,$45, $E 1,$9d, $C 5. But I found in the actual test that the pass code of the pause key is actually the first 3 bytes: $E 1,$1d,$45, after 3 bytes $e1,$9d, $C 5 is the pause key code break. At least on my keyboard.



In the PS/2 agreement has all three sets of scanning code set all the code and the code is broken into a table, the specific content can be consulted related parts. In the unit file Mousekeyboard.pas I have defined the first set of keyboard scan codes as constant arrays, which also include the characters corresponding to the keys. There are two functions Mkfindkeycode and Mkfindkeychar in the cell, which can be used to find a constant array.



Fourth, mouse simulation



The standard PS/2 mouse supports the following inputs: X (left/right) displacement, Y (up/down) displacement, left, middle, and the back. The mouse reads these inputs at a fixed frequency and updates the different counters and then marks the moving and key states that are reflected. There are many PS/2 mice with additional input such as Microsoft's IntelliMouse, which supports both standard input and scroll wheel and two additional keys.



The standard mouse has two counters to keep track of displacement: X-offset counter and Y-shift counter. can store 9-bit 2 complement and each counter has an associated overflow flag. Their contents are sent to i8042 in the form of three-byte mobile packets, along with the state of the three mouse buttons. The displacement counter indicates the amount of displacement occurred after the last displacement packet was sent to i8042. The standard PS/2 mouse sends the displacement and key information to the i8042 using the following 3-byte packet format:



Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
┌────┬────┬────┬────┬──┬───┬───┬───┐
Byte 1│y Overflow bit │x overflow bit │y sign bit │x sign bit │ reset 1│ keys │ Right keys │ left keys │
├────┴────┴────┴────┴──┴───┴───┴───┤
Byte 2│x shift value, complement │
├──────────────────────────────────┤
Byte 3│y up/down SHIFT value, complement │
└──────────────────────────────────┘



The displacement counter is a 9-bit twos complement integer. Its highest bit appears as a sign bit in the first byte of the displacement packet, which is updated when the mouse read input is found to have a displacement, which is the cumulative amount of displacement since the last time the displacement packet was sent to i8042 (i.e. the displacement counter is reset after the last packet was sent to i8042). The range of values that the offset counter can represent is 255 to +255. If the range is exceeded, the corresponding overflow bit is set and the counter does not increase or decrease before the reset.



A popular extension of the standard PS/2 mouse is Microsoft's IntelliMouse. It includes support for five mouse buttons and three displacement axes (left and right, up and down, and rollers). These additional features require the use of 4-byte displacement packets instead of standard 3-byte packets. Microsoft's IntelliMouse uses a 4-byte displacement packet format in two cases, such as the following:



1, three keys with the wheel Mouse:



Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
┌────┬────┬────┬────┬──┬───┬───┬───┐
Byte 1│y Overflow bit │x overflow bit │y sign bit │x sign bit │ reset 1│ keys │ Right keys │ left keys │
├────┴────┴────┴────┴──┴───┴───┴───┤
Byte 2│x shift value, complement │
├──────────────────────────────────┤
Byte 3│y up/down SHIFT value, complement │
├──────────────────────────────────┤
Byte 4│z Scroll shift value, complement │
└──────────────────────────────────┘



The z-offset is a binary complement indicating the displacement of the wheel since the last data report. Valid values range from 8 to +7, which means that the value is actually only low four bits useful, and the high four bits are used only as symbol extension bits. When Z is less than 0, it means scrolling up and scrolling down when Z is greater than 0.



2, five keys with the Wheel Mouse:



Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
┌────┬────┬────┬────┬──┬───┬───┬───┐
Byte 1│y Overflow bit │x overflow bit │y sign bit │x sign bit │ reset 1│ keys │ Right keys │ left keys │
├────┴────┴────┴────┴──┴───┴───┴───┤
Byte 2│x shift value, complement │
├──────────────────────────────────┤
Byte 3│y up/down SHIFT value, complement │
├────┬────┬────┬────┬──┬───┬───┬───┤
Byte 4│ Place 0│ 0│ 5th keys │ 4th keys │z3│z2│z1│z0│
└────┴────┴────┴────┴──┴───┴───┴───┘



Z0~Z3 is the twos complement used to represent the displacement of the rollers since the last data report, the effective range from 8 to +7; the 4th key: 1 means the 4th button is pressed, 0 means the 4th key is not pressed; 5th key: 1 means the 5th button is pressed, and 0 indicates that the 5th key is not pressed. You can see three keys with the Wheel mouse and five keys with the wheel mouse the two packet formats are mutually compatible. Generally, the mouse is now used with a scroll wheel, so the use of the 4-byte packet format. Call the API function GetSystemMetrics (sm_cmousebuttons) to return the number of keys for the current mouse, and call GetSystemMetrics (Sm_mousewheelpresent) to return the current mouse with a scroll wheel. By calling these two API functions, you can determine whether a 3-byte packet or a 4-byte packet is currently being used. Knowing the format of the packet can send the $D3 command to i8042 to simulate the mouse operation, the program to simulate clicking the left mouse button is as follows:



Press the left mouse button
SetByte ($64, $D 3); SetByte ($60,$09);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$00); Three-button with Wheel mouse



Release the left mouse button
SetByte ($64, $D 3); SetByte ($60,$08);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$00); Three-button with Wheel mouse



Now to talk about mouse movement simulation, mouse movement simulation is actually a very headache problem. It's easy to just let the mouse move around, but it's not easy to move the mouse pointer over the screen to the specified coordinates. First, the mouse displacement counter uses a planar Cartesian coordinate system. It says that when the mouse moves to the left, X is less than 0, when the mouse moves to the right, X is greater than 0, and y is less than 0 when the mouse moves down and y is greater than 0 when the mouse moves up. The pointer coordinates on the screen use the computer screen coordinate system, which corresponds to a planar Cartesian coordinate system on the x-axis, and a positive sign on the y-axis.



Second, the decision to change the number of displacement counter is called resolution, the default resolution is: 4 counting units per millimeter. This means that the displacement of the Mouse Displacement counter (hereinafter referred to as the amount of mouse displacement) and the mouse pointer on the screen pixel Displacement (hereinafter referred to as the pointer displacement) is not the same. The ratio of the mouse displacement to the pointer displacement is related to the mouse movement speed setting, which can be set by adjusting the pointer movement speed in the Mouse tab of the Control Panel, which is saved in the registry HKEY_CURRENT_USER\Control Panel\mouse\ In mousesensitivity, this value can be set to a decimal point by modifying the registry, which can be obtained by invoking the API function SystemParametersInfo using the parameter spi_getmousespeed. In addition, the use of third-party mouse driver can also set the mouse movement speed, generally this type of drive has a mouse acceleration function, which makes the mouse displacement and the amount of pointer displacement is not determined at all.



When using the mouse driver with Windows, the pointer movement speed is set in the middle position in the Mouse tab, the value of Mousesensitivity in the registry is 10, and the ratio of mouse displacement to the amount of pointer displacement can be calculated, When the mouse displacement is less than 7 o'clock: the pointer displacement is equal to the amount of mouse displacement; When the mouse displacement is greater than or equal to 7 o'clock: the pointer displacement is twice times the mouse displacement amount. In this case the first 20 ratios are as follows, where n is the mouse displacement amount, CX, CY is the pointer displacement amount:



N, CX, CY
1, 1, 1
2, 2, 2
3, 3, 3
4, 4, 4
5, 5, 5
6, 6, 6
7, 14, 14
8, 16, 16
9, 18, 18
10, 20, 20
11, 22, 22
12, 24, 24
13, 26, 26
14, 28, 28
15, 30, 30
16, 32, 32
17, 34, 34
18, 36, 36
19, 38, 38
20, 40, 40



For example: The program that lets the mouse pointer move on the screen is as follows:



Move Mouse up 50 elephant cable
SetByte ($64, $D 3); SetByte ($60,$08);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$19);
SetByte ($64, $D 3); SetByte ($60,$00); Three-button with rollers



Mouse shift left 50 elephant cable
SetByte ($64, $D 3); SetByte ($60,$18);
SetByte ($64, $D 3); SetByte ($E 7);
SetByte ($64, $D 3); SetByte ($60,$00);
SetByte ($64, $D 3); SetByte ($60,$00); Three-button with rollers



I also found that some mice did not respond to large mouse movements (greater than 128 or greater than 170). Probably because no one can move the mouse so fast with the hand, so no need. This is to be noted during the simulation of mouse movement. Because there is no good algorithm, in the Mousekeyboard.pas I used a mouse to move the conversion table to calculate the mouse movement, this table is actually a 255-length integer array, which records how many units each mouse movement, the pointer will move how many pixels. I have also written several functions that provide the ability to import and export the table to the INI format file, so that it should be adaptable to most mouse configurations. I wrote a test of the mouse movement speed of the program, it can test the current mouse displacement and pointer displacement ratio, can be based on the diagonal movement, horizontal movement, vertical movement of the ratio to calculate the mouse Movement conversion table and saved to the INI file. The download of this program is at the end of this building.



Fifth. Advantages and disadvantages of using Winio



The advantage of using Winio is self-evident, and the direct hardware port read and write makes it impossible for many programs to block it. Its shortcomings are also very headache, the first is the problem of compatibility, the direct read and write hardware port will make the program run on some of the configured computers, and on other configured computers can not run. In particular, the USB mouse, my program is on the PS/2 mouse test, may be a part of the USB mouse is not compatible. The second is the problem of data conflict, in the simulation operation of the mouse keyboard is still working, if you operate the mouse keyboard may appear out of control phenomenon. especially the mouse. The reason: When the program to operate the simulation operation of the mouse keyboard, the program sent to i8042 packets may be sent to i8042 with the mouse keyboard packets to each other (because only 1 bytes can be sent at a time), resulting in packet chaos caused by the mouse keyboard out of control. I touched the mouse at one test and the mouse pointer flew on the screen. The last drawback is that this simulation is global, in the process of simulation you can not do anything, in fact, SendInput is the same.



Sixth. Use of Mousekeyboard.pas



The above package contains 4 files: Mousekeyboard.pas, WinIo.dll, Winio.sys, and Winio.vxd, and the following 3 files are Winio related files. Put the 4 files in the same folder as the project, and you can call the functions in Mousekeyboard.pas by adding Mousekeyboard to the uses segment of the cell. It is important to note that when your program is published, WinIo.dll, Winio.sys, and Winio.vxd are 3 files to be placed in the same folder as the executable file, which is called when the program is run. When the program is running on a "strange" computer, it is best to call the Mktestconversion function test and save the current computer's Mouse movement conversion table. It is also possible to generate INI files using the mouse move test program provided upstairs.



In Mousekeyboard.pas I defined an enumeration type of Tmkkeycode with 104 items corresponding to different keys. I have also defined a constant record array mkkeydata, which defines the scan code for 104 keys, the length of the pass code, the length of the code break, and the character corresponding to the key. There are 21 functions in Mousekeyboard.pas, using the following instructions:



1, function Mkinitmousekey:boolean;
This function initializes the Winio and initializes some internal variables, and the function attempts to open an INI file named "Mouse.ini" from the current folder and loads the mouse move conversion table from the "Conversion" section of the file. If this function fails, it calls Mkinitconversion to initialize a default mouse-movement conversion table. In general, do not call this function, the function is automatically called when the unit is loaded to complete the initialization.



2, procedure Mkfreemousekey;
Release the driver uninstall Winio, generally do not call this function, when the unit is unloaded automatically call this function to complete the unload release.



3, function mksenddata (const data:tmkpacketdata; Len:byte; Typ:tmkdatatype): Boolean;
Sends a packet to the specified keyboard mouse port to return success. The packet can be up to 4 bytes long, and Len is the byte length of the packet. This function embeds a setbyte function mentioned above to send bytes to the port.



4, Function Mkfindkeycode (code:tmkkeycode): Integer;
Finds the ID of the specified key in Mkkeydata, finds the return ID, and finds no return-1.



5, Function Mkfindkeychar (Char:ansichar): Integer;
Finds the ID of the specified character in Mkkeydata, finds the return ID, and does not find return-1.



6, Function Mkkeydown (code:tmkkeycode): Boolean;
Press the specified key to return the success.



7, Function Mkkeyup (code:tmkkeycode): Boolean;
Releases the specified key and returns whether it is successful.



8, function mkkeypress (code:tmkkeycode; interval:cardinal): Boolean;
Press and release the specified key to return to success. Interval is the time interval between pressing and releasing, in milliseconds. Note: This function does not support duplicate machines, that is, no matter how much interval is set, only one keystroke.



Demonstration program, combination key CTRL + A as follows:
Mkkeydown (Kclctrl); Hold down CTRL
Mkkeypress (KcA); Keystroke a
Mkkeyup (Kclctrl); Release CTRL



9, Function mkkeyinput (const text:string; interval:cardinal): Boolean;
Simulates the keyboard input of the specified text and returns whether it is successful. The text can only be single-byte characters (#32 ~ #126), Tab (#9) and enter (#13), that is, characters that can be entered from the keyboard, cannot be Chinese characters, and other characters are ignored. Interval is the time interval between press and release keys, in milliseconds.



10, Function Mkmousedown (code:tmkmousecode): Boolean;
Press the specified key of the mouse to return to success.



11, Function Mkmouseup (code:tmkmousecode): Boolean;
Releases the mouse's specified key and returns whether it is successful.



12, function Mkmouseclick (code:tmkmousecode; interval:cardinal): Boolean;
Click the specified key of the mouse to return to success. Interval is the time interval between press and release keys, in milliseconds.



13, Function Mkmousewheel (cz:integer): Boolean;
Scrolls the mouse wheel and returns whether it is successful. CZ for mouse wheel Scroll shift value, non-pixel value. CZ valid values range from 8 to +7 when the CZ is less than 0 o'clock scroll up when the CZ size 0 scrolls down.



14, Function Mkmousemove (cx,cy:integer): Boolean;
Moves the mouse pointer over the position on the screen and returns whether it is successful. CX and CY are the values of the mouse offset counter, non-pixel values. When CX is less than 0 o'clock to the left, when the CX size 0 o'clock moves to the right, when CY is less than 0 o'clock down, when CY is greater than 0 o'clock, move up. The values for CX and CY range from 255 to +255.



15, Procedure Mkinitconversion (Var con:tmkmoveconversion);
Initializes a mouse move conversion table, assuming that the mouse moves at a moderate speed and does not use other third-party mouse acceleration drivers.



16, Function Mktestconversion (var con:tmkmoveconversion; Maxmove:integer): Boolean;
Test and confirm the mouse move conversion table and return success. Maxmove is the maximum value of the mouse movement at the time of testing, this function will move the mouse diagonally, and record the actual moving pixels of the mouse pointer, calculate the mouse Movement conversion table. The mouse can not be manipulated during the test, or the mouse may be out of control, the test is not allowed.



17, Function Mkconversiontoini (const con:tmkmoveconversion; Inifile:tinifile; Const section:string): Boolean;
Exports the mouse move conversion table to the specified section of the INI file, returning success.



18, Function Mkconversionfromini (var con:tmkmoveconversion; Inifile:tinifile; Const section:string): Boolean;
Imports the mouse move conversion table from the specified section of the INI file, returning success.



19, Procedure mkloadconversion (const con:tmkmoveconversion);
Import a mouse move conversion table as the default conversion table.



20, function Mkmousemoveto (x,y:integer; const con:tmkmoveconversion; Maxmove:integer; interval:cardinal): Boolean;
21, function Mkmousemoveto (X,y:integer; Maxmove:integer; interval:cardinal): Boolean;
This is an overloaded two function that can move the mouse pointer to the specified position and return success. X and y are pixel values, and the range of values for x and Y cannot exceed the screen. Maxmove is the maximum value of CX and CY when moving. Interval is the time interval between two moves. The 1th function uses the specified mouse movement conversion table con for the calculation of moving coordinates, and the 2nd function calculates the movement coordinates using the default mouse movement conversion table. If the mouse movement speed is not set to medium, or use other third-party mouse acceleration driver, may make the function can not move the mouse pointer to the exact position, there will be some error. Some programs are sensitive to mouse movement speed, when the mouse moves too fast to respond to the mouse, the appropriate setting of the Maxmove value can solve the problem.



Demonstration program, drag and drop to the specified location as follows:
Mkmousedown (Mcleft); Press the left mouse button
Mkmousemoveto (780,300); Move to the specified position
Mkmouseup (Mcleft); Release the left mouse button



Update (January 8, 2010):



Update Mousekeyboard.pas file, there is a small bgu in the original file. Analog keyboard Input "Q", regardless of the case, the analog press is the input "Q", analog release when the input becomes "P". I checked the pass-through code, found that the "Q" of the code is actually "P" and the pass code is "$19". It must have been wrong. My pass-through code data was copied from the PS/2 protocol, and I looked at the same error as the data found in the file. "Q" of the pass code is "$", I try to pass the highest position of the code 1 into "$" as "Q" of the broken code. Such a test was successful on my computer and could successfully simulate the release of "Q". But I don't know if this will be a keyboard-compatible issue.



The updated Mousekeyboard.pas file only changes a small place. The 150th line in the original file consists of the following:



(CODE:KCQ; Char: ' QQ '; Length: $11; Make: ($10,$00,$00,$00); Break: ($19,$00,$00,$00)),



Revision changed to



(CODE:KCQ; Char: ' QQ '; Length: $11; Make: ($10,$00,$00,$00); Break: ($90,$00,$00,$00)),//code $19 changed to $



That is, the "Q" of the Broken code from "$19" changed to "$". You can also use the link below to download the updated Mousekeyboard.pas file






File Download: Http://files.cnblogs.com/rogee/SIMouseKeyboard.pas.zip



Using Winio to simulate the mouse keyboard in Delphi


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.