21 septiembre 2007

Mostrando datos en el componente StringGrid

Anteriormente vimos como mostrar información en un componente ListView llegando incluso a cambiar el color de filas y columnas a nuestro antojo. El único inconveniente estaba en que no se podían cambiar los títulos de las columnas, ya que venían predeterminadas por los colores de Windows.

Pues bien, el componente de la clase TStringGrid es algo más cutre que el ListView, pero permite cambiar al 100% el formato de todas las celdas. Veamos primero como meter información en el mismo. Al igual que ocurría con el ListView, todos las celdas de un componente StringGrid son de tipo string, siendo nosotros los que le tenemos que dar formato a mano.

AÑADIENDO DATOS A LA REJILLA

Vamos a crear una rejilla de datos con las siguiente columnas:

NOMBRE, APELLIDO1, APELLIDO2, NIF, IMPORTE PTE.

Cuando insertamos un componente StringGrid en el formulario nos va a poner por defecto la primera columna con celdas fijas (fixed). Vamos a fijar las siguientes propiedades:

Propiedad Valor Descripción
--------- ----- -----------
ColCount 5 5 columnas
RowCount 4 4 filas
FixedCols 0 0 columnas fijas
FixedRows 1 1 fila fija
DefaultRowHeight 20 altura de las filas a 20 pixels

Ahora creamos un procedimiento para completar de datos la rejilla:

procedure TFormulario.RellenarTabla;
begin
with StringGrid do
begin
// Título de las columnas
Cells[0, 0] := 'NOMBRE';
Cells[1, 0] := 'APELLIDO1';
Cells[2, 0] := 'APELLIDO2';
Cells[3, 0] := 'NIF';
Cells[4, 0] := 'IMPORTE PTE.';

// Datos
Cells[0, 1] := 'PABLO';
Cells[1, 1] := 'GARCIA';
Cells[2, 1] := 'MARTINEZ';
Cells[3, 1] := '67348321D';
Cells[4, 1] := '1500,36';

// Datos
Cells[0, 2] := 'MARIA';
Cells[1, 2] := 'SANCHEZ';
Cells[2, 2] := 'PALAZON';
Cells[3, 2] := '44878234A';
Cells[4, 2] := '635,21';

// Datos
Cells[0, 3] := 'CARMEN';
Cells[1, 3] := 'PEREZ';
Cells[2, 3] := 'GUILLEN';
Cells[3, 3] := '76892693L';
Cells[4, 3] := '211,66';
end;
end;

Al ejecutar el programa puede apreciarse lo mal que quedan los datos en pantalla, sobre todo la columna del importe pendiente:


DANDO FORMATO A LAS CELDAS DE UN COMPONENTE STRINGGRIND

Lo que vamos a hacer a continuación es lo siguiente:

- La primera fila fija va a ser de color de fondo azul oscuro con fuente blanca y además el texto va a ir centrado.

- La columna del importe pendiente va a tener la fuente de color verde y va a ir alineada a la derecha.

- El resto de columnas tendrán el color de fondo blanco y el texto en negro.

Todo esto hay que hacerlo en el evento OnDrawCell del componente StringGrid:

procedure TFormulario.StringGridDrawCell( Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState );
var
sTexto: String; // Texto que va a imprimir en la celda actual
Alineacion: TAlignment; // Alineación que le vamos a dar al texto
iAnchoTexto: Integer; // Ancho del texto a imprimir en pixels
begin
with StringGrid.Canvas do
begin
// Lo primero es coger la fuente por defecto que le hemos asignado al componente
Font.Name := StringGrid.Font.Name;
Font.Size := StringGrid.Font.Size;

if ARow = 0 then
Alineacion := taCenter
else
// Si es la columna del importe pendiente alineamos el texto a la derecha
if ACol = 4 then
Alineacion := taRightJustify
else
Alineacion := taLeftJustify;

// ¿Es una celda fija de sólo lectura?
if gdFixed in State then
begin
Brush.Color := clNavy; // le ponemos azul de fondo
Font.Color := clWhite; // fuente blanca
Font.Style := [fsBold]; // y negrita
end
else
begin
// ¿Esta enfocada la celda?
if gdFocused in State then
begin
Brush.Color := clRed; // fondo rojo
Font.Color := clWhite; // fuente blanca
Font.Style := [fsBold]; // y negrita
end
else
begin
// Para el resto de celdas el fondo lo ponemos blanco
Brush.Color := clWindow;

// ¿Es la columna del importe pendiente?
if ACol = 4 then
begin
Font.Color := clGreen; // la pintamos de azul
Font.Style := [fsBold]; // y negrita
Alineacion := taRightJustify;
end
else
begin
Font.Color := clBlack;
Font.Style := [];
end;
end;
end;

sTexto := StringGrid.Cells[ACol,ARow];
FillRect( Rect );
iAnchoTexto := TextWidth( sTexto );

case Alineacion of
taLeftJustify: TextOut( Rect.Left + 5, Rect.Top + 2, sTexto );
taCenter: TextOut( Rect.Left + ( ( Rect.Right - Rect.Left ) - iAnchoTexto ) div 2, Rect.Top + 2, sTexto );
taRightJustify: TextOut( Rect.Right - iAnchoTexto - 2, Rect.Top + 2, sTexto );
end;
end;
end;

Así quedaría al ejecutarlo:


Sólo hay un pequeño inconveniente y es que la rejilla primero se pinta de manera normal y luego nosotros volvemos a pintarla encima con el evento OnDrawCell con lo cual hace el proceso dos veces. Si queremos que sólo se haga una vez hay que poner a False la propiedad DefaultDrawing. Quedaría de la siguiente manera:


Por lo demás creo que este componente que puede sernos muy útil para mostrar datos por pantalla en formato de sólo lectura. En formato de escritura es algo flojo porque habría que controlar que tipos de datos puede escribir el usuario según en que columnas esté.

Pruebas realizadas en Delphi 7.

20 septiembre 2007

Creando aplicaciones MDI

Una aplicación MDI en Windows es aquella que contiene una ventana principal la cual que contiene a su vez ventanas hijas (al estilo Word o Excel). Cada ventana hija no puede salirse del marco de trabajo de la ventana padre aunque si puede minimizarse, maximizarse, etc.


A su vez no todas las ventanas creadas tienen que ser hijas de la ventana padre. Pueden crearse ventanas independientes ya sean normales o modales (una ventana modal es aquella que no permite acceder a ninguna otra hasta que se cierre, como los típicas ventanas de diálogo).

COMO CREAR UNA APLICACION MDI

Aunque el asistente de creación de proyectos de Delphi permite crear aplicaciones MDI, realmente no tiene mucha ciencia. Sólo hay que coger el formulario principal de la aplicación y cambiar su propiedad FormStyle a fsMDIForm. Con sólo hacer eso ya tenemos la ventana padre contenedora.

Para crear una ventana hija hay que hacer lo siguiente:

procedure TFormulario.MDIChildClick( Sender: TObject );
var
Form: TForm;
begin
Form := TForm.Create( Self );
Form.FormStyle := fsMDIChild;
Form.Caption := 'Ventana hija MDI';
Form.OnClose := AlCerrar;
Form.Show;
end;

Como puede apreciarse hemos creado una ventana y le hemos dicho que su estilo es fsMDIChild. También hemos asignado el evento OnClose para cerrar la ventana:

procedure TFormulario.AlCerrar( Sender: TObject; var Action: TCloseAction );
begin
Action := caFree;
end;

Hay que hacer esto porque por defecto cuando se crea una ventana hija y se cierra, realmente no se cierra si no que se minimiza. Por ello he creado el evento AlCerrar en la ventana padre para asignarlo a todas las ventanas hijas.

Si queremos hacer un formulario normal que no esté relacionado con el formulario padre MDI, entonces el procedimiento sería el siguiente:

procedure TFormulario.NormalClick( Sender: TObject );
var
Form: TForm;
begin
Form := TForm.Create( Self );
Form.Caption := 'Ventana normal';
Form.Show;
end;

Cuando se crea un formulario nuevo su propiedad FormStyle es por defecto fsNormal. El crear una ventana modal es prácticamente lo mismo:

procedure TFormulario.ModalClick( Sender: TObject );
var
Form: TForm;
begin
Form := TForm.Create( Self );
Form.Caption := 'Ventana modal';
Form.ShowModal;
end;

Cuando se crea una ventana hija MDI hay que tener presentes un par de cosas:

- Nunca pueden ser invisibles, con lo cual si utilizamos los métodos Show o Hide provocará un error. Igual para la propiedad Visible.

- Tampoco pueden ser modales, para ello utiliza una ventana modal como hemos visto anteriormente.

ORGANIZANDO LAS VENTANAS HIJAS

Una vez creadas las ventanas hijas, la ventana padre puede organizarlas en cascada, mostrarlas todas a la vez, colocarlas horizontalmente, verticalmente e incluso cerrarlas todas.

Por ejemplo, para poner todas las ventanas hijas en cascada hacemos lo siguiente:

procedure TFormulario.CascadaClick( Sender: TObject );
begin
VentanasNormales;
Cascade;
end;


El procedimiento VentanasNormales se encarga de dejar cada una de las ventanas hijas de manera normal por si acaso estaban minimizadas:

procedure TFormulario.VentanasNormales;
var i: Integer;
begin
for i := 0 to MDIChildCount - 1 do
MDIChildren[i].WindowState := wsNormal;
end;

La clase TForm dispone de las propiedades MDIChildCount y MDIChildren para controlar el número de ventanas hijas abiertas así como cada una de ellas.

Aparte de ponerlas en cascada podemos hacer que todas se repartan en pantalla horizontamente:

procedure TFormulario.HorizontalClick( Sender: TObject );
begin
VentanasNormales;
TileMode := tbHorizontal;
Tile;
end;



Y también verticalmente:

procedure TFormulario.VerticalClick( Sender: TObject );
begin
VentanasNormales;
TileMode := tbVertical;
Tile;
end;


Si queremos minimizarlas todas hay que decírselo a cada una de ellas:

procedure TFormulario.MinimizarClick( Sender: TObject );
var i: Integer;
begin
for i := MDIChildCount - 1 downto 0 do
MDIChildren[i].WindowState := wsMinimized;
end;


También ocurre lo mismo si queremos cerrarlas todas:

procedure TFormulario.CerrarClick( Sender: TObject );
var i: Integer;
begin
for i := 0 to MDIChildCount - 1 do
MDIChildren[i].Close;
end;

Las aplicaciones MDI son muy útiles para realizar programas de gestión, procesadores de texto, visualizadores de imágenes, etc.

Pruebas realizadas en Delphi 7.

19 septiembre 2007

Creando un cliente de chat IRC con Indy (y III)

Después de haber visto la parte básica del componente IdIRC pasemos a ver algunas cosas que hay que controlar en un cliente de chat.

QUIEN SALE Y QUIEN ENTRA A UN CANAL

Mientras permanezcamos en un canal entrarán y saldrán usuarios constantemente, lo cual nos obliga a refrescar la lista de usuarios y notificar los cambios en la misma ventana del canal:

Ha entrado el usuario lola33
Ha salido el usuario carlos21

Para controlar los usuarios que entran a un canal utilizaremos el evento OnJoin:

procedure TFormulario.IRCJoin( Sender: TObject; AUser: TIdIRCUser; AChannel: TIdIRCChannel );
begin
if Assigned( AChannel ) and Assigned( AUser ) then
if AChannel.Name = CanalActual.Text then
begin
Canal.Lines.Add( 'Ha entrado el usuario ' + AUser.Nick );

if Usuarios.Items.IndexOf( AUser.Nick ) = -1 then
Usuarios.Items.Add( AUser.Nick );
end;
end;

Después de informar en el canal actual que ha aparecido un nuevo usuario también lo hemos dado de alta en la lista de usuarios, controlando que no se repitan, ya que a veces suele coincidir que se ejecuta el comando NAMES del servidor y a la vez entra un usuario nuevo.

Y cuando un usuario abandona el canal entonces utilizamos el evento OnPart:

procedure TFormulario.IRCPart( Sender: TObject; AUser: TIdIRCUser; AChannel: TIdIRCChannel );
var iUsuario: Integer;
begin
if Assigned( AChannel ) and Assigned( AUser ) then
if AChannel.Name = CanalActual.Text then
begin
Canal.Lines.Add( 'Ha salido el usuario ' + AUser.Nick );
iUsuario := Usuarios.Items.IndexOf( AUser.Nick );

if iUsuario > -1 then
Usuarios.Items.Delete( iUsuario );
end;
end;

La única dificultad que hay que controlar es que si tenemos varias ventanas (una por canal) hay que llevar las notificaciones a la ventana correspondiente.

Los canales de chat tienen dos clases de usuarios: operadores y usuarios normales. Los operadores son usuarios que tienen permisos especiales: pueden hacer operadores a usuarios normales o echar a un usuario de un canal si esta incumpliendo las normas del mismo.

Cuando un operador echa fuera a un usuario entonces nuestro componente IdIRC provoca el evento OnKick:

procedure TFormulario.IRCKick( Sender: TObject; AUser, AVictim: TIdIRCUser; AChannel: TIdIRCChannel );
var iUsuario: Integer;
begin
if Assigned( AChannel ) and Assigned( AUser ) then
if AChannel.Name = CanalActual.Text then
begin
Canal.Lines.Add( 'El usuario ' + Auser.Nick + ' ha expulsado a usuario ' + AVictim.Nick );
iUsuario := Usuarios.Items.IndexOf( AUser.Nick );

if iUsuario > -1 then
Usuarios.Items.Delete( iUsuario );
end;
end;

Este evento nos informa del nombre del operador, el de la victima y del canal de donde ha sido expulsado.

Y por último tenemos el problema de que un usuario puede cambiarse el apodo (nick) en cualquier momento. Para ello utilizaremos el evento OnNickChange para notificarlo:

procedure TFormulario.IRCNickChange( Sender: TObject; AUser: TIdIRCUser; ANewNick: String );
var iUsuario: Integer;
begin
Canal.Lines.Add( 'El usuario ' + AUser.Nick + ' ahora se llama ' + ANewNick );
iUsuario := Usuarios.Items.IndexOf( AUser.Nick );

if iUsuario > -1 then
Usuarios.Items[iUsuario] := ANewNick;
end;

Aparte de notificarlo le hemos cambiado el nombre en nuestra lista de usuarios.

INTERCEPTANDO LOS MENSAJES DEL SISTEMA

A pesar de todos los eventos de los que dispone el componente de la clase TIdIRC también podemos interceptar a pelo los mensajes del sistema a través del evento OnSystem, el cual nos dice el usuario, el código de comando y el contenido del mensaje del sistema. Por ejemplo estos son algunos códigos de comando del servidor:

353 -> Comienzo del comando NAMES
366 -> Fin del comando NAMES
376 -> Mensaje del día
etc.

Para más información hay que ver el documento RFC perteneciente al protocolo IRC que mencione en el artículo anterior. Por ejemplo, para averiguar los datos sobre un usuario en concreto hay que mandarle al servidor el comando:

WHOIS maria

Y el servidor devolverá lo siguiente:

319 - WHOIS - maria is on #amistades
312 - WHOIS - maria is using jupiter2.irc-hispano.org Servidor IRC de LLeida Networks
318 - WHOIS - maria :End of /WHOIS list

Nos esta diciendo que maria está en el canal #amistades y que está conectada utilizando el servidor jupiter2. Si estuviera conectada a más canales también lo diría (así sabemos también sus otras aficiones).

¿Cómo nos comemos todo eso? Pues supongamos que si yo hago doble clic sobre un usario quiero que me devuelva información sobre el mismo en un campo Memo cuyo nombre es DatosUsuario. Lo primero sería procesar el evento OnDblClick en la lista de usuarios:

procedure TFormulario.UsuariosDblClick( Sender: TObject );
begin
if Usuarios.ItemIndex > -1 then
IRC.Raw( 'WHOIS ' + Usuarios.Items[Usuarios.ItemIndex] );
end;

Y ahora en el evento OnSystem del componente IdIRC esperamos a que nos llegue la información:

procedure TFormulario.IRCSystem( Sender: TObject; AUser: TIdIRCUser; ACmdCode: Integer; ACommand, AContent: string );
begin
case ACmdCode of
312, 318, 319: DatosUsuario.Lines.Add( AContent );
end;
end;

Así, estudiando un poco el protocolo IRC y sabiendo algunos comandos podemos hacer más cosas de las que permite el componente IdIRC.

ENVIO Y RECEPCION DE ARCHIVOS POR ACCESO DIRECTO

El protocolo IRC permite establecer el envío y recepción de archivos con conexión punto a punto entre la IP del remitente y la IP del receptor. Esto ya no se suele utilizar hoy en día por las siguiente razones:

- Debido a que casi todas las redes locales están detrás de un router se hace necesario abrir y redireccionar puertos en el mismo, cosa que no todo el mundo sabe hacer.

- En cuanto intentemos establecer conexión por puertos que no sean los estandar los cortafuegos saltarán como liebres pidiendo permiso para conectar. Los novatos siempre dirán NO por si acaso.

- Hay robots automáticos programados en MIRC mediante scripts que no paran de realizar ataques continuamente a conexiones DCC.

Por ello no voy a comentar aquí como utilizarlo (para ello tenemos rapidshare, megaupload y demás hierbas que superan con creces este tipo de conexiones y además son más seguros).

Con esto finalizamos lo más importante del componente IdIRC de la paleta de componentes Indy.

Pruebas realizadas en Delphi 7.

18 septiembre 2007

Creando un cliente de chat IRC con Indy (II)

Una vez establecida la conexión con el servidor y sabiendo de que salas de chat dispone, vamos a entrar a un canal a chatear.

ENTRANDO A UN CANAL

Para entrar a un canal se utiliza el método Join:

IRC.Join( '#amistades' );

Esto viene a ser lo mismo que hacer:

IRC.Raw( 'join #amistades' );

Podemos entrar a tantos canales como deseemos pero para hacer un buen cliente de chat hay que crear un formulario por canal, ya que el protocolo IRC nos permite chatear en múltiples canales simultaneamente.

Una vez se ha enviado el comando JOIN el servidor nos devuelve la lista de usuarios que hay en ese canal. Para recoger dicha lista hay que utilizar el evento OnNames del componente IdIRC, donde volcaremos el contenido de la misma en un ListBox que vamos a llamar Usuarios:

procedure TFormulario.IRCNames( Sender: TObject; AUsers: TIdIRCUsers; AChannel: TIdIRCChannel );
var i: Integer;
begin
if Assigned( AUsers ) then
begin
Usuarios.Clear;

for i := 0 to AUsers.Count - 1 do
Usuarios.Items.Add( AUsers.Items[i].Nick );
end;
end;

Es conveniente que el ListBox este ordenado alfabéticamente activando la propiedad Sorted para no volvernos locos buscando los usuarios por su nombre.

LEYENDO LOS MENSAJES DEL SERVIDOR

Una vez conectados a un canal, el servidor nos mandará dos tipos de mensajes: lo que hablan todos los usuarios en el canal y lo que un usuario en concreto nos esta diciendo. ¿Cómo distinguimos cada cual? Pues para ello el evento OnMessaje nos dice el usuario y canal que nos manda el mensaje:

procedure TFormulario.IRCMessage( Sender: TObject; AUser: TIdIRCUser;
AChannel: TIdIRCChannel; Content: string );
begin
if Assigned( AUser ) then
begin
if Assigned( AChannel ) then
Canal.Lines.Add( AUser.Nick + '> ' + Content )
else
Privado.Lines.Add( AUser.Nick + '> ' + Content );
end;
end;

Como se puede apreciar primero comprobamos si existe el usuario (por si acaso es un mensaje del sistema) y luego si tiene canal metemos el mensaje por el mismo (poniendo el nick delante como MIRC) y si no es asi lo mandamos a una conversación privada. En este caso he enviado el texto de la conversación a un componente RichEdit.

Sería interesante que nuestro cliente de chat dispusiera de un formulario por cada conversación privada. Por ello, sería recomendable que nuestro programa de chat utilizara ventanas MDI para permitir el control absoluto cada una de las salas en las que estamos así como cada una de las conversaciones privadas. En otro artículo escribiré como crear aplicaciones MDI.

Otra característica que lo haría más profesional sería dibujar el nick y el mensaje del usuario con colores distintos como vimos anteriormente en el artículo dedicado al componente RichEdit. Y si además damos al usuario la posibilidad de seleccionar los colores de fondo, texto, nicks y tipo de fuente, el programa se aproximaría al famoso cliente MIRC.

ENVIANDO MENSAJES AL SERVIDOR

Se pueden enviar dos tipos de mensajes: a un canal donde estamos (para el público en general ) o a un usuario en concreto. El método say del componente IdIRC cumple dicho cometido.

Si quiero enviar un mensaje al canal amistades:

IRC.Say( '#amistades', 'hola a todos' );

Y si es para un usuario con el que estamos chateando:

IRC.Say( '#maria', 'hola guapa, que tal?' );

Al fin y al cabo para el servidor todo son canales, tanto canales públicos como usuarios particulares. Tenemos que ser nosotros los que debemos procesar de donde viene el mensaje y a donde deseamos enviarlo. De ahí la necesidad de crear un formulario por canal y otro por conversación privada.

ABANDONANDO UN CANAL Y UN SERVIDOR

Para abandonar un canal se utiliza el método Part:

IRC.Part( '#amistades' );

Si se nos olvida hacer esto y seguimos abriendo canales al final gastaremos mucho ancho de banda, ya que el servidor nos manda todos los mensajes publicos de cada uno de los canales abiertos.

Si queremos desconectar del servidor se utiliza el comando:

IRC.Disconnect;

Esto cancelará la conexión con el servidor cerrando todos los mensajes públicos y privados del mismo. En nuestro programa deberemos cerrar todas las ventanas de conversación abiertas.

Todavía quedan algunos puntos importantes para terminar de crear un cliente de chat, tales como saber si un usuario entra o abandona el canal donde estamos.

Pruebas realizadas en Delphi 7.

17 septiembre 2007

Creando un cliente de chat IRC con Indy (I)

Aunque MSN es el rey de la comunicación instantánea aún siguen muy vivos los servidores de chat IRC tales como irc-hispano.

IRC define un protocolo de comunicaciones entre clientes y servidores permitiendo incluso el envío de archivos por conexión directa. De todos es conocido el potente programa para Windows llamado MIRC creado hace años y que aún sigue siendo el cliente más utilizado para el IRC debido a sus múltiples extensiones.

En nuestro caso vamos a ver como utilizar el componente de la clase TIdIRC el cual esta situado en la pestaña de componentes Indy.

CONECTANDO CON EL SERVIDOR

Antes de comenzar a chatear con el servidor hay que establecer una conexión con el mismo utilizando un apodo (nick) y una contraseña en el caso de que sea necesaria (la mayoría de los servidores IRC son públicos).

Supongamos que tenemos en el formulario principal de nuestra aplicación un componente IdIRC que vamos a llamar IRC. Para conectar con el servidor hay que hacer lo siguiente:

IRC.Nick := 'juanito33487';
IRC.AltNick := 'juanito33488';
IRC.Username := 'juanito33487';
IRC.RealName := 'juan';
IRC.Password := '';
IRC.Host := 'irc.irc-hispano.org';

try
IRC.Connect;
except
Application.MessageBox( 'No se ha podido conectar con el servidor.',
'Error de conexión', MB_ICONSTOP );
end;

Estos son los parámetros para conectar:

Nick -> apodo por el que nos conocerán los demás usuarios
AltNick -> si el nick que hemos utilizado está ocupado por otro usuario cogerá este otro nick
Username -> Nombre del usuario para el servidor (da lo mismo si no estamos registrados)
Realname -> Nombre real del usuario
Password -> Clave de acceso para usuarios registrados
Host -> Dirección IP del servidor

Cualquier persona puede conectarse a un servidor de chat dando sólo el nombre del usuario sin contraseña. Pero si queremos que nadie utilice nuestro nick nos podemos registrar gratuitamente (en la mayoría de los casos) en el servidor con un usuario y password obteniendo además algunas características adicionales como entrar a salas de chat restringidas o tener nuestro propio servidor de mensajes y correo online 24 horas al día.

Una vez conectados al servidor toca entrar en una sala de chat. Pero, ¿de que salas de chat dispone el servidor? Para ello utilizamos el comando:

IRC.Raw( 'LIST' );

El método Raw permite mandar cualquier tipo de comando al servidor. Se suele utilizar cuando el componente IRC no contiene métodos para realizar tareas específicas. Los servidores IRC trabajan enviando y recibiendo mensajes de texto continuamente. Para los que les interese saber como funciona por dentro el protocolo IRC disponen de este documento RFC:

http://www.rfc-es.org/rfc/rfc1459-es.txt

Pese a los comandos del IRC estándar algunos servidores disponen de comandos propios para tareas específicas. Para esos casos utilizaremos el método Raw.

Hay que tener mucho cuidado cuando se llama al comando LIST ya que hay servidores como los irc-hispano que disponen de miles de canales lo cual puede hacer que el tiempo en sacar el listado llegue a ser desesperante. Por ello sería deseable que tanto la función de conectar a un servidor IRC como la de listar los canales estuviera dentro de un hilo de ejecución, ya que hasta que no conecta da la sensación de que nuestro programa esta colgado.

Después de ejecutar dicho comando tenemos que programar el evento OnList para recoger la información del listado de canales. En este caso para volcar los canales en un componente ListBox llamado Canales hacemos lo siguiente:

procedure TFormulario.IRCList( Sender: TObject; AChans: TStringList;
APosition: Integer; ALast: Boolean );
begin
Canales.Items := AChans;
end;

Con esto ya tenemos la lista de canales que dispone el servidor así como el número de usuarios que hay conectados por canal y su descripción. Por ejemplo:

#amistades 20 Busca nuevos amig@s
#amor 50 Conoce a tu media naranja
#sexo 80 No te cortes un pelo
#musica 34 Comparte la pasión por tus artistas preferidos
....

En un servidor de IRC los canales comienzan con el carácter # seguido de su nombre sin espacios.

En el próximo artículo veremos como entrar a los canales de chat y hablar con otros usuarios.

Pruebas realizadas en Delphi 7.

Publicidad