el Guille, la Web del Visual Basic, C#, .NET y más...

Incrustar una aplicación en un control o en un formulario

Publicado el 15/Ago/2005
Actualizado el 19/Nov/2006
Autor: Guillermo 'guille' Som

En este artículo veremos cómo incrustar (o poner) una aplicación dentro de un control o de un formulario, para ello usaremos funciones del API de Windows, particularmente tres: SetParent, FindWindow y MoveWindow.
Como es mi costumbre, el código de ejemplo estará tanto para Visual Basic como para C#.

 

Nota del 05/Nov/2015:
Aquí tienes un enlace para un código parecido pero para usar con VB5/VB6

Especial Docking: Meter un formulario dentro de un control Picture

 



 

Introducción:
 

En este artículo veremos cómo poner (o meter o incrustar o incluir) dentro de un control o de un formulario una aplicación que, o bien esté ya funcionando o bien la iniciemos nosotros. Para hacer esto, vamos a echar mano del API de Windows, ya que, (al menos no lo he encontrado), el .NET Framework no dispone de clases para hacerlo.

Funciones del API de Windows usadas para poner una aplicación en un contenedor de Windows Forms

Como he comentado antes, para hacer el trabajo que nos ocupa, vamos a usar tres funciones del API de Windows:

  • FindWindow, esta nos servirá para buscar una ventana por el título y devolverá el "handle" de esa ventana.
  • SetParent, esta función hará que una ventana sea hija de otra.
  • MoveWindow, la utilizaremos para cambiar el tamaño de una ventana de la que conocemos el handle.

 

Nota:
Si quieres ver la declaración para VB6, VB.NET, C/C++ y C# de estas funciones, pásate por la página de Equivalencias con el API de Windows.

 

Encontrar una ventana

Lo primero que tenemos que hacer es encontrar la ventana que queremos incluir dentro de un control o bien dentro de un formulario. De esa ventana lo que nos interesa es el "handle" de la misma. Una vez que conocemos ese "identificador", podremos usar otras funciones del API de Windows para que trabajen con ella.

Una de las cosas que haremos en la aplicación de ejemplo será "incrustar" una aplicación que nosotros iniciemos. Para iniciar esa aplicación vamos a usar la clase Process (System.Diagnostics.Process), esa clase tiene una propiedad llamada Handle, pero esa propiedad no devuelve el "identificador" de la ventana creada, sino que devuelve el identificador del proceso recién creado. Por tanto no nos servirá ese valor, en su lugar usaremos la función del API FindWindow, a la cual se le pasan dos parámetros, el primero es el nombre de la clase de la ventana, pero este se puede omitir, pasando un valor nulo (Nothing en VB, null en C#); el segundo parámetro es el título de la ventana que queremos encontrar. Ese nombre debe ser el título exacto que tiene la ventana. Por ejemplo, si queremos "buscar" el bloc de notas recién abierto, buscaremos el siguiente texto si nuestro sistema operativo está en inglés: Untitled - Notepad, y este otro: Sin título - Bloc de notas, si el sistema operativo está en español. En cualquiera de los dos casos debemos indicar el título completo, ya que si sólo buscamos parte de él, FindWindow devolverá un cero, indicando que no ha encontrado una ventana con el título indicado.

Cambiar el contenedor de una ventana

Es complicado esto de las traducciones "técnicas", ya que en inglés sería parent window, que traducido literalmente podría ser  ventana madre, ventana progenitora e incluso ventana padre, pero como ventana es femenino, pues como que "parent" no se adecua mucho a padre, por eso me he decidido por usar "contenedor de una ventana", con idea de que quede claro de que una ventana puede tener a su vez otras ventanas, además de que es la forma que se utiliza en la documentación de Visual Studio .NET.

Para cambiar el contenedor de una ventana, por defecto suele ser el escritorio la ventana predeterminada, vamos a usar la función del API de Windows: SetParent. Esta función recibe dos parámetros, los cuales son los identificadores de las ventanas que están en juego, el primer parámetro será la ventana que queremos contener dentro de otra, y el segundo será el identificador de la ventana que hará de contenedor.

En .NET Framework, todos los controles usados con las aplicaciones de Windows.Forms se derivan de la clase Control, esa clase tiene una propiedad llamada Handle que es el identificador (HWND) de la ventana usada para mostrar ese control, por tanto, al menos teóricamente, podemos usar cualquier control como contenedor de otros controles (o ventanas).
En la aplicación de ejemplo utilizaremos un control Panel para contener a una aplicación.

Cambiar el tamaño y posición de una ventana

Otra de las cosas que haremos en la aplicación de ejemplo es mover la ventana "hija" dentro de la ventana contenedora, con idea de que en un principio esté totalmente visible y ocupe el mismo espacio que el control (o formulario) en el que vamos a incrustar la ventana de la aplicación que indiquemos. Debido a que de esa aplicación solo conoceremos el identificador de la ventana, tendremos que echar nuevamente mano del API de Windows para usar la función MoveWindow, la cual recibe seis parámetros, el primero es el identificador de la ventana que queremos mover, los dos siguientes son la posición de la equina superior izquierda de la ventana (x e y), los dos siguientes son el ancho y el alto de la ventana, y por último un valor que indica si queremos que se "repinte" la ventana después de moverla.

La posición de la ventana será relativa al contenedor, no a la ventana principal (escritorio), por tanto, si le indicamos 0, 0, estaremos situando la ventana hija en la esquina superior izquierda de la ventana contenedora.

La aplicación de ejemplo

Con la aplicación que vamos a usar para explicar cómo usar esas tres funciones del API de Windows para que hagan lo que queremos, haremos varias cosas:
1- Podremos iniciar una aplicación y ponerla dentro de un control del formulario principal o bien ponerla dentro de un segundo formulario.
2- También podremos indicar el título de una de las aplicaciones que estén en ejecución y meterla dentro del control o de otro formulario.

 

Nota:
Es importante advertir que todo este "manejo" de ventanas puede llegar a producir inestabilidad en el sistema operativo, por tanto, deberías tener mucho cuidado con que ventana quieres indicar para que se "incruste" en otra, incluso esa inestabilidad del sistema puede llegar a producirse al manipular aplicaciones simples como el bloc de notas.

 

Una clase con las funciones del API de Windows

Para tener mejor organizado nuestro código, vamos a declarar las tres funciones del API de Windows en una clase.
En Visual Basic podemos usar un módulo en lugar de una clase, incluso sería más cómodo de usar, pero como quiero que el código mostrado quede claro para todo el mundo, voy a usar una clase en la que esas funciones estarán compartidas (Shared en VB, static en C#), de forma que para usar cualquiera de ellas, solo tengamos que indicar el nombre de la clase seguida de la función: WinApi.SetParent(h1, h2).

Iniciar un proceso y meter la aplicación en un control

Esta es una de las opciones que tendremos en el programa.
Para iniciar el proceso usaremos la clase Process, el nombre de la aplicación a iniciar estará en la caja de textos.
Este es el código de Visual Basic a usar:

' Iniciar el proceso indicado en txtApp
Dim proc As New System.Diagnostics.Process
proc.StartInfo.FileName = txtApp.Text
proc.Start()
hWndNotepad = WinApi.FindWindow(Nothing, proc.MainWindowTitle)
If hWndNotepad.ToInt32 > 0 Then
    WinApi.MoveWindow(hWndNotepad, 0, 0, PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
    WinApi.SetParent(hWndNotepad, PanelApp.Handle)
Else
    proc.Close()
    hWndNotepad = IntPtr.Zero
End If

 

Buscar el título de la ventana a contener en un control

El código para esta tarea es similar al anterior, con la única diferencia de que en esta ocasión no tendremos que iniciar ningún proceso, simplemente buscamos el título de la ventana que queremos meter dentro del control y ya está.

' Capturar la ventana con el título indicado en txtApp
hWndNotepad = WinApi.FindWindow(Nothing, txtApp.Text)
If hWndNotepad.ToInt32 > 0 Then
    WinApi.MoveWindow(hWndNotepad, 0, 0, PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
    WinApi.SetParent(hWndNotepad, PanelApp.Handle)
Else
    hWndNotepad = IntPtr.Zero
End If

 

El formulario principal de la aplicación

El formulario principal de nuestra aplicación tendrá una serie de controles que nos permitirán realizar las acciones que te he indicado, y este es el aspecto de ese formulario:

La aplicación con el bloc de notas en un control Panel
La aplicación con el bloc de notas en un control Panel

Como podemos comprobar, tenemos cuatro botones, una caja de textos, un checkBox y un control Panel.
Dos de esos botones servirán para iniciar la aplicación indicada en la caja de textos. Dependiendo de que queramos "meter" esa aplicación en el panel o que se muestre otro formulario que lo contenga, pulsaremos en uno u otro botón.
Los otros dos botones nos servirán para "capturar" una aplicación que ya esté en funcionamiento, para poder capturar esa aplicación, tendremos que indicar en la caja de textos el título completo de la ventana. Al igual que ocurría con los otros botones, uno nos servirá para poner la aplicación en el panel de este formulario y el otro para incluirlo en un nuevo formulario.
El checkBox lo utilizaremos para ajustar la aplicación al tamaño del panel.
En el otro formulario, también habrá un checkBox con la misma funcionalidad.

 

Nota:
En las pruebas que he hecho, solo me "capturaba" la primera aplicación que le indicara, si después intentaba capturar otras aplicaciones, "pasaba" olímpicamente, y la única solución que me quedaba era cerrar el programa y volver a abrirlo. Seguramente será cosa del código, pero no me he puesto a "mirarlo" a fondo... así que, si lo solucionas, me lo dices y lo corrijo.

 

Y esto es todo amigos... espero que te sea de utilidad y que lo disfrutes.

Aquí tienes el proyecto con el código tanto para Visual Basic como para C#.

Y aquí abajo tienes el código de los dos formularios y la clase con las declaraciones del API de Windows, también para Visual Basic y para Visual C#.

Nos vemos.
Guillermo

 


Código para Visual Basic.NET (VB.NET)El código para VB .NET

La clase WinApi con las declaraciones del API de Windows

'------------------------------------------------------------------------------
' Clase con las funciones del API de Windows                        (14/Ago/05)
' Las funciones están declaradas como compartidas
' para usarlas sin crear una instancia.
'
' ©Guillermo 'guille' Som, 2005
'------------------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System

Public Class WinApi
    ' Hace que una ventana sea hija (o esté contenida) en otra
    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Public Shared Function SetParent(ByVal hWndChild As IntPtr, _
				ByVal hWndNewParent As IntPtr) As IntPtr
    End Function
    ' Devuelve el Handle (hWnd) de una ventana de la que sabemos el título
    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Public Shared Function FindWindow(ByVal lpClassName As String, _
				ByVal lpWindowName As String) As IntPtr
    End Function
    ' Cambia el tamaño y la posición de una ventana
    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Public Shared Function MoveWindow(ByVal hWnd As IntPtr, _
				ByVal x As Integer, ByVal y As Integer, _
                                ByVal nWidth As Integer, ByVal nHeight As Integer, _
                                ByVal bRepaint As Integer) As Integer
    End Function

End Class

El formulario principal

'------------------------------------------------------------------------------
' Poner una aplicación dentro de un formulario                      (14/Ago/05)
'
' ©Guillermo 'guille' Som, 2005
'------------------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing

Public Class Form1
    Inherits System.Windows.Forms.Form
    '
    Private hWndNotepad As IntPtr = IntPtr.Zero
    '
    <STAThread()> _
    Shared Sub Main()
        Application.EnableVisualStyles()
        Application.DoEvents()
        '
        Application.Run(New Form1)
    End Sub
    Public Sub New()
        MyBase.New()

        'El Diseñador de Windows Forms requiere esta llamada.
        InitializeComponent()

        'Agregar cualquier inicialización después de la llamada a InitializeComponent()

    End Sub
    '
#Region " Código generado por el Diseñador de Windows Forms "


#End Region

    Private Sub btnFormRun_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnFormRun.Click
        ' Iniciar el proceso indicado en txtApp en un formulario
        Dim frm2 As New FormContenedor
        frm2.chkAjustarAuto.Checked = True
        frm2.IniciarApp(txtApp.Text)
        frm2.Show()
    End Sub

    Private Sub PanelApp_Resize(ByVal sender As Object, _
				ByVal e As System.EventArgs) _
				Handles PanelApp.Resize
        ' Ajustar automáticamente el tamaño del contenido, si así se ha indicado
        If hWndNotepad.ToInt32 > 0 Then
            If chkAjustarAuto.Checked Then
                WinApi.MoveWindow(hWndNotepad, 0, 0, _
				PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
            End If
        End If
    End Sub

    Private Sub btnPanelRun_Click(ByVal sender As Object, _
				ByVal e As System.EventArgs) _
				Handles btnPanelRun.Click
        ' Iniciar el proceso indicado en txtApp
        Dim proc As New System.Diagnostics.Process
        proc.StartInfo.FileName = txtApp.Text
        proc.Start()
        hWndNotepad = WinApi.FindWindow(Nothing, proc.MainWindowTitle)
        If hWndNotepad.ToInt32 > 0 Then
            WinApi.MoveWindow(hWndNotepad, 0, 0, _
				PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
            WinApi.SetParent(hWndNotepad, PanelApp.Handle)
        Else
            proc.Close()
            hWndNotepad = IntPtr.Zero
        End If
    End Sub

    Private Sub btnPanel_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnPanel.Click
        ' Capturar la ventana con el título indicado en txtApp
        hWndNotepad = WinApi.FindWindow(Nothing, txtApp.Text)
        If hWndNotepad.ToInt32 > 0 Then
            WinApi.MoveWindow(hWndNotepad, 0, 0, _
				PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
            WinApi.SetParent(hWndNotepad, PanelApp.Handle)
        Else
            hWndNotepad = IntPtr.Zero
        End If
    End Sub

    Private Sub btnForm_Click(ByVal sender As Object, _
                              ByVal e As EventArgs) _
                              Handles btnForm.Click
        ' Capturar la aplicación con el título indicado en txtApp
        ' y mostrarlo en otro formulario
        Dim frm2 As New FormContenedor
        frm2.chkAjustarAuto.Checked = True
        frm2.CapturarApp(txtApp.Text)
        frm2.Show()
    End Sub

    Private Sub chkAjustarAuto_CheckedChanged(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles chkAjustarAuto.CheckedChanged
        ' Ajustar automáticamente el tamaño del contenido, si así se ha indicado
        If hWndNotepad.ToInt32 > 0 Then
            If chkAjustarAuto.Checked Then
                WinApi.MoveWindow(hWndNotepad, 0, 0, _
				PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1)
            End If
        End If
    End Sub
End Class

El segundo formulario (que contendrá las aplicaciones)

'------------------------------------------------------------------------------
' Formulario contenedor de aplicaciones                             (14/Ago/05)
'
' ©Guillermo 'guille' Som, 2005
'------------------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing

Public Class FormContenedor
    Inherits System.Windows.Forms.Form
    '
#Region " Código generado por el Diseñador de Windows Forms "


#End Region
    '
    Private hWndApp As IntPtr = IntPtr.Zero
    '
    Public Sub IniciarApp(ByVal nombre As String)
        ' Iniciar el proceso indicado en el parámetro
        Dim proc As New System.Diagnostics.Process
        proc.StartInfo.FileName = nombre
        proc.Start()
        hWndApp = WinApi.FindWindow(Nothing, proc.MainWindowTitle)
        CapturarApp(proc.MainWindowTitle)
    End Sub
    Public Sub CapturarApp(ByVal titulo As String)
        ' Captura la ventana con el título indicado y la incrusta en el formulario
        hWndApp = WinApi.FindWindow(Nothing, titulo)
        If hWndApp.ToInt32 > 0 Then
            WinApi.MoveWindow(hWndApp, 0, 0, Me.ClientRectangle.Width, _
				Me.ClientRectangle.Height - 4 - chkAjustarAuto.Height, 1)
            WinApi.SetParent(hWndApp, Me.Handle)
        Else
            hWndApp = IntPtr.Zero
            Close()
        End If
    End Sub
    '
    Private Sub FormContenedor_Resize(ByVal sender As Object, _
				ByVal e As EventArgs) _
				Handles MyBase.Resize
        ' Ajustar automáticamente el tamaño del contenido, si así se ha indicado
        If hWndApp.ToInt32 > 0 Then
            If chkAjustarAuto.Checked Then
                WinApi.MoveWindow(hWndApp, 0, 0, Me.ClientRectangle.Width, _
				Me.ClientRectangle.Height - 4 - chkAjustarAuto.Height, 1)
            End If
        End If
    End Sub
    Private Sub chkAjustarAuto_CheckedChanged(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles chkAjustarAuto.CheckedChanged
        ' Ajustar también al pulsar en el checkbox
        If chkAjustarAuto.Checked Then
            FormContenedor_Resize(Nothing, Nothing)
        End If
    End Sub
End Class


Código para C Sharp (C#)El código para C#

La clase WinApi con las declaraciones del API de Windows

//-----------------------------------------------------------------------------
// Clase con las funciones del API de Windows                       (14/Ago/05)
// Las funciones están declaradas como compartidas
// para usarlas sin crear una instancia.
//
// ©Guillermo 'guille' Som, 2005
//-----------------------------------------------------------------------------
using System;

namespace ponerAppDentroFormCS
{
    public class WinApi
    {
        // Hace que una ventana sea hija (o esté contenida) en otra
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public extern static IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        // Devuelve el Handle (hWnd) de una ventana de la que sabemos el título
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
        // Cambia el tamaño y la posición de una ventana
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public extern static int MoveWindow(IntPtr hWnd, int x, int y, 
				int nWidth, int nHeight, int bRepaint);
    }
}

El formulario principal

//-----------------------------------------------------------------------------
// Poner una aplicación dentro de un formulario                     (14/Ago/05)
//
// ©Guillermo 'guille' Som, 2005
//-----------------------------------------------------------------------------
using System;
using System.Windows.Forms;
using System.Drawing;

namespace ponerAppDentroFormCS
{
    public class Form1 : System.Windows.Forms.Form
    {
        private IntPtr hWndNotepad = IntPtr.Zero;
        //
        [STAThread]
        static void Main() 
        {
            Application.EnableVisualStyles();
            Application.DoEvents();
            //
            Application.Run(new Form1());
        }
        public Form1() : base() 
        {
 
            //El Diseñador de Windows Forms requiere esta llamada.
            InitializeComponent();
 
            //Agregar cualquier inicialización después de la llamada a InitializeComponent()
            btnFormRun.Click += new System.EventHandler(btnFormRun_Click);
            PanelApp.Resize += new System.EventHandler(PanelApp_Resize);
            btnPanelRun.Click += new System.EventHandler(btnPanelRun_Click);
            btnPanel.Click += new System.EventHandler(btnPanel_Click);
            chkAjustarAuto.CheckedChanged += new System.EventHandler(chkAjustarAuto_CheckedChanged);
            btnForm.Click += new EventHandler(btnForm_Click);
        }  
        //
        #region Código generado por el Diseñador de Windows Forms
 
        #endregion
        //
        private void btnFormRun_Click(System.Object sender, System.EventArgs e) 
        {
            // Iniciar el proceso indicado en txtApp en un formulario
            FormContenedor frm2 = new FormContenedor();
            frm2.chkAjustarAuto.Checked = true;
            frm2.IniciarApp(txtApp.Text);
            frm2.Show();
        }  
 
        private void PanelApp_Resize(object sender, System.EventArgs e) 
        {
            // Ajustar automáticamente el tamaño del contenido, si así se ha indicado
            if( hWndNotepad.ToInt32() > 0 )
                if( chkAjustarAuto.Checked )
                    WinApi.MoveWindow(hWndNotepad, 
                        0, 0, 
                        PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1);
        }  
 
        private void btnPanelRun_Click(object sender, System.EventArgs e) 
        {
            // Iniciar el proceso indicado en txtApp
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = txtApp.Text;
            proc.Start();
            hWndNotepad = WinApi.FindWindow(null, proc.MainWindowTitle);
            if( hWndNotepad.ToInt32() > 0 )
            {
                WinApi.MoveWindow(hWndNotepad, 
                    0, 0, 
                    PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1);
                WinApi.SetParent(hWndNotepad, PanelApp.Handle);
            }
            else
            {
                proc.Close();
                hWndNotepad = IntPtr.Zero;
            }
        }  
 
        private void btnPanel_Click(System.Object sender, System.EventArgs e) 
        {
            // Capturar la ventana con el título indicado en txtApp
            hWndNotepad = WinApi.FindWindow(null, txtApp.Text);
            if( hWndNotepad.ToInt32() > 0 )
            {
                WinApi.MoveWindow(hWndNotepad, 
                    0, 0, 
                    PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1);
                WinApi.SetParent(hWndNotepad, PanelApp.Handle);
            }
            else
                hWndNotepad = IntPtr.Zero;
        }  
 
        private void btnForm_Click(object sender, EventArgs e) 
        {
            // Capturar la aplicación con el título indicado en txtApp
            // y mostrarlo en otro formulario
            FormContenedor frm2 = new FormContenedor();
            frm2.chkAjustarAuto.Checked = true;
            frm2.CapturarApp(txtApp.Text);
            frm2.Show();
        }  
 
        private void chkAjustarAuto_CheckedChanged(System.Object sender, System.EventArgs e) 
        {
            // Ajustar automáticamente el tamaño del contenido, si así se ha indicado
            if( hWndNotepad.ToInt32() > 0 )
                if( chkAjustarAuto.Checked )
                    WinApi.MoveWindow(hWndNotepad, 
                        0, 0, 
                        PanelApp.Bounds.Width - 4, PanelApp.Bounds.Height - 4, 1);
        }  
    }
} 

El segundo formulario (que contendrá las aplicaciones)

//-----------------------------------------------------------------------------
// Formulario contenedor de aplicaciones                            (14/Ago/05)
//
// ©Guillermo 'guille' Som, 2005
//-----------------------------------------------------------------------------
using System;
using System.Windows.Forms;
using System.Drawing;

namespace ponerAppDentroFormCS
{
    public class FormContenedor : System.Windows.Forms.Form
    {
        //
        public FormContenedor() : base() 
        {
 
            //El Diseñador de Windows Forms requiere esta llamada.
            InitializeComponent();
 
            //Agregar cualquier inicialización después de la llamada a InitializeComponent()
            base.Resize += new EventHandler(FormContenedor_Resize);
            chkAjustarAuto.CheckedChanged += new System.EventHandler(chkAjustarAuto_CheckedChanged);
        }  
        //
        #region Código generado por el Diseñador de Windows Forms
 
 
        #endregion
        //
        private IntPtr hWndApp = IntPtr.Zero;
        //
        public void IniciarApp(string nombre) 
        {
            // Iniciar el proceso indicado en el parámetro
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = nombre;
            proc.Start();
            hWndApp = WinApi.FindWindow(null, proc.MainWindowTitle);
            CapturarApp(proc.MainWindowTitle);
        }  
        public void CapturarApp(string titulo) 
        {
            // Captura la ventana con el título indicado y la incrusta en el formulario
            hWndApp = WinApi.FindWindow(null, titulo);
            if( hWndApp.ToInt32() > 0 )
            {
                WinApi.MoveWindow(hWndApp, 
                    0, 0, 
                    this.ClientRectangle.Width, 
                    this.ClientRectangle.Height - 4 - chkAjustarAuto.Height, 1);
                WinApi.SetParent(hWndApp, this.Handle);
            }
            else
            {
                hWndApp = IntPtr.Zero;
                Close();
            }
        }  
        //
        private void FormContenedor_Resize(object sender, EventArgs e) 
        {
            // Ajustar automáticamente el tamaño del contenido, si así se ha indicado
            if( hWndApp.ToInt32() > 0 )
                if( chkAjustarAuto.Checked )
                    WinApi.MoveWindow(hWndApp, 
                        0, 0, 
                        this.ClientRectangle.Width, 
                        this.ClientRectangle.Height - 4 - chkAjustarAuto.Height, 1);
        }  
        private void chkAjustarAuto_CheckedChanged(System.Object sender, System.EventArgs e) 
        {
            // Ajustar también al pulsar en el checkbox
            if( chkAjustarAuto.Checked )
                FormContenedor_Resize(null, null);
        }  
    }
}

Código de ejemplo (comprimido):

Fichero con el código de ejemplo: setParentNET.zip 28.4 KB


 


La fecha/hora en el servidor es: 23/12/2024 3:39:52

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024