Mausklick in Drittprogramm ohne es in den Vordergrund zu holen?

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Viercnt.

    Mausklick in Drittprogramm ohne es in den Vordergrund zu holen?

    Moin leute :)

    und zwar habe ich folgendes Problem: Ich habe ein Android Emulator auf dem PC (BlueStacks), darauf hab ich Whatsapp laufen, etc. pp. leider geht der Emulator alle 3 Minuten Inaktiv, sollte keine EIngabe etc erfolgen.
    Jetzt würde ich sehr gerne ein kleines Programm haben, was bsp. im Hintergrund ein Mausklick, oder sontige Tasteneingabe (Banane was, hauptsache irgendein "Wake up" signal) an ein, in dem fall, externes, bereits geöffnetes Programm sendet.

    Kann ich sowas realisieren? und wenn ja, wie?
    Any Suggestions? :)
    Danke!

    Grüße,
    Kevin
    Magie, der Typ wollte das selbe machen, wie du ;)

    Edit:
    Für die richtigen Signaturen, schau in PInvoke.net nach
    "Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." Albert Einstein
    Danke dir erstmal für deine Antwort, hellmaster! :)

    Das ist, im Endeffekt, genau das, was ich suche :)
    Leider sind meine C Sharp Kenntnisse irgendwo zwischen 0 und 1 :D
    Ich habe mich trotzdem mal daran versucht, hier mein Code:


    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Runtime.InteropServices;
    8. using System.Text;
    9. using System.Threading.Tasks;
    10. using System.Windows.Forms;
    11. namespace WindowsFormsApplication1
    12. {
    13. public class ClickOnPointTool
    14. {
    15. [DllImport("user32.dll")]
    16. static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);
    17. [DllImport("user32.dll")]
    18. internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
    19. #pragma warning disable 649
    20. internal struct INPUT
    21. {
    22. public UInt32 Type;
    23. public MOUSEKEYBDHARDWAREINPUT Data;
    24. }
    25. [StructLayout(LayoutKind.Explicit)]
    26. internal struct MOUSEKEYBDHARDWAREINPUT
    27. {
    28. [FieldOffset(0)]
    29. public MOUSEINPUT Mouse;
    30. }
    31. internal struct MOUSEINPUT
    32. {
    33. public Int32 X;
    34. public Int32 Y;
    35. public UInt32 MouseData;
    36. public UInt32 Flags;
    37. public UInt32 Time;
    38. public IntPtr ExtraInfo;
    39. }
    40. #pragma warning restore 649
    41. public static void ClickOnPoint(IntPtr wndHandle, Point clientPoint)
    42. {
    43. var oldPos = Cursor.Position;
    44. /// get screen coordinates
    45. ClientToScreen(wndHandle, ref clientPoint);
    46. /// set cursor on coords, and press mouse
    47. Cursor.Position = new Point(clientPoint.X, clientPoint.Y);
    48. var inputMouseDown = new INPUT();
    49. inputMouseDown.Type = 0; /// input type mouse
    50. inputMouseDown.Data.Mouse.Flags = 0x0002; /// left button down
    51. var inputMouseUp = new INPUT();
    52. inputMouseUp.Type = 0; /// input type mouse
    53. inputMouseUp.Data.Mouse.Flags = 0x0004; /// left button up
    54. var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
    55. SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
    56. /// return mouse
    57. Cursor.Position = oldPos;
    58. }
    59. }
    60. public partial class Form1 : Form
    61. {
    62. public Form1()
    63. {
    64. InitializeComponent();
    65. }
    66. private void btn_go_Click(object sender, EventArgs e)
    67. {
    68. }
    69. }
    70. }


    gibt nachdem ich

    C#-Quellcode

    1. using System.Runtime.InteropServices;
    eingefügt hab und die ddl injecte Fehlermeldungen mehr.
    Aber genausowenig funktioniert natürlich auch.


    Jetzt ist aber meine Frage, wie genau Aktiviere ich diese "voids" denn, per Mausclick?
    Bsp. ein Go Button, den ich da eingefügt hatte, soll doch, meines Wissens nach die

    C#-Quellcode

    1. public static void ClickOnPoint(IntPtr wndHandle, Point clientPoint)
    abfahren und ihm ein wndHandle und einen clientPoint übergeben? right?

    Zweite Frage: Woher bekomme ich denn das wndHandle für den BlueStacks App Player und den clientPoint?
    Danke!

    Grüße,
    Kevin
    *hui* Ein ganz schön langer Text
    Wenn du C# nicht kannst, verwende VB.net ;)

    Mithilfe von FindWindow kannst du anhand vom dem Fenster-Klassennamen und Titel das Handle herauskriegen.
    Den Fenster-Klassennamen kannst du z.B. mithilfe vom AutoIt Info Tool finden oder soweit ich weiß auch mit (UI-)Spy++.

    Du kannst auch mit der Process Klasse arbeiten und versuchen von dem Bluestack Prozess das MainWindowHandle nehmen.

    Der clientPoint ist ein einfacher Point.
    Also einfach: Dim clientPoint As Point = new Point(x,y)

    Das ganze übergibt du dann an die ClickOnPoint-Methode.
    Die übrigens genauso, wie in VB.Net aufrufst, also ClickOnPoint(handle,point)
    "Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." Albert Einstein
    @Viercnt Vielleicht probierst Du mal dies, Du startest Dein Programm und sendest ihm permanent Click-Events in einem Takt:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. <DllImport("user32.dll")>
    4. Public Shared Function SendMessage(hwnd As IntPtr, uMsg As Integer, wParam As IntPtr, lParam As Integer) As Integer
    5. End Function
    6. Public Const BM_CLICK = &HF5
    7. Private pr As Process
    8. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    9. pr = Process.Start("Notepad.exe") ' hier Dein Programm mit Pfad reinschreiben
    10. pr.WaitForInputIdle(1000)
    11. Timer1.Enabled = True ' setze ein vernünftiges Interval
    12. End Sub
    13. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    14. SendMessage(pr.MainWindowHandle, BM_CLICK, IntPtr.Zero, 0)
    15. End Sub
    16. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke Rod, er startet da schonmal das Programm, Hellmasters Ansatz war leider etwas zu kompliziert .(

    Leider, nachdem es gestartet wird, kommt ein "Ein Ausnahmefehler des Typs "System.InvalidOperationException" ist in System.dll aufgetreten." beim Timer1_Tick Sub.


    Muss ich wirklich das Programm darüber starten lassen? Oder machst du das hier unr, um den MainWindowHandle relativ einfach zu bekommen?
    Danke!

    Grüße,
    Kevin

    Viercnt schrieb:

    beim Timer1_Tick Sub
    Kannst Du bitte mal die betreffende Code-Zeile posten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wenn das bei dir klappt ists ja gut, aber BM -> ButtonMessage ist für Buttons. Sollte in deinem Fall eigentlich komplett egal sein. Wenn du aber einen "echten" Klick senden möchtest, musst du über andere Messages gehen oder über SendInput.