Autoclick -- cliquer automatiquement à plusieurs endroits à la fois

Description

Ce petit programme permet d'enregistrer des séquences de points puis de cliquer automatiquement dessus. Il est possible de spécifier le nombre de séquences à "jouer" et de mettre un délai entre chaque click et entre chaque séquence. Ce programme permet par exemple de cliquer à intervalle régulier sur une bannière de pub, de voter automatiquement pour un site ou toute autre utilisation qui implique de cliquer à intervalle régulier à un endroit donné.

Dans le code, pour ceux que ça intéresse, il y a des exemples pour faire les choses suivantes :
- Déplacer automatiquement le curseur
- Cliquer automatiquement à un endroit donné
- Créer une "hotkey" globale qui peut être déclenchée même quand le prog n'a pas le focus
- Créer des timer dynamiquement
- Faire une classe réutilisable et entièrement indépendante de l'interface graphique

Ci-dessous, la classe utilisée par le programme (voir le ZIP pour le programme complet :)

Source / Exemple :


unit pointListClass;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, inifiles;

type TPointList = class (TObject)
  private
    pPointList: array of TPoint;
    pFileName : string;
    pPointTimer : TTimer;
    pSequenceTimer : TTimer;
    pGlobalTimer : TTimer; // Sert juste à mesurer le temps entre chaque click
    pForm : TForm;
    pCurrentPointID : word;
    pClickInterval : LongWord;
    pSequenceInterval : LongWord;
    pNbSequences : LongWord;
    pSequenceCount : LongWord;
    procedure pPointOnTimer(Sender : TObject);
    procedure pSequenceOnTimer(Sender : TObject);
    procedure pGlobalOnTimer(Sender : TObject);
    procedure ClickPoint(const point : TPoint);
  public
    constructor Create(const form : TForm);
    function TimeToNextClick : longWord;
    procedure add(const point : TPoint);
    function get(const i : byte) : TPoint;
    procedure deleteLast;
    procedure deleteAt(const listIndex : word);
    function count : word;
    procedure clear;
    function print : string;
    function getFileName : string;
    procedure setFileName(const s : string);
    function toStringList : TStringList;
    function save(const fileName : string) : boolean; overload;
    function load(const fileName : string) : boolean; overload;
    function save() : boolean; overload;
    function load() : boolean; overload;
    procedure run();
    procedure stop();
    function isRunning : boolean;
    property NumberOfSequences : LongWord read pNbSequences write pNbSequences;
    property TimeBetweenSequences : LongWord read pSequenceInterval write pSequenceInterval;
    property TimeBetweenClicks : LongWord read pClickInterval write pClickInterval;
  end;

implementation

uses main;

// Simule un click sur le point passé en paramètre
procedure TPointList.ClickPoint(const point : TPoint);
var saveState : TWindowState;
begin
  // Réduit la fiche
  saveState := pForm.WindowState;
  if pForm.WindowState <> wsMinimized then pForm.WindowState := wsMinimized;
  // Déplace le curseur
  setCursorPos(point.X, point.Y);
  // Clique
  mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
  mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
  // Restore la fiche
  pForm.WindowState := saveState;
end;

// Procédure appelée par le timer "pointTimer"
procedure TPointList.pPointOnTimer(Sender : TObject);
begin
  // Si tous les points n'ont pas encore été cliqués...
  if pCurrentPointID < self.count() then begin
    // Clique le point
    clickPoint(self.get(pCurrentPointID));
    pCurrentPointID := pCurrentPointID + 1;
    pGlobalTimer.Tag := 0;
  end;

  // Si tous les points ont été cliqués
  if pCurrentPointID = self.count() then begin
    // Désactive le timer "pointTimer" ...
    pPointTimer.Enabled := FALSE;
    // ...et active le timer "sequenceTimer"
    pSequenceCount := pSequenceCount + 1;
    // Si toutes les séquences n'ont pas été exécutées
    if pSequenceCount <= pNbSequences then begin
      // Démarre le timer pour que le programme pause pendant "pSequenceInterval" ms
      pSequenceTimer.Interval := pSequenceInterval;
      pSequenceTimer.Enabled := TRUE;
      pGlobalTimer.Tag := 0;
    end else begin
      // Stop
      self.stop();
    end;
  end;
end;

procedure TPointList.stop();
begin
  // Détruit tous les timers
  if pSequenceTimer <> nil then begin
    pSequenceTimer.Destroy;
    pSequenceTimer := nil;
  end;

  if pPointTimer <> nil then begin
    pPointTimer.Destroy;
    pPointTimer := nil;
  end;

  if pGlobalTimer <> nil then begin
    pGlobalTimer.Destroy;
    pGlobalTimer := nil;
  end;
end;

procedure TPointList.pGlobalOnTimer(Sender : TObject);
begin
  // Le tag sert à mémoriser le temps écoulé depuis le dernier click
  pGlobalTimer.Tag := LongWord(pGlobalTimer.Tag) + pGlobalTimer.Interval;
end;

procedure TPointList.pSequenceOnTimer(Sender : TObject);
begin
  // Prépare les données pour une nouvelle séquence
  pCurrentPointID := 0;
  pPointTimer.Interval := pClickInterval;
  pPointTimer.Enabled := TRUE;
  pSequenceTimer.Interval := pSequenceInterval;
  pSequenceTimer.Enabled := FALSE;
  pGlobalTimer.Tag := 0;
  self.pPointOnTimer(self);
end;

procedure TPointList.run();
begin
  if (pNbSequences > 0) and (self.count > 0) then begin
    // Créé les timers
    pPointTimer := TTimer.Create(nil);
    pPointTimer.OnTimer := self.pPointOnTimer;
    pPointTimer.Enabled := FALSE;

    pSequenceTimer := TTimer.Create(nil);
    pSequenceTimer.OnTimer := self.pSequenceOnTimer;
    pSequenceTimer.Enabled := FALSE;

    pGlobalTimer := TTimer.Create(nil);
    pGlobalTimer.OnTimer := self.pGlobalOnTimer;
    pGlobalTimer.Enabled := FALSE;

    // Valeur minimum de 1 sinon ça ne marche pas
    if pClickInterval = 0 then pClickInterval := 1;
    if pSequenceInterval = 0 then pSequenceInterval := 1;

    // Initialise les données pour une nouvelle séquence
    pCurrentPointID := 0;
    pPointTimer.Interval := pClickInterval;
    if pPointTimer.Interval = 0 then pPointTimer.Interval := 1;
    pSequenceCount := 1;
    pPointTimer.Enabled := TRUE;

    pGlobalTimer.Enabled := TRUE;
    pGlobalTimer.Interval := 1000;
    pGlobalTimer.Tag := 0;
    self.pPointOnTimer(self);
  end;
end;

function TPointList.isRunning : boolean;
begin
  Result := (pPointTimer <> nil) and (pSequenceTimer <> nil);
end;

constructor TPointList.Create(const form : TForm);
begin
  setLength(pPointList, 0);
  pForm := form;
  pFileName := '';
  pNbSequences := 1;
  pClickInterval := 0;
  pSequenceInterval := 0;
end;

procedure TPointList.clear;
begin
  setLength(pPointList, 0);
end;

function TPointList.getFileName : string;
begin
  result := pFileName;
end;

procedure TPointList.setFileName(const s : string);
begin
  pFileName := s;
end;

// Ajoute un point
procedure TPointList.add(const point : TPoint);
begin
  setLength(pPointList, length(pPointList) + 1);
  pPointList[length(pPointList) - 1] := point;
end;

// Retourne un point
function TPointList.get(const i : byte) : TPoint;
begin
  Result := pPointList[i];
end;

// Efface le dernier point
procedure TPointList.deleteLast;
begin;
  if length(pPointList) > 0 then begin
    setLength(pPointList, length(pPointList) - 1);
  end;
end;

// Efface un point
procedure TPointList.deleteAt(const listIndex : word);
var i : word;
begin
  if listIndex < length(pPointList) then begin
    i := listIndex;
    while i < length(pPointList) - 1 do begin
      pPointList[i] := pPointList[i+1];
      i := i + 1;
    end;
    setLength(pPointList, length(pPointList) - 1);
  end;
end;

// Nombre de points dans la liste
function TPointList.count;
begin
  Result := length(pPointList);
end;

function TPointList.print : string;
var i : byte;
    s : string;
begin
  i := 1;
  s := '';
  while i <= length(pPointList) do begin
    if i <> 1 then s := s + chr(13) + chr(10);
    if self.isRunning() then begin
      if pCurrentPointID = i - 1 then begin
        s := s + '->'
      end;
    end;
    s := s + 'Point ' + IntToStr(i) + ' = ';
    s := s + '(' + IntToStr(pPointList[i - 1].X) + ', ' + IntToStr(pPointList[i - 1].Y) + ')';
    i := i + 1;
  end;

  Result := s;
end;

function TPointList.toStringList : TStringList;
var i : byte;
begin
  i := 0;
  Result := TStringList.Create();
  while i < length(pPointList) do begin
    Result.Add('Point ' + IntToStr(i+1) + ' = ');
    Result[i] := Result[i] + '(' + IntToStr(pPointList[i].X) + ', ' + IntToStr(pPointList[i].Y) + ')';
    if self.isRunning() then begin
      if i < pCurrentPointID then begin
        Result[i] := Result[i] + ' <--'
      end;
    end;
    i := i + 1;
  end;
end;

function TPointList.TimeToNextClick : longWord;
begin
  Result := 0;
  if (self.isRunning()) then begin
    if pPointTimer.Enabled then begin
      if pGlobalTimer.Tag > pPointTimer.Interval then
        result := 0
      else
        Result := (Integer(pPointTimer.Interval) - pGlobalTimer.Tag);
    end else begin
      if pSequenceTimer.Enabled then begin
        if pGlobalTimer.Tag > pSequenceTimer.Interval then
          Result := 0
        else
          Result := (Integer(pSequenceTimer.Interval) - pGlobalTimer.Tag);
      end;
    end;
  end;
  Result := Result div 1000;
end;

// Sauvegarde
function TPointList.save(const fileName : string) : boolean;
var iniFile: TIniFile;
		i: LongWord;
begin
  iniFile := TIniFile.Create(fileName);

  iniFile.WriteString('CONFIG', 'ClickInterval', intToStr(pClickInterval));
  iniFile.WriteString('CONFIG', 'SequenceInterval', intToStr(pSequenceInterval));
  iniFile.WriteString('CONFIG', 'NumberOfSequences', intToStr(pNbSequences));
  iniFile.WriteString('CONFIG', 'NumberOfPoints', intToStr(length(pPointList)));
  i := 0;
	while i < length(pPointList) do begin
	  iniFile.WriteString('POINTS', 'px' + intToStr(i), intToStr(pPointList[i].x));
    iniFile.WriteString('POINTS', 'py' + intToStr(i), intToStr(pPointList[i].y));
    i := i + 1;
  end;
  iniFile.Free;

  result := true;
end;

// Charge
function TPointList.load(const fileName : string) : boolean;
var iniFile: TIniFile;
		i, numberOfPoints: LongWord;
    pointToAdd: TPoint; 
begin
	iniFile := TIniFile.Create(fileName);

  pClickInterval := strToInt(iniFile.ReadString('CONFIG', 'ClickInterval', '1'));
  pSequenceInterval := strToInt(iniFile.ReadString('CONFIG', 'SequenceInterval', '1'));
  pNbSequences := strToInt(iniFile.ReadString('CONFIG', 'NumberOfSequences', '1'));
  numberOfPoints := strToInt(iniFile.ReadString('CONFIG', 'NumberOfPoints', '0'));
  
  i := 0;
  while i < numberOfPoints do begin
    pointToAdd.X := strToInt(iniFile.ReadString('POINTS', 'px' + intToStr(i), '0'));
    pointToAdd.Y := strToInt(iniFile.ReadString('POINTS', 'px' + intToStr(i), '0'));
    self.add(pointToAdd);
    i := i + 1;
  end;
  
  iniFile.Free;
  
	result := true;
end;

function TPointList.save() : boolean;
begin
  if pFileName <> '' then
    Result := self.save(pFileName)
  else
    Result := FALSE;
end;

function TPointList.load() : boolean;
begin
  if pFileName <> '' then
    Result := self.load(pFileName)
  else
    Result := FALSE;
end;

end.

Conclusion :


L'exécutable est désormais disponible sur :

http://pogopixels.fr/download/AUTOCLICK.zip

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.