Curso Básico de Programación
en Visual Basic

 

Entrega Treinta y dos: 23/Ene/2000
por Guillermo "guille" Som

Si quieres linkar con las otras entregas, desde el índice lo puedes hacer

 

¿Que tal?
Creías que ya no volvería por aquí ¿verdad? pues te has vuelto a equivocar... espero que te cueste trabajo librarte de mí... así que... a aguantar al Guille que aún me queda cuerda "pa" rato... ¡espero!

En esta entrega terminaremos de ver el código del Editor ese con el que llevamos varias entregas "enfangao", si no recuerdo mal, (mirando de reojo al final de la entrega anterior), lo que tenemos pendiente es:

Usar detección de errores, al menos al acceder a los cuadros de diálogos,
Seleccionar la impresora a usar e imprimir el contenido del texto que hemos escrito... 
además de las "respuestas" a los ejercicios "camuflados"... ya veremos en que queda todo esto... (es que los ejercicios yo aún no los he resuelto... je, je, en fin...)

Empecemos por:

La detección de errores al usar los cuadros de diálogos

Cuando pulsas en el botón cancelar del cuadro de diálogo no hay forma de saber que se ha pulsado ese botón... pero lo lógico es hacer algo en particular si así ha sido... ¿verdad? (si bwana), pues eso... vamos a ver cómo "detectar" que se ha pulsado en Cancelar...

Para lograr esto, usaremos la instrucciones:
On Error Resume Next

Cuando Visual Basic se encuentra con esta instrucción continuará a pesar de que ocurran errores...
¿de que sirve el que continúe cuando se produce un error?
La verdad es que de nada si no tenemos en cuenta ese "detalle", por tanto, si usamos esa instrucción, tendremos que ser consecuentes con nuestros actos... (Guille, eso te ha quedado en plan sermón... no se si lo aguantaré...)

La forma de saber que se ha producido un error es comprobarlo... ¿cómo? usando la propiedad Number del objeto Err, o lo que es lo mismo la propiedad por defecto del objeto Err, por tanto podemos hacerlo de dos formas:

If Err.Number Then...

o

If Err Then...

El resultado es el mismo: si se ha producido un error se ejecutará el código que esté después del Then...

Veamos esto que te estoy contando en el código de abrir y de camino vemos la respuesta:

'
Private Sub mnuFicAbrir_Click()
    ' Comprobar si el texto se ha modificado
    ' si es así, guardarlo o no, según la respuesta del usuario
    Dim ret As Long

    If Modificado Then
        ret = MsgBox("El fichero se ha modificado, ¿quieres guardarlo?", vbYesNoCancel)
        ' Si hemos contestado "Si"
        If ret = vbYes Then
            ' Guardarlo
            mnuFicGuardar_Click
        ' Si pulsamos el botón Cancelar, salimos del procedimiento
        ElseIf ret = vbCancel Then
            Exit Sub
        End If
    End If

    ' Usar detección de errores para saber si se ha pulsado en cancelar
    On Error Resume Next

    With CommonDialog1
        ' Esto hará que VB devuelva un error al pulsar Cancelar
        .CancelError = True
        '
        .DialogTitle = "Seleccionar un fichero para abrilo"
        .FileName = NombreFichero
        .ShowOpen
        ' Si no se ha producido ningún error,
        ' es que NO se ha pulsado en Cancelar
        If Err.Number = 0 Then
            If Len(.FileName) Then
                NombreFichero = .FileName

                ' Abrir el fichero y asignarlo al textbox
                Dim nFic As Long
                Dim sTmp As String

                nFic = FreeFile
                Open .FileName For Input As nFic
                sTmp = Input$(LOF(nFic), nFic)
                Close nFic

                ' Asignarlo al textbox
                txtEditor.Text = sTmp

                Modificado = False
            End If
        End If
    End With
    ' Es buena costumbre volver a ponerlo a cero...
    Err = 0
End Sub

Como ves no tiene mayor problema comprobar si el contenido del fichero ha cambiado y preguntar si queremos guardarlo, etc. (me estoy refiriendo al ejercicio que había al principio del procedimiento de abrir), en el procedimiento de Guardar se comprueba si hay algún nombre asignado y si no es así, se preguntará por ese nombre... de eso se encargan los procedimientos de Guardar y Guardar como...
Para hacer la pregunta he usado un MsgBox, pero con tres opciones: Si, No y Cancelar... por si nos arrepentimos y no queremos guardar el contenido del textbox con el nombre por defecto, por ejemplo...

En cuanto a la detección de errores... primero ponemos las instrucciones esas que vimos hace un rato... en el Cuadro de diálogos se asigna a True la propiedad .CancelError, con esto se le dice al Visual Basic que si se pulsa en Cancelar, produzca un error detectable, (el número 32755), por tanto, después del .ShowOpen comprobamos si NO se ha producido un error, en ese caso quiere decir que se puede continuar, ya que si se produce un error, no hacemos nada y se continúa con el resto del código... que por cierto es ninguno, ya que el código restante está dentro del If Then... salvo el volver a poner el número del objeto Err a cero, para que no se quede ningún número de error "colgado" y pueda interferir en otros procedimientos.

Sigue este link y aprenderás un poco más sobre esto de la detección de errores.

 

En cuanto a la respuesta de cómo abrir el fichero y asignarlo al textbox, ya tenias la respuesta en la parte de mezclar... o casi, pero como ves es bastante simple y no hay que hacer nada del otro mundo.
Simplemente abrimos el fichero, leemos el TOTAL del contenido del mismo y lo asignamos a una variable y después lo asignamos al TextBox, aunque podríamos haberlo asignado directamente... pero es que tengo costumbre de usar variables intermedias... cosas... en fin...

Fíjate que después de abrir el fichero se asigna el valor False a la variable Modificado, esto es para que se sepa que el contenido no se ha modificado después de asignar el contenido al textbox... aunque creo que esto ya lo expliqué en otra ocasión... ¿no? la verdad es que no me acuerdo, así que mejor son dos que ninguna...

Veamos ahora:

Cómo seleccionar la impresora a usar por nuestra aplicación.

Para hacer esto, usaremos también el Common Dialog que tenemos insertado en nuestro formulario:

'
Private Sub mnuFicImpSelec_Click()
    ' Seleccionar la impresora a usar                               (23/Ene/00)

    ' La detección de errores es por si no hay impresora instalada
    On Error Resume Next

    With CommonDialog1
        .DialogTitle = "Seleccionar impresora"
        .Flags = cdlPDPrintSetup
        .ShowPrinter
    End With

    Err = 0
End Sub

El truco está en usar el valor cdlPDPrintSetup como valor para la propiedad Flags del cuadro de diálogo y después, por supuesto, usar el método ShowPrinter; cuando el control de diálogos comunes se encuentra con ese "flag" sabe que debe mostrar el cuadro de diálogo de configurar impresora, desde el cual podemos seleccionar otra de las impresoras instaladas en el sistema.

Nota:
Los valores a usar con Flags puedes averiguarlos pulsando F1 sobre la propiedad Flags, la ayuda te dará una lista de los valores posibles.

 

Ahora veamos:

Cómo imprimir el contenido de la caja de textos.

En esta ocasión también usaremos el Cuadro de Diálogo pero, para saber cuantas copias quiere el usuario imprimir,  si la quiere en horizontal o vertical, etc., etc. (aunque esto último se suele hacer al configurar la impresora, no al imprimir).

'
Private Sub mnuFicImpImp_Click()
    ' Imprimir el contenido del TextBox en la impresora             (23/Ene/00)

    On Error Resume Next

    ' Averiguamos cuantas copias quiere el usuario y dejamos que elija otras cosas,
    ' el propio cuadro de diálogo nos lo permitirá hacer...
    With CommonDialog1
        .CancelError = True
        .DialogTitle = "Imprimir"
        ' cdlPDHidePrintToFile  No mostrar el botón de imprimir en un archivo
        ' cdlPDNoPageNums       No mostrar desde que página imprimir, etc.
        ' CdlPDUseDevModeCopies Dejar al SO que se encargue de imprimir las copias
        '                       En caso de que la impresora no lo soporte, estará
        '                       deshabilitada la opción del número de copias.
        .Flags = cdlPDHidePrintToFile Or cdlPDNoPageNums Or cdlPDUseDevModeCopies
        .ShowPrinter
        ' Si no se ha cancelado
        If Err = 0 Then
            ' En la propiedad .Copies estará el número de copias a imprimir.
            ' Hay casos en los que las impresoras "automáticamente" usan ese valor,
            ' por tanto si no queremos hacer un bucle para imprimir el número de
            ' copias solicitadas, podemos dejar que sea el propio sistema el que
            ' se encargue de esa cuestión...
            ' El problema, cuando la impresora no permite imprimir varias copias
            ' Para simplificar, dejaremos que sea el propio O.S. el que se encargue
            '
            ' Imprimimos el contenido del textbox... simple, ¿verdad?
            Printer.Print ""
            Printer.Print txtEditor.Text
            Printer.EndDoc
        End If
    End With
End Sub

También podríamos hacerlo más complicado, de forma que podamos controlar cada una de las líneas a imprimir... no es que tenga ninguna utilidad práctica, pero así sabes como controlar el contenido de cada una de las líneas de un TextBox Multiline, por ejemplo puedes usarlo para hacer que el texto esté justificado, etc... aunque no se si esa parte la veremos en el curso básico... ya veremos.

 

Cómo controlar cada línea de un TextBox Multiline

Esta tarea está contenida en un procedimiento, el cual recibe como parámetro un TextBox Multiline el cual contendrá el texto a imprimir; el hacerlo de esta forma, en lugar de usar directamente el control txtEditor, es para los casos en que necesitemos una rutina genérica o bien porque tengamos más textboxes en nuestro proyecto...

Para usarlo simplemente se haría:

ImprimirPorLinea txtEditor

Este es el contenido del mencionado procedimiento.

'
Private Sub ImprimirPorLinea(qControl As TextBox)
    ' Este procedimiento tomará cada línea de un textbox multiline  (23/Ene/00)
    ' y lo imprimirá en la impresora predeterminada
    '
    ' El parámetro qControl, será el TextBox a usar, en este caso no es necesario
    ' ya que sólo tenemos un TextBox, pero si se usaran varios...
    ' sería un procedimiento de uso genérico...
    '
    Dim i As Long, k As Long
    Dim L1 As Long, L2 As Long
    ' Constantes para usar con SendMessage
    Const EM_GETLINECOUNT = &HBA
    Const EM_LINEFROMCHAR = &HC9
    Const EM_LINELENGTH = &HC1

    ' Número de líneas del TextBox
    k = SendMessage(qControl.hWnd, EM_GETLINECOUNT, 0, 0&)

    Printer.Print ""
    For i = 0 To k - 1
        ' Primer carácter de la línea actual
        L1 = SendMessage(qControl.hWnd, EM_LINEINDEX, i, 0&) + 1
        ' Longitud de la línea actual
        L2 = SendMessage(qControl.hWnd, EM_LINELENGTH, L1, 0&)
        ' Imprimimos el trozo de texto que representa a una línea
        Printer.Print Mid$(qControl.Text, L1, L2)
    Next
    ' Le indicamos que ya no hay más que imprimir
    Printer.EndDoc
End Sub

Esto es todo, al menos por ahora, aunque aún queda por hacer la parte de Buscar y Reemplazar, pero eso lo dejaremos para otra ocasión, ya que si no se iba a alargar más de la cuenta el tema y no es plan, como adelanto te diré que seguramente, lo programaremos usando clases, que ya va siendo hora de que entremos de lleno en ese mundo tan desconocido para unos y casi tan mágico para otros... o casi... aún así, espero que no tengas queja... ya que esta entrega ha valido por dos... o más... ahora, a esperar a la siguiente...  paciencia, paciencia... 

Nos vemos
Guillermo


 
entrega anterior ir al índice siguiente entrega

Ir al índice principal del Guille