Boletín Pascal #22
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
![]() |
Boletín Pascal #22 - 18-MAY-2001 INDICE 1. UNAS PALABRAS DEL EDITOR 2. DELPHI 6 3. VALIDANDO DIRECCIONES DE EMAIL EN DELPHI 4. VIEJOS TIEMPOS (II) - Opinión - Por H.R Quiroga - Un programador de verdad - Volviendo a principio de los 80 - La Guerra Santa - Basic y Java - En la actualidad - A donde vamos 5. FUNCIONES MISCELANEAS DE MANEJO DE CADENAS - Contando ocurrencias en una cadena - Dividiendo una cadena en un arreglo - Dividiendo una cadena en una lista de cadenas - Convirtiendo TimeStamps de MySql 6. GREATIS PRINT SUITE - ¿Qué es Greatis Print Suite? - Componentes - Descarga - Licencia - Más información 7. ¿COPIAR, HEREDAR O USAR? 8. DELPHI EN LA RED ________________________________________________________________________ 1. UNAS PALABRAS DEL EDITOR Y LA LICENCIA ES PARA... Roberto Martinez Olvera, de 31 años, Ejecutivo de Sistemas de IEQSA, Querétaro (México), ha resultado ser el ganador del Sorteo de Help & Manual, por tener el número 059 (correspondiente al segundo premio de la Lotería de Córdoba, dado que ningún participante tenía el número 347 correspondiente al primer premio). ¡Felicitaciones! ERRATA La rutina presentada en el artículo "Obteniendo el número de serie del BIOS" en el boletín pasado no funciona en Windows NT/2000 causando una AV. Puede ver los comentarios (en inglés) en http://www.delphi3000.com/articles/article_2194.asp#Comments Atentamente, Ernesto De Spirito eds2004 @ latiumsoftware.com ________________________________________________________________________ JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más de 40 componentes integrados y personalizables. Múltiples problemas de programación resueltos. Administración centralizada de recursos. Para Delphi 3-7 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm ________________________________________________________________________ 2. DELPHI 6 Si -como yo- usted pensaba que Delphi 6 sólo iba a introducir algunas mejoras sobre Delphi 5 y que la portabilidad con Kylix iba a ser la estrella en la nueva versión de Delphi, estaba totalmente equivocado... Mientras el Visual Studio .NET de Microsoft todavía está en su primer beta, Borland anunció la disponibilidad de Delphi para el 8 de Junio y ya está tomando preórdenes. De esta manera Delphi 6 será la primer herramienta RAD para Windows con soporte completo para Web Services (Servicios Web), el nuevo estándar de la industria, habilitando inte- gración inmediata y progresiva con plataformas basadas en Web Services de otros fabricantes como por ejemplo .Net y BizTalk de Microsoft, y ONE de Sun Microsystems. Más información: * Borland unveils industry's first RAD Web Services development platform http://www.borland.com/about/press/2001/del6released.html * Borland enters Web services fray http://www.infoworld.com/articles/hn/xml/01/05/07/010507hnborland.xml * Borland aims to make Web services a "Snap" http://www.zdnet.com/eweek/stories/general/0,11011,2712635,00.html * Delphi gets corporate http://www.comp-buyer.co.uk/index71/newnews/newsarticle.php3?id=2124 * Screenshots and articles on Delphi 6 in the Delphi community http://community.borland.com/delphi/0,1419,1,00.html * What's new in Delphi 6 http://www.borland.com/delphi/del6/whatsnew.html * Delphi 6 feature matrix http://www.borland.com/delphi/del6/featurematrix/ * Delphi 6 system requirements http://www.borland.com/delphi/del6/sysreq.html * Delphi 6 editions and prices http://shop.borland.com/Category/0,1257,3-15-983,00.html ________________________________________________________________________ 3. VALIDANDO DIRECCIONES DE EMAIL EN DELPHI Hoy en día muy común que nuestros programas guarden direcciones de email en bases de datos como parte de los datos de empleados, clientes, proveedores, etc. Al solicitar una dirección de email al usuario, ¿cómo sabemos si el valor ingresado es formalmente correcto? En este artículo le mostraré como validar direcciones de email usando una variación de la RFC #822. La RFC #822 regula el "ESTÁNDAR PARA EL FORMATO DE LOS MENSAJES DE TEXTO DE ARPA INTERNET". Puede encontrarla en: http://www.isi.edu/in-notes/rfc822.txt (en inglés) Según esta normativa, las siguientes son direcciones de email válidas: Juan Perez jperez@servidor.com Juan Perez <jperez@servidor.com> "Juan Perez" jperez@servidor.com "Juan Perez" <jperez@servidor.com> El propósito de mi código no es validar esas cosas, sino estrictamente la dirección que se necesita para llegar a un destinatario (como "jperez@servidor.com"), que en la especificación se refiere como un "addr-spec", que tiene la siguiente forma: parte-local@dominio parte-local = una "palabra" o más, separadas por puntos dominio = un "sub-dominio" o más, separados por puntos Una "palabra" puede ser un "átomo" o una "cadena-entrecomillada": átomo = uno o más caracteres en el rango #33..#126 con excepción de los siguientes: ()<>@,;:\/".[] cadena-entrecomillada = Un texto encerrado en comillas dobles que puede contener cero o más caracteres (#0..#127) excepto '"' y #13. La barra invertida ('\') "literaliza" el siguiente caracter. Un "sub-dominio" puede ser un "ref-de-dominio" (un "atom") o un "literal-de-dominio": literal-de-dominio = Un texto encerrado entre corchetes que puede contener cero o más caracteres (#0..#127) excepto '[', ']' y #13. La barra invertida ('\') "literaliza" el siguiente caracter. Según la RFC 822, los caracteres extendidos (#128..#255) no pueden ser parte de una dirección de email, pero no obstante ello muchos servidores del correo los aceptan y la gente los usa, así que voy a tomarlos en cuenta. La RFC 822 es muy abierta acerca de los nombres de dominio. Para una dirección de email real de Internet quizás deberíamos restringir la parte del dominio. Puede leer más sobre nombres del dominio en la RFC #1034 y RFC #1035 que puede encontrar aquí: http://info.internet.isi.edu/in-notes/rfc/files/rfc1034.txt http://info.internet.isi.edu/in-notes/rfc/files/rfc1035.txt Para la RFC 1034 y la RFC 1035, un nombre de dominio se forma por "sub- dominios" separados por puntos, y cada subdominio comienza con una letra ('a..'z', 'A..'Z') seguida por cero o más letras, dígitos y guiones, pero no puede terminar con un guión. Vamos a considerar además que un dominio válido debe tener por lo menos dos "sub-dominios" (como "host.com"). Ahora que tenemos las reglas claras, vamos al trabajo. El algoritmo para la función se asemeja a una máquina de transición de estados. Los caracteres de la cadena se procesan en un bucle, y por cada caracter primero determinamos en qué estado se encuentra la máquina (con un "case..of") y luego procesamos el carácter de acuerdo con eso, para determinar si la máquina debe continuar en ese estado, pasar a un estado diferente o producir un error (cortando el bucle con "break"). Este clase de algoritmos se tratan extensamente en libros de algoritmos de programación, así vayamos directo al código: function ValidEmail(email: string): boolean; // Devuelve True si la dirección de email es válida // Autor: Ernesto De Spirito <eds2004 @ latiumsoftware.com> const // Caracteres válidos en un "átomo" atom_chars = [#33..#255] - ['(', ')', '<', '>', '@', ',', ';', ':', '\', '/', '"', '.', '[', ']', #127]; // Caracteres válidos en una "cadena-entrecomillada" quoted_string_chars = [#0..#255] - ['"', #13, '\']; // Caracteres válidos en un subdominio letters = ['A'..'Z', 'a'..'z']; letters_digits = ['0'..'9', 'A'..'Z', 'a'..'z']; subdomain_chars = ['-', '0'..'9', 'A'..'Z', 'a'..'z']; type States = (STATE_BEGIN, STATE_ATOM, STATE_QTEXT, STATE_QCHAR, STATE_QUOTE, STATE_LOCAL_PERIOD, STATE_EXPECTING_SUBDOMAIN, STATE_SUBDOMAIN, STATE_HYPHEN); var State: States; i, n, subdomains: integer; c: char; begin State := STATE_BEGIN; n := Length(email); i := 1; subdomains := 1; while (i <= n) do begin c := email[i]; case State of STATE_BEGIN: if c in atom_chars then State := STATE_ATOM else if c = '"' then State := STATE_QTEXT else break; STATE_ATOM: if c = '@' then State := STATE_EXPECTING_SUBDOMAIN else if c = '.' then State := STATE_LOCAL_PERIOD else if not (c in atom_chars) then break; STATE_QTEXT: if c = '\' then State := STATE_QCHAR else if c = '"' then State := STATE_QUOTE else if not (c in quoted_string_chars) then break; STATE_QCHAR: State := STATE_QTEXT; STATE_QUOTE: if c = '@' then State := STATE_EXPECTING_SUBDOMAIN else if c = '.' then State := STATE_LOCAL_PERIOD else break; STATE_LOCAL_PERIOD: if c in atom_chars then State := STATE_ATOM else if c = '"' then State := STATE_QTEXT else break; STATE_EXPECTING_SUBDOMAIN: if c in letters then State := STATE_SUBDOMAIN else break; STATE_SUBDOMAIN: if c = '.' then begin inc(subdomains); State := STATE_EXPECTING_SUBDOMAIN end else if c = '-' then State := STATE_HYPHEN else if not (c in letters_digits) then break; STATE_HYPHEN: if c in letters_digits then State := STATE_SUBDOMAIN else if c <> '-' then break; end; inc(i); end; if i <= n then Result := False else Result := (State = STATE_SUBDOMAIN) and (subdomains >= 2); end; Cualquier colaboración para mejorar esta función es bienvenida. ________________________________________________________________________ 4. VIEJOS TIEMPOS (I) - Opinión - Por H.R Quiroga Un programador de verdad ------------------------ Muchos quizás hayan leído la frase "Real Programmers Don't Use Pascal" ("Los verdaderos programadores no usan Pascal"). Esta frase pertenece a un artículo de 1983 publicado en "Datamation" por Ed Post. Las cosas han cambiado al grado que muchos de los utilitarios de "PCMagazine" están hechos en Delphi, y si esos programadores no son de "verdad", no queda mucho para mí. No pienso que mi conocimiento de C, Assembler, Fortran, Cobol, Clipper y demás lenguajes me hagan más "real". Volviendo a principio de los 80 ------------------------------- Cuando apareció Turbo Pascal de Borland, Microsoft vendía un compilador de Pascal (tengo recuerdos nebulosos de ello, así que disculpen si no soy exacto). Se requerían tres disquetes, compilación y enlace en varios pasos y varios cientos de dólares por licencia, además de algún editor como Wordstar. Por otro lado "Turbo Pascal" necesitaba 32K, tenía un editor integrado, generaba ejecutables de unos 30K que eran mucho menores de los de la competencia y llegó a costar menos de 100 dólares. Entenderán por qué Microsoft eventualmente se retiró de esa competencia (es posible que hayan eliminado cualquier registro histórico de este fracaso como el protagonista de la novela de Orwell en la novela 1984). Uno probaba Turbo Pascal pensando en lo ridículo del nombre... Pronto dejaba de sonar ridículo. En el camino hubo algunas pérdidas importantes. Paz a los restos de "Topspeed Modula-2". La Guerra Santa --------------- En computación las "Guerras Santas" se basan en posiciones no técnicas (casi religiosas) llevadas por medio de silogismos a posiciones técnicas. Son divertidísimas o al menos ingeniosas. Siempre ha habido guerras de C vs. alguna cosa. Obviamente "C" vs. "Pascal". La guerra no destrozó mucho y ambos lenguajes sobreviven hoy en día. El compilador de Object Pascal es en extremo lejano a Pascal como quizás el de C++ a C. Paradójicamente este artículo se parece mucho a la artillería de una guerra santa ;-> y dado el foro donde expongo esto, es casi convencer a los convencidos. En cualquier caso, los defectos señalados a cada lenguaje durante las guerras fueron muy ciertos en su mayoría. Muchos cambios en estos lenguajes son sólo para cubrir esas terribles debilidades. Basic y Java ------------ Siempre ha existido algo muy molesto en la persistencia de Basic, y no sólo es su origen; es también su pobre evolución. Basic sobrevive porque Microsoft lo mantiene; cosa que podríamos afirmar también de Pascal con respecto a Borland (creo que en algún momento ha sido al contrario). Quizás de esto se salven C, derivados y Java. Microsoft ha intentado en vano echarnos a perder Java. Borland, en un camino más discreto, aportó cosas importantes a su especificación (léase JavaBeans) sin intentar apropiárselo, y de esta manera discreta mantienen uno de las mejores herramientas de desarrollo Java. Será interesante ver el futuro de Java y Borland. Basic, con lo terrible que es, aún existe derivado en Visual Basic. Detesto enfrentarme a programadores de Visual Basic que insisten en que debo usarlo, sin importarles que yo de hecho lo he utilizado y abandonado. Actualmente pienso dedicarle algo de esfuerzo a Java. Me parece que esto aportará algo útil o por lo menos me dará la oportunidad de rechazarlo con propiedad. En la actualidad ---------------- Ya sabemos que Pascal tiene presencia en la actualidad y de manera significativa aplicado a través de Delphi. Lo interesante es ver en dónde se aplica y si podemos reconocer por esto su madurez. Sabemos que la NASA lo usa. Sabemos también que hay algunas aplicaciones comerciales hechas con Delphi. Lo que me gustaría ver es una Suite Completa de oficina hecha con Delphi; sin embargo, sé que ese es un mercado muy difícil, así que por lo pronto sólo es un sueño. Debo añadir que este sueño tiene un ambiente Linux. A dónde vamos ------------- Sí, primera persona en plural. Marco Cantú dijo "Dephi no es sólo un producto. Es una comunidad". Esta comunidad parece impulsada cada vez más por medio de la Internet y por lo visto cada vez crece más. Me agrada pertenecer a la Comunidad de Delphi y creo que somos muchos y entusiastas, y por ello debemos hacernos notar. No importa que se vendan más copias de Visual alguna cosa si la calidad de nuestro trabajo es superior y llena de mucho más gusto. Es inevitable mencionar Kylix. Cualquier vaticinio aún es un poco aventurado. Espero que incluso eventualmente escuchemos de Delphi para Mac o algo así. A diferencia de la Mac creo que Linux no va disminuir su ímpetu. ------------- Para recordar la historia recomiendo un vistazo a (muchos datos precisos aquí señalados provienen de esta fuente): "THE JARGON FILE, VERSION 2.9.12", conocido como "The Hacker's Dictionary". Otros datos son tomados de artículos de Marco Cantú (www.marcocantu.com) ------------------------------------ Copyright (c) 2001 H.R Quiroga ________________________________________________________________________ 5. BUSCANDO TEXTO EN UN CAMPO MEMO Si necesita buscar texto en un campo memo, puede hacerlo recorriendo el dataset registro por registro para ver si el texto buscado se encuentra en el campo memo o no: procedure TForm1.btnFindClick(Sender: TObject); var SearchStr: string; begin SearchStr := UpperCase(Edit1.Text); Table1.DisableControls; if Sender = btnFindFirst then Table1.First // Botón Find First else if not Table1.Eof then Table1.Next; // Botón Find Next while not Table1.Eof and (AnsiPos(SearchStr, UpperCase(Table1Notes.AsString)) = 0) do Table1.Next; Table1.EnableControls; if Table1.Eof then ShowMessage('No encontrado') end; El código fuente completo de este ejemplo puede encontrarlo en el archivo adjunto a este boletín. ________________________________________________________________________ 6. GREATIS PRINT SUITE ¿Qué es Greatis Print Suite? ---------------------------- Greatis Print Suite es un extremadamente conveniente juego de compo- nentes que permiten incorporar características avanzadas de impresión y previsualización a las aplicaciones hechas con Delphi y C++ Builder. Componentes ----------- La suite contiene: * TPrintJob: Principal componente no visual de la suite que provee fácil impresión multipágina * TPreview: Control que provee fácil previsualización de impresión * TPreviewWindow: Ventana de previsualización lista para usar * TPreviewToolbar: Barra de herramientas lista para usar que provee control de previsualización * TPreviewStatusBar: Barra de estado lista para usar que permite mostrar parámetros de previsualización * TPreviewComboBox: Cuadro combinado que muestra y provee control de la escala de previsualización * TPreviewLabel: Etiqueta para mostrar parámetros de previsualización Greatis Print Suite Pro contiene adicionalmente el paquete Print Jobs - un juego de componentes listos para usar para imprimir cuadrículas, bases de datos y tablas, con varias clases abstractas para crear trabajos de impresión a la medida. * TSimpleGridPrintJob: Para imprimir fácilmente cualquier cuadrícula gráfica * TSimpleTextGridPrintJob: Para imprimir fácilmente cualquier cuadrícula de texto * TDBGridPrintJob: Para imprimir fácilmente cualquier cuadrícula de datos * TStringGridPrintJob: Para imprimir fácilmente el contenido de un TStringGrid * TListViewPrintJob: Para imprimir fácilmente el contenido de un TListView * TStringsPrintJob: Para imprimir fácilmente el contenido de archivos de texto y TStrings * TMultiPrintJob: Componente para integrar otros trabajos de impresión * TDraftPrintJob: Componente para impresión borrador (tipo diapos) Olvídese de BeginDoc, EndDoc, NewPage y otros procedimientos de impresión de bajo nivel. Simplemente dibuje su trabajo de impresión y deje que Print Suite se encargue del resto. Descarga -------- Un EXE-demo compilado, documentación imprimible en formato PDF y las versiones de prueba de todos los componentes Print Suite Pro se incluyen en el kit demostrativo, que puede descargar de la siguiente dirección: http://www.greatis.com/printsuitedemo.zip (~735K) Si lo desea puede solicitar una copia de evaluación. Licencia -------- Print Suite cuesta US$ 29.95-39.95 para una licencia de un sólo usuario. Más información --------------- Vea más información en la página web de Print Suite: http://www.greatis.com/printsuite.htm Para más información, contacte Greatis Software <b-team@greatis.com> ________________________________________________________________________ 7. FUNCIONES MISCELANEAS DE MANEJO DE CADENAS - Por Ernesto De Spirito Por si alguien las encuentra útiles, aquí van algunas funciones de manejo de cadenas que me han pedido en mi "Delphi Help Desk". Contando ocurrencias en una cadena ================================== Las siguientes funciones devuelven la cantidad de ocurrencias de un caracter o una subcadena dentro de una cadena: interface function Occurs(const str: string; c: char): integer; overload; function Occurs(const str: string; const substr: string): integer; overload; function AnsiOccurs(const str: string; const substr: string): integer; implementation uses sysutils; function Occurs(const str: string; c: char): integer; // Devuelve la cantidad de veces que un caracter está en una cadena var p: PChar; begin Result := 0; p := PChar(Pointer(str)); while p <> nil do begin p := StrScan(p, c); if p <> nil then begin inc(Result); inc(p); end; end; end; function Occurs(const str: string; const substr: string): integer; // Devuelve la cantidad de veces que una subcadena está en una cadena var p, q: PChar; n: integer; begin Result := 0; n := Length(substr); if n = 0 then exit; q := PChar(Pointer(substr)); p := PChar(Pointer(str)); while p <> nil do begin p := StrPos(p, q); if p <> nil then begin inc(Result); inc(p, n); end; end; end; function AnsiOccurs(const str: string; const substr: string): integer; // Devuelve la cantidad de veces que una subcadena está en una cadena // Versión ANSI var p, q: PChar; n: integer; begin Result := 0; n := Length(substr); if n = 0 then exit; q := PChar(Pointer(substr)); p := PChar(Pointer(str)); while p <> nil do begin p := AnsiStrPos(p, q); if p <> nil then begin inc(Result); inc(p, n); end; end; end; Dividiendo una cadena en un arreglo =================================== Las siguientes funciones dividen una cadena en partes separadas por una subcadena y devuelven las partes en un arreglo dinámico de cadenas: interface type TStringArray = array of string; function Split(const str: string; const separator: string = ','): TStringArray; function AnsiSplit(const str: string; const separator: string = ','): TStringArray; implementation uses sysutils; function Split(const str: string; const separator: string): TStringArray; // Devuelve un arreglo con las partes de "str" separadas por // "separator" var i, n: integer; p, q, s: PChar; begin SetLength(Result, Occurs(str, separator)+1); p := PChar(str); s := PChar(separator); n := Length(separator); i := 0; repeat q := StrPos(p, s); if q = nil then q := StrScan(p, #0); SetString(Result[i], p, q - p); p := q + n; inc(i); until q^ = #0; end; function AnsiSplit(const str: string; const separator: string): TStringArray; // Devuelve un arreglo con las partes de "str" separadas por // "separator" // Versión ANSI var i, n: integer; p, q, s: PChar; begin SetLength(Result, AnsiOccurs(str, separator)+1); p := PChar(str); s := PChar(separator); n := Length(separator); i := 0; repeat q := AnsiStrPos(p, s); if q = nil then q := AnsiStrScan(p, #0); SetString(Result[i], p, q - p); p := q + n; inc(i); until q^ = #0; end; Ejemplo: procedure TForm1.Button1Click(Sender: TObject); var a: TStringArray; i: integer; begin a := Split('parte1,parte2,parte3'); for i := 0 to Length(a) - 1 do begin // Mostrará tres diálogos ShowMessage(a[i]); // 'parte1', 'parte2', 'parte3' end; end; Dividiendo una cadena en una lista de cadenas ============================================= Las siguientes funciones dividen una cadena en partes separadas por una subcadena y devuelven las partes en una lista de cadenas que puede ser pasada como tercer parámetro o ser creada por la función (y en tal caso deberá ser liberada por el llamador): interface uses classes; function SplitStrings(const str: string; const separator: string = ','; Strings: TStrings = nil): TStrings; function AnsiSplitStrings(const str: string; const separator: string = ','; Strings: TStrings = nil): TStrings; implementation uses sysutils; function SplitStrings(const str: string; const separator: string; Strings: TStrings): TStrings; // Llena una lista de cadenas con las partes de "str" separadas por // "separator". Si se pasa Nil en vez de una lista de cadenas, la // función crea un objecto TStringList que debe ser liberado por el // llamador var n: integer; p, q, s: PChar; item: string; begin if Strings = nil then Result := TStringList.Create else Result := Strings; try p := PChar(str); s := PChar(separator); n := Length(separator); repeat q := StrPos(p, s); if q = nil then q := StrScan(p, #0); SetString(item, p, q - p); Result.Add(item); p := q + n; until q^ = #0; except item := ''; if Strings = nil then Result.Free; raise; end; end; function AnsiSplitStrings(const str: string; const separator: string; Strings: TStrings): TStrings; // Llena una lista de cadenas con las partes de "str" separadas por // "separator". Si se pasa Nil en vez de una lista de cadenas, la // función crea un objecto TStringList que debe ser liberado por el // llamador // Versión ANSI var n: integer; p, q, s: PChar; item: string; begin if Strings = nil then Result := TStringList.Create else Result := Strings; try p := PChar(str); s := PChar(separator); n := Length(separator); repeat q := AnsiStrPos(p, s); if q = nil then q := AnsiStrScan(p, #0); SetString(item, p, q - p); Result.Add(item); p := q + n; until q^ = #0; except item := ''; if Strings = nil then Result.Free; raise; end; end; Ejemplos: procedure TForm1.Button1Click(Sender: TObject); begin SplitStrings(Edit1.Text, ', ', ListBox1.Items); end; procedure TForm1.Button2Click(Sender: TObject); var Parts: TStrings; begin Parts := nil; try Parts := SplitStrings(Edit1.Text, ', '); ShowMessage('La primera parte es "' + Parts[0] + '"'); finally Parts.Free; end; end; Convirtiendo TimeStamps de MySql ================================ Las siguientes funciones convierten timestamps completas de MySql (cadenas en formato 'YYYYMMDDHHMMSS') a un Variant tipo TDateTime y viceversa. uses sysutils; function MySqlTimeStampToDateTime(const TimeStamp: string): variant; // Convierte un TimeStamp de MySql a un TDateTime de Delphi begin if TimeStamp = '' then Result := Null else Result := EncodeDate(StrToInt(Copy(TimeStamp, 1, 4)), StrToInt(Copy(TimeStamp, 5, 2)), StrToInt(Copy(TimeStamp, 7, 2))) + EncodeTime(StrToInt(Copy(TimeStamp, 9, 2)), StrToInt(Copy(TimeStamp, 11, 2)), StrToInt(Copy(TimeStamp, 13, 2)), 0); end; function DateTimeToMySqlTimeStamp(DateTime: variant): string; // Convierte un TDateTime de Delphi a un TimeStamp de MySql begin if VarType(DateTime) in [varNull, varEmpty] then Result := '' else Result := FormatDateTime('yyyymmddhhnnss', DateTime); end; Ejemplo: procedure TForm1.Button1Click(Sender: TObject); var timestamp: string; begin timestamp := DateTimeToMySqlTimeStamp(Now); ShowMessage(timestamp + #13#13 + DateTimeToStr(MySqlTimeStampToDateTime(timestamp))); end; ________________________________________________________________________ 8. ¿COPIAR, HEREDAR O USAR? La reutilización de código nos ahorra tiempo y esfuerzo, aumentando nuestra productividad. La programación orientada a objetos tiene que ver con eso, y en el caso de Delphi se pueden reutilizar hasta los formularios e incluso proyectos enteros. Por ejemplo si tenemos un formulario con una tabla, un dbgrid, un navegador y varios botones para funciones varias, podemos guardarlo como un modelo en el Repositorio de Objetos para reutilizarlo en varias partes de nuestra aplicación o en otras aplicaciones. Lo mismo para un formulario estándar tipo "Guardar, No guardar, Cancelar". Para agregar un formulario al repositorio le hacemos clic con el botón derecho del ratón y elegimos "Add to Repository...". Para guardar un proyecto en el repositorio elegimos "Add to Repository..." en el menú Project. Para usar un formulario del Repositorio en nuestra aplicación, en el menú File elegimos New y en el diálogo New Items hacemos clic en la solapa Forms para ver los formularios disponibles en el Repositorio. Seleccionamos el formulario deseado, la forma de uso (Copy, Inherit, o Use) y hacemos clic el botón OK. Las diferencias entre estas tres formas de uso se describen brevemente a continuación: COPIAR (Copy): Crea un formulario que es copia del formulario que está en el repositorio. Los cambios que se hagan a la copia no afectarán al formulario en el repositorio (y obviamente tampoco a los proyectos que lo usen), así como los cambios hechos en el formulario del repositorio no afectarán los formularios previamente copiados de él. El nivel posible de adaptación es total. Esta opción se usa cuando el formulario del repositorio es apenas una base para trabajar, con un muy bajo nivel de estandarización. HEREDAR (Inherit): Crea un formulario que hereda del formulario en el repositorio. Los cambios que se hagan a este formulario derivado (heredado) no afectarán al formulario en el repositorio, pero sí a la inversa. Es la forma más poderosa para usar un formulario en el repositorio. Esta opción se usa cuando el formulario del repositorio está bastante estandarizado pero se desea permitir algo de adaptación. USAR (Use): Agrega el formulario del repositorio al proyecto, pero no es una copia, sino que ES el formulario del repositorio y cualquier modificación que se le haga se aplicará a otros proyectos que lo Usen o lo Hereden. Esta opción se usa cuando el formulario del repositorio es un estándar y está definido en sí mismo (no requiere de adaptaciones particulares para cada caso/aplicación). ________________________________________________________________________ 9. DELPHI EN LA RED * Delphi Database Programming Course - by Zarko Gajic Free online database programming course for beginner Delphi developers focused on ADO techniques. A new chapter has been added in the last two weeks (Chapter 8 "Data filtering"). http://delphi.about.com/compute/delphi/library/weekly/aa010101a.htm * Learning Assembler with Delphi - by Ian Hodger http://www.delphi3000.com/articles/article_2245.asp * Starting an application as an icon in the system tray - by De Spirito http://www.delphi3000.com/articles/article_1606.asp * QuickReports Manuals and Tutorials - by QuSoft http://195.12.232.172/Downloaddoc.html ________________________________________________________________________ ¡TÚ PUEDES AYUDARNOS! Necesitamos tu ayuda para que este boletín pueda continuar y crecer. Una forma en que puedes ayudarnos es enviando este enlace a tus amigos: http://www.latiumsoftware.com/es/pascal/index.php Otra forma es votándonos en alguno de estos rankings para darle más visibilidad a nuestro sitio web y aumentar así el número de suscrip- ciones al boletín, que esperamos en el futuro se traduzca también en un mayor número de colaboraciones de artículos, trucos, etc.: http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://www.top219.org/cgi-bin/vote.cgi?delphi&83 http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80 http://www.programacion.net/votar-enlace.php?id=474 http://www.lawebdelprogramador.com/buscar/enlace.php?id=615 Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden hacer la diferencia. Necesitamos tu ayuda para poder continuar. ________________________________________________________________________ Si no has recibido el archivo con el código fuente completo de los ejemplos que se presentan en este boletín, puedes descargarlo de la siguiente dirección: http://www.latiumsoftware.com/descarga/p0022.zip ________________________________________________________________________ Página principal: http://www.latiumsoftware.com/es/pascal/index.php Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/ Para suscribirse / apuntarse: boletin-pascal-subscribe@gruposyahoo.com Para cancelar / removerse: boletin-pascal-unsubscribe@gruposyahoo.com Para reportar problemas con la suscripción: eds2004 @ latiumsoftware.com ________________________________________________________________________ Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase. Su uso implica la aceptación de nuestros términos de licencia y de la ausencia de garantía que puedes leer en nuestro sitio web. Allí también encontrarás una nota sobre marcas registradas. Te animamos a que redis- tribuyas este boletín, siempre y cuando lo hagas en forma completa (incluyendo la información de copyright), sin modificaciones y de manera gratuita. Los artículos son copyright de sus respectivos autores y se reproducen aquí con el permiso de los mismos. ________________________________________________________________________ Latium Software http://www.latiumsoftware.com/es/index.php Copyright (c) 2001 por Ernesto De Spirito. Todos los derechos reservados ________________________________________________________________________ |
Los ejemplos completos de código fuente de este número están disponibles para descargar.
![]() |
¿Errores? ¿Omisiones? ¿Comentarios? Por favor contáctanos!






