2010-01-18 11 views
1

J'utilise le code suivant pour itérer et trouver des fenêtres contenant des chaînes spécifiques dans leurs barres de titre. J'ai deux projets contenant cette information identique, mais pour une raison quelconque - cela fonctionne quand ciblé à x64, mais FindWindowLike renvoie 0 toujours sur x86. J'ai besoin de cela pour fonctionner en x86.Pourquoi cela fonctionnera-t-il en 32 bits, mais pas en 64 bits? (x86 vs x64 dans les options du compilateur)

Je développe ceci sur Windows 7 x64, mais il doit fonctionner sur ma machine aussi bien que XPx32. Ce que je ne comprends pas pourquoi il compile/Runs sur x64 x32 mais pas (étant donné que je suis utilisateur 32 ciblage .dll)

Voici le code:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr 
    End Function 

    <DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindowByClass(ByVal lpClassName As String, ByVal zero As IntPtr) As IntPtr 
    End Function 

    <DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindowByCaption(ByVal zero As IntPtr, ByVal lpWindowName As String) As IntPtr 
    End Function 

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> Public Shared Function IsWindow(ByVal hWnd As IntPtr) As Boolean 
    End Function 

    Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr 
    Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr 
    Public Declare Function GetDesktopWindow Lib "user32"() As Long 
    Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long 
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long 
    Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long 
    Public Const GW_HWNDFIRST = 0 
    Public Const GW_HWNDLAST = 1 
    Public Const GW_HWNDNEXT = 2 
    Public Const GW_HWNDPREV = 3 
    Public Const GW_OWNER = 4 
    Public Const GW_CHILD = 5 
    Public listWindows As New List(Of String) 

Private Function FindWindows() As Long 
     Dim hWndStart As Long = 0 
     Dim WindowText As String = "*message*" 
     Dim Classname As String = "*" 
     Dim hwnd As Long 
     Dim sWindowText As String 
     Dim sClassname As String 
     Dim r As Long 

     'Hold the level of recursion and 
     'hold the number of matching windows 
     Static level As Integer 

     'Initialize if necessary. This is only executed 
     'when level = 0 and hWndStart = 0, normally 
     'only on the first call to the routine. 
     If level = 0 Then 
      If hWndStart = 0 Then hWndStart = GetDesktopWindow() 
     End If 

     'Increase recursion counter  
     level = level + 1 

     'Get first child window 
     hwnd = GetWindow(hWndStart, GW_CHILD) 

     Do Until hwnd = 0 

      'Search children by recursion 
      Call FindWindows() 

      'Get the window text and class name 
      sWindowText = Space$(255) 
      r = GetWindowText(hwnd, sWindowText, 255) 
      sWindowText = Microsoft.VisualBasic.Left(sWindowText, r) 
      sClassname = Space$(255) 
      r = GetClassName(hwnd, sClassname, 255) 
      sClassname = Microsoft.VisualBasic.Left(sClassname, r) 

      'Check if window found matches the search parameters 
      If (sWindowText Like WindowText) And (sClassname Like Classname) Then 
       If listWindows.Contains(hwnd & "||||" & sClassname & "||||" & sWindowText) = False Then 
        listWindows.Add(hwnd & "||||" & sClassname & "||||" & sWindowText) 
       End If 
       FindWindows = hwnd 

       'uncommenting the next line causes the routine to 
       'only return the first matching window. 
       'Exit Do 

      End If 

      'Get next child window 
      hwnd = GetWindow(hwnd, GW_HWNDNEXT) 

     Loop 

     'Reduce the recursion counter 
     level = level - 1 
End Function 

Répondre

3

Vos définitions de fonctions sont faux. En C LONG est de 32 bits de large, mais en C# et VB.NET long est de 64 bits de large sur les deux systèmes 32 bits et 64 bits. En outre, vos paramètres de poignée de fenêtre doivent être IntPtr s.

Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr 
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr 
Private Declare Function GetDesktopWindow Lib "user32"() As IntPtr 
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr 
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As IntPtr, ByVal lpString As String, ByVal cch As Integer) As Integer 
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer 

Notez que vous ne devriez pas être de passage String s à GetWindowText et GetClassName. Essayez StringBuilder.

+1

"ne devrait pas" n'est pas assez fort, c'est grossièrement faux. Visitez pinvoke.net pour de meilleures déclarations. –

+0

Eh bien ce n'est pas si mal. Si vous créez une chaîne d'une certaine longueur et assurez-vous qu'elle n'est pas internée, alors vous devriez être OK. – wj32

1

Un autre conseil consiste à conclure les appels qui ciblent 32 systèmes & 64 bits. Voici un exemple pour GetWindowLong:

Public Shared Function GetWindowLong(ByVal hWnd As HandleRef, ByVal nIndex As Integer) As IntPtr 
    If (IntPtr.Size = 4) Then 
     Return NativeMethods.GetWindowLong32(hWnd, nIndex) 
    End If 
    Return NativeMethods.GetWindowLongPtr64(hWnd, nIndex) 
End Function 

Comme le dit nobugz, vous pouvez jeter un oeil à pinvoke.net. Je préfère utiliser un réflecteur et voir, exactement, comment le cadre le gère.