Spy++

Iniciado por Piratex, 22 Marzo 2015, 12:37 PM

0 Miembros y 1 Visitante están viendo este tema.

Piratex

Hola a todos.

Si tengo una aplicación como por ejemplo la calculadora donde todos los botones son la clase "Button", como puedo recorrer todos los botones y saber en cada momento en el botón que estoy.

Muchas gracias por anticipado.

1010.c0der.1010

Cita de: Piratex en 22 Marzo 2015, 12:37 PM
Hola a todos.

Si tengo una aplicación como por ejemplo la calculadora donde todos los botones son la clase "Button", como puedo recorrer todos los botones y saber en cada momento en el botón que estoy.

Muchas gracias por anticipado.

No te comprendo pero puedes crear un array de botones y asi recorrer todos, a medida que vas agregando los botones te puede ir creando button(1), button(2), button(3), etc., asi mas facilmente puedes identificarlo y con un bucle puedes recorrer todos los botones.

Tambien puedes usar el evento focus para saber en que botón estas.

Código (vb) [Seleccionar]
Private Sub Button1_GotFocus()
    Label1 = "El foco lo tiene: " & Button1.Caption
End Sub

okik

#2
Hola

Por decucción, como has titulado el asunto como "Spy++", supongo que te refieres a la Calculadora de Windows accediendo a ella desde tu apliación.  En Spy++ al hacer clic en "+" correspondiente a la Calculadora se despliega un árbol donde aparecen todos los handles y textos de cada botón. De modo que cada botón tiene un Handle (un número aleatório identificativo) y una etiqueta o texto "1","2", "Bin","hyp", "=", etc.

Para recorrer los botones primero se obtiene el handle de la calculadora con la declaración API FindWindow, después el handle del PRIMER  botón con FindWindowEx, y para ir recorriendo los siguientes botones se usa GetWindow y el comando GW_HWNDNEXT.

Para saber si estás en un determinado botón obtienes su etiquieta o texto con GetWindowText, así si estás en "5" obtienes "5".



Aquí te dejo un plantilla de ejemplo,  que recorre todos los botones e introduce el nombre de cada uno en un ListBox. Además, al pasar el cursor por los botones de la calculadora muestra en un Label el botón donde se encuentra el cursor.

Necesitas un Botón, un Label , un ListBox y un control Timer


En un Form:
EN VB6
Código (vb) [Seleccionar]
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Const WM_SYSCOMMAND = &H112
Private Const SC_CLOSE = &HF060&

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

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long

Private Type POINTAPI
x As Long
y As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPointXY Lib "user32" Alias "WindowFromPoint" _
(ByVal xPoint As Long, ByVal yPoint As Long) As Long

Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long

'Para recorrer todos los botones
Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Private Const GW_CHILD = 5
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_MAX = 5
Private Const GW_OWNER = 4

Private Sub Command1_Click()
Shell "Calc", vbNormalFocus
Timer1.Enabled = True
RecorrerBotones
End Sub

Public Function TextoBoton() As String
Dim pt32 As POINTAPI
Dim ptx As Long
Dim pty As Long
Dim x As Long
Dim hw As Long
Dim hWndParent As Long
Dim TextWindow As String * 100
Call GetCursorPos(pt32)                ' obtiene la posición del cursor
ptx = pt32.x
pty = pt32.y
   hw = WindowFromPointXY(ptx, pty) ' Obtiene el handle debajo del cursor
   hWndParent = GetParent(hw) ' Consigue el handle padre de una ventana
   x = GetWindowText(hWndParent, TextWindow, 100) 'Obtiene el texto de la ventana
If Left(TextWindow, x) = "Calculadora" Then
   x = GetWindowText(hw, TextWindow, 100) 'Obtiene el texto de un botón
   TextoBoton = Left(TextWindow, x)
End If

End Function

Private Sub Form_Load()
Timer1.Enabled = False
Command1.Caption = "Abrir calculadora"
End Sub

Private Sub Form_Unload(Cancel As Integer)
Dim hw As Long
hw = FindWindow("SciCalc", vbNullString)
SendMessage hw, WM_SYSCOMMAND, SC_CLOSE, &H0 'Cierra la calculadora
End
End Sub

Private Sub Timer1_Timer()
'Para obtener el texto del botón donde se encuentra el cursor
Label1.Caption = TextoBoton

Me.Caption = TextoBoton

End Sub

Public Sub RecorrerBotones()
Dim hw As Long
Dim x As Long
Dim TextWindow As String * 100
hw = FindWindow("SciCalc", vbNullString)
hw = FindWindowEx(hw, &H0, "Button", vbNullString) 'obtiene el primer handle de un botón
   Do While Left(TextWindow, x) <> "C "
       hw = GetWindow(hw, GW_HWNDNEXT) '<--- Esto permite obtener y pasar al siguiente Handle de la lista
       x = GetWindowText(hw, TextWindow, 100) 'Obtiene el texto de un botón
       If x > 0 Then
       List1.AddItem Left(TextWindow, x)
       End If
       DoEvents
   Loop
End Sub




EN VB.NET
Código (vbnet) [Seleccionar]
Imports VB = Microsoft.VisualBasic
Public Class Form1
   Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
       (ByVal hWnd As Integer, _
        ByVal wMsg As Integer, _
        ByVal wParam As Integer, _
        ByRef lParam As Object) As Integer

   Private Const WM_SYSCOMMAND = &H112
   Private Const SC_CLOSE = &HF060&


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

   Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
   (ByVal hWnd1 As Integer, _
   ByVal hWnd2 As Integer, _
   ByVal lpsz1 As String, _
   ByVal lpsz2 As String) As Integer

   Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
   (ByVal hwnd As Integer, _
   ByVal lpString As String, _
   ByVal cch As Integer) As Integer

   Structure POINTAPI
       Dim X As Integer
       Dim Y As Integer
   End Structure

   Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Integer
   Private Declare Function WindowFromPointXY Lib "user32" Alias "WindowFromPoint" _
   (ByVal xPoint As Integer, ByVal yPoint As Integer) As Integer

   Private Declare Function GetParent Lib "user32" (ByVal hwnd As Integer) As Integer
   'Para recorrer todos los botones
   Private Declare Function GetWindow Lib "user32" _
   (ByVal hwnd As Integer, _
   ByVal wCmd As Integer) As Integer
   Private Const GW_CHILD = 5
   Private Const GW_HWNDFIRST = 0
   Private Const GW_HWNDLAST = 1
   Private Const GW_HWNDNEXT = 2
   Private Const GW_HWNDPREV = 3
   Private Const GW_MAX = 5
   Private Const GW_OWNER = 4


   Public Function TextoBoton() As String
       Dim pt32 As POINTAPI
       Dim ptx As Long
       Dim pty As Long
       Dim x As Long
       Dim hw As Long
       Dim hWndParent As Long
       Dim TextWindow As String
       TextoBoton = ""
       TextWindow = Space(100)
       Call GetCursorPos(pt32)                ' obtiene la posición del cursor
       ptx = pt32.X
       pty = pt32.Y
       hw = WindowFromPointXY(ptx, pty) ' Obtiene el handle debajo del cursor
       hWndParent = GetParent(hw) ' Consigue el handle padre de una ventana
       x = GetWindowText(hWndParent, TextWindow, 100) 'Obtiene el texto de la ventana
       If VB.Left(TextWindow, x) = "Calculadora" Then
           x = GetWindowText(hw, TextWindow, 100) 'Obtiene el texto de un botón
           TextoBoton = VB.Left(TextWindow, x)
       End If
       Return TextoBoton
   End Function


   Public Sub RecorrerBotones()
       Dim hw As Long
       Dim x As Long
       Dim TextWindow As String
       TextWindow = Space(100)
       hw = FindWindow("SciCalc", vbNullString)
       hw = FindWindowEx(hw, &H0, "Button", vbNullString) 'obtiene el primer handle de un botón
       Do While VB.Left(TextWindow, x) <> "C "
           hw = GetWindow(hw, GW_HWNDNEXT) '<--- Esto permite obtener y pasar al siguiente Handle de la lista
           x = GetWindowText(hw, TextWindow, 100) 'Obtiene el texto de un botón
           If x > 0 Then
               ListBox1.Items.Add(VB.Left(TextWindow, x))
           End If
           Application.DoEvents()
       Loop
   End Sub

   Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
       Dim hw As Long
       hw = FindWindow("SciCalc", vbNullString)
       SendMessage(hw, WM_SYSCOMMAND, SC_CLOSE, &H0) 'Cierra la calculadora
       End
   End Sub
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Timer1.Enabled = False
       Timer1.Interval = 1
       Button1.Text = "Abrir calculadora"
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       Shell("Calc", vbNormalFocus)
       Timer1.Enabled = True
       RecorrerBotones()
   End Sub

   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
       'Para obtener el texto del botón donde se encuentra el cursor
       Label1.Text = TextoBoton()
       Me.Text = TextoBoton()
   End Sub
End Class