Visual Basic Foro

Programación => Visual Basic 6 => Mensaje iniciado por: TOLO68 en Octubre 17, 2017, 02:30:56 pm

Título: Problema al leer la propiedad Left y Top de los UserControl
Publicado 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!!!!!









Título: Re:Problema al leer la propiedad Left y Top de los UserControl
Publicado por: LeandroA en Octubre 18, 2017, 08:56:25 pm
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.
Título: Re:Problema al leer la propiedad Left y Top de los UserControl
Publicado por: NEBIRE en Octubre 20, 2017, 08:40:04 pm
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).

Código: (VB) [Seleccionar]
]
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:
Código: (VB) [Seleccionar]
' 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:
Código: (VB) [Seleccionar]
' 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:
Código: (VB) [Seleccionar]
    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