Alguien sabe como conseguir esto

Iniciado por Fran1946, 4 Febrero 2020, 13:39 PM

0 Miembros y 2 Visitantes están viendo este tema.

Fran1946


Hola a todos;
Estoy haciendo un programa que carga imágenes, las salva en una carpeta, y luego  las procesa.
Después visualiza, utilizando el Visualizador de fotos de Windows, las originales y las procesadas para poder compararlas, conmutando las 2 imágenes pulsando los botones 3 o 5, en la imagen del Visualizador de fotos de Windows, o pulsando las teclas Dcha o Izq del teclado.
Pero hay que cerrar las ventanas que enumero mas abajo, para que el usuario no pueda utilizar los menúes, ni los botones 1, 2, 4, 6, 7 y 8 de la imagen.

Se como obtener los Hwnd de las ventanas del Visualizador de fotos de Windows de estas clases, que se ven en la imagen:
   photos_navigationpane
        photos_navigationbar
   photos_commandbar
        photos_buttonex

Pero dentro de la ventana photos_buttonex (color naranja en la imagen)
Hay 8 button numerados del 1 al 8 en la imagen, que en realidad tambien son ventanas, por que tienen Hwnd cada uno.
Y necesito obtener el Hwnd de cada uno, y no veo la forma de hacerlo.
Por que con el código que utilizo para obtener los Hwnd de las clases(ventanas)
photos_navigationpane, photos_navigationbar, photos_commandbar, y photos_buttonex, no me sirve por que no detecta los 8 botones.

El código es este:

Public Sub EnumChildProc(ByVal hWnd As Long)
    Dim hChild As Long, ret As Long, Caption As String, i As Integer
    Form5.ListMemoRuta.Clear
    hChild = FindWindowEx(hWnd, 0, vbNullString, vbNullString)
1:
    Do While hChild <> 0
        DoEvents
        'Llenamos un Buffer
        ClassName = Space$(128)
        'Recupera el Classname y lo devuelve en el Buffer
        ret = GetClassName(hChild, ClassName, 128)
        'Extraemos el nombre de la clase
        ClassName = LCase(Left$(ClassName, ret))
        Caption = String(GetWindowTextLength(hChild), Chr$(0))
        If InStr(ClassName, "photos_navigationpane") Then
            If Todo Then Form5.ListMemoRuta.AddItem hChild
            navigationpane = hChild
        ElseIf InStr(ClassName, "photos_commandbar") Then
            Form5.ListMemoRuta.AddItem hChild
        ElseIf InStr(ClassName, "atl:") Then
            Form5.ListMemoRuta.AddItem hChild
        ElseIf InStr(ClassName, "photos_navigationbar") Then
            If Todo Then Form5.ListMemoRuta.AddItem hChild
            navigationbar = hChild
        ElseIf InStr(ClassName, "photo_lightweight_viewer") Then
            'Form5.ListMemoRuta.AddItem hChild
            viewer = hChild
        ElseIf ClassName = "photos_buttonex" Then
            buttonex = hChild
        End If
        hChild = GetNextWindow(hChild, 2)
    Loop
    'lista de clases que hay que cerrar
2:
    For i = 0 To Form5.ListMemoRuta.ListCount - 1
        hChild = Form5.ListMemoRuta.List(i)
        Call SendMessage(hChild, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
        Form5.ListMemoRuta.RemoveItem (i)
        GoTo 2
    Next



Pero con un timer y este código:


'Obtiene la coordenada del Mouse
ret = GetCursorPos(Cor)
'Recuperamos el HWND de la ventana asociada a esa coordenada
Handle = WindowFromPoint(Cor.x, Cor.y)
'Para calcular el ancho actual de la ventana
Call GetClientRect(Handle, rct)
If ClassName = "photos_buttonex" Then
        If rct.Right = 51 And rct.Bottom = 25 Then
                 'son los botones de 3  y  5 de la imagen
                 'no hace nada, por que son los que utiliza el programa
        Else
                 'cierra estas ventanas(botones), para que no el usuario no pueda pulsarlos
                  Call SendMessage(Handle, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
        End If
End If


Al pasar el cursor del ratón encima del área de los botones 1, 2, 4, 6, 7 y 8, se cierran, por que solo de esta forma consigo obtener los Hwnd de cada uno, en la variable Handle del código.
Alguien sabe como conseguir los Hwnd de los botones 1, 2, 4, 6, 7 y 8 con código, sin tener que pasar el cursor del ratón encima de cada uno.
Y en el caso de que no se pueda o nadie lo sepa:

Alguien puede sugerirme el código para que el programa ponga el cursor del ratón encima del centro de cada uno de estos botones del  Visualizador de fotos de Windows(tengo las coordenadas X,Y de cada uno), para poder obtener el Handle, y así poder cerrarlos con Call SendMessage(Handle,WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)

Por que no he conseguido nada que funcione.

Espero que me podáis ayudar a conseguirlo.

Gracias y un saludo.

fary

Un byte a la izquierda.

FJDA

#2
hola
has tenido suerte porque hace, no si más de diez años que no toco VB. El caso es que me he puesto a ayudar a un compañero y recién he instalado vB6 y he hecho un programa con él.

No puedes encontrar en handle (hwnd) porque tienes que obtenerlo de forma descendente, primero el padre que es la ventana, luego el panel que contiene el objeto, luego el objeto y luego sus botones y todo a partir del primero. Es decir con el primero obtienes el segundo, con el segundo el tercero, con el tercero el cuarto.


Código (vb) [Seleccionar]

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 GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long

Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" _
(ByVal hwnd As Long, ByVal wFlag As Long) As Long

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

Const GW_HWNDNEXT = 2
Const GW_CHILD = 5

   
Private Sub Command2_Click()
Dim TITULODELAVENTANA As String
Dim hPhoto_Lightweight_Viewer As Long
Dim hPhotos_NavigationPane As Long
Dim hPhotos_NavigationBar As Long
Dim hPhotos_ButtonEx_1 As Long
Dim hPhotos_ButtonEx_2 As Long
Dim hPhotos_ButtonEx_3 As Long
Dim hPhotos_ButtonEx_4 As Long
Dim hPhotos_ButtonEx_5 As Long
TITULODELAVENTANA = "24TL510V.jpg - Visualizador de fotos de Windows"
'Orden de padre a hijos
'1.Photo_Lightweight_Viewer
'-----Photos_NavigationPane
'------------Photos_NavigationBar
'----------------------Photos_ButtonEx

'//handle de la ventana
hPhoto_Lightweight_Viewer = FindWindow("Photo_Lightweight_Viewer", TITULODELAVENTANA)

'//handle del panel
'handle de Photo_Lightweight_Viewer
handlePhotos_NavigationPane = FindWindowEx(hPhoto_Lightweight_Viewer, ByVal 0&, "Photos_NavigationPane", vbNullString)

'//Handle del control de botones
'handle de hPhotos_NavigationBar
handlePhotos_NavigationBar = FindWindowEx(handlePhotos_NavigationPane, ByVal 0&, "Photos_NavigationBar", vbNullString)


'//BOTONES
'//Como Photos_ButtonEx no tiene hijos a partir de aquí se usa  GW_HWNDNEXT
'//para obtener el handle del siguiente botón (ventana)

'handle de Photos_ButtonEx (la lupa)
hPhotos_ButtonEx_1 = FindWindowEx(handlePhotos_NavigationBar, ByVal 0&, "Photos_ButtonEx", vbNullString)

'handle de Photos_ButtonEx (botón maximizar)
hPhotos_ButtonEx_2 = GetWindow(hPhotos_ButtonEx_1, GW_HWNDNEXT)

'handle de Photos_ButtonEx (botón "izquierda")
hPhotos_ButtonEx_3 = GetWindow(hPhotos_ButtonEx_2, GW_HWNDNEXT)

'handle de Photos_ButtonEx (botón diapositivas)
hPhotos_ButtonEx_4 = GetWindow(hPhotos_ButtonEx_3, GW_HWNDNEXT)

'handle de Photos_ButtonEx (botón "derecha")
hPhotos_ButtonEx_5 = GetWindow(hPhotos_ButtonEx_4, GW_HWNDNEXT)


MsgBox "LUPA = " & Hex(hPhotos_ButtonEx_1)
MsgBox "MAXIMIZAR = " & Hex(hPhotos_ButtonEx_2)
MsgBox "IZQUIERDA = " & Hex(hPhotos_ButtonEx_3)
MsgBox "DIAPOSITIVAS = " & Hex(hPhotos_ButtonEx_4)
MsgBox "DERECHA = " & Hex(hPhotos_ButtonEx_5)


End Sub



luego  a partir de Photos_ButtonEx debes buscar el siguiente porque Photos_ButtonEx es el classname de todos los botones



Había otra manera para conseguir todos los handles de una ventan pero no me acuerdo, voy a ver si tengo algún snippet por ahí

Otra cosa, no necesitas ese código del timer para ver los handles, VB6 viene tine SPY++ con el que puedes encontrar los handles e información de las ventanas e hijos. Deberías ver una acceso directo en el menú incio\programas, en"Herramientas de Microsoft Visual Studio 6.0" y si no en "C:\Program Files\Microsoft Visual Studio\Common\Tools\SPYXX.EXE"




y te digo otra cosa, no te lo puedo asegurar pero creo que si importas los botones por separado no te van a hacer nada, ya me contarás.

@XSStringManolo

Para comparar las imágenes puedes usar ImageMagik para vb.net, he visto por ahí códigos simples de 20 líneas que lo hacen. También hay apis online a las que les envías las imágenes y te devuelven el resultado de la comparación.

Serapis

Cita de: Fran1946 en  4 Febrero 2020, 13:39 PM
...Después visualiza, utilizando el Visualizador de fotos de Windows, las originales y las procesadas para poder compararlas...
Me temo que estás cazando moscas a cañonazos...
Define adecuadamente eso de: "...procesarlas para compararlas..."

FJDA

Cita de: NEBIRE en  5 Febrero 2020, 03:24 AM
Me temo que estás cazando moscas a cañonazos...
Define adecuadamente eso de: "...procesarlas para compararlas..."

yo entiendo que se refiere con procesarlas a editarlas, cambiar brillo, contraste y estas cosas, puede que incluso el formato o compresión. Después compara una imagen "procesada" con otra original que no ha recibido cambios. ¿para qué? pues él sabrá.


de momento a mi eso me parece irrelevante, me he limitado a centrarme en el tema de la programación, ¿quiere obtener el handle de los botones pero no los consigue? pues ahí está, aunque recuerdo un código que tenía que lo hacía de forma escalonada hasta obtener todos los handles y classname de una ventana, pero no lo encuentro, eran como 6 u 8 líneas y lo hacía.



Fran1946

Hola FJDA:
;-) ;-) ;-)
Tienes razón he tenido mucha suerte con tu respuesta.
Es excelente, exactamente lo que necesitaba saber.

Y también por SPY++ , nunca lo había utilizado.

Pero tengo una duda, que te explico.
Este es el árbol, he añadido las clases que tu no mencionas.

'Orden de padre a hijos
    '1.Photo_Lightweight_Viewer
    '-----Photos_commandbar
    '-----Photos_photocanvas  Este handle no lo necesito
    '-----Photos_NavigationPane
    '---------Photos_NavigationBar
    '--------------Photos_ButtonEx

Yo supongo que de la ventana padre '1.Photo_Lightweight_Viewer' ...
sale estas 3:
Photos_commandbar este handle no se como conseguirlo, con tu código
Photos_photocanvas  Este handle no lo necesito, es la imagen
Photos_NavigationPane, este y sus hijos está claro

Me podrías decir como conseguir Photos_commandbar, por que esta ventana alberga los menúes que no puede utilizar el usuario, y esta ventana el programa tiene que cerrarla.

Muchísimas gracias por tu ayuda.


Fran1946

Cita de: FJDA en  5 Febrero 2020, 09:34 AM
yo entiendo que se refiere con procesarlas a editarlas, cambiar brillo, contraste y estas cosas, puede que incluso el formato o compresión. Después compara una imagen "procesada" con otra original que no ha recibido cambios. ¿para qué? pues él sabrá.

Una vez más has acertado, hago un proceso bastante complicado, que es irrelevante.
Y por cierto NEBIRE, yo no mato moscas a cañonazos, mi pregunta está muy clara, al menos para FJDA.

Serapis

Pués si, matas moscas a cañonazos.... te guste o no aceptarlo.
Querer controlar mediante programación la interfaz de usuario de otra aplicación, es matar moscas a cañonazos.
La interfaz de usuario, como su nombre indica está pensada para ser utilizada por personas... para aplicaciones hay multitud de librerías que permiten invocar su funcionalidad, para hacer lo que pretendas hacer (modificar brillo, contraste, saturación, girar imagen, etc...), con sus respectivos parámetros... sin complicaciones estúpidas que uno se impone como una barrera...

Entiendo que uno no quiera implementar determinada funcionalidad, porque o bien no sabe como hacerlo o bien no quiere perder demasiado tiempo en hacerlo, pero perderlo en pretender controlar la interfaz de otro programa además tan limitado... es lo que es.

Te preguntaba en mi mensaje anterior, por la funcionalidad, simplemente para sugerirte opciones más amplias, sencillas (de usar) y válidas, si se tratara (por ejemplo) de algo como girar una imagen cambiar brillo, guardar una imagen, etc, pués ofrecerte ejemplos de código, si fueran demasiadas cosas o bien más complejas sugerirte alguna librería... pero si prefieres no dar explicaciones en tu "proceso bastante complicado, que es irrelevante", entonces sigue con el camino que llevas...

FJDA

En realidad te equivocas respecto al árbol. Por esta razón no encuentras Photos_commandbar. No has entendido el concepto de ventanas Parents y Childs.

Realmente el árbol sería así:

Photo_Lightweight_Viewer
  - Photos_CommandBar
          - Photos_ButtonEx (Arc&hivo)
          - Photos_ButtonEx (&Imprimir)
          - Photos_ButtonEx (Correo &electrónico)
          - Photos_ButtonEx (&Grabar)
           - Photos_ButtonEx  (&Abrir)
           - Photos_ButtonEx ("") objeto oculto
           - Photos_ButtonEx ("") objeto oculto
  - Photos_PhotoCanvas
  - ATL:568ED690
           - Photos_ButtonEx  ("") objeto oculto
           - Photos_ButtonEx  ("") objeto oculto
           - Photos_ButtonEx  ("") objeto oculto
  - Photos_NavigationPane
            - Photos_NavigationBar
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)
                   - Photos_ButtonEx (control de navegación)


Entonces,  Photo_Lightweight_Viewer tiene cuatro hijos que son Photos_CommandBarPhotos_PhotoCanvas, ATL:568ED690 (no se lo que es) y Photos_NavigationPane

Con mi código lo que hice fue encontrar primero Photo_Lightweight_Viewer  y luego el hijo Photos_NavigationPane mediante éste encuentro su hijo Photos_NavigationBar y despues los botones.

Para encontrar Photos_CommandBar  necesito el handle (hwnd) del padre que es Photo_Lightweight_Viewer.

Por lo tanto para encontrarlo primero encuentras el padre que es
hPhoto_Lightweight_Viewer = FindWindow("Photo_Lightweight_Viewer", TITULODELAVENTANA)

y después uno de sus hijos que en este caso te interesa Photos_CommandBar

hPhotos_commandbar = FindWindowEx(hPhoto_Lightweight_Viewer, ByVal 0&, "Photos_commandbar", vbNullString)

Demostración:

Código (vb) [Seleccionar]
Dim TITULODELAVENTANA As String
Dim hPhoto_Lightweight_Viewer As Long
Dim hPhotos_commandbar As Long
TITULODELAVENTANA = "demo.jpg - Visualizador de fotos de Windows"

hPhoto_Lightweight_Viewer = FindWindow("Photo_Lightweight_Viewer", TITULODELAVENTANA)
hPhotos_commandbar = FindWindowEx(hPhoto_Lightweight_Viewer, ByVal 0&, "Photos_commandbar", vbNullString)
MsgBox "barra = " & Hex(hPhotos_commandbar)


Por si te sirve te dejo este código para ajustar colores (brillo, contraste, escala de grises, etc)

https://mega.nz/#!fBlyUCpQ!Kemdm1iZ52dScMcYy6cfak2VzEV4jZ8pBlByvkrLK_0

demostración: