You are on page 1of 8

Especial

Docking
Meter un formulario
dentro de un control
Picture
Para poder acoplarlo a otros controles de un formulario.
También se explica cómo meter otra aplicación "dentro"
del Picture, (en el ejemplo se usa el bloc de notas)

Publicado el 25/Ene/2004
Revisión del 26/May/2004

En este ejemplo te voy a mostrar cómo hacer que un formulario se pueda


"meter" en un control PictureBox, con idea de poder simular acoplamiento
de formularios con otros controles, es decir, tener un formulario con varios
controles, por ejemplo un ToolBar, StatusBar, un TreeView, etc. y en otro de
los controles tener un formulario.

Normalmente tendremos un formulario principal, el cual puede tener un


menú principal y también en la parte superior un ToolBar. Por otro lado, en
la parte inferior también tendremos un StatusBar. En el centro, (en la parte
principal del formulario), tendremos dos "paneles", uno a la izquierda y otro
a la derecha. En el panel izquierdo podríamos insertar un control al estilo
del Outlook con una serie de botones de opciones, etc. y en el panel
derecho podríamos tener el contenido de otro formulario de nuestra
aplicación.

Todo esto son "deseos", ya que en el ejemplo que te voy a mostrar, todos
estos "posibles" controles serán del tipo PictureBox, aunque realmente el
único que "debería" ser un PictureBox es el panel de la derecha, el que
contendrá el "otro" formulario. Pero, para no complicar demasiado el
ejemplo, he preferido dejarlos todos como controles Picture. Sigue las
"recomendaciones" de los comentarios del ejemplo y verás que te resultará
fácil usar otros controles.

Como te decía, el ejemplo tiene dos "trucos".


El primero es: incrustar (o meter) un formulario dentro de un control de
tipo Picture.
Para lograr esto, usaremos una (realmente varias) función del API de
Windows: SetParent.
De forma simple te diré los pasos que habría que seguir:
Tendremos dos funciones (procedimientos) que se encargarán de meter el
formulario dentro del control y otro que ajustará el tamaño del formulario
al que tenga dicho control.

Este es el código de esos dos procedimientos, los cuales estarán declarados


en el mismo formulario principal, el que hará de contenedor:

' Mostrar el formulario indicado, dentro de picDock


Private Sub dockForm(ByVal formhWnd As Long, _
ByVal picDock As PictureBox, _
Optional ByVal ajustar As Boolean
= True)
' Hacer el formulario indicado, un hijo del
picDock
' Si Ajustar es True, se ajustará al tamaño del
contenedor,
' si Ajustar es False, se quedará con el tamaño
actual.
Call SetParent(formhWnd, picDock.hWnd)
posDockForm formhWnd, picDock, ajustar
Call ShowWindow(formhWnd, NORMAL_eSW)
End Sub

' Posicionar el formulario indicado dentro de picDock


Private Sub posDockForm(ByVal formhWnd As Long, _
ByVal picDock As PictureBox, _
Optional ByVal ajustar As
Boolean = True)
' Posicionar el formulario indicado en las
coordenadas del picDock
' Si Ajustar es True, se ajustará al tamaño del
contenedor,
' si Ajustar es False, se quedará con el tamaño
actual.
Dim nWidth As Long, nHeight As Long
Dim wndPl As WINDOWPLACEMENT
'
If ajustar Then
nWidth = picDock.ScaleWidth \
Screen.TwipsPerPixelX
nHeight = picDock.ScaleHeight \
Screen.TwipsPerPixelY
Else
' el tamaño del formulario que se va a
posicionar
Call GetWindowPlacement(formhWnd, wndPl)
With wndPl.rcNormalPosition
nWidth = .Right - .Left
nHeight = .Bottom - .Top
End With
End If
Call MoveWindow(formhWnd, 0, 0, nWidth, nHeight,
True)
End Sub

Para usar estos procedimientos necesitaremos unas declaraciones de


funciones del API de Windows, así como unos tipos definidos:

'-----------------------------------------------------
-------------------------
' APIS para incluir las ventanas en un PictureBox
'-----------------------------------------------------
-------------------------
'
' Para hacer ventanas hijas
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, ByVal hWndNewParent As
Long) As Long
'
' Para mostrar una ventana según el handle (hwnd)
' ShowWindow() Commands
Private Enum eShowWindow
HIDE_eSW = 0&
SHOWNORMAL_eSW = 1&
NORMAL_eSW = 1&
SHOWMINIMIZED_eSW = 2&
SHOWMAXIMIZED_eSW = 3&
MAXIMIZE_eSW = 3&
SHOWNOACTIVATE_eSW = 4&
SHOW_eSW = 5&
MINIMIZE_eSW = 6&
SHOWMINNOACTIVE_eSW = 7&
SHOWNA_eSW = 8&
RESTORE_eSW = 9&
SHOWDEFAULT_eSW = 10&
MAX_eSW = 10&
End Enum

Private Declare Function ShowWindow Lib "user32" _


(ByVal hWnd As Long, ByVal nCmdShow As
eShowWindow) As Long
'
' Para posicionar una ventana según su hWnd
Private Declare Function MoveWindow Lib "user32" _
(ByVal hWnd As Long, ByVal x As Long, ByVal y As
Long, _
ByVal nWidth As Long, ByVal nHeight As Long, ByVal
bRepaint As Long) As Long
'
' Para cambiar el tamaño de una ventana y asignar los
valores máximos y mínimos del tamaño
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECTAPI
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type WINDOWPLACEMENT
Length As Long
Flags As Long
ShowCmd As Long
ptMinPosition As POINTAPI
ptMaxPosition As POINTAPI
rcNormalPosition As RECTAPI
End Type
Private Declare Function GetWindowPlacement Lib
"user32" _
(ByVal hWnd As Long, ByRef lpwndpl As
WINDOWPLACEMENT) As Long
Ahora, simplemente haremos que el formulario se "meta" en el contenedor
y que al cambiar el tamaño del formulario, también se cambie el tamaño
del formulario "incrustado".
En el siguiente código se supone que el formulario que queremos mostrar
se llama "Form2" y que el control que contendrá dicho formulario se llama
Picture1.
También tendremos un botón que se usará para mostrar dicho formulario.
Para que se vea el "efecto", tendremos a la izquierda un segundo control,
en este ejemplo es otro PictureBox, pero, como te comentaba antes, puede
ser cualquier otro control que queramos tener acoplado a la parte izquierda
del formulario. En este caso ese control se llama picIzq y haremos que se
acople a la izquierda, asignando a la propiedad Align el valor vbAlignLeft.

Private Sub cmdMostrarForm2_Click()


'
' Asignar el Tag del formulario para saber que
está incluido en el Picture
Form2.Tag = valorDock
'
dockForm Form2.hWnd, Picture1, True
End Sub

Private Sub Form_Resize()


' ajustar el tamaño del Picture al del formulario
' sólo si no está minimizado
If WindowState <> vbMinimized Then
' ajustar el Picture a todo el formulario
Picture1.Move picIzq.Width, 0, ScaleWidth -
picIzq.Width, ScaleHeight
End If
End Sub

Private Sub Picture1_Resize()


' sólo si no está minimizado
If WindowState <> vbMinimized Then
' posicionar el botón en el centro
With cmdMostrarForm2
.Left = (Picture1.ScaleWidth - .Width) \ 2
.Top = (Picture1.ScaleHeight - .Height) \
2
End With
'
Dim oForm As Form
'
For Each oForm In Forms
' El tag del formulario incluido en el
picture tendrá el Tag asignado
' con el valor "valorDock"
If CStr(oForm.Tag) = valorDock Then
posDockForm oForm.hWnd, Picture1
End If
Next
End If
End Sub

En la parte de declaraciones del formulario tendremos una constante


llamada valorDock que simplemente nos servirá para saber si un
formulario está o no incluido dentro del picture.
Cuando queramos "meter" un formulario en el picture, asignaremos esa
constante a la propiedad Tag y seguidamente llamaremos al procedimiento
dockForm indicándole el formulario que queremos meter, además del
control en el que queremos que se meta.

Cuando cambia el tamaño del formulario, el Picture1 se ajusta a ese nuevo


tamaño. En este código sólo tenemos en cuenta que hay otro control a la
izquierda, pero no arriba ni abajo, en caso de que tengamos otros controles
arriba y/o abajo, tendremos que tener en cuenta esos controles a la hora
de posicionar y dar tamaño al Picture1.

En el evento Resize del Picture1 se centra el botón y posteriormente


recorremos todos los formularios que tenemos en la aplicación para
comprobar si hay alguno que tenga ese valor "mágico" que indica que el
formulario debe estar dentro del Picture. En caso de que así sea, llamamos
al procedimiento posDockForm para que ajuste el tamaño y posición del
formulario "incrustado".

En las siguientes capturas, puedes ver el formulario principal sin y con otro
formulario dentro.
El formulario "normal"

El formulario con el otro formulario "incrustado"

Y eso es todo.

Para saber cómo agregar una barra que te permita cambiar el tamaño de
los dos paneles, échale un vistazo a este otro ejemplo.

Nos vemos.
Guillermo

Pulsa aquí si quieres bajarte el código con el proyecto completo:


dockVB6.zip 3.74 KB

En el código de completo se muestra cómo posicionar el botón Cerrar del


segundo formulario en la parte inferior derecha.

Si quieres ver funcionando este ejemplo y el de cambiar el tamaño de los


paneles centrales, puedes bajarte el código completo, en el que se incluye
un ejemplo de cómo poner cualquier ventana (de la que sabemos el caption
o título) en un picture: DockSplitVB6.zip 5.42 KB
Nota del 26/May/2004:
En el código de ejemplo tengo puesto como programa a incluir, el bloc de
notas, pero como mi sistema operativo está en inglés, utilizo "Untitled -
Notepad", así que tendrás que cambiar el nombre al que corresponda en
español, que me imagino que es: "Sin título - Bloc de notas".
En el zip ya está incluido un comentario en el sitio que hay que hacer el
cambio.
Este "bug" (si es que se le puede llamar así), ya me lo reportaron hace
tiempo, pero ahora no recuerdo quién fue... cuando encuentre el mensaje,
lo pondré...
Gracias a los que reportáis los fallos que de vez en cuando cometo... ¡que
yo no soy perfecto!

El formulario con el Notepad dentro de un picture.

QUIERES SABER MAS SOBRE VISUAL BASIC?


ENTRA A www.recursosvisualbasic.com.ar

You might also like