Hej, Testa med EnumWindows. Problemet med EnumWindows är att den listar alla fönster i systemet, inte bara de som tillhör min process. Kör du allting i samma tråd, dvs in-process komponenter (DLL)? Enbart in-process, så EnumThreadWindows verkar ju lovande, ska kolla på allapi.net om de har ett exempel på hur man använder denna metod. Tackar! Nu börjar det likna något. Med nedanstående kod så kan man gallra ut alla formulär som har klassnamnet "ThunderFormDC" (motsvarar VB-Formulär) och den verkar ge mig alla formulär som jag är intresserad av. Tack för tipset... Du behöver inte hämta ditt eget ThreadID med ett API om du inte vill. Min och min :-) Jag lånade den från www.allapi.net och modifierade den lite...Enumerera formulär
Har ett problem i en applikation där jag i vissa lägen behöver enumerera alla formulär och stänga (en del av) dessa. Problemet är att det är en stor applikation med kanske 100 komponenter (dll;ocx;exe) och det verkar som om Forms-collectionen bara visar formulär som existerar i den aktuella komponenten. De flesta formulär som jag är intresserad av öppnas av helt andra komponenter än den i vilken jag vill stänga formulären ifrån. Kan jag på något sätt enumerera alla formulär i den aktuella processen?Sv: Enumerera formulär
<code>
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
</code>
där din callback-funktion bör se ut nåt sånt här:
<code>
Public Function EnumWindowProc(ByVal hwnd As Long, _
ByVal lParam As Long) As Long
'Gör nåt kul här (du får handle till ett fönster)
End Function
</code>
anropa EnumWindows med adressen till din Callback-procedure.
<code>
EnumWindows(AddressOf EnumWindowProc, &H0)
</code>
Det finns även en EnumChildWindows du kan använda om du vill, fungerar på liknande sätt. Leta i MSDN efter den.
/EggetSv: Enumerera formulär
EnumChildWindows returnerar alla fönster som tillhör ett annat fönster, dvs du får även med kontroller (knappar och dylikt), men framförallt verkar den inte ge mig alla fönster i processen.
Vad jag behöver är en "Forms-collection" som verkar över alla dll:er i mitt program. Jag överväger att skippa den här lösningen helt och själv implementera en Forms-collection i varje DLL, vilket blir en hel del Copy/Paste-jobb, men om det inte finns någon enkel metod att få ut alla formulär så får det bli så.Sv: Enumerera formulär
Eller kör du med en massa ActiveX-exe, dvs out-of-process komponenter?
I första fallet tror jag du kan testa med
EnumThreadWindows
<code>Public Declare Function EnumThreadWindows Lib "user32" Alias "EnumThreadWindows" (ByVal dwThreadId As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long
</code>
Den tar trådID för din process som inparameter, i övrigt samma som EnumWindows.
Har faktiskt inte använt den här själv men den passar ju rätt bra in.
/EggetSv: Enumerera formulär
Sv: Enumerera formulär
Här är koden, först lite i ett formulär...
<code>
' I ett formulär
Private Sub Command1_Click()
Dim ThreadID As Long, ProcessID As Long ' receive id to thread and process of Form1
' Determine the thread which owns this window
ThreadID = GetWindowThreadProcessId(Me.hwnd, ProcessID)
' Use the callback function to list all of the enumerated thrad windows
EnumThreadWindows ThreadID, AddressOf EnumThreadWndProc, 0
'Show the results
Me.AutoRedraw = True
MsgBox sClasses
End Sub
</code>
...samt nedanstående kod i en modul :
<code>
'In a module
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
'variable used to list all the classnames
Public sClasses As String
Public Function EnumThreadWndProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
Dim Ret As Long, sText As String
Dim sSave As String
'create a string-buffer
sText = Space(255)
'get the classname of the window handle
Ret = GetClassName(hwnd, sText, 255)
'cut off the unnecessary part of Chr$(0)'s
sText = Left$(sText, Ret)
'add this classname to the list of classnames
sClasses = sClasses + sText
Ret = GetWindowTextLength(hwnd)
sSave = Space(Ret)
GetWindowText hwnd, sSave, Ret + 1
sClasses = sClasses + " : " + sSave + vbCrLf
'continue the enumeration
EnumThreadWndProc = 1
End Function
</code>Sv: Enumerera formulär
Det hittar du i App.ThreadID.
I alla fall i din huvud-app, men eftersom alla DLL:er kör in-process borde det funka i vilket fall om du kör anropet från någon av dem istället.
Fast din lösning funkar ju minst lika bra :)
/EggetSv: Enumerera formulär
Ska kolla om App.ThreadID ger samma ID...jag försöker alltid minimera antalet API-anrop eftersom de brukar vara en källa till bekymmer och märkliga krascher :-)