Visual Basic Foro
Programación => Visual Basic 6 => Mensaje iniciado por: TOLO68 en Octubre 17, 2017, 02:30:56 pm
-
Hola a todo el Foro
Espero que esteis bien!!!
Tengo un problema con la propiedad Left y Top de los UserControl en VB6
Por algunos foros he leido que eso es un bug de Microsoft que nunca lo arreglaron
En cambio con el Control PictureBox de VB6 si va bien
-------------------------------------------------------
Con VB6 creo un proyecto nuevo Estandar EXE
luego le agrego otro proyecto Control ActiveX
la propiedad ControlContainer del control = True
para que pueda contener otros
por defecto la propiedad de ScaleMode tanto del Form
como del UserControl son Twips
Al Form le agrego un UserControl, y dentro de este UserControl
otro UserControl ( Como Meter un PictureBox dentro otro PictureBox )
como se puede ver en la imagen adjunta
(https://s1.postimg.org/2y2yvnf7ej/User_Control_Scale_Mode.jpg) (https://postimg.org/image/2y2yvnf7ej/)
entonces el left y top del usercontrol1 y usercontrol2 es de 240
ya que el segundo esta dentro del primero
hasta aqui todo correcto
el problema viene aqui
en las propiedades del Form pongo ScaleMode en pixels
en las propiedades del UserControl pongo ScaleMode en pixels
entonces el left y top del UserControl1 da 16(medida en pixels),
que esta bien porque 16 * 15twips = 240 twips
pero....
el left y top del usercontrol2 (el que esta dentro del usercontrol1)
sigue dando la medida de left y top en twips (240),
cuando deberia darla en pixels porque el scalemode del usercontrol ahora esta en pixels
una idea que se me ocurrio es leer el left/15 o top/15
pero no funciona en el usercontrol que hay en el Form porque desde el form lee bien
y da 1,06 que son los 16 que me lee bien /15
a no ser que ponga el scaleMode del Form en twips
otra idea es que de alguna manera leer el contenedor asi como
if UserControl.extender.container.name = usercontrol then
left=left/15
end if
y ya que estoy
Hay alguna manera de saber el tipo de objeto contenedor ?, porque con
UserControl.extender.container.name
da Form1,Form2, etc...
simplemente que me diga si es un Form o PictureBox, o sea el name pero sin el numero
porque asi lo podria arreglar dividiendo /15 solo si el contenedor es el UserControl
con el codigo de ejemplo que he puesto arriba
lo vi algun dia en una web pero no le di importancia y ahora no lo encuentro, :(
Bueno muchas gracias, espero haberme explicado bien
Saludos a Todos!!!!!
-
Hay alguna manera de saber el tipo de objeto contenedor ?, porque con
UserControl.extender.container.name
da Form1,Form2, etc...
simplemente que me diga si es un Form o PictureBox, o sea el name pero sin el numero
MsgBox TypeName(UserControl.Extender.Container)
en los form te da el nombre pero en los controles el tipo de control
de todas formas nose es medio chivo el tema de las escalas, yo optaría para la solución hacerlo con apis siempre te va a dar el valor en pixels. GetParent(usercontrol.hwnd) y luego si no me equivoco el api getwindowRect o ClientToScreen o ScreenToClient no recuerdo bien ahora.
-
Como dice Leandro, con las API siempre suele resolverse con píxels.
De todos modos, si en diseño pones siempre tus usercontrol en píxels (Scalemode = 3, vbpixels) y los formularios también, serán pocas ocasiones donde no se obtengan dichos valores.
Los valores siempre son devueltos en el scalemode del contenedor. Luego cambiar en tiempo de ejecución el 'sacalemode', suele generar problemas salvo que recurras a usar las propiedades 'ScaleLeft, ScaleTop, ScaleWidth y ScaleHeight'... junto con el método Scale, para generar tu propio sistema de cordenadas (que no interesa salvo que realmente se desee generar un sistema de cordenadas específico).
Pero nota que por ejemplo para imagenes el scalemode 'por defecto' suele ser vbHimetric (ni siquiera vbTwips)...
Aunque poseer una referencia de escalas es muy útil, casi toda esa funcionalidad en vb6 es un lastre si no se sabe utilizar y resulta confuso, porque no está bien documentado.
Otro modo es poner las funciones/propiedades en el propio usercontrol, para reclamar la escala...
(con esto debes dejar el scalemode en twips durante diseño, es decir no cambiarlo, ya que si lo pones en vbpixels, luego traduciría el valor de pixels a pixels, es decir no traduciria nada, erróneamente).
]
Public Function EscalarXToPx(ByVal Medida As Single) As Single
EscalarXToPx = UserControl.ScaleX(Medida, UserControl.ScaleMode, vbPixels)
End Function
Public Function EscalarXFromPx(ByVal Medida As Single) As Single
EscalarXFromPx = UserControl.ScaleX(Medida, vbPixels, UserControl.ScaleMode)
End Function
Public Function EscalarYToPx(ByVal Medida As Single) As Single
EscalarYToPx = UserControl.ScaleY(Medida, UserControl.ScaleMode, vbPixels)
End Function
Public Function EscalarYFromPx(ByVal Medida As Single) As Single
EscalarYFromPx = UserControl.ScaleY(Medida, vbPixels, UserControl.ScaleMode)
End Function
[/code]
Determinada funcionalidad es provista por el contenedor para sus propios controles. Ya que por sí mismo los controles no tienen forma clara de proveerla o bien el propio contenedor le basta tener una copia para manejarlo convenientemente haciendo inutil que el propio control la posea. Dichas propiedades y métodos son las llamadas 'extender'... Left, Top, Width, Height, Move son parte de ellas, provistas por el contenedor, algunas de ellas, solo aparecen durante diseño, otras todavía están disponibles en ejecución. Ergo otra solución es crear tu mismo tales propiedades, obviando las que provee el contenedor e invocando por dentro al contenedor...
Aquí un ejemplo para Left:
' Valores devueltos y entregados en píxels...
' ...pero el usercontrol mantiene el scalemode en twips (u otro valor)
Public Property Get LeftUc() As Single
LeftUc = UserControl.ScaleX(UserControl.Extender.Left, UserControl.ScaleMode, vbPixels)
End Property
Public Property Let LeftUc(ByVal x As Single)
UserControl.Extender.Left = UserControl.ScaleX(x, vbPixels, UserControl.ScaleMode)
End Property
' TopUc
'WidthUc
'HeightUc
Finalmente otras funciones que te ayuden a entender la diferencia:
' Valores a entrar en el scalemode que tenga el control.
Public Sub MoveInTwips(ByVal Left As Single, Optional ByVal Top, Optional ByVal Width, Optional ByVal Height)
With UserControl.Extender
If (IsMissing(Top)) Then Top = .Top
If (IsMissing(Width)) Then Width = .Width
If (IsMissing(Height)) Then Height = .Height
Call .Move(Left, Top, Width, Height)
End With
End Sub
' Valores a entrar en píxeles
' (internamente se converten a la escala que contiene (vbtwips))
Public Sub MoveInPixels(ByVal Left As Single, Optional ByVal Top, Optional ByVal Width, Optional ByVal Height)
With UserControl.Extender
Left = Me.EscalarXFromPx(Left)
If (IsMissing(Top)) Then
Top = .Top
Else
Top = Me.EscalarYFromPx(Top)
End If
If (IsMissing(Width)) Then
Width = .Width
Else
Width = Me.EscalarXFromPx(Width)
End If
If (IsMissing(Height)) Then
Height = .Height
Else
Height = Me.EscalarXFromPx(Height)
End If
Call .Move(Left, Top, Width, Height)
End With
End Sub
' Valores en el scalemode que tenga el control.
Public Sub Size(ByVal Width As Single, Optional ByVal Height As Single)
If (IsMissing(Height)) Then Height = UserControl.Height
Call UserControl.Size(Width, Height)
End Sub
Desde el formulario podrías probarlo con algo como:
Dim m As single
Me.Print CStr(UserControl1.EscalarXToPx(UserControl1.Left))
Me.Print CStr(UserControl1.Left)
Me.Print CStr(UserControl1.LeftUc)
' Valores son twips
Call UserControl1.Move(800, 150, 180, 240)
' Valor dado es píxel, que se convierte a twips, elresto de parámetros mantiene su valor actual.
Call UserControl1.MoveInPixels(150)
' Estas medidas en píxels se convierten a twips
Call UserControl1.MoveInPixels(120, 150, 180, 240)
' Ahora los valores son twips, resultando como con 'Move'...
Call UserControl1.MoveInTwips(800, 150, 180, 240)
UserControl1.Left = 200
UserControl1.LeftUc = 200