Jak klikać myszką na pozycję w innej aplikacji działającej w tle

0

Witam,
Napisałem program który klika mi na pewne pozycje na ekranie.
Chciałbym jednak móc korzystać z komputera kiedy ten program będzie działać.

Potrzebuje więc żeby program nie "przejmował kontrolę" nad moją myszką , a wysyłał te kliknięcia do konkretnej aplikacji - nie ingerując w pracę mojej prawdziwej myszki.
Jak to zrealizować aby wysyłać kliknięcia do konkretnej aplikacji *.exe która działa np będąc zminimalizowaną ?

3

Do zminimalizowanej nie wyślesz, natomiast do przesuniętej za krawędź czasami się da.
https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keydown

0
_13th_Dragon napisał(a):

Do zminimalizowanej nie wyślesz, natomiast do przesuniętej za krawędź czasami się da.
https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keydown

nie wiem za bardzo jak tego użyć ;/
co robię źle ? np. gdybym chciał kliknąć myszką na pozycje 1100, 200

Const MK_LBUTTON = &H1
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202


Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
             (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim destination As IntPtr = FindWindow(Nothing, "MojaAplikacja")
    Call SendMessage(destination, WM_LBUTTONDOWN, MK_LBUTTON, 0&)
    Call SendMessage(destination, WM_LBUTTONUP, MK_LBUTTON, 0&)
End Sub
1

A może uruchomisz w wirtualnej maszynie, tam może ta aplikacja być cały czas uruchomiona i sfocusowana i tam nikomu nie będzie przeszkadzało jak program będzie wciskał losowe klawisze.

0
Imports System.Threading

Public Class Form1
    Declare Function SendMessage Lib "user32.dll" _
Alias "SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long,
ByVal wParam As Long, ByVal lParam As Long) As Long


    Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
                 (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr

    Const MK_LBUTTON = &H1
    Const WM_LBUTTONDOWN = &H201
    Const WM_LBUTTONUP = &H202
    Const WM_MOUSEMOVE As Long = &H200
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        Dim destination As IntPtr = FindWindow(Nothing, "MojaAplikacja")
        Dim xcoord As Long
        Dim ycoord As Long
        Dim packed As Long

        xcoord = 550
        ycoord = 549
        packed = (ycoord * &H10000) + xcoord
        Call SendMessage(destination, WM_MOUSEMOVE, 0&, packed)
        Call SendMessage(destination, WM_LBUTTONDOWN, MK_LBUTTON, packed)
        Call SendMessage(destination, WM_LBUTTONUP, MK_LBUTTON, packed)
    End Sub

End Class

Co w tym kodzie jest nie tak? Nie mogę sobie z tym poradzić =/
@_13th_Dragon
@kAzek:

2

@Jacek Milewski Ostatnim parametrem SendMessage tego co klikasz (WM_LBUTTONDOWN, WM_LBUTTONUP) powinny być koordynaty pozycji myszki a co jest u Ciebie?

0

A próbowałeś to debugować?

Ogólnie aplikacje GUI mają architekturę Event driven.
Pętla loop, która sobie odbiera zdarzenia.

SendMessage i PostMessage wstrzykują z zewnątrz zdarzenia.

Jak chcesz takie coś zdebugować to musisz podpiąć się pod strukturę przechowującą lub funkcję przetwarzającą te eventy.

Akurat tak się składa, że microsoft ma dedykowany software spy++, którym możesz podsłuchiwać event loop w gui programach.

Teraz tak klikasz coś myszką i patrzysz jakie eventy się tam generują, potem samemu wysyłasz event i patrzysz czy wygląda tak samo jak ten co wysłałeś.
Tak mniej więcej możesz to zdebugować i rozwiązać samodzielnie ten problem.

Jako ciekawostkę podam, że w przeglądarce jak klikniemy myszka też jest generowany event, mouse, key i jak spróbujemy go podrobić jakimś document.getElementId().click() to event dostanie taki specjalną wartość o treści isTrusted = False, a w przypadku kliknięcia normalnie myszką to otrzyma isTrusted = True, mogą się zdarzyć zabezpiecznia w kodzie.
Można to obejść pachtując daną funkcję, po prostu ją kasując.

Może się też zdarzyć, że aplikacja twoja też cię jakoś wykryje.

0

za pomocą SendMessage ,KEYDOWN, WM_KEYUP, - chciałbym wysłać "[email protected]" do aplikacji...wszystkie znaki mogę wysłać ale mam problem z wysłaniem znaków "@" i "." w jaki sposób można to wykonać ?

0
Jacek Milewski napisał(a):

...wszystkie znaki mogę wysłać ale mam problem z wysłaniem znaków "@" i "." w jaki sposób można to wykonać ?

Jaki problem?
Podaj kod, przekazujący niepoprawnie "[email protected]" do notepada

0
             Dim oknoProgramu As IntPtr = FindWindow(Nothing, "Notepad")
            
               Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
                 (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
               Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
                 (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr

     Function StringToHex(ByVal text As String) As String
        Dim hex As String
        For i As Integer = 0 To text.Length - 1
            hex &= Asc(text.Substring(i, 1)).ToString("x").ToUpper
        Next
        Return hex
    End Function

wywołuje tak (robię .ToUpper - bo zauważyłem że tylko powiększone litery się przesyłają):

         For Each ch As Char In TextBox1.Text.ToUpper
                Dim VK_POJ_LIT As Integer = CInt("&H" + StringToHex(ch))
                SendMessage(oknoProgramu, WM_KEYDOWN, VK_POJ_LIT, 0)
                SendMessage(oknoProgramu, WM_KEYUP, VK_POJ_LIT, 0)
            Next

otrzymuje taki wynik: ADRESEMAILWPPL

(bez "@", bez".")

1

Jasne.
Masz wysyłać scancode a nie znak.
https://www.millisecond.com/support/docs/current/html/language/scancodes.htm
Przypadkiem dla dużych liter się zgadza.

0

no ale na tej liscie scancode nie ma znaku "@", jak więc go wysłać ? da się w ogóle ?

0

@: <Shitf+2>
x: <X>
X: <Shift+X>
Ą: <RAlt+Shift+A>

1 użytkowników online, w tym zalogowanych: 0, gości: 1