• Viernes 3 de Mayo de 2024, 04:49

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Nebire

Páginas: 1 ... 3 4 [5] 6 7 ... 29
101
Visual Basic 6.0 e inferiores / Re: API - WaitMessage
« en: Jueves 25 de Marzo de 2010, 15:39 »
Bueno, tenía un hueco en dicho momento, pero llevo unos días bastante ocupado y todavía estaré bastante ocupado una semana más por lo menos, pero lo anoto y en cuanto encuentre un tiempo libre te lo hago.

Mientras intenta ver si logras resolverlo por tu ingenio.
Eso si, cuando hablo de eventos, no necesariamente estoy hablando de los eventos de la API, los de vb valen también.

Te pongo un resumen de como es el procedimiento (con el poco tiempo que ahora mismo tengo), aunque se pueda implementar con las variaciones que cada uno considere.

Primero debemos decidir, si la aplicación ha de tener capacidad de decidir si 'autoesperar' cuando solicita una petición o si esta actúa como un servicio y por tanto siempre espera hasta que otra aplicación la active o la pare.

Sea como fuere hay que establecer un pequeño protocolo para que una aplicación comunique a la otra, lo mejor para ello es disponer de unos datos que ambas aplicaciones sepan entender. Para esto lo mejor es inyectar (encapsular) todo el protocolo en una clase de la que ambas aplicaciones tienen una instancia.

Esta clase portaría toda la funcionalidad y tendría al menos 2 eventos. Y tendría 2 campos que por comodidad podríamos llamar cliente y servidor, cliente sería un puntero a la aplicación que tiene que esperar y servidor sería un puntero a la aplicación que en un momento dado debe enviar el mensaje esperado. El tipo de mensaje esperado debería ser un mensaje de usuario (WM_USER), y el código recibido es lo que la clase trata en profundidad, por ejemplo un valor x enviado al servidor pone al cliente en modo de espera y estará así hasta que el servidor le envíe un valor de mensaje Y, esto se le comunica al servidor mediante el evento a tal fin, una vez que el servidor devuelva por referencia si acepta o no la petición delcliente, la clase pondría al cliente en espera... como ya se indicó esto sería usando una función de callback, cuando se reciben mensajes se comparan con el estado establecido en la clase (esperando=true ?), si es true, se comprueba si es wm_user y si lo es si tiene el 'valor esperado', si es así cambiamo estado (esperando=false), ahora todos los mensajespasan, antes todos rebotaban (exit sub). En esta parte, pued eusarse alguna función de Wait de la API, si cumple nuestros propósitos o bien dejarlo tal como lo hemos descrito, no se notará mucha diferencia de rendimiento,  ya que las funciones wait hacen esto mismo, interponer una función callback y filtrar.

Los filtros a este nivel son ra´pidos porque los mensajes no seprocesan, sólo se filtran, es el procesarlos (todos) lo que produce  una caída de rendimiento si luego van a ser descartados.

Las funciones wait, no obstante están un 'nivel' más arriba pues, es decir estarían colocados antes que cualquiera de nuestras funciones callback, en una posible cascada, de hecho están en el nivel donde se decide que mensajes se envían o no a una aplicación.

102
Sobre los Foros de SoloCodigo / Eliminar hilo
« en: Jueves 25 de Marzo de 2010, 15:14 »
Alguien puede eliminar el hilo que está en el siguiente link: viewtopic.php?f=39&t=42542

La razón es que es el foro de vb6 y el tema no sólo no habla de vb6, ni siquiera habla de programación, el autor lo ha colocado ahí a propósito, a juicio mío actuando de mala fe, pués sabe que no es el sitio que le corresponde y aún así se lo pasa por ... excusándose de que si no es el sitio adecuado que 'alguien' lo mueva.

Si todos hiciéramos igual los administradores no tendrían descanso, escribo en cualquier foro y digo lo mismo: ''sé que no va aquí, que alguien lo mueva...' . Eso es actuar de mala fe, especialmente cuando se sabe es menos tolerable que cuando se ignora.

Por lo demás el tema es puramente spam, pero a mi eso ya me importa menos, sino se elimina que al menos se retire de allí.

103
General / ELIMINAR - ES SPAM
« en: Jueves 25 de Marzo de 2010, 15:06 »
Eliminar

Este tema es 100% spam.
No tiene absolutamente nada que ver con vb6, ni siquiera con programación.

No te exime, la excusa de:
Citar
Yo sé que aquí no va este post, pero no encontré en qué otro ponerlo, en dado caso, si me pudieran ayudar a moverlo.
...salvo que admitas públicamente que eres tonto. Porque se requiere o bien ser tonto, para ponerlo aquí o bien mala fé al querer tratarnos a los demás de tontos con esa estupidez de excusa para justificarte y darte autobombo.

104
Visual Basic 6.0 e inferiores / Re: TransOCX (Frames Transparentes)
« en: Jueves 18 de Marzo de 2010, 17:25 »
Se me olvidó decirte que hay un par de líneas en el código de ejemplo que realmente no son necesarias, pero que se incluyeron para que se viera paso a paso como sucede

las líneas son las que están a ambos lados de paintpicture, las ...Tr(7).ShowClient , las puedes quedar comentadas.
Código: Visual Basic
  1.  
  2. Private Sub Form_Resize()
  3.     MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."
  4.     Stop  ' pulsa la TECLA F8 para continuar, paso a paso
  5.     With Picture1
  6.         Tr(7).ShowClient = True  ' desactivamos, para que luego al activarlo 'lea' el nuevo contenido que enmascarar
  7.         Call .PaintPicture(Me.Picture, 0, 0, , , .Left, .Top, .Width, .Height, vbSrcCopy) ' pegamos un nuevo contenido gráfico
  8.         Tr(7).ShowClient = False  ' ahora al activarlo crea una máscara para el contenido gráfico, que ahora coincide con el del fondo.
  9.     End With
  10. End Sub
  11.  
  12.  

Hay también otra forma de verificar como el control asume la máscara del contenedor... cambiándolo de contenedor, prueba este ejemplo haciendo los cambios oportunos.
Código: Visual Basic
  1.  
  2. Private Sub Form_Resize()
  3.     MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."
  4.     Stop  ' pulsa la TECLA F8 para continuar, paso a paso
  5.  
  6.     Set Frame5(0).Container = Me         ' al mudarlo al formulario, enmascara con el contenido gráfico del mismo,
  7.     Set Frame5(0).Container = Frame2  ' al mudarlo de nuevo al frame del que procede, nuevamente se vuelve a enmascaras, con su contenido gráfico.
  8. End Sub
  9.  
  10.  

...y una solución algo más simple aún a base de unas líneas extras respecto del código que tengas actualmente, saca los frames de dentro del frame, es decir que el contendor sea el formulario, sin anidamiento, pero sitúalos en la posición actual y el que hasta ahora el contenedor envíalo alplano z del fondo. Con esto consifues lo que necesitas visualmente, sólo deberás tener en cuenta otros detalles, como por ejemplo cuando tengas que ocultar lo que antes era el frame padre..., haz la operación inversa, calculas o guardas la posición que toca dentro del frame anidado y le devuelves como contenedor el original
ejemplo, en el evento resize del  formulario llamas a esta función :
Código: Visual Basic
  1.  
  2. Private Sub Form_Resize()
  3.      Call Desanidar(Frame5(0))
  4. End Sub
  5.  
  6. Private Sub DesAnidar(ByRef f As Frame)
  7.     Dim x As Single, y As Single
  8.     x = f.Left + f.Container.Left
  9.     y = f.Top + f.Container.Top
  10.     Set f.Container = Me
  11.     f.Move x, y
  12.     f.ZOrder 0
  13. End Sub
  14.  
  15. Private Sub ReAnidar(ByRef f As Frame, ByRef O As Control)
  16.     Dim x As Single, y As Single
  17.     x = f.Left - O.Left
  18.     y = f.Top - O.Top
  19.     Set f.Container = O
  20.     f.Move x, y
  21.     f.ZOrder 0
  22. End Sub
  23.  
  24. ' oculta o muestra el frame2, al hacerlo arrastra con ello también al que tiene anidado...
  25. ' OJO: usar un check no  es muy bueno (se pone sólo como ejemplo) porque al hacer resize lo desanidamos, y por tanto puede no corresponderse con el estado del check... lo que movería el frame afectado a unas cordenadas incorrectas.
  26. Private Sub Check3_Click()
  27.     If Check3.Value = 1 Then
  28.         Frame2.Visible = True
  29.         Call Desanidar(Frame5(0))
  30.     Else
  31.         Call Reanidar(Frame5(0), Frame2)
  32.         Frame2.Visible = False
  33.     End If
  34. End Sub
  35.  
  36.  
Este último método creo que es más cómodo para ti, porque lo diseñas completamente como tu quieres, y en ejecución posiblemente sólo necesites  hacerlo (desanidar) una vez...

105
Visual Basic 6.0 e inferiores / Re: hora llegada fichero a filelistbox
« en: Jueves 18 de Marzo de 2010, 13:05 »
Si no tienes mucha idea de programación, lo adecuado es que adquieras conocimientos básicos.

Un bebé, primero aprende a gatear, luego aprende a andar y ya de mayor podrá pilotar un avión si le place, pero no puede saltarse los pasos previos, porque incurrirá en graves lagunas de conocimiento, como la importancia del equilibrio y el sentido de la orientación.

Respecto de tu otro problema, si ya tienes un timer, aprovéchalo para localizar entre los ficheros la hora de creación del mismo, el que tenga la hora más reciente según tu caso.

Por otro lado es un trabajo tonto, porque sobrecargas al procesador en una tarea que lo más probable es que sea del todo inútil. Si tienes 5 o 6 ficheros vale, pero si el número va creciendo, pongamos 50 a la hora, te encontrarás con que al cabo de un día, cada que el timer se active debe repasar entre una lista de 1200 archivos, multiplica por 30 al cabo de un mes. Lo acertado es que el propio envío de FTP activara un servidor indicando el nombre y ruta del archivo, eso evita la necesidad de usar un timer para buscar entre los que ya hemos mirado 500 veces en el día para ver si es el archivo más reciente. Si ya le hemos preguntado si era el último 500 veces que necesidad hay de volverlo a hacer.... no retienes memoria sin gastar memoria ?...

Si no sabes como resolverlo, te sugiero una idea usando tu timer de una forma al menos más efectiva:
Cada fichero que llegue debe acceder sólo a una única carpeta, realmente llegarán 2 archivos, el deseado de nombre por ejemplo: xxxx2345.xxx y un 2º llamado: ruta2345.txt , importa que estén emparejados por el nombre, para no ser confundidos por otro envío muy reciente aún sin procesar. El 2º archivo contiene la ruta donde se señala que el fichero recibido debe ir a parar y que tu usarás para enviarlo a la ruta destinada (si es procedente, obviamente).
Por tanto el timer, lo que hace es cuando vence su período, comprobar si existen ficheros en dicha carpeta de Entrada, si hay alguno, lo toma y el equivalente con mombre basado en el: rutaXXXX.txt, no hace falta consultar hora, la hora es Ahora mismo, una vez hecho esto lees el archivo txt  y verificas la ruta de destino, aco seguido mueves el archivo a la carpeta de destino,  eliminas el txt y actualizas en el label el fichero recibido (con su ubicación definitiva). Si hay más archivos en la carpeta de entrada, los procesas todos, carece de importancia si uno llegó 1 segundo antes que el otro. 2 archivos son enviados, A fue enviado a las 10:59 y B fue enviado a las 10:55 , A llegó a las 11:00 y B llegó a las 11:01, aunque B llegó después fue enviado antes, es probable que tardaramás debido a su tamaño, o a otras causas... si no hemos accedido a la hora de envío, menos importante será la hora de llegada.

En determinados casos puede ser crítico, cierta prioridad, pero desde luego siempre será más relevante la prioridad de hora de envío que la de llegada.

106
Visual Basic 6.0 e inferiores / Re: TransOCX (Frames Transparentes)
« en: Miércoles 17 de Marzo de 2010, 18:01 »
He hecho un pequeño proyecto de prueba, y la causa queda clara... la propiedad zorder no interviene para nada, da igual el orden Z

El control enmascara el contenedor con el contenido gráfico del contenedor padre. Esto es lo que hace el control, y lo hace bien.
El problema está en lo que tú asumes que hace, pero que no hace. Me explico.

Tu tienes una ventana que tiene una imagen de fondo,  tienes un control lamémosle frame1, y dentro de este otroframe, llamémosle frame2. Bien cuando se establece la propiedad autofindcontrol (o se cambia cualquier otra propiedad) internamente el control invoca a crear la máscara, esta se crea con el contenido gráfico (el ORIGINAL) del contendor padre donde está alojado el control transpar... Veamos, le toca el turno al frame1, crea una máscara con el contenido gráfico del formulario ... ahora le toca el turno al frame2 crea una máscara con el contenido gráfico del frame1, pero el contenido gráfico del frame1 no es lo que visualmente 'se ve', lo que se ve es el resultado del contenido gráfico y la máscara, así si el frame1 tuviera un fondo rojo, el frame2 crea una máscara para ese contenido gráfico (en la practica una cantidad de bytes cuyo contenido es el byte RED, rojo).

Dicho de otro modo, el control notiene capacidad de anidamiento. al control le falta 'un hervor', para que fuera más útil. La propiedad autofindcontrol, localiza el contenedor padre, si tuviera una propiedad que realizara la función como señala el nombre ContainerMask, entonces permitíría asignar el contenedor del que crear la máscara, así para el frame2 en vez de enmascarar contenido del frame1 podríamos decirle:
frame2.autofindcontrol=false
set frame2.ContainerMask = Me (el formulario)
Entonces daría un resultado correcto. como no tiene una propiedad similar, entonces la solución pasa por colocar el contenido gráfico directamente tú sobre el contenedor, para que así el contenedor  anidado, tome dicho contenido para enmascarar...

Hay un problema, los controles frame, no implementan una interfaz que es la que proporciona el método paintpicture (no tiene propiedad hDC)...
Por tanto tu solución pasa por una entre varias alternativas, en vez de usar frames, utiliza controles picture, y un label para emular el control frame, o bien crea un usercontrol que imite un frame pero que tenga propiedad picture.

Te envío una copia del proyecto que he realizado para probarlo... en el mismo verás la solución aplicada sobre un picture...
El proyecto inicialmente recoge 3 imágenes, que las va alternando para que se vea como enmascara el contenido. Observarás como cuando se hace un resize, se realiza... también debe suceder cada vez que cambie el contenido gráfico (es decir la imagen del formulario), para verificar bien esto se ha provisto  2 botones "demostración" . Pulsa preferiblemente el botón 'Demostracion2', par aalternar lasimágenes y siguiendolo paso a paso ver como se va actualizando. ... si tienes dudas pregunta.
Tal vez debas modificar la referencia del control transpar (para localizar el componenete) ... ya que yo lo tenía localizado sin registrar en la misma carpeta del proyecto... búscalo si te lo pide...

p.d.: antes de ejecutar el proyecto, elimina la línea (del procedimiento Form_Load)  me.show o bien carga en diseño una imagen en el formulario... olvidé limpiar las líneas extras... ya que quité la imagen, para que el proyecto apenas pesara, cargándolas desde windows, al empaquetarlo...

107
Los archivos se escriben siempre detrás... no se puede escribir al principio así 'alegremente'. Para hacerlo hay que mover hacia abajo todo el resto del contenido.

Lo cual puede no ser sensato, cuando el archivo adquiere cierto tamaño. Si tenemos un archivo de 40Mb. y deseas añadir Hola al principio, debes mover los 40Mb., 4 caracteres atrás, luego insertar 'Hola' en la 1ª posición... esto es ineficiente. Es lo mismo que si tienes un camión de arena, traes un cubito de arena de la playa y tu quieres que quede debajo del todo, el único modo de hacerlo es tirarlo al suelo y depositar luego todo el camión de arena existente encima de este cubito, no podrás hacerlo sin mover todo el otro contenido, lo cual es desproporcionado.

Puedes hacer algo más útil, puedes crear un fichero tipo índice cuyo contenido es parecido a los chunks de los archivos IFF.
Código: Visual Basic
  1.  
  2. private type Bloques
  3.     Numero as long
  4.     Tamaño as long
  5. end type
  6.  
  7. Nº Comentario Long
  8. TamañoComentario long
  9. Comentario string
  10.  
El chunk, utiliza la estructura para saltar número a numero por el fichero, una vez localizado el chunk deseado, toma el texto asociado... además los chunks pueden estar incluso desordenados, por si eliminas alguno aún sirva el mismo código.
Esta estructura se repite a lo largo del archivo, si tu ahora necesitas acceder al comentario 54, para tomarlo y hacer con él lo que quieras, puedes ir recorriendo el archivo, hasta encontrar el comentario 54... empiezas por el principio o por el punto actual si queda más cerca y los chunks están ordenados

 Aquí, en el código, partimos delas siguientes suposiciones: empezamos por el principio, el fichero existe y está abierto, no sabemos si existe el comentario 54. y el fichero puede tener los chunks desordenados. Por supuesto en ningún caso hay chunks repetidos (el número de bloque es único para cada chunk)

Código: Visual Basic
  1.  
  2. dim ff as integer   ' canal del fichero abierto
  3. public function Buscarcomentario(byval Numcomentario as long) as string
  4.        dim bl as bloque           ' estructura de tipo bloque
  5.        dim puntero as long      ' puntero de avance sobre el fichero.
  6.        dim comen as string    ' contendrá el texto que se ha de devolver
  7.  
  8.       ' esta búsqueda es comenzando desde el punto inicial, que suponemos el byte 1 del fichero
  9.          puntero=-7  ' nótese que al entrar al bucle sumaremos 8, por lo que el será 1, cuando leamos el fichero  
  10.          
  11.         on local error goto sale  
  12.         do while bl.Numero < Numcomentario   ' suponemos numerocomentario basado en 0, si se basa en 1 hacer los cambios pertinentes
  13.                puntero=puntero + bl.Tamaño + 8    ' busca el puntero a la siguiente estructura  
  14.                get  #ff,puntero,bl        ' obtenemos la siguiente estructura del fichero
  15.         loop  
  16.         comen= space$(bl.tamaño)
  17.         get #ff,puntero + 8, comen
  18.         Buscarcomentario = comen
  19.  
  20.         exit function
  21.        sale :   ' el error se producirá cuando se alcancé EOF #ff, no se encontró el número de comentario deseado.
  22.         err.clear    
  23. end function
  24.  
  25.  

Una vez tu tengas fácil acceso a los comentarios, puedes volcarlos a un control (en la interfaz de usuario) delante del todo o donde quieras, porque ya no estarás moviendo tropecientos millones de bytes....

108
Visual Basic 6.0 e inferiores / Re: API - WaitMessage
« en: Miércoles 17 de Marzo de 2010, 14:38 »
El problema que planteas está resuelto, otra cosa es que tu no veas claramente como se logra.

La respuesta son los eventos. Un evento es precisamente eso, compartimentar código de ejecución...
Y efectivamente se necesita una función callback para 'estudiar' los eventos y cuando suceda el deseado producir el evento.
Dado que tu quieres que no se precesen en resto de eventos mientras no llegue un evento de tipo determinado, debes cerrar en la función de callback el reenvío hacia adelante de todo los eventos.

Te pondré un sencillo ejemplo que puedas calcar y hacer los cambios que precises... si sigues interesado, dame un par de días, que encuentre una hora disponible para realizarlo...

p.d.: también puedes optar por la función SignalObjectAndWait y / ó WaitForSingleObject.

109
Visual Basic 6.0 e inferiores / Re: TransOCX (Frames Transparentes)
« en: Martes 16 de Marzo de 2010, 22:35 »
Puedes subir el control a algún sitio donde pueda descargarlo y probarlo ?.
Dado que no es un control de VB si falla es necesario verificar el propio control...

110
Visual Basic 6.0 e inferiores / Re: API - WaitMessage
« en: Martes 16 de Marzo de 2010, 03:58 »
Tienes un pequeño error de concepto respecto de lo que supones que ocurre
Desde el momento que sale el msgbox, como es una ventana modal, cuando el usuario pulsa el botón para cerrar la ventana modal, acontece en ese momento un mensaje, por tanto ya hay mensajes en la cola y por tanto waitmessage, deja de ceder el control a otros hilos. ...Aparte de los mensajes de mover el ratón (mousemove)...

El problema lo tienes porque tu sólo chequeas si en la cola hay eventos de sendmessage sin procesar, te devuelve 0, es decir no hay mensajes de ese tipo en la cola, pero hay mensajes serán de otro tipo, pero los hay... coloca el mismo código  dentro de un evento click de un botón verás como 'z' devuelve diferentes valores del load del  formulario... que aparte tiene pendiente un show...

prueba con esto y lo verás tu mismo.
Código: Visual Basic
  1.  
  2. Private Sub Form_Load()
  3.     const TodosLosEventos = 191
  4.    
  5.     z = GetQueueStatus(TodosLosEventos)
  6.     sigue = WaitMessage
  7.     WaitMessage
  8.     MsgBox sigue & " Ha pasado " & z
  9. End Sub
  10.  
  11.  


WaitMessage lo puedes poner para recibir un tipo de datos boolean... si te resulta más cómodo.

111
Visual Basic 6.0 e inferiores / Re: Crear un horario de cursado
« en: Lunes 15 de Marzo de 2010, 15:25 »
Bueno, previamente quiero aclararte que este tipo de post (al menos a mi) me da pereza contestarlos, porque quedan tantas cosas al aires, que en primer lugar genera una respuesta muy larga y en segundo lugar es muy probable que tras darte una respuesta luego venga un aluvión con un 'pequeño ciento' de preguntas secundarias al respecto y uno no tiene tanto tiempo libre como para responder a cada detalle que además es muy probable que sean muy básicas.
Pese a todo, no puedo pasar tu mensaje por alto y quiero darte por lo menos una orientación....

Aunque dices tener claro la tabla 'horarios' TblHorarios... sin embargo me parece que mejor repases todo el post para hacer los cambios oportunos... el post en sí, es una 'pequeña  lección' de como diseñar tablas y compartimentar los campos en las tablas necesarias y como estas se relacionan entre si.

__________________
PRIMERA PARTE:
Bien a partir de aquí conviene que tengas la primera tabla, para las materias, y ahora te explico como debe estar organizada esta tabla:
Tabla: 'TblMaterias
* Id_Materia: valor autonumérico y único
* Nombre: el nombre que define la materia
* Descripcion: Texto ampliado que describe la materia. este campo no es estrictamente necesario

Si hay alguna particularidad más común a todas las materias, pero que cada una tiene la suya, debe usarse un campo para esa propiedad. En cambio si hay una propiedad que como el horario, lo tienen todas las materias, pero evidentemente no es fijo por la materia sino por la carrera, no puede ser asignado a esta tabla.

A esta tabla se le asocia otra muy parecida llamada materias por carrera. Este tipo de tablas son 'tablas Indice'
Tabla: 'TblaMateriasCarrera
* id_Carrera: utiliza el msmo valor que la carrera en cuestión, para la que se oferta la asignatura.
* Id_Materia: no puede ser autonumérico, sino relacionado con la materia en cuestión, lo mismo que id_Carrera

Nota, al mantener 2 ids, podemos referenciar las materias de una carrera sobre esta tabla, y la descripción única de cada materia se toma de la tabla Materias. Al usar id_Carrera habrá registros cuasi duplicados * , pero aumenta la efectividad, ya que permite filtrar los registros para una materia dada o para una carrera dada .
Es decir podemos preguntar (crear 2 funciones) que carreras usan tal materia o que materias tiene una carrera. Un hipotética respuesta de estas 2 consultas:
Carreras que tiene la asignatura matemáticas: Física, Química, Política, Medicina, Biología...
Materias que tiene la carrera Medicina: Matemáticas, química orgánica, Aparatos médicos, Fisiología, Neurología, Medicamentos...

* Por otra parte los duplicados son finitos(el numero de carreras nnunca será de millones de modo que tenga que haber millones de registros duplicados). al describir la tabla horarios parte de esta tabla se entenderá mejor.

Hay que crear una tabla llamada carrera. Los detalles se relacionan a continuación:
Tabla: TblCarrera
* Id_Carrera: valor autonumérico y único.
* Nombre: El nombre descriptivo y completo de la carrera en cuestión.
* Aula: nombre o número de la estancia donde se los alumnos deben acudir, también puede ser una descripción... "escalera 2, frente al patio principal"... o algo más criptico: "E2,P2,N5" (escalera 2 piso 2º puerta nº 5", o incluso una imagen autodescriptiva señalando con una flecha la ubicación exacta...
* Planning: indica los días en que esta carrera es cursada, muy probablemente sea siempre de lunes a viernes sin excepción y sin ausencias, si es así para todas las carreras este campo se puede omitir, si no, debe seguir un criterio similar (funcionalmente) al siguiente, su valor se toma del siguiente modo:
Lunes=1, Martes=2, Miercoles=4 .... Domingo=64
Planning, por tanto vale la suma de los valores de los días en que esa carrera es desarrollada, si tiene de lunes a viernes ambos inclusive sería: 31 (1 +2 +4 +8 +16) , si una carrera se realizara los lunes, martes jueves viernes y sábado sería: 1 +2 +8 +16 +32= 59). Debe crearse una enumeración DiasSemana,  en el código, DIA_Lunes=1 .... y unas funciones para saber si un día en concreto está dentro de dicho código: ejemplo:
Código: Visual Basic
  1.  
  2. public Function SeEstudiaElDia(byval Dia as DiasSemana, byval Carrera as string) as boolean
  3.    dim plan as long
  4.    ' se omite el código para obtener el dato planning de la tabla carreras, en cualquier caso se usaría el nombre de la carrera (o mejor el id) para obtener el planning
  5.    Plan= x ' como se señala en la nota en cabeza
  6.  
  7.     if dia < 128 and dia >0 then  ' comprobamos que día está dentro de los límites aceptables, para no perder tiempo investigando algo que sabemos que está fuera de rango
  8.           SeEstudiaElDia = (( dia or Plan) = Plan)
  9.     end if
  10. end function
  11.  
  12.  
* FechaInicio: para el año en vigor
* Duración: en horas, semanas, meses, etc...
* Tutor: un valor que coincide con el identificador de un profesor. Esposible que una carrera no tenga un profesor que 'dirige' especialmente esa carrera, se pone más bien para explicar cn más detenimiento como se aborda un campo de 1 único valor frente a la necesidad de dun campo con varos valores (lista) y del que este se tomará como base y ejemplo.
Como en la tabla Materias, otros campos que sean comunes a todas las carreras...

* Profesorado: es un método para obtener todos los profesores que imparten esta carrera, dicho método es una query sobre la tabla de datos de profesores. como parámetro se pasa el id_carrera a la función
* Materias: también es un método para obetener todas las materias que se cursan en esta carrera, como parámetro se pasa el id_carrera a la función.
* Horarios: también es un método para obetener el horario de cada materia, como parámetro se pasa la carrera y la materia, la materia se obtien previamente del métodos materias...

Las tabla Horarios, se compone de tres campos, y refleja los horarios existentes diferentes (una única vez)
Tabla: TblHorarios
* Id_Horario: identificador único para cada horario, este valor debe ser autonumérico.
* Dia: un valor numérico que coindice con la enumeración DiasSemana, señala para que día es este horario
* HoraInicio: hora de inicio puede ser un campo de tipo Date o una cadena de texto, por ejemplos : 11:00    , 12:15, etc...
* HoraFinal: ídem, como hora inicio...

Nota: Añadir el campo día permite filtrar consultas para restringir los horarios de un día concreto. Además flexibiliza la tabla auqnue haya hrarios cuyos valores horainicio y horafinal sean idénticos.

esta tabla tiene otra asociada que deriva de esta y relaciona además a otras 2 tablas. En la que deberían constar 3 campos, para identificar unívocamente un horario
Tabla: TblHorariosMateriasCarrera
* Id_Carrera: se relaciona con la tabla carrera
* Id_Materia: se relaciona con la tabla metrias
* Id_Horario: se relaciona con la tabla horarios
Esta tabla permitiría mucha flexibilidad para realizar consultas sobre los horarios. Puede preguntarse por todos los horarios de una carrera dada, todos los horarios para una carrera y materia, y con ayuda delparámetro día aúnpodemos solicitar los horarios de una carrera para el jueves. El resto de consultas posibles no es muy necesario que sean implementadas por lo menos no son de primera utilidad.


Por fin la Tabla profesorado tiene las mismas características que la tabla TblMateriasCarrera
Tabla: TblProfesorado
* id_Profesor: da acceso relacionado  a una tabla que contiene los datos de los profesores
* Id_Carrera: mismo código asociado a la tabla de carreras


Al igual que aquella tabla, podemos pués hacer 2 consultas de modo sencilo, que profesores imparten una determinada carrera y en qué carreras imparte clase un determinado profesor...un ejemplo (como en aquella tabla de una hipotéctica respuesta a estas 2 funciones).
Profesores en la carrera de Matemáticas: Juan.. , Andrés...,  César... , Arturo... , Pedro... ...
Carreras en las que el profesor Andrés imparte clases: Matemáticas, Física, Biología ...

Fijate que un profesor puede impartir clase en varias carreras, por tanto aquí consta un registro por cada par unívoco profesor-carrera

Esta tabla se relaciona a través del id_Profesor con la tabla profesores que se describe a continuación:
Tabla: TblProfesores
* Id_Profesor: identificador único, no necesariamente autonumérico, posiblemente sea mejor un número de identificación personal (cédula, carnet de identidad... como sea que se llame en tu país).
* Nombre: nombre del profesor.
* Edad: .......... este campo y los siguientes pueden ser ignorados y utilizarse si se quiere una tabla adcional lamada TablaProfesoresDatos, donde se describen datos más personalizados y a los que sólo se tendría un acceso más restringido...  dicha tabla debería contener la misma cantidad de registros que esta y estar relacionado con id_Profesor para recoger estos datos, añadir o eliminar registros en una tabla implicaría hacer lo equivalente en la otra tabla 'hermana'  . La razón para crear esta tabla adciional es que suele ser útil y más rápido y cómodo disponer de los datos mínimos, en la mayoría de consultas, seguramente nos baste con saber el nombre del profesor y puesto que se devuelve también el identificador si fuera preciso podría ampliarse información del profesor posteriormente al profesor seleccionado...
* Domicilio: .........
Puesto que un profesor puede impartir más de 1 materia, no sería sensato introducir aquí un campo llamado materia para señalar la materia que imparte, sino que tenemos que crear otra tabla que relaciones los id_Profesor con los Id_materia, tal como se ha descrito más arriba cuando un campo ha de ser una lista debe crearse un método, al final se explica esto con más detenimiento.

por tanto necesitamos crear otra tabla
Tabla: TblMateriasProfesor
* id_Profesor: identificador del profesor relacionado con la tabla TblProfesores
* id_Materia: identificador relacionado con la tabla TblMaterias
Ahora como se ve en esta tabla se puede añadir un registro por cada materia que imparta un profesor.
..y tal como ya se ha explicado podemos hacer 2 cnsultas a esta tabla: Todas las materias que imparte un profesor y todos los profesores que imparten una materia.

__________________
SEGUNDA PARTE:
Para finalizar, fíjate como un campo que tiene un único valor se introduce su valor, en cambio si un capo es unalista, entonces los valores deben reflejarse en una nueva tabla  usando un par de identificadores, y crear métodos para filtrar esa tabla por uno u otro identificador, uno de los identificadores se realciona con la tabla donde nos interesaba introducir el campo y el otro identificador se relaciona con una tabla que contiene como registros la lista deseada. Por tanto en aquella tabla en vez de meter un campo se le añade un método, para obetener la lista deseada. Puede crearse métodos adicionales para buscar un elemento dado, o todos los que cumplan cierto criterio.
Un ejemplo claro del uso de un campo y y de un campo que debería ser lista, lo tenemos en la tabla Carrerasm, donde se ha añadido a propósito el campo tutor donde debe contener el identificador de un único profesor y en cambio el profesorado sería una lista, que como hemos dicho no puede ser introducido como un campo si no como un método. el método relamente debe constar en la tabla que mantiene la relación es decir la tabla TblProfesoresCarrera. Por último debe constatarse que que estas tablas son 'de paso' es decir con los registros obtenidos debe hacerse una nueva consulta para seleccionar todos los registros de la tabla que contiene dichos identificadores.
Más claro si queremos conocer la lista de profesores que imparten matemáticas en la carrera de medicina, debemos usar el id_Carrera preguntar a la tabla TblProfesoresCarrera por todos los registros cuyo id_carrera coincida con ese, con esos datos (sólo tendremos unos valores numéricos) luego debemos dirigirnos a la tabla TblProfesores y recoger todos los registros cuyos id_profesor coincida con los id_profesor que hemos obtenido previamente, ahora ya tendremos un recordset con los registros  de datos de los profesores de esa carrera.

Verás que a mi me salen 8 tablas, aunque parece algo apabullante, lo cierto es que el hecho de tener bien organizadas las tablas facilita luego cualquier consulta, así mismo resulta más sencillo diseñar las funciones que son necesarias, tanto  que incluso resulta evidentes por sí mismas.
Es más rápido (las búsqeudas de resultados) si los métodos se diseñan como procedmientos almacenados dentro de la propia base de datos y en la aplicación se diseñan funciones que delegan en los procedimientos almacenados . Estas funciones entonces son realmente simples, pués simplemente reciben 1 parámetro e internamente reinvocan al procedimiento almacenado con ese parámetro y uno constante en función de que 'dato' realiza la consulta. En definitiva si se crean procedimientos almacenados, las funciones de la aplicación resultan luego muy sencillas...

________
FINAL

Bueno, espero que te sirve para algo lo explicado. Dado que se ha escrito del tirón y lleva cierto tiempo y no dispongo ahora mismo de más, no está revisado por lo que es probable que haya alguna inconsistencia en las explicaciones (revisarlo me llevaría  cierto tiempo adicional), por lo que sírvete de preguntar si algo no lo entiendes o  encuentras alguna contradicción que por falta de revisión se me haya escapado...

p.d.: Fíjate que al igual que tú he omitido todo lo respecto a los alumnos... deberías ser capaz de relacionar correctamente estos en las tablas adecuadas metidando sobre lo indicado y viendo (más bien comprendiendo) como se relaciona cada campo lógicamente a una tabla.

112
Visual Basic 6.0 e inferiores / Re: encryptar codigo
« en: Domingo 14 de Marzo de 2010, 03:26 »
Un detalle...
...aunque es habitual que los profanos utilicen términos como encriptar indiscriminadamente y debamos hacernos cargo... sin embargo el que se pretenda programador no debería confundir términos y usar cifrar que es la palabra correcta en español, 'encriptar' es realmente una traducción literal del término inglés que se corresponde a cifrar. De hecho si lo buscas en el diccionario verás que no aparece y en todo caso significaría 'encerrar en una cripta'.

113
Visual Basic 6.0 e inferiores / Re: encryptar codigo
« en: Domingo 14 de Marzo de 2010, 02:36 »
Si te basta con un cifrado simple, puedes usar el sistema ROT13...
ROT13, sólo oculta de ojos profanos a la programación, es un cifrado de sustitución sin seguridad, pero puede valerte según para lo que lo necesites. A cambio es bastante rápido.
ROT13 sólo trata los caracteres A-Z (del 65 al 90) , pero puedes modificarlo a ROT47, caracteres  desde admiración a tilde (33 a 126) fácilmente...
ROT13 es reversible, es decir ejecutado 1 vez cifra, el texto cifrado ejecutado de nuevo lo descifra.

Como quizás te resulte más útil ROT47, te pongo una posible implementación...
Código: Visual Basic
  1.  
  2.  
  3. ' primero localiza la api Copymemory con el visor de APIs e introdúcela en tu código...
  4.  
  5. Public Function Rot47(ByVal Texto As String) As String
  6.     Dim n() As Integer, max As Long, k As Long, t As Integer
  7.    
  8.     If Texto <> "" Then
  9.         max = Len(Texto)
  10.         ReDim n(0 To max - 1)
  11.         Call CopyMemory(ByVal VarPtr(n(0)), ByVal StrPtr(Texto), max * 2) ' convertimos el texto en una matriz de enteros para trabajar más rápido con números
  12.      
  13.         For k = 0 To max - 1
  14.             t = n(k)
  15.             If t > 32 And t < 127 Then           ' signo de amiración hasta la tilde
  16.                 If t < 80 Then
  17.                     n(k) = t + 47
  18.                 Else
  19.                     n(k) = t - 47
  20.                 End If
  21.             End If
  22.         Next
  23.         Call CopyMemory(ByVal StrPtr(Texto), ByVal VarPtr(n(0)), max * 2)  '  pasamos la matriz de enteros a cadena...
  24.         Erase n
  25.     End If
  26.    
  27.     Rot47 = Texto
  28. End Function
  29.  
  30.  

ejemplo de uso:
Código: Visual Basic
  1.  
  2. dim s as string
  3.  
  4. s= "Hola"
  5. s= ROT47(s)
  6. msgbox s
  7. 'resultado: w@=2
  8.  
  9. ' cifrando 2º ejemplo
  10. s= "Lo que quiero es aumentarle mas linea para que esa line la que dice hola se muestre encriotada o mas bien dicho como encripto"
  11. s= ROT47(s)
  12. msgbox s
  13. 'resultado: {@ BF6 BF:6C@ 6D 2F>6?E2C=6 >2D =:?62 A2C2 BF6 6D2 =:?6 =2 BF6 5:46 9@=2 D6 >F6DEC6 6?4C:@E252 @ >2D 3:6? 5:49@ 4@>@ 6?4C:AE@
  14.  
  15.  descifrando 2º ejemplo
  16. s= ROT47(s)
  17. msgbox s
  18. 'resultado: Lo que quiero es aumentarle mas linea para que esa line la que dice hola se muestre encriotada o mas bien dicho como encripto
  19.  
  20.  

114
Visual Basic 6.0 e inferiores / Re: TransOCX (Frames Transparentes)
« en: Jueves 11 de Marzo de 2010, 18:37 »
Hola.

Intenta lo siguiente:
Cuando se inicie la aplicación en el evento 'load' recorres toda la colección de controles del formulario, preguntandopor su tipo, si el control es del tipo transparente,  invocas su método 'zorder 1'
ç
algo así...

Código: Visual Basic
  1.  
  2. dim c as control
  3. on local error resume next  
  4. for each c in form1.Controls
  5.      if typename(c)= "NombreControlDeseado"  then ' el nombre de la librería, no la propiedad name del control.
  6.          c.zorder 1
  7.      end if
  8. next
  9.  
  10.  

Debería funcionar salvo que haya un control que realice alteraciones en el orden z.
Si esto sucediera, entonces tras cada intervención de ese suceso, se debería ejecutar una rutina que ejecute de nuevo el proceso de enviarlos al fondo.
Para el caso no tiene cuenta volver a recorrer la colección controls del formulario, basta recorrerla una vez al principio, se añaden a un objeto  dictionary y luego cuando se precise se reinvoca la función que los envía a todos al fondo. Un ejemplo... Nota que en ejemplo se usan textbox, sustituyelo por el tipo de objetos que es el control deseado.
Código: Visual Basic
  1.  
  2. ' a nivel del formulario, añade una referencia a microsoft scripting runtime
  3. Dim Trans As Scripting.Dictionary
  4.  
  5. Private Sub Form_Load()
  6.     Dim c As Control, k As Long
  7.    
  8.     Set Trans = New Scripting.Dictionary
  9.     For Each c In Form1.Controls
  10.         If TypeName(c) = "TextBox" Then ' el nombre de la librería, no la propiedad name del control.
  11.            k = k + 1
  12.             Call Trans.Add(CStr(k), c)
  13.         End If
  14.     Next
  15.     Call EnviarAlfondo
  16. End Sub
  17.  
  18. ' cada vez que se requiera se llama a este métdo, para reenciar los objetos  deseados al fondo.
  19. Private Sub EnviarAlfondo()
  20.     Dim c As Object, k As Long
  21.    
  22.     For k = 1 To Trans.Count
  23.         Set c = Trans.Item(CStr(k))
  24.         c.ZOrder 1
  25.         c.BackColor = vbRed  ' como el orden no se aprecia visualmente, cambiamos el color del fondo... sólo vale para controles con una propiedad backcolor, por supuesto, si no dará error.
  26.    Next
  27. End Sub
  28.  
  29.  

...ya nos cuentas si te funcionó o no...

115
Visual Basic para principiantes / Re: Varios listbox
« en: Domingo 7 de Marzo de 2010, 12:45 »
Cita de: "kelmax"
los list estan con informacion ejemplo
list1         list2          list3             list4
codigo1    nombre1   categoria1   fecha1
codigo2    nombre2   categoria2   fecha2
codigo3    nombre3   categoria3   fecha3
codigo4    nombre4   categoria4   fecha4
codigo5    nombre5   categoria5   fecha5

cuando seleccionan el codigo3 se seleccione el nombre3 + categoria3 + fecha3
eso es lo que necesito.

Si tu selección es siempre unívoca, es decir si al seleccionar codigo3 siempre se ha de seleccionar nombre3 + categoría3 + fecha3, e ídem al selecccionar codigo4, etc... entonces esta construcción usando listas es bastante 'torpe'.

Ya que lo que tu necesitas para este caso es una estructura, dicha estructura es contenida sobre una matriz  (o en una colección) y aparte hay un elemento seleccionado, dicho elemento es quien dirige el puntero para saber que elemento de la estructura está seleccionado...
Código: Visual Basic
  1.  
  2. private type Seleccionable
  3.      Codigo as long            ' suponiendo que sea un número
  4.      Nombre as string
  5.      Categoria as string
  6.      Fecha as date
  7. end type
  8.  
  9. Dim p_Selecciones() as seleccionable   '  mantiene una matriz de estructuras. donde cada índice representa un elemento 
  10. Dim p_Actual as long   ' señala el indice actualmente seleccionado de la matriz
  11. dim p_Codigo as long  '  un puntero único incremental, para asegurarse que no haya 2 códigos iguales
  12.  
  13.  
Luego puedes añadir código para moodificar los datos de la estructura actual y un par de métodos para añadir elementos y eliminar elementos y por supuesto otro para cambiar la selección a otro elemento.
Código: Visual Basic
  1.  
  2.  
  3. ' cuando se decide añadir un nuevo elemento debe invocarse esta función tras recoger, los datos de nombre, categoría y fecha de controles a tal efecto.
  4. ' la función devuelve un resultado que es el dato que debería añadirse justo al salir de la función al listbox.
  5. public Function AñadirElemento(byref Optional Nombre as variant, byref Optional Cat as variant, byref Fecha as variant) as long
  6.         if  (not(p_Selecciones)) <> -1 then   ' si la matriz ya está redimensionada...
  7.               if  ubound(p_Selecciones) = ( list1.listcount-1)  then   ' si la matriz tiene tantos elementos como la lista
  8.                    redim preserve p_Selecciones(0 to  list1.listcount + 10)  ' añadimos 10 elementos más de golpe...
  9.               end if
  10.               p_Codigo = p_Codigo +1  ' el código se auotincrementa con cada nuevo añadido
  11.         else                                              ' si la matriz no está redimensionada, la redimensionamos, con 10 elementos
  12.              redim p_Selecciones(0 to 9)
  13.              p_Codigo = 0
  14.         end if
  15.  
  16.        p_Actual = list1.listcount + 1
  17.        p_Selecciones(p_Actual).Codigo = p_Codigo
  18.  
  19.        on local error resume next
  20.        if not  IsMissing(Nombre) then
  21.               p_Selecciones(p_Actual).Nombre=trim$(cstr( Nombre))  ' si se produce un error, contínua
  22.              if err.number <> 0 then
  23.                   p_Selecciones(p_Actual).Nombre= cstr(Codigo)
  24.                   err.clear
  25.              end if      
  26.       end if
  27.       if not  IsMissing(Cat) then
  28.               p_Selecciones(p_Actual).Categoria=trim$(cstr( Cat))  ' si se produce un error, contínua
  29.              err.clear
  30.        end if
  31.       if not  IsMissing(Fecha) then
  32.               p_Selecciones(p_Actual).Fecha=cdate( Fecha)  ' si se produce un error, contínua
  33.               if err.number <> 0 then
  34.                   p_Selecciones(p_Actual).Fecha= Now
  35.                   err.clear
  36.              end if
  37.        end if
  38.  
  39.         AñadirElemento= p_Codigo
  40. end function
  41.  
  42. public property get Codigo as long  ' sólo lectura
  43.          Codigo = p_Selecciones(p_Actual).Codigo
  44. end property
  45.  
  46. public property get Nombre as string                ' leemos el nombre actual seleccionado
  47.           Nombre = p_Selecciones(p_Actual).Nombre
  48. end property
  49.      public property let Nombre(byval n as string)   ' cambiamos el nombre del elemento actualmente seleccionado
  50.               if n <>"" then     ' sólo se acepta si la cadena no está vacía...
  51.                   p_Selecciones(p_Actual).Nombre= n
  52.              else
  53.                   msgbox "El nombre debe tener al menos 1 carácter."  ' ó 4, 6, etc...
  54.              end if
  55.      end property
  56.  
  57. public property get Categoria as string
  58.           Categoria = p_Selecciones(p_Actual).Categoria
  59. end property
  60.      public property let Categoria (byval c as string)   ' cambiamos la Categoria del elemento actualmente seleccionado
  61.               if c <>"" then
  62.                   p_Selecciones(p_Actual).Categoria = c
  63.              else
  64.                   msgbox "No se indicó categoría, no fue cambiada..."  ' ó  lo que quieras hacer...
  65.              end if
  66.      end property
  67.  
  68. public property get Fecha as Date
  69.           Set Fecha = p_Selecciones(p_Actual).Fecha
  70. end property
  71.      public property set Fecha (byval c as Date)   ' cambiamos la Categoria del elemento actualmente seleccionado
  72.               if not(f) isnothing then
  73.                   set p_Selecciones(p_Actual).Fecha = f
  74.              else
  75.                  msgbox "No se indicó fecha. La fecha no ha sido cambiada."
  76.             end if
  77.      end property
  78.  
  79. public property get Actual as long   '  se lee el índice de la matriz que es el actual
  80.           Actual = p_Actual
  81. end property
  82.      public property let Actual (byval a as long)   '  seleccionamos otro
  83.               dim x as long
  84.               if (a> -1) and (a<= list1.listcount) then
  85.                    if a <> p_actual then
  86.                        x= p_Actual
  87.                        p_Actual = a                             ' ahora, antes
  88.                        ' raiseevent SeleccionCambiada( P_Actual, x)  ' si tuviéramos un evento quizás nos interesara indicar cuando cambió la selección.
  89.                    end if
  90.              else
  91.                  msgbox "No existe el elemento " & a & " " & "sigue seleccionado el elemento " & p_Actual  
  92.             end if
  93.      end property
  94.  
  95.  '  ... de igual modo puedes recrear una función para eliminar un eleemnto de la matriz, fíjate que basta con borrarlo de la lista (list1) y luego vaciarlo en la matriz.
  96. '        Si la  matriz tuviera ahora menos de 10 elementos que la lista, la matriz la redimensionamos con 10 elementos menos
  97. '       (no necesita en este caso vaciar el elemento que será eliminado).
  98.  
  99.  
  100. '  un ejemplo de selección a través del listbox
  101. Private Sub List1_Click()
  102.        if list1.listindex > -1 then  ' si la lista tiene elementos, entonces lo seleccionamos
  103.                  Actual = list1.listindex
  104.                  '  como hemos supuestamente cambiado la selección, actualizamos los datos...sobre unos textbox o mejor labels....
  105.                  txtNombre.text = nombre
  106.                  txtCat.text = categoria
  107.                  txtFecha.Text= Fecha
  108.        end if  
  109. End Sub
  110.  
  111.  
Por supuesto te faltaría añadir 2 botones uno para añadir elementos y otro para eliminarlos, si el usuario puede añadirlos y / o eliminarlos desde la interfaz.

116
Visual Basic para principiantes / Re: Numero de version
« en: Domingo 7 de Marzo de 2010, 11:49 »
Código: Visual Basic
  1.  
  2. Private Sub Form_Initialize()
  3.     Dim Version As String
  4.    
  5.     Version = App.Major & "." & App.Minor & "." & App.Revision
  6.     MsgBox Version
  7. End Sub
  8.  
  9.  
Ya tu comparas lo que necesites saber... como una cadena conjunta o comparando cada parte por separado.
Por ejemplo para lo que tu quieres, en el evento initialize (por ejemplo):

Código: Visual Basic
  1. form1.caption= form1.caption & " "  & varsion
  2.  

117
Visual Basic 6.0 e inferiores / Re: Problema con los Itemdata de un Listbox
« en: Jueves 4 de Marzo de 2010, 15:30 »
Listindex se refiere al índice actualmente seleccionado en la interfaz. Tu no lo  cambias en ningún momento, luego el programa te funcionacorrectamente acorde lo que tienes programado.

El error está en la linea que indicas. Es un error de sujeto, tu le dices Rs, toma el valor seleccionado, cuando le debes decir Rs, toma el valor w, puesto que estás recorriendo un bucle...

Así, en vez de esto:
Código: Visual Basic
  1. rs!mat_correlativa = lstcorrelativas.ItemData(lstcorrelativas.ListIndex)
  2. rs!id_materia = LstMaterias.ItemData(LstMaterias.ListIndex)
  3.  
  4.  
Debes poner el puntero al elemento deseado:
Código: Visual Basic
  1.  
  2. rs!mat_correlativa = lstcorrelativas.ItemData(w)
  3. rs!id_materia = LstMaterias.ItemData(w)
  4.  
  5.  

Desde luego podrías cambiar el elemento actualmente seleccionado, pero sería 'tonto', además el usuario se sentiría extrañado de que le hayan cambiado el ítem que él tenía señalado...
Código: Visual Basic
  1. LstMaterias.ListIndex = w
  2.  
, pero como digo esto no interesa, sólo interesa cuando realmente debas seleccionar un elemento específico.

118
Cita de: "DeathWatch"
Hola que hay  :D
 pero "C:archivo.banco", donde se carga, que carga (las clases del archivo .banco?), para que sirve el 1er parametro si el 2do no hace referencia a él
Un saludo  :)
Creo que me he explicado bien, sin embargo es normal que a pesar de ello a veces alguien no acabe de entender una cosa que nos parece (al que lo explica) bastante clara..

...así que intentaré explicártelo mejor con otro ejemplo.

Supongamos que tu eres el creador de  winrar, el programa para comprimir archivos. bien, como parte de tu programa tu has creado unas librerías pero también un tipo de fichero que se asocia con el programa, los archivos *.rar .... entonces se puede usar getobject, para que al mismo tiempo que crear el objeto ya reciba como parámetro de entrada un archivo de tipo rar.
Para qué quieres cargar un archivo rar ?.... pués porque eso es lo que se supone que hace tu programa trabajar con artivos de ese tipo... por tanto usas getobject y si lo necesitas le pasas la ruta de un archivo rar (por ejmplo: c:mis secretos.rar), entonces cuando se cargue el objeto ya abre el archivo de acuerdo a como opera el programa. Naturalmente no esás obligado a usar dicho parámetro, por ejemplo si vas a comprimir, no te hará falta, perosi vas a descomprimir un archivo (y esa es la razón por la que necesitas crear el objeto), pués selo pasas directamente...

Un modo de entenderlo mejor es llevándolo a la práctica... y un excelento ejemplo para llevarlo a la práctica esutilizar excel (por ejemplo),

Código: Visual Basic
  1.  
  2. dim xcel as object
  3.  
  4. set xcel = getobject("c:mis gastos.xls","Excel.Application")
  5.  
Debes notar YA sin dificultad que 'C:mis gastos.xls es un archivo que excel reconoce, que excel crea y que excel entiende. si yo le  digo "Excel.Application", ya sabe que objeto es (si está en la ROT o por lo menos regisrado en el equipo), por tanto carece de sentido indicar la ruta de donde se encuantra excel.exe, a nosotros no nos importa. La ruta del exe, sólo debe usarse para registrar la librería y ni getobject, ni createobject registran ninguna librería, tan sólo proporcionan una instancia a un objeto ya registrado, al igual que NEW, la diferencia con New, es que createobject y getobject se aplican a objetos no referenciados al crear la aplicación.

La programación en realidad no tiene nada de misterioso, son cosas muy sensatas y muy meditadas, a menudo cuando alguien pretende enseñarte algo, en realidad no te enseña nada que no supieras ya (de algún modo), sino que lo que hace es decirte con otro nombres y jerga 'extraña' algo que ya sabías tú por tí mismo. si en la vida piensas de forma coherente, verás que la programación es fácil y la parte difícil es aquella en la que tienes que entender que tal nombre largo y extraño es tal cosa.

Imgina el S.O. como tu casa, imagina los objetos como 'comida'... cuando usamos new, es como ir a la nevera (frigorífico), si hay cerveza, pués coges una pero y si no hay ???  (esto es una referencia en el proyecto, asegurarse de poner en la nevera las cervezas para cuando por la tarde empiece el partido y lo vayas a ver con los amigotes, estén a mno y fresquitas), pero si olvidaste reponerlo, puedes ir a la despensa, ese pequeño almacén donde guardas las compras dirias o semanales, claro que las cervezas estar´ñan calientes y seguramente estará más alejado de la tv. que la nevera, pero es lo que hay... bien este almacén, alacena, despensa o como lo quieras llamar, es el registro de 'güindous', para acceder aquí ya no se usa new, ahora debe usarse createobject  o getobject ... finalmente si ni en tu alamacén hay cervezas, lo que queda es mandar a alguien a comprarlas a la tienda más cercana... esto es instalar la librería, para que así esté diponible en tu almacén, y si lo quieres fresquito pués lo metes en la nevera (una referencia en tu proyecto)... Ahora entiende que tomar una cerveza de la nevera, o del almacén implica que debe existir , que ya lo has comprado y comprarlo (el paquete de cervezas) es lo que llamamos registrar la librería.... son 2 cosas ditintas.... new=trae la cervezade la nevera, Createobject= trae la cerveza del almacén (es más lento, debe comprobar si existe, y como es bastante más grandote que la nevera tardará mucho más) y  regsvr32= ve a comprar un paquete de cervezas (que son depositadas  en el almacén, disponibles si es whisky a lo mejor está reservado y no cualquiere puede echarse un vasito,  :beer: ).

No puedo explicarlo más claro, si te quedan dudas quizás debas mirar en otro sitio y ver si te lo explican de un modo que puedas entenderlo, aunque como te digo, a mi me parece que hablo muy sencillo y claro, de hecho casi nunca uso jerga, precisamente porque sólo sirve para entorpecer al que no sabe.

p.d.: Me olvidaba de una cosa importante respecto a GetObject...
Al usar el primer parámetro, ya no es obligatorio el segundo (en según qué objetos), usando el ejemplo que puse como código...:
set xcel = getobject("c:mis gastos.xls","Excel.Application"), puesto que he proporcionado una ruta, el ya localiza que librería le pertenece, por tanto asigna una referencia al objeto que lo manipula, por tanto esta otra línea es igualmente correcta (fíjate que utilizo otro objeto de excel distinto del anterior):
Código: Visual Basic
  1.  
  2. dim xBook  as excel.workbook
  3. set xBook  = getobject("c:mis gastos.xls")
  4.  
  5.  
Puede (eso si), ocurrir algún problema si otra librería que no es la esperada se ha asignado(la ha desbancado al pulsar doble click sobre un xls, se abre otra aplicación y no excel) , la extensión xls para si y sucede que los métodos (con sus parámetros) y propiedades  para manejar ese 'otro' objeto, no son los que utiliza excel.exe que son los que tu usas en tu código...

Con éste último ejemplo, espero que ahora si, podrás entender porqué este parámetro (que te parece extraño), es útil... porque resulta válido para localizar,  crear y devlver una instancia válida al objeto que lo maneja, que en este caso es excel... Y por último debes saber que esto último sólo funciona si el objeto es lo que se conoce como un 'documento compuesto', es decir tiene referencias a varios objetos (fíjate como el objeto lo he designado para que lo veas claramente: as excel.workbook, no como excel.application).

119
Diseño de Algoritmos / Re: Calcular camino entre dos coordenadas
« en: Domingo 28 de Febrero de 2010, 17:50 »
En otro momento reviso tu algoritmo....

...y de paso te pondré las incrementos para cada octante...

120
Cita de: "DeathWatch"
Hola de nuevo, ya ando por aqui otra vez  :P
Citar
Nebire escribio:
Eres tú quien pregunta y tienes dudas... yo lo tengo muy claro.
:huh:
Yo se que tu lo tienes claro, puesto que me explicaste y me ayudaste a resolver mi problema.
Me referia a si no habia enredado mucho comentando lo que estaba haciendo, de forma que solo yo me estuviera entendiendo, y si habia explicado esta vez la raiz del problema que tenia.
Esto te lo decía en broma... entendí que al intentar explicarte, te pareció no desenvolverte bien y enbarullarlo más...

Cita de: "DeathWatch"

Código: Visual Basic
  1.  
  2. dim fso, carp
  3. set fso=GetObject("", "Scripting.FileSystemObject")
  4. set carp=fso.GetFolder("C:Documents and SettingsDeathWatchMis documentosScripts")
  5. x=carp.Name
  6. msgbox x
  7. set fso=Nothing
  8. set carp=Nothing
  9.  
Es correcto, pero siempre que puedas usa referencias,  piensa que además de lo referente a la tabla, si en tiempo de diseño se declara el tipo de objeto, cuando se compila no necesita comprobar los tipos, por lo que resulta más rápido

Cita de: "DeathWatch"
En mi ejemplo, al  registrar el Exe ActiveX con /RegServer, debo usar GetObject en lugar de CreateObject?
Son similares, pero se usa Create object para obtener la 1º referencia y luego getObject para las siguientes...

Cita de: "DeathWatch"
Si no lo registro, usando Set Ejec_1 = GetObject("C:Documents and SettingsDeathWatchMis documentosXEjecutor.exe", "XProyEjec.XClsEjec"), funcionaría?
Set Ejec_1 = GetObject("C:Documents and SettingsDeathWatchMis documentosXEjecutor.dll", "XProyEjec.XClsEjec")
Esto está equivocado... no me leiste bien al final del post anterior

autocitándome:
Cita de: "Nebire"
Luego, si por ejemplo tu aplicación opera con un tipo de archivo cuya extensión fuera pongamos ".banco" , podrías utilizar la función getobject para crear el objeto cargando ya el archivo indicado...
Código: Visual Basic
  1. dim miObjeto as object
  2. Set miObjeto= GetObject("C:archivo.banco", "MiproyectoActivexexe.Suclase")
  3.  
Y por tanto como podrás ver, nada tiene que ver esta ruta con la ruta donde se localiza el exe activeX

Cita de: "DeathWatch"
(Esto lo voy a probar personalmente, pero si no funciona, si me pudieras comentar la razon, porfas)
No te molestes, ya te he indicado que eso no es correcto... y te he indicado la razón.

Cita de: "DeathWatch"
Una ultima pregunta  :P
Usando el ejemplo que puse, si en lugar de un Exe ActiveX fuera un Dll ActiveX, tal cual con los objetos form y timer y demas, he indicando en las propiedades del proyecto, Subprocesos independientes, si escribo
podria funcionar? respetando el multi-threading?
Échale un vistazo al 'patrón Singleton', bucea por 'gúgel'...

121
Cita de: "DeathWatch"
]Recibia Error de compilacion: No se ha definido el tipo definido por el usuario.
Y lo sigo recibiendo. Supongo que si no se hace referencia entrando a Proyecto – Referencias, y agregando el ActiveX, no se puede hacer referencia de la manera que expuse anteriormente.
Exactamente. Si no hay una referencia añadida no se puede usar NEW, porque no consta en la tabla (ROT) dicho objeto. Precisamente para eso sirven las referencias, para localizarlo en la tabla, por eso usar referencias es más rápido... Cuando se usa NEW, por debajo le está diciendo que debe buscarlo en la ROT y crear una instancia desde allí. Usando CreateObject le está diciendo que busque en el registro. y GetObject le está diciendo que si ya hay una instancia cargada con createobject, la obtenga de ahí (ahorra tiempo en verificaciones) y si no que la localice en el registro...

Cita de: "DeathWatch"
Si no deje algo en claro, comentamelo, para tratar de exponerlo un poco mejor.
Pues nuevamente, te agradezco mucho tu tiempo y tu ayuda.  :beer:  :good:  :good:
:rolleyes:  Eres tú quien pregunta y tienes dudas... yo lo tengo muy claro.

Tienes un pequeño error de concepto, que trataré de corregir..
Cuando usas la función CreateObject, la dirección que admite en todo caso se utiliza para el 2ª parámetro no para el 1º, además ahí la ruta se refiere a una ruta del servidor... de red donde se desea crear el objeto.

Luego, si por ejemplo tu aplicación opera con un tipo de archivo cuya extensión fuera pongamos ".banco" , podrías utilizar la función getobject para crear el objeto cargando ya el archivo indicado...
Código: Visual Basic
  1. dim miObjeto as object
  2. Set miObjeto= GetObject("C:archivo.banco", "MiproyectoActivexexe.Suclase")
  3.  
Y por tanto como podrás ver, nada tiene que ver esta ruta con la ruta donde se localiza el exe activeX

122
Visual Basic para principiantes / Re: Generar un portable
« en: Sábado 27 de Febrero de 2010, 12:56 »
Cita de: "kelmax"
un punto exe sin instalacion previa.
Este tipo de portabilidad requiere que tu proyecto provea todas las librerías que necesita. De ese modo lo haces independiente.

Lo adecuado para el caso es que aplicación arranque desde Main, verifique si las librerías que utiliza tu proyecto están instaladas o no, si no están instaladas entonces las registras, si se registraron todas satisfactoriamente entonces arrancas la aplicación ...

Para saber que librerías necesita tu proyecto, lo mejor es hacer un empaquetado (utiliza el asistente de empaquetado que tiene vb), una vez hagas el empaquetado verás que hay un archivo que contiene la lista de las librerías y ficheros adicionales que pueda necesitar. Utiliza esa lista para localizar los ficheros e incluirlos en tu carpeta de distribución. Naturalmente el empaquetado, después de saber que necesitas, puedes eliminarlo.

Por último si tu programa utiliza algún tipo de salvaguarda de opciones y configuración del usuario, utiliza un fichero dentro de tu carpeta en vez de utilizar el registro como almacén, así además de portar el programa también es portable la configuración.

123
Aunque has dato algunos detalles, no son todos los necesarios para entender tu problema.

Por ejemplo, el objeto que tratas de cargar, está compilado o lo usas en el proyecto de prueba todavía en diseño ?.
Puedes exponer una imagen del cuadro de propiedades del exe activeX  (de la clase)?
Hay más objetos o sólo una clase... ?
Has registrado la librería ?.

Suponiendo que por ahí no te hayas encontrado problemas, pués, pasemos a lo siguiente....

Te pongo un pequeño ejemplo que te servirá de guía, luego que lo verifiques por tí mismo, introduce las equivalencias a tu proyecto...
1 Crea un nuevo proyecto de tipo EXE ACTIVEX...
2 Dale un nombre al proyecto, por ejemplo : ExeActiveX y un nombre a la clase, por ejmplo: EXejemplo
3 Asegúrate que la clase tiene la propiedad instancing establecida a 5 (multiuse)
4 Escribe este código para clase (copia y pega)
Código: Visual Basic
  1.  
  2. Private Sub Class_Initialize()
  3.     MsgBox "hola"
  4. End Sub
  5.  
  6. Public Sub Saludar(ByVal cadena As String)
  7.     MsgBox cadena
  8. End Sub
  9.  
  10.  
5 En proyecto propiedades del proyecto modelo de subprocesos -> activa la casilla que que mejor te convenga, para el ejemplo nos vale bien ''conjunto de: 1 subprocesos'' (puedes aumentar la cifra si lo requiere tu aplicación, pero en esta de ejemplo con 1 nos vale)
6 Ahora compila el proyecto y cuando termine, ciérralo. Ahora abrimos nuevamente el entorno de vb6 para crear una aplicaciónde tipo exe estándar...
7 en el mismo código de carga del formulario (puesto que es un simple ejemplo vale, si lo prefieres ponlo para un botón), pega este código:
Código: Visual Basic
  1.  
  2. Private Sub Form_Load()
  3. '    Dim Ejec_1 As ExeActiveX.EXejemplo  ' sólo si se añade una referencia
  4.   Dim Ejec_1 As Object   'ExeActiveX.EXejemplo
  5.  
  6.     'Set Ejec_1 = New ExeActiveX.EXejemplo    ' sólo si se añade una referencia al proyecto.
  7.    Set Ejec_1 = CreateObject("ExeActiveX2.EXejemplo")
  8.     Set Ejec_1 = GetObject("", "ExeActiveX2.EXejemplo")
  9.    
  10.     Ejec_1.Saludar ("funciona correctamente")
  11. End Sub
  12.  
  13.  
Debería funcionarte sin problemas... cuando creas la instancia se crea la clase, por lo qwue se invoca el método initialize del activex y se ejecutará el código que pusimos, nos responderá 'Hola'
Cuando se ejecute el método Saludar, tomará la cadena que le hemos pasado y deberá mostrarnos el mensaje pertienente...

Fíjate que podemos usar tanto GetObject  como CreateObject... (cada una utiliza sus propios parámetros)
fíjate que no señalo ninguna ruta... ¿ por qué ? te preguntaras... porque cuando he compilado el proyecto automáticamente se ha registrado la librería. Por tanto lo que tienes que hacer es registrar adecuadamente la librería.

124
Visual Basic 6.0 e inferiores / Re: ¿como puedo hacer esto????
« en: Viernes 26 de Febrero de 2010, 12:36 »
Incluso ahora no te explicas lo suficiente.

Me parece entender que puedes querer esto otro...
Un método que describa como guardar los datos relevqntes de modo que puedas luego obtener un conjunto de ellos filtrando por año.
Bien si fuera esto, como tampoco indicas el método para guardar los datos (asumo que es una base de datos), entonces lo  adecuado es
que tengas un campo Año en tu base de datos.
Supongamos que los campos que contiene una tabla son (esta tabla podría llamarse DatosCurso):
IdAlumno: un identificador único autoincrementable enlazado a otra tabla que contiene datos específicos del alumno, (nombre apellidos,fecha nacimiento, teléfono, localidad, calle...)
Grado: el que está cursando actualmente,  1º, 2º, 3,º.... sean en semestres o anualidades...
Materia:  El curso que realiza... Psicología, Medicina...
Por tanto sería acorde introducir un campo más llamado año:
Año: año en que el alumno referenciado cursa tal materia y tal grado....

Por tanto tú luego puedes hacer varias funciones para obtener datos de esta tabla (DatosCurso) (o de la tabla DatosAlumno)  las más lógicas serían...
(en el código de más abajo se muestra un ejemplo para que todas estas funciones por separado sean 1 sola).
Filtrar por materia:
01º Obtener todos los alumnos que cursan una materia (por ejemplo que estudien psicología)
05º Obtener todos los alumnos que cursan una materia filtrado por grado (por ejemplo que estudian psicología de 5º grado).
03º Obtener todos los alumnos que cursan una materia filtrado por año (por ejemplo que estudian psicología, en 2010)
07º Obtener todos los alumnos que cursan una materia filtrado por grado y año (por ejemplo que estudian psicologia de 5º grado en 2010)
Filtrar por grado:
04º Obtener todos los alumnos que tienen tal grado (por ejmplo todos los que acaban de iniciar (no han cursado 2º grado aún)
06º Obtener todos los alumnos que tienen tal grado filtrado por fecha (por ejmplo todos los que acaban de iniciar (no han cursado 2º grado aún), en 2010)
- el filtrado por grado, fecha y materia sería lo mismo que el 3º caso
Filtrar por fecha:
02º Obtener todos los alumnos que cursaron el año x (por ejmplo que estuvieron matriculados en 2008)
- Filtrar por año y grado es igual 6º
- filtrar por año y materia es igual que 3º
- filtrar por año, grado y materia es igual que 7º

Por tanto la base de estas querys podría ser obtener un recordset a partir de unas cadenas que podrían ser en su base constantes y donde cada vez lo que cambia son los parámetros.
El siguiente código sería un ejemplo de como obtener un recordset sin necesidad de crear tantas funciones explícitamente... para ello primero habría de llamarse a una función que crea una query en base a usar o no cualquiera de los 3 parámetros de filtrado, luego con dicha query pedimos el recordset, queda a tu esfuerzo (aparte de corregir algún fallo en el código, está hecho directamente) volcar el recordset al control/les tal como tengas diseñada la interfaz...

Código: Visual Basic
  1.  
  2. ' Prepara una query en base a los parámetros que utilicemos, sean estos cuales sean... si se omiten todos los parámetros, se recogerían todos los registros de dicha tabla.
  3. public function PreparaQuery(byref optional Materia as vaiant, byref optional Fecha as variant, byref optional Grado as variant, optional Cuantos as variant) as string
  4.        dim  b as string, w as string, m as string, g as string, f as string
  5.      
  6.        if isMissing(cuantos) then
  7.               if isNumeric(cuantos) then
  8.                      b = " TOP " & cstr(cuantos)   'seleccionará los x primeros, esto lo puedes modificar a tu gusto, se expone sólo como ejemplo de sugerencia
  9.                else
  10.                     b= " *"                                     ' seleccionará todos
  11.                end if
  12.        else
  13.             b= " *"                                            ' seleccionará todos
  14.        end if
  15.              
  16.        ' se usan los 3 campos (siempre que no se haya omitido alguno), se prepara esta parte en base a este hecho                    
  17.           m= Subwhere(Materia, "Materia")
  18.           f= Subwhere(Fecha, "Fecha")
  19.           g= Subwhere(Grado, "Grado")
  20.  
  21.            ' Si materia no fue omitido                    
  22.           if m <>"" then w = " WHERE " & m
  23.  
  24.           if w <>"" then
  25.                   if f <>"" then w = w " AND " & f     ' si fecha no fue omitido
  26.           else   ' materia fue omitido
  27.                   if f <>"" then w = " WHERE " & f     ' si fecha no fue omitido
  28.           end if  
  29.  
  30.            ' si al menos materia o fecha no fueron omitidos
  31.           if w <>"" then
  32.                   if g <>"" then w = w " AND " & g     ' si grado no fue omitido
  33.           else    ' materia y fecha fueron omitidos
  34.                   if g <>"" then w = " WHERE " & g     ' si grado no fue omitido
  35.           end if  
  36.  
  37.        PreparaQuery = "Select" &  b & " FROM tblDatosCurso" & iif( w<>"", w,"")
  38. end function
  39.  
  40. '  compone parte de los campos para el filtro.
  41. private function Subwhere( byref Valor as variant, byval Campo as string) as string
  42.          dim w as string
  43.  
  44.          on local error goto SaleWhere
  45.          if not ismissing(Valor ) then
  46.                  w = ucase$(trim$((Valor ))
  47.           end if
  48.           if w <> "" then
  49.                   w = " " & chr(34) & Campo & chr(34) & " = " & w
  50.           end if
  51.  
  52.          Subwhere=w
  53.  
  54.        exit function
  55. SaleWhere:
  56.        Subwhere=""
  57. end function
  58.  
  59. ' supongamos que utilizamos por debajo un control  adodc...
  60. public function GetDatosCurso(byval query as string) as ADODB.recordset
  61.         Dim Cmd As ADODB.Command, Conex As ADODB.Connection
  62.  
  63.         if query <> "" then
  64.               Set Conex = New ADODB.Connection
  65.               Conex.Open Adodc1.ConnectionString   ' utilizamos la conexión establecida con el objeto Adodc1
  66.               Set Cmd = New ADODB.Command
  67.               With Cmd
  68.                     Set .ActiveConnection = Conex
  69.                     .CommandType = adCmdText
  70.                     .CommandText = query  
  71.                     set  GetDatosCurso = .Execute(, , adCmdText)
  72.              End With
  73.         end if
  74. end function
  75.  
  76.  
NOTA: el código está puesto 'al vuelo'  de modo que a lo mejor necesitas hacer alguna corrección, (en la query  sobretodo)

Luego de obtenido el recorset si se quiere obtener datos del alumno, fuerza a seleccionar una fila (del control donde exhibas los datos) y en conjunto con un botón (o sin él, directamente al cambiar de fila), obtén los datos del alumno a través de su id alumno:
Código: Visual Basic
  1.  
  2.      "SELECT * FROM  tblDatosAlumno WHERE idalumno = fila(idseleccionado)" ' fila(idseleccionado) recoge el dato idAlumno correspondiente al registro seleccionado.
  3.  
  4.  
y vuelcas dicho contenido , sobre unos controles al efecto...
 
En fin no sé si esto lo que querías, porque no has sido lo suficientemente claro... o por lo menos yo no he terminado de comprender lo que reclamas.

125
Me surgen demasiadas dudas leyendo tu mensaje, al contestarte saldría un post muy largo y vago...

¿ Puede explicitar claramente lo que necesitas, dejando aparte el 'polvo y la paja'...?

Páginas: 1 ... 3 4 [5] 6 7 ... 29