10 de Agosto de 1998

Truco Juegos II

Continuo con la descripción y explicación de los aspectos más interesantes del programa. Empezando por el borrado de registros, que es un tema que hace algo de tiempo se comentaba en las News. Si has ejecutado el programa, fijate que cuando se va a borra un registro, se muestra un cuadro de dialogo en castellano, y no el mensaje en inglés, que es el mensaje que muestra el control DbGrid por defecto. Lo que hace exactamente el programa es que el borrado del registro actual no se hace por orden del control DbGrid. Sino que la orden proviene de la opción Borrar Regristro del menú Registros. Este es el procedimiento responsable.

procedure TForm1.BorrarRegistro1Click(Sender: TObject);
Var
Boton : Integer;

begin
   Boton := Application.MessageBox ('¿Está seguro que desea borrar este registro',
                              'Borrar registro',MB_YESNO+MB_ICONINFORMATION);
   If Boton = ID_YES Then
    DataModule2.Table1.Delete
   Else
    DataModule2.Table1.Cancel;
end;

Lo que hace este procedimiento es sencillo, lo primero que hace es mostrar el cuadro de dialogo para pedir la conformidad del usuario, y según su valor devuelto toma una decisión. Hay un detalle que quizas despiste, y es que la primera línea hay una variable de tipo entero que recoge el valor devuelto por la función Application.MessageBox. Esto es posible ya que esta función es propia de windows (una Api), y como tal devuelve enteros, y Delphi la tiene definida como tal. La siguiente línea se comprueba el valor contenido en Boton con una constante. Una vez aclarado esto, fijate que si el usuario contesta que si se procede a borrar el registro, sino se cancela el proceso actual de la tabla. Aunque la tabla no esta haciendo nada, por si las moscas decido cancelar.

Por otra parte, si el usuario decide borrar el registro pulsando sobre la barra de navegación, este será borrado y el mensaje no será mostrado siempre y cuando la propiedad ComfirgDelete de la barra de navegación valga Falso.Lo cual nos obliga a tomar cartas en el asunto. Cuando hablé de la barra de navegación comenté que tenia un evento que se producia cuando se registraba la pulsación de un botón, y antes de que se produzca la acción según el botón pulsado.

procedure TForm1.DBNavigator1BeforeAction(Sender: TObject;
  Button: TNavigateBtn);
begin
     If Button = nbDelete Then
      BorrarRegistro1CLick (Sender);
end;

Este procedimiento tiene la variable Button que contiene el identificador del botón pulsado, así que si el botón pulsado (recuerda que este evento se produce para cualquier botón de la barra de navegación) es el de borrado llamo al evento procedimiento que os acabo de comentar.

Este es el sistema que he usado, pero todo esto está sujeto a la condición que el componente Dbgrid no permita la edición, osea que su propiedad ReadOnly valga True. En otras circustancias sino se quiere que apararezca el mensaje en Inglés debemos indicar que no queremos que se muestre mensaje en las propiedades correspondientes de los controles DbGrid y DbNavigator, y mostrar nosotros nuestro propio mensaje. Lo cual se hace en el evento BeforeDelete de la tabla correspondiente. Aqui os pongo un ejemplo de ello.

procedure TForm1.Table1BeforeDelete(DataSet: TDataSet);
Var
 Valor : integer;
begin
 Valor := Application.MessageBox ('¿Borrar este registro?','Borrar un registro',
                                   mb_YESNO+MB_ICONSTOP);
 If Valor = ID_NO Then
   Abort;

end;

Como acabo de comentar que el componente DbGrid no permite la edición e inserción de datos en la tabla porque he puesto su propiedad ReadOnly en True. La opción para editar los datos puede estar la página de detalles, donde hay controles para ello. Pero decidí hacerlo en una ventana propia, para hacer el proceso más amigable al usuario.

Este es el formulario que diseñe. He usado un control DbEdit, un DbMemo y un DbComboBox. Los tres botones que contiene son para añadir un dato y no salir, para salir añadiendo los datos, y para cancelar la operación. Este formulario se no se crea automaticamente cuando arranca la aplicación, sino que es creado cada vez que es necesitado. Sobre la creación que formularios en tiempo de ejecución es algo que no he hablado hasta ahora.

Cada vez que añades un formulario a tu proyecto, Delphi lo añade a la lista de creación automática, así cuando se ejecuta la aplicación se crean todos los formularios, empezando por el principal que es el primero, hasta el último. Esto se puede evitar, dejando solo que se cree el formulario principal, y que los formularios "secundarios" los creemos cuando los necesitamos. La lista de formularios que se crean al arrancar esta el fichero del proyecto, el que tiene extensión DPR, lo puede ver su pulsas Project Source, en el menú View. Pero cuidado no toques ahi, a la ligera, si deseas quitar o añadir un formulario debes usar la ventana que pone Delphi a tu disposición. Para ello pulsa en la opción Options del menú Project. En ella tienes una pestaña que pone Forms, seleccionala y veras dos ListBox, en uno estan los formularios que se crean automaticamente y en el otro los disponibles.

Cuando el usario decide que quiere añadir un registro a la tabla, pulsará la opción correspondiente en un menú, así que es aqui cuando debemos crear el formulario antes de mostrarlo. Vemos como se puede hacer esto.

procedure TForm1.InsertarRegistro1Click(Sender: TObject);
Var
  Form4 : TForm4;
begin
     Form4 := TForm4.Create (Self);

     Try
       Form4.BorderStyle := BsDialog;
       Form4.DBComboBox1.Items := Form1.DBComboBox1.Items;
       Form4.ShowModal;
     Finally
       Form4.Destroy;
       DataModule2.NumeroRegistros (DataModule2.Table1);
     End;
end;

Lo primero es crear el formulario, antes he defino un variable que es del tipo TForm4, lo cual esta definido en la unidad que contiene este formulario. Recuerda que el formulario desde el cual llamas al nuevo, debe hacer referencia al nuevo formulario en la línea uses. Creo el formulario inicializando la variable que he creado (Form4), luego dentro de un bloque Try Finally, hago modificaciones en el formulario, le paso la lista de Temas que esta contenido en el DbComboBox1 del formulario Form1 al DbComboBox del Form4, luego muestro el formulario de manera Modal, cuando retorna el control destruyo el formulario y actualizo el número de registros. El motivo de que exista el bloque Try Finally es que si algo va mal cuando trata de pasarle los datos al formulario recién creado, o cuando trato de mostrar el formulario, me aseguro de que el formulario es destruido (liberando la memoria ocupada), o sino todo ha ido bien tambien libero la memoria.

Cuando se crea el formulario coloca la tabla en modo inserción para poder modificar el valor del registro actual.El formulario tiene tres botones, que son del tipo BitBtn, los cuales al ser pulsado cierran el formulario, pero a mi solo me interesa que se cierre el formulario cuando se pulse el botón Cancelar o Salir. Para ello he declarado una variable a nivel privado que se llama PuedoCerrar y es de tipo lógico. La cual compruebo su valor en el evento OnCloseQuery del formulario. Hay que tener en cuenta que cuando se añade un registro, el nombre del juego no puede existir, ya que la tabla cuando la diseñe indique que el valor de ese campo era único. Si el valor está repetido se produce una excepción. Este es el procedimiento que realiza esta operación.

procedure TForm4.BitBtn1Click(Sender: TObject);
begin
     With DataModule2.Table1 Do
     Begin
     Try
      Post;
     Except
      Application.MessageBox ('El nombre introducido no es correcto'+chr(13)+
                              'El nombre esta repetido, prueba con otro',
                             'Insertar registro',
                             Mb_Ok+Mb_IconStop);
      Cancel;
      Insert;
     End;
      Insert;
     End;

end;

El botón de salir, realiza un par de comprobaciones antes de salir. La primera es avisar si hay campos vacios, si el usuario decide salir de todos modos, se cancela la edición de la tabla, para evitar que haya campos sin datos. Si los campos están correctamente llenos, se trata de guardar los datos, si hay algún error se dispara la excepción, así cancelo la operación de inserción, y se cierra el formulario.

procedure TForm4.BitBtn2Click(Sender: TObject);
begin
     If (DbEdit1.Text = '') or (DbComboBox1.Text = '') Then
      Begin
       IF Application.MessageBox ('No se puede grabar con los campos vacios.'+
           Chr(13)+'¿Deseas salir sin grabar?',
          'Campos vacios',mb_YesNoCancel+MB_IconStop) = idYes Then
          Begin
          DataModule2.Table1.Cancel;
          PuedoCerrar := True;
          End;
       End
       Else
        Begin
         Try
          DataModule2.Table1.Post;
         Except
           DataModule2.Table1.Cancel;
         End;
        PuedoCerrar := True;
       End;
 end;  

Recuerda que el formulario se cierra siempre y cuando la variable PuedoCerrar valga True, ten en cuenta que cuando se crea el formulario, la tabla se pone en modo inserción por la orden que hay en el evento OnCreate de este formulario, y cuando se cancela la operación actual de la tabla, la tabla pasa a modo normal (Browse).

Para la edición de los datos, he puesto otro formulario, el cual se crea y se destruye igual que el anterior. Estos son los tres procedimiento del formulario que controlan todo el proceso.

procedure TForm3.BitBtn3Click(Sender: TObject);
begin
     DataModule2.Table1.Cancel;
     PuedoCerrar := True;
end;

procedure TForm3.BitBtn1Click(Sender: TObject);
begin
     If (DbEdit1.Text = '' ) or (DbComboBox1.Text = '' ) Then

       IF Application.MessageBox ('No se puede grabar con los campos vacios.'+
           Chr(13)+'¿Deseas salir sin grabar?',
          'Campos vacios',mb_YesNoCancel+MB_IconStop) = idYes Then
        Begin
         DataModule2.Table1.Cancel;
         PuedoCerrar := True;
        End
       Else
        PuedoCerrar := False
     Else
        Begin
        PuedoCerrar := True;
         Try
          DataModule2.Table1.Post;
         Except
          DataModule2.Table1.Cancel;
         End; //De la excepción.

        End;
end;

procedure TForm3.FormCreate(Sender: TObject);
Begin
     PuedoCerrar := False;
     Resolucion;
     
End;

procedure TForm3.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
Begin
     CanClose := PuedoCerrar;
End;

El primero de todos es el del botón Cancelar, lo único que hace es cancelar la operación de la tabla, por si esta en modo edición y luego cambiar el valor de la varible PuedoCerrar, que hace la misma función que en el formulario principal. En este procedimiento cancelo la operación de la tabla, pero fijate que no hay ninguna línea que ponga la tabla en modo edición, pero te aseguro que la tabla entra en modo edición. Esto es posible ya que son los propios controles de bases de datos (Data Aware) los que lo hacen.
El siguiente procedimiento es el que esta asociado a la pulsación del botón Aceptar, de nuevo verifica que no haya campos vacios, si el usuario decide que quiere salir de todos modos, se cancela la edición de la tabla y se cambia el valor de la ya conocida variable PuedoCerrar. Si los campos estan llenos correctamente se guardan en la tabla las moficaciones (método Post), si hay algun problema se cancela la edición y se cierra de todos modos el formulario.

Basicamente este es el "despiece" de este programa, como podies ver no es difícil hacer un programa que gestiones una base de datos, todo depende de lo que se quiera complicar. Creo que quedan explicados los aspectos generales sobre este programa. Os recuerdo que solo es un ejemplo y que hay más maneras de hacer las cosas todas iguales o mejores que esta.