Fensterhandle ermitteln

Bild

Betrifft: Fensterhandle ermitteln
von: Barbara
Geschrieben am: 16.09.2015 16:27:06

Hallo
zum Thema
"Alle Fensterhandle und Tasks ermitteln"
habe ich hier in einer früheren Anfrage den Hinweis auf folgende Seite bekommen:
http://www.activevb.de/tipps/vb6tipps/tipp0123.html
Nur leider kann ich damit nichts anfangen, weil es nicht funktioniert.
Hätte gerne erklärt, wie ich diesen Code nutzen kann. In den VBA-Editor einfügen und ein Sub abarbeiten geht nicht, weil da eine Menge Fehlermeldungen kommen.
Habe auch probiert, kritische Zeilen auszukommentieren, damit wenigstens die schrittweise Abfolge gestartet werden kann.
Dann kommt zB bei Me.hWnd eine Fehlermeldung. Ich glaube, da fehlt es an grundsätzlichem Wissen.
Dabei will ich doch nur an ein bestimmtes beliebiges Fenster mit Sendkeys was schicken.
Oder gibt es eine andre Lösung?
Bitte um Hilfe oder Anleitung.
LG,
Barbara

Bild

Betrifft: AW: Fensterhandle ermitteln
von: Nepumuk
Geschrieben am: 16.09.2015 16:40:29
Hallo,
hier hast du fast das selbe mit Ausgabe in einer Exceltabelle:

Option Explicit

Private Declare Function EnumWindows Lib "user32.dll" ( _
    ByVal lpEnumFunc As Long, _
    ByVal lParam As Long) As Boolean
Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" ( _
    ByVal hwnd As Long, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" ( _
    ByVal hwnd As Long) As Long
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" ( _
    ByVal hwnd As Long, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" ( _
    ByVal hwnd As Long, _
    ByVal nIndex As Long) As Long

Private Const GWL_STYLE = (-16)
Private Const WS_VISIBLE = &H10000000
Private Const WS_BORDER = &H800000

Private llngRow As Long

Public Sub Start()
    llngRow = 1
    Columns("A:C").ClearContents
    With Range("A1:C1")
        .Value = Array("Hwnd", "Klasse", "Caption")
        .Font.Bold = True
    End With
    Call EnumWindows(AddressOf WindowCallBack, ByVal 0&)
    Columns("A:C").AutoFit
    Tabelle1.Sort.SortFields.Clear
    Tabelle1.Sort.SortFields.Add Key:=Columns(2)
    With Tabelle1.Sort
        .SetRange Columns("A:C")
        .Header = xlYes
        .MatchCase = False
        .Apply
    End With
End Sub

Private Function WindowCallBack(ByVal lngHwnd As Long, ByVal lngParam As Long) As Long
    Dim strCaption As String, strClassName As String
    Dim lngReturn As Long, lngStyle As Long
    lngStyle = GetWindowLong(lngHwnd, GWL_STYLE)
    If Cbool(lngStyle And (WS_VISIBLE Or WS_BORDER)) Then
        strClassName = Space$(256)
        lngReturn = GetClassName(lngHwnd, strClassName, 256)
        lngReturn = GetWindowTextLength(lngHwnd)
        strCaption = Space$(lngReturn)
        Call GetWindowText(lngHwnd, strCaption, lngReturn + 1)
        llngRow = llngRow + 1
        Cells(llngRow, 1).Resize(1, 3) = Array(lngHwnd, Trim$(strClassName), strCaption)
    End If
    WindowCallBack = 1
End Function

Gruß
Nepumuk

Bild

Betrifft: OT - API?
von: Michael
Geschrieben am: 16.09.2015 16:51:18
Hallo zusammen,
ich hätte gerne gewußt, wozu bei API-Aufrufen manchmal ein Alias mit angegeben wird (eigentlich immer mit angehängtem "A"), manchmal auch nicht, und warum die jeweilige Fkt. dann aber *nie* mit dem Alias angesprochen wird?
Schöne Grüße,
Michael

Bild

Betrifft: AW: OT - API?
von: Nepumuk
Geschrieben am: 16.09.2015 17:09:21
Hallo,
der Alias-Name ist der eigentliche Name der Funktion in der DLL. Die mit dem Endbuchstaben A verarbeiten Ansi-Code also die ASCII-Zeichen. Es gibt dann die selbe Funktion noch mit einem W am Ende für Wide also Unicode-Zeichen.
Auf diese Weise kannst du den Funktionen eigene Namen geben, der Bezug zur DLL erfolgt über den Alias-Namen. Ich hab z.B. die selbe Funktion mit unterschiedlichen Parameterdeklarationen im Einsatz.
Obiger Code ist schon ziemlich alt, da ich seit längerem die Aliase weg lassen und die Funktion so deklariere:

Private Declare Function GetWindowLongA Lib "user32.dll" ( _
    ByVal hwnd As Long, _
    ByVal nIndex As Long) As Long

Und nachdem ich sowieso nur noch in Windows 64Bit schreibe so:
Private Declare PtrSafe Function GetWindowLongA Lib "user32.dll" ( _
    ByVal hwnd As LongPtr, _
    ByVal nIndex As Long) As LongPtr

Gruß
Nepumuk

Bild

Betrifft: AW: OT - API? Aha...
von: Michael
Geschrieben am: 16.09.2015 17:31:15
Hi Nepumuk,
vielen Dank für Deine Hinweise.
Ich habe zwischenzeitlich eine Runde recherchiert, wie man überhaupt an die Funktionen kommt, die irgendwelche DLLs zur Verfügung stellen. Viele schlagen nirsofts dll viewer vor, wenn man nicht ne "große" Programmiersprache einsetzen will, dort lese ich aber wiederum, daß es rund 50000 Methoden/Eigenschaften geben dürfte, wenn man sich denn alle anzeigen ließe.
Hier setzt eine gewisse Verwirrung ein: das eine sind DLLs, die man explizit als solche anspricht, das andere Objekte, die man einfach mal so benutzt, wie das Dictionary. Letzteres läßt sich ja problemlos recherchieren, aber gibt es einen allgemeinen Weg, sich Methoden/Eigenschaften eines externen Objekts anzeigen zu lassen?
Kennst Du einen "handlichen" Weg, sich in so Sachen zu vertiefen?
Gruß,
Michael

Bild

Betrifft: AW: OT - API? Aha...
von: Nepumuk
Geschrieben am: 16.09.2015 17:37:41
Hallo,
Kennst Du einen "handlichen" Weg, sich in so Sachen zu vertiefen?
Klar, knapp 30 Jahre Erfahrung mit API.
Es gibt ein wirklich gutes Buch von Dan Applemann: Visual Basic Programmer's Guide to the Win32 API
Ist allerdings auf Englisch. Das kannst du bei AMAZON bestellen.
Gruß
Nepumuk

Bild

Betrifft: Achso
von: Nepumuk
Geschrieben am: 16.09.2015 17:49:10
Hallo,
der Unterschied zwischen den DLL's wie scrrun.dll und kernell32.dll.
In der einen sind registrierte Klassen wie das Dictionary implementiert, welches du also über die Registry ansprichst. In der anderen sind Sub's und Functions implementiert welches du über die Declare-Anweisung importierst.
Gruß
Nepumuk

Bild

Betrifft: AW: Achso
von: Michael
Geschrieben am: 16.09.2015 22:17:38
Hi Nepomuk,
jetzt bin ich beim Lesen Deiner Antworten durcheinandergekommen.
Ich sehe schon, um das wirklich zu begreifen (und nicht nur das eine oder andere Häppchen zu verwenden), muß ich etwas weiter ausholen und 30 Jahre Zeit investieren.
Aber deshalb habe ich extra die Maschine nochmal hochgefahren. Weil ich das "knapp" überlesen hatte. Mann, vor (exakt) 30 Jahren gab's grad mal DOS 2.11 (wenn überhaupt), und "grafische Betriebssystemzusätze" für 808x waren auch noch nicht in Sicht.
Im Grunde hat man aber damals schon Funktionen des jeweiligen OS (oder BIOS) benutzt - ist ja prinzipiell nix anderes als API.
Danke und tschüß,
Michael

Bild

Betrifft: ... von denen ich fast alle verpennt habe,
von: Michael
Geschrieben am: 16.09.2015 17:49:48
Mann, Mann.
Ich habe, als die Zeit da war, versäumt, mich von DOS auf Win zu stürzen, derweil ich damals beruflich ganz andere Sachen um die Ohren hatte...
Excel taugt mir schon, aber heute frage ich mich wiederum, ob nicht die Zeit wäre, sich mit Schmarr-Phones und deren Programmierung auseinander zu setzen. Ach, sollen's die Jungen machen.
Herzlichen Dank für den Buchtip, die elffuffzich kann und werde ich noch investieren.
Schöne Grüße,
Michael

Bild

Betrifft: AW: Fensterhandle ermitteln
von: Barbara
Geschrieben am: 16.09.2015 19:18:16
Hallo Nepomuk,
danke für Deine Antwort. Habe Deinen Code eingefügt und wollte Public Sub Start() starten.
Ergebnis: Fehlermeldung:
"Fehler beim kompilieren
Unzulässige Verwendung des AdressOf-Operators"
Mach ich da was falsch?
LG,
Barbara

Bild

Betrifft: AW: Fensterhandle ermitteln
von: Nepumuk
Geschrieben am: 16.09.2015 19:29:57
Hallo,
hast du noch Excel97? Da war dieser Operator noch nicht implementiert.
Gruß
Nepumuk

Bild

Betrifft: AW: Fensterhandle ermitteln
von: Nepumuk
Geschrieben am: 16.09.2015 19:48:53
Hallo,
oder hast du Office2010 in der 64Bit-Version? Wenn ja, dann benutze folgenden Code:

Option Explicit

Private Declare PtrSafe Function EnumWindows Lib "user32.dll" ( _
    ByVal lpEnumFunc As LongPtr, _
    ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetWindowTextA Lib "user32.dll" ( _
    ByVal hwnd As LongPtr, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long
Private Declare PtrSafe Function GetWindowTextLengthA Lib "user32.dll" ( _
    ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function GetClassNameA Lib "user32.dll" ( _
    ByVal hwnd As LongPtr, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Long) As Long
#If Win64 Then
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongPtrA" ( _
    ByVal hwnd As LongPtr, _
    ByVal nIndex As Long) As LongPtr
#Else
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" ( _
    ByVal hwnd As LongPtr, _
    ByVal nIndex As Long) As LongPtr
#End If

Private Const GWL_STYLE = (-16)
Private Const WS_VISIBLE = &H10000000
Private Const WS_BORDER = &H800000

Private llngRow As Long

Public Sub Start()
    llngRow = 1
    Columns("A:C").ClearContents
    With Range("A1:C1")
        .Value = Array("Hwnd", "Klasse", "Caption")
        .Font.Bold = True
    End With
    Call EnumWindows(AddressOf WindowCallBack, ByVal 0&)
    Columns("A:C").AutoFit
    Tabelle1.Sort.SortFields.Clear
    Tabelle1.Sort.SortFields.Add Key:=Columns(2)
    With Tabelle1.Sort
        .SetRange Columns("A:C")
        .Header = xlYes
        .MatchCase = False
        .Apply
    End With
End Sub

Private Function WindowCallBack(ByVal pvlngptrHwnd As LongPtr, ByVal lngptrParam As LongPtr) As Long
    Dim strCaption As String, strClassName As String
    Dim lngReturn As Long
    Dim lngptrStyle As LongPtr
    lngptrStyle = GetWindowLong(pvlngptrHwnd, GWL_STYLE)
    If Cbool(lngptrStyle And (WS_VISIBLE Or WS_BORDER)) Then
        strClassName = Space$(256)
        lngReturn = GetClassNameA(pvlngptrHwnd, strClassName, 256)
        strClassName = Left$(strClassName, lngReturn)
        lngReturn = GetWindowTextLengthA(pvlngptrHwnd)
        strCaption = Space$(lngReturn)
        Call GetWindowTextA(pvlngptrHwnd, strCaption, lngReturn + 1)
        llngRow = llngRow + 1
        Cells(llngRow, 1).Resize(1, 3) = Array(pvlngptrHwnd, strClassName, strCaption)
    End If
    WindowCallBack = 1
End Function

Gruß
Nepumuk

Bild

Betrifft: AW: Fensterhandle ermitteln
von: Barbara
Geschrieben am: 16.09.2015 20:00:01
Auch hier, selbe Fehlermeldung. Und dann ist
"AddressOf WindowCallBack" markiert.
Meine Version: Microsoft Excel 2010(14.0) SP2 MSO (32-bit)
Muss ich vielleicht was dazu laden?

Bild

Betrifft: Tester gesucht
von: Nepumuk
Geschrieben am: 16.09.2015 20:14:40
Hallo,
jetzt bin ich echt überfragt. Beide Codes laufen bei mir unter Excel 2013 32 Bit.
Kann das mal jemand anders mit Excel 2010 testen
Gruß
Nepumuk

Bild

Betrifft: Klappt 1A!
von: Sepp
Geschrieben am: 16.09.2015 20:29:50
Hallo Max,
der Code läuft wie erwartet.
Office Professional Plus 2010, Win 7 32 Bit

Gruß Sepp


Bild

Betrifft: AW: Tester gesucht
von: Mullit
Geschrieben am: 16.09.2015 20:31:45
Hallo Nepumuk,
ich vermute den Klassiker, sie hat den Code nicht in ein Standardmodul, sondern in ein Tabellenblattmodul oder Arbeitsmappenmodul gepackt, läuft sonst wie geschnitten Brot...
Gruß, Mullit

Bild

Betrifft: Danke an die Tester !!!
von: Nepumuk
Geschrieben am: 16.09.2015 20:36:00
Hallo Mullit,
Ohhhhhhhhhhhhh Mann !!!! Daran hab ich gar nicht gedacht. Vielen Dank !!!!!!!!!!
Also Barbara, der Code muss in ein Standardmodul. Menüleiste - Einfügen - Modul.
Gruß
Nepumuk

Bild

Betrifft: AW: Danke an die Tester !!!
von: Mullit
Geschrieben am: 16.09.2015 21:19:19
Hallo Nepumuk,
null Problemo, in den Fehler bin ich wohl schon zu oft reingekachelt....
Gruß, Mullit

Bild

Betrifft: AW: Danke an die Tester !!!
von: Barbara
Geschrieben am: 16.09.2015 22:48:47
Danke, jetzt geht's.
Mit meinem bescheidenen Horizont wäre ich nicht drauf gekommen.
Dennoch trete ich weiter auf der Stelle mit meine eigentlichen Problemchen:
Siehe auch angehängte Beispieldatei.
https://www.herber.de/bbs/user/100236.xlsm
Da ist in Modul1 ein Makro, das Folgendes macht:
Der Werte der Zellen A1 bis A5 werden im Sekundentakt in die Zwischenablage kopiert.
Diese muss ich genauso im Sekundentakt woanders so abladen (dzt. händisch):
Nachdem ich dieses Makro gestartet habe, gehe ich innerhalb einer Sekunde mit einem Mausklick in ein bereits offenes anderes Programm und mache Folgendes fünf Mal im Sekundentakt:
STRG+V (um den Inhalt dort einzufügen)
und dann drücke ich ohne eine andere Taste nur die rechte (!) STRG-Taste der Tastatur oder die Enter-Taste vom Num-Block. (Ob das mit Sendkeys geht?)
Das ist eine Eigenheit dieses anderen 20 Jahre alten Programms, um dort die Eingabe zu verarbeiten.
Diese händische Prozedur sollte ins bestehende Makro eingebaut werden, denn in Wirklichkeit sind es 50 solche Zyklen, die ich jetzt händisch abarbeite. Und dabei jedes Mal die Existenz dieses Zielfensters geprüft werden, damit nichts ins Leere geht.
Vielen Dank für Eure Bemühungen.
LG,
Barbara

Bild

Betrifft: Danke für Eure Hilfe.
von: Barbara
Geschrieben am: 16.09.2015 23:49:28
Jetzt geht alles Durcheinander.
BITTE MEINEN LETZTEN BEITRAG IGNORIEREN.
ICH MACHE DAZU EIN NEUES THEMA AUF.
Danke für Eure Hilfe.

Bild

Betrifft: x2000/Vista auch ok - bis auf Sortieren owT
von: Michael
Geschrieben am: 16.09.2015 22:43:10


 Bild

Beiträge aus den Excel-Beispielen zum Thema "Fensterhandle ermitteln"