Wie führe ich einen Maus Klick in C# durch?

2 Antworten

Eigentlich ist die Vorgehensweise von @regex9 (via SendInput() ) der der legitime Weg.

Neben der von @regex9 gibt es auch noch die alte mouse_event-Funktion . Die wird auch noch weiter funktioneren. (und man spart sich die herumrödelei mit den Strukturen)

Um das einen System-API-aufruf kommst Du auch mit dieser Funktion nicht herum.

[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

zum einbinden von API-Funktionen:

Der nächste Knackpunkt wäre sowohl bei SendInput als auch mouse_event die zu übergebenden !!Absoluten!! Mousekoordinaten (dwflag 0x8000). Diese haben nichts mit einer direkten Kordinatenangabe zu tun , sondern müss(t)en erst auf eine Wert von 0 bis 65535 bezogen auf den Virtuellen Desktop (der kann auch negative Positionen aufweisen!) normalisiert werden.

(Die nativen API-Funktionen wissen nichts von der modernen Displayverwaltung oder MultiMonitorsystemen)

Da die nötigen Daten zum virtuellen Desktop sich nativ auch nur umständlich ermitteln lassen, würde die Sache richtig fies. Deshalb greifen wir frech auf die Cursorpositionerung von Windows.Forms zurück . Diese weiß wie groß dein Desktop ist und normalisiert automatisch angegebene die Position.

Cursor.Position = new Point(30, 30);

Nicht schön, aber in der not frisst der Teufel Fliegen.

Jetzt lösen wir einfach das gewünschte MouseEreignis aus.

Im folgenden mache ich mir nicht die Mühe banale Dinge wie args[] zu verwenden.

Ich setze einfach den Cursor auf die DesktopPosition 30 , 30 und wende einen Rechtsklick auf diese Position an.

Das genügt im die Kernfunktionalität zu erläutern. Was Du darüber hinaus noch brauchst wäre ein anderes Thema.

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;


class Prog{
    //https://learn.microsoft.com/de-de/windows/win32/api/winuser/nf-winuser-mouse_event
    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);


    //die  gängigen MouseTastenaktionen (es gibt  noch mehr)
    private const int MOUSEEVENTF_LEFTDOWN  = 0x02;
    private const int MOUSEEVENTF_LEFTUP    = 0x04;
    private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
    private const int MOUSEEVENTF_RIGHTUP   = 0x10;
    
    //ein Click  ist  immer  eine Ereignis aus  Up und Down  also  OR-verknüpfen  wir jeweils  die beiden Ereignise
    private const int LeftClick  = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;   // 0x06 = dezimal 6
    private const int RightClick = MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP; // 0x18 = dezimal 24
    
    
    //  Butter bei  die Fische
    public static void Main(string[] args){
        //wir   positionieren  die  Mouse  einfach bequem per : https://learn.microsoft.com/de-de/dotnet/api/system.windows.forms.cursor.position?view=windowsdesktop-8.0
        //MouseCursor nach Position 30,30
        Cursor.Position = new Point(30, 30);
        //jetzt zur Demo mal ein RechtsClick  auf  Position 0,0 , relativ zur zuvor gesetzten Corsorposition
        mouse_event(RightClick, 0, 0, 0, 0);


         //nur  mal was in  der Console anzeigen...
        Console.WriteLine("Mouse X = " +Cursor.Position.X);
        Console.WriteLine("Mouse Y = " +Cursor.Position.Y);
        Console.ReadKey();
    }
}

..darauf basierend kann man die Sache auch noch "eindampfen":

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;


class Prog{
    [DllImport("user32.dll",CharSet=CharSet.Auto)]
    public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

    public static void Main(string[] args){
        Cursor.Position = new Point(30, 30);
        mouse_event(24, 0, 0, 0, 0);
    }
}

so ganz neu ist die Thematik nicht.

einfach eine Batch (.cmd). nur mal als Anregung ... bezüglich der Verwendung von Argumenten

Das Projekt ist dafür gedacht, dass ich die Sprache lerne, (...)

Das ist eine denkbar schlechte Wahl, da du hierfür (für Windows OS) die Win32-API benötigst.

Ich kann dir für deine Frage folgend zwar einen Lösungsansatz geben, würde dir aber grundsätzlich dazu raten, mit einfacheren Projekten/Übungen zu starten.

Sofern du dich bereits mit Variablen, Operatoren, Arrays und Kontrollstrukturen beschäftigt hast, könntest du beispielsweise Spiele für die Konsole bauen (Black Jack, Hangman, Mau-Mau, Snake, Tic-Tac-Toe).

Meine Frage war wie ich einen Maus Klick durch führe.

Schau dir die SendInput-Methode an.

In deinem Projekt benötigst du den entsprechenden DLL-Import:

[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs,  [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);

Sowie die entsprechenden Typen (in diesem Fall INPUT mitsamt all seiner Typabhängigkeiten). Die C-Typdefinitionen müssen hierbei in C#-Typdefinitionen übersetzt werden.

Ich gebe folgend nur ein paar Typen vor. Für Vollständigkeit und Erklärungen, schau in die Dokumentation.

[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
  internal uint type;
  internal InputUnion info;
}

[StructLayout(LayoutKind.Explicit)]
internal struct InputUnion
{
  [FieldOffset(0)]
  internal MOUSEINPUT mi;

  [FieldOffset(0)]
  internal KEYBDINPUT ki;

  [FieldOffset(0)]
  internal HARDWAREINPUT hi;
}

[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
  internal int dx;
  internal int dy;
  internal int mouseData;
  internal uint dwFlags;
  internal uint time;
  internal UIntPtr dwExtraInfo;
}

/* etc. ... */

Anschließend kannst du dir die entsprechenden Argumente für einen Aufruf zusammenbauen.

MOUSEINPUT mouseInput = new MOUSEINPUT
{
  dwExtraInfo = UIntPtr.Zero,
  dwFlags = 0x8000 | 0x0002,
  dx = // absolute x position ...
  dy = // absolute y position ...
  time = 0
};
INPUT[] input = new INPUT[]
{
  new INPUT
  {
    info = mouseInput,
    type = 0
  }
};
        
SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
Erzesel  13.04.2024, 20:48

Die Sache mit den Absoluten Koordinaten (dwFlags = 0x8000) ist noch wesentlich komplexer die linke obere Ecke des Desktops ist für die Mouse immer 0,0 auch wenn ein MultimonitorDesktop diese Position als zB. -1980,50 definiert. ...und rechts unten ist für die Mouse immer absolut 65535,65535.

Die desktopkoordinaten müssen als auf Werte zwischen 0,0 und 65535,65535 normalisiert werden.

Echter Sackstand, wenn man erstmal ermitteln muss wie groß der Desktop ist.

...Das gilt sowohl für SendInput- als auch die alte mouse_event -Funktion.

Auch wenn in der Doku steht das Letztere ersetzt wurde, so wirds auch weiter funktionieren.

Mal Hand aufs Herz wer, wer es nötig hat Mousereignisse zu triggern um etwas zu bewirken, der frisst auch kleine Kinder .

Wenn man's denoch tun will , den Cursor einfach plump via Windows.Forms.Cursor.Position platzieren , denn Forms rechnet die Koordinaten automatisch um.

0