Título: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 19 Junio 2018, 19:31 pm Hola a todos:
Esta pregunta parece obvia y simple, pero me está volviendo loco.. Tengo un proyecto con 14 Forms, en el principal (Main) tengo un PictureBox donde se grafican lineas, círculos,etc. Hasta aquí todo correcto, pero este PictureBox, contiene imágenes, TextBox, y ListBox. Todo funciona OK, pero he tenido que poner 30 Labels que necesito en tiempo de diseño, por que si pongo solo una, por ejemplo Label1 con índice 0 Label1(0), y luego cargo mas en tiempo de ejecución con un For-Next, Load Label1(i), etc, me sale un error "Uso no válido de la propiedad" y no me explico por que. En el resto de los Foms si me deja hacerlo, y no me lo explico. Alguna ayuda? Gracias. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 20 Junio 2018, 03:09 am No queda claro, cual pueda ser el problema, la información proporcionada es insuficiente.
A primera instancia pùdiera ser que ya tuvieras el label1(1) en el formulario, pero el mensaje del error (y el nº) sería uno distinto... ¿¿¿Puedes poner el código de la función donde lo cargas (y así se pueda ver exactamente sobre qué linea recáe el error)??? Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 2 Julio 2018, 18:30 pm Hola NEBIRE:
Gracias por responder. El código donde lo cargo, es simplemente For i = 1 to N Load Label1(i) Next Pero es que el error no está en el código, este label, y varios mas, están dentro de un PictureBox llamado "picContenedor", que ademas tiene varios Image, TextBox, otros PictureBox, ListBox,Shapes, Lines, etc. Resumiendo, en este "picContenedor" es donde se dibujan una serie de planos de partes de estructuras metálicas, que algunos parámetros de dibujo dependen de otros Foms que calculan y devuelven datos para dibujar los planos. Debido a la complejidad de todo esto, es imposible que adjunte código, por que lo que yo creo es que ese PictureBox "picContenedor" que utilizo esta corrupto y por eso no me deja utilizar Load ni para Labels, Image, Textbox ni nada. Pero todos los demás Forms (13 en total), que algunos también tienen PictureBox si me permiten utilizar Load. Quiero hacer una prueba de copiar todo el contenido de este "picContenedor" en otro nuevo llamado por ejemplo pic, luego borrar "picContenedor" y renombrar pic por "picContenedor" De esta forma al menos podría verificar si el problema es de "picContenedor" o de alguno de los elemento contenidos en el. Pero no veo ninguna forma de seleccionar todo el contenido de "picContenedor" copiarlo y pegarlo en el nuevo pic, en tiempo de diseño. Alguna idea? Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 3 Julio 2018, 22:53 pm Ya, pero es que ese mensaje de errror, no se puede generar así como así...
VB6, tiene un límite de controles gráficos que se pueden cargar en un solo formulario... tal como señalas que tienes muchos objetos... solo puedo asumir que el problema esté por ahí... Prueba antes de cargar con load... un msgbox que indique cuantos controles tienes cargados... Código
y repite lo mismo, justo antes de que se origine el error, aver si viendo la diferencia de controles entre el antes y el después queda claro algo más... Haz copia del formulario antes de nada (y su *.frx asociado)... Una forma de reproducir dicho picturebox, es crear un nuevo proyecto vacío... y 'copiar el picturebox' y pegarlo al formulario de ese nuevo proyecto (si lo pegas en el mismo formulario-proyecto, corres el riesgo de que se las colecciones de controles aumenten su índice, pero pegado a un nuevo proyecto, cada control se mantiene con su índice (y tabindex) correctamente... Si la copia resultó sin problemas, crea otro nuevo proyecto ahora corta el picturebox y pégalo allí... guarda cambios en los 3 proyectos, y luego la copia que pegaste en el proyecto nuevo previo, muévelo al proyecto original... y vuelve a guardar cambios... si sigue dando problemas sin más detalles será difícil saber qué es... No puedes dar al menos el nº de error?... aquí tengo la ayuda en ingés, y no aparece ningún texto similar (traducido)... De todos modos, por lo que me cuentas, creo que estás cometiendo un grave error al querer manipular gráficos complejos con controles de usuario... dichos controles realmente ni lo son, no poseen un handle propio, si no el del contenedor y sobrecargas innecesariamente el contenedor... aunque este tipo de 'controles' son muy livianos, precisamente por no tener un manejador propio... Lo adecuado es tener un 'hiddenSurface', una clase que alberga un objeto bitmap, donde vas dibujando con las API de GDI32 y luego tras el dibujado lo vuelcas como gráfico al picturebox... allí si que no importa si luego tienes unos pocos controles line, o label, pero 4, 8, 12, 20, pero ya, no 150... Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 4 Julio 2018, 17:45 pm Hola de nuevo:
He copiado el Picture, y lo he pegado en un único Form en un proyecto nuevo. desde el Form_Load con esto: n=Me.Controls.Count, me dice que tiene 246 objetos,. Este picture ocupa todo el ancho del Form y el alto menos 100. He puesto un label nuevo "Label1" con indice 0 En en un Sub MouseDown del picture copiado, he puesto: For i =1 to 60 Load Label1(i) Next Y lo carga sin problemas, por lo tanto no es el Picture el que genera el error, y me preguntas por el nº de error... no hay nº de error, simplemente el mensaje dice "Uso no válido de la propiedad" si mas. Me sugieres esto: Lo adecuado es tener un 'hiddenSurface', una clase que alberga un objeto bitmap, donde vas dibujando con las API de GDI32 y luego tras el dibujado lo vuelcas como gráfico al picturebox... Esto no se lo que es, pero no tengo problemas de memoria ni de velocidad, ten en cuenta que todo se dibuja en tiempo real en el Picture, utilizando solo Picture.Line, y Picture.Circle, solo dibujo rectángulos con y sin fill, líneas y arcos, y sitúo objetos Image, Picture con Bitmap cargados en diseño, Label, Textbox y algunos Shapes y Lines creados en tiempo de diseño, que sitúo con sus coordenadas, y los hago visibles o no. Luego el proceso de dibujado es muy complejo, hace cientos de operaciones de trigonometría, pero todo va muy rápido. No creo que pueda averiguar donde está el problema, por eso decidí, crear en tiempo de diseño, 30 TextBox, 40 Labels, que son el máximo de textos o parámetros que puede necesitar el programa. De nuevo gracias por tu interés y ayuda, alguna idea que pueda comprobar?. Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 4 Julio 2018, 18:45 pm Para que te hagas una idea, he subido un pequeño vídeo, una imagen vale mas que mil palabras. Este es ellink:
https://youtu.be/fwodS_yRjTk Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 4 Julio 2018, 19:41 pm Un poco más tarde miro el vídeo, ahora tengo solo justo un ratito libre...
Bien... ya me has contestado... Todo apunta a que el problema es el que asumía... 246 controles en el form... luego en efecto la causa es alcanzar el límite de controles para el formulario... pero, vamos ahora a encasillarlo exactamente... En la función que te origina el error, coloca algo de código similar a esto: Código
Lós métodos gráficos, circle, line, no son problema, pero ojo, no confundas los métodos gráficos con los 'controles de usuario': line, shape, label, image y frame, todos ellos son 'irreales', pero ocupan puesto como control de usuario... A la noche que llegue a casa, miro el vídeo y te pongo un ejemplo de operativo... Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 5 Julio 2018, 10:39 am Al final se me hizo muy tarde...
He visto el vídeo, y aunque sirve para hacerse una ídea d elo que estás haciendo, no aporta detalles sobre el problema. Quiero decir que no recala en ningún momento en el error que reportas. Te decía que cuando debes utilizar gráficos a mansalva, los gráficos conviene que sean 'dibujados', es decir métodos y no 'controles'. Los controles ocupan espacio de memoria, pero más alla de eso, el uso indiscriminado puede hacerlo lento y caer en el error que te sugrge. estoy convencido que has alcanzado el límite máximo de controles que s epermite para un formulario (ahora mismo no recuerdo cual es, ya que es algo que uno nunca considera que se va a dar y lo acaba olvidando (el valor exacto)). Para usar métodos gráficos, lo más adecuado es recurrir a las API gráficas que proveen GDI32 o al menos simplemente GDI, indistintamente de que uno se provea sus propios métodos cuando se quiera hacer algo específico que no esté prtevisto, o que no satisfaga por algna razón. El inconveniente de usar las API, es que evidentemente se necesita aprender a conocerlo y eso lleva su tiempo. Especialmente si uno nunca se ha acercado a usar APIs, puede sonarle a chino, la forma de funcionar y no entender ciertos detalles por que se alejan (de alguna manera), de la forma relativamente sencilla (y a veces tortuosa) en que funcionan las cosas en VB6. Otro forma, es que sin salirse de vb6, cree uno mismo determinada funcionalidad, por ejemplo crear un control de usuario transparente, que provea no solo funcionalidad gráfica, sino también alguna colección, para almacenar métodos gráficos, entonces de ese modo, un solo control, podría tener por ejemplo 200 métodos gráficos, usando un único control de usuario... y por ejemplo, el control podría contener dibujado toda esa escalera sobre sí, podrías tener luego otro control (otra instancia del mismo control), para la leyenda, o bien otros métodos gráficos en el mismo control... Asumo que básicamente operas en un entorno 2D... aunque se puede hacer también un entorno 3D, e incluso ir más alla, con raytracing y tal... se sale de la envergadura de ayuda para unos foros, aunque siempre se puede dar orientación si la precisas... ... La colección podría almacenar una estructura (o clase) con los siguientes tipos (así a bote pronto): Código
Dibujar sería una función que simplemente recibe el objeto y mediante un 'select case' invoca a la función específica que se encarga de dibujar la orden específica... Nota como esta función también es pública, para permitir dibujar una orden que no conste en la colección, peor que a cierto momento pueda interesar. Lógicamente también podrán invocarse externamente los métodos gráficos, sin necesidad de que existan como un 'objeto'... Código
Y algunas funciones... en este ejemplo, varias funciones que definen un objeto sin ambigüedad, finalmente invocan al mismo (privado)... Código
También puede suceder CurrentX y CurrentY se guardan como propiedades que no aparecen en el visor de propiedades (deben retirarse, para estar disponibles solo en tiempo de ejecución), es adecuado, para trazar por ejemplo polilíneas... Una polilínea, sería simplemente una colección de puntos, + 1 orden gráfica que defina el primer punto, el color, ancho, etc... Esto te permite obtener donde terminó de dibujar un objeto para (por ejemplo) seguir dibujando en un punto específico, algo que Código
Como hablamos de una colección lógicamente hacen falta dos cosas para ello, además operaciones en la colección: añadir, eliminar, vaciar... Aquí un ejemplo para añadir: Código
También es adecuado contar con otras operaciones menos frecuentes, pero igualmente útiles... Aquí remplazar (una existente por otra que se entrega), y una que intercambia el orden de dos (el orden almacenado supone el orden en que se dibujan). Código
También puede suceder que uno no quiera dibujar en orden todo, sino solo ciertas órdenes... puede construirse funciones que recorriendo la colección solo dibuje determinadas funciones, si es complicado y exige ciertos condicioonantes muy variables, se puede reclamar una enumeración de la colección y entonces en la entrega evaluar si debe o no dibujarse: Código
Se ha mostrado algún evento... el control puede proveer algunos eventos, como cuando termina de redibujartodo, por si se precisa hacer algo desde fuera, como activar algún botón, etc... Código
Con el valor activo, puedes desactivar que un método gráfico no se dibuje la próxima vez, etc... Como ves, un control así permite almacenar muchos métodos gráficos contiene todos los datos precisos para dibujar, pero no alcanza ni sobrepasa límites impuestos, además permite aislar adecuadamente unos gráficos de otros, por ejemplo un único control podría contener todos los métodos gráficos para dibujar la escalera... añadiendo además por ejemplo una función GrEscala(byval Escala as single), podría tomar toda la colección de métoso y rescalar su 'ancho y alto' o sólo a aqellos métodos que sean de cierto tipo... igualmente moverlos todos de sitio sería desplazar el control, pero mover a determinados objetos de sitio, podría hacer otra función que recorra la colección para añadir restar a las cordenadas un valor específico... ...y fíjate que sin embargo todo ese código, está en VB6 "puro", sin APIs, recurriendo a las APIs, sería más potente... (gráficamente VB6 es bastante pobre, no es esforzaron demasiado durante el diseño de VB, de dotarle de buneas funcionalidades) pero asumo que no dominas el mundo de las API. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 5 Julio 2018, 14:01 pm Hola NEBIRE:
Tu explicación es simplemente magistral, y ojala yo supiera hacer lo que me sugieres, de todas formas he copiado y salvado todo el código por que voy a hacer pruebas a ver que consigo y de paso aprendo, pero para este proyecto esta solución es impracticable por que nada del código que tengo me serviría, pero al menos ya se cual es el problema, estoy reduciendo algunos objetos, pasándolos a nuevos Forms, pero como ya no necesito añadir mas objetos y como está el programa funciona perfecto, incluso en PC's con poca memoria, pues se queda así. Pero has mencionado esto que si me sería muy interesante: Citar por ejemplo crear un control de usuario transparente, que provea no solo funcionalidad gráfica, sino también alguna colección, para almacenar métodos gráficos, entonces de ese modo, un solo control, podría tener por ejemplo 200 métodos gráficos, usando un único control de usuario... y por ejemplo, el control podría contener dibujado toda esa escalera sobre sí, podrías tener luego otro control (otra instancia del mismo control), para la leyenda, o bien otros métodos gráficos en el mismo control... Como se hace un control de usuario transparente, que sería el que tendría el Picture que tengo donde se dibuja todo, y entonces sería reemplazar en todo el código en nombre del Picture. No se si esto sería abusar de tu generosidad y empeño que has puesto en ayudarme, o en su caso algún link?. Yo voy a buscar a ver si encuentro algo por donde empezar. Muchísimas gracias por tu ayuda. Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 6 Julio 2018, 19:33 pm ... Como se hace un control de usuario transparente, que sería el que tendría el Picture que tengo donde se dibuja todo, y entonces sería reemplazar en todo el código en nombre del Picture. ... No es difícil, son solo un cúmulo de condiciones concretas que como mínimo hay que mantener inalterables o bien, los cambios que se hagan deben ser consecuentes...Mañana que tengo un poco más de tiempo libre, te hago uno con la funcionalidad mínima y adecuada al caso, del que partir... Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 9 Julio 2018, 21:03 pm Pues de nuevo...
Muchísimas gracias, tu ayuda esta siendo inestimable. Estoy depurando muchas cosas que tenía mal o que se podían implementar mejor. Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Serapis en 10 Julio 2018, 03:25 am Saque un tiempo el fin de semana para hacer un sencillo ejemplo de prueba, pero me faltó tiempo para probarlo y subirlo...
Aunque se puede hablar largo y variado sobre la trnasparencia, vamos a ir al grano... En los controles d eusuario de VB6, hay dos formas de dibujar: A - La primera es usar el evento paint del propio usercontrol... cuando una parte dle control queda expuesta y luego liberada, salta un evento paint, que da la ocasión de redibujar el control. Así que en éste caso todo lo que se deba dibujar debe estar dentro de ese evento. B - Un defecto del método propio, es que en generla se procede a dibujar por completo el control aunque solo hay sido expuesta una pequeña área. VB6, provee un método alternativo. Cuando se pone la propiedad Autoredraw a TRUE, una vez pintado, VB6, hace una especie de 'capura' del gráfico, luego cuando se tapa y expone, VB6, solo pega parcialmente el área recién descubierta en vez de redibujar todo. Naturalmente cuando haya que hacer cambios, hay que redibujar el control al completo por lo general... Es importante saber que si se pone Autoredraw a TRUE, el evento paint, no salta, porque VB6 se encarga de repintar el área que lo precise, sin embargo o mejor dicho queda a cargo del programador actualizar convenientemente el gráfico cuando convenga... Aclarado el tema, podemos crear una función llamada por ejemplo "Redibujar", si autoredraw está a false, saltará el evento paint, allí simplemente innnvocamos a esta función y listo. Y si Autoredraw está a TRUE, simplemente desde nuestro código debemos invocar dicha función cuando necesitemos actualizar el gráfico... Vamos a lo primero, algunas propiedades para controlar y que sirvan de ejemplo... ' OK: Devuelve o establece si el color del fondo del display es transparente y deja ver lo que hay bajo él. Código
Añade tus funciones gráficas, en general pinta con el 'ColorTinta', digamos que es el color por defecto para pintar... Es útil disponer también de una propiedad: "ColorPreset". que no es otra cosa que un array de colores... Si son fijos los estableces en código, si son elegibles por el usuario, que el mismo los pueda remplazar, aunque siempre conviene que existan por defecto... en generla basta con 16 colores, digamos 15 para el array + el 'color Tinta' (el valor por defecto). La ventaja de un color preset, es que si tiene spongamos 300 líneas que dibujar y 35 de ellas tienen un color morado y decides cambiarlo a amarillo, en vez de recordar que líneas son es preferible asignar un color preset a cada línea, luego cuando se queira cambiar el color, la propiedad detecta que ha cambiado y al dibujar lo hará con el nuevo color... sin tener que recorrer las 300 líneas para asignarle un nuevo color... así pasamos por ejemplo de la estructura: Código Es preferible usar una estructura ligeramente diferente... Código
IndexColor apunta a un índice en el array de ColorPreset, así cambiar el color a 52 líneas no exige más que cambiar el color al índice concreto, y no a todas las 52 lineas recorriendo las 300... Una vez hecho el cambio, al dibujar sería algo como: Código
La propiedad ColorPreset, requiere dos parámetros, el índice y el color que se asigna a dicho índice: Código
Esto sin embargo es mejorable en dos aspectos. Lo primero es que al poner dos parámetros en una propiedad, ya no puede aparecer en la "ventana de propiedades" durante el diseño y por tanto durante diseño, la aplicación cliente, no podrá poner reasignar colores salvoque se añada una página d epropiedades, que es complicarlo solo para esto. Hay una técnica muy sencilla, que admeás puede también aplicarse a otros objetos que posena índice y varia spropiedades... y consiste en desdoblar la propiedad en dos... por un lado el índice y por otro el color, como se muestra a continuación: Código Ahora ya aparece esa propiedad en la 'ventana de propiedades', para cambiar un color del array, basta cambiar el array y luego asignar un color... Antes decía que tenía dos carencias, una ya ha quedado subsanada, la otra es que anque tenemos 16 colores, no necesariamente deben estar todos en uso, sin embargo al cambiar un color del preset, forzamos un redibujado... algo caro si resulta que nada está dibujado con ese color. Algo más optimo es mantener un array paralelo que lleve la cuenta de 'objetos' que usan cada color... Cuando se añade un nuevo 'objeto gráfico', se añade 1 a la cuenta, si se elimina (o se cambia de índice asignado de color), se resta 1 para ese índice (y se suma uno al otro si cambió de índice). Entonces ahora la última propiedad puede mejorarse así: Código Ahora es más eficiente, al coste de mantener convenientemente actualizado el array con la cuenta de objetos que mantienen tal o cual color... Claramente si el número de líneas a dibujar son pocas, redibujarlo todo cada vez, no sea pesado y a cambio uno se olvida de la complejidad añadida por la eficiencia, en cambio sin son algunas miles d elínea sa dibujar... redibujarlas todas cuando ningún objeto utiliza dicho color, no es ideal... En fin uno debe decidir que conviene mas dado el caso de que vaya a usarse muchas o pocos objetos gráficos... Todo lo previo es para optimizar operaciones, ahora veremos unamanera de reutilizar el mismo control para 3 tareas diferentes... - Polilínea: Son varios puntos conectados entre sí, formando un único objeto gráfico, más o menos complejo... Se dibuja una línea de un punto a otro, si uno no está activo se pasa al siguiente (es decir el que noes ´te activo se ignora). - Múltiples líneas inconexas entre sí. Es decir cada línea tiene dos puntos que definen su inicio y su fin. Cad alínea comienza en un índice par como X1,Y1 y termina en el siguiente punto delarray (punto impar), como X2, Y2. - Poligonos: Cada polígono se compone de varios vértices. realmente también puede considerarse múltples polilíneas, ya que ser polígono, exige que la última línea del polígono se conecte a la primera. Un poligono dibuja de un punto a otro, hasta encontrar uno no activo, momento en que se considera que acaba e polígono (o polilínea en múltiples polilineas). Todo ello soportado con una misma y única colección o array (luego un par de párrafos al respecto). Aquí, código para dar salida a todas esas ideas... Código
Los campos para otras propiedades: - p_ptActual: Sirve para usar la misma técnica anterior y poder asignar línea durante diseño, sobre la ventana d epropiedades... va bien cuando son pocas, si son muchas es preferible usar un fichero externo y proveer una función de carga d elos datos... - p_ptInicio, p_ptFinal... aunque se comentan brevemente en su declaración, sirven para dibujar en un bucle... por defecto una vale 0 y la otra el último punto del array/colección, pero en la práctica, puede ser usado como separador de objetos, por ejemplo podrías tener olilíneas entre el indice 0 y el 60, línea ssueltas entre el índice 61 y 130 y poligonos (de pocos lados cada uno) entre el punto índice 131 y el 540, y otro objeto más complejo entre el índice 541 y el 650 (por ejemplo)... así si precisas redibujar solo las líneas, estbalece inicio y fin a los valores 61 y 130 respectivamente y luego con polilinea = DIBUJA_INCONEXA, si está establecda una propiedad AutoRedibujar , ya haría el redibujado, y si no puede crearse una función publica que admita dichos parámetros... Ahora la función de dibujado que aplica las diferentes formas de dibujado: Código
El campo "p_ptEvento" da pie a otra propiedad... por eejmplo dado un indice que se debe dibujar con un color o ancho distintos, alllegar aél se lanza el evento, y se responde cambiando el color y/o el ancho de dibujado de la línea y/o también el próximo punto donde parar... en este ejemplo de función no he hecho uso del array ColorPreset, ya puse un ejemplo muy simple más arriba de como usarlo, aquí se ha puesto para el caso, p_ColorTinta, ya que la estructura definida algo más arriba, no aloja un color, si no otro campo interesante "Activo", para señalar qué hacer o para que sirve o como funcionar con dicho punto de formas diversas... Y como ya me he extendido más d elo que pretendía, finalmente podrmeos dibujar con transparencia... Respeta lo que en esta función aparece y lo que modifiques que sea en una función aparte o bien enciam o debajo de la función usada para todo el dibujado... Código
pongo alguna imagen... y como ya se me hace tarde para más, mañana (o pasado, si no tengo tiempo mañana) comprimo el proyecto de ejemplo y lo subo a alguna página de descarga... comentaré alguna cosa más antes... (https://i.imgur.com/VOFePwL.png) (https://i.imgur.com/Ds52Rp4.png) (https://i.imgur.com/aQsFFIl.png) Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 10 Julio 2018, 09:52 am Perfecto, me espero a que subas todo esto.
Muchas gracias. Un saludo. Título: Re: No puedo utilizar Load Label en PictureBox Publicado por: Fran1946 en 16 Julio 2018, 13:36 pm Copiado todo este código
Espero a lo que subas. Muchas gracias de nuevo. Un saludo. |