Código PHP:
hWnd = FindWindowEx(Label1.Text, 0, Nothing, "Save Now")
| ||||
![]() Es que en este caso ya no estás buscando el hWnd de la ventana, sino el hWnd del botón: Código PHP:
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. lástima, igual me sigue dando cero. Estoy claro con lo que me dices, no se me habia ocurrido lo de "Save Now" y la verdad suena bien lógico que debí escribir eso. Además veo que el nombre de la clase del botón no cambia, es "Button". Así lo ando declarando: Código PHP: Tambien puse el nombre de la clase de la ventana donde salen los botones y tambien me da cero. Última edición por moradazo; 02/09/2008 a las 07:56 |
| ||||
![]() Bueno, prueba declarándola así:
Código:
También tienes que mirar en el Spy++ si no hay un objeto de transición entre la ventana padre y el botón. <System.Runtime.InteropServices.DllImport("user32.dll")> _ Private Shared Function FindWindowEx( _ ByVal hWnd1 As System.IntPtr, ByVal hWnd2 As System.IntPtr, _ ByVal lpsz1 As String, ByVal lpsz2 As String) _ As System.IntPtr End Function
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Solo cero me sigue dando.... FindWindowEx(Label1.Text, 0, Nothing, "Save Now") Disculpa como desconozco un poco del Spy++, como se donde hay un objeto de transicion? |
| ||||
![]() Fíjate en la lista de ventanas que tienes, al abrir un nodo aparecen sus hijas, si esas hijas tienen otras hijas también te permite abrir el Nodo: Por ejemplo, para llegare al hWnd del ListBox del Spy++ deberías primero ir obteniendo los hWnd de los padres. Además, otra cosa que no entendí, se supone que usas este código para obtener el hWnd de la ventana del Warning: Código PHP:
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. El label1.text es el hwnd de la ventana del Treat, si bien leí que el FindWindowEx busca el hWnd padre y luego el hijo, por eso de primero puse el label. No se si estoy bien. En todo caso creo que Reprox Warning es más independiente al Treat, fijate en esta imagen: ![]() Como ves, Treat y Reprox Warning estan en un mismo rango, por lo que puedo tratarla como ventana independiente. Si usara el Sendmessage ya tengo el hWnd, el WM_Command, solo me quedaría por buscar bien el wparam y el lparam para completar esta busqueda. Tu que opinas? Esta bien mi desicion o ando perdido? |
| ||||
![]() Pues sí, así es, Reprox Warning es una ventana independiente, así que lo que deberías hacer es obtener su hWnd con el FindWindow, y luego con FindWindowEx obtener el hWnd del botón. Si lo logras, nos cuentas ![]()
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Ya se que pasa David, cuando sale el cuadro de Reprox Warning, el textbox me muestra que el hWnd sigue valiendo cero, ahora puse un botón buscando el hWnd cuando yo quiera activarlo y un momento despues de que sale el Reprox Warning si me manda un numero que significa el hWnd. El codigo me parece tenerlo bien, ya que una linea despues del SendMessage sigue la parte de averiguar el hWnd de Reprox Warning. Que puede ser? Por cierto, estoy usando SendNotifyMessage., ya que SendMessageCallback me da un error despues de salvar. Gracias! |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Lo que puedes hacer es un bucle hasta que encuentre el hWnd, ya que puede que en el mismo instante de pasar del SendNotifyMessage aún no se haya creado la ventana.
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Cita: Exactamente David eso se puede hacer, con esto digo fin al tema al menos ya que logré por fin mi objetivo.Lo que hice en vez de un bucle fue poner otro timer con el mismo tiempo que el de autosalvar. Por ejemplo, autosalvar lo hacia cada 5 minutos por decir algo, el otro timer, duraba 5:00:00:01, entonces esa milésima de más fue la espera de que saliera la ventana que buscaba, entonces ahi si la encontraba. Una vez encontrada la ventana, use lo siguiente en el procedimiento del timer creado: Código PHP: |
| ||||
![]() Me alegra que lo hayas resuelto ![]() ¿Usaste keybd_event al final? ![]() ¿No lograste simular el click en el botón con SendMessage?
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. No David, es que me parece complejo pues nunca encontre el wparam del boton nada me servia, me parece que es por el asunto del tiempo, al adelantarse unas milesimas un timer al otro, ya la ventana aparecio y puedo procesar con el keyevent Igualmente muchas gracias. |
| ||||
![]() Con el Spy++ se puede, dijiste que al hacer Click en el botón enviaba esto: Cita: Entonces el wParam es ese, y el lParam como te había comentado es el hWnd del botón.wparam: 00000401 lparam: 01C80550 Código PHP:
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Si gracias David, lo que noto es que necesito a fuerzas ese hwnd del Reprox Warning y para obtenerlo sera unos instantes después de que el SentNotifyMessage haya ejecutado su función. Si lo hago al mismo tiempo, el valor del hwnd es siempre cero. Ahorita tengo un problema pues tengo 2 timers, uno que es el que salva cada cierto tiempo, y el otro es igual al que decribí pero con 30 milésimas más. Ejemplo: AutoSave.Interval = Val(15) * 1000 SaveNow.Interval = (Val(15) * 1000) + 30 El segundo como se puede notar tiene 30 milésimas más pero esto hace a que cada vez que salva, ese tiempo se va incrementar, a tal punto que el keybd_event se tardará en actuar. Necesito decirle a SaveNow.Interval que empieze con esas 30 milésimas y que de ese momento en adelante siga teniendo el mismo intervalo que AutoSave.Interval, o sea: 1 vez: 15000/15030 2 vez: 30000/30030 3 vez: 45000/45030 Actualmente el programa me lo hace asi: 1 vez: 15000/15030 2 vez: 30000/30060 3 vez: 45000/45090 Así no me sirve, necesito que sea inmediato, me podrías dar una mano en esto? Gracias! |
| ||||
![]() ¿Por qué mejor después del SendNotifyMessage no haces un bucle que ejecute el FindWindow hasta que el hWnd devuelto sea diferente a cero? ![]() Código PHP:
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Gracias David, el bucle es exactamente lo que ocupaba, jamas me iba a imaginar que ese codigo fuera tan importante para mi proyecto. Muchas gracias! Aca dejo todo el codigo. Ocupan 2 textbox, un listview, un label y 3 timers ![]()
Código:
Public Class Form1 Dim stopAutosave As New Stopwatch Dim stoptiempos As New Stopwatch Dim stoplapsos As New Stopwatch ' #Region " Código generado por el Diseñador de Windows Forms " '... código de diseño del formualrio ... #End Region ' ' Private Delegate Function EnumWindowsDelegate _ (ByVal hWnd As System.IntPtr, ByVal parametro As Integer) As Boolean 'FUNCIONES <System.Runtime.InteropServices.DllImport("user32.dll")> _ Private Shared Function EnumWindows( _ ByVal lpfn As EnumWindowsDelegate, _ ByVal lParam As Integer) As Boolean End Function ' <System.Runtime.InteropServices.DllImport("user32.dll")> _ Private Shared Function GetWindowText( _ ByVal hWnd As System.IntPtr, _ ByVal lpString As System.Text.StringBuilder, _ ByVal cch As Integer) As Integer End Function <System.Runtime.InteropServices.DllImport("user32.DLL")> _ Private Shared Function SendNotifyMessage( _ ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _ ByVal wParam As Integer, ByVal lParam As Integer _ ) As Integer End Function <System.Runtime.InteropServices.DllImport("user32.DLL")> _ Private Shared Function SendMessage( _ ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, _ ByVal wParam As Integer, ByVal lParam As Integer _ ) As Integer End Function <System.Runtime.InteropServices.DllImport("user32.dll")> _ Public Shared Function SetForegroundWindow(ByVal hWnd As System.IntPtr) As Boolean End Function Declare Function ShowWindow Lib "user32" Alias "ShowWindow" _ (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long Public Const SW_SHOWNOACTIVATE = 4 Public Const SW_SHOWNORMAL = 1 <System.Runtime.InteropServices.DllImport("user32.dll")> _ Private Shared Function ShowWindow(ByVal hWnd As System.IntPtr, ByVal nCmdShow As Integer) As Integer End Function Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer Declare Function SetActiveWindow Lib "user32.dll" (ByVal hwnd As Long) As Long Public Const SW_RESTORE = 9 'FUNCION QUE USA LAS KEYS VIRTUALES PARA VENTANAS ACTIVAS Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, _ ByVal dwFlags As Long, _ ByVal dwExtraInfo As Long) Private Const VK_CONTROL As Long = &H11 Private Const VK_S As Long = &H53 Private Const VK_SPACE As Long = &H20 Private Const KEYEVENTF_KEYUP As Long = &H2 Private Const VK_RIGHT As Long = &H27 ' Para EnumWindows Private colWin As New System.Collections.Specialized.StringDictionary ' Private Function EnumWindowsProc(ByVal hWnd As System.IntPtr, ByVal parametro As Integer) As Boolean ' Esta función "callback" se usará con EnumWindows y EnumChildWindows Dim titulo As New System.Text.StringBuilder(New String(" "c, 256)) Dim ret As Integer Dim nombreVentana As String ' ret = GetWindowText(hWnd, titulo, titulo.Length) If ret = 0 Then Return True ' nombreVentana = titulo.ToString.Substring(0, ret) If nombreVentana <> Nothing AndAlso nombreVentana.Length > 0 Then colWin.Add(hWnd.ToString, nombreVentana) End If ' Return True End Function 'TIEMPO DE AUTOSALVACION, EL TIMER1 CALCULA CADA CIERTO TIEMPO PARA SALVAR 'Y DEPENDE DEL INTERVALO CARGADO EN EL FORM_LOAD Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If stopAutosave.IsRunning Then Dim ts1 As TimeSpan = stopAutosave.Elapsed String.Format("{0:00}:{1:00}:{2:00}", ts1.Hours, ts1.Minutes, ts1.Seconds) simulacion() End If End Sub Private Const WM_COMMAND = &H111 'PASO SEGUIDO DEL TIMER1 DONDE BUSCA EL MENU DE LA VENTANA PARA SALVAR 'Y SE PREPARA PARA RECIBIR OTRA VENTANA Y TERMINAR DE SALVAR Private Sub simulacion() Dim wParam As Long Dim lParam As Long Dim hwnd As Long Dim a As Long wParam = 57603 'ID del Save lParam = 0 a = SendNotifyMessage(Label1.Text, WM_COMMAND, wParam, lParam) TB3.Text = a Do While hwnd = 0 hwnd = FindWindow(Nothing, "Reprox Warning") Loop SetActiveWindow(hwnd) SetForegroundWindow(hwnd) keybd_event(VK_RIGHT, 1, 0, 0) keybd_event(VK_RIGHT, 1, KEYEVENTF_KEYUP, 0) keybd_event(VK_SPACE, 1, 0, 0) keybd_event(VK_SPACE, 1, KEYEVENTF_KEYUP, 0) TB1.Text = hwnd End Sub 'ESTE TIMER CONTARA CADA CIERTO TIEMPO ESPECIFICO EN EL FORM_LOAD QUE SALVARA EL PROGRAMA ' Private Sub Tiempos_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tiempos.Tick If stoptiempos.IsRunning Then Dim ts As TimeSpan = stopAutosave.Elapsed String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds) ListView1.Items.Clear() Label1.Text = "" VentanaTreat() If Label1.Text = "" Then stopAutosave.Stop() Label1.Text = "No hay Treat" Else If TextBox1.Text > 1 Then If stopAutosave.IsRunning Then stopAutosave.Stop() End If Else stopAutosave.Start() End If End If End If End Sub 'PROCEDIMIENTO MAS IMPORTANTE DEL PROGRAMA '------------------------------------------ ' ' 'BUSCA TODAS LAS VENTANAS ACTIVAS O INACTIVAS EJECUTADAS EN MEMORIA, Y ADEMAS SE FILTRA 'CON UNA BUSQUEDA ESPECIFICA, EN ESTE CASO, TODAS LAS VENTANAS QUE CONTENGAN "TREAT3" Y '"CRTreat" DONDE MOSTRARA EN UN LISTVIEW LAS VENTANAS ABIERTAS CON ESAS DESCRIPCIONES. Private Sub VentanaTreat() colWin.Clear() Dim i As Integer = 0 ListView1.Items.Clear() EnumWindows(AddressOf EnumWindowsProc, 0) For Each s As String In colWin.Keys If colWin(s).Contains("Treat3") And colWin(s).Contains("CRTreat") Then Label1.Text = s ListView1.Items.Add(colWin(s), i) i = i + 1 End If Next TextBox1.Text = i End Sub 'EL INICIO DEL PROGRAMA, CARGA TODOS LOS TIMERS PARA INICIAR IGUAL Y EN DOS INICIA SUS INTERVALOS Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load stoplapsos.Start() stoptiempos.Start() stopAutosave.Start() Tiempos.Interval = Val(3000) Timer1.Interval = Val(10 * 1000) End Sub 'TIMER QUE CUENTA TODO EL TIEMPO QUE EL PROGRAMA ESTE ABIERTO Private Sub TimerCrono_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Intervalos.Tick If stoplapsos.IsRunning Then Dim ts As TimeSpan = stoplapsos.Elapsed Me.TextBox2.Text = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10) End If End Sub End Class |
| ||||
![]() Qué bien que hayas resuelto el problema. Aunque sigo insistiendo que debías simular el Click en el botón con SendMessage ![]() Y, ¿para qué éstos? Código PHP: ![]()
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Bueno como verás esas clases son para calcular tiempos, y con estas indicaciones inicializo los timers en el form_load: stoplapsos.Start() stoptiempos.Start() stopAutosave.Start() Y como ves ahora en la imagen de como quedó la interfaz del programa, en realidad esa interfaz fue para ver como se mueve el programa en tiempo de ejecución. En realidad el programa no tendrá interfaz, de hecho arrancará una vez que Windows inicie, y se cerrará cuando se apague la PC. Ahora ando averiguando eso, gracias !!!! |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Hola, vuelvo con este tema: Ocupo que por medio de un botón funcione para pegar un texto, yo ya tengo esta parte que copia de un textbox: Código PHP: ![]() |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Prueba con SetWindowText.
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Gracias a Seb123neo y a David el Grande. Ya tengo el código para copiar y pegar, pero ese no es el problema, el asunto es que tengo un textbox donde escribo cualquier texto, tengo un botón que va copiar ese texto, y quiero pegarlo en el cuadro de texto de otro programa, independiente al mío, por eso necesito el SendMessage. Aprendí precisamente con David el Grande la función del WM_Command que sirve para utilizar los Menú de los programas, pero en este caso no se si erá necesario este WM para buscar el cuadro de texto donde se va a pegar ese texto, me entienden? Gracias!!! |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Exacto, a eso mismo me refería con que uses SetWindowText. Mira la documentación en la MSDN.
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Gracias David, pero esta documentación me dice que lo que hace SetWindowText es cambiar el texto del nombre de la ventana: "La función SetWindowText cambia el texto de la barra de título de la ventana especificada (si es que tiene). Si la ventana especificada es un control, se modificará su texto." No se si entendí bien pero según leo solo cambia la barra de titulo, o es que estoy malentendiendo? |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. ¿Y no es eso lo que quieres hacer?. Colocar el texto de un TextBox de tu aplicación en un control de otra aplicación.
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Exacto, pero es que leo la función de SetWindowText y se me hace extraño por eso de que solo se usa para cambiar la barra de título. Dime, uso la misma función del WM_Command? o es otro? |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. No solo cambia la barra de título sino también el texto de los controles. En cuanto al SendMessage ahora no tengo VB para hacer las pruebas, pero estoy casi seguro que el mensaje no es el WM_COMMAND.
__________________ Por favor, antes de preguntar, revisa la Guía para realizar preguntas. |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Ok investigaré más a fondo el SetWindowText. gracias David |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Hola que tal. Mira intenté realizar algo con este código: Código PHP: Veo que el SetWindowText no necesita un WMessage, será posible al menos colocar el cursor del mouse en el cuadro de texto de la otra aplicación con esta API? Gracias! |
| ||||
Respuesta: Visual Basic 2005: Usar SendMessage. Esto es lo que yo necesito, copiar mi cuadro de la izquierda al de la derecha, o sea su texto. Lei por ahi que con un focus a ese cuadro podré realizarlo, pero como identifico el cuadro? Gracias ![]() |