C # One of the simulated keyboard and mouse

Source: Internet
Author: User
Tags reflector

 

Some tasks in the work need to use a simulated keyboard and mouse to automatically call the business, although the original colleagues have done some sharing methods and used XML configuration files to configure the simulated action flow, however, the combination of common methods and XML configuration still requires a lot of trouble.

The configuration is as follows:

  
It is hard to understand some configurations. I personally think that apart from writing this configuration myself or using developers for a period of time, it is difficult for other developers to modify or recreate the configuration. You may be looking forward to business processing. The business judgment is as follows:

  

Basically, it is the Switch judgment for each node. General nodes are nothing more than that. However, when extra services are involved, other nodes must be set as the basis for the judgment, complex.

As a result, almost a month after I entered the company, I was assigned this task and tried to understand the configuration, public methods, and processing code, we found that we still need to re-create a new module, which makes business processing clearer and easier to configure.

First, I started with configuration. In fact, every node is a step, each step is nothing more than capturing the parent form, capturing the corresponding child form from the parent form, moving the mouse to a coordinate or form, inputting a value, and obtaining a value.

The new configuration is as follows:

  

The new configuration uses a common name as the name of the node. Different Nodes are configured for different configurations. The NameSpace attribute in root is used to configure specific business classes for reflection.

Program: The Program started, which is read according to the Registry.

 

Form: a separate Form.

 

Child: Child forms or controls inside the form, except for labels.

 

KeyBoard: a key, a separate key or a combination of keys.

 

ClickTo: locates in the center of the form of the previous node based on the specific coordinates or when the coordinate data does not exist. Click

 

If: when determining a node, you should be familiar with it, that is, when the condition is true, the internal actions of the node will be executed.

 

Each: similar to If, but will be executed cyclically.

 

Call: calls a specific class method, which is not shown in the configuration diagram.

 

Because the steps are triggered by reading the information of each node in XML, and some molecular steps need to call the parent step form, we need to provide a base class method for each subclass to implement, the Code is as follows:

 

1 /// <summary>

2 // Execute

3 /// </summary>

4 public abstract void Execute ();

5

6 /// <summary>

7 // Initialization

8 /// </summary>

9 // <param name = "step"> previous step </param>

10 /// <param name = "node"> node </param>

11 public virtual void Init (AbstractStep step, XElement node)

12 {

13 this. ParentStep = step;

14 this. Node = node;

15 this. State = EnumStepState. Normal;

16 this. Message = string. Empty;

17}

Subclass:

 

1 /// <summary>

2 // procedure description: Move

3 // created by ahl

4 // Creation Time: 2011-10-31

5 /// </summary>

6 class MoveToStep: AbstractStep

7 {

8 # region variable

9

10 /// <summary>

11 /// abscissa

12 /// </summary>

13 int x = 0;

14

15 /// <summary>

16 // ordinate

17 /// </summary>

18 int y = 0;

19

20 # endregion

21

22 # region Method

23

24 /// <summary>

25 // execution Method

26 /// </summary>

27 public override void Execute ()

28 {

29 if (this. ParentStep. Wnd! = IntPtr. Zero)

30 {

31 var rect = this. ParentStep. Wnd. GetWindowRect ();

32 if (this. x = 0 & this. y = 0)

33 {

34 this. x = (rect. Left + rect. Right)/2;

35 this. y = (rect. Top + rect. Bottom)/2;

36}

37 else

38 {

39 this. x + = this. x <0? Rect. Right: rect. Left;

40 this. y + = this. y <0? Rect. Bottom: rect. Top;

41}

42}

43 Hook. SetCursorPos (this. x, this. y );

44}

45

46 // <summary>

47 // Initialization

48 /// </summary>

49 // <param name = "step"> previous step </param>

50 /// <param name = "node"> node </param>

51 public override void Init (AbstractStep step, XElement node)

52 {

53 base. Init (step, node );

54 var nodeValue = this. Node. Value;

55 if (! String. IsNullOrEmpty (nodeValue ))

56 {

57 var pos = nodeValue. Split (',');

58 this. x + = Convert. ToInt32 (pos [0]);

59 this. y + = Convert. ToInt32 (pos [1]);

60}

61}

62

63 # endregion

64}

1 /// <summary>

2 // program description: Move to click

3 // created by ahl

4 // Creation Time: 2011-10-31

5 /// </summary>

6 class ClickToStep: AbstractStep

7 {

8 # region variable

9

10 /// <summary>

11 // move

12 /// </summary>

13 MoveToStep moveTo;

14

15 # endregion

16

17 # region Method

18

19 /// <summary>

20 // execution Method

21 /// </summary>

22 public override void Execute ()

23 {

24 this. moveTo = new MoveToStep ();

25 this. moveTo. Init (this. ParentStep, this. Node );

26 this. moveTo. Execute ();

27 Hook. MouseEvent (MouseEventFlag. LeftDown | MouseEventFlag. LeftUp, 0, 0, 0, IntPtr. Zero );

28}

29

30 # endregion

31}

Otherwise, the code is too long. With some basic steps and configurations, we need a class that can be used to parse the configuration. It mainly resolves nodes and recursive subnodes. For some special nodes, such as If, Each, and Call, additional processing is required. The Code is as follows:

 

1 /// <summary>

2 // obtain the subnode

3 /// </summary>

4 /// <param name = "parentStep"> step object of the parent node </param>

5 /// <param name = "childList"> subnode list </param>

6 /// <param name = "nowList"> List of subnode steps </param>

7 void GetChildStep (AbstractStep parentStep, IEnumerable <XElement> childList, IList <AbstractStep> nowList)

8 {

9 foreach (var node in childList)

10 {

11 SimpleReflector normalReflector = new SimpleReflector (typeof (AbstractStep), string. Format ("AHL. HookHelper. SMK. {0} Step", node. Name. LocalName ));

12 AbstractStep step = normalReflector. GetClassObject () as AbstractStep;

13 step. Init (parentStep, node );

14 nowList. Add (step );

15 switch (node. Name. LocalName)

16 {

17 case "Form ":

18 case "Child ":

19 this. GetChildStep (step, step. Node. Elements (), nowList );

20 break;

21 case "If ":

22 case "Each ":

23 var eachStep = step as SMK. IfStep;

24 this. GetChildStep (step. ParentStep, step. Node. Elements (), eachStep. StepList );

25 eachStep. SetProperty (this. reflector, this. simulation, this. interval );

26 break;

27 case "Call ":

28 (step as SMK. CallStep). ReflectorMethod (this. reflector );

29 break;

30}

31}

32}

Now we have completed the configuration, node, and resolution work, so it is almost the final stage. That is, we can use the timer to perform regular operations on the current step, the Code is as follows:

 

1 /// <summary>

2 // set the timer event

3 /// </summary>

4 void SetTimerTick ()

5 {

6 this. timer. Tick + = (_ s, _ e) =>

7 {

8 var step = this. stepList [this. index ++];

9 try

10 {

11 step. Execute ();

12 switch (step. State)

13 {

14 case EnumStepState. Normal:

15 this. stepList. Count. If (l => l <= this. index, () =>

16 {

17 this. index = 0;

18 this. Finish (EnumStepState. Normal, step. Message );

19 });

20 break;

21 case EnumStepState. Back:

22 this. index --;

23 break;

24 default:

25 this. Finish (step. State, step. Message;

26 break;

27}

28}

29 catch (Exception ex)

30 {

31 this. Finish (EnumStepState. Exception, ex. Message );

32}

33 };

34}

Because the current version only simulates the keyboard and mouse, but when the form uses a Label like this, the window api cannot capture any data in this case, in this case, I started another new learning. I will continue to discuss about the process memory in the window api.

 

Author ahl5esoft

Related Article

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.