none
Enviar valor de textbox a textbox de aplicacion externa RRS feed

  • Pregunta

  • Hola amigos, quisera saber si se puede enviar un valor de un textbox de un form vb.net a un textbox de otra aplicacion externa la cual conozco el nombre del textbox y form, me he topado con algunos ejemplos utilizando APIs pero no me han funcionado, tal ves tengan una rutina como poder realizarlo desde ya se lo agradezco, gracias por su ayuda
    miércoles, 10 de diciembre de 2014 23:12

Todas las respuestas

  • Hola amigos, quisera saber si se puede enviar un valor de un textbox de un form vb.net a un textbox de otra aplicacion externa la cual conozco el nombre del textbox y form, me he topado con algunos ejemplos utilizando APIs pero no me han funcionado, tal ves tengan una rutina como poder realizarlo desde ya se lo agradezco, gracias por su ayuda

    miércoles, 10 de diciembre de 2014 23:11
  • Si puedes apoyarme con algunos ejemplos..

    Public Declare Function GetActiveWindow Lib "user32" () As System.IntPtr
    Public Declare Auto Function GetWindowText Lib "user32" (ByVal hWnd As System.IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer

    Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Long) As Long


    miércoles, 10 de diciembre de 2014 23:48
  • Esta bien, seguire revisando..
    miércoles, 10 de diciembre de 2014 23:59
  • mmmmm la verdad cuando lei la pregunta pense que seria mas sencilla ahora que lei bien creo que no es tan sencillo... si yo tuviera el codigo de ambos proyectos lo haria con un archivo de texto compartido o con una base de datos compartida pero eso ya es enrrollarse mucho
    jueves, 11 de diciembre de 2014 0:23
  • hola

    usando asl api de hooking del sistema operativo podrias acceder al proces de la otra aplicacion y realizar acciones, pero no es nada simple lograrlo

    Read/Write textbox of another application

    veras que se usa las api de FindWindowEx y SendMessage

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 11 de diciembre de 2014 0:27
  • otra forma podrias ser usando DDE (Dynamic Data Exchange)

     DDE with VB.Net

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 11 de diciembre de 2014 0:29
  • se repondio en el foro de Windows Forms

    Enviar valor de textbox a textbox de aplicacion externa



    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 11 de diciembre de 2014 0:31
  • Leandro si puedes compartir el post o la parte de solución seria genial ya que no puedo tener acceso al parecer se requiere registro y pago para acceder al post..
    jueves, 11 de diciembre de 2014 0:45
  • Hola:
    Una posible solucion seria:
    Desde la aplicacion 1 copias el valor del TextBox en el portapapeles.
    Desde la aplicacion 2 copias el valor del portapapeles al TextBox.

    Un saludo desde Bilbo
    Carlos

    jueves, 11 de diciembre de 2014 8:38
  • Le propongo la respuesta de Christian.  Eso es básicamente lo que necesita asumiendo que su proceso no está ejecutándose a un nivel de seguiridad más restringido que el proceso externo (si le interesa, lea acerca de low integrity processes; el tema es popular en el contexto de Protected Mode de IE).

    El detallito que me parece que debo aclarar con respecto a la respuesta de Christian, es que no es necesario, hasta donde recuerdo, usar SendMessage() para enviar el texto con un mensaje WM_SETTEXT pues existe la función nativa SetWindowText() que es más sencilla de usar.

    Otro detalle:  Veo algunos parámetros en las funciones de la respuesta propuesta incorrectamente declarados como Long cuando deberían ser tipo IntPtr.


    Jose R. MCP
    Code Samples


    jueves, 11 de diciembre de 2014 14:26
    Moderador
  • No. SetWindowText() no marshallea el string. No hay manera que pueda pasarlo a otro proceso.
    jueves, 11 de diciembre de 2014 14:44
  • No. SetWindowText() no marshallea el string. No hay manera que pueda pasarlo a otro proceso.
    Ah ok.  En ese caso nos olvidamos de SetWindowText() y usamos SendMessage para enviar WM_SETTEXT.  Gracias por salvarme el pellejo aquí, no revisé ese detalle.

    Jose R. MCP
    Code Samples

    jueves, 11 de diciembre de 2014 14:50
    Moderador
  • Gracias Carlos Herrero tu comentario me ayudo de mucho.

    Saludos

    viernes, 12 de diciembre de 2014 0:07
  • Bueno de alguna manera lo he solucionado basándome en un comentario que me hicieron en el foro Lenguaje VB.NET

    El comentario es el siguiente:

    Una posible solucion seria:
    Desde la aplicacion 1 copias el valor del TextBox en el portapapeles.
    Desde la aplicacion 2 copias el valor del portapapeles al TextBox.

    Gracias a todos por su valiosas respuestas.


    viernes, 12 de diciembre de 2014 0:13
  • >>Desde la aplicacion 1 copias el valor del TextBox en el portapapeles. Desde la aplicacion 2 copias el valor del portapapeles al TextBox.

    pero como haces estas operaciones desde codigo, cuando la segunda aplicacion tu no puedes modificarla? porque es de terceros

    ademas que pasa si en el intervalo que operas entre aplicaciones alguna otra aplicacion cambia el valor del portapapeles

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 12 de diciembre de 2014 0:50
  • Leandro lo que sucede es que esta aplicacion de terceros si me permite hasta cierto grado de acceso y modificacion de interface/código, me permite como desarrollador agregar un campo nuevo en la interface y asi mediante un boton llamo a una ventana de ayuda en .net con lo cual mediante el portapapeles y algún otro artificio estoy logrando simular pasar el dato entre aplicaciones, es cierto que tal ves no es la solucion mas optima pero por el momento logra su cometido.

    Saludos


    viernes, 12 de diciembre de 2014 1:46
  • Hola:

    "pero como haces estas operaciones desde codigo, cuando la segunda aplicacion tu no puedes modificarla? porque es de terceros"
    Que yo sepa para pegar el contenido del pòrtapapeles se hace con Control + V.
    Para hacer esto, no hay que modificar nada en la segunda aplicacion.

    "ademas que pasa si en el intervalo que operas entre aplicaciones alguna otra aplicacion cambia el valor del portapapeles"
    No pasa nada, se repite la operacion hasta que tenga exito.
    No he dicho que sea la MEJOR manera de hacerlo, pero es una manera.

    Un saludo desde Bilbo
    Carlos

    viernes, 12 de diciembre de 2014 7:56
  • Christian, la solución que le dieron no es buena.  ¿Qué pasa si el usuario tenía un dato importante en el portapapeles?  Yo soy muy dado a usar el portapapeles cuando borro código y estoy acomodando de un lado al otro.  Yo desinstalaría su aplicación en el acto con el primer bloque de código que me haga perder.  El portapapeles no debe ser usado de esa manera.


    Jose R. MCP
    Code Samples

    viernes, 12 de diciembre de 2014 13:03
    Moderador
  • De acuerdo en cierta forma Jose R., aún sigo revisando alguna posible solución..

    Creo que el usuario no debería mantener por mucho datos importantes en el portapapeles además creo antes de empezar a hacer otras cosas es decir realizar la operación en cuestión debería haber terminado de "salvar" aquellos datos importantes del portapapeles, si llegara a ocurrir este siniestro para el usuario creo sería aprender sobre ello, de todas formas sigo revisando una mejor solución.

    Saludos,

    viernes, 12 de diciembre de 2014 13:12
  • Christian, la solución está aquí.  ¿No sabe cómo usar las API que le mostraron?  No es problema, le podemos escribir un ejemplo si nos responde algunas preguntas.  Le explico primero cómo trabaja para que me entienda las preguntas.

    En Windows, todo es una "ventana".  Los botones, casillas de texto, los formularios, el botón del menún inicio, los tooltips, todo.  La excepción es WPF donde solamente el formulario es ventana.  Los controles contenidos son dibujos sobre esa ventana y no son ventanas aparte.

    Cada ventana tiene su "clase" que define su comportamiento y forma.  De esta forma uno puede tener múltiples botones o múltiples ListView simplemente generando ventanas nuevas de la misma clase.

    Entonces la idea del método es usar FindWindowEx() para buscar una ventana con un texto particular de una clase particular.  Uno empieza buscando la ventana raíz usando el texto y su clase.  Cuando la encuentra entonces uno busca la ventana hijo a la cual quiere enviarle el dato, que sería el textbox que usted menciona.  Normalmente uno lo busca por ID o algo similar porque el texto varía y solamente la clase no es suficiente.  Aquí puede usarse la función EnumWindows() para enumerar ventanas hijo.  Uno enumera hasta que encuentra.

    Cuando ya tenemos el window handle del textbox simplemente mandamos un WM_SETTEXT con la función SendMessage().  Y listo.  Suena a mucho, lo sé.  Programación nativa en Windows suele ser intimidante para el principiante, pero cuando uno llega a entender, no hay nada que no pueda resolver. :D

    Jaja, olvidé hacerle las preguntas.  Usando la aplicación Spy++:

    1. ¿Cuál es el control ID del textbox que busca y cuál es su clase?
    2. ¿Cuán adentro de la jerarquía de ventanas se encuentra dicho texto?
    3. ¿Cuál es la clase y texto de la ventana raíz de la aplicación?

    Jose R. MCP
    Code Samples

    viernes, 12 de diciembre de 2014 13:26
    Moderador
  • Jose R. gracias por su explicación, ojala pueda servir la siguiente imagen, la línea resaltada es la del textbox de la aplicación a la cual quiero pasar el dato.

    viernes, 12 de diciembre de 2014 15:27
  • Sí sirve.  Ese Class Name es una de las cosas que buscamos.  En el tab General está el control ID.  También se ocupa.

    Revise cuál es la ventana raíz, que me parece es esa 00840FF4, pero no estoy muy seguro.  Revise el treeview a ver si hay otra raíz o use la función de buscar de Spy++ para localizarla.  Necesitamos la ventana raíz porque el método comienza buscando entre todas las ventanas "top level".


    Jose R. MCP
    Code Samples

    viernes, 12 de diciembre de 2014 15:34
    Moderador
  • Gracias Jose R. ya encontré el control ID del textbox 00271BEA y es correcto existe un nivel anterior a 00840FF4 que no se llega a ver en la imagen que vendria a ser la raiz su Window Handle es 0555070C


    viernes, 12 de diciembre de 2014 15:47
  • Los window handles cambian de valor entre ejecuciones así que no nos fiamos de esos valores.  Apunte el class name de la ventana raíz y el control ID y class name de la casilla de texto.

    Cierre y abra la aplicación varias veces y constate que los valores apuntados NO cambian.


    Jose R. MCP
    Code Samples

    viernes, 12 de diciembre de 2014 16:09
    Moderador
  • Ah, y si la aplicación raíz tiene Window Text (que sería el título que se lee en la parte de la barra de título en la parte superior), también lo apunta y constata que no cambia.  Si cambia, apunte el texto en común.  Ejemplo:  Bloc de Notas siempre agrega el nombre del documento al título, pero mantiene las palabras "Bloc de Notas" siempre.  Esa información es útil.

    Jose R. MCP
    Code Samples

    viernes, 12 de diciembre de 2014 16:13
    Moderador
  • Jose R. he notado que toda la jerarquia incluso la ventana (por ejemplo la ventana de menu) que se encuentra al mismo nivel raiz de mi ventana tienen el mismo class name WindowsForms10.Window.8.app.0.2004eee tal ves se pueden diferenciar por el Window Caption que sería el título (no encuentro Window Text) pues no cambia.
    Con respecto a la casilla de texto despues de varias pruebas tambien posee el mismo class name WindowsForms10.Window.8.app.0.2004eee y el control ID cambia cada que vuelvo a abrir la aplicacion de tercero, no cambia cuando vuelvo a abrir el Spy, tal ves se puedan tomar otros datos de la pestaña Class que al parecer no cambian como Instance Handle, Window Proc
    viernes, 12 de diciembre de 2014 16:57
  • Bueno, gracias por sus apuntes.
    jueves, 18 de diciembre de 2014 19:33
  • Uf, se me había escapado esta pregunta.  Hoy no me he acercado a una PC.  Hasta ahora.  Mañana trato de sacar tiempo para esto.

    Jose R. MCP
    Code Samples

    viernes, 19 de diciembre de 2014 3:45
    Moderador
  • Todos los controles de windows forms son servidores de UI Automation.

    Un cliente de UI Automation, entonces,  puede hallarlos.

    El espacio de nombres System.Windows.UIAutomation permite escribir clientes de UIAutomation.

    Tu aplicación puede entonces buscar el formulario de la aplicación externa, ya que conoces su nombre. Puede también localizar el control dentro del formulario, del que tienes su nombre. Puede obtener el ValuePattern del elemento. Y, finalmente, puede usar el pattern para hacer un SetValue() del string que deseas copiar al textbox de la otra aplicación.

    Si te interesa un ejemplo de esto (media docena de líneas), me dices como se llaman el formulario y el control y yo te lo escribo.

    Fijate que todos los controles de windows forms tienen una propiedad AccesibleName. Una aplicación que permite ser manipulada desde un cliente, usa las propiedades Accesible*, para darse a conocer.

    De todos modos, con la propiedad Name del control basta para hallarlo. 

    Los controles (WS_CHILD), de windows forms no establecen el GWL_ID en compile time. Lo hacen sí en runtime, asignando el valor del handle de la ventana. Lo que convierte a ese identificador en algo inútil.

    '/r: UIAutomationClient.dll
    '/r: UIAutomationTypes.dll
    Imports System.Windows.Automation
    
    Public Class Form1
    
        Dim tbe As TextBoxExterno
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            'frmPirulo es el Name del formulario
            'txtPirulo es el nombre del textbox
            tbe = TextBoxExterno.FromName("frmPirulo", "txtPirulo")
        End Sub
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            tbe.Texto = TextBox1.Text
        End Sub
    
        Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
            TextBox1.Text = tbe.Texto
        End Sub
    End Class
    
    Class TextBoxExterno
        Dim element As AutomationElement
        Dim pattern As ValuePattern
    
        Public Property Texto() As String
            Get
                Return pattern.Current.Value
            End Get
            Set(ByVal value As String)
                pattern.SetValue(value)
            End Set
        End Property
    
        Private Sub New(e As AutomationElement)
            pattern = DirectCast(e.GetCurrentPattern(ValuePattern.Pattern), ValuePattern)
        End Sub
    
        Public Shared Function FromName(nombreFormulario As String, nombreTextBox As String) As TextBoxExterno
    
            Dim condición As New AndCondition(New PropertyCondition(AutomationElement.AutomationIdProperty, nombreFormulario), New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window))
            Dim formulario As AutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, condición)
    
            If Not formulario Is Nothing Then
                Dim condición2 As New AndCondition(New PropertyCondition(AutomationElement.AutomationIdProperty, nombreTextBox), New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit))
                Dim tb As AutomationElement = formulario.FindFirst(TreeScope.Descendants, condición2)
    
                If Not tb Is Nothing Then
                    Return New TextBoxExterno(tb)
                End If
            End If
    
            Throw New ApplicationException("Exception Occured")
        End Function
    
    End Class
    

    TextBoxExterno es un tipo de dato con el que puedes leer y escribir el contenido de un textbox existente en otra aplicación de windows forms. Para crear una instancia de la clase usas como argumento los nombres del form y del textbox de la aplicación externa.

    • Editado Langosta sábado, 20 de diciembre de 2014 17:26
    sábado, 20 de diciembre de 2014 14:38