Procedura: simulare eventi di mouse e tastiera nel codice
Windows Form include varie opzioni per la simulazione a livello di codice di input del mouse e della tastiera. Nel presente argomento viene illustrata una panoramica di tali opzioni.
Simulazione dell'input del mouse
Il modo migliore per simulare eventi di mouse consiste nel chiamare il metodo OnEventName che genera l'evento di mouse da simulare. L'opzione è generalmente possibile solo all'interno di controlli e form personalizzati, in quanto i metodi che generano gli eventi sono protetti e non sono accessibili dall'esterno del controllo o del form. Ad esempio, la procedura seguente illustra come simulare il clic con il pulsante destro del mouse nel codice.
Per fare clic con il pulsante destro del mouse a livello di codice
Creare una classe MouseEventArgs la cui proprietà Button sia impostata sul valore MouseButtons.Right.
Chiamare il metodo OnMouseClick con l'oggetto MouseEventArgs come argomento.
Per ulteriori informazioni sui controlli personalizzati, vedere Sviluppo di controlli Windows Form in fase di progettazione.
Esistono altri modi per simulare l'input del mouse. Ad esempio, è possibile impostare a livello di codice una proprietà dei controlli che descriva uno stato normalmente impostato tramite l'input del mouse, come la proprietà Checked del controllo CheckBox, oppure chiamare direttamente il delegato connesso all'evento da simulare.
Simulazione dell'input della tastiera
Sebbene sia possibile simulare l'input della tastiera utilizzando gli approcci descritti sopra per l'input del mouse, in Windows Form è inoltre disponibile la classe SendKeys per l'invio di sequenze di tasti all'applicazione attiva.
Attenzione |
---|
Se l'applicazione è pensata per l'utilizzo internazionale con vari tipi di tastiere, l'utilizzo di SendKeys.Send potrebbe portare a risultati imprevisti. È quindi consigliabile evitarlo. |
Nota
La classe SendKeys è stata aggiornata in .NET Framework 3.0 per consentirne l'utilizzo nelle applicazioni eseguite in Windows Vista. La sicurezza migliorata di Windows Vista (tramite la funzionalità di controllo dell'account utente) impedisce il funzionamento previsto dell'implementazione precedente.
La classe SendKeys è vulnerabile a problemi di temporizzazione che alcuni sviluppatori hanno dovuto risolvere. L'implementazione aggiornata è ancora suscettibile a tali problemi, ma è leggermente più veloce e potrebbe richiedere modifiche alle soluzioni alternative. La classe SendKeys tenta di utilizzare dapprima l'implementazione precedente e, in caso di errori, utilizza la nuova implementazione. Di conseguenza, la classe SendKeys potrebbe avere un comportamento diverso in sistemi operativi diversi. Inoltre, quando la classe SendKeys utilizza la nuova implementazione, il metodo SendWait non attenderà l'elaborazione dei messaggi quando vengono inviati a un altro processo.
Se l'applicazione si basa su un comportamento coerente indipendentemente dal sistema operativo, è possibile forzare la classe SendKeys a utilizzare la nuova implementazione aggiungendo la seguente impostazione di applicazione al file app.config.
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Per forzare la classe SendKeys a utilizzare l'implementazione precedente, utilizzare il valore "JournalHook".
Per inviare una sequenza di tasti alla stessa applicazione
Chiamare il metodo Send o SendWait della classe SendKeys. Le sequenze di tasti specificate saranno ricevute dal controllo attivo dell'applicazione. Nell'esempio di codice seguente viene utilizzato Send per simulare la pressione del tasto INVIO quando l'utente fa doppio clic nell'area del form. Nell'esempio si suppone la presenza di una classe Form con un singolo controllo Button con indice di tabulazione 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}"); }
Per inviare una sequenza di tasti a una diversa applicazione
Attivare la finestra dell'applicazione che riceverà le sequenze di tasti, quindi chiamare il metodo Send o SendWait. Poiché non esiste alcun metodo gestito per l'attivazione di un'altra applicazione, è necessario utilizzare i metodi di Windows nativi per imporre lo stato attivo su altre applicazioni. Nell'esempio di codice seguente viene utilizzato platform invoke per chiamare i metodi FindWindow e SetForegroundWindow e attivare la finestra dell'applicazione Calcolatrice e quindi chiamare SendWait per generare una serie di calcoli nell'applicazione.
Nota
I parametri corretti della chiamata FindWindow che individua l'applicazione Calcolatrice variano in base alla versione di Windows. Nel codice riportato di seguito viene ricercata l'applicazione Calcolatrice in Windows 7. In Windows Vista, modificare il primo parametro in "SciCalc". È possibile utilizzare lo strumento Spy++, incluso con Visual Studio, per determinare i parametri corretti.
' 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("="); }
Esempio
L'esempio di codice seguente rappresenta l'applicazione completa per gli esempi di codice precedenti.
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());
}
Compilazione del codice
L'esempio presenta i seguenti requisiti:
- Riferimenti agli assembly System, System.Drawing e System.Windows.Forms.
Per informazioni sulla compilazione di questo esempio dalla riga di comando per Visual Basic o Visual C#, vedere Building from the Command Line (Visual Basic) o Compilazione dalla riga di comando con csc.exe. È anche possibile compilare questo esempio in Visual Studio incollando il codice in un nuovo progetto. Per ulteriori informazioni, vedere Procedura: compilare ed eseguire un esempio di codice Windows Form completo tramite Visual Studio e Procedura: compilare ed eseguire un esempio di codice Windows Form completo tramite Visual Studio e Procedura: compilare ed eseguire un esempio di codice Windows Form completo tramite Visual Studio e Procedura: compilare ed eseguire un esempio di codice Windows Form completo tramite Visual Studio e Procedura: compilare ed eseguire un esempio di codice Windows Form completo tramite Visual Studio.