Comment : simuler des événements de la souris et du clavier dans le code
Windows Forms fournit plusieurs options pour simuler par programme l'entrée effectuée par clavier ou souris. Cette rubrique fournit une vue d'ensemble de ces options.
Simulation des entrées de la souris
Pour simuler les événements de souris, le mieux est d'appeler la méthode OnEventName qui déclenche l'événement de souris que vous souhaitez simuler. Cette option est généralement uniquement possible dans les contrôles et formulaires personnalisés, parce que les méthodes qui déclenchent des événements sont protégées et ne sont pas accessibles à l'extérieur du contrôle ou formulaire. Par exemple, les étapes suivantes illustrent comment simuler le clic avec le bouton droit de la souris dans le code.
Pour cliquer par programme avec le bouton droit de la souris
Créez un MouseEventArgs dont la propriété Button a la valeur MouseButtons.Right.
Appelez la méthode OnMouseClick en utilisant MouseEventArgs comme argument.
Pour plus d'informations sur les contrôles personnalisés, consultez Développement de contrôles Windows Forms au moment du design.
Il existe d'autres manières de simuler les entrées de souris. Par exemple, vous pouvez définir par programme une propriété de contrôle qui représente un état qui est défini en général à travers l'entrée de souris (telle que la propriété Checked du contrôle CheckBox), ou vous pouvez appeler directement le délégué qui est attaché à l'événement que vous souhaitez simuler.
Simulation d'une entrée au clavier
Bien que vous puissiez simuler l'entrée au clavier à l'aide des stratégies abordées ci-avant à propos de l'entrée de souris, Windows Forms fournit également la classe SendKeys pour envoyer des séquences de touches à l'application active.
Avertissement
Si votre application est prévue pour une utilisation internationale avec divers claviers, l'utilisation de SendKeys.Send pourrait donner lieu à des résultats imprévisibles et doit être évitée.
Notes
La classe SendKeys a été mise à jour pour le .NET Framework 3.0 afin d'activer son utilisation dans les applications qui s'exécutent sur Windows Vista. La sécurité améliorée de Windows Vista (connue sous le nom de contrôle de compte d'utilisateur) empêche l'implémentation antérieure de fonctionner comme prévu.
La classe SendKeys peut être exposée à des problèmes de synchronisation que certains développeurs ont dû contourner. L'implémentation mise à jour est encore vulnérable par rapport à ces problèmes, mais est légèrement plus rapide et peut nécessiter l'apport de modifications aux solutions de contournement. La classe SendKeys essaie d'abord d'utiliser l'implémentation antérieure et, en cas d'échec, utilise la nouvelle implémentation. Par conséquent, la classe SendKeys peut se comporter différemment sur les systèmes d'exploitation différents. En outre, lorsque la classe SendKeys utilise la nouvelle implémentation, la méthode SendWait n'attend pas le traitement des messages lorsqu'ils sont envoyés à un autre processus.
Si votre application compte sur un comportement cohérent indépendamment du système d'exploitation, vous pouvez forcer la classe SendKeys à utiliser la nouvelle implémentation en ajoutant le paramètre d'application suivant à votre fichier app.config.
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Pour forcer la classe SendKeys à utiliser l'implémentation antérieure, utilisez à la place la valeur "JournalHook".
Pour envoyer une séquence de touches à la même application
Appelez la méthode Send ou SendWait de la classe SendKeys. Les séquences de touches spécifiées seront reçues par le contrôle actif de l'application. L'exemple de code suivant utilise Send pour simuler un appui sur la touche ENTRÉE lorsque l'utilisateur double-clique sur la surface du formulaire. Cet exemple suppose un Form avec un contrôle Button unique qui a un index de tabulation de 0.
' Send a key to the button when the user double-clicks anywhere ' on the form. Private Sub Form1_DoubleClick(ByVal sender As Object, _ ByVal e As EventArgs) Handles Me.DoubleClick ' Send the enter key to the button, which raises the click ' event for the button. This works because the tab stop of ' the button is 0. SendKeys.Send("{ENTER}") End Sub
// Send a key to the button when the user double-clicks anywhere // on the form. private void Form1_DoubleClick(object sender, EventArgs e) { // Send the enter key to the button, which raises the click // event for the button. This works because the tab stop of // the button is 0. SendKeys.Send("{ENTER}"); }
// Send a key to the button when the user double-clicks anywhere // on the form. private: void Form1_DoubleClick(Object^ sender, EventArgs^ e) { // Send the enter key to the button, which triggers the click // event for the button. This works because the tab stop of // the button is 0. SendKeys::Send("{ENTER}"); }
Pour envoyer une séquence de touches à une application différente
Activez la fenêtre d'application qui recevra les séquences de touches, puis appelez la méthode Send ou SendWait. Parce qu'il n'y a aucune méthode managée pour activer une autre application, vous devez utiliser les méthodes Windows natives pour forcer le focus sur d'autres applications. L'exemple de code suivant utilise un appel de code non managé pour solliciter les méthodes FindWindow et SetForegroundWindow afin d'activer la fenêtre de l'application Calculatrice, puis appelle SendWait pour émettre une série de calculs vers l'application Calculatrice.
Notes
Les paramètres corrects de l'appel FindWindow recherchant l'application Calculatrice varient en fonction de votre version de Windows. Le code suivant recherche l'application Calculatrice dans Windows 7. Dans Windows Vista, modifiez le premier paramètre en « SciCalc ». Vous pouvez utiliser l'outil Spy++, fourni avec Visual Studio, afin de déterminer les paramètres appropriés.
' Get a handle to an application window. Declare Auto Function FindWindow Lib "USER32.DLL" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As IntPtr ' Activate an application window. Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _ (ByVal hWnd As IntPtr) As Boolean ' Send a series of key presses to the Calculator application. Private Sub button1_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles button1.Click ' Get a handle to the Calculator application. The window class ' and window name were obtained using the Spy++ tool. Dim calculatorHandle As IntPtr = FindWindow("CalcFrame", "Calculator") ' Verify that Calculator is a running process. If calculatorHandle = IntPtr.Zero Then MsgBox("Calculator is not running.") Return End If ' Make Calculator the foreground application and send it ' a set of calculations. SetForegroundWindow(calculatorHandle) SendKeys.SendWait("111") SendKeys.SendWait("*") SendKeys.SendWait("11") SendKeys.SendWait("=") End Sub
// Get a handle to an application window. [DllImport("USER32.DLL", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Activate an application window. [DllImport("USER32.DLL")] public static extern bool SetForegroundWindow(IntPtr hWnd); // Send a series of key presses to the Calculator application. private void button1_Click(object sender, EventArgs e) { // Get a handle to the Calculator application. The window class // and window name were obtained using the Spy++ tool. IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator"); // Verify that Calculator is a running process. if (calculatorHandle == IntPtr.Zero) { MessageBox.Show("Calculator is not running."); return; } // Make Calculator the foreground application and send it // a set of calculations. SetForegroundWindow(calculatorHandle); SendKeys.SendWait("111"); SendKeys.SendWait("*"); SendKeys.SendWait("11"); SendKeys.SendWait("="); }
// Get a handle to an application window. public: [DllImport("USER32.DLL", CharSet = CharSet::Unicode)] static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName); public: // Activate an application window. [DllImport("USER32.DLL")] static bool SetForegroundWindow(IntPtr hWnd); // Send a series of key presses to the Calculator application. private: void button1_Click(Object^ sender, EventArgs^ e) { // Get a handle to the Calculator application. The window class // and window name were obtained using the Spy++ tool. IntPtr calculatorHandle = FindWindow("CalcFrame", "Calculator"); // Verify that Calculator is a running process. if (calculatorHandle == IntPtr::Zero) { MessageBox::Show("Calculator is not running."); return; } // Make Calculator the foreground application and send it // a set of calculations. SetForegroundWindow(calculatorHandle); SendKeys::SendWait("111"); SendKeys::SendWait("*"); SendKeys::SendWait("11"); SendKeys::SendWait("="); }
Exemple
L'exemple de code suivant constitue l'application complète pour les exemples de code précédents.
Imports System
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Windows.Forms
Namespace SimulateKeyPress
Class Form1
Inherits Form
Private WithEvents button1 As New Button()
<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
Public Sub New()
button1.Location = New Point(10, 10)
button1.TabIndex = 0
button1.Text = "Click to automate Calculator"
button1.AutoSize = True
Me.Controls.Add(button1)
End Sub
' Get a handle to an application window.
Declare Auto Function FindWindow Lib "USER32.DLL" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
' Activate an application window.
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
' Send a series of key presses to the Calculator application.
Private Sub button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles button1.Click
' Get a handle to the Calculator application. The window class
' and window name were obtained using the Spy++ tool.
Dim calculatorHandle As IntPtr = FindWindow("CalcFrame", "Calculator")
' Verify that Calculator is a running process.
If calculatorHandle = IntPtr.Zero Then
MsgBox("Calculator is not running.")
Return
End If
' Make Calculator the foreground application and send it
' a set of calculations.
SetForegroundWindow(calculatorHandle)
SendKeys.SendWait("111")
SendKeys.SendWait("*")
SendKeys.SendWait("11")
SendKeys.SendWait("=")
End Sub
' Send a key to the button when the user double-clicks anywhere
' on the form.
Private Sub Form1_DoubleClick(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.DoubleClick
' Send the enter key to the button, which raises the click
' event for the button. This works because the tab stop of
' the button is 0.
SendKeys.Send("{ENTER}")
End Sub
End Class
End Namespace
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
namespace SimulateKeyPress
{
class Form1 : Form
{
private Button button1 = new Button();
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
button1.Location = new Point(10, 10);
button1.TabIndex = 0;
button1.Text = "Click to automate Calculator";
button1.AutoSize = true;
button1.Click += new EventHandler(button1_Click);
this.DoubleClick += new EventHandler(Form1_DoubleClick);
this.Controls.Add(button1);
}
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}
// Send a key to the button when the user double-clicks anywhere
// on the form.
private void Form1_DoubleClick(object sender, EventArgs e)
{
// Send the enter key to the button, which raises the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys.Send("{ENTER}");
}
}
}
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing;
using namespace System::Windows::Forms;
namespace SimulateKeyPress
{
public ref class Form1 : public Form
{
public:
Form1()
{
Button^ button1 = gcnew Button();
button1->Location = Point(10, 10);
button1->TabIndex = 0;
button1->Text = "Click to automate Calculator";
button1->AutoSize = true;
button1->Click += gcnew EventHandler(this, &Form1::button1_Click);
this->DoubleClick += gcnew EventHandler(this,
&Form1::Form1_DoubleClick);
this->Controls->Add(button1);
}
// Get a handle to an application window.
public:
[DllImport("USER32.DLL", CharSet = CharSet::Unicode)]
static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName);
public:
// Activate an application window.
[DllImport("USER32.DLL")]
static bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private:
void button1_Click(Object^ sender, EventArgs^ e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame", "Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr::Zero)
{
MessageBox::Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys::SendWait("111");
SendKeys::SendWait("*");
SendKeys::SendWait("11");
SendKeys::SendWait("=");
}
// Send a key to the button when the user double-clicks anywhere
// on the form.
private:
void Form1_DoubleClick(Object^ sender, EventArgs^ e)
{
// Send the enter key to the button, which triggers the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys::Send("{ENTER}");
}
};
}
[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew SimulateKeyPress::Form1());
}
Compilation du code
Cet exemple nécessite les éléments suivants :
- Références aux assemblys System, System.Drawing et System.Windows.Forms.
Pour plus d'informations sur la génération de cet exemple à partir de la ligne de commande pour Visual Basic ou Visual C#, consultez Génération à partir de la ligne de commande (Visual Basic) ou Génération à partir de la ligne de commande avec csc.exe. Vous pouvez aussi générer cet exemple dans Visual Studio en collant le code dans un nouveau projet. Pour plus d'informations, consultez Comment : compiler et exécuter un exemple complet de code Windows Forms à l'aide de Visual Studio et Comment : compiler et exécuter un exemple complet de code Windows Forms à l'aide de Visual Studio et Comment : compiler et exécuter un exemple complet de code Windows Forms à l'aide de Visual Studio et Comment : compiler et exécuter un exemple complet de code Windows Forms à l'aide de Visual Studio et Comment : compiler et exécuter un exemple complet de code Windows Forms à l'aide de Visual Studio.