Autor Tema: App.PrevInstance para UserControl en VB5-6  (Leído 4847 veces)

0 Usuarios y 1 Visitante están viendo este tema.

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
App.PrevInstance para UserControl en VB5-6
« en: Enero 16, 2017, 03:30:44 pm »
Hola a todo el foro, Tengo un preguntita.

En VB5 o 6 hay una funcion, si es que puede llamarse asi, App.PrevInstance, que obtiene un valor de true si ya hay una aplicacion igual en ejecución, me imagino que sabeis cual es.

Sabeis si se puede aplicar esto a un UserControl ????, o sea lo que necesito es que si coloco un control en el Form, no me deje colocar otro, lo consegui de una manera "chapuzera", que no se ni donde la tengo, pero no me agradaba mucho, era algo que lo eliminaba con SendKeys y la tecla Sup.

Bueno como se que por aqui hay un par de "Genios" del VB Clasico, a ver si podeis ayudarme.

Saludos.


LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #1 en: Enero 16, 2017, 04:03:33 pm »
Hola una respuesta rápida, ya que no se si es en un solo form o para todo el proyecto.

una de las formas seria

declarar en un modulo publico una varialbe, en este caso Public ParentName  as string.

y luego en el usercontrol
Código: [Seleccionar]
Private Sub UserControl_InitProperties()
    If ParentName = vbNullString Then
        ParentName = UserControl.Parent.Name
    Else
        Err.Raise 1001, , "No se permiten mas de un control"
    End If
End Sub

Private Sub UserControl_Show()
    ParentName = UserControl.Parent.Name
End Sub
en el ide va a dar error y te va a depurar, si es un ocx ya compilado, si no me equivoco, mostrar un cartel con el error y listo no se insertara el control.

ahora si vos quisieras uno por formulario y varios en el proyecto ParentName podria ser una colección o un array donde se almacenan los nombres de los formularios ya utilizados

Saludos.

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #2 en: Enero 16, 2017, 04:20:24 pm »
Esto esta mejor para la segunda opcion (solo uno por formulario pero varios en el proyecto.)

Private Sub UserControl_InitProperties()
    Dim o As Object, lCount As Long
   
    For Each o In UserControl.Parent
        If TypeName(o) = UserControl.Name Then
            lCount = lCount + 1
            If lCount > 1 Then
                  Err.Raise 1001, , "No se permiten mas de un control"
            End If
        End If
    Next
End Sub

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #3 en: Enero 16, 2017, 05:09:15 pm »
Oleeee!!!!!, a lo primero no me funcionaba porque siempre pego el codigo sin leer, jejejeje, me faltaba lo del modulo. Pero lo del array tambien puede estar bien aunque con el primer codigo suficiente.

Yo aparte le he añadido un codigo porque cuando me salia el Error, quitaba el primer control, y me salia otra vez el mensaje de Error al colocar el primero, tenia que hacer F5  para que fuera bien

asi que al quitarlo pongo la variable a vbNullString, y con esto ya no falla

Private Sub UserControl_Terminate()
ParentName = vbNullString
End Sub

' el vbNullString tambien lo he cambiado por "" , e iba perfecto

Muchas gracias Leandro.




TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #4 en: Enero 16, 2017, 06:15:57 pm »
Hola, acabo de probar el segundo codigo, y tienes razon es mejor y mas seguro, ademas puedo controlar la cantidad de controles maximos a poner, que esto posiblemente lo use luego.

Gracias de Nuevo

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #5 en: Enero 16, 2017, 08:24:08 pm »
El primero código que te ofrece Leandro, es más limpio... no exige recorrer todos los controles de un formulario en busca del tuyo...

Modificándolo un poco puede hacer lo mismo que el segundo...

En este código, puede especificarse un máximo por aplicación y un máximo por formulario (o contenedor si se cambia adecuadamente):

Este código va en un módulo:
Código: [Seleccionar]
Private colPresencias           As New Collection
Private p_MaxInstanciasXApp     As Long
Private p_MaxInstanciasXFrm     As Byte


' Devuelve la cantidad de instancias añadidas.
Public Property Get Count() As Long
    Count = colPresencias.Count
End Property

' Un valor <=0, permite ilimitadas instancias.
' Un valor mayor que 0, limita a ese número *
'   * (si aún no se alcanzó dicho límite, si ya se guardaron 10, y luego se limita a 5, seguirán existiendo 10)
Public Property Let MaxInstanciasXApp(ByVal X As Long)
     p_MaxInstanciasXApp = X
End Property

' OJO: Esta propiedad y la anterior, conviene establecerse SOLO cuando la colección no tiene ningún control.
Public Property Let MaxInstanciasXFrm(ByVal X As Byte)
     p_MaxInstanciasXFrm = X
End Property

   

' Intenta añadir una nueva instancia (solo si no se alcanzó el límite para ese formulario y el límite establecido para la aplicación).
Public Function Add(byval hWnd As Long) As Boolean
    Dim Intentos As Byte, sWnd As String
   
    On Local Error GoTo YaExiste
   
    If ((colPresencias.Count <= p_MaxInstanciasXApp) Or (p_MaxInstanciasXApp < 1)) Then
        sWnd = CStr(hWnd) & CStr(Intentos)
       
        Call colPresencias.Add(hWnd, sWnd)
        Add = True
    End If
    Exit Function
   
YaExiste:
    Err.Clear
    ' Si ya existe, se intentará más veces, cambiando la 'key' usada para añadirlo a la colección...
    If (p_MaxInstanciasXFrm > 0) Then
        Intentos = (Intentos + 1)
        If (Intentos < p_MaxInstanciasXFrm) Then
            sWnd = CStr(hWnd) & CStr(Intentos)
            ' irá sucediendo valores de key así:
            ' ejemplo para 4 instancias por formulario:
            '987654&0
            '987654&1
            '987654&2
            '987654&3 <--- esta será la ultima key para el form con hWnd: 987654.
            Resume
        End If
    Else
          Add = True ' ya fue añadido un control para este formulario, pero puede añadirse infinitos controles al formulario, no es necesario que se guarde en la colección, la constancia de cada uno.
    End If
End Function

' Intenta eliminar una instancia.
Public Sub Delete(ByVal hWnd As Long)
    Dim Intentos As Byte, sWnd As String
   
    Intentos = p_MaxInstanciasXFrm
    sWnd = CStr(hWnd) & CStr(Intentos)
    On Local Error GoTo NoExiste '0 ' el error ocurriría, si no existe...
   
    Call colPresencias.Remove(sWnd)
    Exit Sub
   
NoExiste:
    Err.Clear
    ' Si no existe, se intentará más veces, cambiando la 'key' que fue usada para añadirlo a la colección...
    If ((p_MaxInstanciasXFrm > 0) or (colPresencias.count) >0) Then
        Intentos = (Intentos - 1)
        If (Intentos > 0) Then
            sWnd = CStr(hWnd) & CStr(Intentos)
            ' irá intentando eliminar instancias (con valores de key así):
            ' ejemplo para 4 instancias por formulario:
            '987654&3
            '987654&2
            '987654&1
            '987654&0 <--- esta será la ultima key para el form con hWnd: 987654.
            Resume
        End If
    End If
End Sub

Si prefrieres tener un control más completo de todo el trabajo (como eliminar la colección), el código sería mejor portarlo a una clase (la clase debería declararse Privada), y en el módulo (bas) simplemente crear una única instancia que se comparte entre todos tus controles en la aplicación cliente de la siguiente forma:
Código: [Seleccionar]
private p_RefControlInstancias as new clsControlInstancias '<---- supuesto el caso de darle este nombre.
public property get ControlInstancias as clsControlInstancias
    set ControlInstancias = p_RefControlInstancias
end property

Este otro código va en el usercontrol, Eventos InitProperties (no en Initialize, porque aún no está disponible el sitio cliente) y en el evento Terminate:
Código: [Seleccionar]
Private Sub UserControl_InitProperties()
    ' Limitación del número de controles por aplicación y formulario...
    If (Module1.Count = 0) Then
        ' Recuerda un valor 0 o menor, indica sin límites...
        Module1.MaxInstanciasXApp = 0  ' ilimitado número de instancias por aplicación.
        Module1.MaxInstanciasXFrm = 1  ' pero limitado a 1 control por formulario
        ' en resumen  podría poner 200 instancias del control si pone 200 formularios...
    End If

    If (Module1.Add(UserControl.Parent.hWnd) = False) Then
        ' error 419: Permission to use object denied
        Call Err.Raise(419, UserControl.Extender.Name, "Solo se permiten X instancias del control por formulario. ----> e indicar también el límite total para la aplicación, si lo hay... ")
    End If
End Sub


Private Sub UserControl_Terminate()
    Call Module1.Delete(UserControl.Parent.hWnd)
End Sub



--------------------------------
p.d.: He añadido, algo de código más, por si quieres pasarlo a una clase para tener un control más exhaustivo del proceso... por ejemplo al destruir la clase, en el evento terminate, podrías vacíar la colección... en vez de dejarlo como tarea para el sistema.

También recomendarte que si esto lo vas a usar mucho (por ejemplo el código del módulo), sería muy acorde crear el módulo con el código, e incluso copiar al módulo y comentar el código que va en el usercontrol, y luego guardar el módulo en la ruta: "Unidad:\Programa File\Microsoft visual Studio\VB98\Template\Modules", obviamente cambiando lo que proceda en la ruta específica en que VS, está instalado en tu equipo. De estemodo cada vez que quieras añadirlo a un proyecto, cuando el dés a añadir módulo, tendrás presente esa plantilla, para elegirla entre las disponibles (es más cómodo que recordar donde lo guardaste en el disco y tener que buscarlo).

---------------------------------------------
p.d2.: Este código, es un código que se ha hecho rápido y no se ha probado a conciencia, por ello contiene algunos errores, por ejemplo, en el Usercontrol debe ejecutarse el mismo código en el evento ReadProperties, no solo en InitProperties, y le falta tratar error en el evento Terminate... Algunos mensajes más abajo, hay un código más robusto, listo para descargarse... el código sobre el módulo se ha movido a una clase.
« última modificación: Enero 17, 2017, 01:26:59 pm por NEBIRE »

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #6 en: Enero 16, 2017, 08:41:03 pm »
Nebire acabo de leer tu mensaje, muchas gracias, mañana lo pruebo que ya me voy a dormir, aqui en España ya son las 0:37, ya miro por cual me decido, si el de leandro o el tuyo.

O igual pillo la mitad de codigo de cada uno y lo mezclo con el audio mixer, igual sale una top model, volando con una bici al lado de ET, jajajajajaja

Bueno hasta la proxima


NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #7 en: Enero 16, 2017, 08:48:36 pm »
OK...
Pero recoge el código de nuevo, que lo he actualizado... en Delete... olvidé ponerte el caso de eliminar teniendo en cuenta los controles por formulario... ya está añadido.

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #8 en: Enero 17, 2017, 01:22:06 pm »
He tenido un momento para probar un poco a fondo el ejemplo, he corregido un par de cosas y lo he pasado a una clase, donde se lleva mejor...

He añadido código que permita ver las instancias que se crean y destruyen y las que no se permite crear...

Aquí una captura de ejmplo:


En esta otera captura, se ve el punto donde se definen los límites para poder crear instancias del control:
Un valor 0 o menor, implica poder crear instancias ilimitadas, un valor maor que 0, se ciñe a ese valor como límite.
Puede verse que hay 2 límites, si se pone ilimitado las instancias por App, pero se limitan las instancias por formulario... se pueden crear tantas como se quiera, pero solo el máximo indicado en cada formulario... si se pone un límite a las instancias por aplicación, cuando se  alcance, no deja añadir más, sin importar las que haya en tal o cual formulario.


Si en vez de limitar por formulario, se quiere limitar por contenedor (picturebox, Sstab, etc...), debe cambiarse la propiedad, en vez de parent.hWnd, puede usarse ContainerhWnd...


Descarga del proyecto (podría ir como un recurso para el foro):
http://workupload.com/file/jzEnHca 6Kb.

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #9 en: Enero 17, 2017, 03:44:50 pm »
Muchas gracias por los demas ejemplos, aunque con los dos primeros ya tengo lo que necesito, jejejeje, asi y todo los analizare para ver si hay alguna funcion que me interese para otras cosas.  :) :D ;D

Saludos desde Mallorca (España)

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #10 en: Febrero 08, 2017, 07:43:28 pm »
Buenas a todos
He hecho este codigo para las instancias de controles
A ver que os parece la idea
Si se supera el maximo de instancias, crea un control todo negro

----------------------------------------------------------

Dim NumberCtlNormal As Integer
Dim NumberCtlArray As Integer

Private Sub UserControl_Show()

    On Error Resume Next
    NumberCtlNormal = Val(Right(UserControl.Extender.Name, 1))
    NumberCtlArray = Val(UserControl.Extender.Index)
   
    If Val(Right(UserControl.Extender.Name, 1)) > 2 Then
        MsgBox "Demo, Max 2 Instancias"
        UserControl.BackColor = 0 ' "Demo"
        Exit Sub
    End If

    If NumberCtlArray > 0 Then
        MsgBox "Demo, No se permiten Arrays"
        UserControl.BackColor = 0 ' "Demo"
        Exit Sub
    End If

    CreateControl

End Sub

Sub CreateControl()
    UserControl.BackColor = vbWhite
    UserControl.Line (0, 0)-(100, 100), vbGreen
    'Resto de codigo................
    UserControl.Refresh
End Sub

Albertomi

  • Gigabyte
  • ****
  • Mensajes: 281
  • Reputación: +153/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #11 en: Febrero 08, 2017, 11:07:32 pm »

Estimado TOLO68


Por lo que entiendo quieres de alguna manera restringir el uso de tu control, lo cual no me parece malo.


Particularmente no me parece que sea una buena práctica que lo restringas en tiempo de diseño, deberías de restringirlo en tiempo de ejecución.


De esta manera el que use tu control tendrá la libertad de desarrollar su aplicación por completo, hasta testearla en tiempo de diseño; pero cuando trate de comercializar su aplicación tu control se ejecutará en tiempo de ejecución y es ahí donde tu control le muestre mensajes de advertencia o deshabilite cada una de las instancias del control hasta que te paguen


Saludos, desde algún lugar de Lima-Perú

Saludos, desde algún lugar de Lima-Perú

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #12 en: Febrero 09, 2017, 06:40:46 am »
Gracias Albertomi, el ejemplo que puse era para saber si os parecia bien el sistema.
Leandro y Nebire ya me pusieron por aqui algunos ejemplos tambien, y me gustaron bastante
Estos Controles en principio quiero venderlos, o por lo menos intentarlo, :)
Lo de hacerlo en "tiempo de ejecución" esta bien si es para una DEMO de una aplicación que haga yo mismo u otro programador, (por ejemplo un programa de dibujo, contabilidad o el tipo que sea), para el usuario final.
Pero lo de hacerlo en "tiempo de diseño" en un Control, es porque si me los compra alguien, seran programadores para meterlos en las aplicaciones que hagan, pero una vez creada la aplicacion donde esta este control, al estar en tiempo de ejecucion no pedirá un registro por cada aplicacion donde este este control (de hecho algunos controles que venian con programas que descargaba de internet, si intentaba usarlos yo en VB me decia algo asi, "no tiene la licencia para poder usar este control en tiempo de diseño".
Lo de las instancias lo quiero para la DEMO del control, para que el programador solo pueda poner 1 o 2 instancias(dependiendo del control) en cada aplicación, y asi poder probar como funciona. Pero si compra la licencia, poder poner todas las instancias que quiera en "tiempo de diseño" para ir creando la aplicacion.
Lo de la licencia es solo valida para un computador (el que usa el programador), ya que se basa en leer un serial del mismo, (todo este sistema ya lo tengo hecho y funcionando)

Espero haberme explicado bien :)

Gracias a todos.

Saludos desde España.

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #13 en: Febrero 09, 2017, 07:01:12 pm »
Sí, en un caso así, es mejor hacer una versión Demo, que aparte de la limitación de instancias, tenga también alguna limitación de propiedades... muy elementales...

por ejemplo :
Código: [Seleccionar]
private sub Usercontrol_Initialize
     Usercontrol.backcolor = vbmagenta
end sub

public property get BackColor as Ole_color
    BackColor= usercontrol.Backcolor
end property
      public property let BackColor(byval X as Ole_Color)
                call Limite("BackColor")
      end property

private sub Lmite(byref PropLimitada as string)
   msgbox "La propiedad " & proplimitada & " está limitada de escritura en esta demo..."
end sub

La razñon de limitar alguna propiedad obedecería a que si el control demo es completo, con la única limitación de 1-2 instancias, por proyecto-formulario-contenedor, podría aún así satisfacer las necesidades de alguien para su programa.
Dejando un fondo rosa, para el control, como que va a desentonar en exceso en el programa que alguien desarrolle, luego es más probable que desista de usarlo...

Por supuesto las propiedades elegidas para limitar la funcionalidad, no debe anular que pueda probar la funcionalidad del control. Si básicamente el control es gráfico, y para probarlo bien es requisito que pueda cambiarse la propiedad BackColor, elige otra/s propiedades al caso.
Por ejemplo limitar el tamaño, o hacerlo fijo a un tamaño gigante o minúsculo, tal que alguien vea inaceptable tomar ese tamaño para el control como parte de su programa...

Ejemplo:
Código: [Seleccionar]
private sub Usercontrol_Resize
     Usercontrol.size(Ancho, Alto) ' Definir valores de ancho y alto, por ejemplo: 6000,3000 en twips.
     msgbox "La versión DEMO del control tiene un tamaño fijo y limitado..."
end sub
Obviamente, eres tú quien debe definir que sería un tamaño pequeño o grande para el control en la versión de demostración...

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:App.PrevInstance para UserControl en VB5-6
« Respuesta #14 en: Febrero 09, 2017, 08:09:00 pm »
Gracias NEBIRE

Si, esta idea de las limitaciones tambien la tenia en mente, por ejemplo uno de los controles es un display hexadecimal, parecido al ke llevan los multimetros, el cual puede tener desde 1 a 32 digitos, una limitacion seria que solo fuera de 2 digitos por ejemplo, o que los numeros solo pudieran ser de color verde.

Se me habia olvidado tambien que en la demo, cada cierto tiempo, (2 o 3 minutos), sale un form Modal, diciendo algo asi, "Esto es una version demo, si quiere dejar de ver esta pantalla registre el control" o pulse continuar para seguir con la demo.

O sea que si no cierra el form no puede seguir trabajando, :)

La cuestion es poner "travas" por decirlo de alguna manera, que puedan probar el control totalmente, pero de manera incomoda

Ya me diras que opinas de esto del form, diciendo que es una demo

Bueno gracias por la respuesta, Saludos