<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8419825193906400044</id><updated>2012-01-28T23:07:57.528-06:00</updated><category term='Windows XP'/><category term='mensajes Windows'/><category term='manejo de cadenas'/><category term='clase de objeto'/><category term='China'/><category term='GetFieldData'/><category term='memoria compartida'/><category term='debate'/><category term='Skype'/><category term='BLOBs'/><category term='farmacéuticas'/><category term='Windows messages'/><category term='déficit'/><category term='GH Freebrary'/><category term='compilador'/><category term='Embarcadero'/><category term='Object Pascal'/><category term='AfterFieldChange'/><category term='molde de acceso'/><category term='OnValidate'/><category term='ghCountTo'/><category term='GHFStrings'/><category term='BoundsRect'/><category term='historia monetaria'/><category term='publicistas'/><category term='Delphi'/><category term='documental'/><category term='economía'/><category term='conjuntos de datos'/><category term='herencia insertada'/><category term='video'/><category term='Eventos'/><category term='libro'/><category term='TDataSource'/><category term='carteles'/><category term='TField'/><category term='TDateTime'/><category term='Inc con Strings'/><category term='Sierra de Nombre de Dios'/><category term='TRect'/><category term='clases virtuales'/><category term='Finalization'/><category term='asignación de campos'/><category term='ghInc'/><category term='directive'/><category term='expresión objeto'/><category term='tipos genéricos'/><category term='epidemia'/><category term='PRect'/><category term='truco'/><category term='asesoría presencial'/><category term='NativeFormat'/><category term='AdSense'/><category term='anclar'/><category term='presentación'/><category term='sistema bancario'/><category term='compiler'/><category term='.NET'/><category term='OnDataChange'/><category term='redefinición de clases'/><category term='Delphi Prism'/><category term='Microsoft'/><category term='incrustar'/><category term='instancia'/><category term='$Include'/><category term='redacción'/><category term='Panda'/><category term='inversiones'/><category term='ghCased'/><category term='Chihuahua'/><category term='factura electrónica'/><category term='unidades'/><category term='arte'/><category term='cloning datasets'/><category term='publicidad'/><category term='ghEquals'/><category term='pattern objects'/><category term='Guadalajara'/><category term='ámbito'/><category term='usura'/><category term='compartir datos entre programas'/><category term='Obama'/><category term='data modules'/><category term='actualizaciones'/><category term='España'/><category term='embed'/><category term='Darío Álvarez'/><category term='SetData'/><category term='pandemia'/><category term='otoño'/><category term='Ian Marteens'/><category term='Variant'/><category term='objetos patrón'/><category term='Magia Data'/><category term='bonos'/><category term='la obra de mi vida'/><category term='Delphi 7'/><category term='Google'/><category term='bolsas'/><category term='Format con argumentos opcionales'/><category term='Interfaz GH'/><category term='sintaxis. syntax'/><category term='formato nativo'/><category term='dinero como deuda'/><category term='trick'/><category term='virus'/><category term='TMagiaDataSource'/><category term='ghCorrelStr'/><category term='autobús'/><category term='originalidad'/><category term='TIntegerField'/><category term='comprobante fiscal digital'/><category term='instancias en memoria compartida'/><category term='México'/><category term='suspensión de pagos'/><category term='Río Sacramento'/><category term='ghCount'/><category term='ghFormatOptional'/><category term='Marco Santin'/><category term='desierto'/><category term='TDataSet'/><category term='universidades'/><category term='antivirales'/><category term='ghCopy'/><category term='prevent from moving'/><category term='window'/><category term='edición'/><category term='noviembre'/><category term='evitar que se mueva'/><category term='CFDI'/><category term='OnChange'/><category term='intereses'/><category term='timbrado'/><category term='embeber'/><category term='bancos'/><category term='WM_MOVING'/><category term='funcionamiento sistema monetario'/><category term='units'/><category term='buffers'/><category term='POO'/><category term='conciencia global'/><category term='DataSetCloned'/><category term='scope'/><category term='Top'/><category term='calificadoras'/><category term='verificar clase'/><category term='gramática'/><category term='Hacienda'/><category term='National Geographic'/><category term='SetFieldData'/><category term='BeforeFieldChange'/><category term='EDL'/><category term='método Clear'/><category term='dólar'/><category term='PAC'/><category term='comparar sin acentos'/><category term='taller Delphi'/><category term='biblioteca'/><category term='calidad del texto'/><category term='directiva Absolute'/><category term='objetos superglobales'/><category term='ventana'/><category term='profesor'/><category term='deuda pública'/><category term='Delphi 2009'/><category term='música'/><category term='evento'/><category term='CFD'/><category term='depuración de proyectos'/><category term='viaje'/><category term='Fey'/><category term='form'/><category term='fotografía'/><category term='TDateField'/><category term='dinero'/><category term='Electronic Document Library'/><category term='ortografía'/><category term='aprendizaje'/><category term='influenza'/><category term='Initialization'/><category term='motor de búsquedas'/><category term='Gopac'/><category term='tipo declarativo'/><category term='antivíricos'/><category term='creación de dinero'/><category term='Override'/><category term='SAT'/><category term='LastUnits'/><category term='sistema'/><category term='clonación de objetos'/><category term='anchoring'/><category term='crédito'/><category term='objetos compartidos'/><category term='banqueros'/><category term='Estados Unidos'/><category term='data sets'/><category term='préstamos'/><category term='2005'/><category term='directiva'/><category term='CodeGear'/><category term='Ballmer'/><category term='gripe'/><category term='TCustomClientDataSet'/><category term='empresas'/><category term='Vialidad Sacramento'/><category term='formulario'/><category term='ghEqualStrs'/><category term='historia bancaria'/><category term='paisaje'/><category term='Uses'/><category term='ghFormatStr'/><category term='títulos de deuda'/><category term='Norteamérica'/><category term='operador Is'/><category term='módulos de datos'/><category term='TStringField'/><category term='calidad ortográfica'/><category term='capitales'/><category term='CFD 3.0'/><title type='text'>Rescatando a Delphi</title><subtitle type='html'>Por lo que Object Pascal representa.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-4854675200541413810</id><published>2011-11-18T21:39:00.001-06:00</published><updated>2011-11-18T21:51:54.158-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fotografía'/><category scheme='http://www.blogger.com/atom/ns#' term='Chihuahua'/><category scheme='http://www.blogger.com/atom/ns#' term='otoño'/><category scheme='http://www.blogger.com/atom/ns#' term='Sierra de Nombre de Dios'/><category scheme='http://www.blogger.com/atom/ns#' term='paisaje'/><category scheme='http://www.blogger.com/atom/ns#' term='Norteamérica'/><category scheme='http://www.blogger.com/atom/ns#' term='México'/><category scheme='http://www.blogger.com/atom/ns#' term='viaje'/><category scheme='http://www.blogger.com/atom/ns#' term='noviembre'/><category scheme='http://www.blogger.com/atom/ns#' term='autobús'/><category scheme='http://www.blogger.com/atom/ns#' term='Río Sacramento'/><category scheme='http://www.blogger.com/atom/ns#' term='Vialidad Sacramento'/><category scheme='http://www.blogger.com/atom/ns#' term='desierto'/><title type='text'>Paraje otoñal</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-4Xv1aRmTKJ8/TsclZh3XjdI/AAAAAAAAAJg/SjW6NqpFCMc/s1600/ParajeOto%25C3%25B1al.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://2.bp.blogspot.com/-4Xv1aRmTKJ8/TsclZh3XjdI/AAAAAAAAAJg/SjW6NqpFCMc/s400/ParajeOto%25C3%25B1al.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt; &lt;w:WordDocument&gt;  &lt;w:View&gt;Normal&lt;/w:View&gt;  &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;  &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;  &lt;w:DoNotOptimizeForBrowser/&gt; &lt;/w:WordDocument&gt;&lt;/xml&gt;&lt;![endif]--&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt;"&gt;Al llegar a Chihuahuahace un par de días.&amp;nbsp; Imagen captada através de la ventana del autobús (perdón por los reflejos del cristal).&lt;span style="mso-spacerun: yes;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-4854675200541413810?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/4854675200541413810/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/11/paraje-otonal.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4854675200541413810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4854675200541413810'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/11/paraje-otonal.html' title='Paraje otoñal'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-4Xv1aRmTKJ8/TsclZh3XjdI/AAAAAAAAAJg/SjW6NqpFCMc/s72-c/ParajeOto%25C3%25B1al.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7230950758622816880</id><published>2011-11-10T23:58:00.001-06:00</published><updated>2011-11-11T00:10:01.775-06:00</updated><title type='text'>Un TTimer no crea otro hilo</title><content type='html'>&lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Esta noche, curioseando en las estadísticasde Rescatando a Delphi, descubrí que algún &lt;i&gt;internauta&lt;/i&gt; de buen corazónentró aquí a través de mi firma en uno de los mensajes de Club Delphi.&amp;nbsp; Y a pesar de que el tema en cuestión es dehace escasos seis meses, ya había olvidado por completo esa intervención.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Tras leer el tema nuevamente me pareció quepodría valer la pena facilitar a otras personas la explicación que, de formamuy resumida, puse ahí sobre el funcionamiento de un temporizador:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=73908"&gt;Enlace&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Además, esto invita a otros desarrolladoresa enriquecer la discusión en el foro.&amp;nbsp;Una respuesta de pocas líneas (como fue la mía) no hace un apartadodigno de encuadernarse, pero con la participación atrevida de otros más lo peorque puede pasar es que surjan &lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=73375"&gt;experienciasinolvidables&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Normalmente se facilitan hipervínculos debitácoras Web dentro de los foros, pero ¿cuál es la razón por la cual no escostumbre poner enlaces a temas puntuales de foros dentro de las bitácorasWeb?&amp;nbsp; Razonándolo, creo que mientrashaya algo bueno qué compartir, no debe ser de gran consideración dónde seencuentre ni dónde se divulgue.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;O, ¿ustedes qué piensan?&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Al González.&lt;/span&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7230950758622816880?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7230950758622816880/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/11/un-ttimer-no-crea-otro-hilo.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7230950758622816880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7230950758622816880'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/11/un-ttimer-no-crea-otro-hilo.html' title='Un TTimer no crea otro hilo'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-4485868963796423627</id><published>2011-10-22T18:55:00.000-05:00</published><updated>2011-10-22T18:55:15.331-05:00</updated><title type='text'>Magia Data disponible para descarga</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt; &lt;w:WordDocument&gt;  &lt;w:View&gt;Normal&lt;/w:View&gt;  &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;  &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;  &lt;w:DoNotOptimizeForBrowser/&gt; &lt;/w:WordDocument&gt;&lt;/xml&gt;&lt;![endif]--&gt;&lt;br /&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt; &lt;w:WordDocument&gt;  &lt;w:View&gt;Normal&lt;/w:View&gt;  &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;  &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;  &lt;w:DoNotOptimizeForBrowser/&gt; &lt;/w:WordDocument&gt;&lt;/xml&gt;&lt;![endif]--&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Estos son unos componentes en los que hetrabajado durante más de cinco años, derivados de varias clases nativas deDelphi 7 pero con características interesantes que les dan cierta ventaja.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Mi plan es integrarlos como parte de GHFreebrary en una sola biblioteca de licencia libre, pero últimamente no hepodido dedicar el tiempo suficiente a terminar esa integración.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Así que hace algunos días los puse adisposición del público tal cual estaban hasta marzo de 2011.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Cuando haya terminado de integrar en unsolo paquete a GH Freebrary y Magia Data, lo subiré muy probablemente a BerliOSy, claro está, con una licencia de software libre y un pequeño manual dereferencia.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Mientras tanto solicito medisculpen por ofrecerles algo tan poco presentable por fuera, esperando que seaprovechoso a más de uno lo que viene dentro.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Navegando en las declaraciones del códigofuente (o en el resto del mismo) les será relativamente fácil vislumbrar elpropósito de la mayoría de las características agregadas, pero cualquier dudaque les surja tendrá en esta bitácora o a través de mi correo unarespuesta&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;(prefiero que sea aquí paramayor retroalimentación entre todos).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;En los archivos de texto encontrarán lasinstrucciones de instalación.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;a href="http://www.terawiki.com/clubdelphi/archivos/Delphi/Componentes-Funciones/MagiaData7.zip"&gt;Descarga&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Un abrazo imperfecto.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Al González.&lt;/span&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12.0pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12.0pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-4485868963796423627?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/4485868963796423627/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/10/magia-data-disponible-para-descarga.html#comment-form' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4485868963796423627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4485868963796423627'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/10/magia-data-disponible-para-descarga.html' title='Magia Data disponible para descarga'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-766226325682329078</id><published>2011-08-30T15:18:00.000-05:00</published><updated>2011-08-30T15:18:31.752-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ortografía'/><category scheme='http://www.blogger.com/atom/ns#' term='carteles'/><category scheme='http://www.blogger.com/atom/ns#' term='AdSense'/><category scheme='http://www.blogger.com/atom/ns#' term='edición'/><category scheme='http://www.blogger.com/atom/ns#' term='calidad del texto'/><category scheme='http://www.blogger.com/atom/ns#' term='publicistas'/><category scheme='http://www.blogger.com/atom/ns#' term='empresas'/><category scheme='http://www.blogger.com/atom/ns#' term='calidad ortográfica'/><category scheme='http://www.blogger.com/atom/ns#' term='publicidad'/><category scheme='http://www.blogger.com/atom/ns#' term='motor de búsquedas'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><category scheme='http://www.blogger.com/atom/ns#' term='redacción'/><category scheme='http://www.blogger.com/atom/ns#' term='originalidad'/><category scheme='http://www.blogger.com/atom/ns#' term='Panda'/><category scheme='http://www.blogger.com/atom/ns#' term='gramática'/><title type='text'>Ortografía sepulturera</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;  &lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Como habrán notado, recientemente agregué a esta bitácora &lt;a href="http://es.wikipedia.org/wiki/AdSense"&gt;AdSense&lt;/a&gt;, el servicio de Google para insertar mesurada publicidad en los sitios Web a cambio de regalías.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Cabe decir que he configurado dicho servicio procurando que esa publicidad resulte muy poco o nada molesta a los lectores.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Por otra parte, Google &lt;a href="http://www.bbc.co.uk/mundo/noticias/2011/08/110816_tecnologia_google_algoritmo_panda_jrg.shtml"&gt;ha modificado&lt;/a&gt; su fastuoso motor de búsquedas, para priorizar en sus listas de resultados a los sitios con originalidad de contenido y calidad ortográfica mayores.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;  &lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Todo esto me parece muy bien, pero confío en que la publicidad de las empresas aquí anunciadas no será tomada en cuenta por el mencionado motor como parte del sitio:&lt;/span&gt;&lt;/div&gt;&lt;span lang="ES-MX"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-HryBN8iFOGo/Tl1C5WqqArI/AAAAAAAAAIs/GbNbndgO4kI/s1600/Ortograf%25C3%25ADaSepulturera.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="372" src="http://4.bp.blogspot.com/-HryBN8iFOGo/Tl1C5WqqArI/AAAAAAAAAIs/GbNbndgO4kI/s400/Ortograf%25C3%25ADaSepulturera.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;/span&gt;&lt;span lang="ES-MX"&gt;En lo cotidiano no hay individuo salvo de incurrir en una que otra falta de ortografía, y no por ello se acaba el mundo.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Sin embargo, la publicidad comercial tiene consecuencias realmente negativas para una empresa anunciante cuando sus textos aparecen mal escritos, pues muchos de sus potenciales clientes pensarán:&lt;/span&gt;  &lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoBodyText"&gt;&lt;i&gt;&lt;span lang="ES-MX"&gt;¡Vaya!&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Si no tienen cuidado en esto, ¿cómo serán los productos y servicios que me ofrecen?&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Un abrazo sin previo anuncio.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Al González.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-766226325682329078?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/766226325682329078/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/08/ortografia-sepulturera.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/766226325682329078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/766226325682329078'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/08/ortografia-sepulturera.html' title='Ortografía sepulturera'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-HryBN8iFOGo/Tl1C5WqqArI/AAAAAAAAAIs/GbNbndgO4kI/s72-c/Ortograf%25C3%25ADaSepulturera.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7645420898639786185</id><published>2011-08-16T02:30:00.000-05:00</published><updated>2011-08-16T02:30:07.901-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WM_MOVING'/><category scheme='http://www.blogger.com/atom/ns#' term='mensajes Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='prevent from moving'/><category scheme='http://www.blogger.com/atom/ns#' term='ventana'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows messages'/><category scheme='http://www.blogger.com/atom/ns#' term='window'/><category scheme='http://www.blogger.com/atom/ns#' term='formulario'/><category scheme='http://www.blogger.com/atom/ns#' term='PRect'/><category scheme='http://www.blogger.com/atom/ns#' term='TRect'/><category scheme='http://www.blogger.com/atom/ns#' term='truco'/><category scheme='http://www.blogger.com/atom/ns#' term='BoundsRect'/><category scheme='http://www.blogger.com/atom/ns#' term='evitar que se mueva'/><category scheme='http://www.blogger.com/atom/ns#' term='trick'/><title type='text'>Inamovible</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;  &lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Un truco nada complicado pero en ocasiones útil:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="delphi" style="background-color: #dcdccd; border: 1px solid #d0d0d0; color: #000066; font-family: monospace;"&gt;&lt;span style="color: black; font-weight: bold;"&gt;type&lt;/span&gt;&lt;br /&gt;&amp;nbsp; TForm1 &lt;span style="color: #000066;"&gt;=&lt;/span&gt; &lt;span style="color: black; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: #000066;"&gt;(&lt;/span&gt;TForm&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;private&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: grey; font-style: italic;"&gt;{ Private declarations }&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;Procedure&lt;/span&gt; WMMoving &lt;span style="color: #000066;"&gt;(&lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;Var&lt;/span&gt; Mensaje &lt;span style="color: #000066;"&gt;:&lt;/span&gt;TMessage&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt; Message wm_Moving&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;public&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: grey; font-style: italic;"&gt;{ Public declarations }&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;end&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;var&lt;/span&gt;&lt;br /&gt;&amp;nbsp; Form1&lt;span style="color: #000066;"&gt;:&lt;/span&gt; TForm1&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green; font-style: italic;"&gt;{$R *.dfm}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;Procedure&lt;/span&gt; TForm1&lt;span style="color: #000066;"&gt;.&lt;/span&gt;&lt;span style="color: #006600;"&gt;WMMoving&lt;/span&gt; &lt;span style="color: #000066;"&gt;(&lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;Var&lt;/span&gt; Mensaje &lt;span style="color: #000066;"&gt;:&lt;/span&gt;TMessage&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;Begin&lt;/span&gt;&lt;br /&gt;&amp;nbsp; PRect &lt;span style="color: #000066;"&gt;(&lt;/span&gt;Mensaje&lt;span style="color: #000066;"&gt;.&lt;/span&gt;&lt;span style="color: #006600;"&gt;LParam&lt;/span&gt;&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;span style="color: #000066;"&gt;^&lt;/span&gt; &lt;span style="color: #000066;"&gt;:&lt;/span&gt;&lt;span style="color: #000066;"&gt;=&lt;/span&gt; BoundsRect&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;Inherited&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;End&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7645420898639786185?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7645420898639786185/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/08/inamovible.html#comment-form' title='11 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7645420898639786185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7645420898639786185'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/08/inamovible.html' title='Inamovible'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-279163100144978355</id><published>2011-07-31T21:45:00.001-05:00</published><updated>2011-08-03T23:05:55.802-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dinero'/><category scheme='http://www.blogger.com/atom/ns#' term='títulos de deuda'/><category scheme='http://www.blogger.com/atom/ns#' term='deuda pública'/><category scheme='http://www.blogger.com/atom/ns#' term='inversiones'/><category scheme='http://www.blogger.com/atom/ns#' term='capitales'/><category scheme='http://www.blogger.com/atom/ns#' term='suspensión de pagos'/><category scheme='http://www.blogger.com/atom/ns#' term='economía'/><category scheme='http://www.blogger.com/atom/ns#' term='bolsas'/><category scheme='http://www.blogger.com/atom/ns#' term='China'/><category scheme='http://www.blogger.com/atom/ns#' term='Obama'/><category scheme='http://www.blogger.com/atom/ns#' term='Estados Unidos'/><category scheme='http://www.blogger.com/atom/ns#' term='déficit'/><category scheme='http://www.blogger.com/atom/ns#' term='bonos'/><category scheme='http://www.blogger.com/atom/ns#' term='dólar'/><category scheme='http://www.blogger.com/atom/ns#' term='calificadoras'/><title type='text'>Ensayo sobre los bonos del tesoro — intentando explicar algo de lo que pasa.</title><content type='html'>&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Un estado, entendido como «&lt;i&gt;conjunto de los órganos de gobierno de un país soberano&lt;/i&gt;», necesita financiación, o financiamiento, como decimos en varios países de América, para llevar a cabo sus funciones.&amp;nbsp; La manera más elemental de obtenerlo es mediante los impuestos, pero a veces esto resulta insuficiente, ya sea por una muy baja tributación o por una mala planeación de presupuestos de parte del gobierno, así que ocasionalmente los estados optan por crear más dinero y ponerlo en circulación.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Con esta medida se estimulan las actividades económicas y el estado se ve temporalmente favorecido por una mayor captación de impuestos, pero tiene su lado malo: poner más dinero en circulación suele generar inflación.&amp;nbsp; Esto se explica porque a mayor dinero circulante, mayor demanda de productos y servicios, lo cual deriva (en regímenes económicos de libre mercado) en un alza generalizada de precios.&amp;nbsp; La inflación hace que el valor real del dinero —lo que con él puede adquirirse— disminuya.&amp;nbsp; Por ejemplo, en 1997 compré con 500 pesos una bici de montaña, pero hoy necesitaría por lo menos el doble de dinero para comprarme una nueva bicicleta de iguales características.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hay otro mecanismo por el cual un estado puede hacerse de recursos financieros para su operación, que consiste sencillamente en pedir prestado a todas aquellas personas, organizaciones y gobiernos de cualquier parte del mundo que tengan algo de dinero "extra".&amp;nbsp; Para que el préstamo resulte atractivo al potencial prestamista, el estado promete devolverle su dinero, al cabo de algún tiempo, añadiéndole un interés (ganancia) que por lo general es mayor al que puede obtenerse con una cuenta de ahorro bancaria.&amp;nbsp; Sin embargo, al estado le resultaría tremendamente complicado celebrar un contrato de préstamo con cada individuo de cualquier parte del mundo dispuesto a prestarle el dinero de su alcancía, por lo cual recurre a un mecanismo muy práctico llamado &lt;i&gt;bono&lt;/i&gt;.&amp;nbsp; No hablo del vocalista de U2 (que si todos los políticos fueran como él estaría yo escribiendo otras cosas), sino de una especie de &lt;i&gt;letra&lt;/i&gt; o &lt;i&gt;pagaré &lt;/i&gt;pero, &lt;i&gt;al portador&lt;/i&gt;, con vencimiento de meses, años o incluso décadas.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Cuando el estado se ve necesitado de dinero hace una subasta de miles de bonos y todo aquel que tenga el suficiente dinero como para comprarse una bici de montaña (con lo cual ese individuo lo invertiría muy sanamente), puede optar por gastárselo en uno o más de los llamados &lt;i&gt;bonos del tesoro&lt;/i&gt; o &lt;i&gt;del estado&lt;/i&gt;.&amp;nbsp; Con esa operación el que aporta el dinero confía en que, cuando venza el documento, el estado emisor del bono habrá administrado de manera eficiente la economía de su país, éste habrá generado riqueza a través de la actividad productiva de su población, sin mal gastar dicha riqueza ni el propio dinero del préstamo, y entonces el estado le habrá de regresar una cantidad algo más alta (&lt;i&gt;retorno de inversión&lt;/i&gt;) que le alcanzará para comprarse, además de la bici, un casco y un helado de zapote.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Los bonos, como casi siempre son &lt;i&gt;títulos de deuda&lt;/i&gt; al portador, pueden ser transferidos por el inversionista a cualquier persona.&amp;nbsp; Entonces resulta habitual que muchos poseedores de bonos, vendan estos en algún momento, ya sea por necesidad de liquidez inmediata o por&amp;nbsp; alguna repentina desconfianza en la capacidad de pago del estado deudor.&amp;nbsp; Pero también es relevante decir que la compra-venta de bonos es una forma ciertamente extendida de hacer negocio, y que muchos bonos se utilizan hoy en día en forma de reservas (como tener oro almacenado por si acaso ocurre un imprevisto) y para comprar bienes y servicios (a manera de dinero).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;El problema para el poseedor de un bono es que si el estado emisor del documento hace un mal manejo de su economía, mal gasta la hacienda pública, su población no produce la riqueza suficiente o el país como tal incurre en alguna crisis, puede no llegar a recibir a tiempo el dinero y los intereses que representa ese bono, o incluso no recibirlos jamás.&amp;nbsp; Situaciones así han ocurrido a lo largo del último siglo, donde más de un país se ha visto en serios aprietos al no poder hacer frente a las deudas que ha contraído mediante emisión de bonos.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hace muchos años surgieron las llamadas &lt;i&gt;agencias de calificación de riesgos&lt;/i&gt; (como las odiosas Standard &amp;amp; Poor's, Moody's y Fitch, cuya reputación quedó en entre dicho tras la crisis financiera de 2008).&amp;nbsp; Estas empresas se dedican, &lt;i&gt;grosso modo&lt;/i&gt;, a señalar qué tan confiables son las inversiones en una u otra cosa, incluyendo los bonos estatales de los diferentes países que emplean este divertido mecanismo de conseguir dinero rápido.&amp;nbsp; Las calificaciones hechas por estas agencias les permiten a los inversionistas decidir entre comprar bonos de un país o de otro, ya no sólo con base al rédito ofrecido, sino también considerando la probabilidad de que dichos bonos vayan a ser pagados debidamente en su fecha de vencimiento.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;La mayor calificación que otorgan estas entidades es la &lt;i&gt;triple A&lt;/i&gt; (AAA), que no se refiere a la lucha libre mexicana xD.&amp;nbsp; Es simplemente una forma de decir que el bono de tal país es altamente confiable, estable y que tiene el grado más pequeño de riesgo.&amp;nbsp; Resulta que los bonos del tesoro de Estados Unidos de América han gozado durante años de esa magnífica categoría, pero desde las últimas dos o tres administraciones se ha venido gestando un espinoso escenario que quizá empuje a las agencias calificadoras a darles una posición menor en los próximos días.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Estados Unidos debe en bonos del tesoro miles de millones de dólares a tenedores de todos los tamaños (individuos, empresas, gobiernos) y de todas partes del mundo.&amp;nbsp; Tenedores que en algún momento, creyendo ciegamente en la solvencia del gigante norteamericano, le prestaron dinero (directa o indirectamente) y obtuvieron a cambio estos venerados documentos que han venido cuidando y manejado como si fueran un auténtico tesoro, haciendo planes y negocios con base al dinero futuro que cobrarán cuando los documentos lleguen a su respectiva fecha de vencimiento.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;En ese país, la ley impide que la deuda pública total del estado (entre bonos y otro tipo de deudas contraídas) sea superior a 14.29 billones de dólares, es decir, 14.29 &lt;i&gt;trillones&lt;/i&gt; gringos es el techo o tope máximo de deuda que el estado puede permitirse.&amp;nbsp; Por ahora desconozco la razón de esa cifra en específico, pero el hecho es que esta se alcanzó o estuvo a punto de alcanzarse a mediados de mayo y entonces el gobierno tomó medidas emergentes (ajustes de gastos, contables y fiscales) para darse algo más de tiempo y componer la situación.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Pero ya se llegó a un punto crítico: si no se hace nada, este martes 2 de agosto Estados Unidos amanecerá con la incapacidad económica de su gobierno para cumplir debidamente sus funciones y sus obligaciones de deuda.&amp;nbsp; Tendrá que recortar gastos en diferentes áreas de la administración y posiblemente entrar en suspensión o moratoria de pagos.&amp;nbsp; Esto no agradaría en absoluto ni a los empleados del gobierno, ni a los contratistas, ni a las empresas del país, ni a los inversionistas, ni a los actuales tenedores de bonos.&amp;nbsp; Sometería a la economía mundial a una fuerte presión, a una prolongada incertidumbre y a un temeroso ánimo por retener capitales, pues esta economía global en la que vivimos está cimentada sobre la aparente fortaleza del dólar y de los bonos estadounidenses.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;El siguiente enlace muestra cuáles son los 15 mayores acreedores de Estados Unidos en materia de bonos del tesoro, con China a la cabeza ostentando la friolera cifra de 1.15 billones de dólares:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;a href="http://www.libertaddigital.com/multimedia/galerias/acreedores-estados-unidos/Picadilly-circus.jpg.html#dolar-yuanes.jpg"&gt;http://www.libertaddigital.com/multimedia/galerias/acreedores-estados-unidos/Picadilly-circus.jpg.html#dolar-yuanes.jpg&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Pueden hacerse varias cosas para salir del paso nuevamente, los políticos estadounidenses —demócratas y republicanos— intentan ponerse de acuerdo en el método: aumentar el techo de endeudamiento para poder seguir captando dinero de un futuro cada vez más extraño, &lt;i&gt;adelgazar el estado&lt;/i&gt; (recortes en gastos del gobierno y despido de funcionarios), aumentar impuestos o una combinación de las tres cosas.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Echemos un último vistazo a las noticias del día...&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;&lt;a href="http://www.elpais.com/articulo/internacional/Acuerdo/Estados/Unidos/evitar/quiebra/elpepuint/20110801elpepuint_1/Tes"&gt;Acuerdo en Estados Unidos para evitar la quiebra.&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;¿Notan lo frágil que es este mundo?&amp;nbsp; Mejoremos el sistema antes de que el propio sistema nos deje a todos en &lt;i&gt;default&lt;/i&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Al González.&lt;/span&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-279163100144978355?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/279163100144978355/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/ensayo-sobre-los-bonos-del-tesoro.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/279163100144978355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/279163100144978355'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/ensayo-sobre-los-bonos-del-tesoro.html' title='Ensayo sobre los bonos del tesoro — intentando explicar algo de lo que pasa.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7451256159657226668</id><published>2011-07-22T23:10:00.000-05:00</published><updated>2011-07-22T23:10:22.378-05:00</updated><title type='text'>Feliz amanecer</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-b3yLgyEYayA/TipIhwaPYTI/AAAAAAAAAIg/cgRNN0J7Rr8/s1600/SDC13121b.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="285" src="http://2.bp.blogspot.com/-b3yLgyEYayA/TipIhwaPYTI/AAAAAAAAAIg/cgRNN0J7Rr8/s400/SDC13121b.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7451256159657226668?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7451256159657226668/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/feliz-amanecer.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7451256159657226668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7451256159657226668'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/feliz-amanecer.html' title='Feliz amanecer'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-b3yLgyEYayA/TipIhwaPYTI/AAAAAAAAAIg/cgRNN0J7Rr8/s72-c/SDC13121b.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-4670957372215043313</id><published>2011-07-06T01:45:00.000-05:00</published><updated>2011-07-06T01:45:48.828-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='timbrado'/><category scheme='http://www.blogger.com/atom/ns#' term='CFD 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='SAT'/><category scheme='http://www.blogger.com/atom/ns#' term='Hacienda'/><category scheme='http://www.blogger.com/atom/ns#' term='CFDI'/><category scheme='http://www.blogger.com/atom/ns#' term='México'/><category scheme='http://www.blogger.com/atom/ns#' term='comprobante fiscal digital'/><category scheme='http://www.blogger.com/atom/ns#' term='factura electrónica'/><category scheme='http://www.blogger.com/atom/ns#' term='PAC'/><category scheme='http://www.blogger.com/atom/ns#' term='Darío Álvarez'/><category scheme='http://www.blogger.com/atom/ns#' term='EDL'/><category scheme='http://www.blogger.com/atom/ns#' term='CFD'/><category scheme='http://www.blogger.com/atom/ns#' term='Electronic Document Library'/><category scheme='http://www.blogger.com/atom/ns#' term='biblioteca'/><title type='text'>Creación y timbrado de facturas electrónicas - CFDs firmados por un PAC</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;  &lt;br /&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:DoNotOptimizeForBrowser/&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;  &lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hace algún tiempo que trabajo para un cliente, que es desarrollador de software también, en la modernización de una de sus principales aplicaciones.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Al comenzar el año me encargó que fuera estudiando la manera de implementar facturación electrónica en el nuevo proyecto Delphi, pues empezaban a vislumbrarse casos donde su uso sería obligado.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Estimo que familiarizarse y tener cierto dominio con todos los conceptos que integran ese tema, conforme a lo establecido en las leyes mexicanas (porque en este caso México es el mercado destino del software en cuestión), puede llevar desde un par de meses hasta varios años, según el grado de interés que se ponga y la profundidad con que se investigue en las áreas contables, fiscales, legales y técnicas.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Me conozco y estoy seguro que seré de los que tardarán dos o tres años en sentir que manejo bien el tema.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;No obstante, leer una veintena de artículos, intercambiar varios correos, comentar en algunas bitácoras, participar en los foros y hacer un par de llamadas telefónicas me ayudó a determinar el camino más viable para lograr la generación de CFDs (Comprobantes Fiscales Digitales) desde una aplicación Delphi, y que estos CFDs o &lt;i&gt;facturas electrónicas&lt;/i&gt;, pudieran ser firmadas en tiempo real —vía Internet— por parte de un PAC (Proveedor Autorizado de Certificación).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Tenía muchas ganas de hacer esto con una biblioteca libre que crearon unos colegas de mi ciudad natal, pero desafortunadamente no recibieron un buen trato por parte de los PACs que contactaron, así que hasta el momento no han implementado la parte del timbrado.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Opté por acercarme a Darío Álvarez (alias &lt;i&gt;E=M*C^2 &lt;/i&gt;o&lt;i&gt; darioaa &lt;/i&gt;en algunos foros), quien ya me había requerido en 2010 para echar un vistazo a la biblioteca de programación que estaba por liberar, pero en aquel entonces carecía yo del tiempo y conocimiento fiscal suficiente para atreverme a hacerle alguna recomendación sobre su trabajo.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hoy ya sé a grandes rasgos lo que es un CFD, qué lo origina, qué elementos se necesitan para generarlo y qué datos devuelve un PAC cuando le es enviada una factura electrónica para su timbrado.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Y este conocimiento se refuerza conforme utilizo &lt;a href="http://www.electronicdocument.com.mx/"&gt;Electronic Document Library&lt;/a&gt;, la biblioteca Delphi que Darío creó para facilitar el trabajo de generar y timbrar comprobantes fiscales digitales.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Ahora que he tenido oportunidad de mirar su funcionamiento —por fuera, porque de momento no incluye el código fuente—, me hubiera gustado haber comenzado con todo este proceso un año antes para aconsejar puntualmente a Darío sobre varios aspectos de EDL que pueden y deben ser mejorados.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Él afortunadamente sigue abierto a mis aportaciones de revisión, por lo que seguramente le estaré haciendo llegar algunos correos con propuestas para las siguientes versiones de la biblioteca.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Sin embargo, hay que ver los actuales puntos a favor:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b&gt;&lt;span lang="ES-MX"&gt;1.&lt;/span&gt;&lt;/b&gt;&lt;span lang="ES-MX"&gt; La biblioteca EDL es funcional, genera, valida y permite timbrar CFDs.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Incluye lo necesario para realizar el timbrado con el PAC Freight Ideas, mejor conocido como Facturaxion.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;No obstante, escribiendo un poco más de código, el timbrado podría ser hecho con cualquier otro PAC que tenga la amabilidad de proporcionar acceso a su servicio Web de pruebas sin trabas comerciales de por medio.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Según comenta Darío, pocos fueron los PACs que se mostraron abiertos a esta iniciativa.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b&gt;&lt;span lang="ES-MX"&gt;2.&lt;/span&gt;&lt;/b&gt;&lt;span lang="ES-MX"&gt; El autor trabajó por nueve años para una compañía que desarrolla en Delphi un software de gestión empresarial.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;En ese tipo de aplicaciones resulta ineludible contemplar todos los detalles posibles de un comprobante fiscal digital, así que pocas cosas se le escapan cuando llega a sus manos una factura rebelde.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b&gt;&lt;span lang="ES-MX"&gt;3.&lt;/span&gt;&lt;/b&gt;&lt;span lang="ES-MX"&gt; Darío, si bien no es el programador más hábil que haya visto, es uno de los desarrolladores Delphi que más conoce sobre la historia y los aspectos técnicos, legales y fiscales de la facturación electrónica mexicana.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;Comenzó a estudiar el tema en el año 2005, justo cuando el gobierno dispuso el camino para la adopción de la factura electrónica a nivel nacional.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hasta ahora no he utilizado EDL en producción, pero al menos en las pruebas y con el PAC Facturaxion el objetivo se está cumpliendo.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;El timbrado es automático (demora un segundo a lo mucho con una conexión a Internet típica de hogar), y el XML enviado al PAC es regresado con el complemento &lt;a href="ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/TimbreFiscalDigital.xsd"&gt;TimbreFiscalDigital&lt;/a&gt; que tanto se desea.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Recomiendo pues &lt;a href="http://www.electronicdocument.com.mx/"&gt;Electronic Document Library (EDL)&lt;/a&gt;, una iniciativa Delphi que cuando menos un PAC ha sabido reconocer (esperemos que se sumen todos los demás).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Por cierto, que alguien le diga al SAT que &lt;i&gt;adenda&lt;/i&gt;, en castellano, no lleva doble de y que se escribe "&lt;i&gt;da validez&lt;/i&gt;" no "&lt;i&gt;da valides&lt;/i&gt;" (esta última es imperdonable).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Un abrazo electrónico.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Al González. :)&lt;/span&gt;&lt;/div&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12.0pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;/span&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12.0pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-4670957372215043313?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/4670957372215043313/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/creacion-y-timbrado-de-facturas.html#comment-form' title='12 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4670957372215043313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4670957372215043313'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/07/creacion-y-timbrado-de-facturas.html' title='Creación y timbrado de facturas electrónicas - CFDs firmados por un PAC'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-19628274965166692</id><published>2011-06-14T03:17:00.000-05:00</published><updated>2011-06-14T03:17:24.064-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='directive'/><category scheme='http://www.blogger.com/atom/ns#' term='unidades'/><category scheme='http://www.blogger.com/atom/ns#' term='directiva'/><category scheme='http://www.blogger.com/atom/ns#' term='Initialization'/><category scheme='http://www.blogger.com/atom/ns#' term='scope'/><category scheme='http://www.blogger.com/atom/ns#' term='Finalization'/><category scheme='http://www.blogger.com/atom/ns#' term='Ian Marteens'/><category scheme='http://www.blogger.com/atom/ns#' term='Uses'/><category scheme='http://www.blogger.com/atom/ns#' term='$Include'/><category scheme='http://www.blogger.com/atom/ns#' term='anclar'/><category scheme='http://www.blogger.com/atom/ns#' term='ámbito'/><category scheme='http://www.blogger.com/atom/ns#' term='truco'/><category scheme='http://www.blogger.com/atom/ns#' term='units'/><category scheme='http://www.blogger.com/atom/ns#' term='anchoring'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='sintaxis. syntax'/><category scheme='http://www.blogger.com/atom/ns#' term='compilador'/><category scheme='http://www.blogger.com/atom/ns#' term='trick'/><category scheme='http://www.blogger.com/atom/ns#' term='LastUnits'/><title type='text'>Anclar unidad al final del Uses</title><content type='html'>&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;span style="font-size: large;"&gt;&lt;span lang="ES-MX"&gt;[Anchoring a unit at the end of &lt;i&gt;Uses&lt;/i&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;span lang="ES-MX" style="font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;   &lt;br /&gt;&lt;span lang="ES-MX"&gt; &lt;/span&gt;   &lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;span lang="ES-MX"&gt;Contexto&lt;/span&gt; &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Una pregunta cuya respuesta es la razón de este artículo: ¿Importa el orden en el que aparecen los nombres de unidades en las cláusulas &lt;i&gt;Uses&lt;/i&gt; de una aplicación?&amp;nbsp; Un programador Delphi con cierta experiencia sabe que la respuesta es sí, y que existen básicamente dos razones por las cuales ese orden puede tener relevancia: &lt;b&gt;ámbito&lt;/b&gt; e &lt;b&gt;inicializaciones / finalizaciones&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;El &lt;i&gt;ámbito&lt;/i&gt; se refiere a cómo el compilador de Delphi&amp;nbsp; (al igual que muchos otros compiladores e intérpretes) localiza el origen de los identificadores que son referidos en el código fuente.&amp;nbsp; Para ilustrarlo, iniciemos en el IDE un nuevo proyecto Windows estándar.&amp;nbsp; Con esto será establecido en automático un primer formulario para el nuevo proyecto; guardemos todo (proyecto, formulario y su archivo de código fuente) con los nombres que Delphi propone.&amp;nbsp; El nuevo formulario aparecerá vacío y su código fuente, es decir, la unidad Unit1.pas, tendrá un aspecto como el siguiente:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="delphi" style="background-color: #dcdccd; border: 1px solid #d0d0d0; color: #000066; font-family: monospace;"&gt;&lt;span style="color: black; font-weight: bold;"&gt;unit&lt;/span&gt; Unit1&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;interface&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;uses&lt;/span&gt;&lt;br /&gt;&amp;nbsp; Windows&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Messages&lt;span style="color: #000066;"&gt;,&lt;/span&gt; SysUtils&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Variants&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Classes&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Graphics&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Controls&lt;span style="color: #000066;"&gt;,&lt;/span&gt; Forms&lt;span style="color: #000066;"&gt;,&lt;/span&gt;&lt;br /&gt;&amp;nbsp; Dialogs&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;type&lt;/span&gt;&lt;br /&gt;&amp;nbsp; TForm1 &lt;span style="color: #000066;"&gt;=&lt;/span&gt; &lt;span style="color: black; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: #000066;"&gt;(&lt;/span&gt;TForm&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;private&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: grey; font-style: italic;"&gt;{ Private declarations }&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;public&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: grey; font-style: italic;"&gt;{ Public declarations }&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: black; font-weight: bold;"&gt;end&lt;/span&gt;&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;var&lt;/span&gt;&lt;br /&gt;&amp;nbsp; Form1&lt;span style="color: #000066;"&gt;:&lt;/span&gt; TForm1&lt;span style="color: #000066;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green; font-style: italic;"&gt;{$R *.dfm}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;end&lt;/span&gt;&lt;span style="color: #000066;"&gt;.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Este código compilará sin problemas, pues se encuentra sintácticamente bien y todos los identificadores referidos pueden ser encontrados por el compilador (si no se ha hecho ningún cambio inadecuado en las opciones de configuración).&amp;nbsp; Durante la compilación, el analizador sintáctico de Delphi revisa este código fuente de arriba abajo y cuando encuentra la declaración de variable &lt;i&gt;Form1: TForm1&lt;/i&gt; verifica que ese tipo de dato, "TForm1", haya sido definido anteriormente.&amp;nbsp; En efecto, ahí podemos ver que la declaración del tipo clase TForm1 hubo de ser encontrada previamente varias líneas más arriba (&lt;i&gt;TForm1 = class...&lt;/i&gt;).&amp;nbsp; Por tanto, la declaración de la variable Form1 es correcta, ya que su tipo de dato, la clase TForm1, fue declarado con anticipación y además en el mismo ámbito: la sección pública &lt;i&gt;Interface&lt;/i&gt; de la unidad.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;¿Pero entonces qué pasó milésimas de segundo antes, cuando el analizador encontró el inicio de dicha clase, es decir, la línea&amp;nbsp; &lt;i&gt;TForm1 = class(TForm)&lt;/i&gt;?&amp;nbsp; Esta línea indica que se define una clase, de nombre "TForm1" e hija de la clase "TForm", pero ¿acaso TForm fue también definida antes en nuestra Unit1?&amp;nbsp; No, pero sí lo está dentro de una de las unidades nativas de Delphi señaladas por la cláusula &lt;b&gt;&lt;i&gt;Uses&lt;/i&gt;&lt;/b&gt;&lt;i&gt;:&lt;/i&gt; la unidad Forms.&amp;nbsp; En la VCL, dentro de la sección pública &lt;i&gt;Interface&lt;/i&gt; de la unidad Forms.pas, podemos encontrar su declaración:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="delphi" style="background-color: #dcdccd; border: 1px solid #d0d0d0; color: #000066; font-family: monospace;"&gt;&amp;nbsp; TForm &lt;span style="color: #000066;"&gt;=&lt;/span&gt; &lt;span style="color: black; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: #000066;"&gt;(&lt;/span&gt;TCustomForm&lt;span style="color: #000066;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #000066;"&gt;...&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Dado que Forms aparece nombrada en la cláusula &lt;i&gt;Uses&lt;/i&gt; de Unit1, el análisis sintáctico del compilador no tiene problemas para resolver que la clase TForm definida en Forms.pas será el padre de TForm1 —&lt;i&gt;TForm1 = class(TForm)&lt;/i&gt;—.&amp;nbsp; Lo que ocurrió fue que el analizador sintáctico primero revisó si el identificador referido (TForm), había sido declarado o no de manera previa en la misma sección de código de Unit1.&amp;nbsp; Como la clase TForm no está definida ahí, el analizador comenzó a buscarla en la parte pública de las unidades agrupadas bajo la cláusula &lt;i&gt;Uses&lt;/i&gt;, pero &lt;u&gt;comenzando por la última&lt;/u&gt; (Dialogs) y luego la penúltima (Forms), dentro de la cual fue felizmente encontrada.&amp;nbsp; Suponiendo que TForm no hubiera estado definida dentro de la unidad Forms, el analizador habría revisado en la sección pública &lt;i&gt;Interface&lt;/i&gt; de cada una de las otras (Controls, Graphics, Classes, Variants, SysUtils, Messages y Windows) hasta aparecer un error &lt;i&gt;Undeclared identifier: 'TForm'&lt;/i&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;He explicado de una manera un tanto burda cómo hace Delphi para localizar un identificador referido, pero es muy probable que dicha búsqueda se lleve a cabo sobre código pre-compilado y no entrando cada vez y físicamente a las unidades nombradas en el &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; El hecho es que, por las reglas de ámbito del compilador, &lt;u&gt;un identificador referido es localizado "hacia arriba" y comenzando por el elemento "más cercano"&lt;/u&gt;, de ahí que la búsqueda en las unidades del &lt;i&gt;Uses&lt;/i&gt; empiece por la última de estas.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Ahora bien, puede ocurrir que entre las unidades que tengamos nombradas en una cláusula &lt;i&gt;Uses&lt;/i&gt;, dos de ellas definan en su interior algún elemento público con el mismo nombre (coincidencia de identificadores).&amp;nbsp; Esto suele ocurrir cuando utilizamos varias bibliotecas de terceros y alguna constante, función, clase, etc. de una de las bibliotecas lleva el mismo identificador que algún elemento público de las otras (aún hay programadores de bibliotecas que no aprecian el debido uso de prefijos).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;También hay casos donde la coincidencia de identificadores es deliberada, como sucede al emplear &lt;i&gt;clases interpuestas&lt;/i&gt;, una socorrida técnica que Ian Marteens explica muy bien en uno de sus artículos: &lt;a href="http://www.marteens.com/trick46.htm"&gt;http://www.marteens.com/trick46.htm&lt;/a&gt;.&amp;nbsp; Ponga especial atención sobre "&lt;i&gt;LOS LIMITES DE LA TÉCNICA&lt;/i&gt;", en el párrafo que dice:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;«[...] &lt;i&gt;tenemos que incluir la nueva unidad en la cláusula uses del formulario, pero teniendo cuidado de ubicarla después de la unidad donde se encuentra la clase original&lt;/i&gt; [...]»&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;En ambas situaciones de coincidencia de nombres (caso fortuito o intencional), conocer la regla de ámbito del compilador, de buscar "hacia arriba" y empezando por "lo más cercano", nos permite determinar en qué orden deben ser colocadas las unidades del &lt;i&gt;Uses&lt;/i&gt; para que el compilador y la aplicación misma trabajen como se quiere.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Con todo lo anterior queda explicado que, debido a la regla de ámbito mencionada, sí puede ser importante el orden en el que aparecen los nombres de unidades en las cláusulas &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; Mientras que el otro motivo que mencioné al principio —inicializaciones / finalizaciones&lt;i&gt; &lt;/i&gt;— se refiere a cómo se ejecutan las secciones &lt;i&gt;Initialization&lt;/i&gt; y &lt;i&gt;Finalization&lt;/i&gt; contenidas en algunas unidades de código.&amp;nbsp; Pero en ello no habremos de profundizar ahora, sólo diremos que el orden en el cual se ejecutan dichas secciones depende de cómo el compilador va encontrando referencias a esas unidades en las diferentes cláusulas &lt;i&gt;Uses&lt;/i&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span lang="ES-MX" style="font-size: large;"&gt;El problema&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Ya vimos que ante ciertas situaciones puede ser relevante el lugar que ocupe el nombre de una unidad dentro de una cláusula &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; El problema es que ni el lenguaje Object Pascal ni el IDE de Delphi poseen un mecanismo para indicar de forma explícita tal relevancia, y bajo algunas circunstancias el IDE, en su noble afán de facilitarnos las cosas, agrega por sí solo nombres de unidades al final del &lt;i&gt;Uses&lt;/i&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Para ver cuándo ocurre eso, volvamos a nuestro proyecto de ejemplo.&amp;nbsp; Supongamos que el formulario Form1, es decir, la clase TForm1, requiere de un archivo de código llamado Ultima.pas (unidad propia, nativa o de terceros) para las operaciones que se realizan en él, y que por alguna razón como las ya mencionadas es menester que el nombre de esa unidad aparezca siempre en el extremo final de la cláusula &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; Pues sencillo: simplemente escribimos "&lt;i&gt;, Ultima&lt;/i&gt;" al final de dicha cláusula:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-U3lmE5Ck38E/TfcTL9phtoI/AAAAAAAAAIM/J3E6FdfB0Ec/s1600/Imagen1.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="412" src="http://4.bp.blogspot.com/-U3lmE5Ck38E/TfcTL9phtoI/AAAAAAAAAIM/J3E6FdfB0Ec/s640/Imagen1.JPG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Pero ¿qué sucedería si luego agregamos al formulario un componente, por ejemplo un TEdit y, acto seguido, guardamos nuevamente el formulario?&amp;nbsp; Lo que va a pasar es que Delphi añadirá a nuestra clase TForm1 un campo llamado "Edit1" (que representará al componente) indicando que su tipo de dato es TEdit.&amp;nbsp; Como la clase TEdit pertenece a la unidad nativa StdCtrls, esta debe aparecer en el &lt;i&gt;Uses&lt;/i&gt; para que más tarde el compilador localice esa clase y no haya error alguno.&amp;nbsp; Por tal motivo el IDE nos ahorrará el trabajo de tener que escribir &lt;i&gt;StdCtrls&lt;/i&gt;, colocando él mismo ese nombre de unidad justo &lt;u&gt;al final&lt;/u&gt; de la cláusula &lt;i&gt;Uses&lt;/i&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-k9_CnQ6mjtY/TfcUZP03qNI/AAAAAAAAAIQ/gWDWCDZYAW4/s1600/Imagen2.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="428" src="http://2.bp.blogspot.com/-k9_CnQ6mjtY/TfcUZP03qNI/AAAAAAAAAIQ/gWDWCDZYAW4/s640/Imagen2.JPG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span lang="ES-MX"&gt;Este mecanismo automático y tan útil de Delphi resulta contraproducente cuando queremos mantener una unidad específica al final de la cláusula &lt;i&gt;Uses&lt;/i&gt;, independientemente de qué otras unidades estén o vayan a estar luego en la lista.&amp;nbsp; El IDE no emite aviso alguno cuando agrega unidades de esta manera.&amp;nbsp; Podemos no estar viendo el código al momento de guardar el formulario y su respectivo archivo .pas, o encontrarnos en alguna sección de este último muchas líneas abajo, de tal suerte que la cláusula &lt;i&gt;Uses&lt;/i&gt; de la sección &lt;i&gt;Interface&lt;/i&gt; será modificada por Delphi sin percatarnos de que nuestra unidad &lt;i&gt;Ultima&lt;/i&gt; ya no es la última.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Esto sugiere la necesidad de poder "anclar" el nombre de una unidad al final del &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; Y existen otras razones, como que los nombres de estas unidades especiales casi nunca son tan elocuentes (recuerde que "Ultima" es un nombre ficticio), así que, conforme transcurran las semanas y los meses de labor en un proyecto, puede que olvidemos el requerimiento de mantener tales unidades al final de las cláusulas &lt;i&gt;Uses&lt;/i&gt; para garantizar el correcto funcionamiento de la aplicación.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span lang="ES-MX" style="font-size: large;"&gt;La solución&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Hace unos tres años tuve la necesidad de crear una serie de clases interpuestas, de muy diversa índole, en un proyecto que tenía varias decenas de formularios, y casi todos ellos necesitaban una o varias de esas clases interpuestas. Ubiqué el código de estas clases en un par de unidades y me di a la tarea de colocar el nombre de ese par de unidades al final del &lt;i&gt;Uses&lt;/i&gt; de cada formulario.&amp;nbsp; Pero el camino empezó a hacerse nebuloso cortesía del complaciente IDE, debido al problema descrito en el apartado anterior.&amp;nbsp; Entonces, meditando sobre alguna posible solución, me surgió una idea: «&lt;i&gt;¿Se podrá engañar al IDE usando la directiva $Include?&lt;/i&gt;».&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Desde los tiempos de Turbo Pascal existe un directiva de compilación que permite insertar (virtualmente) el contenido de un archivo de texto en casi cualquier punto del código fuente, de tal manera que el compilador toma ese texto como si fuera parte integral del código.&amp;nbsp; Pues inmerso en la emoción, descubrí que aquella directiva &lt;i&gt;$I&lt;/i&gt;, que hoy puede usarse con un nombre más largo y apropiado, &lt;i&gt;$Include,&lt;/i&gt; puede ayudarnos a fijar uno o varios nombres de unidades al final del &lt;i&gt;Uses&lt;/i&gt; de la sección &lt;i&gt;Interface&lt;/i&gt;, sin que el IDE los mueva de su sitio cuando añada por sí mismo otros nombres de unidades.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;El truco es crear un archivo de texto, cuyo nombre puede ser &lt;b&gt;LastUnits.inc&lt;/b&gt;, y escribir en ese archivo el nombre de todas las unidades que deseemos anclar al extremo final de una cláusula &lt;i&gt;Uses&lt;/i&gt; (separados por coma si son más de uno).&amp;nbsp; Siguiendo con el ejemplo de este artículo, el contenido del archivo LastUnits.inc sería simple y sencillamente el nombre de la unidad Ultima:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span lang="ES-MX"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-UFS-qxbkBb8/TfcU3caIjOI/AAAAAAAAAIU/ji2HmqPZGh0/s1600/Imagen3.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-UFS-qxbkBb8/TfcU3caIjOI/AAAAAAAAAIU/ji2HmqPZGh0/s1600/Imagen3.JPG" /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span lang="ES-MX"&gt;Luego hay que colocar la directiva &lt;i&gt;{$Include LastUnits.inc}&lt;/i&gt; al final del &lt;i&gt;Uses&lt;/i&gt; de la sección &lt;i&gt;Interface&lt;/i&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-q77h6arUDe8/TfcVdnDJyZI/AAAAAAAAAIY/5Ml_4F6kOhA/s1600/Imagen4.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="412" src="http://2.bp.blogspot.com/-q77h6arUDe8/TfcVdnDJyZI/AAAAAAAAAIY/5Ml_4F6kOhA/s640/Imagen4.JPG" width="640" /&gt;&lt;/a&gt;&lt;span lang="ES-MX"&gt; Repitiendo la operación de hace un momento, pero con este nuevo esquema, observe lo que pasa en el código fuente cuando agregamos al formulario un componente TEdit y guardamos:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-H8n6nd6gsdE/TfcVsHUEVcI/AAAAAAAAAIc/qIMzpyn7Rj4/s1600/Imagen5.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="428" src="http://1.bp.blogspot.com/-H8n6nd6gsdE/TfcVsHUEVcI/AAAAAAAAAIc/qIMzpyn7Rj4/s640/Imagen5.JPG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span lang="ES-MX"&gt;Sorpresivo, ¿no? :)&amp;nbsp; A mí me causó esa misma grata impresión cuando lo vi por primera vez.&amp;nbsp; Si colocamos esta directiva &lt;i&gt;$Include&lt;/i&gt; al final del &lt;i&gt;Uses&lt;/i&gt;, el IDE la respeta y agrega la unidad StdCtrls delante y no detrás de la directiva.&amp;nbsp; Por lo tanto nuestra unidad Ultima, cuyo nombre es el contenido de LastUnits.inc, queda anclada al final de la cláusula &lt;i&gt;Uses&lt;/i&gt;.&amp;nbsp; No importa que Delphi añada más nombres de unidades conforme llenemos el formulario de componentes, la directiva conservará su privilegiado último lugar.&amp;nbsp; Además, como se trata de un elemento muy distintivo, difícilmente olvidaremos con qué propósito la tenemos ahí, y menos con un nombre de archivo sumamente explícito como &lt;i&gt;LastUnits&lt;/i&gt;.&amp;nbsp; Si por nuestra cuenta llegamos a escribir en esa cláusula &lt;i&gt;Uses&lt;/i&gt; otros nombres de unidades, lo haremos conscientemente a la izquierda de la directiva, no al final como es costumbre.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Por último decir que, como requisito de la directiva &lt;i&gt;$Include,&lt;/i&gt; el archivo debe localizarse ya sea en el mismo directorio del proyecto, o en las "rutas de búsqueda" (en Delphi 7 se accede a ellas con la opción "Project|Options|Directories/Conditionals|Search path").&amp;nbsp; Así no habrá problema alguno a la hora de compilar.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span lang="ES-MX"&gt;Siéntanse animados a compartir sus dudas, opiniones o sugerencias.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span lang="ES-MX"&gt;Al González. &lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-19628274965166692?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/19628274965166692/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/06/anclar-unidad-al-final-del-uses.html#comment-form' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/19628274965166692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/19628274965166692'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/06/anclar-unidad-al-final-del-uses.html' title='Anclar unidad al final del Uses'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-U3lmE5Ck38E/TfcTL9phtoI/AAAAAAAAAIM/J3E6FdfB0Ec/s72-c/Imagen1.JPG' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-2164984253553796601</id><published>2011-05-26T01:29:00.000-05:00</published><updated>2011-05-26T01:29:16.062-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='Ballmer'/><category scheme='http://www.blogger.com/atom/ns#' term='Skype'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Algo de humor contra la brusquedad</title><content type='html'>Ejecutivo de Microsoft —Jefe, la comunidad Delphi mundial sigue muy presente.&lt;br /&gt;&lt;br /&gt;Steve Ballmer —¡Esos señoritos afrancesados y su fastidioso Delphi! Ahora verán quiénes somos. ¿Cuál es el programa más famoso hecho con Delphi?&lt;br /&gt;&lt;br /&gt;E.M. —Pues hay varios productos muy buenos, señor, pero uno de los más conocidos es Skype.&lt;br /&gt;&lt;br /&gt;S.B. —¡Me lo juras! Sí que es bueno ese programa, hay que admitirlo.&lt;br /&gt;&lt;br /&gt;E.M. —Jefe, si me permite una observación, ya no usamos el término &lt;em&gt;programa&lt;/em&gt;, eso es de los ochentas. Ahora decimos &lt;em&gt;aplicación&lt;/em&gt;, &lt;em&gt;paquete&lt;/em&gt;, &lt;em&gt;software&lt;/em&gt; o &lt;em&gt;producto&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;S.B. —¡Caramba! Recuérdame despedirte el próximo mes. Pero mientras tanto quiero que compres la..."aplicación" Skype.&lt;br /&gt;&lt;br /&gt;E.M. —Perdón señor. ¿Quiere que instalemos Skype en su ordenador?&lt;br /&gt;&lt;br /&gt;S.B. —¡Imbécil! Quiero que compren el maldito Skype, la marca, el producto, ¡todo! ¡Que Skype sea ahora propiedad de Microsoft! ¡Ahhgggrrrrr!&lt;br /&gt;&lt;br /&gt;E.M. —¡Sí señor Ballmer! Como usted diga y ordene, en seguida prepararé...&lt;br /&gt;&lt;br /&gt;S.B. —¡Mueve ese maldito trasero, empleado de mierda! Quiero ver mi partido de &lt;em&gt;football&lt;/em&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-2164984253553796601?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/2164984253553796601/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/05/algo-de-humor-contra-la-brusquedad.html#comment-form' title='16 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2164984253553796601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2164984253553796601'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/05/algo-de-humor-contra-la-brusquedad.html' title='Algo de humor contra la brusquedad'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-9067973094608293172</id><published>2011-05-20T17:09:00.000-05:00</published><updated>2011-05-20T17:09:57.576-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sistema'/><category scheme='http://www.blogger.com/atom/ns#' term='conciencia global'/><category scheme='http://www.blogger.com/atom/ns#' term='España'/><title type='text'>No somos antisistema, el sistema es antinosotros.</title><content type='html'>&lt;div class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;Así reza uno de los carteles en la Puerta del Sol.&amp;nbsp; ¿Alguien todavía se siente indiferente o lejano a esta realidad?&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0cm 0cm 0pt;"&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;/span&gt;&lt;span lang="ES-MX" style="font-family: &amp;quot;Times New Roman&amp;quot;; font-size: 12pt; mso-ansi-language: ES-MX; mso-bidi-language: AR-SA; mso-fareast-font-family: &amp;quot;Times New Roman&amp;quot;; mso-fareast-language: ES;"&gt;&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://1.gvt0.com/vi/mFmD67iAtIU/0.jpg"&gt;&lt;param name="movie" value="http://www.youtube.com/v/mFmD67iAtIU&amp;fs=1&amp;source=uds" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266" src="http://www.youtube.com/v/mFmD67iAtIU&amp;fs=1&amp;source=uds" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none; margin: 0cm 0cm 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-9067973094608293172?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/9067973094608293172/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/05/no-somos-antisistema-el-sistema-es.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/9067973094608293172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/9067973094608293172'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/05/no-somos-antisistema-el-sistema-es.html' title='No somos antisistema, el sistema es antinosotros.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-2787563088363603070</id><published>2011-02-23T18:08:00.000-06:00</published><updated>2011-02-23T18:08:41.244-06:00</updated><title type='text'>Postre del día</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-sOJGW6rTigY/TWWg94YQnbI/AAAAAAAAAII/bzcsGgUOa9U/s1600/SDC12499b.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="237" j6="true" src="http://4.bp.blogspot.com/-sOJGW6rTigY/TWWg94YQnbI/AAAAAAAAAII/bzcsGgUOa9U/s320/SDC12499b.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;¿Gustan nueces y fresas? :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-2787563088363603070?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/2787563088363603070/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/02/postre-del-dia.html#comment-form' title='14 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2787563088363603070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2787563088363603070'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2011/02/postre-del-dia.html' title='Postre del día'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-sOJGW6rTigY/TWWg94YQnbI/AAAAAAAAAII/bzcsGgUOa9U/s72-c/SDC12499b.JPG' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-211961008864705013</id><published>2010-10-10T22:50:00.000-05:00</published><updated>2010-10-10T22:50:13.191-05:00</updated><title type='text'>Desde Quanax-huato</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_9N_Agt_qWL4/TLKIZNT7uVI/AAAAAAAAAH0/3cbi-jsWaoA/s1600/SDC11757b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="http://3.bp.blogspot.com/_9N_Agt_qWL4/TLKIZNT7uVI/AAAAAAAAAH0/3cbi-jsWaoA/s320/SDC11757b.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;o:OfficeDocumentSettings&gt;   &lt;o:AllowPNG/&gt;  &lt;/o:OfficeDocumentSettings&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:TrackMoves/&gt;   &lt;w:TrackFormatting/&gt;   &lt;w:HyphenationZone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:PunctuationKerning/&gt;   &lt;w:ValidateAgainstSchemas/&gt;   &lt;w:SaveIfXMLInvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:IgnoreMixedContent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:AlwaysShowPlaceholderText&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:DoNotPromoteQF/&gt;   &lt;w:LidThemeOther&gt;ES-MX&lt;/w:LidThemeOther&gt;   &lt;w:LidThemeAsian&gt;X-NONE&lt;/w:LidThemeAsian&gt;   &lt;w:LidThemeComplexScript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;   &lt;w:Compatibility&gt;    &lt;w:BreakWrappedTables/&gt;    &lt;w:SnapToGridInCell/&gt;    &lt;w:WrapTextWithPunct/&gt;    &lt;w:UseAsianBreakRules/&gt;    &lt;w:DontGrowAutofit/&gt;    &lt;w:SplitPgBreakAndParaMark/&gt;    &lt;w:EnableOpenTypeKerning/&gt;    &lt;w:DontFlipMirrorIndents/&gt;    &lt;w:OverrideTableStyleHps/&gt;   &lt;/w:Compatibility&gt;   &lt;m:mathPr&gt;    &lt;m:mathFont m:val="Cambria Math"/&gt;    &lt;m:brkBin m:val="before"/&gt;    &lt;m:brkBinSub m:val="&amp;#45;-"/&gt;    &lt;m:smallFrac m:val="off"/&gt;    &lt;m:dispDef/&gt;    &lt;m:lMargin m:val="0"/&gt;    &lt;m:rMargin m:val="0"/&gt;    &lt;m:defJc m:val="centerGroup"/&gt;    &lt;m:wrapIndent m:val="1440"/&gt;    &lt;m:intLim m:val="subSup"/&gt;    &lt;m:naryLim m:val="undOvr"/&gt;   &lt;/m:mathPr&gt;&lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"  DefSemiHidden="true" DefQFormat="false" DefPriority="99"  LatentStyleCount="267"&gt;   &lt;w:LsdException Locked="false" Priority="0" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt;   &lt;w:LsdException Locked="false" Priority="9" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 1"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 2"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 3"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 4"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 5"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 6"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 7"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 8"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 9"/&gt;   &lt;w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/&gt;   &lt;w:LsdException Locked="false" Priority="10" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Title"/&gt;   &lt;w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/&gt;   &lt;w:LsdException Locked="false" Priority="11" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/&gt;   &lt;w:LsdException Locked="false" Priority="22" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Strong"/&gt;   &lt;w:LsdException Locked="false" Priority="20" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="59" SemiHidden="false"   UnhideWhenUsed="false" Name="Table Grid"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/&gt;   &lt;w:LsdException Locked="false" Priority="1" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/&gt;   &lt;w:LsdException Locked="false" Priority="34" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/&gt;   &lt;w:LsdException Locked="false" Priority="29" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="30" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="19" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="21" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="31" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="32" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="33" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/&gt;   &lt;w:LsdException Locked="false" Priority="37" Name="Bibliography"/&gt;   &lt;w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt; /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Tabla normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;}&lt;/style&gt; &lt;![endif]--&gt;&lt;span style="font-family: &amp;quot;Calibri&amp;quot;,&amp;quot;sans-serif&amp;quot;; font-size: 11pt; line-height: 115%;"&gt;Un saludo desde la tierra del Pípila.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-211961008864705013?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/211961008864705013/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/10/desde-quanax-huato.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/211961008864705013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/211961008864705013'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/10/desde-quanax-huato.html' title='Desde Quanax-huato'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9N_Agt_qWL4/TLKIZNT7uVI/AAAAAAAAAH0/3cbi-jsWaoA/s72-c/SDC11757b.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-8084971686577128847</id><published>2010-03-22T16:50:00.003-06:00</published><updated>2010-03-23T00:07:07.643-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AfterFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='TDateTime'/><category scheme='http://www.blogger.com/atom/ns#' term='BeforeFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='formato nativo'/><category scheme='http://www.blogger.com/atom/ns#' term='molde de acceso'/><category scheme='http://www.blogger.com/atom/ns#' term='GetFieldData'/><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><category scheme='http://www.blogger.com/atom/ns#' term='TIntegerField'/><category scheme='http://www.blogger.com/atom/ns#' term='OnValidate'/><category scheme='http://www.blogger.com/atom/ns#' term='BLOBs'/><category scheme='http://www.blogger.com/atom/ns#' term='SetFieldData'/><category scheme='http://www.blogger.com/atom/ns#' term='TDateField'/><category scheme='http://www.blogger.com/atom/ns#' term='TStringField'/><category scheme='http://www.blogger.com/atom/ns#' term='conjuntos de datos'/><title type='text'>BeforeFieldChange y AfterFieldChange.  Parte 3.</title><content type='html'>Hace un par de semanas nos aproximamos a cómo implementar ese par de nuevos eventos en una clase derivada de TClientDataSet. Si el lector no tuvo oportunidad de visitar esta bitácora recientemente, quizá por estar al servicio de algún indómito capitalista, le recomiendo leer la &lt;a href="http://rescatandoadelphi.blogspot.com/2010/02/eventos-beforefieldchange-y.html"&gt;parte 1&lt;/a&gt; y la &lt;a href="http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange.html"&gt;parte 2&lt;/a&gt; de esta emocionante aventura.&lt;br /&gt;&lt;br /&gt;Este es el código que hemos escrito hasta ahora:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Interface&lt;br /&gt;&lt;br /&gt;Uses&lt;br /&gt;&amp;#160;&amp;#160;DB, DBClient;&lt;br /&gt;&lt;br /&gt;Type&lt;br /&gt;&amp;#160;&amp;#160;{ Tipos de datos procedimentales para los&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;eventos AfterFieldChange y BeforeFieldChange }&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;TFieldAfterChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; PrevValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;TFieldBeforeChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; NewValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;// Clase derivada de TClientDataSet&lt;br /&gt;&amp;#160;&amp;#160;TClientDataSetB = Class (TClientDataSet)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Private&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FAfterFieldChange :TFieldAfterChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FBeforeFieldChange :TFieldBeforeChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Protected&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Procedure SetFieldData (Field :TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer :Pointer); Override;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Published&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Eventos nuevos&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property AfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldAfterChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FAfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FAfterFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property BeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldBeforeChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FBeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FBeforeFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;&lt;br /&gt;Implementation&lt;br /&gt;&lt;br /&gt;Procedure TClientDataSetB.SetFieldData (&lt;br /&gt;&amp;#160;&amp;#160;Field :TField; Buffer :Pointer);&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;Value :Variant;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;Value := { Valor en Buffer };&amp;#160;&amp;#160;// NewValue&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If Value = Field.Value Then&amp;#160;&amp;#160;// No cambia&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer)&lt;br /&gt;&amp;#160;&amp;#160;Else&amp;#160;&amp;#160;// Sí cambia&lt;br /&gt;&amp;#160;&amp;#160;Begin&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (BeforeFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;BeforeFieldChange (Field, Value);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Value := Field.Value;&amp;#160;&amp;#160;// PrevValue&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (AfterFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;AfterFieldChange (Field, Value);&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;La más &lt;em&gt;difícil&lt;/em&gt; tarea del método SetFieldData redefinido es obtener como Variant el valor apuntado por el parámetro Buffer. Como señalé en la entrada anterior, el formato de lo contenido en ese buffer depende de cada tipo de campo y los conjuntos de datos nativos no cuentan con un método específico para extraer dicho contenido en forma de Variant.&lt;br /&gt;&lt;br /&gt;El parámetro puntero Buffer puede traer un valor de Nil, lo cual significa que el campo será limpiado (puesto en blanco). Cuando no es Nil, apunta a un grupo de bytes cuyo formato binario y tamaño corresponden al tipo de campo en cuestión. Si el campo (parámetro Field) es de clase TIntegerField, Buffer apuntará a un bloque de cuatro bytes, un entero en la típica representación de 32 bits, siendo por tanto Buffer equivalente a un valor de tipo PInteger. Si el campo es de clase TStringField, Buffer apuntará al inicio de una cadena de caracteres de longitud variable, siendo Buffer equivalente a un valor de tipo PChar.&lt;br /&gt;&lt;br /&gt;El problema es que hay al menos una veintena de posibles estructuras apuntadas por Buffer, debido a la gran variedad de tipos de campos que existen en Delphi. Por otra parte, con algunos tipos de campos el &lt;em&gt;formato nativo&lt;/em&gt; es menos transparente que el de los ejemplos anteriores. Por ejemplo, para los campos de clase TDateField, el buffer es un entero de 32 bits que indica una cantidad de días transcurridos desde el inicio de la Era Cristiana, incompatible con el estándar número flotante TDateTime (cuya cuenta inicia el 30 de diciembre de 1899). Allende de esto, el formato nativo de los campos puede variar de algunos conjuntos de datos a otros, lo cual dificultaría adaptar los eventos BeforeFieldChange y AfterFieldChange a clases derivadas de diferentes ramas.&lt;br /&gt;&lt;br /&gt;Si bien Delphi no dispone de una función a la que podamos darle como argumento uno de esos buffers nativos y, acaso indicándole el tipo de campo, nos regrese en forma de Variant el valor que contiene, ¿poseen los conjuntos de datos algún mecanismo que realice esa conversión de otra manera? La respuesta es definitiva: Así como al escribir el valor de un campo, éste llega a SetFieldData contenido en un buffer de formato nativo que seguidamente es copiado en el interior del registro, cuando leemos el valor de un campo, el método virtual &lt;em&gt;GetFieldData&lt;/em&gt; del conjunto de datos realiza la operación inversa. GetFieldData copia los bytes de la misma sección del registro en un buffer que el objeto campo en cuestión le proporciona; entonces el objeto campo toma el valor de ese buffer según el formato que corresponde a su clase.&lt;br /&gt;&lt;br /&gt;Consideremos la siguiente sentencia con un objeto campo de clase TDateField:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Fecha := DS.FieldByName ('Fecha').Value;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;En tiempo de ejecución, al evaluarse la expresión que está del lado derecho de la asignación, el objeto TField devuelto por FieldByName llamará al método GetFieldData del conjunto de datos para obtener una copia del grupo de bytes que guardan el valor nativo del campo en el registro actual, y la convertirá a un valor de tipo TDateTime. La referencia a la propiedad Value causará que ese dato sea a su vez convertido en un Variant, siendo éste el resultado de la expresión, ya que la propiedad Value de TField es de tipo Variant y su referencia en el ejemplo es polimórfica (FieldByName regresa un TField, &lt;em&gt;no&lt;/em&gt; un TDateField).&lt;br /&gt;&lt;br /&gt;En efecto. Estoy sugiriendo que, para convertir el parámetro Buffer en un valor de tipo Variant, aprovechemos el habitual mecanismo de lectura que poseen los campos. Puede que lo anterior haga perder el sosiego: «&lt;em&gt;¡Espera Al! Recuerda que esa conversión debe ser hecha en el interior del nuevo SetFieldData antes de aplicar la asignación, no después. Si leemos la propiedad Value del campo, ésta nos regresará el valor que tiene actualmente en el registro, no lo que viene dentro del parámetro Buffer. Pero bueno, te conozco y seguramente nos sorprenderás&lt;/em&gt;». xD&lt;br /&gt;&lt;br /&gt;Versión maquiavélica: «&lt;em&gt;Seguramente hará una especie de asignación silenciosa en el registro para en seguida leer con la propiedad Value del campo, e inmediatamente restaurará el valor con otra asignación silenciosa, para entonces llamar al evento BeforeFieldChange, y, si no pasa nada, ejecutar la asignación normal. Que poco elegante, ¡demasiadas asignaciones! Borraré a Al de mi lista de contactos&lt;/em&gt;».&lt;br /&gt;&lt;br /&gt;Pero antes de que me pongan como &lt;em&gt;no admitido&lt;/em&gt;, convendría hacernos una segunda pregunta: ¿puede decírsele a un campo que lea su valor de otro lugar que no sea la memoria del registro actual? La respuesta la tiene el casi místico evento OnValidate de TField. Quienes hayan usado este evento con regularidad, tendrán claro que durante su ejecución puede leerse el nuevo valor del campo como si ya hubiera sido plenamente asignado, pero si ahí mismo es elevada alguna excepción, el campo &lt;em&gt;recupera&lt;/em&gt; el valor que tenía previamente. ¿Cómo sucede esto? Es sencillo: sin realizar todavía la asignación, el conjunto de datos le dice al campo que mire temporalmente en otro lugar, siendo ese &lt;em&gt;otro lugar&lt;/em&gt; el mismísimo buffer dado a SetFieldData. Si el lector siente curiosidad por conocer los detalles de esa dinámica, puede apoyarse en &lt;a href="http://www.clubdelphi.com/foros/showpost.php?p=356787&amp;amp;postcount=6"&gt;esta breve explicación&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Aquí haremos algo similar, agregando a nuestra clase TClientDataSetB tres elementos nuevos:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Un método función llamado &lt;em&gt;NativeValue&lt;/em&gt;, que servirá para convertir un buffer de formato nativo a Variant.&lt;/li&gt;&lt;li&gt;Un campo de tipo PPointer llamado &lt;em&gt;TempFieldData&lt;/em&gt;, para guardar de forma temporal una referencia al buffer que deseamos convertir.&lt;/li&gt;&lt;li&gt;La redefinición del método virtual GetFieldData para desviar la lectura del campo a TempFieldData, en lugar de leer del registro actual.&lt;/li&gt;&lt;/ul&gt;La declaración de los dos primeros estará en la sección protegida de la clase:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Protected&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TempFieldData :PPointer;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Function NativeValue (Const Field :TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Const Buffer :Pointer) :Variant;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Y la declaración del tercero en la sección pública (su visibilidad en la clase padre es pública también):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Public&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Function GetFieldData (Field :TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer :Pointer) :Boolean; Override;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;La implementación del método NativeValue es realmente sencilla:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Function TClientDataSetB.NativeValue (&lt;br /&gt;&amp;#160;&amp;#160;Const Field :TField; Const Buffer :Pointer)&lt;br /&gt;&amp;#160;&amp;#160;:Variant;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;TempFieldData := @Buffer;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;Try&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Field.Value;&lt;br /&gt;&amp;#160;&amp;#160;Finally&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TempFieldData := Nil;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Ahora, cuando necesitemos extraer el valor contenido en un buffer nativo, bastará que hagamos una llamada al método auxiliar NativeValue, dándole como parámetros el campo en cuestión y dicho buffer. Como puede verse en el código, NativeValue asigna de forma temporal la dirección del puntero Buffer al campo TempFieldData, esto con el fin de extraer su contenido mediante la propiedad Value del objeto campo Field. La clave para que eso sea posible se encuentra en la nueva implementación del método GetFieldData:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;#160;&amp;#160;Type&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TFieldAccess = Class (TField);&lt;br /&gt;Function TClientDataSetB.GetFieldData (&lt;br /&gt;&amp;#160;&amp;#160;Field :TField; Buffer :Pointer) :Boolean;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;If TempFieldData = Nil Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Inherited GetFieldData (Field,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer)&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;Begin&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := TempFieldData^ &amp;lt;&amp;gt; Nil;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Result And (Buffer &amp;lt;&amp;gt; Nil) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TFieldAccess (Field).CopyData (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TempFieldData^, Buffer);&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Cuando TempFieldData tenga un valor de Nil, se realizará una lectura del valor almacenado en el registro, de la forma en que dicha lectura está implementada por la clase padre. Pero si TempFieldData es distinto de Nil, significa que apunta a un buffer nativo del cual hay que sacar el valor, y no del registro.&lt;br /&gt;&lt;br /&gt;GetFieldData debe devolver False cuando el campo leído es Null. Esto es importante para el correcto funcionamiento de varios métodos de TField y sus clases derivadas. La sentencia “&lt;em&gt;Result := TempFieldData^ &lt;&gt; Nil&lt;/em&gt;” es congruente con ese requisito, considerando que el puntero Buffer proporcionado al método NativeValue podría ser Nil, en cuyo caso, viniendo del método SetFieldData, significa que el campo está por ser limpiado. Regresando False, hará que el campo —la expresión &lt;em&gt;Field.Value&lt;/em&gt; dentro de NativeValue— devuelva un valor de Null, puesto que ese es el Variant que un buffer nativo Nil representa.&lt;br /&gt;&lt;br /&gt;En cambio, si el buffer apuntado por TempFieldData es diferente de Nil, GetFieldData devolverá un valor de True (indicación de que sí hay un valor para el campo). En este caso GetFieldData copiará el contenido del buffer dado a NativeValue a su propio parámetro Buffer, el cual es suministrado internamente por el objeto campo en cuestión siempre que se produce una lectura de su valor, en esta ocasión la lectura hecha por NativeValue. Para ello nos valemos de un método virtual llamado CopyData, el cual, dependiendo de la clase del campo, sabe cuántos bytes copiar de un buffer a otro y de qué manera. A fin de lograr que el compilador admita referirnos a ese método protegido de TField, empleamos el clásico truco del &lt;em&gt;molde de acceso&lt;/em&gt; (clase auxiliar TFieldAccess). Y la condición “&lt;em&gt;Buffer &lt;&gt; Nil&lt;/em&gt;” es por si se llegara a hacer un uso alternativo del campo TempFieldData, junto con métodos que no proporcionen un buffer para la extracción del valor, como es el caso de TField.IsNull.&lt;br /&gt;&lt;br /&gt;Con todo esto, la propiedad Value del objeto campo en cuestión hará que NativeValue devuelva el contenido del buffer que recibe como parámetro, pero en forma de Variant. Siendo su resultado un valor de Null si tal buffer es Nil. Así pues, queda todo listo para utilizar el método NativeValue en el interior de SetFieldData:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Procedure TClientDataSetB.SetFieldData (&lt;br /&gt;&amp;#160;&amp;#160;Field :TField; Buffer :Pointer);&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;Value :Variant;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;If State In [dsEdit, dsInsert] Then&lt;br /&gt;&amp;#160;&amp;#160;Begin&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// NewValue&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Value := NativeValue (Field, Buffer);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Value &amp;lt;&amp;gt; Field.Value Then&amp;#160;&amp;#160;// Sí cambia&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Begin&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (BeforeFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;BeforeFieldChange (Field, Value);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Value := Field.Value;&amp;#160;&amp;#160;// PrevValue&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (AfterFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;AfterFieldChange (Field, Value);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Exit;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;End;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer);&lt;br /&gt;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Respecto a la aproximación que hicimos anteriormente, he agregado una condición para asegurar que el disparo de los eventos BeforeFieldChange y AfterFieldChange ocurra solamente si el estado del conjunto de datos es dsEdit o dsInsert (durante otros estados suele haber asignaciones especiales). Si el conjunto de datos está en modo de edición (primer If) y la asignación que está por realizarse representa un cambio real de valor (segundo If), se dispararán los eventos al realizar tal operación si éstos tienen manejador asignado. Si se quiere, desde el manejador de eventos asignado a BeforeFieldChange puede ser elevada una excepción y con ello se evitará que el valor del campo sea modificado. En caso de incumplirse alguna de las dos condiciones, el programa saltará a la última sentencia de la rutina, efectuándose una asignación nativa normal, sin el disparo de los nuevos eventos.&lt;br /&gt;&lt;br /&gt;El código es funcional, siéntanse con la libertad de registrar esta nueva clase en el IDE y probarla en alguna aplicación. Asimismo, con el código y la explicación dados, confío en que no les resultará difícil añadir estos dos nuevos eventos en los conjuntos de datos de su preferencia. En mi opinión se trata de una implementación básica que puede ser mejorada en varios aspectos, pero suficiente para disfrutar ya de los beneficios planteados al inicio de este artículo.&lt;br /&gt;&lt;br /&gt;Es importante señalar que los campos BLOB quedan imposibilitados para el uso de estos eventos, debido a que emplean mecanismos especiales de lectura y escritura que no hacen llamadas a los métodos virtuales GetFieldData y SetFieldData.&lt;br /&gt;&lt;br /&gt;Un abrazo antes y otro después.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-8084971686577128847?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/8084971686577128847/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange_22.html#comment-form' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8084971686577128847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8084971686577128847'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange_22.html' title='BeforeFieldChange y AfterFieldChange.  Parte 3.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-2421453431953652758</id><published>2010-03-01T17:35:00.005-06:00</published><updated>2010-03-23T00:42:40.965-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AfterFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='asignación de campos'/><category scheme='http://www.blogger.com/atom/ns#' term='TField'/><category scheme='http://www.blogger.com/atom/ns#' term='NativeFormat'/><category scheme='http://www.blogger.com/atom/ns#' term='Variant'/><category scheme='http://www.blogger.com/atom/ns#' term='BeforeFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='formato nativo'/><category scheme='http://www.blogger.com/atom/ns#' term='TCustomClientDataSet'/><category scheme='http://www.blogger.com/atom/ns#' term='método Clear'/><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><category scheme='http://www.blogger.com/atom/ns#' term='buffers'/><category scheme='http://www.blogger.com/atom/ns#' term='SetData'/><category scheme='http://www.blogger.com/atom/ns#' term='SetFieldData'/><category scheme='http://www.blogger.com/atom/ns#' term='TDataSet'/><title type='text'>BeforeFieldChange y AfterFieldChange. Parte 2.</title><content type='html'>En el &lt;a href="http://rescatandoadelphi.blogspot.com/2010/02/eventos-beforefieldchange-y.html"&gt;episodio anterior&lt;/a&gt;, planteamos la utilidad que tendrían en Delphi un par de eventos relacionados con el cambio genuino de valor en los campos de un conjunto de datos. Un evento que se dispare antes de que ese auténtico cambio ocurra, diciéndonos cuál es el nuevo valor que el campo está por aceptar; y un evento disparado tras ocurrir el cambio, informándonos sobre el valor que fue reemplazado.&lt;br /&gt;&lt;br /&gt;Por ahora Delphi y otros lenguajes orientados a objetos no admiten redefinición de clases. Así que en lugar de implementar estos nuevos eventos de forma centralizada para que toda la familia de los TDataSet cuente con ellos sin escribir código redundante o invasivo, los crearemos como parte de una sola clase derivada de TClientDataSet (la más acreditada de las nativas). Considero que el lector, si lo prefiere, podrá adaptar esta misma implementación a otros descendientes de TDataSet sin grandes dificultades.&lt;br /&gt;&lt;br /&gt;Empecemos pues.&lt;br /&gt;&lt;br /&gt;Algo que me &lt;em&gt;entona&lt;/em&gt; de la programación es que se parece a escribir en prosa. Una vez que se tiene la idea básica de lo que se pretende expresar, puede uno depositar esa semilla en el escrito para que entonces el conocimiento solar y la hídrica imaginación la hagan germinar y crecer.&lt;br /&gt;&lt;br /&gt;En la sección Interface de una nueva unidad, coloquemos el siguiente código:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Uses&lt;br /&gt;&amp;#160;&amp;#160;DB, DBClient;&lt;br /&gt;&lt;br /&gt;Type&lt;br /&gt;&amp;#160;&amp;#160;{ Tipos de datos procedimentales para los&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;eventos AfterFieldChange y BeforeFieldChange }&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;TFieldAfterChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; PrevValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;TFieldBeforeChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; NewValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;// Clase derivada de TClientDataSet&lt;br /&gt;&amp;#160;&amp;#160;TClientDataSetB = Class (TClientDataSet)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Private&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FAfterFieldChange :TFieldAfterChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FBeforeFieldChange :TFieldBeforeChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Published&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Eventos nuevos&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property AfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldAfterChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FAfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FAfterFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property BeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldBeforeChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FBeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FBeforeFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Estoy utilizando no más de 50 columnas de caracteres debido a la estrechez del diseño de fábrica que tiene esta bitácora.&lt;br /&gt;&lt;br /&gt;Primero aparece la cláusula Uses anunciando a las unidades donde se encuentran las clases referidas TField y TClientDataSet. Luego se declaran dos tipos de datos procedimentales para las propiedades eventos AfterFieldChange y BeforeFieldChange. Y finalmente la nueva clase descendiente, que de manera simplista hemos llamado &lt;em&gt;TClientDataSetB&lt;/em&gt;, declarando en ella los dos nuevos eventos y los campos privados en los cuales se almacenarán éstos. Para ambos eventos el parámetro &lt;em&gt;Field&lt;/em&gt; señalará el objeto que representa al campo que cambia de valor. El parámetro &lt;em&gt;NewValue&lt;/em&gt; del evento BeforeFieldChange (&lt;em&gt;antes de que el campo cambie&lt;/em&gt;) indicará el valor que está por sustituir al actual, mientras que el parámetro &lt;em&gt;PrevValue&lt;/em&gt; del evento AfterFieldChange (&lt;em&gt;después de que el campo cambió&lt;/em&gt;) indicará el valor que fue sustituido.&lt;br /&gt;&lt;br /&gt;Si registramos esa clase como parte de un paquete e instalamos éste en el IDE, tendremos un nuevo tipo de componente con eventos AfterFieldChange y BeforeFieldChange perfectamente visibles y asignables con el inspector de objetos. Pero, claro está, dichos eventos no tendrían funcionamiento alguno todavía, debido a que nuestra nueva clase ya tiene el &lt;em&gt;qué&lt;/em&gt;, pero todavía hay que escribir en ella el &lt;em&gt;dónde&lt;/em&gt; y el &lt;em&gt;cómo&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Los eventos actúan como avisos de que algo está pasando, está por pasar o acaba de pasar. En esencia, queremos que cada vez que se asigne valor a un campo en el registro activo de un objeto TClientDataSetB, y dicho valor sea distinto del actual, se ejecute un aviso previo a la operación que nos informe que está por cambiar el valor de ese campo, y también un aviso posterior que nos diga que ese campo ha cambiado. Como es de esperarse, dichos avisos serán llamadas a los manejadores de eventos (&lt;em&gt;event handlers&lt;/em&gt;) que estén asignados a las propiedades BeforeFieldChange y AfterFieldChange, respectivamente. Es responsabilidad del creador de nuevas propiedades eventos escribir el código necesario para que éstos sean &lt;em&gt;disparados&lt;/em&gt; en el momento apropiado, así que debemos buscar la forma de que eso ocurra en nuestra nueva clase.&lt;br /&gt;&lt;br /&gt;Hablando de conjuntos de datos, un campo cambia de valor en el registro actual solamente por una operación de asignación, la cual puede ser evidente en sentencias como estas:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;DS.FieldByName ('Fecha').Value := Now;&lt;br /&gt;DS.FieldByName ('Fecha').AsString := ed1.Text;&lt;br /&gt;DS ['Fecha'] := qrAlumnosFechaIngreso.Value;&lt;br /&gt;DSFecha.Value := dmServidor.CurrentDate;&lt;br /&gt;DS.Fields [I].Assign (DSOrigen.Fields [I]);&lt;br /&gt;DS.FieldByName ('Fecha').Clear;&amp;#160;&amp;#160;// Asignamos Null&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;O también puede ocurrir mediante captura de datos en un control &lt;em&gt;data-aware&lt;/em&gt; (como un cuadro de texto TDBEdit o una rejilla TDBGrid).&lt;br /&gt;&lt;br /&gt;Haciendo pruebas con el depurador y observando el código fuente de la unidad DB, podemos percatarnos de que, sea cual sea la vía de asignación de valor a un campo, siempre se ejecuta el método SetData del objeto TField en cuestión. Incluso el método TField.Clear, que nos permite dejar en blanco a un campo, llama a SetData. TField.SetData, a su vez, siempre llama al método SetFieldData del conjunto de datos al cual pertenece el campo.&lt;br /&gt;&lt;br /&gt;De la unidad DB.pas de Delphi 7 y otras versiones:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;procedure TField.SetData(Buffer: Pointer;&lt;br /&gt;&amp;#160;&amp;#160;NativeFormat: Boolean = True);&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;if FDataSet = nil then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;DatabaseErrorFmt(SDataSetMissing,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;[DisplayName]);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;FValueBuffer := Buffer;&lt;br /&gt;&amp;#160;&amp;#160;try&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FDataSet.SetFieldData(Self, Buffer,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;NativeFormat);&lt;br /&gt;&amp;#160;&amp;#160;finally&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FValueBuffer := nil;&lt;br /&gt;&amp;#160;&amp;#160;end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TField.Clear;&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;if FieldKind in [fkData, fkInternalCalc] then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;SetData(nil);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TBooleanField.SetAsBoolean(&lt;br /&gt;&amp;#160;&amp;#160;Value: Boolean);&lt;br /&gt;var&lt;br /&gt;&amp;#160;&amp;#160;B: WordBool;&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;if Value then Word(B) := 1 else Word(B) := 0;&lt;br /&gt;&amp;#160;&amp;#160;SetData(@B);&lt;br /&gt;end;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Al final del artículo haré una mención especial sobre la familia de los campos BLOB, ya que éstos son la excepción a esa regla y desde ya descartamos el uso de los nuevos eventos con ese tipo de campos.&lt;br /&gt;&lt;br /&gt;El método TDataSet.SetFieldData viene en dos versiones (es sobrecargado) y ambas son virtuales. Una de ellas tiene tres parámetros y es a la que llama TField.SetData, como bien puede verse en el código fuente que transcribí arriba. La otra tiene solamente dos parámetros y es la única redefinida por TCustomClientDataSet (la clase precursora de TClientDataSet y descendiente inmediata de TDataSet):&lt;br /&gt;&lt;br /&gt;De la unidad DBClient.pas de Delphi 7 y otras versiones:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;TCustomClientDataSet = class(TDataSet)&lt;br /&gt;...&lt;br /&gt;protected&lt;br /&gt;&amp;#160;&amp;#160;...&lt;br /&gt;&amp;#160;&amp;#160;procedure SetFieldData(Field: TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer: Pointer); override;&lt;br /&gt;&amp;#160;&amp;#160;...&lt;br /&gt;&lt;br /&gt;TClientDataSet = class(TCustomClientDataSet)&lt;br /&gt;published&lt;br /&gt;...&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;En la unidad DB, la versión de tres parámetros de TDataSet.SetFieldData siempre llama a la versión de dos parámetros, es decir, a la que TClientDataSet tiene redefinida. Por lo tanto, siempre que se asigne valor a un campo de un conjunto de datos cliente se ejecutará el método virtual redefinido TCustomClientDataSet.SetFieldData.&lt;br /&gt;&lt;br /&gt;TField.SetData -&gt; TDataSet.SetFieldData(3p) -&gt; TCustomClientDataSet.SetFieldData(2p)&lt;br /&gt;&lt;br /&gt;Observando el código fuente de este último, podemos apreciar que es ahí, precisamente, donde el conjunto de datos otorga el nuevo valor al campo mediante ciertas operaciones de buffers. Y como un método virtual nunca deja de serlo, ¿qué les parecería redefinirlo una vez más en nuestra clase TClientDataSetB para disparar desde su interior a los dos nuevos eventos? ;)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;#160;&amp;#160;TClientDataSetB = Class (TClientDataSet)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Private&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FAfterFieldChange :TFieldAfterChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FBeforeFieldChange :TFieldBeforeChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Protected&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Procedure SetFieldData (Field :TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer :Pointer); Override;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Published&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property AfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldAfterChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FAfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FAfterFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property BeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldBeforeChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FBeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FBeforeFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Esta redefinición del método SetFieldData tiene toda la pinta de ser el &lt;em&gt;dónde&lt;/em&gt;, faltando solamente el &lt;em&gt;cómo&lt;/em&gt;, es decir, su implementación. La siguiente es una aproximación:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Procedure TClientDataSetB.SetFieldData (&lt;br /&gt;&amp;#160;&amp;#160;Field :TField; Buffer :Pointer);&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;Value :Variant;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;Value := { Valor en Buffer };&amp;#160;&amp;#160;// NewValue&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If Value = Field.Value Then&amp;#160;&amp;#160;// No cambia&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer)&lt;br /&gt;&amp;#160;&amp;#160;Else&amp;#160;&amp;#160;// Sí cambia&lt;br /&gt;&amp;#160;&amp;#160;Begin&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (BeforeFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;BeforeFieldChange (Field, Value);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Value := Field.Value;&amp;#160;&amp;#160;// PrevValue&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Inherited SetFieldData (Field, Buffer);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If Assigned (AfterFieldChange) Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;AfterFieldChange (Field, Value);&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;br /&gt;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;En ella hay varias cuestiones qué atender, empezando por cómo extraer en forma de Variant el nuevo valor que viene dentro del parámetro Buffer, pues como Variant lo necesitamos para compararlo contra el valor actual del campo, y también para usarlo como parámetro NewValue del evento BeforeFieldChange. Ese parámetro Pointer señala un buffer que contiene el valor a asignar pero en &lt;em&gt;formato nativo&lt;/em&gt;, es decir, la representación binaria del valor cuyos bytes terminan siendo copiados en el registro. Proviene tal cual de alguno de los métodos de asignación del campo, o bien de una conversión especial hecha por el método TDataSet.SetFieldData. Para casi todos los tipos de campos su estructura interna es por demás distinta de la estructura interna de un Variant, y depende completamente del tipo de campo en cuestión (TIntegerField, TStringField, TBooleanField,...).&lt;br /&gt;&lt;br /&gt;Aunque el lector no lo crea, Delphi carece de una función o método especializado en convertir estos buffers nativos en valores de tipo Variant. Considerando que existe una amplia variedad de tipos de campos, podríamos entonces decir que estamos ante un buffer incómodo que nos hará escribir un enorme y divertido Case.&lt;br /&gt;&lt;br /&gt;Pues no es así.  Porque encontré &lt;a href="http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange_22.html"&gt;una forma elegante&lt;/a&gt; de convertir ese buffer a Variant...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-2421453431953652758?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/2421453431953652758/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2421453431953652758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2421453431953652758'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange.html' title='BeforeFieldChange y AfterFieldChange. Parte 2.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-1486875699545838726</id><published>2010-02-20T19:47:00.009-06:00</published><updated>2010-03-01T18:20:42.068-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AfterFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='Object Pascal'/><category scheme='http://www.blogger.com/atom/ns#' term='redefinición de clases'/><category scheme='http://www.blogger.com/atom/ns#' term='POO'/><category scheme='http://www.blogger.com/atom/ns#' term='herencia insertada'/><category scheme='http://www.blogger.com/atom/ns#' term='BeforeFieldChange'/><category scheme='http://www.blogger.com/atom/ns#' term='Override'/><category scheme='http://www.blogger.com/atom/ns#' term='OnChange'/><category scheme='http://www.blogger.com/atom/ns#' term='Top'/><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><category scheme='http://www.blogger.com/atom/ns#' term='debate'/><category scheme='http://www.blogger.com/atom/ns#' term='OnDataChange'/><category scheme='http://www.blogger.com/atom/ns#' term='clases virtuales'/><category scheme='http://www.blogger.com/atom/ns#' term='OnValidate'/><category scheme='http://www.blogger.com/atom/ns#' term='TDataSource'/><title type='text'>BeforeFieldChange y AfterFieldChange.  Parte 1.</title><content type='html'>En ocasiones, cuando utilizamos conjuntos de datos en Delphi, escribimos código para ejecutarse en respuesta al cambio de valor de un campo, generalmente cuando tal cambio ocurre como parte de una captura de datos.  Delphi permite hacer esto con el evento OnChange de la clase TField y con el evento OnDataChange de la clase TDataSource.&lt;br /&gt;&lt;br /&gt;Pero estos presentan dos grandes desventajas.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Desventaja #1: Mienten.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Se disparan siempre que hay asignación de valor al campo, no solamente cuando éste cambia de valor.  Para entender la diferencia, considere que tenemos un campo de tipo entero con un valor de 5 en el registro actual y ahora le asignamos el resultado de la suma 3 + 2, o bien el usuario captura nuevamente &lt;em&gt;5&lt;/em&gt; en un cuadro de texto que está asociado a ese campo.  En cualquiera de estos casos, ¿cambió el campo de valor?  La respuesta es no, sin embargo se ejecuta el código de esos mentirijillos eventos “change”.  Esto resulta, bajo la mayoría de los casos, en un procesamiento innecesario que puede consumir pocos o muchos recursos (procesador, memoria, tiempo), dependiendo de lo que haga el manejador de evento que hayamos programado.&lt;br&gt;&lt;br /&gt;&lt;strong&gt;Desventaja #2: Ocultan el pasado.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Una vez que el campo cambia, ¿cómo podemos saber qué valor tenía previamente?  Puede ser que, tras ser modificado el valor del campo, necesitemos realizar algo en especial con el valor que tenía anteriormente.&lt;br /&gt;&lt;br /&gt;Ni siquiera el evento OnValidate de TField se salva de esas dos desventajas.  Alguna vez me vi utilizando una variable auxiliar para guardar el último valor asignado de un campo, con el fin de verificar si éste realmente había cambiado de valor o de ejecutar una tarea que requería el valor previo como parámetro.&lt;br /&gt;&lt;br /&gt;Abriendo un pequeño paréntesis, estoy seguro que en algún momento Delphi contará con un manejo nativo, rico y muy eficiente de entidades de datos, a través de clases &lt;em&gt;Row&lt;/em&gt; o &lt;em&gt;Record&lt;/em&gt; cuyas instancias representen las filas de un cursor, como ha sucedido ya en otras tecnologías de programación y como de alguna manera se intentó con ECO, y donde cuestiones como las planteadas aquí y otras menos ordinarias (como saber si el valor de un campo está siendo asignado o no) estén felizmente resueltas.  Cuando el fabricante se vaya a poner a trabajar en ello, me gustaría muchísimo tener algún tipo de participación, pues bajo el desarrollo de mi marco personal he venido asentando una serie de mecanismos y conceptos que siento deben ser considerados.&lt;br /&gt;&lt;br /&gt;Por el momento y regresando al tema, podría ser buena idea que la clase TDataSet tuviera un par de eventos adicionales llamados &lt;em&gt;BeforeFieldChange&lt;/em&gt; y &lt;em&gt;AfterFieldChange&lt;/em&gt;, ambos disparados cuando un campo realmente cambie de valor.  El primero justo antes de que ocurra el cambio, e informando mediante un parámetro Variant cuál es el valor que está por ser asignado.  El segundo justo después de ocurrir el cambio, e informando mediante un parámetro Variant cuál es el valor que tenía previamente.&lt;br /&gt;&lt;br /&gt;De esta forma todas las clases descendientes de TDataSet heredarían esos nuevos eventos, permitiéndonos usarlos con cualquiera de los componentes de acceso a datos nativos o de terceros.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;procedure TDataModule1.DataSet1BeforeFieldChange(&lt;br /&gt;&amp;#160;&amp;#160;Field: TField; NewValue: Variant);&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;{ Verificamos qué campo está por cambiar (Field)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;y cuál será su nuevo valor (NewValue),&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;elevando una excepción si queremos impedir el&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;cambio o realizando alguna tarea específica }&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TDataModule1.DataSet1AfterFieldChange(&lt;br /&gt;&amp;#160;&amp;#160;Field: TField; PrevValue: Variant);&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;{ Verificamos qué campo acaba de cambiar (Field)&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;y cuál era su valor anterior (PrevValue),&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;realizando alguna tarea específica }&lt;br /&gt;end;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;En Delphi, como en muchos otros lenguajes, podemos redefinir métodos que previamente han sido declarados como virtuales.  Esto nos permite extender las capacidades de una clase, creando una derivada con dichos métodos reimplementados por nosotros mismos.  Eso es algo de lo más común.  No obstante, pocos son los que se han atrevido a tocar el tema de la &lt;em&gt;redefinición de clases&lt;/em&gt;, &lt;em&gt;clases virtuales&lt;/em&gt; o &lt;em&gt;herencia insertada&lt;/em&gt;, como si se tratara de un tabú en la POO.  Con esos términos no acuñados me refiero a la capacidad de ampliar una clase sin tocar su código fuente, consiguiendo que sus actuales descendientes adquieran en automático la nueva herencia al ser compilada la aplicación que los utilice.  O, dicho de una manera burda, insertar herencia adicional en medio de una jerarquía de clases.&lt;br /&gt;&lt;br /&gt;Si las clases Delphi fueran redefinibles en ese sentido, podríamos agregar los eventos BeforeFieldChange y AfterFieldChange a la nativa TDataSet, sin esperar a que Embarcadero lo haga y sobre todo respetando el código fuente de la VCL.  Logrando así que todas las clases de conjuntos de datos nativas y de terceros (TClientDataSet, TADODataSet, TIBTable,  TMemoryTable, TMDOQuery, etc.) que utilicemos en nuestros proyectos cuenten con dichos eventos, sin necesidad de crear una clase derivada para cada una escribiendo código repetido.  Lo más cercano que Borland estuvo de ello fue la inclusión de los ayudantes de clases, pero éstos dejan mucho qué desear.&lt;br /&gt;&lt;br /&gt;Imaginemos que ya estamos en el mundo justo y feliz que a Object Pascal le corresponde tener, y que podemos escribir algo como esto:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Uses&lt;br /&gt;&amp;#160;&amp;#160;DB;&lt;br /&gt;&lt;br /&gt;Type&lt;br /&gt;&amp;#160;&amp;#160;TFieldAfterChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; PrevValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;TFieldBeforeChangeEvent = Procedure (&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Field :TField; NewValue :Variant) Of Object;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;// Ampliaremos a TDataSet&lt;br /&gt;&amp;#160;&amp;#160;TDataSet = Class &lt;strong&gt;Override&lt;/strong&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Private&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FAfterFieldChange :TFieldAfterChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;FBeforeFieldChange :TFieldBeforeChangeEvent;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Protected&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{ Versión "superior" del método virtual&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;SetFieldData, usada para implementar el&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;disparo de los eventos BeforeFieldChange y&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;AfterFieldChange.&amp;#160;&amp;#160;&lt;em&gt;Top&lt;/em&gt; significa que, para&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;todos los descendientes de TDataSet, se&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ejecutará esta versión del método como si&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;fuera una redefinición por encima de las&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ya existentes. }&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Procedure SetFieldData (Field :TField;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Buffer :Pointer); &lt;strong&gt;Top;&lt;/strong&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Published&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property AfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldAfterChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FAfterFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FAfterFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Property BeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;:TFieldBeforeChangeEvent&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Read FBeforeFieldChange&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Write FBeforeFieldChange;&lt;br /&gt;&amp;#160;&amp;#160;End;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Estoy consciente de que una característica como ésta de la redefinición de clases presentaría varias repercusiones a considerar, pero es posible que en muchos casos se trate de situaciones salvables en las que los beneficios de programación tengan mayor peso que las medidas de control subyacentes que haya que tomar.  En todo caso, si nuestra falta de experiencia en una tecnología prácticamente inexistente nos impide ver con claridad las vicisitudes que vendrían si intentáramos crear ésta, al menos deberíamos empezar por debatir el tema y sacar en claro lo que sí podríamos hacer y lo que no deberíamos hacer.  ¿No lo creen?&lt;br /&gt;&lt;br /&gt;En la &lt;a href="http://rescatandoadelphi.blogspot.com/2010/03/beforefieldchange-y-afterfieldchange.html"&gt;segunda parte&lt;/a&gt; de este artículo entraremos de lleno a la práctica, implementando estos dos nuevos eventos en una clase derivada de TClientDataSet.  Estén pendientes de ello.&lt;br /&gt;&lt;br /&gt;Mientras tanto arrojen sus comentarios.&lt;br /&gt;&lt;br /&gt;Un abrazo natural y eficiente.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-1486875699545838726?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/1486875699545838726/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/02/eventos-beforefieldchange-y.html#comment-form' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1486875699545838726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1486875699545838726'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2010/02/eventos-beforefieldchange-y.html' title='BeforeFieldChange y AfterFieldChange.  Parte 1.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-4692967423131158378</id><published>2009-12-31T18:00:00.003-06:00</published><updated>2009-12-31T18:13:39.457-06:00</updated><title type='text'>1927 - 2009</title><content type='html'>&lt;div align="right"&gt;Chihuahua, México, 30 de diciembre de 2009.&lt;/div&gt;&lt;br /&gt;En 1927 nació muy cerca de esta ciudad un varón que de nombre llevó Rito González.&lt;br /&gt;&lt;br /&gt;Rito se casó a los 34 años con una mujer de palabras discretas pero muy amorosa, quien se convirtió en madre de mis cinco hermanos y yo, y lo acompañó hasta el último día de su existencia con un cariño y una dedicación tales que nunca fueron vistos con indiferencia.  Un matrimonio exitoso que concluyó hace un par de días por designios de la Providencia.  De ese matrimonio surgieron seis personas de nobles cualidades y sentimientos que hoy día nos sentimos orgullosos de haber crecido en el hogar que ellos, mis queridos padres, forjaron con esfuerzo y amor.&lt;br /&gt;&lt;br /&gt;En el mundo que presenció este éxito familiar, algunos decían que Rito era un hombre ignorante porque no terminó la escuela primaria, pero fue capaz de construir con sus propias manos una completa y bonita casa para su hija mayor.  Ya quisiéramos entonces muchos de nosotros contar con la &lt;em&gt;ignorancia&lt;/em&gt; suficiente para construir siquiera una escueta casa de mascotas.&lt;br /&gt;&lt;br /&gt;Otras personas decían que Rito era un hombre desaseado porque no tenía ese hábito tan criollo de bañarse a diario, pero gracias al sudor de sus largas jornadas como obrero jamás faltó el agua corriente en casa para mantenernos limpios.&lt;br /&gt;&lt;br /&gt;Algunas personas decían que Rito estaba chiflado porque en ocasiones expresaba frases y ademanes extraños.  Lo que no sabían esas personas era que con esas expresiones él ajustaba su sincronía en el Universo.  Sencillamente era Rito en momentos de plenitud.&lt;br /&gt;&lt;br /&gt;Fue criticado por no tener grandes ambiciones y acusado de conformista, pero terminó dándonos a todos la lección de cómo una persona puede dormir en paz y con la conciencia tranquila durante 30 mil apacibles noches.&lt;br /&gt;&lt;br /&gt;Otros decían que era un mal padre porque casi todas las decisiones las dejaba en manos de mamá.  Puso con ello a prueba la gran valía de su esposa, logrando que dicha valía quedara manifestada sin la menor duda.  Millones de niños quisieran tener a un padre como lo fue Rito, que nos dio apellido y nos procuró cuidados, salud, techo y alimentación.  Que nos enseñó a todos sus hijos algo de su variado y práctico conocimiento.  Que nos dio amor de la forma más natural en que un padre de familia puede hacerlo: trabajando con poco descanso para brindar elementos de bienestar a su familia.&lt;br /&gt;&lt;br /&gt;Nos acordaremos de Rito, nuestro padre y amigo, cada vez que nos invada la pereza porque él rara vez la tuvo.  También cuando tengamos miedo porque él lo venció mucho antes de llegar al episodio 82 de su vida.  Cuando nos intente dominar la ira, porque él siempre desvió la suya hacia el viento que terminaba desintegrándola.  Cuando estemos a punto de comprar algo que terminará siendo olvidado en un rincón, porque él vivió en constante austeridad.  Cuando volvamos a comer en exceso o nos quedemos hasta tarde contemplando las engañosas fantasías del televisor, porque él jamás engolosinó su cuerpo ni su espíritu, lo cual le permitió llegar muy lejos.&lt;br /&gt;&lt;br /&gt;Su existencia nos deja un mensaje a todos los que conocimos alguna parte de su historia.  Nos invita a ser nosotros mismos y no consumir días que podrían ser grandiosos en intentar destinos que no se nos tienen designados.  Nos invita a aceptar el camino que es armonioso para cada quien, a no acoger ambiciones nacidas de la envidia o del simple deseo de posesión, a reafirmar nuestra fe y ese devaluado pero muy poderoso recurso llamado intuición.  Aunque mi padre no tuvo en vida noción aparente de este mensaje, con su deceso nos hace un llamado a concienciarnos de que no estamos solos, y de que todos repercutimos en la vida de todos de alguna u otra manera, en la familia, en la ciudad y en el planeta entero.  Ya basta de buscar sabiduría de laboratorio y seamos verdaderos sabios de la vida como ese hombre de inteligencia incomprendida que fue Rito González.&lt;br /&gt;&lt;br /&gt;Padre, no te has ido, te convertiste en parte de la conducta y pensamiento que tu familia y amigos tendrán desde hoy en el resto de sus días como personas y que no dejarán de transmitir al prójimo durante todo ese tiempo.  No te digo que descanses en paz porque estarás muy activo en nosotros.&lt;br /&gt;&lt;br /&gt;Hasta siempre papá.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-4692967423131158378?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/4692967423131158378/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/12/1927-2009.html#comment-form' title='21 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4692967423131158378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4692967423131158378'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/12/1927-2009.html' title='1927 - 2009'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-2735238752917585073</id><published>2009-11-13T11:38:00.004-06:00</published><updated>2009-11-13T11:49:33.689-06:00</updated><title type='text'>Redes sociales</title><content type='html'>Últimamente se habla mucho de las &lt;em&gt;redes sociales&lt;/em&gt;. Pues les contaré sobre una que me cautivó desde que la conocí.&lt;br /&gt;&lt;br /&gt;Se trata de un sitio donde las personas pueden saludarse con calidez y mirarse entre sí, o al menos escucharse, percibiendo con certeza el ánimo del interlocutor y dando poco espacio a las malas interpretaciones. Tienes las opciones de hacer cuádruple &lt;em&gt;toc&lt;/em&gt; en la puerta del domicilio o trabajo de la persona que quieres saludar, citarte con ella en un lugar público agradable, como un parque o un café (donde con muy poca suerte podrás conocer a más afables personas), o bien emplear un aparato que denominan &lt;em&gt;teléfono&lt;/em&gt; para conversar de viva voz si ambos se encuentran geográficamente distanciados.&lt;br /&gt;&lt;br /&gt;La red posee un interesante mecanismo llamado &lt;em&gt;presentación&lt;/em&gt;, por el cual una persona le permite a uno de sus conocidos entablar primera conversación con otro, facilitando la comunicación entre éstos y dando con ello pie a todo tipo de constructivas relaciones. Los amigos y familiares pueden reunirse en grupos de dos o más personas para llevar a cabo toda clase de actividades de esparcimiento y formación cultural, desde ir al cine a ver una buena película, hasta un viaje vacacional.&lt;br /&gt;&lt;br /&gt;Con el tiempo las relaciones establecidas fortalecen los lazos de afecto e identidad, de tal manera que todos los individuos del grupo pueden llegar a contar con un buen número de personas con quienes celebrar los triunfos, apoyarse en momentos difíciles o sencillamente compartir algo. Existe muy poco SPAM y agresiones, ya que las personas suelen decir las cosas en función de lo que creen, pero guardando casi siempre consideración, prudencia y respeto ante el carácter y cariz de los demás.&lt;br /&gt;&lt;br /&gt;Esta red lleva muchísimos años demostrando ser un modelo exitoso para la convivencia social y el desarrollo de las virtudes humanas, además de ser biológicamente saludable. El sitio del que les hablo es vvvvvv.novivoeninternet.com&lt;br /&gt;&lt;br /&gt;Dedicado a todos aquellos que conocen lo que es disfrutar un tibio baño de Sol en un amanecer frío, y a los que desean experimentarlo antes de que sea demasiado tarde.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-2735238752917585073?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/2735238752917585073/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/11/redes-sociales.html#comment-form' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2735238752917585073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2735238752917585073'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/11/redes-sociales.html' title='Redes sociales'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-1354969077022352833</id><published>2009-11-03T23:49:00.002-06:00</published><updated>2009-11-04T00:03:18.715-06:00</updated><title type='text'>Tono, Sony, Cheché y yo</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/_9N_Agt_qWL4/SvEYVCV4gpI/AAAAAAAAAF0/JYenDu0I31E/s1600-h/DSC06907.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5400124177878909586" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 300px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_9N_Agt_qWL4/SvEYVCV4gpI/AAAAAAAAAF0/JYenDu0I31E/s400/DSC06907.JPG" border="0" /&gt;&lt;/a&gt;Deliciosa cena y más deliciosa charla con tres entrañables amigos y programadores Delphi.&lt;br /&gt;&lt;br /&gt;«&lt;em&gt;¡¡ GRACIAS !!»  &lt;/em&gt;xD&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-1354969077022352833?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/1354969077022352833/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/11/tono-sony-cheche-y-yo.html#comment-form' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1354969077022352833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1354969077022352833'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/11/tono-sony-cheche-y-yo.html' title='Tono, Sony, Cheché y yo'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9N_Agt_qWL4/SvEYVCV4gpI/AAAAAAAAAF0/JYenDu0I31E/s72-c/DSC06907.JPG' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-1702012004901066398</id><published>2009-10-24T17:32:00.007-05:00</published><updated>2009-10-24T19:04:04.508-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='operador Is'/><category scheme='http://www.blogger.com/atom/ns#' term='expresión objeto'/><category scheme='http://www.blogger.com/atom/ns#' term='verificar clase'/><category scheme='http://www.blogger.com/atom/ns#' term='instancia'/><category scheme='http://www.blogger.com/atom/ns#' term='tipo declarativo'/><category scheme='http://www.blogger.com/atom/ns#' term='clase de objeto'/><category scheme='http://www.blogger.com/atom/ns#' term='directiva Absolute'/><title type='text'>Ser o no ser</title><content type='html'>Los saludo con gusto, nuevamente desde Morelia, México. Esta vez para exponer algunas curiosidades del no tan famoso pero sí muy útil operador &lt;strong&gt;&lt;em&gt;Is&lt;/em&gt;&lt;/strong&gt;, que el lector probablemente ha utilizado alguna vez en sus aplicaciones Delphi.&lt;br /&gt;&lt;br /&gt;Como saben, el operador Is tiene como propósito permitirnos averiguar si una referencia de objeto apunta o no a una instancia de cierta clase o de clase descendiente de ésta. Como ejemplo, usamos el operador en este pequeño procedimiento llamado SetText, cuya finalidad hipotética es establecer el texto de un componente dado de forma genérica:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Procedure SetText (Const C :TComponent; Const Text :String);&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;If C Is TButton Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TButton (C).Caption := Text&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;If C Is TEdit Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;TEdit (C).Text := Text&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Otras clases de componentes&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;El parámetro C es declarado de tipo TComponent para que el polimorfismo permita que se proporcione cualquier objeto de clase descendiente de TComponent. El primer If resultará verdadero si el componente dado es un TButton (o de clase descendiente de TButton). El segundo If resultará verdadero si C es de clase TEdit o descendiente.&lt;br /&gt;&lt;br /&gt;Podemos entonces llamar al procedimiento SetText de esta forma:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SetText (Button1, 'Hola');&lt;br /&gt;SetText (Edit1, 'a todos');&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Por favor, no ahondemos en la finalidad de ese procedimiento y su implementación, es sólo un ejemplo de introducción al tema que quiero plantear. Tampoco pretendo hacer una exposición académica sobre el uso tradicional del operador Is, pues de eso hay ya mucho material publicado. Quiero enfocarme en un detalle curioso y poco documentado que convendría tomarse muy en cuenta.&lt;br /&gt;&lt;br /&gt;Consideremos el siguiente formulario (admito que hasta hace un par de años les llamaba &lt;em&gt;formas&lt;/em&gt;), en el que tenemos un componente TButton y un componente TEdit:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_9N_Agt_qWL4/SuOIlY90acI/AAAAAAAAAFk/W4uLngIUtW8/s1600-h/Form1.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5396306954458261954" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 249px; CURSOR: hand; HEIGHT: 128px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_9N_Agt_qWL4/SuOIlY90acI/AAAAAAAAAFk/W4uLngIUtW8/s400/Form1.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Hace tiempo, trabajando en no sé qué cosa, necesitaba obtener un componente por su nombre, conociendo de antemano que el componente en cuestión era de una clase específica. Sabemos que el método FindComponent sirve para obtener un componente por su nombre, y siempre devuelve éste como expresión de tipo TComponent, lo cual está muy bien.&lt;br /&gt;&lt;br /&gt;Declaración del método TComponent.FindComponent:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function FindComponent(const AName: string): TComponent;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Pero conociendo no sólo el nombre, sino también la clase del componente que yo deseaba obtener, TButton, para fines de este ejemplo, me resultaba muy útil contar con una rutina que actuara como FindComponent, pero que, en lugar de regresar el objeto como TComponent, lo devolviese como TButton (así evitaría escribir un molde de tipo cada vez que obtuviera un TButton por su nombre). Por tal razón creé una rutina parecida a este método función:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Function TForm1.Boton (Const Nombre :String) :TButton;&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;C :TComponent;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;C := FindComponent (Nombre);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If C Is TButton Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := TButton (C)&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Nil;&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Hasta ahí todo estaba en armonía con el cosmos, hasta que mi espíritu perfeccionista me dijo al oído «&lt;em&gt;ahórrate la variable C&lt;/em&gt;». Decidí entonces cambiar un poco el código, en principio para experimentar:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Function TForm1.Boton (Const Nombre :String) :TButton;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;Result := TButton (FindComponent (Nombre));&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If Result Is TButton Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Exit&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Nil;&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;En esta segunda versión de la rutina utilizo Result directamente, en lugar de la variable local C que ha sido desechada. El molde de tipo TButton en la llamada a FindComponent es necesario por obvias razones: el compilador no permitiría asignar una expresión TComponent a una variable cuyo tipo declarativo no fuese esa clase o alguno de sus ancestros (el tipo declarativo de Result es TButton, clase que no es ancestro, sino descendiente, de TComponent).&lt;br /&gt;&lt;br /&gt;A simple vista podría parecer aceptable esta forma de simplificar el código, pero surge una puntual interrogante, ¿cómo evalúa Delphi la expresión &lt;em&gt;Result Is TButton&lt;/em&gt;? es decir:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;¿El operador Is trabaja todo el tiempo con la clase real de la instancia proporcionada o también considera el tipo declarativo de esa expresión objeto?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La respuesta a dicha pregunta puede ser respondida poniendo a prueba la nueva versión del método Boton, con el siguiente código:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;procedure TForm1.FormShow(Sender: TObject);&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;B :TButton;&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;B := Boton ('Edit1');&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If B &amp;lt;&amp;gt; Nil Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ShowMessage ('Encontramos el botón ' + B.Name + '.');&lt;br /&gt;end;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Cuando el formulario se abra, observarán en pantalla un bonito, revelador y algo desalentador mensaje como este:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_9N_Agt_qWL4/SuOIxNX9FyI/AAAAAAAAAFs/Hu8MIe2fhug/s1600-h/Form2.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5396307157505087266" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 167px; CURSOR: hand; HEIGHT: 110px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_9N_Agt_qWL4/SuOIxNX9FyI/AAAAAAAAAFs/Hu8MIe2fhug/s400/Form2.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Hagamos otro pequeño cambio al método Boton:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Function TForm1.Boton (Const Nombre :String) :TButton;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;Result := TButton (FindComponent (Nombre));&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If Result Is TButtonControl Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Exit&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Nil;&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;En lugar de TButton, he puesto su clase padre (TButtonControl) a la derecha de Is, y el resultado de la prueba fue el mismo. Esto me permite elaborar algunas conclusiones de cómo trabaja realmente el operador Is:&lt;br /&gt;&lt;br /&gt;La ayuda de Delphi dice que Is verifica la clase real que en tiempo de ejecución tiene la instancia evaluada. Pero con las pruebas anteriores hemos descubierto que este operador considera en primer lugar el tipo de dato con el que fue declarada la expresión objeto que se evalúa. Si el tipo de dato declarativo de la expresión, a la izquierda del operador Is, es la clase indicada a la derecha de éste o una descendiente, el operador devuelve True en automático sin revisar ya la clase real de objeto. Así pues, la clase real del objeto es revisada solamente en los casos donde la expresión del lado izquierdo indica (por su declaración) una clase ancestro de la especificada en el lado derecho.&lt;br /&gt;&lt;br /&gt;Lo anterior hace que este par de Ifs se cumplan, y sin que ocurra error alguno en el segundo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;procedure TForm1.Button1Click(Sender: TObject);&lt;br /&gt;begin&lt;br /&gt;&amp;#160;&amp;#160;If TForm (Button1) Is TCustomForm Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ShowMessage ('!');&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If TComponent (5) Is TComponent Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ShowMessage ('!');&lt;br /&gt;end;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Debo decir que este funcionamiento del operador Is me parece muy razonable, pues es poco visto que una expresión regrese un valor que no sea compatible con su tipo declarativo. De hecho, en la mayoría de los casos, eso es totalmente desaconsejable. El hecho de que Is no siempre verifique la clase real del objeto dado contribuye con toda seguridad a una ejecución más rápida de la operación.&lt;br /&gt;&lt;br /&gt;Entonces, para ahorrarnos la variable C en el método Boton, haría falta un pequeño ajuste:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Function TForm1.Boton (Const Nombre :String) :TButton;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;Result := TButton (FindComponent (Nombre));&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If TComponent (Result) Is TButton Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Exit&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Nil;&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Podemos recurrir a los métodos ClassType o InheritsFrom, en lugar del operador Is. Pero también podemos declarar la variable C con la directiva Absolute, para que ocupe el mismo espacio de memoria que Result (uno de mis trucos favoritos):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Function TForm1.Boton (Const Nombre :String) :TButton;&lt;br /&gt;Var&lt;br /&gt;&amp;#160;&amp;#160;C :TComponent Absolute Result;&lt;br /&gt;Begin&lt;br /&gt;&amp;#160;&amp;#160;C := FindComponent (Nombre);&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;If C Is TButton Then&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Exit&lt;br /&gt;&amp;#160;&amp;#160;Else&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Result := Nil;&lt;br /&gt;End;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Lo importante es tener presente que el operador Is toma en cuenta el tipo declarativo del objeto evaluado y no siempre revisa la clase de esa instancia.&lt;br /&gt;&lt;br /&gt;Un verdadero abrazo.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-1702012004901066398?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/1702012004901066398/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/10/ser-o-no-ser.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1702012004901066398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1702012004901066398'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/10/ser-o-no-ser.html' title='Ser o no ser'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_9N_Agt_qWL4/SuOIlY90acI/AAAAAAAAAFk/W4uLngIUtW8/s72-c/Form1.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-5725502072710436768</id><published>2009-09-26T10:18:00.003-05:00</published><updated>2009-09-28T13:54:52.547-05:00</updated><title type='text'>Cinco años exprés</title><content type='html'>Hace varios días tuve esta breve y espontánea conversación con un amigo desarrollador que conozco desde hace más de un lustro, y quien me ha dado autorización para hacerla pública, dado el interés que puede suscitar en la comunidad Delphi. Lo más interesante para mí es que durante los últimos años he participado en unas treinta charlas de similar contexto.&lt;br /&gt;&lt;br /&gt;A este estimado programador PHP, altamente orientado a herramientas libres (pero no siendo uno de esos fundamentalistas que ubican su Meca en la Antártida) le di un curso de POO en Delphi hace cinco años, adquiriendo bases con las cuales ahora ha creado su &lt;em&gt;primer objeto derivado&lt;/em&gt; en un lenguaje que sí tiene intenciones de utilizar.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;hola hola mi estimado, cómo has estado, ya tiene un buen que no te conectabas&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;/span&gt;&lt;br /&gt;¡Hola! Muy bien, gracias, ¿y tú?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;/span&gt;&lt;br /&gt;igual bien bien, sigues en Morelia?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;/span&gt;&lt;br /&gt;Así es, ¿y tú?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;si, aqui en Chetumal, trabajando y aprendiendo &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;Que bien, ¿con qué estás ahora?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;estamos concluyendo y dándole mantenimiento al sistema de control escolar de ahi donde trabajo, y en proyectos extras estoy en espera que me den luz verde para comenzar con un sistema de almacén&lt;br /&gt;&lt;br /&gt;y tu que onda?? en qué andas trabajando?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;[...] y dando asesorías sobre DataSnap y DBX&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;qué son DataSnap y DBX?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;Tecnologías de Delphi para aplicaciones multicapa&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;/span&gt;&lt;br /&gt;si, ya he escuchado eso, incluso si autorizan el sistema de almacén y según lo que logre analizar ya más detenidamente, usaré ASP.NET MVC&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;Vaya, por fin vas a usar algo distinto a lo tradicional del mundo Open Source&lt;br /&gt;¿Con qué lenguaje lo manejarás?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;de hecho ya he estado trabajando con .NET, usando Windows Forms&lt;br /&gt;y trabajo con C#&lt;br /&gt;e incluso cree mi primer objeto derivado e hice uso de la sobreescritura de métodos, y agregué nuevas propiedades que se ven en el inspector de objetos&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;color:#993300;"&gt;jejejeje mis primeros pininos, aún me falta, y mucho de donde aprender&lt;br /&gt;[...]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;/span&gt;&lt;br /&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;color:#993300;"&gt;¿Y cuánto invertiste en licencias?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Colega dice:&lt;br /&gt;&lt;/span&gt;nada, estoy trabajando con las versiones exprés de los editores, tanto de C#, como de ASP.NET y también de SQL Server Express, de igual manera el amigo con el que estoy trabajando tiene licencias gratis por 3 años debido a que dio de alta su empresa en el sitio de Microsoft y puede descargar los productos sin problema alguno&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;color:#993300;"&gt;Ya me voy Al, fue un gusto platicar contigo, nos vemos, cuídate y espero verte pronto de nuevo para seguir charlando sobre programación &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color:#993300;"&gt;&lt;span style="font-size:85%;"&gt;Al González dice:&lt;br /&gt;&lt;/span&gt;Hasta pronto, muy buen día.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Cualquier parecido con la realidad es cruda coincidencia. :)&lt;br /&gt;&lt;br /&gt;Un abrazo testimonial.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-5725502072710436768?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/5725502072710436768/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/cinco-anos-expres.html#comment-form' title='13 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/5725502072710436768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/5725502072710436768'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/cinco-anos-expres.html' title='Cinco años exprés'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-1277001637137223937</id><published>2009-09-23T10:55:00.002-05:00</published><updated>2009-09-23T11:08:51.518-05:00</updated><title type='text'>Guanajuato, otra Nueva Inglaterra del siglo XVII</title><content type='html'>Hoy por la mañana me enteré estupefacto que el gobierno del estado de Guanajuato, en México, está diciéndole a los chavales de sus escuelas secundarias que, cito textualmente: «&lt;em&gt;el único medio garantizado al 100% para evitar el SIDA y otras enfermedades de transmisión sexual es esperar hasta el matrimonio&lt;/em&gt;».&lt;br /&gt;&lt;br /&gt;De entrada la frase está incompleta, pues pareciera que a alguien le ganó el pudor cuando debía añadir “&lt;em&gt;para empezar a disfrutar del sexo en pareja&lt;/em&gt;” (y ya ni hablemos de sexo grupal, porque vivo muy cerca de la capital de ese estado y podrían venir por mí para quemarme en leña verde).&lt;br /&gt;&lt;br /&gt;¡Pero caramba!  La Secretaría de Educación de Guanajuato no sólo condena a miles de jóvenes a evitar el pleno disfrute de su sexualidad durante muchos de los mejores años de su vida (considerando que ya nadie en su sano juicio se casa antes de cumplir 28), y con todas las consecuencias sicológicas negativas que la abstinencia sexual conlleva, sino que encima de todo miente a sus futuros ciudadanos diciéndoles que, como por arte de magia, el organismo humano adquiere infalibles anticuerpos contra el VIH y otras enfermedades venéreas en cuanto se firma un acta matrimonial.  ¡Qué estupidez!&lt;br /&gt;&lt;br /&gt;Ya veo las oficinas del registro civil de León atestadas de adolescentes inquietos y sudorosos, con la mochila escolar en la espalda y mandando mensajes escritos a la velocidad del rayo, en espera del juez que habrá de unirlos de dos en dos, cual Noe funcionario.  Casarse para tener sexo cien por cien seguro, ¡qué gran idea!  Yo mañana mismo me registro, ¡por fin sabré lo que es hacerlo sin condón!&lt;br /&gt;&lt;br /&gt;No cabe duda que mientras la mayor parte de la gente de este planeta intenta progresar de algún modo, ciertas mentes pequeñitas pero con poder político buscan hacer realidad el infierno de Hester Prynne.&lt;br /&gt;&lt;br /&gt;Ojalá destituyan a los funcionarios responsables de atrocidades como &lt;a href="http://www.milenio.com/node/290297"&gt;esta&lt;/a&gt;, pues necesitan ser educados antes de injerir en el destino de una sociedad.&lt;br /&gt;&lt;br /&gt;Un abrazo sexual.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-1277001637137223937?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/1277001637137223937/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/guanajuato-otra-nueva-inglaterra-del.html#comment-form' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1277001637137223937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1277001637137223937'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/guanajuato-otra-nueva-inglaterra-del.html' title='Guanajuato, otra Nueva Inglaterra del siglo XVII'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-478975063858022504</id><published>2009-09-12T02:45:00.006-05:00</published><updated>2009-09-22T16:09:06.918-05:00</updated><title type='text'>Cierre de Programadores Delphi de México</title><content type='html'>Hola a todos.&lt;br /&gt;&lt;br /&gt;Como muchos saben, en el año 2008 Microsoft cerró el servicio de MSN Groups, lugar donde se encontraban alojados inicialmente los registros de la comunidad Web &lt;a href="http://pdm2.multiply.com/"&gt;Programadores Delphi de México&lt;/a&gt; (PDM). Ya para entonces el sitio contaba con más de 3 mil colegas inscritos y un acervo considerable de mensajes con información técnica. Había cumplido con su misión de acercar entre sí a una cantidad importante de desarrolladores Delphi de la República Mexicana y otros países de habla hispana.&lt;br /&gt;&lt;br /&gt;En un mundo global, donde la única frontera vigente es el idioma, otro sitio Web de mejor formato y mayor trayectoria y riqueza informativa empezó a cumplir el mismo propósito para los desarrolladores Delphi de México y países vecinos. Alrededor del año 2004 Club Delphi dejaba de ser visto por los desarrolladores americanos como “&lt;em&gt;un foro de España&lt;/em&gt;”, para convertirse en una comunidad verdaderamente plural, en la cual ahora es fácil encontrar personas de cualquier país de Iberoamérica.&lt;br /&gt;&lt;br /&gt;Para PDM, que nunca tuvo el objetivo de competir contra otras comunidades Web, sino llenar espacios que estaban vacíos para los desarrolladores mexicanos, dejó de tener sentido su operación desde que tales desarrolladores comenzamos (porque me incluyo) a encontrar comodidad, trascendencia, respuestas, crecimiento y satisfacción en el otro foro. Así que el cierre de PDM quedaba anunciado implícitamente en su propia naturaleza.&lt;br /&gt;&lt;br /&gt;Personas cercanas a mí me sugirieron añadir al sitio el ingrediente de la competencia, mantenerlo en pie, mejorarlo y ofrecer características que atrajeran la preferencia de un mayor número de participantes. Mi opinión fue que como iban las cosas con Delphi (mal), lo mejor era contribuir a tener una sólida y única comunidad Web de programadores Delphi de habla castellana. Y qué mejor que Club Delphi para ser esa comunidad.&lt;br /&gt;&lt;br /&gt;Pero se atravesó una serie de sucesos desafortunados que parecen haber sido orquestados por una mente perversa, y el sueño de tener una gran, única e incluyente comunidad Web que ejerciera mayor presión sobre el fabricante de Delphi y tomara participación considerable en su destino como herramienta de programación, se esfumó cuando varios miembros destacados del prestigioso club se vieron orillados a abandonarlo y crearon legítimamente un espacio alternativo. Aquello sucedió de tal manera que resultó imposible emitir un juicio contundentemente a favor de alguna de las partes en conflicto, pues todo mundo tenía razón y todo mundo estaba equivocado. Si fuera yo un conspiracionista, de esos que creen en el falso precepto de “&lt;em&gt;piensa mal y acertarás&lt;/em&gt;” (la verdad es que casi siempre se yerra), diría que alguien poderoso estaba interesado en provocar la separación ocurrida pero con la menor pérdida de credibilidad posible para ambas partes. Sí, suena como si alguien hubiese querido &lt;em&gt;abrir el mercado&lt;/em&gt; sin que ninguno de los protagonistas se diera cuenta del plan (una locura conspiracionista, no hagan mucho caso a esta parte :p).&lt;br /&gt;&lt;br /&gt;El hecho palpable es que hay un nuevo foro para los miles de desarrolladores Delphi que hablan español, y sus dirigentes llevan consigo una tremenda carga de motivación y energía que seguramente trascenderá a su primer año de vida, pues éste está por cumplirse ya. Sus estadísticas son relevantes, y aunque por ahora la mayoría de los mensajes publicados son de esparcimiento, existe una clara tendencia de crecimiento en las aportaciones técnicas, además de que se promueven diversos tipos de actividades más allá de los tableros de mensajes. DelphiAccess, es pues, una comunidad prometedora.&lt;br /&gt;&lt;br /&gt;Con el cierre oficial de PDM (en la práctica ha ido ocurriendo a la velocidad en que muere una planta de maíz después de ser cosechada), sus administradores, Alejandro Ontiveros, Fabián Durón y un servidor, recomendamos a todos los desarrolladores Delphi de habla castellana registrarse y participar en las dos comunidades Web más importantes para la programación en Delphi de nuestra región idiomática:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/"&gt;Club Delphi&lt;/a&gt;, poseedora de un invaluable acervo técnico y cultural, casa de decenas de desarrolladores que merecen una estatua y sitio con gran infraestructura subyacente.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.delphiaccess.com/"&gt;DelphiAccess&lt;/a&gt;, el foro que asemeja a las 13 Colonias americanas en su espíritu por encontrar justicia y libertad.&lt;br /&gt;&lt;br /&gt;Muchas gracias a todos los miembros de PDM por estos siete años de increíble aventura.&lt;br /&gt;&lt;br /&gt;Un abrazo mexicano.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-478975063858022504?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/478975063858022504/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/cierre-de-programadores-delphi-de.html#comment-form' title='14 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/478975063858022504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/478975063858022504'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/09/cierre-de-programadores-delphi-de.html' title='Cierre de Programadores Delphi de México'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-6656684572766074959</id><published>2009-08-28T02:08:00.002-05:00</published><updated>2009-08-28T02:37:51.375-05:00</updated><title type='text'>El evento OnTwentyTen</title><content type='html'>Quizá muy pocos conocen algo acerca de este evento.  Pertenece al componente TEmbarcadero y se dispara los días 1 y 3 de septiembre de 2009.  Se trata de la gran presentación de Delphi 2010 y la explicación de buena parte de sus principales novedades ante dos multitudinarios grupos de desarrolladores de software, los cuales por fortuna nos encontramos en la zona central de México (cuando vivía en Chihuahua estas cosas eran muy lejanas para mí, aunque echo de menos la paradójica modernidad de aquella bella localidad).&lt;br /&gt;&lt;br /&gt;El día martes 1 será la primera presentación en la Cámara Nacional de Comercio de Guadalajara y el jueves 3 en el Centro Asturiano Polanco de Ciudad de México.  Su servidor irá desde Morelia a ésta última, a diferencia del año anterior, cuando pude asistir a la presentación de Delphi 2009 en Guadalajara.&lt;br /&gt;&lt;br /&gt;Se nota que esta versión 2010 lleva buena hechura y es muy posible que la incluya en mi lista de versiones más recomendables, junto con Delphi 7 y 2007.&lt;br /&gt;&lt;br /&gt;Consecutivamente y para fines de soporte técnico es la versión 13 de Delphi, un número cabalístico entre millones de estadounidenses, pero de significado positivo entre los programadores de todo el mundo.  Pues 13 es el valor ASCII de la tecla de computadora más emblemática, y por si fuera poco en hexadecimal se escribe con una enorme y regia letra...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:lucida grande;font-size:180%;"&gt;&lt;a href="http://latam.embarcadero.com/es/delphi2010/"&gt;D&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Si tienen oportunidad no dejen de asistir a alguna de las dos presentaciones.  Y si son clientes de Gopac o Embarcadero que viven en grandes ciudades olvidadas como Chihuahua, Monterrey, Culiacán, Torreón, Veracruz, Cancún, Mérida, Tuxtla, Acapulco, Tampico, Chilpancingo, Campeche, León, Pachuca, Reynosa, Hermosillo, etc. (u otras todavía más olvidadas como Parral o Huauchinango), llámenles para que miren a verlos y pronto se logre materializar uno de estos eventos en su localidad.&lt;br /&gt;&lt;br /&gt;Un abrazo hacia la grandeza de Delphi en México.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;br /&gt;&lt;br /&gt;P.D.  Además &lt;em&gt;D&lt;/em&gt; en números romanos es 500, el precio en dólares que tarde o temprano habrá de tener la edición &lt;em&gt;Professional&lt;/em&gt; del paquete para por fin ser altamente competitiva esa edición en el mercado.  Claro, siempre y cuando se incluya el controlador de Firebird en ella. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-6656684572766074959?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/6656684572766074959/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/08/el-evento-ontwentyten.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6656684572766074959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6656684572766074959'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/08/el-evento-ontwentyten.html' title='El evento OnTwentyTen'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-4848264765825977986</id><published>2009-08-08T21:32:00.002-05:00</published><updated>2009-08-08T21:37:40.386-05:00</updated><title type='text'>Descubren ciudad perdida</title><content type='html'>Enclavada en la serrana comunidad de El Rodeo, perteneciente al municipio de Tamazula, a más de 330 kilómetros de la capital duranguense y en la zona limítrofe con Sinaloa –dentro del llamado &lt;em&gt;Triángulo Dorado&lt;/em&gt;–, Ciudad Crystal es un complejo de 22 módulos distribuidos en 240 hectáreas, donde el cártel de Sinaloa fabricaba toneladas de drogas sintéticas.&lt;br /&gt;&lt;br /&gt;Consta de cinco laboratorios, áreas de hospedaje, cascada artificial, aeropista, tres plantas de luz, sistema de drenaje y agua potable.&lt;br /&gt;&lt;br /&gt;Sus operarios y ocupantes tenían catálogos de prostitutas con tarifas de hasta 22 mil dólares, y también disponían de 10 antenas de Sky [televisión de paga satelital], tres de red satelital, 18 vehículos, entre camionetas y cruatrimotos, y dos retroexcavadoras (una, de las llamadas mano de chango).&lt;br /&gt;&lt;br /&gt;Entre los edificios de complejo hay bodegas, lavanderías, cocina y enfermería. También se hallaron 164 tambos [bidones] de 200 litros, todos llenos de acetona, tolueno, sosa cáustica y otros precursores químicos; tanques de gas y oxígeno, así como de 10 toneladas de marihuana, 20 kilos de cocaína pura, 12 armas largas, 500 cartuchos, 20 mil dólares en efectivo y equipo de radiocomunicación.&lt;br /&gt;&lt;br /&gt;Considerada por militares como la más grande fábrica de drogas sintéticas hallada en el país, Ciudad Crystal fue descubierta en el transcurso de la semana, durante un operativo conjunto de las zonas militares novena y décima.&lt;br /&gt;&lt;br /&gt;Desde el aire no se distinguía gracias a su camuflaje de hojarasca en techos y paredes. Más de cerca se notaba su silueta arquitectónica, pero fue necesario volar en helicóptero hasta la comunidad de Las Trancas, y de ahí subir a la alta Sierra Madre Occidental para llegar al sitio.&lt;br /&gt;&lt;br /&gt;Personal militar calculó que en el complejo trabajaban unas 120 personas entre vigilantes, laboratoristas, cocineros y personal de enfermería; pero no hubo detenidos pues cuando el Ejército se acercaba todos pudieron escapar.&lt;br /&gt;&lt;br /&gt;Habitantes de comunidades cercanas dijeron al Ejército que en las cabañas rodeadas de casas de seguridad y laboratorios vivían capos de alto rango como Joaquín &lt;em&gt;El Chapo&lt;/em&gt; Guzmán, Ismael &lt;em&gt;El Mayo&lt;/em&gt; Zambada e Ignacio &lt;em&gt;Nacho&lt;/em&gt; Coronel.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jornada.unam.mx/2009/08/08/index.php?section=politica&amp;amp;article=012n1pol"&gt;Fuente&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-4848264765825977986?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/4848264765825977986/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/08/descubren-ciudad-perdida.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4848264765825977986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/4848264765825977986'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/08/descubren-ciudad-perdida.html' title='Descubren ciudad perdida'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7653962800575957309</id><published>2009-07-15T13:19:00.018-05:00</published><updated>2009-10-26T11:09:24.177-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='libro'/><category scheme='http://www.blogger.com/atom/ns#' term='Marco Santin'/><category scheme='http://www.blogger.com/atom/ns#' term='Delphi Prism'/><title type='text'>Pascal en .NET</title><content type='html'>Hace algún tiempo la empresa Embarcadero (actual propietario del prestigioso y legendario Borland Delphi) se alió con RemObjects, un discreto pero muy exitoso fabricante de herramientas de programación multiplataforma, con el fin de crear algo que CodeGear había intentado por sí solo sin obtener resultados relevantes: Un entorno Delphi para desarrollo de aplicaciones de software que corrieran sobre la plataforma .NET.&lt;br /&gt;&lt;br /&gt;Los pasos de Microsoft eran demasiado grandes para llevarles el ritmo al tiempo de tratar de conservar en Delphi su tradicional compatibilidad hacia atrás, además de su compatibilidad en paralelo con la emblemática API Win32, conjunto de DLLs que en su momento Microsoft incluyó de forma bastante generosa en todas las versiones de Windows para facilitar a otros la creación de aplicaciones.&lt;br /&gt;&lt;br /&gt;.NET es la “nueva API de Windows”, con un par de grandes diferencias. Más que una API, es un conjunto de varias tecnologías mucho más avanzadas y orientadas a objetos que la API Win32. La otra gran diferencia es escabrosa: Microsoft decidió crearla al mismo tiempo que decidió pelear por ser también un fabricante competitivo de lenguajes, con el surgimiento de las primeras versiones de sus C# y Visual Basic .NET. Imaginen a un arquitecto obeso que diseña la más moderna alberca pública del mundo, y el día de la inauguración es el primero en meterse a ella, ¡pero arrojándose de panza desde la plataforma de 10 metros! Salpicando a todo el mundo a su alrededor y regodeándose mientras nada, sin mirar dónde patalea.&lt;br /&gt;&lt;br /&gt;Entre el afán de CodeGear de mantener compatibilidad hasta con el color de ojos de Gonzalo Guerrero (el conquistador español que fue convertido en guerrero y noble maya), y el afán de Microsoft de convertirse en un verdadero fabricante de lenguajes, el espíritu prudente de Delphi no tenía mucho espacio para respirar. Así que, aunque algo tarde, en California decidieron tomar medidas extremas y por primera vez aceptaron que no podrían ser los mejores, encargando a la pequeña empresa RemObjects una versión especial de su ya famoso entorno Object Pascal, &lt;em&gt;Oxygen&lt;/em&gt;, la cual fue bautizada como &lt;em&gt;&lt;strong&gt;Delphi Prism&lt;/strong&gt;&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Al gordo ya se le pasó la euforia y empieza a tener problemas serios con otras de sus tecnologías (Windows, Office, Entity Framework, LINQ...). Sin embargo, la alberca .NET ha quedado bastante bien como para dar servicio a miles de bañistas (cabe mencionar que un ingeniero ex-Borland estuvo detrás de los trabajos y es el verdadero arquitecto de muchas de sus características).&lt;br /&gt;&lt;br /&gt;Así las cosas, con una plataforma .NET estable y rica y este nuevo Delphi Prism nada titubeante en comparación con los Delphi .NET anteriores, lo único que hacía falta era un buen libro para aprender a conocer esta nueva herramienta. ¡Ah! pero tenía que ser un libro que sirviera a todos aquellos que no habíamos querido tocar las aguas de .NET ni con los dedos del pie por falta de certidumbre en la época del CodeGear solitario, y quizá también por miedo a lo desconocido y el romanticismo cultural que guardamos entorno a la popular API Win32. Un libro que además de explicarnos paso a paso el uso de Delphi Prism, también nos explicara qué rayos es .NET y con qué cubiertos se come.&lt;br /&gt;&lt;br /&gt;Este es un libro escrito en español por un desarrollador mexicano con gran experiencia en Delphi. No tuvo que exiliarse o hacer muchos viajes al extranjero para darse a conocer. Marco Antonio Santin ha escrito su ópera prima desde el lugar donde ha vivido gran parte de su vida, la pequeña ciudad de Zitácuaro, Michoacán. Es de los que ven a México como lo que es, un país hermoso lleno de oportunidades de éxito. Éxitos como este:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_9N_Agt_qWL4/Sm9IwBegOTI/AAAAAAAAAE8/EpFfMqodTH4/s1600-h/portadaprismweb.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5363585671088847154" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 307px; CURSOR: hand; HEIGHT: 400px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_9N_Agt_qWL4/Sm9IwBegOTI/AAAAAAAAAE8/EpFfMqodTH4/s400/portadaprismweb.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p align="center"&gt;&lt;strong&gt;&lt;a href="http://markdelphi.intelsoftassociates.com/"&gt;http://markdelphi.intelsoftassociates.com/&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Muchas felicidades, Marco.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7653962800575957309?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7653962800575957309/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/07/pascal-en-net.html#comment-form' title='12 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7653962800575957309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7653962800575957309'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/07/pascal-en-net.html' title='Pascal en .NET'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_9N_Agt_qWL4/Sm9IwBegOTI/AAAAAAAAAE8/EpFfMqodTH4/s72-c/portadaprismweb.jpg' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-5805488934210624915</id><published>2009-06-28T21:42:00.004-05:00</published><updated>2009-06-28T23:06:52.186-05:00</updated><title type='text'>DTE y la figura del bibliotecario</title><content type='html'>Hola a todos.&lt;br /&gt;&lt;br /&gt;He decidido rescatar un par de artículos que publiqué hace varios años en Club Delphi y Programadores Delphi de México, y unirlos en uno solo, dada la relación tan estrecha que guardan entre sí y la importancia que considero podría tener este material en el mundo del desarrollo de software.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:180%;"&gt;Distribución del Trabajo&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:180%;"&gt;por Especialidades (DTE)&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;La Distribución del Trabajo por Especialidades es un paradigma de organización laboral aplicable a todas las profesiones que alcanzan cierto nivel de complejidad. Consiste en clasificar todas las tareas involucradas en un ámbito laboral por tipo de actividad o, más formalmente, por especialidades, y respetando esa clasificación durante los procesos de estimación, repartición y ejecución del trabajo. La idea fundamental de la DTE es tener claramente identificadas las diferentes áreas de una profesión y promover el surgimiento de especialistas y el trabajo en equipo, para lograr resultados de mayor calidad, dignificar la labor de los profesionistas y elevar su nivel de vida. Por dar un ejemplo donde la DTE ha tenido éxito, podemos mencionar la profesión médica, la cual lleva muchos años fomentando la especialización con resultados realmente admirables.&lt;br /&gt;&lt;br /&gt;Debemos aceptar el hecho de que, en cualquier profesión, la especialización siempre será una ventaja competitiva tanto para los trabajadores como para las empresas que los emplean. El resultado directo de la especialización es un mejor desempeño y una mayor calidad en los productos y servicios obtenidos. Una persona especializada tiende a realizar mejor su trabajo que una no especializada. Al unir los esfuerzos de diferentes especialistas en un mismo equipo de trabajo, logramos un entorno de alta productividad.&lt;br /&gt;&lt;br /&gt;Quizá el lector empresario se plantea en este momento el siguiente cuestionamiento: «&lt;em&gt;De acuerdo, lo ideal sería que mi empresa contara con varios especialistas, pero sería imposible sostener esa nómina. La cantidad de trabajo y los ingresos por ventas son insuficientes&lt;/em&gt;».&lt;br /&gt;&lt;br /&gt;Ese es un punto de vista típico del empresariado del siglo XX. En la mayoría de los casos, esa perspectiva derrotista pierde validez y se vuelve anacrónica cuando en contraparte se exponen estos sólidos argumentos del siglo XXI:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Un especialista no necesariamente debe percibir un salario mucho mayor que el de un trabajador no especializado, aunque es deseable y económicamente sano que si tenga un nivel de ingresos superior. Un especialista es un profesional, y por lo tanto entiende que el valor económico de su trabajo está determinado por el mercado; siempre habrá un punto de equilibrio aceptable entre lo que las empresas quieran pagarle al especialista y lo que éste quiera cobrar. &lt;/li&gt;&lt;li&gt;Un trabajador puede cubrir dos o más especialidades. La especialización no significa que la empresa deba contar forzosamente con un trabajador por cada especialidad. La meta laboral es cubrir todas las especialidades, independientemente de cuántas personas se ocupen para ello. Lo importante es que cada especialidad esté cubierta por alguien que desempeñé eficazmente su labor en esa área. Hay muchos profesionales que destacan en más de una.&lt;/li&gt;&lt;li&gt;La empresa puede recurrir a la contratación de servicios externos (&lt;em&gt;outsourcing&lt;/em&gt;) y al pago por hora, dos prácticas altamente efectivas y cada vez más difundidas alrededor del mundo. Una excelente forma de contar con el trabajo de diversos especialistas es contratando los servicios de profesionales independientes o de compañías consultoras, además de instaurar el pago por hora en lugar de abultados sueldos que, en muchos casos, no equivalen a la cantidad real de tiempo efectivo trabajado. De esta manera, la empresa decide cuándo, a quién, por cuánto tiempo y para qué actividades contratar a cada especialista. Por su parte, los especialistas gozan de una mayor autonomía laboral, permitiéndose cotizar sus servicios en el mercado con toda libertad.&lt;/li&gt;&lt;li&gt;Cuando una empresa desarrolla sus actividades más importantes empleando a especialistas, lógicamente incrementa sus ingresos por ventas. Esto es porque al mejorar la calidad de sus productos y servicios —gracias a la especialización— eleva su competitividad, logra una mayor aceptación de los mismos en el mercado y, opcionalmente, puede cotizarlos a un precio más alto.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;DTE en el desarrollo de software&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;Evidentemente, cada profesión tiene sus rampas y sus muros que facilitan u obstaculizan la especialización. Y cada una requiere un tratamiento específico para establecer una logística DTE efectiva. El autor de este artículo es un desarrollador de software, especialista en programación de bibliotecas, a quien le interesa la puesta en práctica de un modelo DTE en las empresas de software y en las oficinas de los programadores independientes. Tanto él como otros colegas de diversas especialidades están convencidos de que la DTE dará grandes beneficios tanto a los profesionistas y empresas creadores de software como a los usuarios de tecnologías de información, empezando por una mayor calidad de los productos y servicios proporcionados y propiciando que los desarrolladores —usualmente llamados &lt;em&gt;informáticos&lt;/em&gt;—, convivan en un entorno laboral más digno, respetado, satisfactorio y estable.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;Clasificación de las especialidades &lt;/span&gt;&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Cuando se pretende establecer un modelo DTE, lo primero es determinar cuál o cuáles son las clasificaciones más efectivas. En ocasiones leemos o escuchamos sobre desarrolladores especialistas en el manejo de herramientas o entornos de software específicos, como base de datos Oracle™, lenguaje Delphi™, programación Web, y muchísimos otros. Eso nos muestra que, de facto, ya existe una serie de especialidades que puede ser aprovechada al aplicar la DTE. Sin embargo, creo que la clasificación de especialidades por herramientas o entornos de software obedece más al gusto personal que a las habilidades reales del profesionista.&lt;br /&gt;&lt;br /&gt;Supongamos que tenemos a un autodenominado &lt;em&gt;experto en Java&lt;/em&gt;, un fanático del lenguaje que no programa nada si no es con algún entorno Java. Éste realiza un trabajo excelente programando rutinas de eventos, validando la lógica de negocios y creando clases de objetos para las aplicaciones que desarrolla, pero sus sentencias SQL de acceso a datos no son del todo óptimas y su diseño de interfaces de usuario carece de estilo gráfico y calidad gramatical. Entonces inferimos que realmente no se trata de un experto, más bien es un desarrollador que conoce el lenguaje lo suficiente como para crear aplicaciones funcionales y hasta cierto punto aceptables; se le reconocen importantes habilidades de programador operativo, de lógica de negocios y de bibliotecas, pero tiene escasa destreza en las áreas de administración de datos y diseño visual. Si una empresa le asigna cualquier actividad que tenga que ver con programación en Java, muchas de esas actividades serán mal ejecutadas (las que no son de su dominio).&lt;br /&gt;&lt;br /&gt;El ejemplo anterior es tan claro como lamentablemente típico. La especialización a partir de herramientas o entornos de software por lo general termina siendo una especialización a medias, poco eficiente. Como promotor de la DTE creo que la clasificación de especialidades debe originarse en función de los diferentes tipos de labores, lo cual va más acorde con las habilidades reales de los desarrolladores y no tanto con sus gustos personales. Naturalmente, pienso que es válido crear subespecialidades por herramientas, entornos u otras clasificaciones que satisfagan el gusto personal de cada desarrollador, pero siempre partiendo de especialidades mayores clasificadas por tipo de actividad. Bajo esta tónica, la empresa del ejemplo anterior le encargará a nuestro reconocido &lt;em&gt;especialista en programación operativa, de lógica de negocios y de bibliotecas en Java&lt;/em&gt; las tareas que son de su competencia profesional, mientras que el diseño de las interfaces de usuario y la construcción de sentencias SQL serán asignados al especialista respectivo.&lt;br /&gt;&lt;br /&gt;Si el lector empresario está pensando de nuevo en la “imposibilidad” de contratar a «&lt;em&gt;tantos&lt;/em&gt;» desarrolladores especialistas, le sugiero, de la manera más atenta, que vuelva a leer los cuatro sólidos argumentos del siglo XXI que expuse casi al comienzo de este artículo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Principales especialidades&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Algunos colegas y yo hemos detectado doce principales especialidades y cinco subespecialidades, en función de los diferentes tipos de tareas realizadas al desarrollar sistemas de software. A cada una le hemos asignado un acrónimo de dos letras mayúsculas para fines de simplificación. Se listan en seguida:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Análisis (AN)&lt;/li&gt;&lt;li&gt;Dirección (DI)&lt;/li&gt;&lt;li&gt;Administración de datos (AD)&lt;br /&gt;- Modelado de datos (MD)&lt;br /&gt;- Administración de bases de datos (AB) &lt;/li&gt;&lt;li&gt;Diseño visual (DV)&lt;br /&gt;- Diseño gráfico (DG)&lt;br /&gt;- Diseño operativo (DO)&lt;br /&gt;- Reporteo (RE)&lt;/li&gt;&lt;li&gt;Programación operativa (PO)&lt;/li&gt;&lt;li&gt;Programación de lógica de negocios (LN)&lt;/li&gt;&lt;li&gt;Programación de bibliotecas (PB)&lt;/li&gt;&lt;li&gt;Preparación de instaladores (PI)&lt;/li&gt;&lt;li&gt;Documentación (DC)&lt;/li&gt;&lt;li&gt;Control de calidad (CC)&lt;/li&gt;&lt;li&gt;Instrucción (IN)&lt;/li&gt;&lt;li&gt;Soporte técnico (ST)&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Red Colaborativa DTE&lt;/strong&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Concientes de que no es muy viable ni estratégico para la mayoría de las empresas de software contratar a doce o más especialistas de tiempo completo, pero a la vez convencidos de las ventajas de una organización DTE, los promotores del modelo consideramos que deben aceptarse dos escenarios perfectamente combinables:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Cada uno de los desarrolladores en una empresa estará a cargo de la realización de tareas de una o más especialidades. El equipo de desarrolladores (que en algunos casos podrá ser de uno sólo) deberá identificar y tratar de cubrir todas las especialidades mayores propuestas en este modelo. La repartición de las tareas se hará en función de las especialidades y disponibilidad de tiempo —en ese orden— de cada desarrollador. Siempre toda tarea deberá estar enmarcada en alguna de las especialidades, desde el análisis hasta la implantación.&lt;/li&gt;&lt;li&gt;La empresa recurrirá a la contratación de especialistas DTE externos cuando lo considere estratégico. Esto puede suceder cuando la empresa no cuente con el especialista interno adecuado o cuando éste no disponga de tiempo por estar ejecutando otras actividades que le fueron asignadas previamente. El servicio de &lt;em&gt;outsourcing&lt;/em&gt; contratado podrá ser ejecutado de forma presencial en las instalaciones de la empresa, o a distancia, con las facilidades que Internet ofrece para ello.&lt;/li&gt;&lt;/ol&gt;Para que esto sea factible y tenga aceptación general, los promotores del modelo proponemos crear una &lt;em&gt;Red Colaborativa DTE&lt;/em&gt;; un directorio de desarrolladores especialistas, tanto independientes como de empresas consultoras, que ofrezcan servicio profesional externo de desarrollo de software. Cada &lt;em&gt;desarrollador público&lt;/em&gt;, por llamarlo de alguna manera, deberá estar perfectamente registrado en ese directorio, con sus datos personales y fiscales básicos, direcciones y teléfonos donde se le puede localizar, especialidades DTE que domina, empresa a la cual pertenece, currículum, referencias comerciales, calificación o nivel de preferencia que le dan sus clientes, entre otra información importante. Y opcionalmente podrá publicar ahí algunas actividades de su agenda y su tarifa por hora. Un directorio formal y serio como ese le dará a las empresas la confianza necesaria para firmar contratos de trabajo con especialistas DTE externos, independientemente del lugar geográfico donde éstos se encuentren o de su esfera cultural.&lt;br /&gt;&lt;br /&gt;Pero esta Red Colaborativa tiene bondades adicionales. Al instaurarse el modelo DTE en las oficinas de los desarrolladores independientes y en las pequeñas empresas de software, pueden crearse magníficos equipos de teletrabajo para desarrollar proyectos de sistemas de cualquier tamaño y para cualquier compañía u organización. Con el modelo DTE y la Red Colaborativa, todos los desarrolladores independientes y pequeñas empresas de software tendrán la capacidad de competir en el mercado, ofreciendo software de alta calidad y a la medida de cualquier empresa o institución. Así por ejemplo, un programador serio y formal que trabaja desde casa podrá fabricar una completa solución de software para una compañía local, echando mano de especialistas externos DTE de cualquier parte del mundo. Inclusive podrán ocurrir situaciones donde dos desarrolladores o empresas estén mutuamente contratados para la ejecución de varios proyectos. También podrán darse alianzas estratégicas entre los desarrolladores y las empresas de software, con el fin de garantizar su estabilidad a largo plazo, dando pie a la creación de nuevas y más sólidas compañías. Y más aún, entre los desarrolladores podrán surgir acuerdos de colaboración para la fabricación de paquetes de software comerciales, compartiendo riesgos (en este caso se sugiere emplear, en lugar de &lt;em&gt;colaborativo&lt;/em&gt;, el término &lt;em&gt;cooperativo&lt;/em&gt;, distinguiendo dos tipos de proyectos compartidos que propone el modelo DTE). También es posible que surjan nuevas empresas especialistas DTE. Que no nos extrañe ver el surgimiento de compañías especializadas en AN, CC, DC, etc., además de las de DG y PB (componentes), las cuales ya son algo comunes.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:180%;"&gt;La figura del bibliotecario&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;En un equipo de desarrolladores debe existir por lo menos un &lt;em&gt;programador bibliotecario&lt;/em&gt;, cuya definición que propongo es esta:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Desarrollador encargado de elaborar, adquirir, investigar, administrar y facilitar recursos técnicos a otros desarrolladores, principalmente a los que se encuentran dentro de su grupo o equipo de trabajo.&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;El bibliotecario debe programar y mantener una biblioteca de funciones, componentes y otros recursos de software prefabricados, cuyos elementos sean creados como soluciones a necesidades reales, reportadas por los demás programadores en sus respectivos proyectos. También debe encargarse de evaluar los requerimientos de los programadores, hacer investigaciones al respecto y en su caso solicitar y / o adquirir los recursos que sean necesarios para satisfacer tales requerimientos. Además el bibliotecario, en la medida de lo posible, debe ser intuitivo, analítico, suspicaz, metódico, imaginativo, perspicaz, persuasor, disuasivo y cuestionante respecto a las peticiones que le hacen sus compañeros, pero sobre todo debe apoyarlos, entenderlos, y ponerse en sus zapatos para determinar qué es lo mejor que se puede hacer en cada caso que le plantean.&lt;br /&gt;&lt;br /&gt;Supongamos que Pascual es el programador bibliotecario, y Lorena y Roberto dos de los programadores finales (los que realizan la programación de alto nivel y ensamblado final del producto). En determinado proyecto, Lorena se ve en la necesidad de convertir un arreglo abierto de enteros &lt;em&gt;Array Of Integer&lt;/em&gt;, en una cadena de caracteres String separada por comas. Por ejemplo, necesita convertir el arreglo de enteros [78, 27, 2, 19] a la cadena '78, 27, 2, 19' (considerando que el vector de enteros es variable). Lorena intuye que esta necesidad pudo haberse presentado antes en algún otro proyecto del equipo, así que lo primero que hace es plantearle su caso a Pascual, el bibliotecario:&lt;br /&gt;&lt;br /&gt;—Mira. Este procedimiento de nuestro proyecto recibe un arreglo abierto de enteros. Se me facilitaría mucho poder convertir el arreglo recibido en una cadena tipo lista separada por comas, porque así podría darla como parámetro al llamar a este método que espera un String. Creo saber cómo realizar la conversión, pero quizá alguien más pudo haber necesitado algo así antes. ¿Tendrás algo para estos casos? Si no, te sugiero tomarlo en cuenta, porque eventualmente podría presentarse de nuevo esta necesidad.&lt;br /&gt;&lt;br /&gt;—¡Este es tu día de suerte, Lorena! —le responde Pascual—. Sabes, hace algunas semanas Roberto me planteó un caso muy similar. Desde entonces tenemos en la unidad Convertidores.pas de nuestra biblioteca, una función llamada EnterosALista que hace precisamente la conversión que requieres de Array Of Integer a String. Se usa de esta manera...&lt;br /&gt;&lt;br /&gt;—¡Órale, me impresionas Pascual! Me has ahorrado algunas horas de trabajo y medio dolor de cabeza, je-je-je. Muchas gracias, niño listo.&lt;br /&gt;&lt;br /&gt;El anterior es un ejemplo de cómo interviene el bibliotecario en la solución de necesidades técnicas de los programadores finales. Se destaca la importancia que tiene en el manejo efectivo de los recursos del equipo, y se observa cómo los programadores finales no se desvían de su objetivo principal, ya que varias tareas adyacentes le son delegadas al bibliotecario.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Si les interesa conocer las opiniones de algunos colegas respecto a la DTE y la figura del bibliotecario, les recomiendo ampliamente echarle una mirada a estas sanas discusiones:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=25463"&gt;http://www.clubdelphi.com/foros/showthread.php?t=25463&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=6559"&gt;http://www.clubdelphi.com/foros/showthread.php?t=6559&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=64236"&gt;http://www.clubdelphi.com/foros/showthread.php?t=64236&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;El tercer enlace es un grato testimonio del éxito que ha tenido una pequeña empresa de software de la ciudad Córdoba, en México, respecto de la figura del bibliotecario.&lt;br /&gt;&lt;br /&gt;Espero sus opiniones vertidas a través del enlace / recuadro de comentarios que ven debajo de estas líneas.&lt;br /&gt;&lt;br /&gt;Un abrazo especializado.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-5805488934210624915?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/5805488934210624915/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/06/dte-y-la-figura-del-bibliotecario.html#comment-form' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/5805488934210624915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/5805488934210624915'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/06/dte-y-la-figura-del-bibliotecario.html' title='DTE y la figura del bibliotecario'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7453617338175399023</id><published>2009-05-17T12:27:00.002-05:00</published><updated>2009-05-17T12:56:04.752-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='música'/><category scheme='http://www.blogger.com/atom/ns#' term='Fey'/><category scheme='http://www.blogger.com/atom/ns#' term='arte'/><title type='text'>Lentamente</title><content type='html'>¡Hola!&lt;br /&gt;&lt;br /&gt;Espero disfruten este pedazo de arte tanto como yo.&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/lYWG1jb9WTo&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/lYWG1jb9WTo&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;No soy un gran aficionado a esta música, pero es de reconocer que el video está muy bien trabajado.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;em&gt;...Llevas en la sangre una dulce tentación,&lt;br /&gt;no podrás curarte despistando al corazón...&lt;/em&gt;&lt;/div&gt;&lt;br /&gt;Un tentador abrazo.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7453617338175399023?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7453617338175399023/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/05/lentamente.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7453617338175399023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7453617338175399023'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/05/lentamente.html' title='Lentamente'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-6649829009812180014</id><published>2009-04-28T16:26:00.004-05:00</published><updated>2009-04-29T10:52:29.605-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='pandemia'/><category scheme='http://www.blogger.com/atom/ns#' term='National Geographic'/><category scheme='http://www.blogger.com/atom/ns#' term='documental'/><category scheme='http://www.blogger.com/atom/ns#' term='2005'/><category scheme='http://www.blogger.com/atom/ns#' term='influenza'/><category scheme='http://www.blogger.com/atom/ns#' term='embed'/><category scheme='http://www.blogger.com/atom/ns#' term='México'/><category scheme='http://www.blogger.com/atom/ns#' term='incrustar'/><category scheme='http://www.blogger.com/atom/ns#' term='virus'/><category scheme='http://www.blogger.com/atom/ns#' term='embeber'/><category scheme='http://www.blogger.com/atom/ns#' term='farmacéuticas'/><category scheme='http://www.blogger.com/atom/ns#' term='epidemia'/><category scheme='http://www.blogger.com/atom/ns#' term='antivirales'/><category scheme='http://www.blogger.com/atom/ns#' term='antivíricos'/><category scheme='http://www.blogger.com/atom/ns#' term='gripe'/><title type='text'>Pandemia de gripe</title><content type='html'>Hola a todos.&lt;br /&gt;&lt;br /&gt;Antes que nada quiero agradecer a Luis Peña, Heberto Coss y Esteban Arias las atenciones y hospitalidad que tuvieron conmigo durante mi visita a Guadalajara. Espero les haya dejado algo bueno mis exposiciones sobre Delphi, dentro de las limitantes que se presentaron.&lt;br /&gt;&lt;br /&gt;Entrando al principal tema en la agenda del mundo, quiero decirles que esta podría ser la primera pandemia que me toque presenciar, deseando de todo corazón que esto no llegue a ocurrir en carne propia de ninguno de mis lectores, ni de mí. Uno de mis hermanos mayores y su familia salieron esta mañana hacia un paraje alejado de la ciudad donde viven, ya que su apartamento se encuentra ubicado muy cerca de dos concurridos hospitales. Permanecerán en aquel lugar por tiempo indefinido para prevenirse de la influenza.&lt;br /&gt;&lt;br /&gt;El que más me preocupa, ya que no he logrado localizarlo, es mi hermano menor, el médico, quien apenas lleva dos meses como habitante de Ciudad de México y por quién seré nuevamente tío. Él y su esposa acaban de concebir al que será su primogénito y mi séptimo sobrino. Parece que ya sólo falto yo de fecundar un óvulo, aunque sinceramente no es algo que me atraiga mucho hacer, viendo cómo está el planeta y habiendo tantos niños huérfanos sufriendo hambre. Hermano, espero te encuentres bien, haznos saber cómo lo están pasando tú y mi cuñada. Cuídense mucho, no escatimen precauciones.&lt;br /&gt;&lt;br /&gt;El resto de mi familia, por encontrarse poco más al norte del Trópico de Cáncer —una región con menor densidad poblacional— corren un riesgo relativamente menor. Mientras yo sigo aquí, viviendo justo entre la dos ciudades más grandes del país, en una provincia empobrecida por los políticos insensibles de toda la vida, a pesar de ser la tierra del mejor presidente que ha tenido México (y aclaro que no me refiero al actual ;)).&lt;br /&gt;&lt;br /&gt;Encontré este documental que relata una historia ficticia que podría estar volviéndose una terrible realidad. Trata de una supuesta pandemia de gripe aguda que podría desatarse en cualquier momento de un futuro cercano. El problema es que ese futuro parece estar sufriendo ya la metamorfosis que lo convierte en presente.&lt;br /&gt;&lt;br /&gt;En este material se explica con argumentos sencillos, pero científica e históricamente válidos, cómo se origina y se propaga por el mundo una nueva y muy maligna cepa del virus de la gripe. Decidí incrustarlo en esta bitácora por dos razones principales (algunos dirían “embeberlo”, pero este palabro, por cierto, muy mal relacionado con &lt;em&gt;embed&lt;/em&gt;, me recuerda al sucio y desgastado trapo de &lt;em&gt;Magitel&lt;/em&gt; con que mi madre me ordenaba contener las bebidas derramadas accidentalmente antes de que la mesa y la física molecular crearan una delgada película con el líquido).&lt;br /&gt;&lt;br /&gt;Esas razones son el dar a conocer algunos puntos interesantes que son poco conocidos sobre la gripe y mostrar la asombrosa semejanza que el documental del 2005 guarda con la realidad actual. Una de las revelaciones que llamó más mi atención es que no existen suficientes antivirales para todos los seres humanos en caso de presentarse una nueva pandemia de gripe aguda, y esto es por la sencilla razón de que hasta la fecha los gobiernos no se han propuesto financiar una masiva y necesaria fabricación de tales medicamentos. Como lo dice uno de los entrevistados, parecen estar más interesados en otras cosas.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/5LZ8NYwpnfo&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/5LZ8NYwpnfo&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-0jqRyKgMbY&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/-0jqRyKgMbY&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/SKe-RN7rDrE&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/SKe-RN7rDrE&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/t7bEAJp2LB4&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/t7bEAJp2LB4&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/c-WwdMKsDfg&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/c-WwdMKsDfg&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Esperemos que esta pandemia potencial no pase de ser un conato, que alguna muy buena validación le aplique un temprano &lt;em&gt;Exit&lt;/em&gt;.  Sin olvidar el hecho de que nuestras precauciones individuales determinarán cuándo ocurrirá esa salida.&lt;/p&gt;&lt;p&gt;Un abrazo por escrito (para evitar contagios).&lt;/p&gt;&lt;p&gt;Al González. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-6649829009812180014?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/6649829009812180014/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/04/pandemia-de-gripe.html#comment-form' title='17 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6649829009812180014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6649829009812180014'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/04/pandemia-de-gripe.html' title='Pandemia de gripe'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-873008894079376556</id><published>2009-04-06T00:38:00.007-05:00</published><updated>2009-04-17T12:10:19.581-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Format con argumentos opcionales'/><category scheme='http://www.blogger.com/atom/ns#' term='comparar sin acentos'/><category scheme='http://www.blogger.com/atom/ns#' term='ghFormatOptional'/><category scheme='http://www.blogger.com/atom/ns#' term='GHFStrings'/><category scheme='http://www.blogger.com/atom/ns#' term='ghFormatStr'/><category scheme='http://www.blogger.com/atom/ns#' term='manejo de cadenas'/><category scheme='http://www.blogger.com/atom/ns#' term='ghInc'/><category scheme='http://www.blogger.com/atom/ns#' term='ghEqualStrs'/><category scheme='http://www.blogger.com/atom/ns#' term='ghEquals'/><category scheme='http://www.blogger.com/atom/ns#' term='Inc con Strings'/><title type='text'>Funciones de GH Freebrary.  Parte 3.- ghEquals, ghEqualStrs, ghFormatOptional, ghFormatStr y ghInc (unidad GHFStrings).</title><content type='html'>¡Hola de nuevo!&lt;br /&gt;&lt;br /&gt;Empiezo con un breve paréntesis para comentarles que ya tengo las fechas para las &lt;a href="http://rescatandoadelphi.blogspot.com/2009/03/en-guadalajara.html"&gt;asesorías de programación&lt;/a&gt; que daré en &lt;strong&gt;Guadalajara&lt;/strong&gt;, México. Serán los días &lt;strong&gt;25, 26 y 27 (sábado, domingo y lunes) de este mes de abril&lt;/strong&gt;. Espero alternar con varios de los lectores que viven o trabajan en esa maravillosa metrópoli y municipios cercanos. Aparte del trabajo que iré a realizar, sugiero que nos reunamos en grupo en alguna cafetería, escuela u oficina para hablar de los temas que nos inquietan como desarrolladores de software y, si se presta la ocasión, llevar a cabo un pequeño taller Delphi.&lt;br /&gt;&lt;br /&gt;Bien, a continuación les presento la tercera parte del tema &lt;em&gt;&lt;a href="http://rescatandoadelphi.blogspot.com/2008/12/funciones-de-gh-freebrary-parte-2.html"&gt;&lt;strong&gt;Funciones de GH Freebrary&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;, dándoles a conocer cinco funciones más para el manejo de cadenas de caracteres.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghEquals&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghEquals&lt;/strong&gt; (Const &lt;strong&gt;Value1&lt;/strong&gt;, &lt;strong&gt;Value2&lt;/strong&gt; :String; Const &lt;strong&gt;CompareType&lt;/strong&gt; :TghStrCompare = ghstcInsensitive) :Boolean; Overload;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Compara dos cadenas de caracteres (Value1 y Value2) y devuelve True si éstas son iguales, o False en caso contrario.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Dado el tipo de documento 'Cotización', verificamos si es "esencialmente", es decir, sin importar el tamaño de letras ni si lleva o no algún acento, lo mismo que 'COTIZACION' }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TipoDoc := 'Cotización';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;If ghEquals (TipoDoc, 'COTIZACION', ghstcEssential) Then&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghEqualStrs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghEqualStrs&lt;/strong&gt; (Const &lt;strong&gt;Values&lt;/strong&gt; :Array Of String; Const &lt;strong&gt;CompareType&lt;/strong&gt; :TghStrCompare = ghstcInsensitive) :Boolean;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve True si todas las cadenas de caracteres de un arreglo dado son iguales, o False en caso de que una o varias sean diferentes al resto.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Si el usuario introduce por tercera vez consecutiva el mismo código, sin importar el tamaño de letras }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;If ghEqualStrs ([CodAnt1, CodAnt2, Edit1.Text]) Then&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghFormatOptional&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghFormatOptional&lt;/strong&gt; (Const &lt;strong&gt;Format&lt;/strong&gt;, &lt;strong&gt;Param&lt;/strong&gt; :String) :String;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Permite dar formato a una cadena de caracteres llamando a la función nativa Format con los parámetros dados, pero sin dejar espacio alguno en la posición del argumento Param si éste es una cadena vacía.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Mostramos una ventana de mensaje indicando que no es correcto el valor del cuatro de texto Edit1, previendo que pueda tratarse de una cadena vacía }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ShowMessage (ghFormatOptional ('Es incorrecto el valor%*s, p&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;or favor verifique.', Edit1.Text));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Resultado cuando Edit1 tiene un valor de 100:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_9N_Agt_qWL4/SdmecOywjZI/AAAAAAAAAEE/pVq8XZ8qa-8/s1600-h/ghFormatOptional1.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5321458642559470994" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 254px; CURSOR: hand; HEIGHT: 110px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_9N_Agt_qWL4/SdmecOywjZI/AAAAAAAAAEE/pVq8XZ8qa-8/s400/ghFormatOptional1.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Resultado cuando Edit1 está vacío:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_9N_Agt_qWL4/SdmekUpkI7I/AAAAAAAAAEM/mMdF3eGtsc8/s1600-h/ghFormatOptional2.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5321458781570474930" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 233px; CURSOR: hand; HEIGHT: 110px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_9N_Agt_qWL4/SdmekUpkI7I/AAAAAAAAAEM/mMdF3eGtsc8/s400/ghFormatOptional2.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghFormatStr&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghFormatStr&lt;/strong&gt; (Const &lt;strong&gt;Format&lt;/strong&gt;, &lt;strong&gt;Str&lt;/strong&gt; :String) :String;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Da formato a una cadena de caracteres llamando a la función nativa Format con los parámetros proporcionados, pero devuelve una cadena vacía en caso de que ese sea el valor del argumento Str.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Establecemos una leyenda en la etiqueta Label1 indicando la calle con la que el domicilio hace esquina, pero solo si tal circunstancia ocurre }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Label1.Caption := ghFormatStr ('(esq. con %s)', CalleEsq);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghInc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghInc&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Inc&lt;/strong&gt; :Integer = 1) :String; Overload;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve la cadena de caracteres Value, incrementando en Inc unidades su parte final numérica. Si la cadena Value no termina en un dígito decimal, el resultado será equivalente a la expresión &lt;em&gt;Value + IntToStr (Inc)&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Dada la clave 'AT-07', obtenemos la que subsigue aritméticamente, o sea 'AT-08' }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Clave := 'AT-07';&lt;br /&gt;ClaveSig := ghInc (Clave);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;¿Qué opinan de estas cinco funciones y las 10 anteriores que describí? Toc, toc, ¿hay alguien ahí, o ya salieron todos de vacaciones? ;)&lt;/p&gt;&lt;p&gt;Un abrazo en primavera.&lt;/p&gt;&lt;p&gt;Al González. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-873008894079376556?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/873008894079376556/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/04/funciones-de-gh-freebrary-parte-3.html#comment-form' title='12 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/873008894079376556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/873008894079376556'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/04/funciones-de-gh-freebrary-parte-3.html' title='Funciones de GH Freebrary.  Parte 3.- ghEquals, ghEqualStrs, ghFormatOptional, ghFormatStr y ghInc (unidad GHFStrings).'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_9N_Agt_qWL4/SdmecOywjZI/AAAAAAAAAEE/pVq8XZ8qa-8/s72-c/ghFormatOptional1.JPG' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-3005171923615839622</id><published>2009-03-17T15:33:00.012-06:00</published><updated>2009-03-30T19:30:03.200-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aprendizaje'/><category scheme='http://www.blogger.com/atom/ns#' term='asesoría presencial'/><category scheme='http://www.blogger.com/atom/ns#' term='Guadalajara'/><category scheme='http://www.blogger.com/atom/ns#' term='profesor'/><category scheme='http://www.blogger.com/atom/ns#' term='taller Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='depuración de proyectos'/><title type='text'>Enseñando Delphi en Guadalajara</title><content type='html'>Esta entrada es para invitarlos a una serie de asesorías Delphi individuales que daré en la ciudad de Guadalajara, México, durante los próximos días.&lt;br /&gt;&lt;br /&gt;Explicaré temas relacionados con programación orientada a objetos, bases de datos, componentes, uso del depurador, opciones del IDE, directivas de compilación, ayudantes de clases (&lt;em&gt;class helpers&lt;/em&gt;) aplicaciones multi hilo, API de Windows, punteros, manejo de memoria, &lt;em&gt;buffers&lt;/em&gt;, &lt;em&gt;streams&lt;/em&gt;, RTTI, dbExpress, TClientDataSet, transacciones y concurrencia, DLLs, manejo adecuado de excepciones (Try-Finally, Try-Except), clonación de objetos, encadenamiento de eventos, tipos de datos, valores procedimentales (punteros a rutinas y &lt;em&gt;callbacks&lt;/em&gt;), archivos Ini, portapapeles, cuadros de diálogo, redondeo numérico, procesos Windows, sistema de archivos (rutas, directorios, extensiones), cadenas de caracteres, variantes, fechas y horas, moldeo de tipos (&lt;em&gt;type casting&lt;/em&gt;), sintaxis del lenguaje, mensajes del sistema operativo, establecimiento de ganchos (&lt;em&gt;hooks&lt;/em&gt;), clases interpuestas, manejo de bits y sus operadores (And, Or, Not, XOr, Shl, Shr), lenguaje ensamblador incrustado, emulación del teclado, registros con parte variante, automatización de Word y Excel, trucos y todo aquello que sea de inquietud para ustedes y no esté fuera de mi experiencia personal.&lt;br /&gt;&lt;br /&gt;El formato es simple: el asesorado me plantea una inquietud o caso (ya sea genérico o concreto, incluso de un proyecto real) y lo desarrollamos / resolvemos en mi computadora o en la suya. En ello veremos de forma práctica y bien explicada varios de los temas mencionados. El costo es de 300 pesos por hora efectiva. El aprendizaje está garantizado (la asesoría es gratis si la persona siente que no le resulta provechosa).&lt;br /&gt;&lt;br /&gt;Y, desde luego, les dejo una copia debidamente comentada de todo el código fuente escrito.&lt;br /&gt;&lt;br /&gt;Para mayores informes, comuníquense conmigo al teléfono &lt;strong&gt;&lt;span style="font-family:arial;"&gt;01 443 314-2467&lt;/span&gt;&lt;/strong&gt; o escríbanme al &lt;a href="mailto:algonzalez74@hotmail.com?subject=Asesor"&gt;&lt;strong&gt;correo&lt;/strong&gt;&lt;/a&gt; de costumbre. Daré algunos descuentos bajo condiciones particulares.&lt;br /&gt;&lt;br /&gt;Muy buen día.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;br /&gt;&lt;br /&gt;P.D. Próximamente lo repetiré en otras ciudades del país.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-3005171923615839622?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/3005171923615839622/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/03/en-guadalajara.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/3005171923615839622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/3005171923615839622'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/03/en-guadalajara.html' title='Enseñando Delphi en Guadalajara'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-1237616801274920366</id><published>2009-02-28T00:26:00.010-06:00</published><updated>2009-03-03T15:05:44.931-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='objetos patrón'/><category scheme='http://www.blogger.com/atom/ns#' term='Magia Data'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern objects'/><category scheme='http://www.blogger.com/atom/ns#' term='módulos de datos'/><category scheme='http://www.blogger.com/atom/ns#' term='clonación de objetos'/><category scheme='http://www.blogger.com/atom/ns#' term='data modules'/><category scheme='http://www.blogger.com/atom/ns#' term='TMagiaDataSource'/><category scheme='http://www.blogger.com/atom/ns#' term='TDataSource'/><category scheme='http://www.blogger.com/atom/ns#' term='data sets'/><category scheme='http://www.blogger.com/atom/ns#' term='cloning datasets'/><category scheme='http://www.blogger.com/atom/ns#' term='DataSetCloned'/><category scheme='http://www.blogger.com/atom/ns#' term='conjuntos de datos'/><title type='text'>El DataSource extendido.  Parte 1.</title><content type='html'>&lt;div align="left"&gt;¡Hola a todos!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.milindohuachi.com.mx/"&gt;Cheché&lt;/a&gt; ha elaborado otro video ilustrativo de los componentes que he venido desarrollando en los últimos años. En este caso se trata del componente &lt;strong&gt;TMagiaDataSource&lt;/strong&gt;, el cual forma parte de la suite &lt;a href="http://www.sistemasgh.com/"&gt;Magia Data&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/69x-bN6wGBo&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/69x-bN6wGBo&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;En términos francos, este componente viene a resolver dos antiguos problemas que durante años hemos tenido muchos programadores Delphi a la hora de crear algunas de nuestras aplicaciones de bases de datos. El video anterior muestra cómo el nuevo componente soluciona ambos problemas, pero intentaré describir éstos con detalle.&lt;br /&gt;&lt;br /&gt;Supongamos que dentro de un módulo de datos tenemos un componente &lt;em&gt;data set&lt;/em&gt; (en español &lt;em&gt;conjunto de datos&lt;/em&gt;), el cual puede ser de cualquier clase (TQuery, TTable, TIBQuery, TADOQuery, TClientDataSet, TpFIBDataSet, TMDOQuery, TkbmMemTable, TOraQuery, etc.) y queremos asociar ese conjunto de datos a los controles (componentes visuales) de un formulario. Para esto, normalmente agregamos un componente TDataSource que sirve como canal de comunicación entre el conjunto de datos y los controles de datos que están presentes en el formulario. El componente TDataSource puede ser colocado en el módulo de datos, junto al &lt;em&gt;data set&lt;/em&gt; asociado, o bien dentro del propio formulario.&lt;br /&gt;&lt;br /&gt;Hasta ahí todo es &lt;em&gt;RADmente&lt;/em&gt; bello, lo reconozco desde aquel glorioso otoño boreal de 1997 en que comencé a conocer Delphi. Pero analicemos las complicaciones que suelen surgir en la práctica.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Problema número 1: Los formularios tienden a “apropiarse” de los conjuntos de datos. &lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Si colocamos un componente conjunto de datos dentro de un &lt;em&gt;data module&lt;/em&gt; es porque pensamos centralizar dentro de ese contenedor la tabla, grupo de tablas o acción que representa el componente. De tal manera que quede disponible al uso que diferentes formularios y procesos quieran hacer de él. En términos de programación escrita, es como declarar una nueva constante o tipo de dato para que pueda ser utilizada por diferentes rutinas del programa, sin tener que repetir la declaración o valor literal de dicho elemento global en cada una de éstas, bastando una mera referencia a su nombre (identificador).&lt;br /&gt;&lt;br /&gt;Pero un conjunto de datos no es algo fijo, es un objeto con un montón de propiedades, métodos y eventos. Algo que puede cambiar conforme se le utiliza. Entonces diríamos que, en términos de programación escrita, más bien es como una variable global, y los formularios son como las rutinas que usan y modifican esa variable global.&lt;br /&gt;&lt;br /&gt;Sólo que existe una gran diferencia que carboniza a esa analogía. Una rutina que modifica el valor de una variable global lo hace &lt;em&gt;conscientemente&lt;/em&gt;, asumiendo que eso afectará a las demás rutinas que la empleen. Hay cierta armonía y respeto hacia la esencia de una variable global, ésta existe para ser un contenedor global de datos. Pero con frecuencia colocamos &lt;em&gt;data sets&lt;/em&gt; en el interior de un &lt;em&gt;data module&lt;/em&gt;, no para hacer de ellos unas especies de variables globales, sino para definirlos en un solo punto, estableciendo en tiempo de diseño las propiedades y eventos que deberán observar los conjuntos de datos cuando vayan a ser utilizados por algún proceso o formulario.&lt;br /&gt;&lt;br /&gt;El código asociado a un formulario suele parametrizar, abrir y cerrar conjuntos de datos, cambiando varias de sus propiedades, como Active, Params, ReadOnly, IndexFieldNames, Filter, Filtered, etc. Es un formulario particular que altera a un objeto globalmente definido. ¿Qué debe hacer un formulario así antes de cerrar, cuando ya ha terminado de trabajar con el conjunto de datos? ¿Debe dejarlo tal cual está? &lt;em&gt;Deberá cerrarlo&lt;/em&gt;, dirán algunos. Correcto, ¿pero que hay de todas aquellas propiedades y parámetros que el formulario ya le estableció o modificó al componente? ¿Abandonamos la playa cual &lt;em&gt;spring breaker&lt;/em&gt;?&lt;br /&gt;&lt;br /&gt;En muchas ocasiones, si hay libertad de abrir por segunda vez el formulario (creando una nueva instancia o simplemente haciéndolo visible), éste o su código debe contemplar que el conjunto de datos (que se encuentra en un &lt;em&gt;data module&lt;/em&gt;) pudo sufrir modificaciones anteriormente. ¿Acaso el formulario debe deshacer esas modificaciones antes de empezar a usar el conjunto de datos, o debería deshacerlas al terminar de usarlo, digamos, al destruirse la instancia del formulario? De ahí surge la idea de que a veces sería conveniente que cada vez que un formulario se creara o abriera, los conjuntos de datos que utiliza se pusieran en automático tal como fueron definidos en tiempo de diseño.&lt;br /&gt;&lt;br /&gt;Una salida falsa es remover el &lt;em&gt;data set&lt;/em&gt; del módulo de datos y colocarlo dentro del propio formulario. Así cada vez que se cree una instancia del formulario obtendremos también una nueva instancia del conjunto de datos, tal como fue definido en tiempo de diseño. Pero ésta no es una solución efectiva porque a la larga terminamos “involucionando” (en Delphi 1 no existían los &lt;em&gt;data modules&lt;/em&gt;). Al hacer eso, nuestro conjunto de datos deja de ser un objeto globalmente definido, ya no es algo que esté elegantemente disponible para toda la aplicación. Si después agregamos otros formularios que necesiten del mismo conjunto de datos, terminaremos con varias copias de éste regadas por todos lados. Y un mal sueño se materializará cuando haya que hacerles algún cambio, por modificaciones a la estructura de una tabla, al formato de despliegue de algunos de sus campos, etc.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;No nos perdamos, los conjuntos de datos viven mejor en los módulos de datos.&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Pero la responsabilidad inherente a que un formulario modifique algunos parámetros o propiedades del conjunto de datos es sólo la arista de un gran cubo de hielo. Hay algo todavía más gordo: a veces necesitamos usar la misma tabla o consulta en dos puntos distintos de la aplicación, pero simultáneamente. Eso es común con formularios múltiples no modales que presentan información extraída con la misma consulta SQL, pero estableciendo parámetros o filtros distintos. Naturalmente, esto no es viable mediante el uso de un solo &lt;em&gt;data set&lt;/em&gt;. Y aún en casos más sencillos, donde se quiera o se tolere que dos o más formularios abiertos muestren el mismo &lt;em&gt;cursor&lt;/em&gt;, resulta que la navegación en uno de los formularios afectará a lo que el otro esté mostrando (imagine, por ejemplo, que hay una rejilla en cada uno, y el usuario cambia de fila en una de ellas; la otra rejilla también cambiará).&lt;br /&gt;&lt;br /&gt;Ante esto, otra salida falsa es acompañar a cada instancia de un formulario con una instancia particular de un módulo de datos que contenga solo los &lt;em&gt;data sets&lt;/em&gt; que el formulario requiera. A mediano plazo, la aplicación terminará con una cantidad de módulos de datos difícil de administrar y mantener, duplicando en tiempo de diseño muchos conjuntos de datos (algo que se buscaba evitar) y complicando las relaciones entre ellos. O habrá quien sacrifique una buena cantidad de memoria creando nuevas instancias de un gran módulo de datos, para formularios que solamente utilizan un par de &lt;em&gt;data sets&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Estas dos salidas falsas van en dirección a lo que sería un modelo ideal, pero no lo consiguen. Ese modelo consiste en que un conjunto de datos pueda ser definido en tiempo de diseño en un solo punto global, pero que en tiempo de ejecución puedan crearse tantas &lt;em&gt;copias locales&lt;/em&gt; de él como resulte necesario. Es decir, que el conjunto de datos definido en tiempo de diseño sea un objeto &lt;em&gt;patrón&lt;/em&gt;, del cual puedan crearse &lt;em&gt;clones&lt;/em&gt; en tiempo de ejecución.&lt;br /&gt;&lt;br /&gt;Pues, señores, eso es lo que obtenemos con la propiedad &lt;strong&gt;&lt;u&gt;DataSetCloned&lt;/u&gt;&lt;/strong&gt; del componente TMagiaDataSource. Me cito a mi mismo con este texto de la &lt;a href="http://www.sistemasgh.com/magiadatasource.php"&gt;referencia técnica&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="font-family:trebuchet ms;"&gt;En tiempo de ejecución, cuando esta propiedad tiene un valor de True, el componente toma el conjunto de datos que tenga o sea asignado a la propiedad DataSet, y crea una copia del mismo. Todas las propiedades, eventos y campos definidos del primer conjunto de datos serán establecidos de igual manera en el objeto clon. Y éste será el nuevo conjunto de datos asignado al componente. Esto permite establecer en tiempo de diseño varias fuentes de datos apuntando al mismo conjunto de datos, pero logrando que en tiempo de ejecución cada una use un objeto distinto para evitar conflictos entre formularios o procesos. Es una excelente alternativa a la tradicional y molesta solución de establecer dos o más conjuntos de datos similares en tiempo de diseño, para satisfacer necesidades que podrían tener conflicto si emplearan el mismo componente de datos. Su valor predeterminado es False.&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;Como se observa en el video, hay dos formularios que muestran datos, cada uno con un componente TMagiaDataSource en su interior, los cuales están enlazados al mismo conjunto de datos &lt;em&gt;patrón&lt;/em&gt; en tiempo de diseño (sus propiedades DataSet apuntan al mismo objeto). Pero se les ha puesto la propiedad DataSetCloned en True para que en tiempo de ejecución cada formulario opere con su propia consulta. O sea que cada DataSource usará realmente un clon del objeto asignado en la propiedad DataSet.&lt;br /&gt;&lt;br /&gt;En la siguiente entrada describiré el segundo problema y cómo es resuelto con la otra nueva propiedad del componente (DataSetEvents). Por lo pronto el video de arriba les habrá dado una idea de las grandes ventajas logradas con ambas.&lt;br /&gt;&lt;br /&gt;Un abrazo extendiendo a Delphi.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-1237616801274920366?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/1237616801274920366/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/02/el-datasource-extendido-parte-1.html#comment-form' title='8 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1237616801274920366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/1237616801274920366'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/02/el-datasource-extendido-parte-1.html' title='El DataSource extendido.  Parte 1.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-8451216726604940045</id><published>2009-01-17T22:27:00.004-06:00</published><updated>2009-01-17T23:47:20.876-06:00</updated><title type='text'>La historia entendible de Palestina</title><content type='html'>&lt;strong&gt;&lt;em&gt;Palestina - Historia De Una Tierra&lt;/em&gt;&lt;/strong&gt;. Otro de esos grandes documentales que valen la pena ser rescatados de la ciberjungla.&lt;br /&gt;&lt;br /&gt;Después de haber visto en su totalidad esta obra de aproximadamente dos horas de duración, creo que guarda un enorme valor histórico por sus explicaciones coherentes e ilustradas de los hechos políticos y demográficos ocurridos en el pueblo palestino, desde los últimos años del &lt;a href="http://es.wikipedia.org/wiki/Imperio_Otomano"&gt;Imperio Otomano&lt;/a&gt; hasta el fin de la &lt;a href="http://es.wikipedia.org/wiki/Guerra_Fr%C3%ADa"&gt;Guerra Fría&lt;/a&gt;. En ella aparecen fotografías y filmaciones exquisitas, dignas de cualquier biblioteca, testimonios de la vida palestina en más de cien años de injusticia e inconformidad sociales, y retratos vivos de muchos líderes internacionales en el momento mismo de sus más célebres declaraciones.&lt;br /&gt;&lt;br /&gt;Esta producción de &lt;a href="http://es.wikipedia.org/wiki/France_3"&gt;France 3&lt;/a&gt; y &lt;a href="http://www.pointdujour-international.fr/"&gt;Point du Jour&lt;/a&gt;, titulada &lt;strong&gt;&lt;em&gt;Palestine: histoire d'une terre&lt;/em&gt;&lt;/strong&gt;, es por sí misma un llamado a equilibrar la Historia, para no terminar olvidando parte de los hechos más importantes del siglo XX. Su difusión me parece culturalmente obligada, y ya sabemos que a los programadores Delphi, por lo general, no nos gusta quedarnos atrás en estas cuestiones. Vamos siempre en búsqueda de la verdad científica de las cosas, y no nos conformamos con usar &lt;em&gt;While&lt;/em&gt; todo el tiempo a sabiendas de que existe &lt;em&gt;Repeat&lt;/em&gt;. Al final de la narración, Simone Bitton y Jean-Michel Meurice causan un hondo respiro de comprensión en los espectadores de su brillante trabajo.&lt;br /&gt;&lt;br /&gt;El fanatismo es uno de los peores enemigos de las personas, y es imposible que dos personas fanáticamente antagónicas convivan en el mismo espacio. Es imperioso desechar ciertas posturas y creencias radicales y poco constructivas, para lograr vivir en paz al lado de quien piensa distinto.&lt;br /&gt;&lt;br /&gt;NOTA: Hay un pequeño “&lt;em&gt;bug&lt;/em&gt;” matemático en uno de los subtítulos. Asumo que se trató de un error en la traducción, pero si alguien tiene sus oídos entrenados en el idioma francés, le agradecería me confirmara lo anterior. ;)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Parte 1&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/kqpzVlNzl3g&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/kqpzVlNzl3g&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/wZP46BsXRZM&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/wZP46BsXRZM&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/628GRLepigQ&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/628GRLepigQ&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/PEuPSQGmlew&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/PEuPSQGmlew&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/pu7i2U3-Du8&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/pu7i2U3-Du8&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/zh_O63VEtC4&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/zh_O63VEtC4&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Parte 2&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-EVRPcMDQZ0&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/-EVRPcMDQZ0&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/UTKJg5Q6PmY&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/UTKJg5Q6PmY&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/LSx6di-NY3w&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/LSx6di-NY3w&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ea8kzJsMzmQ&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/ea8kzJsMzmQ&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/IkMH2uoUgiY&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/IkMH2uoUgiY&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/gvvUmLpyBGQ&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/gvvUmLpyBGQ&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Un abrazo rescatando hechos.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-8451216726604940045?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/8451216726604940045/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/01/la-historia-entendible-de-palestina.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8451216726604940045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8451216726604940045'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2009/01/la-historia-entendible-de-palestina.html' title='La historia entendible de Palestina'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-2587078132944218430</id><published>2008-12-26T03:12:00.013-06:00</published><updated>2009-04-06T01:53:39.421-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ghCount'/><category scheme='http://www.blogger.com/atom/ns#' term='ghCorrelStr'/><category scheme='http://www.blogger.com/atom/ns#' term='GHFStrings'/><category scheme='http://www.blogger.com/atom/ns#' term='ghCopy'/><category scheme='http://www.blogger.com/atom/ns#' term='ghCountTo'/><category scheme='http://www.blogger.com/atom/ns#' term='manejo de cadenas'/><category scheme='http://www.blogger.com/atom/ns#' term='GH Freebrary'/><category scheme='http://www.blogger.com/atom/ns#' term='ghCased'/><title type='text'>Funciones de GH Freebrary.  Parte 2.- ghCased, ghCopy, ghCorrelStr, ghCount y ghCountTo (unidad GHFStrings).</title><content type='html'>&lt;a href="http://rescatandoadelphi.blogspot.com/2008/11/funciones-de-gh-freebrary-parte-1.html"&gt;Lo prometido&lt;/a&gt; es deuda.&lt;br /&gt;&lt;br /&gt;He comenzado a redactar una especie de manual de bolsillo sobre las funciones contenidas en GH Freebrary. Decidí iniciar con las que son para el manejo de cadenas de caracteres, las cuales pertenecen a la unidad &lt;strong&gt;GHFStrings&lt;/strong&gt;. En breve incluiré dicho manual en el &lt;a href="http://www.sistemasgh.com/zonadedescargas.php"&gt;paquete de descarga&lt;/a&gt; de la biblioteca, y conforme vaya agregando más información en el mismo publicaré el nuevo material en esta bitácora también.&lt;br /&gt;&lt;br /&gt;En sus marcas, ¿listos? ¡fuera!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCased&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCased&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Upper&lt;/strong&gt; :Boolean) :String; Overload;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Convierte una cadena de caracteres al tamaño de letras indicado por el parámetro Upper (True = mayúsculas, False = minúsculas).&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Aseguramos que el nombre de una tabla esté en minúsculas sólo cuando la base de datos sea MySQL, en mayúsculas para los demás casos }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TableName := ghCased (TableName, Not (Server = 'MySQL'));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCased&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCased&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;ACase&lt;/strong&gt; :TEditCharCase) :String; Overload;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Convierte una cadena de caracteres al tamaño de letras indicado por el parámetro ACase (ecNormal, ecUpperCase, ecLowerCase). Si ACase es ecNormal, devuelve la cadena dada tal como está.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Asignamos a la variable Leyenda la palabra "nombre" seguida por el texto contenido en Edit1, todo bajo el tamaño de letras restringido de Edit1 para darle uniformidad }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Leyenda := ghCased ('Nombre: ', Edit1.CharCase) + Edit1.Text;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCased&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCased&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt;, &lt;strong&gt;Sample&lt;/strong&gt; :String) :String; Overload;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Convierte una cadena de caracteres al tamaño de letras que tenga otra cadena (parámetro Sample). Si la cadena de muestra Sample tiene letras de ambos tamaños (mayúsculas y minúsculas), devuelve la cadena Value tal como está.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Aseguramos que el texto de Edit2 esté bajo el mismo tamaño de letras que el texto de Edit1 }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Edit2.Text := ghCased (Edit2.Text, Edit1.Text);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCopy&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCopy&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;StartIndex&lt;/strong&gt; :Integer) :String; Overload;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;De una cadena de caracteres dada, devuelve la subcadena que va desde la posición StartIndex hasta el último carácter.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Obtenemos el tipo de un componente sin el prefijo "T" de su clase }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CompType := ghCopy (Component.ClassName, 2);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCopy&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCopy&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;StartIndex&lt;/strong&gt;, &lt;strong&gt;EndIndex&lt;/strong&gt; :Integer) :String; Overload;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;De una cadena de caracteres dada, devuelve la subcadena que va desde la posición StartIndex hasta la posición EndIndex.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Dado el código "DE-97124/A2", obtenemos el número contenido en él desde la posición 4 hasta antes del sufijo "/A2", considerando que el número y ese sufijo pueden ser de longitud variable. }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Code := 'DE-97124/A2';&lt;br /&gt;Number := ghCopy (Code, 4, Pos ('/', Code) - 1);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCorrelStr&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCorrelStr&lt;/strong&gt; (Const &lt;strong&gt;Values&lt;/strong&gt; :Array Of String; Const &lt;strong&gt;Str&lt;/strong&gt; :String; Const &lt;strong&gt;CompareType&lt;/strong&gt; :TghStrCompare = ghstcInsensitive) :String;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;De un arreglo de pares de cadenas de caracteres (Values), dada la cadena Str, devuelve la cadena que hace par con ella dentro del arreglo, es decir, su cadena correlativa. Devuelve como resultado la propia cadena Str si ésta no se encuentra dentro del arreglo Values.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Obtenemos el nombre del producto asociado al fabricante HK-Software (IBExpert) }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Product := ghCorrelStr (['DT/Studio', 'Embarcadero', 'IBExpert', 'HK-Software', 'Magia Data', 'Sistemas GH'], 'HK-SOFTWARE');&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCount&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCount&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Chr&lt;/strong&gt; :Char; Const &lt;strong&gt;StartIndex&lt;/strong&gt; :Integer = 1; &lt;strong&gt;EndIndex&lt;/strong&gt; :Integer = MaxInt) :Integer; Overload;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve el número de veces que aparece el carácter Chr dentro de la cadena Value, desde la posición StartIndex hasta la posición EndIndex.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Si la clave del libro no lleva cuatro guiones }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;If ghCount (ISBN, '-') &lt;&gt; 4 Then&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCount&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCount&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Chrs&lt;/strong&gt; :TSysCharSet; Const &lt;strong&gt;StartIndex&lt;/strong&gt; :Integer = 1; &lt;strong&gt;EndIndex&lt;/strong&gt; :Integer = MaxInt) :Integer; Overload;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve el número de veces que aparece alguno de los caracteres del conjunto Chrs dentro de la cadena Value, desde la posición StartIndex hasta la posición EndIndex.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Si el código contiene operadores matemáticos }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;If ghCount (Code, ['+', '-', '*', '/']) &gt; 0 Then&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCountTo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCountTo&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Chr&lt;/strong&gt; :Char; Const &lt;strong&gt;EndIndex&lt;/strong&gt; :Integer) :Integer; Overload;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve el número de veces que aparece el carácter Chr dentro de la cadena Value, desde el inicio de la misma hasta la posición EndIndex.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Obtenemos la cantidad de nombres de campos puestos y separados por punto y coma en la variable FieldNames, sin contar el punto y coma que se dejó al final de la cadena }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FieldNames := 'ID;FirstName;LastName;';&lt;br /&gt;FieldCount := ghCountTo (FieldNames, ';', Length (FieldNames) - 1) + 1;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ghCountTo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Declaración que tiene:&lt;/u&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Function &lt;strong&gt;ghCountTo&lt;/strong&gt; (Const &lt;strong&gt;Value&lt;/strong&gt; :String; Const &lt;strong&gt;Chrs&lt;/strong&gt; :TSysCharSet; Const &lt;strong&gt;EndIndex&lt;/strong&gt; :Integer) :Integer; Overload;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Descripción corta:&lt;/u&gt;&lt;br /&gt;Devuelve el número de veces que aparece alguno de los caracteres del conjunto Chrs dentro de la cadena Value, desde el inicio de la misma hasta la posición EndIndex.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo de uso:&lt;/u&gt;&lt;br /&gt;{ Obtenemos la cantidad de operaciones matemáticas de esta fórmula, descartando el texto que inicia con "//" }&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Formula := '((A + B) / C) - D // Precio especial';&lt;br /&gt;Ops := ghCountTo (Formula, ['+', '-', '*', '/'], Pos ('//', Formula) - 1);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Espero que esta breve enumeración haya sido de su agrado e interés. Seguiré describiendo más funciones de la unidad GHFStrings en las próximas entregas. Admito que estas descripciones son breves, apenas para un manual de bolsillo, pero es un primer paso en la documentación de &lt;a href="http://rescatandoadelphi.blogspot.com/2008/08/qu-es-gh-freebrary.html"&gt;GH Freebrary&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;No dejen de transmitirme sus opiniones. Sus comentarios son muy valiosos para mejorar lo que esta bitácora ofrece por medio de mis teclado y pensamiento. Me ofrezco a contestar todas las dudas que tengan respecto al uso de estas y otras funciones de la biblioteca.&lt;br /&gt;&lt;br /&gt;Un abrazo encadenado.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-2587078132944218430?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/2587078132944218430/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/12/funciones-de-gh-freebrary-parte-2.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2587078132944218430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/2587078132944218430'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/12/funciones-de-gh-freebrary-parte-2.html' title='Funciones de GH Freebrary.  Parte 2.- ghCased, ghCopy, ghCorrelStr, ghCount y ghCountTo (unidad GHFStrings).'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-6103034178062024587</id><published>2008-11-30T02:41:00.005-06:00</published><updated>2009-01-11T14:54:18.065-06:00</updated><title type='text'>Funciones de GH Freebrary.  Parte 1.- Introducción.</title><content type='html'>Como algunos amigos recordarán, el pasado verano boreal relaté la &lt;a href="http://rescatandoadelphi.blogspot.com/2008/08/qu-es-gh-freebrary.html"&gt;entrañable historia&lt;/a&gt; de una obra cuya construcción se ha convertido en una de mis mayores motivaciones profesionales desde la adolescencia. GH Freebrary (antes Interfaz GH) es una vasta colección de funciones Object Pascal surgida con el propósito de hacer más fácil la programación de aplicaciones. Ayuda a que el código fuente de éstas sea conciso, adaptable y consistente, además de escribirlo en menos tiempo y con menor esfuerzo mental. El fin crucial de toda biblioteca de programación.&lt;br /&gt;&lt;br /&gt;Desde que subí los fuentes a la página de &lt;a href="http://www.sistemasgh.com/"&gt;Sistemas GH&lt;/a&gt;, hace unos cuatro meses, GH Freebrary ha sido descargada ¡más de 150 veces! No tengo una idea clara de quiénes, para qué y cómo la estén usando, cosas que por supuesto me gustaría saber (ahí les encargo ;)), pero me sorprende y congratulo por la cantidad de descargas que han tenido estos archivos .pas, ya que una de mis pequeñas contribuciones técnicas comienza a ser reconocida.&lt;br /&gt;&lt;br /&gt;Todas estas rutinas fueron escritas y actualizadas por un servidor a lo largo de 17 años de programación en Delphi (empezando cuando éste se llamaba Turbo Pascal). Y ahora me dispongo a enumerarlas mediante una serie de entradas que iré publicando en esta bitácora a lo largo de varias semanas. De esta forma ayudaré un poco a su comprensión y aprovechamiento por parte de los colegas, en lo que el tiempo me da permiso de elaborar una formal y más fecunda guía de la biblioteca.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;¿Han usado expresiones regulares a la hora de hacer una búsqueda entre sentencias de código?&lt;/strong&gt; Los invito a hacer el siguiente ejercicio junto conmigo:&lt;br /&gt;&lt;br /&gt;Abran alguno de sus proyectos Delphi en el IDE, de preferencia uno grande o si gustan ese con el que vienen trabajando hace varias semanas. No se preocupen, no les pediré que modifiquen nada. Vamos a hacer algo más interesante.&lt;br /&gt;&lt;br /&gt;Cargado el proyecto en el IDE, asegúrense de tener activo el editor de código abriendo cualquiera de las unidades del proyecto. Ahora presionen la combinación de teclas Ctrl+F. Aparecerá una pequeña ventana de diálogo titulada &lt;em&gt;Find Text&lt;/em&gt;. Se trata de una poderosísima herramienta de búsqueda integrada en el IDE que poca gente aprovecha de verdad para buscar cosas en el código con descarada precisión. Este cuadro de diálogo también puede ser abierto con la opción de menú &lt;em&gt;Search\Find&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Como pueden observar, contiene dos pestañas tituladas &lt;em&gt;Find&lt;/em&gt; y &lt;em&gt;Find in Files&lt;/em&gt;. Presionemos Ctrl+Tab para pasarnos a la segunda de esas pestañas. En el cuadro de texto asociado a la leyenda &lt;em&gt;Text to find&lt;/em&gt; introduzcamos la siguiente expresión tal como la pongo yo en seguida:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;[^A-Z,a-z]gh[A-Z]+&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Marquemos las opciones &lt;em&gt;Case sensitive&lt;/em&gt; y &lt;em&gt;Regular expressions&lt;/em&gt;, y asegurémonos de dejar seleccionado el botón de radio &lt;em&gt;Search all files in project&lt;/em&gt; y desmarcada la opción &lt;em&gt;Whole words only&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Hemos preparado una búsqueda. Pero antes de presionar el botón &lt;em&gt;OK&lt;/em&gt; les explicaré a grandes rasgos qué es lo que vamos a buscar. Le hemos dicho a Delphi que vamos a buscar una &lt;a href="http://en.wikipedia.org/wiki/Regular_expression#Syntax"&gt;expresión regular estándar&lt;/a&gt; en todas las unidades integradas al proyecto. En el texto que escribimos, los corchetes, el acento circunflejo, el guión, la coma, el signo de más y las letras a y zeta se tomarán como caracteres especiales que le ayudarán al buscador a hacer su trabajo. Hemos indicado que busque, en los archivos de código fuente del proyecto, todas las combinaciones de texto que incluyan al par de letras minúsculas “&lt;em&gt;gh&lt;/em&gt;”, seguidas por al menos una letra mayúscula —“&lt;em&gt;[A-Z]+&lt;/em&gt;”— y precedidas por cualquier carácter que no sea otra letra —“&lt;em&gt;[^A-Z,a-z]&lt;/em&gt;“—.&lt;br /&gt;&lt;br /&gt;Ahora sí, presionemos el botón &lt;em&gt;OK&lt;/em&gt; del cuadro de diálogo para ver qué nos encuentra. Si el lector es ya un usuario de GH Freebrary, es probable que le aparezca como resultado una pequeña lista de todas las líneas de código del proyecto donde el programa está llamando a una función de mi humilde acervo programático. Le hemos ordenado al buscador de Delphi que encuentre todas las referencias a identificadores que lleven el prefijo &lt;em&gt;gh&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;No es casual que todas las funciones de GH Freebrary lleven este prefijo. Es una convención con cierto arraigo entre los programadores el prefijar los identificadores de sus bibliotecas con algunas letras que simbolicen su pertenencia a ellas. De esta forma se evitan conflictos por ambigüedad entre identificadores de funciones y clases nativas y aquellos que son de terceras partes, y en general entre fabricantes de bibliotecas de programación y entre componentes de objetivo común. Claro, la búsqueda que hicimos no es del todo perfecta, ya que Delphi además podría encontrar referencias a otros identificadores de programa que llevasen el mismo prefijo sin ser de GH Freebrary, o bien comentarios o constantes String de contenido coincidente. Pero sin duda el soporte de expresiones regulares en la &lt;a href="http://www.google.com/codesearch"&gt;búsqueda de código fuente&lt;/a&gt; es estupendo (iba a escribir &lt;em&gt;la hostia&lt;/em&gt; :D).&lt;br /&gt;&lt;br /&gt;El proyecto que tengo abierto ahora tiene 73 unidades particulares, es decir, sin considerar las plantillas comunes de herencia visual y otras clases del framework que compartimos entre proyectos. Es una aplicación para medición y cobranza del consumo de agua, cuya primera etapa esperamos mis colaboradores y yo terminar este año. Dentro de esas 73 unidades, Delphi encontró 93 referencias a funciones de GH Freebrary. Como pueden argüir entonces, no sólo recomiendo a mis colegas el uso de esta biblioteca gratuita, sino que además y primeramente la empleo en mis propios desarrollos. De hecho todas y cada una de las funciones de esta colección surgieron y fueron probadas en algún proyecto real, desde los programas que me pedían elaborar algunos estudiantes de último grado de ingeniería cuando yo apenas terminaba la carrera vocacional, pasando por mi antiguo sistema de gestión y punto de venta, las aplicaciones de control de peaje que todavía utiliza el gobierno en algunas carreteras de Chihuahua, componentes a medida que me han pedido varios desarrolladores y los propios como &lt;a href="http://www.sistemasgh.com/magiadoc.php"&gt;Magia Doc&lt;/a&gt; y &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;Magia Data&lt;/a&gt;, hasta esta aplicación comercial que esperamos agrade a varios municipios durante los próximos años.&lt;br /&gt;&lt;br /&gt;Para constancia de lo dicho, aquí una copia simplificada de los resultados obtenidos en mi búsqueda anterior:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;200): Result := ghVar (ghConcatenada ([Str ('CalleNombre'), Str (&lt;br /&gt;200): Result := ghVar (ghConcatenada ([Str ('CalleNombre'), Str (&lt;br /&gt;201): 'NumeroExterior') + ghPrefixed (Str ('NumeroInterior'), '-'),&lt;br /&gt;202): ghPrefixed (Str ('ColoniaNombre'), 'colonia ')]));&lt;br /&gt;248): ghEquals (TRecSeragu (Mediciones.LastRec).Periodo, APeriodo) Then&lt;br /&gt;280): If ghEquals (APeriodoAnterior, APeriodo) Then&lt;br /&gt;288): If Not ghEquals (APeriodoAnterior, Incrementado (APeriodo, -1)) Then&lt;br /&gt;356): Agua := Importe + ghMultiply (Consumo - ConsumoPiso,&lt;br /&gt;360): Alcantarillado := ghPercent (Agua, PorcentajeAlcantarillado, 2)&lt;br /&gt;365): Saneamiento := ghPercent (Agua, PorcentajeSaneamiento, 2)&lt;br /&gt;373): IVA := ghPercent (Subtotal, PorcentajeIVA, 2);&lt;br /&gt;392): Result := ghIncUnits (APeriodo, 1, 12, Incremento);&lt;br /&gt;404): With ghDate (Valor) Do&lt;br /&gt;414): Result := ghUnits (APeriodo, 1, 12);&lt;br /&gt;446): Result.PeriodoInicial := ghMax (PeriodoInicial, PeriodoSuspension);&lt;br /&gt;447): Result.PeriodoFinal := ghMin (Incrementado (PeriodoFinal),&lt;br /&gt;660): If Not ghEquals (Consumo.PeriodoInicial, Periodo) Then&lt;br /&gt;980): If (ghPosStr (['Solicitud', 'Presupuesto', 'Contrato', 'Padron',&lt;br /&gt;984): NumeroExterior := ghSeparadaUltima (Values);&lt;br /&gt;986): If ghEsEntero (NumeroExterior) Then&lt;br /&gt;987): Result := VarArrayOf ([ghSinFin (Values,&lt;br /&gt;995): If (ghPosStr (['MedicionConsumo', 'PeriodoFacturacion'], Entity) &gt;&lt;br /&gt;996): -1) And (ghPosStr (['AoPeriodoMinimo', 'AoPeriodoMaximo'], Field) &gt;&lt;br /&gt;261): FacturarContrato (ID, ghTwoInts (PeriodoInicial, AoInicial),&lt;br /&gt;262): ghTwoInts (PeriodoFinal, AoFinal));&lt;br /&gt;295): With ghDate (Fecha) Do&lt;br /&gt;310): Result.Low := StrToInt (ghFinDigitos (Cadena));&lt;br /&gt;321): Result := ghIncUnits (Ao, Numero, 1, PeriodoMayor (), Incremento);&lt;br /&gt;404): Result := (ghUnits (AoFinal, NumeroFinal, 1, Mayor) -&lt;br /&gt;405): ghUnits (AoInicial, NumeroInicial, 1, Mayor)) + 1;&lt;br /&gt;428): If ghEquals (Table + '.' + Field, 'Contrato.IDTarifa') Then&lt;br /&gt;377): //{} Text := ghPesosMayusculas(dtPagosReporteTOTAL.AsCurrency) ;&lt;br /&gt;61): ghAbort ('Datos incompletos','Debe capturar al menos una categoría.',grEntry);&lt;br /&gt;71): ghEnable ([lbPrint, lbDelete], ((ActiveView = vwPago) And&lt;br /&gt;103): If ghAsk ('Cancelar pago',&lt;br /&gt;71): ghAbort ('Datos incompletos','Debe capturar al menos un subconcepto de obra.',grEntry);&lt;br /&gt;428): ghAbort ('Datos incompletos','Debe capturar al menos una tarifa.',&lt;br /&gt;432): If ghFloat (vwEntry.DataController.Summary.FooterSummaryValues [0]) &lt;&gt;&lt;br /&gt;434): ghAbort ('Datos incorrectos',&lt;br /&gt;59): ghAbort ('Dato inválido',&lt;br /&gt;209): ghEnable ([lbFacturar, lbNotificarAdeudo],&lt;br /&gt;213): ghEnable([lbPrint],&lt;br /&gt;252): { With ghCursorSavePoints.Save (crHourGlass) Do&lt;br /&gt;268): ghInform ('Facturación terminada', 'Se facturaron ' +&lt;br /&gt;283): (* ghCursorSavePoints.Save (crHourGlass);&lt;br /&gt;303): ghInform ('Notificación de adeudos terminada',&lt;br /&gt;313): ghCursorSavePoints.Last.Restore;&lt;br /&gt;463): RejillaActiva := TcxGrid (FindComponent ('gr' + ghLeftOf (ghCopy&lt;br /&gt;463): RejillaActiva := TcxGrid (FindComponent ('gr' + ghLeftOf (ghCopy&lt;br /&gt;477): RejillaActiva := TcxGrid (ghContenedor (TcxGrid)) ;&lt;br /&gt;731): ghShowStop ('Alerta', 'Imposible eliminar registro pagado',&lt;br /&gt;764): ghAbort ('Datos incompletos','Debe capturar al menos un detalle de la factura.');&lt;br /&gt;786): ghShowStop ('Importes diferentes', 'El total de pagos es MENOR al total de la factura.');&lt;br /&gt;796): ghShowStop ('Importes diferentes', 'El total de pagos es MAYOR al total de la factura.');&lt;br /&gt;131): ghAbort ('Fecha incorrecta', 'Revise la fecha', edFechaEntrega);&lt;br /&gt;136): ghAbort ('Fecha incorrecta', 'Revise la fecha', edFechaEjecucion);&lt;br /&gt;141): ghAbort ('Fecha incorrecta', 'Revise la fecha', edFechaFuerzaPublica);&lt;br /&gt;146): ghAbort ('Fecha incorrecta', 'Revise la fecha', edFechaEstado);&lt;br /&gt;151): ghAbort ('Fecha incorrecta', 'Revise la fecha', edFechaRemate); }&lt;br /&gt;129): ghAbort ('Datos incompletos',&lt;br /&gt;137): ghAbort ('Dato faltante', 'Si la orden ya fue ejecutada debe ' +&lt;br /&gt;254): ghInform ('Tipo de queja no especificado',&lt;br /&gt;499): If ghEnRango (dmServidor.CurrentDate,&lt;br /&gt;545): (* Adeudo := ghFloat (&lt;br /&gt;547): ghFloat (&lt;br /&gt;552): Total := ghFloat (&lt;br /&gt;554): ghFloat (&lt;br /&gt;576): ghShowStop ('Cantidad inválida',&lt;br /&gt;580): If ghAsk ('Confirmar cantidad',&lt;br /&gt;586): dsEntry ['Importe'] := ghFloat (&lt;br /&gt;620): ghInform ('Pago registrado', 'El pago ha sido registrado. ' +&lt;br /&gt;341): dsDetail['PorcentajeServicios'] := ghPorcentaje (&lt;br /&gt;345): dsDetail['PorcentajeRecargos'] := ghPorcentaje (&lt;br /&gt;349): dsDetail['PorcentajeMultas'] := ghPorcentaje (&lt;br /&gt;353): dsDetail['PorcentajeGastos'] := ghPorcentaje (&lt;br /&gt;489): { Descuentos [0] := ghFloat (&lt;br /&gt;493): { Descuentos [1] := ghFloat (&lt;br /&gt;497): { Descuentos [2] := ghFloat (&lt;br /&gt;501): { Descuentos [3] := ghFloat (&lt;br /&gt;509): ghCadena (I = 0, 'Importe') + Conceptos [I]).AsCurrency Then&lt;br /&gt;513): ghAbort ('Descuentos inválidos',&lt;br /&gt;516): dsFactura.DataSet.FindField (ghCadena (I = 0, 'Importe') +&lt;br /&gt;149): ghAbort ('Datos incompletos', 'Debe especificar al menos una partida.',&lt;br /&gt;192): ghPercent100 (DetailRec.Float ('IVA'),&lt;br /&gt;203): dsDetail.SetQuiet ('IVA', ghDivide (DetailRec ['Importe'] *&lt;br /&gt;207): ghPercent100 (DetailRec.Float ('IVA'),&lt;br /&gt;68): ghAbort ('Datos incompletos','Debe capturar al menos un detalle de la tarifa.',grEntry);&lt;br /&gt;63): Clave := ghSinEspacios (ghSinFin (tbConceptosClave.Value, '0'));&lt;br /&gt;63): Clave := ghSinEspacios (ghSinFin (tbConceptosClave.Value, '0'));&lt;br /&gt;65): If dsConceptoObra.DataSet.Locate ('Nombre', ghUpperFirst (&lt;br /&gt;74): ghUpperFirst (AnsiLowerCase (tbConceptosConcepto.Value));&lt;br /&gt;82): ghSinEspacios (tbSubconceptosClave.Value);&lt;br /&gt;84): ghUpperFirst (AnsiLowerCase (tbSubconceptosConcepto.Value));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Como podrán notar, todavía tengo algunas funciones que no he traducido al idioma inglés (lo voy haciendo poco a poco y más o menos una vez al mes subo una actualización a la Web).&lt;br /&gt;&lt;br /&gt;Lo que sigue es empezar a ilustrar cada una de las funciones de la biblioteca. ¡Cómo me gustaría contar con los recursos suficientes para crear una referencia tan buena como la ayuda de Delphi 7! De momento tendré que conformarme con una sencilla enumeración de las funciones, donde explique brevemente la declaración y uso de éstas a partir de la siguiente entrada. No obstante les solicito que vayan enviándome desde ahora sus sugerencias, dudas e inquietudes sobre este tema, a través del sistema de comentarios de esta bitácora o si prefieren por correo electrónico (“algonzalez” y luego “74” [at]correocalienteperoeninglés[punto]com).&lt;br /&gt;&lt;br /&gt;Antes de despedirme, dos noticias:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1.&lt;/strong&gt; Muy pronto estará lista la versión de GH Freebrary para Delphi 2007 y de ahí el salto a Delphi 2009 tendrá escasa demora. Estén pendientes.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2.&lt;/strong&gt; Esta semana que comienza inicia &lt;a href="http://conferences.codegear.com/coderage08"&gt;CodeRage III&lt;/a&gt;. Del lunes al viernes habrá exposiciones muy interesantes y en español sobre Delphi y otras tecnologías de desarrollo de Embarcadero. Espero poder asistir a algunas de ellas y tener el placer de saludarlos.&lt;br /&gt;&lt;br /&gt;Ahora sí me despido, sólo por unos días.&lt;br /&gt;&lt;br /&gt;Un abrazo útil encontrado.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-6103034178062024587?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/6103034178062024587/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/11/funciones-de-gh-freebrary-parte-1.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6103034178062024587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6103034178062024587'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/11/funciones-de-gh-freebrary-parte-1.html' title='Funciones de GH Freebrary.  Parte 1.- Introducción.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-3029911203753792591</id><published>2008-10-28T22:49:00.003-06:00</published><updated>2008-10-29T00:41:33.225-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='historia bancaria'/><category scheme='http://www.blogger.com/atom/ns#' term='dinero'/><category scheme='http://www.blogger.com/atom/ns#' term='banqueros'/><category scheme='http://www.blogger.com/atom/ns#' term='funcionamiento sistema monetario'/><category scheme='http://www.blogger.com/atom/ns#' term='sistema bancario'/><category scheme='http://www.blogger.com/atom/ns#' term='bancos'/><category scheme='http://www.blogger.com/atom/ns#' term='préstamos'/><category scheme='http://www.blogger.com/atom/ns#' term='crédito'/><category scheme='http://www.blogger.com/atom/ns#' term='historia monetaria'/><category scheme='http://www.blogger.com/atom/ns#' term='intereses'/><category scheme='http://www.blogger.com/atom/ns#' term='creación de dinero'/><category scheme='http://www.blogger.com/atom/ns#' term='usura'/><category scheme='http://www.blogger.com/atom/ns#' term='dinero como deuda'/><title type='text'>¿Cómo funciona el sistema monetario?</title><content type='html'>Lo primero que se preguntará el lector es «&lt;em&gt;¿Qué diablos tiene que ver eso con Delphi? ¿Desde cuándo Al anda con temas de economía? ¿O acaso se trata de un programa de software para convertir importes a diferentes divisas?&lt;/em&gt;» Pero antes de que cambien el canal de su navegador, o se levanten de la silla para observar a través de la ventana si ya inició el fin del mundo, déjenme decirles que he encontrado un estupendo video de cinco partes que describe con peras, manzanas, plátanos y hasta naranjas cómo opera el actual sistema monetario de la mayoría de los países. Con ilustraciones muy claras que lo hacen fácil de entender y una narración amable, objetiva y carente de tendencias ideológicas.&lt;br /&gt;&lt;br /&gt;Siento que vale mucho la pena darlo a conocer, ya que la mayoría de las personas suelen ignorar cómo funcionan los principales mecanismos de la economía, por considerarlos confusos y demasiado complejos. Yo, en lo personal, vengo hace tiempo interesándome en los asuntos que tienen que ver con la economía en general, porque me importa comprender dónde están los puntos malos que originan tanta desigualdad en los niveles de bienestar y de qué manera podría contribuir a mejorar el sistema en el que vivimos.&lt;br /&gt;&lt;br /&gt;Dejo claro que este material que encontré, y que ahora me percato ha sido dado a conocer en muchos otros sitios serios de la Red, está muy lejos de ser uno de esos seudodocumentales o falsos testimonios de estilo apocalíptico, esquizofrénico, paranoico, conspirativo e hipocondríaco que algunos usan para sentir y hacer sentir protagonismo espontáneo y que detrás de una vida rutinaria y aburrida se encuentra oculto un paraíso de verdades asombrosas. Fantasear es bueno en muchas ocasiones, pero hay quienes se afanan en pulverizar la verdad comprobada con hipótesis tergiversadas, y eso es lo que no procede en un mundo que pretende civilizarse.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Money as Debt&lt;/em&gt;&lt;/strong&gt; es un audaz reportaje del canadiense &lt;a href="http://paulgrignon.netfirms.com/MoneyasDebt/ProducersComments.html"&gt;Paul Grignon&lt;/a&gt;, en el cual explica con sencillas animaciones cómo nació y evolucionó nuestro sistema bancario y el manejo que le damos al dinero en los países del llamado &lt;em&gt;libre mercado&lt;/em&gt;. Aborda de una manera serena y convincente las inevitables consecuencias que acarrea un sistema monetario tan frágil como el de Estados Unidos de América y otros países. En él podemos observar con luz de cenit cómo es que llegan a quebrar los bancos, la manera en que éstos se relacionan con el gobierno y de qué forma juntos afectan la vida de las personas. La deuda es el elemento primario del documental y me atrevo a asegurar que, después de verlo, más de uno lo pensará dos veces antes de volver a solicitar un crédito.&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/cNeTIcDyP0A&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed src="http://www.youtube.com/v/cNeTIcDyP0A&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/yUkUFMkVSQ0&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed src="http://www.youtube.com/v/yUkUFMkVSQ0&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/TZ1vR33SX3s&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed src="http://www.youtube.com/v/TZ1vR33SX3s&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/J0ulEJazwjg&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed src="http://www.youtube.com/v/J0ulEJazwjg&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/B88-BDWPl8o&amp;amp;hl=es&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x234900&amp;amp;color2=0x4e9e00"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed src="http://www.youtube.com/v/B88-BDWPl8o&amp;hl=es&amp;fs=1&amp;rel=0&amp;color1=0x234900&amp;color2=0x4e9e00" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Un abrazo sin intereses.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-3029911203753792591?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/3029911203753792591/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/10/cmo-funciona-el-sistema-monetario.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/3029911203753792591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/3029911203753792591'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/10/cmo-funciona-el-sistema-monetario.html' title='¿Cómo funciona el sistema monetario?'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7973154167480774572</id><published>2008-09-29T12:52:00.003-05:00</published><updated>2008-09-29T14:23:19.636-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='universidades'/><category scheme='http://www.blogger.com/atom/ns#' term='Delphi 2009'/><category scheme='http://www.blogger.com/atom/ns#' term='Embarcadero'/><category scheme='http://www.blogger.com/atom/ns#' term='CodeGear'/><category scheme='http://www.blogger.com/atom/ns#' term='actualizaciones'/><category scheme='http://www.blogger.com/atom/ns#' term='Gopac'/><category scheme='http://www.blogger.com/atom/ns#' term='México'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows XP'/><category scheme='http://www.blogger.com/atom/ns#' term='presentación'/><category scheme='http://www.blogger.com/atom/ns#' term='evento'/><category scheme='http://www.blogger.com/atom/ns#' term='tipos genéricos'/><category scheme='http://www.blogger.com/atom/ns#' term='Delphi 7'/><title type='text'>Presentación de Delphi 2009 en Guadalajara.  Lo que se dijo dentro y fuera del evento.</title><content type='html'>Como muchos saben, los días 3 y 4 de septiembre de 2008 se llevó a cabo, por parte de Embarcadero Technologies (su división CodeGear, para ser más precisos), la presentación de Delphi 2009. Una versión más de la potente herramienta de programación que ha dado tanto material qué escribir en foros y bitácoras Web como vida a tantas aplicaciones de software exitosas. El día 3 en Guadalajara, la mañana siguiente en Ciudad de México.&lt;br /&gt;&lt;br /&gt;Esta vez tuve oportunidad de asistir a la primera de las dos presentaciones gracias a la amable invitación de los organizadores. Desafortunadamente llegué hasta la hora en que David I. terminaba su intervención sobre las novedades de C++ Builder (ahora sé que la Fuente Olímpica está muy, pero muy lejos de Plaza Galerías y que el &lt;em&gt;Pretrén&lt;/em&gt; se paga con importe exacto). La sala de cine donde se llevó a cabo el encuentro estaba prácticamente llena, pareciéndome un lugar muy atinado para dar demostraciones de software multitudinarias ya que estos lugares están diseñados para mantener la atención del público sobre lo que se proyecta en pantalla.&lt;br /&gt;&lt;br /&gt;Acomodado en mi butaca, con una camiseta negra extra grande (supongo que ya no había de otro tamaño) y la acostumbrada hoja de comentarios en mano, además del aparato de traducción conectado a mis oídos poco entrenados en el idioma inglés, inició la sesión de preguntas y respuestas con David, la cual duraría entre cinco y diez minutos. Enseguida vendría Andreano Lanusse con el plato fuerte por el que asistieron la mayoría esa mañana al encuentro de Avenida Vallarta: las novedades de Delphi 2009.&lt;br /&gt;&lt;br /&gt;Realmente se están esforzando por incluir en cada nueva versión cosas que son importantes para los desarrolladores, pero es algo incómodo reconocer que el mercado ya no está recibiéndolas con el aprecio que comúnmente se le daba en los años noventas a cada nueva versión de un producto de software. Este fenómeno tiende a materializarse con el software de paga que ha alcanzado cierto nivel de sofisticación y calidad, como por ejemplo Windows XP y Delphi 7. En el caso del primero Microsoft supo con tiempo lo que pasaría si no lograban que la siguiente versión fuera radicalmente diferente: la gente simplemente no cambiaría su estable, suficiente y cómodo XP por uno que fuese 90% igual. Así que decidieron arriesgarse intentando inventar un nuevo tipo de rueda, con las catastróficas consecuencias que ya todos conocemos del golpeado Windows Vista.&lt;br /&gt;&lt;br /&gt;Borland y el ahora CodeGear de Embarcadero no quisieron correr ese mismo riesgo con Delphi. Es demasiado lo que está en juego y pocas las oportunidades de corregir el rumbo en caso de equivocarse tecnológicamente. Borland estuvo cerca de perderlo todo con Delphi 8 y 2005; CodeGear fue la válvula de escape que se creó para comenzar a rescatarlo. Y desde la versión 2007 optaron por retomar la sensata y conservadora postura de 99.9% de compatibilidad hacia atrás, añadiendo novedades importantes sólo habiéndolas analizado concienzudamente, ya sin grandes precipitaciones. Medida inteligente, sin duda, pero poco agresiva para una compañía a la que le urge capitalizarse y reposicionar a Delphi. No obstante, tengo razones para pensar que ya se estudia en California la posibilidad de hacer algunas grandes reformas a la VCL. Recordemos que muchas de las clases conservan aún la misma estructura general que Borland les dio en los tiempos del Paradox, cuando los programadores éramos un gremio subterráneo y los ratones tenían bolita.&lt;br /&gt;&lt;br /&gt;No hablaré en esta entrada de qué es lo que creo que debería hacerse para captar mayores recursos y colocar a Delphi en los primeros lugares. Espero que algunas de las sugerencias que he entregado durante el último año y medio ya estén siendo revisadas por una o varias personas de Embarcadero, y confío en que de todo el planeta les estarán llegando muchas otras aportaciones que nacen del corazón mismo de los desarrolladores que queremos ver a Delphi cual enorme es. El resto de la entrada será para enumerar algunas de las características que fueron incorporadas en Delphi 2009 y dar a conocer varios apuntes interesantes.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Soporte Unicode. Pensando en que podamos exportar nuestras aplicaciones a mercados europeos y asiáticos sin problemas con los diferentes idiomas de esas regiones.&lt;/li&gt;&lt;li&gt;Explorador de Clases. Con el cual podemos examinar visualmente las jerarquías de clases y los miembros de éstas. La rama de una clase puede ser visa hacia sus derivados o hacia sus ancestros.&lt;/li&gt;&lt;li&gt;Nuevas opciones de proyecto.&lt;/li&gt;&lt;li&gt;Nuevo administrador de proyectos (&lt;em&gt;Project Manager&lt;/em&gt;) con directorios y subdirectorios de archivos de código fuente.&lt;/li&gt;&lt;li&gt;Búsqueda incremental filtrante en la localización de componentes.&lt;/li&gt;&lt;li&gt;Se incluye gratis la suite de componentes de terceros InfoPower, si la compra se hace antes del 1 de octubre. En esto de las ofertas siguen fallando. Considero que la validez de esta promoción debió extenderse, al menos en México, hasta el 15 de diciembre para que realmente fuese ponderara por el público. Menos de 30 días para aprovechar la oferta hubiese sido poco incluso para la suite DevExpress. Y no porque valgan poco estas bibliotecas de componentes, sino por la habitual resistencia a las actualizaciones que comenté en los primeros párrafos aunada al tiempo que un micro empresario mexicano necesita para asegurar capital y realizar una compra en estos días.&lt;/li&gt;&lt;li&gt;Se está trabajando de manera coordinada con los principales fabricantes de componentes de terceros para que éstos incluyan sin grandes dificultades el soporte Unicode (nos aseguraron que habrá un &lt;em&gt;QuantumGrid&lt;/em&gt; Unicode por parte de Developer Express).&lt;/li&gt;&lt;li&gt;El procedimiento Exit ahora puede recibir como parámetro el valor a devolver, haciendo con esto las veces de un típico &lt;em&gt;return&lt;/em&gt; de lenguaje C. Esto nos ahorrará muchos &lt;em&gt;Begins&lt;/em&gt; y &lt;em&gt;Ends&lt;/em&gt; en las salidas rápidas de nuestras rutinas.&lt;/li&gt;&lt;li&gt;Nuevos métodos en TObject (y por lo tanto disponibles en todas las clases): UnitName, Equals, GetHashCode, ToString.&lt;/li&gt;&lt;li&gt;Nuevo componente TCategoryPanelGroup. Grupo de paneles colapsables contenedores de controles, con imágenes que se alternan conforme se pasa el cursor por encima.&lt;/li&gt;&lt;li&gt;Soporte para imágenes de formato PNG.&lt;/li&gt;&lt;li&gt;Componente TImageList mejorado para soportar imágenes de mayor tamaño.&lt;/li&gt;&lt;li&gt;Nuevo componente TButtonedEdit. Cuadro de texto con botón(es), al cual pueden definírsele imágenes y eventos específicos para los botones izquierdo y derecho.&lt;/li&gt;&lt;li&gt;Nuevo componente TLinkLabel. Etiqueta de texto con capacidad HTML para presentar, dentro de nuestros formularios, hipervínculos que ejecuten acciones.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Balloom Hints&lt;/em&gt;. Comentarios emergentes que pueden incluir gráficos en su interior y más estéticos que los tradicionales.&lt;/li&gt;&lt;li&gt;La lista de elementos de un componente TListView ahora puede dividirse en grupos, pudiéndose establecer la imagen a usar para los grupos, además de la imagen usada para los elementos.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Ribbon Controls&lt;/em&gt;. Son controles muy coquetos, al estilo de las últimas versiones de Microsoft Office. No sé mucho al respecto porque yo sigo satisfecho con Office 2000, pero son útiles para acceder rápidamente a las opciones de una barra de herramientas, por ejemplo. Desafortunadamente se necesita una especie de licencia por parte de Microsoft para su integración en las aplicaciones que desarrollemos.&lt;/li&gt;&lt;li&gt;Tipos genéricos. Es la capacidad de indeterminar o abstraer el tipo de dato que una clase maneja en algunos de sus puntos, con el fin de poder usar dicha clase abiertamente con valores de diferentes tipos. Esta es una de las características que personalmente me parecen más interesantes debido a mi arraigado interés en la evolución del lenguaje Pascal (quién fuera a decir que se otorgaría un segundo uso a los caracteres “&lt;” y “&gt;” además de ser operadores).&lt;/li&gt;&lt;li&gt;Métodos anónimos. Son rutinas de código sin nombre identificador que pueden ser escritas entre las sentencias de otras rutinas, con el fin de ejecutarlas dos o más veces por medio de una variable de referencia. Una alternativa al uso de subrutinas que me gustaría estudiar con detalle.&lt;/li&gt;&lt;li&gt;En cuanto a DataSnap, ya no se utiliza COM para comunicación entre las capas y se incluyeron nuevos métodos para hacer llamadas al servidor de aplicaciones. Además se pueden observar en el inspector de objetos los métodos y parámetros exportados por el servidor de aplicaciones, algo que me parece muy práctico.&lt;/li&gt;&lt;li&gt;Un dato interesante de InterBase 2009 es que incluye criptografía de campos. De manera opcional, cada campo de una tabla puede ser codificado para que sólo ciertos usuarios tengan acceso visual a su contenido. Esto no me hará abandonar a Firebird, pero reconozco que es una buena característica del nuevo InterBase.&lt;/li&gt;&lt;/ul&gt;Como saben, esta fue la primera presentación de Delphi en Latinoamérica desde que Embarcadero lo adquirió. Una buena señal de confianza para México hubiese sido que al evento acudiera algún ejecutivo o ingeniero de Embarcadero, pero no fue así. Durante la sesión final de preguntas y respuestas pregunté si dentro de esa sala se encontraba alguna persona que llevara cierto tiempo trabajando en Embarcadero pero que no formara parte del equipo de CodeGear creado por Borland. Se sintió un bochorno generalizado en todo el lugar mientras los presentadores trataban de responder con decoro a mi atrevida pero válida pregunta. Lisa Flores finalmente aclaró que hasta el día anterior sí había estado en Guadalajara tal persona, pero que ya no había podido quedarse a la presentación. Me agradó la honestidad de esta respuesta, aunque los asistentes habrán valorado a su propio juicio la importante ausencia.&lt;br /&gt;&lt;br /&gt;En esa misma sesión de intercambio verbal con el público, sugerí a Andreano que analizaran la posibilidad de hacer las presentaciones un poco más tarde, para darle oportunidad a los asistentes foráneos de llegar a tiempo. Amablemente dio a entender que lo estudiarían. Y le pregunté si existía la posibilidad de que lleguemos a ver una licencia de Delphi, edición Professional, a precio competitivo de 500 USD, pero el espíritu de su respuesta fue «&lt;em&gt;mmm, no lo sé, es poco probable&lt;/em&gt;».&lt;br /&gt;&lt;br /&gt;Posteriormente, en los pasillos del edificio, varios colegas y yo charlamos un buen rato con Raúl Gómez, el director de Gopac, e intercambiamos puntos de vista respecto a las estrategias que el distribuidor oficial está poniendo en práctica para aumentar el uso de Delphi en México. Entre los puntos más interesantes revelados me gustaría destacar los siguientes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Embarcadero autorizó, después de largas negociaciones, que Gopac pueda vender Delphi a las universidades mexicanas bajo un esquema especial que les permita a éstas adquirirlo con facilidad y usarlo tanto para enseñanza como para sus propios desarrollos internos. Raúl ha estado supervisando personalmente la nueva estrategia a seguir con las universidades y colegios vocacionales y se muestra muy convencido de tener éxito en la misma. Esto realmente es esperanzador.&lt;/li&gt;&lt;li&gt;A través de este distribuidor Delphi podrá ser adquirido a crédito, ya no sólo con American Express, sino también con tarjetas de crédito de al menos dos o tres bancos nacionales. Comentó que las negociaciones con dichos bancos están muy avanzadas y que es casi un hecho lo anterior.&lt;/li&gt;&lt;li&gt;Gopac está en proceso de certificar a un empleado suyo por cada herramienta de CodeGear. Lo que me preocupa de este punto es que la persona correspondiente a Delphi resulte un consultor de altos vuelos y desconozca, por ejemplo, las ventajas de que el método TObject.NewInstance sea virtual. Ojalá resulte ser un verdadero apasionado por la programación, Pascal, Delphi y su historia. Le externé esta preocupación a Raúl (necesitan contar con un hombre o mujer fuerte en Delphi para defender y apuntalar el avance de sus estrategias).&lt;/li&gt;&lt;/ul&gt;Sin duda creo que valió mucho la pena asistir al encuentro, dándome gusto saludar ahí a Víctor, Ulices, Álvaro, Salvador, José, Ramiro y otros colegas.&lt;br /&gt;&lt;br /&gt;Envío un agradecimiento especial a Gopac por todas las facilidades prestadas.&lt;br /&gt;&lt;br /&gt;Un abrazo 2009.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7973154167480774572?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7973154167480774572/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/09/presentacin-de-delphi-2009-en.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7973154167480774572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7973154167480774572'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/09/presentacin-de-delphi-2009-en.html' title='Presentación de Delphi 2009 en Guadalajara.  Lo que se dijo dentro y fuera del evento.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-8140176162937275642</id><published>2008-08-02T01:55:00.013-05:00</published><updated>2008-12-26T04:22:01.954-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='la obra de mi vida'/><category scheme='http://www.blogger.com/atom/ns#' term='GH Freebrary'/><category scheme='http://www.blogger.com/atom/ns#' term='Interfaz GH'/><title type='text'>¿Qué es GH Freebrary?</title><content type='html'>Una soleada tarde de 1991, después de clases, me dirigí a la librería &lt;em&gt;La Prensa&lt;/em&gt; que en aquel entonces se encontraba en la calle Libertad, en Chihuahua. Estaba ansioso por buscar un libro de Turbo Pascal que me explicara una inquietante relevación hecha por mi profesor de &lt;em&gt;Lógica de Programación&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Durante la mañana de ese día, en los pasillos de la escuela, le había planteado lo siguiente:&lt;br /&gt;&lt;br /&gt;—Profe’, verá, en varios de los programas que hacemos utilizamos algunos procedimientos y funciones que creamos desde las primeras lecciones. Yo mismo he ido creando algunos procedimientos adicionales para cosas que hago con frecuencia en mis programas. El problema es que cada vez que creo un programa, tengo que hacerlo a partir de uno anterior para tener siempre disponibles todas mis rutinas de utilería. Sé que puedo marcar en el editor de Turbo Pascal un bloque de texto y guardarlo con Ctrl+K+W y luego cargarlo en otro archivo con Ctrl+K+R, pero finalmente no dejamos de repetir código. ¿Hay alguna forma de que no tengamos que repetir el código de las rutinas de utilería en cada programa que hagamos?&lt;br /&gt;&lt;br /&gt;—La hay, en Pascal existe algo llamado &lt;em&gt;unidades&lt;/em&gt;, es la solución para eso que planteas —respondió el profesor cuyo apellido lamentablemente no recuerdo.&lt;br /&gt;&lt;br /&gt;Las manos me sudaban al entrar al establecimiento, la ansiedad por descubrir el secreto de las unidades aumentaba conforme me acercaba al área de publicaciones informáticas. Y ahí estaba un libro, no recuerdo el título, pero hablaba de Turbo Pascal y sus bondades; entre ellas, el uso de las palabras reservadas &lt;em&gt;Unit&lt;/em&gt; y &lt;em&gt;Uses&lt;/em&gt;. No disponía de dinero para comprarlo —habría de transcurrir un año más para comprar el único libro de programación que he adquirido en mi vida—. En esta ocasión me limité a hojearlo frente al estante; más que eso, me puse a leerlo ahí mismo, como quien mira un televisor a través del cristal de la tienda donde lo exhiben. Estaba haciendo uso de una librería como si fuese una biblioteca (lo sé, ¡olímpica ironía mutante!). Estuve alrededor de una hora con las pupilas devorando texto, tratando de memorizar cada concepto, técnica y ejemplo que leía acerca de las unidades del Turbo. El lector debe tener en cuenta que la Internet no era una cosa muy popular que digamos en 1991, así que la mayor parte del conocimiento técnico lo adquiríamos en la escuela y a través de los libros, dos medios poco accesibles en aquél lugar y en aquella época para un estudiante de bajos recursos.&lt;br /&gt;&lt;br /&gt;De ahí surgieron, en alguna computadora del laboratorio de cómputo de la escuela, dos semillas llamadas MTR.PAS y MAR.PAS, mis dos primeras unidades de funciones reutilizables. ¿Quieren ver algo de ese antiguo código? Aquí unas muestras:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_9N_Agt_qWL4/SJQJcvU_kyI/AAAAAAAAAB0/cEkREYkhyMk/s1600-h/AntiguoCodigo01.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5229815456629494562" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_9N_Agt_qWL4/SJQJcvU_kyI/AAAAAAAAAB0/cEkREYkhyMk/s400/AntiguoCodigo01.JPG" border="0" /&gt;&lt;/a&gt;&lt;a href="http://bp0.blogger.com/_9N_Agt_qWL4/SJQKhij05nI/AAAAAAAAACM/ieBMdie2JmY/s1600-h/AntiguoCodigo04.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5229816638613022322" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_9N_Agt_qWL4/SJQKhij05nI/AAAAAAAAACM/ieBMdie2JmY/s400/AntiguoCodigo04.JPG" border="0" /&gt;&lt;/a&gt; &lt;a href="http://bp3.blogger.com/_9N_Agt_qWL4/SJQKV9VCAHI/AAAAAAAAACE/KeSB5TQog3U/s1600-h/AntiguoCodigo03.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5229816439640293490" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_9N_Agt_qWL4/SJQKV9VCAHI/AAAAAAAAACE/KeSB5TQog3U/s400/AntiguoCodigo03.JPG" border="0" /&gt;&lt;/a&gt;&lt;a href="http://bp1.blogger.com/_9N_Agt_qWL4/SJQKK8xU5cI/AAAAAAAAAB8/1mSIwlIPVfs/s1600-h/AntiguoCodigo02.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5229816250511975874" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_9N_Agt_qWL4/SJQKK8xU5cI/AAAAAAAAAB8/1mSIwlIPVfs/s400/AntiguoCodigo02.JPG" border="0" /&gt;&lt;/a&gt; ¡Misericordia, tan sólo era un muchacho de 16 años!&lt;br /&gt;&lt;br /&gt;El siguiente semestre vimos más acerca de Pascal, y en las lecciones el empleo de la cláusula &lt;em&gt;Uses&lt;/em&gt; para referirse a unidades propias era algo más cotidiano. Los profesores les llamaban “&lt;em&gt;librerías&lt;/em&gt;”, así que también yo comencé a llamarles de esa equivocada manera. Pero los mejores momentos estaban por venir. Para el último año en el CONALEP, cuando mi obsesión por el desarrollo de software (si es que hacer programas donde jugaba con los caracteres ASCII podía llamarse &lt;em&gt;desarrollo de software&lt;/em&gt;) alcanzaba el grado de hacerme faltar a las clases de Historia, Cobol y Contabilidad, y privarme de comprender a plenitud el cálculo integral en las clases de Matemáticas, mi “&lt;em&gt;librería&lt;/em&gt;” de funciones alcanzaba varias decenas de rutinas que entonces me eran muy útiles en la versión 6 del lenguaje. Una mañana de gran inspiración, durante vacaciones de invierno, entré en hipotermia mientras aporreaba teclas en una máquina del laboratorio de cómputo. Pero aún así me sentía afortunado de que el profesor a cargo me hubiera confiado las llaves por varios días en los que fui sin falta a la desolada escuela, a pesar del terrible viento de hielo que cortaba la piel y que formaba estalactitas en las orillas de los techos. Las instalaciones se encontraban en un descampado típico de las llanuras norteamericanas, en lo que entonces era casi la orilla norte de la ciudad de Chihuahua, zona que siempre ha sido más fría que el acogedor centro.&lt;br /&gt;&lt;br /&gt;Terminé mis estudios como &lt;em&gt;Profesional Técnico en Programación y Análisis de Sistemas&lt;/em&gt;, mas no hice el trabajo de fin de cursos. Salvé mediante exámenes extraordinarios las materias que había reprobado, como Cobol y Contabilidad y no sé qué otra, pero no me titulé ni mucho menos asistí a las ceremonias y al baile de graduación. Las cosas no andaban bien en casa como para gastar más dinero en mí, lo rechazaba. Además la rebeldía y aparente autosuficiencia de mi carácter ahuyentaban a quienes se interesaban en apoyarme de algún modo, y por si fuera poco atravesaba por una profunda depresión emocional que casi me lleva a darme de baja en los últimos meses de la carrera.&lt;br /&gt;&lt;br /&gt;Pero quería seguir programando en Turbo Pascal, así que cuando ya no estudiaba en aulas comencé a estudiar en casa, practicando el uso de &lt;em&gt;Turbo Vision&lt;/em&gt; con la versión 7. Ahí fueron mis primeros encuentros reales con la POO. Pasé muchas horas en la habitación que ahora es de mi madre escribiendo y probando código, mucho código, con la primera computadora que tuve, una 8088 de segunda mano que mi hermano Antonio había comprado...¡adivinen donde!: en la tienda que hace un mes me contactó para solicitar el desarrollo de un sistema de software, motivo por el cual vine en esta ocasión a mi tierra natal —¡el mundo y sus vueltas!—. Y mucho de ese código iba a parar a funciones reutilizables y muy atomizadas (la atomicidad dispara al máximo tal reusabilidad) dentro de mi joven biblioteca de rutinas. No recuerdo con precisión si fue en esta época o hasta entrar en el mundo Delphi, cuando me enteré con sorpresa que el término correcto para denominar a estas colecciones de rutinas es &lt;em&gt;biblioteca&lt;/em&gt; (&lt;em&gt;library&lt;/em&gt;) y no &lt;em&gt;librería&lt;/em&gt; (&lt;em&gt;book&lt;/em&gt; &lt;em&gt;store&lt;/em&gt;). Hoy en día hay menos dudas al respecto, los autores más respetados, y que a su vez se dignan en respetar el idioma español, emplean en sus publicaciones el término &lt;em&gt;biblioteca&lt;/em&gt;. Viéndose, por el contrario, el uso del término &lt;em&gt;librería&lt;/em&gt; como una falta de cultura.&lt;br /&gt;&lt;br /&gt;A finales de 1997 convertí mi biblioteca a Delphi 1, retirando a un gran número de procedimientos y funciones que eran obsoletos para la plataforma Windows, y seguí alimentándola con nuevas rutinas de código que escribía durante los desarrollos que hacía. Para entonces el estilo de mi código fuente había mejorado mucho y se parecía más al que hoy día manejo; durante años fui perfeccionándolo. Lo interesante es que todas esas funciones surgieron de necesidades reales durante los proyectos de software donde participaba. Ya desde el siglo pasado quería compartir mis rutinas con otros programadores para que las emplearan en sus aplicaciones y se facilitaran el trabajo de construir éstas. Pero me creé una estúpida barrera yo mismo al negarles acceso al código fuente, entregándoles solamente los archivos .dcu (mi estimado amigo Emilio Muñoz tal vez recuerde un breve desencuentro al respecto). Entonces pasaba por mi mente la idea de que mi código era tan bueno que nadie o casi nadie más merecía tocarlo —típico signo de inmadurez en algunos desarrolladores jóvenes—.&lt;br /&gt;&lt;br /&gt;Pero desde que establecí el foro Web PDM (cuyo objetivo, por cierto, parece haberse cumplido ya), en el verano boreal de 2002, decidí distribuir con todo y código fuente mi vasta, nada documentada y amada biblioteca de funciones Delphi, bajo el nombre de &lt;em&gt;Interfaz GH&lt;/em&gt;. Con más de mil rutinas de propósito general, estimo que a la fecha es utilizada por varias decenas de desarrolladores, principalmente de América; aunque la gran mayoría de ellos utiliza sólo unas cuantas de las funciones, por la aún carente documentación. No obstante, me provoca orgullo saber que he puesto en manos de muchos estudiantes y profesionistas una herramienta que es cuando menos útil en sus labores, contribuyendo de paso al fortalecimiento de Delphi. Un diamante diminuto en el arenal de buenas acciones.&lt;br /&gt;&lt;br /&gt;El punto crucial de esta historia es que hace tres años decidí hacerle una reforma importante a Interfaz GH: cambiar los nombres de todos sus elementos por identificadores más amigables, ya que hasta entonces empleaba a rajatabla un estricto y fatal estilo de cuatro letras por palabra en los identificadores (cinco cuando se trataba de la primera palabra del nombre de una rutina). Lo sé, andaba yo muy &lt;em&gt;robotizado&lt;/em&gt;. Llevar a cabo este cambio con cientos de funciones y sus variables representaba todo un reto. Pero ahí no para la cosa. Unos cuantos meses después de iniciar esa reforma terminé de convencerme de una gran verdad dentro del desarrollo de software: &lt;strong&gt;el código fuente de todas las bibliotecas de programación públicas del universo debe estar en un único idioma&lt;/strong&gt; (y de hecho algún día estarán en un único lenguaje de programación, pero no quiero adelantarme al futuro ;)). Así que detuve la reforma, o mejor dicho, la redefiní, para considerar en estas modificaciones el uso del idioma universal de la programación: el inglés. Es por ello que también cambié su nombre a &lt;strong&gt;&lt;em&gt;GH Freebrary&lt;/em&gt;&lt;/strong&gt;, pensando que con él será mayor su difusión internacional.&lt;br /&gt;&lt;br /&gt;Actualmente &lt;strong&gt;GH Freebrary&lt;/strong&gt; es un producto relativamente maduro, pero el proceso de &lt;em&gt;humanización&lt;/em&gt; que le estoy haciendo va apenas en un 30% o 40%, considerando que no solo estoy cambiando el idioma y el estilo de nombres, sino también revisando algoritmos para detectar aquellos que pueden tener una mejora sustancial, además de eliminar uno que otro procedimiento medio &lt;em&gt;fumado&lt;/em&gt;. Sin embargo, podría pasar otro año afinando mi biblioteca antes de dejarla como realmente quiero que esté para ofrecerla en grande, y podría decirse que hasta entonces sería prudente comenzar a promocionarla con el nuevo nombre. ¡Pero llevo toda mi vida adulta gestando esta preciada colección! ¿Por qué no invitar a la gente a emplearla, aprovechando sus bondades desde ahora? Después de todo varias decenas de funciones ya están más que revisadas, convertidas al inglés y las utilizo con éxito todos los días en mis propios proyectos. ¿Por qué privar al público de utilizar dichas funciones hasta que toda la biblioteca esté “perfecta”? El cien por ciento del código es funcional y está probado, su tasa de defectos de operación —&lt;em&gt;bugs&lt;/em&gt;— es bajísima (en buena medida gracias a la atomicidad), así que si el único problema es el idioma y el estilo de nombres de un grupo de funciones, ¿por qué no promover al resto de ellas?&lt;br /&gt;&lt;br /&gt;Esta positiva reflexión me llevó a colocar un &lt;a href="http://www.sistemasgh.com/zonadedescargas.php"&gt;enlace para su libre descarga&lt;/a&gt; en la página de mi empresa hace tan solo unas semanas. Y, mientras la gran reforma de GH Freebrary continúa, la recomendación para mis amigos programadores es simple: usar sólo las funciones y otros elementos que ya están en inglés y llevan el prefijo &lt;em&gt;gh&lt;/em&gt;, tales elementos se mantienen y se respetarán. Cuando termine con la reforma, el siguiente paso será crear la tan solicitada documentación.&lt;br /&gt;&lt;br /&gt;Siéntanse libres para &lt;a href="http://www.sistemasgh.com/zonadedescargas.php"&gt;descargarla&lt;/a&gt; y usarla en sus proyectos Delphi. Compila en Delphi 7 sin problemas, aunque se aconseja tenerlo actualizado a 7.1 por un pequeño defecto del compilador. Y, como incluye el código fuente, pueden intentar adaptarla a otras versiones si se les presenta esa necesidad. De cualquier manera, en mis planes de corto plazo está el adaptarla a las versiones 2007 y 2009 (Tiburón), y posiblemente a versiones anteriores si el público así lo pide.&lt;br /&gt;&lt;br /&gt;Respondiendo a la pregunta con que intitulo a esta histórica entrada, GH Freebrary es literalmente la obra de mi vida, la cual comparto ahora con mucho gusto con todos los programadores Delphi del mundo.&lt;br /&gt;&lt;br /&gt;Un abrazo de 17 años.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-8140176162937275642?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/8140176162937275642/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/08/qu-es-gh-freebrary.html#comment-form' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8140176162937275642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8140176162937275642'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/08/qu-es-gh-freebrary.html' title='¿Qué es GH Freebrary?'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_9N_Agt_qWL4/SJQJcvU_kyI/AAAAAAAAAB0/cEkREYkhyMk/s72-c/AntiguoCodigo01.JPG' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-7096974094777963713</id><published>2008-07-24T12:35:00.006-05:00</published><updated>2008-07-27T11:20:41.361-05:00</updated><title type='text'>Reunión de colegas Delphi en Ciudad de México</title><content type='html'>¡Hola a todos!&lt;br /&gt;&lt;br /&gt;Hace algunas semanas &lt;a href="http://jachguate.wordpress.com/"&gt;Antonio Castillo&lt;/a&gt;, uno de los desarrolladores Delphi y Oracle más reconocidos de Guatemala y del mundo de habla hispana, viajó a &lt;a href="http://es.wikipedia.org/wiki/El_Cairo"&gt;El Cairo&lt;/a&gt;, Egipto para entregar el desarrollo de un sistema de software a un cliente de aquel místico país africano.&lt;br /&gt;&lt;br /&gt;A su regreso estará unas horas en &lt;a href="http://es.wikipedia.org/wiki/Madrid"&gt;Madrid&lt;/a&gt; la mañana del sábado (españoles: todos al &lt;a href="http://es.wikipedia.org/wiki/Alta_Velocidad_Espa%C3%B1ola"&gt;AVE&lt;/a&gt; ;)) y posteriormente hará otra escala en &lt;a href="http://es.wikipedia.org/wiki/Ciudad_de_M%C3%A9xico"&gt;Ciudad de México&lt;/a&gt; para participar en una interesante reunión de colegas Delphi que se llevará a cabo en un popular restaurante este lunes 28 de julio.&lt;br /&gt;&lt;br /&gt;En octubre del año anterior tuve oportunidad de conocerlo en persona y desayunamos en ese mismo lugar junto con otros colegas, como aperitivo del evento que organizó &lt;a href="http://dn.codegear.com/es"&gt;CodeGear&lt;/a&gt; para presentar Delphi 2007.&lt;br /&gt;&lt;br /&gt;Esta vez, varios colegas y buenos amigos de Ciudad de México invitan a una quedada Delphi en el Restaurante VIPs de Avenida Insurgentes y Reforma (cerca de la estación del metro Insurgentes). Antonio será el invitado de honor por venir del extranjero y por lo que representa su trayectoria para las comunidades de programadores. Hay un personaje extranjero más de cierto calibre, que casualmente se encuentra en México también y podría asistir a dicha reunión, pero omitiré su nombre hasta que confirme si tendrá oportunidad de allegarse a la cita.&lt;br /&gt;&lt;br /&gt;Para quienes nunca han participado en una reunión presencial de colegas Delphi, les dejo este enlace de hace cuatro años que les ayudará a imaginar lo bien que lo pasa uno:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.msn.com/ce77cj5fut58ai6vahamsb3nb1/interfazgh.msnw?action=get_message&amp;amp;mview=1&amp;amp;ID_Message=1916&amp;amp;all_topics=1"&gt;http://groups.msn.com/ce77cj5fut58ai6vahamsb3nb1/interfazgh.msnw?action=get_message&amp;amp;mview=1&amp;amp;ID_Message=1916&amp;amp;all_topics=1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Aquella fue la primera reunión auspiciada por miembros de la comunidad Delphi mexicana. En esta nueva ocasión habrá exposición planeada de interesantes temas técnicos y estarán presentes algunos de los miembros más activos de &lt;a href="http://www.clubdelphi.com/"&gt;Club Delphi&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tenía toda la disposición de coincidir con Antonio y otros amigos en esta reunión, pero me encuentro &lt;a href="http://es.wikipedia.org/wiki/Chihuahua_%28ciudad%29"&gt;a casi dos mil kilómetros&lt;/a&gt; atendiendo el llamado de un cliente y temo que no dispondré del tiempo necesario para viajar al Distrito Federal. No obstante me siento motivado para publicar este anuncio e invito a todos mis lectores cercanos a la capital del país a asistir al encuentro. No pierdan la oportunidad de convivir con otros colegas Delphi y de intercambiar útiles conocimientos y experiencias de vida. Quienes ya lo hemos hecho descubrimos por qué Delphi es más que un lenguaje de programación.&lt;br /&gt;&lt;br /&gt;Pocas tecnologías propician que sus usuarios enriquezcan su pensamiento y forma de ver el mundo. Delphi es una de ellas gracias a la sólida formación de sus más destacados exponentes.&lt;br /&gt;&lt;br /&gt;No lo olviden, &lt;strong&gt;Ciudad de México, lunes 28 de julio, 6:00 PM, restaurante VIPs de avenida Insurgentes y Reforma&lt;/strong&gt; (cerca del metro Insurgentes). Para mayores informes envíen un mensaje privado a &lt;strong&gt;&lt;em&gt;Poliburro&lt;/em&gt;&lt;/strong&gt; a través de su &lt;a href="http://www.clubdelphi.com/foros/member.php?u=3694"&gt;perfil en Club Delphi&lt;/a&gt; o su &lt;a href="http://groups.msn.com/ce77cj5fut58ai6vahamsb3nb1/profile?user=poliburro"&gt;perfil en PDM&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;¡Mucho éxito! Un abrazo entre colegas.&lt;br /&gt;&lt;br /&gt;Al González.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-7096974094777963713?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/7096974094777963713/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/07/reunin-de-colegas-delphi-en-ciudad-de.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7096974094777963713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/7096974094777963713'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/07/reunin-de-colegas-delphi-en-ciudad-de.html' title='Reunión de colegas Delphi en Ciudad de México'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-704433770463063983</id><published>2008-05-30T02:02:00.004-05:00</published><updated>2008-05-31T14:36:14.685-05:00</updated><title type='text'>¡Magia Data liberado!</title><content type='html'>¡Hola a todos!&lt;br /&gt;&lt;br /&gt;Me siento muy contento porque la pequeña &lt;a href="http://www.sistemasgh.com/"&gt;empresa de software que dirijo&lt;/a&gt; ha liberado este viernes 30 de mayo de 2008 la suite de componentes &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;&lt;strong&gt;Magia Data&lt;/strong&gt;&lt;/a&gt; que comencé a programar hace más de dos años.&lt;br /&gt;&lt;br /&gt;Este es uno de los trabajos a los que mayor dedicación he entregado en mis 16 años de carrera. La constituyen seis componentes Delphi “extendidos” totalmente compatibles con sus versiones nativas, pero que ofrecen nuevas propiedades, métodos y eventos &lt;U&gt;para hacerle la tarea más fácil a los programadores que trabajan con bases de datos&lt;/U&gt;.&lt;br /&gt;&lt;br /&gt;No importa cuál sea el motor utilizado, estos componentes soportan las bases de datos más populares (incluyendo Firebird, por supuesto) y combinan perfectamente con otros componentes de acceso a datos que estemos acostumbrados a utilizar (ADO, IBX, BDE, etc.).&lt;br /&gt;&lt;br /&gt;Tiene:&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiadatasource.php"&gt;un DataSource clonador&lt;/a&gt;,&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiaclientdataset.php"&gt;un ClientDataSet más dinámico&lt;/a&gt;,&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiadatasetprovider.php"&gt;un DataSetProvider cuántico&lt;/a&gt;,&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiasqlconnection.php"&gt;un SQLConnection más humano&lt;/a&gt;,&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiafirebirdsqlconnection.php"&gt;un FirebirdSQLConnection cuyo nombre lo dice todo&lt;/a&gt; y&lt;br /&gt;&lt;a href="http://www.sistemasgh.com/magiasqlquery.php"&gt;un SQLQuery buen padre de sus parámetros&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;La página oficial del producto es: &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;http://www.sistemasgh.com/magiadata.php&lt;/a&gt;. Ahí encontrarán una referencia completa de todas las nuevas características que brindan estos componentes derivados. Las demostraciones de Magia Data que he realizado en algunas ciudades han causado feliz admiración.&lt;br /&gt;&lt;br /&gt;Les agradeceré todo comentario acerca de esta modesta suite de componentes que he desarrollado con pasión, empeño y como un pequeño aporte al fortalecimiento de Delphi. No dejen de leer la &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;referencia&lt;/a&gt;, sospecho que se sentirán familiarizados con varios de los problemas que resuelve &lt;strong&gt;Magia Data&lt;/strong&gt;. Como estos:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=48173"&gt;http://www.clubdelphi.com/foros/showthread.php?t=48173&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=50368"&gt;http://www.clubdelphi.com/foros/showthread.php?t=50368&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=30633"&gt;http://www.clubdelphi.com/foros/showthread.php?t=30633&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=46650"&gt;http://www.clubdelphi.com/foros/showthread.php?t=46650&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=50563"&gt;http://www.clubdelphi.com/foros/showthread.php?t=50563&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Un abrazo mágico.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-704433770463063983?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/704433770463063983/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/magia-data-liberado.html#comment-form' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/704433770463063983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/704433770463063983'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/magia-data-liberado.html' title='¡Magia Data liberado!'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-561867383048558310</id><published>2008-05-26T03:10:00.007-05:00</published><updated>2008-05-30T10:35:57.883-05:00</updated><title type='text'>Resumen norteño</title><content type='html'>&lt;div align="right"&gt;«&lt;em&gt;&lt;strong&gt;En el trabajo les dije que vine a clase &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;contigo,&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;&lt;div align="right"&gt;&lt;em&gt;&lt;strong&gt;pero no me &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;creyeron, &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;mucho &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;menos &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;cuando&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;&lt;div align="right"&gt;&lt;em&gt;&lt;strong&gt;les &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;&lt;strong&gt;comenté que eres mi vecino&lt;/strong&gt;&lt;/em&gt;».&lt;/div&gt;&lt;br /&gt;Atardecer del sábado 24 de mayo de 2008. En las cercanías de &lt;a href="http://es.wikipedia.org/wiki/Torre%C3%B3n"&gt;Torreón&lt;/a&gt;, a bordo de un autobús con destino a &lt;a href="http://es.wikipedia.org/wiki/Zacatecas_%28Zacatecas%29"&gt;Zacatecas&lt;/a&gt;, donde pernoctaré antes de continuar el viaje de regreso &lt;a href="http://es.wikipedia.org/wiki/Morelia"&gt;Morelia&lt;/a&gt;. Después de dos completas e intensas semanas rescatando a Delphi en mi tierra natal.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Chihuahua_%28ciudad%29"&gt;Chihuahua&lt;/a&gt; está esplendorosa. Ya me hacía falta respirar ese aire limpio, apreciar los edificios del centro desde el barrio donde crecí, caminar por sus nuevas y armoniosas plazas dignas de cualquier ciudad europea, y, por supuesto, ver a mi familia.&lt;br /&gt;&lt;br /&gt;Las calles tan limpias y ordenadas, aceras que invitan a andar cómodo y sin presiones, tanto al que camina como al que rueda sobre amables rampas. La urbanidad y el urbanismo plasmados en cada esquina y muy claros en la mente de quienes administran y ejecutan los servicios públicos. La gente, mi gente, feliz de vivir en esa ciudad de la &lt;a href="http://es.wikipedia.org/wiki/Norteam%C3%A9rica"&gt;Norteamérica&lt;/a&gt; mexicana, trabajando con ánimo cuando se debe y celebrando con alegría responsable cuando se puede. Hace más de cien años un pueblo ya viejo que gozaba de mucha energía y valor acordó instalar el bienestar en esa región, y muchos años después, ante la perversión de dicho establecimiento, una corriente política de izquierda no reaccionaria dejó firmemente asentada la cultura de la honestidad y la justicia social en sus habitantes. Fue así que se consolidó el espíritu chihuahuense.&lt;br /&gt;&lt;br /&gt;Pero ni esto salva a mi ciudad maravilla de la poca inteligente guerra que el gobierno libra en el país entero en contra del tráfico ilegal de drogas. Hasta en Chihuahua se han presentado sanguinarias ejecuciones en los últimos meses.&lt;br /&gt;&lt;br /&gt;El autobús acaba de pasar encima del &lt;a href="http://es.wikipedia.org/wiki/R%C3%ADo_Nazas"&gt;río Nazas&lt;/a&gt; (el arenal donde alguna vez estuvo), o sea que hemos salido de &lt;a href="http://es.wikipedia.org/wiki/Durango_%28estado%29"&gt;Durango&lt;/a&gt; y entrado a &lt;a href="http://es.wikipedia.org/wiki/Coahuila"&gt;Coahuila&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Llegué a Chihuahua la madrugada del 10 de mayo, famoso Día de las Madres en México. A la mía le había prometido desde agosto (cuando programaba el sistema de puntos de restauración &lt;em&gt;CSP&lt;/em&gt; de &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;Magia Data&lt;/a&gt;) que iría a visitarla pronto. No me fue posible entonces, ni tampoco en las fiestas de fin de año. Pero no dejaría pasar esta primavera sin venir a ver a mis ancianos padres y casados hermanos. Trabajé en casa ese y los siguientes días, improvisando un modesto estudio en el &lt;em&gt;cuarto de los tiliches&lt;/em&gt; que a la vez me sirvió de dormitorio.&lt;br /&gt;&lt;br /&gt;El martes 13 comí con Luis, quien fue mi pupilo allá por el año 2000, y a quien no veía desde hace casi cuatro años. Recuerdo el día que con solo 17 años de edad acudió a mi tétrica oficina de la calle Segunda para solicitar trabajo de programador y muchas de las buenas horas que pasé enseñándole a desarrollar con Delphi. Hoy trabaja con sistemas &lt;a href="http://es.wikipedia.org/wiki/Planificaci%C3%B3n_de_Recursos_Empresariales"&gt;ERP&lt;/a&gt; en una de las compañías cementeras más grandes del mundo. El año pasado lo enviaron a &lt;a href="http://es.wikipedia.org/wiki/Bolivia"&gt;Bolivia&lt;/a&gt;, donde conoció en persona al buen &lt;a href="http://www.clubdelphi.com/foros/member.php?u=978"&gt;Onti&lt;/a&gt;, conocido forista que también defiende a Delphi a capa y espada en su país.&lt;br /&gt;&lt;br /&gt;El miércoles me llamaron de una casa de software localizada en &lt;a href="http://es.wikipedia.org/wiki/Ciudad_de_M%C3%A9xico"&gt;Ciudad de México&lt;/a&gt;. Se encuentran en un punto crucial de su vida como empresa fabricante de paquetería comercial. Tienen millones de líneas de código que han escrito en Delphi desde hace años, código con el cual han construido muy útiles aplicaciones algo conocidas en México. La finalidad es ayudarles en su transición de Paradox a cliente-servidor, algo que desde hace un lustro viene dándose con todos los desarrolladores Delphi que empezamos usando bases de datos de escritorio. Me hicieron hablar en conferencia telefónica ante su equipo de desarrolladores a quienes comenté algunas de las vicisitudes y oportunidades de este objetivo. Al cabo de unos días me comunicaron que aceptaban contratar los servicios de &lt;a href="http://www.sistemasgh.com/index.php"&gt;Sistemas GH&lt;/a&gt;. Realmente me siento feliz por este importante reto. El 4 de junio iniciaremos con un breve curso de introducción a dbExpress con Firebird, donde mostraré algunas de las ventajas de Magia Data y del resto de nuestro framework. Al parecer ya están convencidos de que DBX es el conducto de bases de datos más certero dentro de Delphi, así que espero no sea difícil convencerlos de usar mis componentes DBX extendidos también. Adicionalmente, decidieron adquirir el viejo pero todavía útil &lt;a href="http://www.sistemasgh.com/cursos.php"&gt;curso “empaquetado” de Firebird con IBX&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Al día siguiente asesoré a Fernando en el uso del componente gratuito para huellas digitales &lt;a href="http://groups.msn.com/ce77cj5fut58ai6vahamsb3nb1/automatizacin.msnw?action=get_message&amp;amp;mview=1&amp;amp;ID_Message=5737"&gt;GH FingReader&lt;/a&gt; y de Magia Data, suite que compró ese mismo día. Él colaboró conmigo en Morelia hace poco más de dos años durante una breve estancia de tres meses. Le tocó entonces conocer los inicios de estos componentes extendidos, cuando un servidor comenzaba a conocer dbExpress y el famoso &lt;em&gt;Client Data Set&lt;/em&gt; del que todo mundo hablaba ya. Un día descubrí que un componente TClientDataSet nativo no puede conectarse a un TDataSetProvider del mismo proyecto si no se encuentran los dos en el mismo módulo de datos. La limitación se justifica con el razonamiento de que este binomio de componentes debe emplearse en un esquema multicapa, o en un proyecto tan sencillo que no amerite emplear más de un módulo de datos. Pero entonces nosotros teníamos la idea de que debería existir un justo medio (como para todo en la vida) entre una típica aplicación de dos capas (interfaz cliente--servidor de base de datos) y una de tres (interfaz cliente--servidor de aplicaciones--servidor de base de datos). Queríamos establecer un esquema que nos permitiera desarrollar aplicaciones cliente-servidor sin complicaciones multicapa que en las primeras versiones de un sistema suelen ser innecesarias, pero de tal manera que la estructura Delphi de tales proyectos estuviese preparada para ser partida por la mitad en el futuro, cual dos hojas de impresión de formato continuo.&lt;br /&gt;&lt;br /&gt;A este esquema le llamamos &lt;strong&gt;&lt;em&gt;2.5 capas&lt;/em&gt;&lt;/strong&gt;; aplicaciones ahorrativas como cualquiera de dos capas, pero preparadas para pasarse a tres cuando el proyecto en cuestión lo amerite. Esto volvía necesario colocar los conjuntos de datos clientes en un módulo de datos y sus respectivos proveedores en otro para poder marcar la línea de corte entre las dos &lt;em&gt;hojas&lt;/em&gt;. Por ello agregué a TMagiaClientDataSet la propiedad Provider, con la cual podemos asociar el conjunto de datos con cualquier TDataSetProvider del proyecto, independientemente del módulo de datos donde se localice éste. Resultó ser una buena alternativa a la propiedad ProviderName. Aún recuerdo la admiración del entonces novato Fer, cuando le mostré el funcionamiento de esa nueva característica. Eran grandes tiempos, yo acababa de conocer a Janett, el changarro tenía ingresos estables, no le debíamos dinero a nadie y no estábamos atrasados en ningún proyecto. Hoy es muy diferente.&lt;br /&gt;&lt;br /&gt;El viernes 16, una amiga de &lt;a href="http://es.wikipedia.org/wiki/Saltillo"&gt;Saltillo&lt;/a&gt; me pasó el dato de que una empresa mediana pero bastante dinámica (por lo que pude inferir después) necesitada de servicios de programación en Delphi. Después de varias llamadas y correos, la mañana de hoy se comunicaron a Morelia para solicitar una entrevista presencial en la capital de Coahuila. Me hubiera gustado disponer de algo más de tiempo para tomar el autobús a Saltillo y no a Zacatecas, pero dado que no quiero descuidar compromisos adquiridos anteriormente, tal visita a Saltillo tendrá que esperar unas semanas. En el peor de los casos, si nos vemos sobrepasados en trabajo buscaré a alguien de confianza y comprobado nivel de servicio que le interese atender este caso. Esto me deja pensando en que nos caería de maravilla, en esta época de nuestra historia como empresa, un inversionista inteligente y honrado que quiera apoyarnos ahora que estamos teniendo francas y buenas oportunidades de negocios. Estamos dejando correr mucho agua, de la que ciertamente no podemos beber, pero sé que podremos beberla cuando contemos con un poco más de recursos.&lt;br /&gt;&lt;br /&gt;El lunes siguiente vi a Mario en su oficina del Colegio de Bachilleres, un antiguo cliente que hace tiempo adquirió el &lt;a href="http://www.sistemasgh.com/cursos.php"&gt;curso empaquetado de POO&lt;/a&gt;, pero a quien todavía no tenía el gusto de conocer en persona. Se comprometió a promover nuestros cursos y talleres ante los directivos de la institución donde trabaja, y personalmente adquirió esta vez el viejo curso de Firebird. Al principio me observaba con un semblante tenso, pero le dije «&lt;em&gt;¡Hey viejo! No me veas como a un extraño, soy tan chihuahuense como tú, sólo que ya llevo varios años viviendo fuera&lt;/em&gt;». Por la ventana de su oficina podía apreciarse la bella claridad del cielo, distinguiéndose sin problemas limpios edificios y jardines lejanos. Vistas que hacen posible estar contento.&lt;br /&gt;&lt;br /&gt;Por la tarde de ese día le llamé a Moisés para preguntarle dónde podía verlo para la clase de programación que me solicitó. Como Fernando, trabaja en el gobierno de Chihuahua, a dos edificios de distancia. Es un joven colega Delphi que tengo en mis contactos del mensajero desde hace varios años pero que, al igual que Mario, no había tratado hasta ese día presencialmente. Para sorpresa de ambos, resultó que vive a doscientos metros de la casa de mis padres (¡vaya que el mundo es pequeño!). Entre otras cosas, viendo su código, le hice hincapié en que no debe emplear constantes literales (1, 2, 3...) para indicar opciones de programa, le expliqué la ventaja de usar en su lugar tipos enumerados (opAlta, opBaja, opCambio...).&lt;br /&gt;&lt;br /&gt;El miércoles 21 y el jueves 22 la familia les hizo un pequeño festejo a mi hermano menor y papá por sus respectivos cumpleaños. La verdad que ya extrañaba comer en casa junto a mis familiares y compartir los últimos sucesos de nuestras historias de vida. ¡Que bueno es convivir con ellos! Comiendo pollo asado al carbón, ahí, en la misma casa de adobe y piedra donde jugábamos los hijos cuando éramos pequeños, atizando la sobremesa con cada graciosa ocurrencia del ingenio fraternal, mientras los sobrinos desarrollan un armonioso caos en otra habitación.&lt;br /&gt;&lt;br /&gt;Ese jueves por la tarde fue Moisés a casa para la segunda clase. Esta vez vimos algo de &lt;a href="http://es.wikipedia.org/wiki/POO"&gt;POO&lt;/a&gt;. Observando el código fuente de la VCL, repasamos las bases de herencia, encapsulamiento y polimorfismo, además de explicar cómo funcionan los métodos virtuales. Creamos una clase de ejemplo &lt;em&gt;TXButton&lt;/em&gt;, derivada de TButton, y aproveché para enseñarle el viejo pero útil truco del &lt;em&gt;molde de acceso&lt;/em&gt;, que nos sirve para hacer referencia a elementos protegidos de una clase, a los cuales el compilador no deja acceder libremente. Al despedirnos compartió conmigo estas insólitas palabras: «&lt;em&gt;En el trabajo les dije que vine a clase contigo, pero no me creyeron, mucho menos cuando les comenté que eres mi vecino&lt;/em&gt;».&lt;br /&gt;&lt;br /&gt;El viernes 23 tuve una reunión más en el mismo edificio donde trabaja Fernando, pero tres pisos más arriba. Vi a un activo funcionario (esas dos palabras sí pueden ir juntas) que ha desarrollado en Delphi mucho del buen software que tiene el gobierno estatal, llamándome la atención un sistema &lt;a href="http://es.wikipedia.org/wiki/Gis"&gt;GIS&lt;/a&gt; con el que pueden saber todo acerca de cualquier edificio o terreno de la ciudad, observando su posición desde una vista satelital que remarca y titula las calles aledañas (aclarando que se ve mucho mejor que el mostrado por Wikipedia). Además desarrolló un software catastral que ya no sólo se utiliza en la administración pública de Chihuahua, sino que además ha “exportado” a otras provincias por su efectividad intrínseca. Quiere que Sistemas GH le de seguimiento y mejora a ese sistema en ciertos municipios del país. Y se mostró interesado en que yo vuelva pronto a Chihuahua para dar cursos y consultorías Delphi a personal y áreas de su influencia.&lt;br /&gt;&lt;br /&gt;Y entre todo esto, conocer a Ilse y convivir con ella en varias ocasiones, fue una de las mejores y más intensas cosas que pudo pasarme en este viaje.&lt;br /&gt;&lt;br /&gt;Un rico burrito de lomo trae buena suerte.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-561867383048558310?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/561867383048558310/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/resumen-norteo.html#comment-form' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/561867383048558310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/561867383048558310'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/resumen-norteo.html' title='Resumen norteño'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-6239212834444507547</id><published>2008-05-05T01:03:00.007-05:00</published><updated>2008-05-15T13:21:44.537-05:00</updated><title type='text'>Resumen tapatío</title><content type='html'>&lt;div align="right"&gt;&lt;strong&gt;Sábado 3 de mayo de 2008, 11:30 PM.&lt;/strong&gt;&lt;/div&gt;&lt;br /&gt;A bordo del autobús, regresando a &lt;a href="http://es.wikipedia.org/wiki/Morelia"&gt;Morelia&lt;/a&gt; después de dos interesantes semanas en &lt;a href="http://es.wikipedia.org/wiki/Guadalajara_%28Jalisco%29"&gt;Guadalajara&lt;/a&gt;. Ha valido mucho la pena dejar ese entelarañado apartamento donde vivía. Creo que a veces es necesario dejar de tener casa para atreverse a salir de las estrechas fronteras de una ciudad y respirar algo de libertad.&lt;br /&gt;&lt;br /&gt;Estando en Guadalajara sucedieron muchas cosas interesantes. Desde que llegué me puse en contacto con todos los colegas Delphi de Jalisco que conozco, foristas de Club Delphi y PDM. A algunos como Norberto y Ramiro ya tenía el gusto de tratarlos en persona, y esta vez tuve el privilegio de conocer y estrechar la mano de varios otros como Paoti, &lt;a href="http://salvador.oversistemas.com/"&gt;Salvador&lt;/a&gt;, Esteban y Gabriela. Desafortunadamente no fue posible conocer en persona en esta ocasión a Omar, Isaac y Ulices (sí, Ulises con ce), éste último uno de mis más antiguos y allegados contactos en el mensajero.&lt;br /&gt;&lt;br /&gt;Ramiro, a quien no veía desde hace un año, fue el primero que estuvo disponible. Le mostré grosso modo el framework que hemos construido en &lt;a href="http://www.sistemasgh.com/"&gt;Sistemas GH&lt;/a&gt;, resultándome muy emotivo notar su admiración ante dos sencillas pero poderosas propiedades que hemos agregado al componente &lt;em&gt;DataSource&lt;/em&gt;: &lt;strong&gt;DataSetCloned&lt;/strong&gt; y &lt;strong&gt;DataSetEvents&lt;/strong&gt;. La capacidad de clonar objetos &lt;em&gt;data sets&lt;/em&gt; en tiempo de ejecución y la de utilizar, de manera particular en cada formulario, los eventos de un &lt;em&gt;data set&lt;/em&gt; colocado en un módulo de datos fue lo que más les llamó la atención a él, y posteriormente a Norberto y Esteban. Incluso este último decidió comprar una copia de &lt;a href="http://www.sistemasgh.com/magiadata.php"&gt;Magia Data&lt;/a&gt; para Delphi 7 después de la asesoría que le di. Ramiro también mostró interés en comprar la suite Magia Data, pero se esperará a que tenga lista la versión para Delphi 2007 dentro de algunas semanas.&lt;br /&gt;&lt;br /&gt;Algo que llamó mucho mi atención es la combinación tan especial que se da en Guadalajara de una vigorosa actividad económica e industrial y la gran pasión con que sus numerosos programadores Delphi aprecian y defienden a este respetado lenguaje de programación. Guadalajara es sencillamente una de las ciudades con mayor corazón pascalero de México. Creo que &lt;a href="http://www.codegear.com/"&gt;CodeGear&lt;/a&gt; y sus distribuidores deberían sacarle mayor provecho a esta estupenda sinergia jalisciense.&lt;br /&gt;&lt;br /&gt;Conocí un poco la bella y famosa zona de &lt;a href="http://es.wikipedia.org/wiki/Tlaquepaque"&gt;Tlaquepaque&lt;/a&gt; gracias a Esteban, quien toda su vida ha residido ahí, y a quien desde el año anterior hemos estado asistiendo en su transición al mundo cliente-servidor, primero a través del mensajero y ahora presencialmente. En estos días aprendió muchos conceptos que no tenia del todo claros y comprendió varias de las vicisitudes que deben tenerse en cuenta en este paradigma de bases de datos. Esclarecimos que el uso de bases de datos cliente-servidor no significa que deba escribir cientos de sentencias SQL &lt;em&gt;Insert Into&lt;/em&gt;, &lt;em&gt;Update&lt;/em&gt; y &lt;em&gt;Delete&lt;/em&gt;; el temeroso mito por el cual muchos desarrolladores demoramos varios años en ingresar a este obligado terreno. Le mostré lo fácil que es acceder a una base de datos Firebird local o remota con dbExpress y TClientDataSet, y le expliqué la razón por la cual se necesita un TDataSetProvider como auxiliar y las ventajas de usar un conjunto de datos de memoria. Cuando terminamos el programa de ejemplo, logrando transferir información de un par de tablas Paradox locales a una base de datos Firebird remota mediante dirección IP y alias, me dijo alegremente sorprendido: «&lt;em&gt;¡No sabes cuánto tiempo esperé para ver esto!&lt;/em&gt;». Como asesor, fue para mí una gran satisfacción, de esas que reafirman porqué es tan bueno enseñar a otros.&lt;br /&gt;&lt;br /&gt;Lamentablemente no me fue posible presenciar los eventos en línea del lunes 21 y martes 22 de abril. Tras algunos amables correos que intercambié con &lt;a href="http://www.gopac.com.mx/v3/index.asp"&gt;Gopac&lt;/a&gt; antes de partir a Guadalajara, y la intención de ambas partes de entrevistarnos, asumí que me dejarían conectarme en sus instalaciones y de paso ver asuntos para los que pudiera ayudarles con el fin de generar mayor cohesión y sinergia entre CodeGear y los programadores Delphi. Pero supongo se les complicó de algún modo, así que me quedé esperando confirmación sin poder ver los eventos. Eso sí, le encargué a Cheché que estuviera muy atento en Morelia a las ponencias para valorar todas las buenas cosas nuevas que han añadido a los productos. Sobre todo me interesa estar al día con Delphi Win32 y adquirir todas las actualizaciones que lancen de Delphi for PHP.&lt;br /&gt;&lt;br /&gt;En compensación, el jueves 24 sucedió algo verdaderamente extraordinario, algo de lo que no debo estar nada orgulloso, pero que le dio un positivo giro de 179 grados a un tremendo problema que venía acarreando desde el año pasado. Como algunos saben, estuve a punto de ser demandado por la empresa de mi principal cliente en el D.F. debido a retrasos en un importante proyecto de software. La empresa ya canceló definitivamente el proyecto, y es &lt;a href="http://www.sap.com/mexico/index.epx"&gt;SAP&lt;/a&gt; quien está haciéndose cargo ahora de ese complejo caso. Pero ha sido él, como socio y director de su empresa, quien hizo frente a los inversionistas cubriéndome la espalda una vez más. Se hizo responsable por el importe hasta ahora pagado, el cual sé, porque conozco sus circunstancias, no le será fácil cubrir. Por mi parte, el compromiso es terminar el proyecto más o menos como se tenía pensado, agregando ciertos módulos.&lt;br /&gt;&lt;br /&gt;La piedra angular de esto es que se ha trabajado tanto en este sistema, que sería absurdo tirarlo todo por la borda. Así que el proyecto continúa, con otro nombre y para otra entidad fiscal, pero continúa. Lo terminaremos y mi cliente hará un uso que considero muy inteligente, redituable y estratégico del mismo. Por fin encontramos salida a la espantosa ecuación en que nos habíamos metido. De momento no habrá más inversión directa para ese proyecto hasta comenzar a obtener los resultados esperados, será difícil sostenerlo a base de utilidades obtenidas en otros rubros, pero no imposible. Al final todo habrá valido la pena y podremos trabajar en muchas más soluciones de software que el cliente ya visualiza con nosotros. Yo nunca quise soltar este proyecto porque es muy interesante todo lo que estamos haciendo en él. Con esto que sucedió ahora hemos entrado a un camino más sano, lógico y transitable y se me ha quitado un enorme peso de encima. Siento que con esto la mitad de mis problemas encuentran resolución, y tengo la extraña impresión de que el desenlace hubiese sido distinto de no haber ido a pasar unos días en Guadalajara.&lt;br /&gt;&lt;br /&gt;Al día siguiente, el viernes 25, me invitaron a una tertulia de colegas en el Sanborns de Avenida Vallarta, el mismo donde conocí a Ramiro hace un año. Fue muy grato ver ahí a Norberto y conocer en persona a Salvador y Álvaro. Me he dado cuenta que cada vez es más común encontrar programadores en los restaurantes, aprovechando la señal abierta de Internet y socializando más. Desaparece el estereotipo del desarrollador solitario, ensimismado, aislado del mundo en una habitación. Empieza a notarse esta tendencia. Incluso hoy, durante la asesoría que le di a Estaban en uno de esos restaurantes, advertimos que en la mesa contigua estaban otro par de desarrolladores trabajando en una laptop y hablando sobre lenguajes de programación.&lt;br /&gt;&lt;br /&gt;El sábado 26 tuvimos una segunda reunión, donde Norberto por fin pudo conocer las mejoras que hemos implementado con Magia Data y las plantillas de herencia visual de nuestro framework. Va a ser muy gratificante para los que formamos parte de Sistemas GH ver a otros desarrolladores utilizando estos componentes que con tanto esfuerzo y dedicación he desarrollado. Por lo pronto la primera venta de éstos se cerró hoy, esperemos que vengan muchas más.&lt;br /&gt;&lt;br /&gt;Cuando no tenía reunión, mis sesiones de trabajo se desarrollaban principalmente en el comedor de mi cuñada. Es una pena que mi hermano mayor tenga menos atenciones conmigo que su propia esposa. Él ni siquiera tiene idea de qué estoy haciendo actualmente, de cuáles son mis circunstancias actuales, mis logros y mis metas, apenas si sabe que tengo una pequeña oficina en Morelia, pero no se interesa en nada que no sea su propia carrera profesional. No recuerdo ninguna pregunta seria y de interés que me haya hecho desde que terminé la escuela secundaria. Es como si simplemente me hubiese borrado de su vida, y no tengo idea de cómo es que aún así me dio alojamiento en su casa. Esta noche hizo el favor de acercarme en su auto a la terminal de autobuses, durante el camino no paró de lanzar maldiciones y palabrotas, acusando a mis padres sin su presencia de no haberme “&lt;em&gt;educado como debe ser&lt;/em&gt;”. A veces me pregunto en qué momento mi hermano perdió el piso y se volvió un amargado egocéntrico empedernido.&lt;br /&gt;&lt;br /&gt;Pero una de las mejores cosas de esta estancia en Guadalajara es haber conocido a Gabriela, una chica de los foros que no sólo es experimentada en Delphi, sino además muy simpática. Es una de esas muchachas auténticas, de las pocas que suelen verse hoy día, sin tapujos para hablar y expresar lo que siente y con una muy atenta manera de escuchar a las personas. Habla muy bien de varios de los compañeros de Club Delphi, a más de diez nos tiene perfectamente identificados. &lt;a href="http://jhonny.clubdelphi.com/"&gt;Jhonny&lt;/a&gt; fue su “iniciador”. Por cierto, este lunes 5 será su cumpleaños.&lt;br /&gt;&lt;br /&gt;Mis quince jornadas en &lt;em&gt;GDL&lt;/em&gt;. Ahora pernoctaré unos días en la oficina de Morelia y luego iré a visitar a mis padres y demás hermanos en Chihuahua, y a varios amigos de esa ciudad. Espero tener la opción de regresar vía &lt;a href="http://es.wikipedia.org/wiki/Los_Mochis"&gt;Los Mochis&lt;/a&gt; para visitar a AGAG4 y su pandilla de buenos pascaleros y foristas Delphi. Después, durante este mismo mes, es probable que vaya a &lt;a href="http://es.wikipedia.org/wiki/Cuernavaca"&gt;Cuernavaca&lt;/a&gt; a dar un taller (sólo estoy esperando una llamada de la persona que me externó su interés hace unos días).&lt;br /&gt;&lt;br /&gt;Un abrazo tapatío.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-6239212834444507547?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/6239212834444507547/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/resumen-tapato.html#comment-form' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6239212834444507547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/6239212834444507547'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/05/resumen-tapato.html' title='Resumen tapatío'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-8632350332852095903</id><published>2008-03-03T02:11:00.017-06:00</published><updated>2008-04-10T14:35:48.245-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='memoria compartida'/><category scheme='http://www.blogger.com/atom/ns#' term='instancias en memoria compartida'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos superglobales'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos compartidos'/><category scheme='http://www.blogger.com/atom/ns#' term='compartir datos entre programas'/><title type='text'>Objetos superglobales.  Memoria compartida como nunca antes.</title><content type='html'>&lt;div align="right"&gt;&lt;strong&gt;«&lt;em&gt;Sería interesante que la propia &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;instancia &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;del objeto &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;de&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="right"&gt;&lt;strong&gt;&lt;em&gt;memoria &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;compartida &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;fuese &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;la memoria &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;&lt;em&gt;compartida en sí&lt;/em&gt;».&lt;/strong&gt;&lt;/div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;p&gt;&lt;br /&gt;¡Hola!&lt;br /&gt;&lt;br /&gt;Antes que nada les comento que estaré este lunes 3 de marzo en Ciudad de México. El plan es regresar Morelia por la noche, a no ser que surja algún llamado para dar un taller o asesoría Delphi, o alguna invitación para permanecer ahí o ir a otra ciudad por unos días. Ya saben que con portátil y sin mujer uno puede moverse a donde lo inviten (aunque sería maravilloso tener una mujer consorte de mis aventuras).&lt;br /&gt;&lt;br /&gt;Por fin me doy un poco de tiempo para hablar del tema que les había prometido: &lt;strong&gt;Memoria compartida en forma de objetos “superglobales”&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Para empezar es conveniente dar un poco de contexto:&lt;br /&gt;&lt;br /&gt;En diciembre de 2003 estuve investigando sobre diferentes formas en que dos aplicaciones Windows en ejecución, es decir, dos &lt;em&gt;procesos&lt;/em&gt;, pueden intercambiar datos en tiempo real. Encontré un interesante mecanismo llamado &lt;em&gt;Named Shared Memory&lt;/em&gt; o &lt;strong&gt;&lt;em&gt;Memoria Compartida con Nombre&lt;/em&gt;&lt;/strong&gt; en un artículo de MSDN (la más vasta y útil referencia acerca de las APIs de Microsoft) similar a este: &lt;a href="http://msdn2.microsoft.com/en-us/library/aa366551(VS.85).aspx"&gt;http://msdn2.microsoft.com/en-us/library/aa366551(VS.85).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Como ya entonces era común en mí usar funciones de la API de Windows para resolver diversos problemas de programación, supe que no me resultaría difícil implementar lo que buscaba. Sólo tenía que estudiar y emplear las funciones &lt;strong&gt;CreateFileMapping&lt;/strong&gt; y &lt;strong&gt;MapViewOfFile&lt;/strong&gt; como lo indicaba uno de los ejemplos de MSDN. Para ello me apoyé también en el sagrado archivo Win32.hlp que, bendita Providencia, acompaña a todo Delphi; un fastuoso archivo de ayuda donde he realizado cientos de consultas fructíferas. En él vienen muy bien explicadas la gran mayoría de las funciones de la API Win32. Es uno de esos archivos de ayuda que se crearon sin prisas, concienzudamente, como fueron creados también los valiosos y extensos archivos de ayuda del propio Delphi en la época en que Microsoft era informativamente justo y Borland una empresa sumamente venerada y con más recursos económicos para documentar debidamente sus herramientas (como lo volverá a ser en pocos años).&lt;br /&gt;&lt;br /&gt;Y aquello funcionaba. Utilizando dichas funciones logré que dos de mis aplicaciones Delphi en ejecución intercambiaran datos de una manera muy transparente. Una escribía bytes en un buffer, y la otra podía leerlos sin más, como por arte de magia. No me extenderé hablando de cómo trabajan estas dos funciones, sobre eso ya hay bastante material en Internet y en Win32.hlp mucho mejor explicado de lo que yo podría tratar.&lt;br /&gt;&lt;br /&gt;Pero si es conveniente mencionar que CreateFileMapping se utiliza para crear o abrir un objeto de mapeo de archivo (&lt;em&gt;file mapping object&lt;/em&gt;) —algunos autores les llaman “proyecciones”, pero no estoy seguro de usar ese término—, el cual puede ser compartido entre procesos. La función se aplica sobre un identificador de archivo (&lt;em&gt;file handle&lt;/em&gt;) que previamente hayamos abierto o creado y nos regresa un identificador de un objeto que nos permite controlar &lt;em&gt;vistas&lt;/em&gt; o “mapas” de diferentes secciones del archivo, sobre las cuales podemos hacer lectura o escritura de bytes. MapViewOfFile es la función que nos permite definir dichas vistas. Al llamarla le damos el identificador obtenido con CreateFileMapping, la posición del archivo a partir de la cual queremos que la vista tenga acceso y la cantidad de bytes disponibles para “ver”. La función nos regresa un puntero al primer byte de memoria de la vista; si escribimos en ese buffer, estaremos escribiendo en el archivo, y si leemos, estaremos leyendo lo que el archivo contiene en esa sección.&lt;br /&gt;&lt;br /&gt;Así pues, CreateFileMapping se utiliza para crear un objeto de mapeo “controlador de vistas” sobre un archivo y MapViewOfFile para abrir en sí cada vista o “ventana”. Es como si el archivo fuese una caja de cartón llena de pelotas de tenis (sus bytes), las vistas pequeños recortes que hacemos en sus paredes para tomar dichas pelotas o introducir otras, y el objeto de mapeo es el encargado de todas esas ventanas por las cuales se accede al contenido del archivo. Pudiendo dicho objeto de mapeo ser compartido entre diferentes programas en ejecución.&lt;br /&gt;&lt;br /&gt;Estas son las cabeceras nativas y sus correspondientes versiones Delphi de dichas funciones:&lt;br /&gt;-----------------------------------------&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;strong&gt;HANDLE CreateFileMapping(&lt;br /&gt;HANDLE hFile, // handle to file to map LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security attributes DWORD flProtect, // protection for mapping object DWORD dwMaximumSizeHigh, // high-order 32 bits of object size DWORD dwMaximumSizeLow, // low-order 32 bits of object size LPCTSTR lpName // name of file-mapping object&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;strong&gt;);&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;strong&gt;function CreateFileMapping(hFile: THandle; lpFileMappingAttributes: PSecurityAttributes;&lt;br /&gt;flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWORD; lpName: PChar): THandle; stdcall;&lt;br /&gt;&lt;br /&gt;LPVOID MapViewOfFile(&lt;br /&gt;HANDLE hFileMappingObject, // file-mapping object to map into address space&lt;br /&gt;DWORD dwDesiredAccess, // access mode&lt;br /&gt;DWORD dwFileOffsetHigh, // high-order 32 bits of file offset&lt;br /&gt;DWORD dwFileOffsetLow, // low-order 32 bits of file offset&lt;br /&gt;DWORD dwNumberOfBytesToMap // number of bytes to map&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;function MapViewOfFile(hFileMappingObject: THandle; dwDesiredAccess: DWORD;&lt;br /&gt;dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap: DWORD): Pointer; stdcall;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;-----------------------------------------&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Pero hasta aquí se habla solamente de archivos, y esta entrada tiene que ver con compartir memoria entre procesos. Pues bien, la clave para crear memoria compartida es llamar a CreateFileMapping con un parámetro inicial de &lt;strong&gt;Invalid_Handle_Value&lt;/strong&gt;, el cual no es un identificador válido de archivo. CreateFileMapping toma esta constante como indicador de que debe crear el objeto de mapeo sobre el famoso &lt;a href="http://es.wikipedia.org/wiki/Espacio_de_intercambio#En_Windows"&gt;&lt;strong&gt;archivo de paginación&lt;/strong&gt;&lt;/a&gt; (o &lt;em&gt;archivo de intercambio&lt;/em&gt;) del sistema operativo. Al ser este archivo “memoria RAM virtual”, usar una parte de él para intercambiar datos entre programas es, en la práctica, lo mismo que sería usar un buffer de RAM para el mismo propósito (imaginando que Windows permitiese acceder a la RAM libremente). Aunque tengo mis dudas de si realmente se graba en disco algo que escribimos en una vista mapeada de este tipo, tal vez el sistema operativo mantiene estas vistas especiales en ágil RAM real; la verdad ignoro cómo Windows maneja estos casos. Pero pues ¡qué bonito! Con CreateFileMapping e Invalid_Handle_Value reservo un bloque de memoria, al que le doy un nombre por el cual otros procesos pueden emplear ese mismo bloque, y con MapViewOfFile creo accesos al mismo.&lt;/p&gt;&lt;p&gt;Sin embargo, como programador bibliotecario que soy, me planteé encapsular el uso de estas dos funciones en una clase o componente Delphi, bajo un nombre como "&lt;em&gt;TMemoriaCompartida"&lt;/em&gt;. Buscando en la Red, descubrí que varios autores ya habían creado soluciones similares a mi idea inicial. Hoy en día pueden verse muchas clases llamadas "&lt;em&gt;TSharedMemory"&lt;/em&gt; que cumplen con el propósito. Por lo general, dichas clases ofrecen algún tipo de propiedad o función de tipo puntero para acceder al bloque de memoria compartida, y para escribir en ese buffer suelen emplearse métodos tipo &lt;em&gt;WriteXXX&lt;/em&gt;/&lt;em&gt;SetXXX&lt;/em&gt;. Pero a finales de 2003, cuando me encontraba sumergido en todo este proceso de análisis y después de haber visto el código fuente de varias de las clases escritas hasta el momento, tuve una reflexión que en un lenguaje de programación diferente a Delphi probablemente se hubiese hundido en el mar de las utopías:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;«&lt;strong&gt;&lt;em&gt;Sería interesante que la propia instancia del objeto de memoria compartida fuese la memoria compartida en sí&lt;/em&gt;&lt;/strong&gt;».&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Después de decirme esto, automáticamente mi cerebro revisó algunos viejos recuerdos de mis primeras indagaciones sobre la clase TObject (ancestro de todas las clases) y...¡lotería!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;«&lt;strong&gt;&lt;em&gt;¡Pero claro, TObject tiene un método virtual que le permite a uno definir dónde y cómo asignar la memoria de la instancia!&lt;/em&gt;&lt;/strong&gt;»&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ese método virtual tiene por nombre &lt;strong&gt;NewInstance&lt;/strong&gt;, es un método clase que es llamado cada vez que se realiza una instanciación de objeto. Una instrucción como &lt;em&gt;TMiClase.Create&lt;/em&gt; causa una llamada inicial al método NewInstance para reservar la memoria que requerirá el objeto, y como este método es virtual, podemos redefinirlo en &lt;em&gt;TMiClase&lt;/em&gt; para hacer que la memoria del objeto se asigne de manera distinta a lo normal.&lt;br /&gt;&lt;br /&gt;La gran ayuda de Delphi es clara al respecto:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Override NewInstance only for special memory allocation requirements. &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;[&lt;em&gt;Redefina NewInstance solo por requerimientos de asignación de memoria especiales.&lt;/em&gt;]&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Fue así que escribí una clase de memoria compartida muy sui géneris, la cual incluí en mi biblioteca de clases y funciones. Hace unos días la desempolvé, afiné, renombré como &lt;strong&gt;&lt;em&gt;TSuperGlobalObject&lt;/em&gt;&lt;/strong&gt; y la publiqué en Club Delphi: &lt;/p&gt;&lt;p align="right"&gt;&lt;a href="http://www.clubdelphi.com/foros/showthread.php?t=53146"&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Código fuente explicado y descarga.&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Los invito a descargar la unidad y probarla creando una clase derivada de TSuperGlobalObject. En un programa en ejecución podrán hacer algo como&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;MiObjetoCompartido.Campo := Valor;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Y en otro programa en ejecución (que puede ser o no instancia del mismo ejecutable) leer el contenido de ese objeto:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;X := MiObjetoCompartido.Campo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Todos los campos que definamos en nuestra nueva clase serán alojados en la propia memoria compartida.&lt;/strong&gt; Con esta solución, el acceso a la memoria compartida encapsulada en un objeto Delphi se hace de manera totalmente natural y transparente desde cualquier proceso. Y por eso les he llamado &lt;strong&gt;&lt;em&gt;objetos superglobales&lt;/em&gt;&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Sólo aclarar que por la naturaleza tan especial de estas clases de objeto, debemos tener muy en cuenta las tres restricciones que enumero en uno de los comentarios del código fuente. Si las respetamos, tendremos una solución Delphi de memoria compartida muy práctica y accesible.&lt;br /&gt;&lt;br /&gt;Espero les sea de utilidad a la hora de compartir datos entre procesos. Todas las preguntas y sugerencias al respecto serán bien recibidas.&lt;br /&gt;&lt;br /&gt;Un abrazo superglobal.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-8632350332852095903?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/8632350332852095903/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/03/objetos-superglobales.html#comment-form' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8632350332852095903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/8632350332852095903'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/03/objetos-superglobales.html' title='Objetos superglobales.  Memoria compartida como nunca antes.'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-345079389984793898</id><published>2008-02-02T02:31:00.000-06:00</published><updated>2008-02-02T10:26:17.845-06:00</updated><title type='text'>Acertadísima adquisición rusa</title><content type='html'>&lt;div align="left"&gt;¡Hola!&lt;br /&gt;&lt;br /&gt;Antes que nada les pido una disculpa por no hablar aún del tema que les había prometido (objetos compartidos). Eso será en unos días.&lt;br /&gt;&lt;br /&gt;Hoy me enteré de que, este viernes 1 de febrero de 2008, CodeGear anunció la venta de...¡sujétense!...&lt;strong&gt;un millón&lt;/strong&gt; de licencias a la Agencia Federal Rusa de Educación para la enseñanza de programación y desarrollo de aplicaciones a estudiantes rusos. Delphi y C++ Builder estarán en &lt;strong&gt;todas&lt;/strong&gt; las escuelas primarias y secundarias de Rusia para enseñarse a su nueva generación de programadores. Esta importantísima venta es parte de una iniciativa federal rusa de 100 millones de dólares llamada &lt;em&gt;Proyecto de Estado Nacional de Educación de Alto Grado&lt;/em&gt;. Con esto, el gobierno ruso espera incrementar la calidad de la educación a lo largo del país proporcionando a maestros y estudiantes acceso a las mejores tecnologías de información disponibles.&lt;br /&gt;&lt;br /&gt;Según la &lt;a href="http://biz.yahoo.com/bw/080201/20080201005191.html?.v=1"&gt;nota de la cual obtuve esta información&lt;/a&gt;, los reportes del gobierno indican que Delphi y Pascal están entre los lenguajes de programación más ampliamente utilizados en el país (yo no lo dudo, hay muy buenos desarrolladores Delphi en Rusia, destacando significativamente los bibliotecarios), y el uso de las herramientas de CodeGear es tan abundante que más de 600 obras consagradas a los productos de CodeGear y Borland han sido lanzadas por el mercado ruso.&lt;br /&gt;&lt;br /&gt;Sin duda es una estupenda noticia de la cual debemos esperar que sucedan cosas buenas para nuestro Delphi, gracias a que CodeGear se beneficiará de una buena inyección de capital. Está claro que algunos de esos beneficios tendrán que repercutir en mejoras para la atención a Hispanoamérica. Es más, creo que esto podría propiciar que existan versiones del entorno de Delphi y su venerable ayuda en dos nuevos idiomas: ruso y castellano. También podríamos ver políticas de difusión, mercadotecnia y comercialización más hechas y eficientes, empezando por mejorar el logotipo y cumpliendo cabalmente con el eslogan.&lt;br /&gt;&lt;br /&gt;Pero sean cuales sean las repercusiones para nosotros, estoy seguro que consistirán en algo muy positivo. Felicidades a CodeGear por este importante acuerdo.&lt;br /&gt;&lt;br /&gt;¿Ustedes qué opinan?&lt;br /&gt;&lt;br /&gt;Un abrazo ruso.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-345079389984793898?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/345079389984793898/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/02/acertadsima-adquisicin-rusa.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/345079389984793898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/345079389984793898'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/02/acertadsima-adquisicin-rusa.html' title='Acertadísima adquisición rusa'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8419825193906400044.post-309763674947485069</id><published>2008-01-29T01:46:00.000-06:00</published><updated>2008-01-29T02:09:36.349-06:00</updated><title type='text'>Una cordial bienvenida</title><content type='html'>Espero que sus visitas a este sitio se traduzcan en algo muy positivo para sus vidas como desarrolladores y como personas que no se conforman con el alimento del rumor.&lt;br /&gt;&lt;br /&gt;En la siguiente entrada daré algunos datos sobre mí, para el lector que me conoce poco o nada (que espero sean muchos ;)).&lt;br /&gt;&lt;br /&gt;Un abrazo inicial.&lt;br /&gt;&lt;br /&gt;Al González. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8419825193906400044-309763674947485069?l=rescatandoadelphi.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rescatandoadelphi.blogspot.com/feeds/309763674947485069/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/01/una-cordial-bienvenida.html#comment-form' title='12 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/309763674947485069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8419825193906400044/posts/default/309763674947485069'/><link rel='alternate' type='text/html' href='http://rescatandoadelphi.blogspot.com/2008/01/una-cordial-bienvenida.html' title='Una cordial bienvenida'/><author><name>Al González</name><uri>http://www.blogger.com/profile/01863287140078495218</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_9N_Agt_qWL4/S1zhc5V-_hI/AAAAAAAAAG8/H4YGPv2LMhY/S220/SDC10357c.JPG'/></author><thr:total>12</thr:total></entry></feed>
