You are on page 1of 24

Impresiones con Visual Basic 2010

Pese a que vivimos en una era digital y todo (bueno, casi todo) se hace por internet y con la computadora, aún hay momentos en que el papel es necesario. Hace tiempo escribí un post donde indicaba cómo imprimir usando Visual Basic 6, pero no había tenido la oportunidad de hacer lo mismo con el Visual Basic .net. Y eso precisamente es lo que pienso hacer en esta ocasión: mostrar como usar los controles y cajas de diálogo para imprimir y la forma de imprimir tanto texto como imágenes. Antes de continuar con rollo, código, ejemplos y demases, voy a describir brevemente los componentes que tiene Visual Basic 2010 para imprimir.

Control PrintDocument
Este control se debe agregar a cualquier proyecto en el que se quiera imprimir algo. Haz de cuenta que es la hoja en blanco donde puedes dibujar diferentes objetos, escribir texto y colocar imágenes de mapa de bits. Cuando acabes de dibujar, escribir, etc., se llama el método Print para que la impresora escupa la hoja. Acepta todos los métodos de dibujo que usa el objeto Graphics (mismo del que di ejemplos aquí y aquí), es decir que si tienes que escribir texto, usas el método DrawString; si quieres dibujar un marco alrededor del texto, puedes usar DrawLine o DrawRectangle. Aunque el control es invisible (no aparece en la ventana ni hay forma de ir viendo conforme se va dibujando), es muy útil.

Control PrintDialog
Este control hace aparecer la ventana default que te permite elegir y configurar la impresora que se desea emplear. Si no se usa, la impresión se hace en la impresora que se tiene definida como default con las propiedades que trae por default (o sea con lo default de lo default se debe usar el método ShowDialog. ). Para que aparezca,

Control PageSetupDialog
Este control hace aparecer la ventana que te permite configurar el papel a usar: tamaño, orientación, márgenes, etc. Se debe usar su método ShowDialog para que aparezca, igual que con el control PrintDialog.

Control PrintPreviewDialog
Este control hace aparecer una vista previa de lo que se va a imprimir. Como mostraré más adelante, se debe vincular este control con lo el control PrintDocument para que todo lo que se va a imprimir, en lugar de ir a la impresora, aparezca en esta ventana. También hay que tener cuidado: si no se tiene acceso a la impresora que está seleccionada (por ejemplo, una impresora de la red a la cual no tengo acceso en este momento o la que tengo conectada está apagada), no aparece la ventana y te marca error. Es necesario recibir este error (con un Try«Catch) para que no termine abruptamente el programa solo porque no halla la impresora (cosa que no hago en este post, por cierto).

Ejemplo de su uso
Después de este rollo (que espero que haya sido breve), voy a ejemplificar el uso de estos controles en un programa que hice con mis queridísimos alumnos de 4TPO. Es un ejemplo muy simple que solo muestra como se usan los controles. Sin embargo, creo que con estas bases ya le pueden echar vuelo a la imaginación para aplicarlo en otros contextos. Antes que nada, les muestro el diseño de la ventana principal. Consta de 3 etiquetas, 3 cajas de texto (txtNombre, txtDir y txtRFC), un PictureBox (picCanoa) que sirve para mostrar como imprimir una imagen de mapa de bits, 7 botones cuyo código explicaré más adelante, 2 controles PrintDocument, un PrintDialog, un PageSetup y unPrintPreviewDialog. Estos 5 últimos no aparecen en la ventana: cuando los agregas a la ventana aparecen en la parte inferior.

Una vez que tienes este evento listo. son las mismas funciones que se usan para dibujar gráficos sobre la ventana cosa que ya escribí en este post y en este también. verás este código: Básicamente uso el parámetro e. Yo lo hago con el botón cuya etiqueta dice Imprimir y este es el código: .Para que un PrintDocument funcione. Como mencioné con anterioridad. es necesario editar su evento PrintPage. que es ³la hoja invisible´ sobre la que voy a dibujar. un rectángulo y la imagen de la canoa. Si le das doble clic al icono PrintDocument1. para escribir 3 cadenas. puedes mandar imprimir con la función Print.

y luego PrintPage). Aquí está la ventana frmPicts y abajo el código que lo usa (primero elel botón que tiene la etiqueta Imprimir formato. Dibujé el esqueleto de un formato. lo guardé como PNG.btnImprime2. Este es el código del botón con la etiqueta Configurar impresora. Configurar la impresora es muy simple usando el control PrintDialog. Fíjate en la manera en que copio las propiedades puestas por el usuario en este cuadro de diálogo en los dos controlesPrintDocument (en las 2 últimas instrucciones): .El PrintDocument2 muestra una idea para imprimir formatos. lo importé a Visual Basic y lo puse en un PictureBox(llamado PictureBox1) en la ventana frmPicts.

el control PrintDialog hace que aparezca esta ventana: También es sencillo modificar la configuración de la página. Al correr este evento. Este es el código del botón etiquetado Configurar página: Antes del ShowDialog es necesario igualar sus propiedades a los que ya tiene unPrintDocument (en las dos instrucciones que siguen al comentario). aparece esta ventana: .A la hora de ejecutarse.

Hacer que aparezca es sencillísimo. en lugar de que el evento PrintPage de un PrintDocument lo mande a la impresora. se le envía a esta caja de diálogo. Lo único que hay que hacer es hacer que.Una vista previa (o presentación preeliminar) de lo que se va a imprimir suele ser bastante útil para muchos usuarios. Abajo pongo el código y luego la ventana que aparece que muestra la vista preeliminar: .

lblDuplex.También es posible jugar con la configuración de la impresora. También es necesario un PrintDocument para poder ver estas propiedades. lblCopiasMax y lblColor. veamos el código con que llena ListBox1: . respectivamente). se ven algunas de sus propiedades. etiquetas que muestran los valores de las copias. Para leer algunas propiedades de las impresoras. Pero antes que nada. el número máximo de copias permitidas y si puede recibir documentos a color (lblCopias. si es duplex (si puede imprimir por ambas caras de la hoja). hice el botón etiquetado Lista de impresoras que abre la ventana frmImpresoras desde donde se pueden ver la lista de impresoras instaladas y al seleccionar una de ellas. Esta es la ventanafrmImpresoras en la vista diseño: Tiene una lista donde voy a escribir la lista de impresoras (ListBox1).

InstalledPrinters misma que contiene la lista de todas las impresoras instaladas en el equipo donde se está ejecutando. Estoy usando la instrucción With para abreviar un poco y no escribir este rollo a cada rato. No necesito escribir un evento PrintPage para el PrintDocument1 porque no voy a imprimir nada: solo lo necesito para poder mostrar las propiedades.PrinterSettings.Nótese que estoy haciendo uso de la colecciónPrinting. Por esta razón el otro código interesante es el que se ejecuta cuando ListBox1 cambia de elemento seleccionado: Este es un ejemplo de como se ve esta ventana con una impresora seleccionada: .

."). . Como dijo Jack el destripador. La pantalla se ve algo así: Al darle click sobre ese mensaje.NET: el menú principal (MenuStrip) y el contextual (ContextMenuStrip).net y 2005 Hay dos tipos de menus que se pueden poner en aplicaciones hechos en Visual Basic . El ambiente de diseño cambia un poco: el "control" aparece en la parte inferior.Menus en Visual Basic . etc. Edición. vámonos por partes. aparece una cajita que dice "Escriba aquí". fuera de la ventana y en la parte superior de la ventana (o forma) que estás creando. te permite escribir un texto (el letrero del primer menú) y aparecen "huecos" para escribir más opciones. Las siguientes imágenes muestran el efecto que tiene ir tecleando opciones del menú. Para crear uno.. El menú principal es el que aparece en las aplicaciones abajo de la barra de la ventana (o sea. se tiene que arrastrar el objetoMenuStrip a la ventana. la tirita que dice "Archivo.

Visualmente quedó muy padre. le dí un doble click sobre la leyenda "FamousStar" y me aparece la ventana de código así: . En este caso. Ahora. ¿qué hacemos? Programar las opciones se hace como con cualquier otro control.

Ahora puedes escribir las diferentes opciones de la misma manera en que lo hice con el menú principal. tenemos que añadir el controlContextMenuStrip a la ventana para que quede abajo de la ventana que estoy diseñando. Bueno.Ya que solo es un ejemplo y no quiero complicarme la vida. así que agrego el código que hace aparecer un MessageBox de la siguiente manera: Al correr el programa y al seleccionar la hamburguesa "FamousStar". Para empezar. Pero de todos modos vamos a crear un menu contextual. con algunas pequeñas variantes que iré detallando. exageré. aparece esta ventana: Fácil. ¿no? Ahora toca retar a un menu contextual a un duelo. Es muy similar al menú principal. Algo así: Como observarás es casi idéntico que el menú principal. solo que aquí no puedes cambiar el texto ContextMenuStrip1. A mí me quedó así: . solo voy a hacer que aparezca una ventana que diga lo que eligió.

Agregar código a las opciones del menú contextual es idéntico a la manera en que se agregan en el menú principal (cosa que ya expliqué más arriba). haz un doble click sobre el ContextMenuStrip1 (suponiendo que no le has cambiado el nombre) que está abajo de la ventana. vuelve a aparecer el menú para que puedas seguir trabajando en él.No te vayas a sacar de onda: si le das click afuera de la ventana del menú contextual que aparece. Pero para que funcione. Al hacerlo. desaparece. Para volverlo a abrir. tenemos que programar .

Se supone que en otra parte ya programamos lo que va a hacer cada opción (de la misma manera en que lo hacíamos para las opciones del menú principal).Y).X y e. pon este código bajo el evento MouseDown del Form. Lo más común es hacer aparecer un menú contextual al darle un click con el botón derecho del mouse. Yo programé el evento MouseDown de una etiqueta (Label1) porque me interesa que abra cuando estoy sobre el label. Esto sería así: ¡Y ya! Usamos la función Show que sirve para mostrar el menú en las coordenadas dadas. En nuestro caso. Así que hay que programar el evento MouseDown. que haga aparecer el menú contextual. así que ahora hay que decirle al programa que si el botón presionado es el derecho. pero si quieres que aparezca cuando le das click derecho sobre la ventana. . Espero que se haya entendido porque lo estoy programando bajo Label1_MouseDown() y no bajo Form1_MouseDown() como probablemente harías en tu proyecto. le estamos pasando las coordenadas del lugar donde está el cursor de nuestro mouse (e.el momento en que queremos que aparezca ese menú.

¿para qué me sirve la OOP (programación orientada a objetos)? ¡Buenas noticias! La gente de Microsoft ha escuchado las plegarias de muchos programadores y han agregado una manera ³natural´ de crear formas similares: la herencia visual. Lo peor de este rollo es cuando tienes que dibujar otra ventana que es muy similar a otra. creo un nuevo proyecto y diseño mi Form1 de esta manera: . voy a agregar una ventana (o formulario) heredado para que se vea como heredo la interfaz. debería poder aprovechar la herencia para evitar andar repitiendo cosas. voy a explicar como es que se heredan las ventanas. etc. Para explicar esto. sino funcional (hace tiempo escribí un artículo sobre las interfaces gráficas. O una de dos: o creas otra ventana y la dibujas de nuevo. si le es de utilidad y.). si es tu caso. que puedes ver aquí). Es importante que no solo sea bello. En este artículo.Heredando la pura guapura« Algo que me da mucha flojera al programar con Visual Basic 6 o 2005 es el tener que dibujar interfaces de las ventanas (o formularios o formas. o copias el archivo de la ventana (en VBasic 6 tiene la extensión . voy a hacer un programa muy sencillo: una ventana con una etiqueta. Para iniciar. como dicen algunos porque por defáult se llaman Form1. una caja de texto y dos botones. si estoy usando un lenguaje quesque orientado a objetos (digo quesque porque el único lenguaje de programación que conozco que totalmente orientado a objetos es el SmallTalk). o GUIs. Es muy importante tardar un rato diseñando el interfaz porque de eso depende que el usuario pueda y quiera usar tu programa. Form2. Luego.frm) y lo pegas con otro nombre e importas este nuevo archivo a tu proyecto. Si no. si te lo compra. Cualquiera de las dos alternativas no es muy natural que digamos y.

Para heredar Form1. me voy al menú Proyecto (también puedo hacer clic derecho sobre el nombre de la solución. Para poder heredar esta forma. no se puede heredar). haga un Exit): le incluyo la instrucción End. vamos ³tirando rostro´. Para hacerlo fácil. en este caso HerenciaVisual. y salen las mismas opciones) y selecciono la opción Agregar Clase« como se ve en la siguiente figura: . es necesario generar el proyecto (si no se compila Form1. me voy al menú Generar y escojo la opción Generar HerenciaVisual: Ahora sí.Voy a agregar código al botón Salir (Button2) que haga que el programa se excite (o sea.

te aparece una ventana como esta: .Al hacer esto. aparece la siguiente ventana. donde vamos a seleccionar la opción Formulario heredado: Después de esto.

no me aparecen los controles heredados: . En Form2. te aparece un candado que indica que no lo puedes eliminar. Eso indica que el control está heredado. Abrí el código desde el botoncito de código que está en la ventana de soluciones. Si le das doble clic al control. mi explorador de soluciones me aparece Form2. Para terminar. vuelve a generar el proyecto. seleccioné el primer botón. como dos cajitas con una flechita. Ahora selecciono la opción Aceptar para decirle que herede la ventana Form1 (en mi caso. Button1. y el ³candadito´ se ve así: Tampoco se puede agregar código a los controles. fíjate que al seleccionar uno de los controles.En dado caso que no te aparezca así. no se abre la ventana de código ni nada. En este momento. como se ve aquí: Y Form2 se ve así: Fíjate que los controles de Form2 tienen un signo chiroliro en su esquina superior izquierda. la única que existe). Si te fijas.

¡Hasta la próxima! . Si quieres agregar algo acerca de tus propias experiencias con la heredada de ³guapuras´.En conclusión. puedes heredar controles pero no su código. de sus interfaces gráficos chiroliros. Se puede hacer una ventana ³base´ y heredar las partes comunes a muchas ventanas y en cada una agregarle ³el saborcito´ individual. deja un comentario. Esto te ahorra mucha lata. Espero que esto les ahorre lata y trabajo extra.

net) que pueden ser accesados de manera aleatoria. No es que un tipo de archivo sea mejor que otro: cada uno tiene sus propios usos. Como no todo es al azar. Así es el diseño del menú: . Todo esto funciona por medio de los botones. hice una pequeña aplicación que le podría servir a la biblioteca personal de alguien. podemos usar un archivo de acceso aleatorio como una tabla de una base de datos. A lo mejor ya los hice bolas con los poemas (lo mencioné como simple cultura general) y los programadores. Esto del acceso aleatorio es una manera rimbombante de decir que podemos accesar cualquier parte del archivo que se nos pegue la gana en el momento en que se nos pegue la gana. se obtiene solamente lo que se ha grabado en ellas.¿Alguna vez has escuchado alguna frase relacionada a los "azares del destino"? No sé que tan cierto es eso que el destino sucede al azar (algunos están en desacuerdo con esta idea. Como habrás notado si leíste algunos de mis posts anteriores. no es permitido saltar a cualquier parte del archivo y agarrarnos leyendo. Esta es la imágen del programa en funcionamiento: La aplicacion usa las cajas de texto para llenarlos de valores y guardar el registro o para mostrar los datos de un libro leído. Gracias a estas estructuras. los programadores decidieron ponerle cierta estructura a las cosas para que no todo fuera tan alocado. o sea. Para ilustrar como funciona esto. este tipo de archivo difiere de los archivos secuenciales en que éstos últimos solamente pueden ser leídos desde el principio hasta el final. aunque es posible (y muy útil) hacer archivos que se puedan accesar de manera aleatoria. pero los programadores no creen en que hay tanto azar en las cosas porque. La idea es que puedo crear archivos por medio de los archivos de programación (aunque ahorita me interesan los que se pueden hacer en Microsoft Visual Basic . decidí también tener un menú contextual que sirva para hacer lo mismo. como lo está Amado Nervo en su poema "Vida nada te debo"). pero solo para farolear y aumentar mi ego y autoestima.

Todo esto va a dentro del PublicClass Form1.EXE de esta aplicación). Todo esto se inicializa en el Form1_Load como se ve en esta figura. NombreArch es una cadena que tiene el nombre del archivo (toda la ruta completa) y NoReg guarda el número de registros que están almacenados en el archivo. uno a uno. solo quiero aclarar lo que guardar. Se te fijas. estoy diciendo que ese archivo va a estar en la misma carpeta donde se encuentra el archivo . como diría Jack el destripador. . Librote es la instancia de la clase Libro que voy a usar. vámonos por partes. el uso de FileOpen() cambia un poco en relación a su uso con los archivos secuenciales. más adelante (después de este código). Pero. Luego cuento el número de registros y guardo en dato en NoReg. Para hacer esto. Luego consigo un número de archivo disponible (con el FreeFile()) y lo abro. comienzo a leer todos los registros usando la instrucción FileGet(). De las variables. esta es la estructura que voy a usar para guardar los datos de los libros y algunas variables globales que me van a ser útiles. e ir acumulando en NoReg cuantas veces he leído hasta llegar al final del archivo (uso EOF() para saber si ya llegué al final).GetCurrentDirectory.Ahora. No voy a redundar con una explicación acera de cómo se hacen las estructuras porque ya escribí acerca de ellos aquí. Esto lo hago con FileClose(). Y no hay que olvidar cerrar el archivo al final. Lo primero que hace es asignarle el nombre Biblioteca. Para empezar.tvr a la cadena NombreArch (fíjate que al usar elDirectory. Como en el código no se ve toda la instrucción. vámonos al código.

En este mismo bloque de código.OpenAccess.Random indica que vamos a usar un archivo de acceso aleatorio. o sea. que lo resuelva como mejor le parezca. En el archivo. Está tan fácil. etc. que ni necesita explicadera. puse lo que tiene el Form1_MouseDown que se va a encargar de mostrar el menú contextual chiroliro que puse.Default maneja toda la movida que pasa cuando varias personas quieren abrir el archivo al mismo tiempo.Len(Librote)) Arriba expliqué lo que contiene NoArch y NombreArch. Aquí está el ejemplo del código de los eventos que pone en blanco a todas las cajas de texto de la ventana y luego los eventos que guardan la información que está en la pantalla. OpenShare. el tamaño de Librote * 1355. Si no le digo cuanto mide cada registro. Se puede bloquear de escritura. Al final. jeje) el botón o usando el menú contextual farol.ReadWrite indica que vamos a poder leer datos del archivo y escribir datos a él. hice funciones que hicieran estas tareas vanas y rutinarias. Ahora sí: la instrucción FileOpen() completo : FileOpen(NoArch.OpenShare . . uso la función Len() para que me devuelva el tamaño en bytes de la estructura. Con el Default le estoy dejando la bronca a VBasic . una instancia de la estructura Libro). el tipo de dato de la variable Librote (o sea.Default. Esto es muy necesario para poder manejar las estructuras en el archivo. OpenAccess. mide le número de bytes que se tiene que "saltar" para leer ese registro.NET y le digo que ahi le encargo la bronca. ¿Entendido? ¡Adelante pues con lo que sigue! Para cada acción que puede realizar el usuario tengo dos eventos donde lo puede hacer ya sea puchurrando (nuevo verbo. es imposible que lo pueda hallar a la primera cuando le digo "quiero el registro 1355 y lo quiero rapidito". Por esta razón.ReadWrite. o sea.Random. OpenMode.NombreArch.OpenMode. lectura.

Una vez terminado. pensándolo bien. nunca hay texto por allí..El código que limpia la ventana (muy original. Después hay una función AsignaLibro que copia los valores que hay en Librote a las cajas de texto de la ventana. en fin. escribo el registro usando la función FilePut(). A continuación está la función GuardaLibro que se encarga de meterlo en su lugar quesque-aleatorio en el archivo. en esa posición del archivo (en este caso. . Ahora sí. lo cierro y uso la función que limpia la ventana.... se llama LimpiaVentana) no tiene ninguna ciencia. Hace lo mismo que haceForm1_Load al principio: encuentra un número de archivo que se puede usar y abre el archivo. Limpia la ventana (o sea. esa es la idea) e inicializa la estructura en ceros. Después le asigna a Librote los valores que hay en los Textboxes y al final le agrega uno al número total de registros para poder poner allí. quita cualquier resto de texto que haya quedado por allí. algo más interesante. al final) el contenido de Librote.

La otra manera de buscar sería la de accesar de forma directa el registro que quiero y leer los datos. Como es un mero ejemplo. pero en las computadoras intentamos reducir el tilichero al máximo. Los dos hacen prácticamente lo mismo: van desde el principio del archivo leyendo registros y comparándolos con el título o ISBN dado en un InputBox chafa que puse allí (mi idea es la de ejemplificar. Para hacer esto. o sea. no la de hecer una aplicación 100% terminada y fresón).Sería inútil en este mundo guardar cosas si no los voy a usar. quien es la función encargada de buscar un libro por número de registro. Pero como queremos hacer algo útil. eso pasa en nuestras casas cuando vamos acumulando tilichero. Dos de ellas son muy similares. Hay 3 botones (y 3 elementos del menú farol) que hacen diferentes consultas. el que busca por el título y el que busca por el ISBN (nada que ver con el INSEN). así que escribo aquí el código de la función BuscaISBN. la función quesque aleatoria del archivo. mejor dedíquense a otra cosa y no se esfuercen en hacer programas. . Depsués de divagar en tiliches. El funcionamiento es también muy similar a lo que expliqué en el Form1_Load(). lo hice de las dos maneras en la función BuscaReg. ahi va la manera de accesar los datos que hemos guardado. intento decir que es muy importante consultar los datos que almacenamos porque si no los consultamos. Bueno. hay de dos sopas: usar la función FileGet() con el último parámetro que indica el número de registro que quier leer o usar la función Seek() para moverse al lugar en el archivo donde está ese registro y luego usar el FileGet() sin el parámetro del número del registro.