Colaboraciones en el Guille

Personalizar celulares Motorola Vxxx

(Editando los SEEMS con una aplicación escrita en VB .NET)

 

Fecha: 27/Ene/2006 (26/01/2006)
Autor: Pablo Tilli - tillipablo@gmail.com

 


En este tutorial veremos como crear una pequeña aplicación en VB .NET, para modificar los SEEMS de los celulares (móviles, como le llaman por otros pagos) Motorola Vxxx. Especificamente, lo he probado con los modelos v186, v220, v220i y v300, aunque debería funcionar con el resto de los modelos Vxxx.

Para los que se esten preguntando de que se trata esto de "modificar los SEEMS" y para que sirve, voy a hacer una breve introducción.

Introducción

Los telefonos celulares actuales presentan una gran cantidad de funciones, llendo mucho mas alla de brindar sólo la posibilidad de hablar; y de hecho, podemos decir que: "hablar por telefono", es solo una función mas. Día a día se parecen mas a una de nuestras computadoras de escritorio: Internet, juegos, aplicaciones, e-mail, chat, etc.

El vocabulario que usamos para referirnos a muchas de las acciones que hacemos en la computadora y en el celular, es cada vez mas parecido: instalar y desinstalar programas, configurar, personalizar, guardar, eliminar y renombrar archivos, espacio disponible, cantidad de memoria y una larga lista de términos mas.

Claro esta, que las diferencias en cuanto a capacidad de procesamiento, almacenamiento, tamaño de la pantalla, etc. son enormes, pero si nos remontamos a un par de años atrás, nos daremos cuenta que estos pequeños equipos, superan a las PCs de esos tiempos en muchos aspectos; por lo que no seria de extrañar que tuvieramos celulares con procesadores cada vez mas rápidos, mayor capacidad de almacenamiento y mas cantidad de memoria, entre otras características.

En forma casi natural, para los que estamos en el mundo de la programación, al utilizar un programa en nuestra computadora, siempre nos interesa tratar de ver como funciona, como lo podemos configurar, modificar, mejorar, buscar opciones que a simple vista no se encuentran, y todo lo referido a investigarlo, para conocerlo a fondo y así poder trabajar de manera comoda con el programa o tal vez crear otra versión nosotros mismo desde cero y a nuestro gusto.

Al ver a los telefonos celulares cada vez mas parecidos a una computadora de escritorio, esto despierta en uno ese instinto casi natural del que hablaba antes, y es por eso que me puse a investigar un poco, para lograr habilitar (y deshabilitar) opciones ocultas, cambiar ciertos comportamientos, o el aspecto del celular; como lo hariamos con nuestra computadora.

Como punto de partida, debemos saber que cuando vamos navegando por los distintos menues de nuestro celular, y cambiamos opciones, lo que estamos haciendo es modificar ciertos archivos y SEEMS del equipo. Los SEEMS son pequeñas porciones de la memoria del celular, donde se encuentra la mayor parte de la información referida a la configuración del mismo. Muchas de las funciones de los telefonos celulares, no se pueden modificar desde la propia interfaz del equipo, y es aquí donde entra en juego este tutorial, con el cual desarrollaremos una aplicación en VB .NET, para poder editar estos SEEMS a los que haciamos referencia.

Con la aplicación que desarrollaremos, podremos modificar 6 opciones de los celulares Motorola Vxxx:

1- Habilitar/deshabilitar el cargador de aplicaciones Java.

2- Habilitar/deshabilitar la animación de Motorola al encender el telefono.

3- Habilitar/deshabilitar la animación de Motorola al apagar el telefono.

4- Personalizar el texto de la pantalla externa.

5- Personalizar el sonido de encendido.

6- Personalizar el sonido de apagado.

Esto no quiere decir que sea lo único que podemos modificar, pero intente elegir las opciones mas comunes que creo la mayoría de la gente quiere cambiar de su telefono, al poco tiempo de adquirirlo.

Antes de ponernos a trabajar en nuestra aplicación, necesitamos saber como descargar y subir un SEEM al telefono. Para llevar a cabo esta tarea, primero lo debes conectar a la computadora (vía cable, infrarrojo, etc) y tener instalado los drivers necesarios para que tu celular sea reconocido correctamente. Una vez que tu celular esta instalado, podemos proseguir a descargar un SEEM del celular.

Descargar un SEEM

Uno de los programas mas utilizados para descargar y subir SEEMS, es el P2K Phone File Manager. A continuación mostrare un ejemplo de como descargar el SEEM 0032_0001 (que es uno de los que usaremos).

Al abrir el P2K Manager, este detecta el celular que tenemos conectado y cargara la lista de archivos que se encuentran en el telefono. En la imagen que se presenta a continuación, se puede ver que el telefono se encuentra conectado y que es un Motorola v220 (Ver en la parte izquierda de la barra de estado).

P2KMan - Descargar SEEM

Imagen 1

Si todo va bien, estamos en condiciones de descargar el SEEM. Para esto, en la sección donde dice SEEM, ponemos el numero 0032 en el campo "De:" y el numero 0001 en el campo "a:" (Como se muestra en la imagen 1). Luego pulsamos el botón "Bajar Seem" y nos aparecera un cuadro de dialogo para elegir donde guardar el archivo. Como nombre de archivo dejamos el que nos sugiere (xxxx_yyyy.seem), con lo cual, en este caso, el nombre del archivo seria 0032_ 0001.seem. Listo, ya hemos bajado un SEEM.

Ahora, nos queda bajar dos SEEMS mas con los que trabajaremos, estos son: El SEEM 004a_0001 y el 0061_0001. O sea, una vez que bajaste el 0032_0001, escribes 004a en el campo "De:" y el valor 0001 en el campo "a:" de la sección Seem, y pulsas nuevamente el botón "Bajar seem", y así sucesivamente con todo lo que necesites bajar.

Subir un SEEM

Al igual que para descargar un SEEM, usaremos el P2K Manager para subirlo. Los pasos para subir un SEEM son básicamente los mismos que para bajarlo. En este caso, si quisiéramos subir el SEEM 0032_0001 escribiríamos el numero 0032 en el campo "Seem:" y el numero 0001 en el campo "rec" (Como se muestra en la imagen 2). Luego pulsamos el botón "Subir seem" y elegimos el archivo 0001_0032.seem que bajamos anteriormente.

P2KMan - Subir SEEM

Imagen 2

¿Como se modifica un SEEM?

Un SEEM no es mas que un conjunto de bytes, donde cada uno de estos representa alguna característica del celular. Por ejemplo, si abrimos el SEEM 0061_0001 con un editor hexadecimal veremos algo como esto:

Hex SEEM 0061_0001

Imagen 3

La idea básica detras de nuestro proyecto es saber que bytes debemos modificar y con que valores, para que al volver a subir el SEEM al celular logremos nuestro objetivo. Nosotros no lo modificaremos con un editor hexadecimal, sino que haremos un pequeña aplicación que se encargara de esto, de una manera mucho mas amigable.

Conclusión

Espero no haberte aburrido con toda esta introducción; pero creo que era lo básico que debías saber para poder continuar con este proyecto. Como resumen podemos decir que para personalizar nuestro celular modificando sus SEEMS, tenemos tres pasos básicos:

1- Bajar un SEEM

2- Modificar el SEEM bajado

3- Subir el SEEM modificado

Ya vimos como cumplir con el primero y el tercer paso, así que ahora solo nos queda trabajar en el segundo punto, por lo tanto... EMPECEMOS.

 

IMPORTANTE

1- Antes de modificar un SEEM, GUARDA una copia del archivo original, por si algo falla o quieres volver tu celular al estado original.

2- Luego de subir los SEEMS modificados, deberás apagar y volver a encender el equipo, para que los cambios tengan efecto

 

Desarrollando la aplicación

Clase cSeem

Objetivo

Esta sera la clase base que contiene las funciones comunes para trabajar con los SEEMS, y a partir de la cual crearemos otras clases que manipulen cada SEEM en particular.

Propiedades

NombreArchivo: Guarda y retorna el nombre del archivo (con la ruta completa) del SEEM que se quiere editar.

Metodos

Public Sub Abrir()

Carga en memoria el archivo especificado en la propiedad NombreArchivo para su edición.

Public Sub ModificarUnByte(ByVal NumByte As Long, ByVal Valor As Byte)

Modifica el contenido del byte especificado por el parametro "NumByte", con el contenido del parametro "Valor".

Public Function LeerUnByte(ByVal NumByte As Long) As Byte

Lee y retorna el contenido almacenado en el byte especificado por el parametro "NumByte"

Public Function LongitudDelArchivo() As Long

Retorna la longitud del archivo cargado tras ejecutar el metodo Abrir().

Public Sub GuardarArchivo()

Guarda el archivo con las modificaciones que hallamos realizado.

Código

Public Class cSeem
  'Nombre del archivo (con el path completo) del seem a editar
  Private m_NombreArchivo As String

  'Array que contiene el archivo cargado en memoria
  Private m_InfoArchivo() As Byte

  'Guarda la longitud del archivo
  Private m_LongitudDelArchivo As Long

  Public Property NombreArchivo() As String
     Get
        Return m_NombreArchivo
     End Get

     Set(ByVal Value As String)
        m_NombreArchivo = Value 
     End Set
  End Property

  Public Sub Abrir()
     Dim NumArch As Integer

     NumArch = FreeFile()

     'Abro el SEEM en modo binario
     FileOpen(NumArch, Me.NombreArchivo, OpenMode.Binary)

     m_LongitudDelArchivo = FileLen(Me.NombreArchivo)

     'Redimensiono el array que contendra el archivo, para poder cargarlo
      ReDim m_InfoArchivo(Me.LongitudDelArchivo - 1)

     'Cargo el SEEM en memoria
     FileGet(NumArch, m_InfoArchivo)

     FileClose(NumArch)
  End Sub

  Public Sub ModificarUnByte(ByVal NumByte As Long, ByVal Valor As Byte)
     'Modifico el archivo cargado en memoria,
     '  cambiando el contenido del byte especificado

     m_InfoArchivo(NumByte) = Valor
  End Sub

  Public Function LeerUnByte(ByVal NumByte As Long) As Byte
     'Retorno el valor del byte solicitado del archivo cargado en memoria
     Return m_InfoArchivo(NumByte)
  End Function

  Public Function LongitudDelArchivo() As Long
     Return m_LongitudDelArchivo
  End Function

  Public Sub GuardarArchivo()
     Dim NumArch As Integer

     NumArch = FreeFile()

     FileOpen(NumArch, Me.NombreArchivo, OpenMode.Binary)

     'Guardo el SEEM modificado
     FilePut(NumArch, m_InfoArchivo)

     FileClose(NumArch)
  End Sub

End Class


Clase cSeem0032_0001

Objetivo

Esta clase se deriva de la clase cSeem, y contiene 3 propiedades para modificar el SEEM 0032_0001.

Propiedades

Public Property HabilitarCargadorDeAplicacionesJava() As Boolean

Habilita o deshabilita el cargador de aplicaciones Java. Esta opción nos permite cargar aplicación Java a nuestro celular sin necesidad de descargarlas desde Internet, sino que basta con que el telefono se encuentre conectado a nuestra computadora y usemos un programa como el Midway para subir las aplicaciones que queramos.

Public Property MostrarAnimacionDeMotorolaAlInicio() As Boolean

Habilita o deshabilita la animación de Motorola, que se muestra al encender el telefono, la cual puede resultar molesta despues de verla varias veces.

Public Property MostrarAnimacionDeMotorolaAlApagar() As Boolean

Habilita o deshabilita la animación de Motorola, que se muestra al apagar el telefono, la cual al igual que la de inicio, puede resultar molesta despues de un tiempo.

Código

Public Class cSeem0032_0001
   Inherits cSeem

   Public Property HabilitarCargadorDeAplicacionesJava() As Boolean
      Get
         'Si el valor guardado en el byte 67 es el &HF7...
         If Me.LeerUnByte(67) = &HF7 Then
            '...el cargador de aplicaciones Java esta habilitado
            Return True
         Else
            '...el cargador de aplicaciones Java esta deshabilitado
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor &HF7 en el byte 67, para
            '    habilitar el cargador de aplicaciones Java
            Me.ModificarUnByte(67, &HF7)
         Else
            'Establezco el valor &HF6 en el byte 67, para
            '    deshabilitar el cargador de aplicaciones Java
            Me.ModificarUnByte(67, &HF6)
         End If
      End Set
   End Property

   Public Property MostrarAnimacionDeMotorolaAlInicio() As Boolean
      Get
         'Si el valor guardado en el byte 29 es el &H38...
         If Me.LeerUnByte(29) = &H38 Then
            '...la animacion de Motorola al encender el tel. esta habilitada
            Return True
         Else
            '...la animacion de Motorola al encender el tel. esta deshabilitada
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor &H38 en el byte 29, para
            '    habilitar la animacion de Motorola al encender el tel.
            Me.ModificarUnByte(29, &H38)
         Else
            'Establezco el valor &H30 en el byte 29, para
            '    deshabilitar la animacion de Motorola al encender el tel.
            Me.ModificarUnByte(29, &H30)
         End If
      End Set
   End Property

   Public Property MostrarAnimacionDeMotorolaAlApagar() As Boolean
      Get
         'Si el valor guardado en el byte 49 es el &H2D...
         If Me.LeerUnByte(49) = &H2D Then
            '...la animacion de Motorola al apagar el tel. esta habilitada
            Return True
         Else
            '..la animacion de Motorola al apagar el tel. esta deshabilitada
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor &H2D en el byte 49, para
            '    habilitar la animacion de Motorola al apagar el tel.
            Me.ModificarUnByte(49, &H2D)
         Else
            'Establezco el valor &H2C en el byte 49, para
            '    deshabilitar la animacion de Motorola al apagar el tel.
            Me.ModificarUnByte(49, &H2C)
         End If
      End Set

   End Property

End Class

Clase cSeem004a_0001

Objetivo

Esta clase se deriva de la clase cSeem, y contiene 3 propiedades para modificar el SEEM 004a_0001.

Propiedades

Public Property UsarTextoPantallaExteriorPersonalizado() As Boolean

Habilita o deshabilita la posibilidad de usar un texto personalizado en la pantalla exterior del celular, cuando la tapa de este se encuentra abierta. Si se activa esta opción, luego se debe modificar el SEEM 0061_0001 con el texto personalizado que se desea mostrar.

Public Property UsarSonidoDeInicioPersonalizado() As Boolean

Si esta propiedad se activa, podremos reproducir un sonido personalizado al encender nuestro telefono. Tras activar esta opción, el celular usara como sonido de inicio, el archivo que se llame Cust_Start~up.mp3.

Public Property UsarSonidoDeApagadoPersonalizado() As Boolean

Si esta propiedad esta activada, podremos reproducir un sonido personalizado al apagar nuestro telefono. Tras activar esta opción, el celular usara como sonido de apagado, el archivo que se llame Power~down.mp3.

Código

Public Class cSeem004a_0001
   Inherits cSeem

   Public Property UsarTextoPantallaExteriorPersonalizado() As Boolean
      Get
         'Si el valor guardado en el byte 39 es el 1...
         If Me.LeerUnByte(39) = 1 Then
            '...el texto personalizado de la pantalla exterior
            '   esta habilitado
            Return True
         Else
            '...el texto personalizado de la pantalla exterior
            '   esta deshabilitado
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor 1 en el byte 39, para
            '    habilitar el texto personalizado de la pantalla exterior
            Me.ModificarUnByte(39, 1)
         Else
            'Establezco el valor 2 en el byte 39, para
            '    deshabilitar el texto personalizado de la pantalla exterior
            Me.ModificarUnByte(39, 2)
         End If
      End Set
   End Property

   Public Property UsarSonidoDeInicioPersonalizado() As Boolean
      Get
         'Si el valor guardado en el byte 34 es el 1...
         If Me.LeerUnByte(34) = 1 Then
            '...el sonido de inicio personalizado esta habilitado
            Return True
         Else
            '...el sonido de inicio personalizado esta deshabilitado
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor 1 en el byte 34, para
            '    habilitar el sonido de inicio personalizado
            Me.ModificarUnByte(34, 1)
         Else
            'Establezco el valor 0 en el byte 34, para
            '    deshabilitar el sonido de inicio personalizado
            Me.ModificarUnByte(34, 0)
         End If
      End Set
   End Property

   Public Property UsarSonidoDeApagadoPersonalizado() As Boolean
      Get
         'Si el valor guardado en el byte 36 es el 1...
         If Me.LeerUnByte(36) = 1 Then
            '...el sonido de apagado personalizado esta habilitado
            Return True
         Else
            '...el sonido de apagado personalizado esta deshabilitado
            Return False
         End If
      End Get

      Set(ByVal Value As Boolean)
         If Value = True Then
            'Establezco el valor 1 en el byte 36, para
            '    habilitar el sonido de apagado personalizado
            Me.ModificarUnByte(36, 1)
         Else
            'Establezco el valor 0 en el byte 36, para
            '    deshabilitar el sonido de apagado personalizado
            Me.ModificarUnByte(36, 0)
         End If
      End Set
   End Property

End Class

Clase cSeem0061_0001

Objetivo

Esta clase se deriva de la clase cSeem, y contiene 1 sola propiedad para modificar el SEEM 0061_0001.

Propiedades

Public Property TextoPantallaExterior() As String

Esta propiedad nos permite leer o especificar el texto que se muestra en la pantalla exterior del celular (Si la tapa esta abierta). Para que este texto se muestre, debemos activar la opción en el SEEM 004a_0001.

Código

Public Class cSeem0061_0001
   Inherits cSeem

   '1- El texto personalizado de la pantalla exterior, se guarda en UNICODE,
   '   por lo que cada caracter ocupa dos bytes, por ejemplo: si tenemos
   '   guardada la cadena "AB", al leerla de a un byte obtendriamos lo siguiente:
   '
   '     41   00   42   00
   '
   '   O sea: leemos cuatro bytes para dos caracteres, por lo que al guardar el archivo, guardo
   '   primero el ASCII del caracter y luego un byte con el valor "00".
   '   Si alguien tiene otra solucion mas optima, por favor comunicarse conmigo a
   '   mi e-mail (tillipablo@gmail.com)
   '
   '2- Otra cuestion a saber, es que al finalizar el texto personalizado guardado
   '   en el archivo, hay un byte con el valor 00 y luego se rellena hasta
   '   completar 48 bytes con el ASCII 255.
   '
   '3- Por ultimo, decir que el primer byte contiene el valor "00".

   Public Property TextoPantallaExterior() As String
      Get
         Dim Texto As String = ""
         Dim i As Integer
         Dim Caracter As Byte

         'Recorro el archivo cargado en memoria, byte a byte
         For i = 0 To LongitudDelArchivo - 1
            'Leo un byte
            Caracter = LeerUnByte(i)

            'Si el byte leido no es "0" y tampoco "255" (ya que esto es relleno)
           If (Caracter > 0) And (Caracter < 255) Then
              'Voy armando la cadena
              Texto = Texto & Chr(Caracter)
           End If
         Next

         Return Texto
      End Get

      Set(ByVal Texto As String)
         Dim i As Integer 'Numero de byte guardado

         'Indica que caracter se esta leyendo del texto a guardar
         Dim PosEnTextoOriginal As Integer

         PosEnTextoOriginal = 1

         'El primer byte del archivo debe ser 00
         ModificarUnByte(0, 0)

         i = 1

         'Guardo 48 bytes en el archivo
         Do While i < 48
            If PosEnTextoOriginal <= Texto.Length Then
               'Guardo el ASCII del caracter
               ModificarUnByte(i, Asc(Mid(Texto, PosEnTextoOriginal, 1)))

               'Guardo un 0, para completar los dos bytes del caracter UNICODE
               ModificarUnByte(i + 1, 0)

               i = i + 2

               If PosEnTextoOriginal = Texto.Length Then
                  'Al terminar el texto, y antes del relleno, debe haber un
                  'byte con el valor 00
                  ModificarUnByte(i, 0)
                  i += 1
               End If

               'Avanzo una posicion en la cadena de texto que estoy guardando
               PosEnTextoOriginal = PosEnTextoOriginal + 1
            Else
               'Guardo un byte de relleno con el valor 255
               ModificarUnByte(i, 255)

               i = i + 1
            End If
         Loop
      End Set
   End Property

End Class

 

Formulario frmAdministrador

frmAdminsitrador

Imagen 4

Descripción

Este formulario, posee un control TabControl, con tres TabPages: 0032_0001, 004a_0001 y 0061_0001 (Como se puede ver en la imagen 4). En tiempo de diseño cada TabPage esta vacía, ya que luego en tiempo de ejecución, se le asignara en forma dinámica un formulario a cada una. De esta se forma se nos hara mas fácil mantener la aplicación si luego queremos agregar nuevos formularios editores de SEEMS.

Podemos ver que posee una "barra de estado", que nos informa del estado del archivo ("Cerrado", "Cargado y GUARDADO" y "Cargado y SIN GUARDAR").

Por ultimo, podemos notar que existen tres botones que se explican por si solos: "Abrir", "Guardar" y "Cerrar Archivo".

Código

Option Strict Off
Option Explicit On

Public Class frmAdministrador
    Inherits System.Windows.Forms.Form

#Region "Código generado por el Diseñador de Windows Forms"

    'Declaro los editores de cada SEEM
    Private EditorSeem0061_0001 As New frmEditorSeem0061_0001()
    Private EditorSeem004a_0001 As New frmEditorSeem004a_0001()
    Private EditorSeem0032_0001 As New frmEditorSeem0032_0001()

    'Creo una coleccion para poder recorrer de manera sencilla,

    'los editores de SEEMS
    Private EditoresDeSeems As New Collection()

    'Hace referencia al editor de SEEM que el usuario esta usando
    Private EditorDeSeemActivo As frmEditorDeSeem

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Agrego los editores al control TabControl

        Call AgregarEditor(tpSeem0061_0001, EditorSeem0061_0001)
        Call AgregarEditor(tpSeem004a_0001, EditorSeem004a_0001)
        Call AgregarEditor(tpSeem0032_0001, EditorSeem0032_0001)

        'Establezco el editor activo de inicio
        EditorDeSeemActivo = EditorSeem0032_0001
    End Sub

    Private Sub AgregarEditor(ByVal Solapa As TabPage, ByVal FormularioDeEdicion As frmEditorDeSeem)
        With FormularioDeEdicion
            .FormularioPadre = Me

            .TopLevel = False

            'Agrego el editor de SEEM (FormularioDeEdicion) a la
            'solapa especificada por el parametro "Solapa"
            Solapa.Controls.Add(FormularioDeEdicion)

            'Modifico el tamaño del editor para que ocupe toda la
            'superficie del TabPage

            .SetBounds(0, 0, Solapa.Width - 110, Solapa.Height) 'Le resto 110 al ancho, para descontar
                                                                'los bordes laterales
            .Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top

            'Muestro el editor

            .Show()
        End With

        'Agrego el editor de SEEM a la coleccion de editores
        EditoresDeSeems.Add(FormularioDeEdicion)
    End Sub

    Private Sub btnAbrir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                                                                      Handles btnAbrir.Click
        'Creo un filtro para que aparezca el nombre del archivo que se debe cargar

        Me.OpenSeemDialog.Filter = EditorDeSeemActivo.NombreDelArchivoOriginal & _
                                         "|" & EditorDeSeemActivo.NombreDelArchivoOriginal

        'Muestro el dialogo de Abrir SEEM
        Me.OpenSeemDialog.ShowDialog()
    End Sub

    Private Sub OpenSeemDialog_FileOk(ByVal sender As Object, _ 
                                      ByVal e As System.ComponentModel.CancelEventArgs) _
                                                            Handles OpenSeemDialog.FileOk
        'Establezco el nombre del archivo que eligio el usario para abrir

        EditorDeSeemActivo.NombreDelArchivo = OpenSeemDialog.FileName

        'Cargo el SEEM en el editor activo
        EditorDeSeemActivo.CargarSeem()
    End Sub

    Private Sub btnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                                                                      Handles btnGuardar.Click
        'Guardo el SEEM modificado

        EditorDeSeemActivo.GuardarSeem()
    End Sub

    Private Sub tcSeems_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
                                                               Handles tcSeems.SelectedIndexChanged
        'Establezco el editor de SEEM activo

        EditorDeSeemActivo = Me.tcSeems.SelectedTab.Controls(0)

        'Actualizo la barra de estado, segun el estado de edicion en el que se encuentra el 
        'archivo del editor activo
        Call Me.CambiarEstadoDelArchivo(EditorDeSeemActivo.EstadoDelArchivo)
    End Sub

    Public Sub CambiarEstadoDelArchivo(ByVal Estado As frmEditorDeSeem.eEstadosDelArchivo)

        'Actualizo la barra de estado, segun el parametro "Estado" y habilito o deshabilito  
        'los controles de "Guardar" y "Cerrar archivo"

        Select Case Estado
            Case frmEditorDeSeem.eEstadosDelArchivo.Cerrado
                lblEstadoDelArchivo.Text = "Archivo CERRADO"
                HabilitarControlesDeEdicion(False)

            Case frmEditorDeSeem.eEstadosDelArchivo.Guardado
                lblEstadoDelArchivo.Text = "Archivo cargado y GUARDADO"

                HabilitarControlesDeEdicion(True)
                btnGuardar.Enabled = False

            Case frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
                lblEstadoDelArchivo.Text = "Archivo cargado y SIN GUARDAR"
                HabilitarControlesDeEdicion(True)
        End Select

    End Sub

    Private Sub btnCerrarArchivo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                                                                      Handles btnCerrarArchivo.Click
        'Cambio el estado del SEEM a "Cerrado"

        EditorDeSeemActivo.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Cerrado
    End Sub

    Private Sub HabilitarControlesDeEdicion(ByVal Estado As Boolean)
        'Habilito o deshabilito el boton "Guardar" y "Cerrar archivo"

        btnCerrarArchivo.Enabled = Estado
        btnGuardar.Enabled = Estado
    End Sub

    Private Sub frmAdministrador_Closing(ByVal sender As Object, _
                                         ByVal e As System.ComponentModel.CancelEventArgs) _
                                                                      Handles MyBase.Closing
        Dim UnEditor As frmEditorDeSeem
        Dim HayArchivosSinGuardar As Boolean

        'Al cerrar el programa, determino si hay archivos sin guardar
        For Each UnEditor In EditoresDeSeems
            If UnEditor.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar Then

                HayArchivosSinGuardar = True
                Exit For
            End If
        Next

        'Si hay archivos sin guardar, pregunto si realmente quiere salir o no
        If HayArchivosSinGuardar Then
            If MsgBox("Existen archivos que aún no han sido guardados." & _
                        Chr(Keys.Return) & _
                        "¿Realmente desea salir del programa?", _
                        MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.No Then

            'No salir
            e.Cancel = True
        End If
    End If

End Sub
End Class
 

Formulario frmEditorDeSeem

frmEditorDeSeem

Imagen 5

Descripción

Como podemos ver en la imagen, este formulario no tiene ningún control, sino que la idea aquí es crear un formulario base de edición. de SEEMS, para luego crear nuevos formularios que nos permitan editar cada SEEM en particular.

Código

Public Class frmEditorDeSeem
    Inherits System.Windows.Forms.Form

#Region "Código generado por el Diseñador de Windows Forms"

    'Defino los tres estados de edicion en los que puede estar el 
    'archivo de SEEM
    Public Enum eEstadosDelArchivo
        Cerrado
        SinGuardar
        Guardado
    End Enum

    'Nombre del archivo cargado (podria ser distinto del original)
    Private m_NombreDelArchivo As String

    Private m_EstadoDelArchivo As eEstadosDelArchivo

    'Formulario al que se le debe comunicar informacion acerca del estado de edicion

    Private m_FormularioPadre As Form

    'Nombre original del archivo (Ej: 0032_0001.seem), usado para crear 
    'el filtro del cuadro de dialogo "Abrir SEEM"
    Private m_NombreDelArchivoOriginal As String

    'Evento que informa que el estado de edicion del archivo ha cambiado
    Public Event CambioElEstadoDelArchivo()

    Public ReadOnly Property NombreDelArchivoOriginal() As String

        Get
            Return m_NombreDelArchivoOriginal
        End Get
    End Property

    Public Property NombreDelArchivo() As String
        Get
            Return m_NombreDelArchivo
        End Get

        Set(ByVal Value As String)
            m_NombreDelArchivo = Value
        End Set
    End Property

    Public Property EstadoDelArchivo() As eEstadosDelArchivo
        Get
            Return m_EstadoDelArchivo
        End Get

        Set(ByVal Estado As eEstadosDelArchivo)
            m_EstadoDelArchivo = Estado

            RaiseEvent CambioElEstadoDelArchivo()
            NotificarEstadoDelArchivo()
        End Set
    End Property

    Private Sub frmEditorDeSeem_Load(ByVal sender As System.Object, _
                                     ByVal e As System.EventArgs) Handles MyBase.Load
        'Cuando se carga el editor, el estado de edicion del archivo del SEEM es "cerrado"

        Me.EstadoDelArchivo = eEstadosDelArchivo.Cerrado
    End Sub

    Public Property FormularioPadre() As frmAdministrador
        Get

            Return m_FormularioPadre
        End Get
        Set(ByVal NombreFormulario As frmAdministrador)
            m_FormularioPadre = NombreFormulario
        End Set

    End Property

    Private Sub NotificarEstadoDelArchivo()
        'Si hay un formulario a quien comunicarle el cambio de estado de edicion del archivo, 
        'llamo al metodo "CambiarEstadoDelArchivo" del formulario en cuestion

        If Not (FormularioPadre Is Nothing) Then
            FormularioPadre.CambiarEstadoDelArchivo(Me.EstadoDelArchivo)
        End If

    End Sub

    Public Overridable Function CargarSeem() As Boolean

    End Function

    Public Overridable Function GuardarSeem() As Boolean

    End Function

End Class
 

Formulario frmEditorSeem0032_0001

frmEditorSeem0032_0001

Imagen 6

Descripción

Este formulario hereda de la clase frmEditorDeSeem, y es una interfaz para manejar las tres propiedades de un objeto de la clase cSeem0032_0001.

Código

Public Class frmEditorSeem0032_0001
    Inherits frmEditorDeSeem

#Region "Código generado por el Diseñador de Windows Forms"

   'Objeto para editar el archivo de SEEM 0032_0001
    Private Seem As New cSeem0032_0001()

    Public Overrides Function CargarSeem() As Boolean

        With Seem
            .NombreArchivo = Me.NombreDelArchivo
            .Abrir()

            'Actualizo los controles, segun el archivo leido
            chkHabilitarCargadorApJava.Checked = .HabilitarCargadorDeAplicacionesJava
            chkAnimacionMotorolaAlEncender.Checked = .MostrarAnimacionDeMotorolaAlInicio
            chkAnimacionMotorolaAlApagar.Checked = .MostrarAnimacionDeMotorolaAlApagar
        End With

        'Al cargar el archivo, el estado de edicion de este es: GUARDADO

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado

        Return True
    End Function

    Public Overrides Function GuardarSeem() As Boolean

        'Guardo el archivo del SEEM, con las modificaciones que se le hayan realizado
        With Seem
            .HabilitarCargadorDeAplicacionesJava = chkHabilitarCargadorApJava.Checked
            .MostrarAnimacionDeMotorolaAlInicio = chkAnimacionMotorolaAlEncender.Checked
            .MostrarAnimacionDeMotorolaAlApagar = chkAnimacionMotorolaAlApagar.Checked

            .GuardarArchivo()
        End With

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado
    End Function

    Private Sub frmEditorSeem0061_0001_CambioElEstadoDelArchivo() Handles MyBase.CambioElEstadoDelArchivo
        'Actualizo la interfaz segun el estado de edicion del archivo
        Select Case Me.EstadoDelArchivo
            Case frmEditorDeSeem.eEstadosDelArchivo.Cerrado
                Me.chkHabilitarCargadorApJava.Enabled = False

                Me.chkAnimacionMotorolaAlEncender.Enabled = False
                Me.chkAnimacionMotorolaAlApagar.Enabled = False

            Case Else
                Me.chkHabilitarCargadorApJava.Enabled = True

                Me.chkAnimacionMotorolaAlEncender.Enabled = True
                Me.chkAnimacionMotorolaAlApagar.Enabled = True
        End Select
    End Sub

    Private Sub chkHabilitarCargadorApJava_CheckedChanged(ByVal sender As System.Object, _
                                                          ByVal e As System.EventArgs) _
                                                           Handles chkHabilitarCargadorApJava.CheckedChanged
        'Hubo modificaciones en el archivo

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
    End Sub

    Private Sub chkAnimacionMotorolaAlEncender_CheckedChanged(ByVal sender As System.Object, _
                                                              ByVal e As System.EventArgs) _
                                                       Handles chkAnimacionMotorolaAlEncender.CheckedChanged
        'Hubo modificaciones en el archivo

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
    End Sub

    Private Sub chkAnimacionMotorolaAlApagar_CheckedChanged(ByVal sender As System.Object, _
                                                            ByVal e As System.EventArgs) _
                                                         Handles chkAnimacionMotorolaAlApagar.CheckedChanged
        'Hubo modificaciones en el archivo

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
    End Sub
End Class
 

Formulario frmEditorSeem004a_0001

frmEditorSeem004a_0001

Imagen 7

Descripción

Este formulario hereda de la clase frmEditorDeSeem, y es una interfaz para manejar las tres propiedades de un objeto de la clase cSeem004a_0001.

Código

Public Class frmEditorSeem004a_0001
    Inherits Proyecto1.frmEditorDeSeem

#Region " Código generado por el Diseñador de Windows Forms "

   'Objeto para editar el archivo de SEEM 004a_0001
   Private Seem As New cSeem004a_0001()

   Public Overrides Function CargarSeem() As Boolean

      With Seem
         .NombreArchivo = Me.NombreDelArchivo
         .Abrir()

         'Actualizo los controles, segun el archivo leido
         Me.chkTextoLCDPersonalizado.Checked = .UsarTextoPantallaExteriorPersonalizado
         Me.chkSonidoDeEncendidoPersonalizado.Checked = .UsarSonidoDeInicioPersonalizado
         Me.chkSonidoDeApagadoPersonalizado.Checked = .UsarSonidoDeApagadoPersonalizado
      End With

      'Al cargar el archivo, el estado de edicion de este es: GUARDADO
      Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado

      Return True
   End Function

   Public Overrides Function GuardarSeem() As Boolean

   'Guardo el archivo del SEEM, con las modificaciones que se le hayan realizado
   With Seem
      .UsarTextoPantallaExteriorPersonalizado = Me.chkTextoLCDPersonalizado.Checked
      .UsarSonidoDeInicioPersonalizado = Me.chkSonidoDeEncendidoPersonalizado.Checked
      .UsarSonidoDeApagadoPersonalizado = Me.chkSonidoDeApagadoPersonalizado.Checked

      .GuardarArchivo()
   End With

   Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado

   End Function

   Private Sub chkTextoLCDPersonalizado_CheckedChanged(ByVal sender As System.Object, _
                                                       ByVal e As System.EventArgs) _
                                                             Handles chkTextoLCDPersonalizado.CheckedChanged
      'Hubo modificaciones en el archivo
      Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
   End Sub

   Private Sub chkSonidoDeEncendidoPersonalizado_CheckedChanged(ByVal sender As System.Object, _
                                                                ByVal e As System.EventArgs) _
                                                    Handles chkSonidoDeEncendidoPersonalizado.CheckedChanged
      'Hubo modificaciones en el archivo
      Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
   End Sub

   Private Sub chkSonidoDeApagadoPersonalizado_CheckedChanged(ByVal sender As System.Object, _
                                                              ByVal e As System.EventArgs) _
                                                      Handles chkSonidoDeApagadoPersonalizado.CheckedChanged
      'Hubo modificaciones en el archivo
      Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
   End Sub

   Private Sub frmEditorSeem004a_0001_CambioElEstadoDelArchivo() Handles MyBase.CambioElEstadoDelArchivo
      'Actualizo la interfaz segun el estado de edicion del archivo
      Select Case Me.EstadoDelArchivo
         Case frmEditorDeSeem.eEstadosDelArchivo.Cerrado
            Me.chkSonidoDeApagadoPersonalizado.Enabled = False
            Me.chkSonidoDeEncendidoPersonalizado.Enabled = False
            Me.chkTextoLCDPersonalizado.Enabled = False
         Case Else
            Me.chkSonidoDeApagadoPersonalizado.Enabled = True
            Me.chkSonidoDeEncendidoPersonalizado.Enabled = True
            Me.chkTextoLCDPersonalizado.Enabled = True
      End Select
   End Sub

End Class
 

Formulario frmEditorSeem0061_0001

frmEditorSeem0061_0001

Imagen 8

Descripción

Este formulario hereda de la clase frmEditorDeSeem, y es una interfaz para manejar un objeto de la clase cSeem0061_0001.

Código

Public Class frmEditorSeem0061_0001
    Inherits frmEditorDeSeem

#Region " Código generado por el Diseñador de Windows Forms "

    'Objeto para editar el archivo de SEEM 0061_0001
    Private Seem As New cSeem0061_0001()

    Public Overrides Function CargarSeem() As Boolean

        With Seem
            .NombreArchivo = Me.NombreDelArchivo
            .Abrir()

            'Actualizo los controles, segun el archivo leido
            txtLCDExterno.Text = .TextoPantallaExterior

            With txtLCDExterno
                .Enabled = True
                .SelectAll()
                .Focus()
            End With

        End With

        'Al cargar el archivo, el estado de edicion de este es: GUARDADO
        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado

        Return True
    End Function

    Public Overrides Function GuardarSeem() As Boolean
        'Guardo el archivo del SEEM, con las modificaciones que se le hayan realizado
        With Seem
            .TextoPantallaExterior = txtLCDExterno.Text
            .GuardarArchivo()
        End With

        Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.Guardado
    End Function

    Private Sub txtLCDExterno_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                                                                        Handles txtLCDExterno.TextChanged
        If Me.EstadoDelArchivo <> frmEditorDeSeem.eEstadosDelArchivo.Cerrado Then

            'Hubo modificaciones en el archivo
            Me.EstadoDelArchivo = frmEditorDeSeem.eEstadosDelArchivo.SinGuardar
        End If
    End Sub

    Private Sub frmEditorSeem0061_0001_CambioElEstadoDelArchivo() Handles MyBase.CambioElEstadoDelArchivo
        'Actualizo la interfaz segun el estado de edicion del archivo

        Select Case Me.EstadoDelArchivo
            Case frmEditorDeSeem.eEstadosDelArchivo.Cerrado
                With txtLCDExterno
                    .Text = ""
                    .Enabled = False

                End With

            Case Else
                Me.txtLCDExterno.Enabled = True
        End Select

    End Sub
End Class

 

Hasta aquí hemos llegado por el momento y espero estar escribiendo otro tutorial en breve, y así poder seguir colaborando con este sitio, que tanto me ha ayudado.

Si bien he intentado ser lo mas claro posible, como para que no tengan dudas sobre el proyecto; es casi de seguro que muchos de los que lo lean, si las tendrán, y es por eso que invito a todos ellos a escribirme a mi e-mail (tillipablo@gmail.com) y así intentar resolver las dudas particulares de cada uno, y a los que no le haya quedado ninguna duda, también los invito a escribirme para poder saber su opinión o que me envien sugerencias, para poder seguir mejorando los tutoriales futuros.

Hasta pronto,

Pablo Tilli.


Espacios de nombres usados en el código de este artículo:

System.Windows.Forms

Microsoft.VisualBasic


Fichero con el código de ejemplo: tillipablo_MotorolaVxxxConfig.zip - 26,3 KB

(MD5 checksum: 5d56af951ae8022098431d760db2a1fa)


ir al índice principal del Guille