public override void Play() { InputBuilder inputBuilder = new InputBuilder(); CoordinateMode modeActual = this.mode; int xActual = this.xMove; int yActual = this.yMove; // Absolute mode in pixels isn't supported by SendInput() API // Glue supports it with this translation if (this.mode == CoordinateMode.PIXEL) { modeActual = CoordinateMode.ABSOLUTE; xActual = NormalizeX(this.xMove); yActual = NormalizeY(this.yMove); } // Add movement if one is specified switch (modeActual) { case CoordinateMode.ABSOLUTE: inputBuilder.AddAbsoluteMouseMovement(xActual, yActual); break; case CoordinateMode.ABSOLUTE_VIRTUAL_DESKTOP: inputBuilder.AddAbsoluteMouseMovementOnVirtualDesktop(xActual, yActual); break; case CoordinateMode.RELATIVE: inputBuilder.AddRelativeMouseMovement(xActual, yActual); break; case CoordinateMode.NONE: default: // If none specified don't do anything break; } switch (this.clickType) { case ClickType.PRESS: if (-1 != this.xButtonId) { inputBuilder.AddMouseXButtonDown(this.xButtonId); } else { inputBuilder.AddMouseButtonDown(this.button); } break; case ClickType.RELEASE: if (-1 != this.xButtonId) { inputBuilder.AddMouseXButtonUp(this.xButtonId); } else { inputBuilder.AddMouseButtonUp(this.button); } break; case ClickType.DOUBLE: if (-1 != this.xButtonId) { inputBuilder.AddMouseXButtonDoubleClick(this.xButtonId); } else { inputBuilder.AddMouseButtonDoubleClick(this.button); } break; case ClickType.CLICK: if (-1 != this.xButtonId) { inputBuilder.AddMouseXButtonClick(this.xButtonId); } else { inputBuilder.AddMouseButtonClick(this.button); } break; case ClickType.NONE: default: // Do nothing break; } if (LOGGER.IsDebugEnabled) { long now = TimeProvider.GetTickCount(); string message = String.Format( " Played at tick {0:n0} dt {1:n0}ms: {2} {3} {4} {5} ({6:n0}, {7:n0})", now, // Time actually played now - this.ScheduledTick, // Time delta (how late were we?) this.clickType, this.button, this.xButtonId, this.mode, this.xMove, this.yMove); LOGGER.Debug(message); } DISPATCHER.DispatchInput(inputBuilder.ToArray()); }