• R/O
  • SSH
  • HTTPS

zostportal: Commit


Commit MetaInfo

Revision109 (tree)
Time2021-04-26 02:35:23
Authorderekwildstar

Log Message

Backup pré atualização

Change Summary

Incremental Difference

--- trunk/Backup/zost.sql (revision 108)
+++ trunk/Backup/zost.sql (revision 109)
@@ -175,7 +175,7 @@
175175 UNIQUE KEY `idx_asset_name` (`name`),
176176 KEY `idx_lft_rgt` (`lft`,`rgt`),
177177 KEY `idx_parent_id` (`parent_id`)
178-) ENGINE=InnoDB AUTO_INCREMENT=614 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
178+) ENGINE=InnoDB AUTO_INCREMENT=615 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
179179 /*!40101 SET character_set_client = @saved_cs_client */;
180180
181181 --
@@ -184,7 +184,7 @@
184184
185185 LOCK TABLES `joomla_assets` WRITE;
186186 /*!40000 ALTER TABLE `joomla_assets` DISABLE KEYS */;
187-INSERT INTO `joomla_assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES (1,0,1,956,0,'root.1','Root Asset','{\"core.login.site\":{\"6\":1,\"2\":1},\"core.login.admin\":{\"6\":1},\"core.admin\":{\"8\":1},\"core.manage\":{\"7\":1},\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1},\"attachments.delete.own\":{\"6\":1,\"3\":1},\"attachments.edit.state.own\":{\"6\":1,\"4\":1},\"attachments.edit.state.ownparent\":{\"6\":1,\"4\":1},\"attachments.edit.ownparent\":{\"6\":1,\"3\":1},\"attachments.delete.ownparent\":{\"6\":1,\"3\":1}}'),(2,1,2,3,1,'com_admin','com_admin','{}'),(3,1,4,19,1,'com_banners','com_banners','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(4,1,20,21,1,'com_cache','com_cache','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(5,1,22,23,1,'com_checkin','com_checkin','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(6,1,24,25,1,'com_config','com_config','{}'),(7,1,26,103,1,'com_contact','com_contact','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(8,1,104,441,1,'com_content','com_content','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(9,1,442,443,1,'com_cpanel','com_cpanel','{}'),(10,1,444,445,1,'com_installer','com_installer','{\"core.admin\":[],\"core.manage\":{\"7\":0},\"core.delete\":{\"7\":0},\"core.edit.state\":{\"7\":0}}'),(11,1,446,447,1,'com_languages','com_languages','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(12,1,448,449,1,'com_login','com_login','{}'),(13,1,450,451,1,'com_mailto','com_mailto','{}'),(14,1,452,453,1,'com_massmail','com_massmail','{}'),(15,1,454,455,1,'com_media','com_media','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":{\"5\":1}}'),(16,1,456,465,1,'com_menus','com_menus','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(17,1,45,46,1,'com_messages','com_messages','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(18,1,468,599,1,'com_modules','com_modules','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(19,1,600,607,1,'com_newsfeeds','com_newsfeeds','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(20,1,608,609,1,'com_plugins','com_plugins','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(21,1,610,611,1,'com_redirect','com_redirect','{\"core.admin\":{\"7\":1},\"core.manage\":[]}'),(22,1,612,613,1,'com_search','com_search','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1}}'),(23,1,614,615,1,'com_templates','com_templates','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(24,1,616,619,1,'com_users','com_users','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(25,1,620,627,1,'com_weblinks','com_weblinks','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1,\"10\":0,\"12\":0},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1}}'),(26,1,628,629,1,'com_wrapper','com_wrapper','{}'),(33,1,690,691,1,'com_finder','com_finder','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1}}'),(36,7,31,32,2,'com_contact.category.11','Uncategorised','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(37,19,603,604,2,'com_newsfeeds.category.12','Uncategorised','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(41,7,33,94,2,'com_contact.category.16','Sample Data-Contact','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(42,19,605,606,2,'com_newsfeeds.category.17','Sample Data-Newsfeeds','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(59,41,34,35,3,'com_contact.category.34','Park Site','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(60,41,36,93,3,'com_contact.category.35','Shop Site','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(61,60,37,38,4,'com_contact.category.36','Staff','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(62,60,39,92,4,'com_contact.category.37','Fruit Encyclopedia','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(63,62,40,41,5,'com_contact.category.38','A','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(64,62,42,43,5,'com_contact.category.39','B','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(65,62,44,45,5,'com_contact.category.40','C','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(66,62,46,47,5,'com_contact.category.41','D','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(67,62,48,49,5,'com_contact.category.42','E','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(68,62,50,51,5,'com_contact.category.43','F','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(69,62,52,53,5,'com_contact.category.44','G','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(70,62,54,55,5,'com_contact.category.45','H','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(71,62,56,57,5,'com_contact.category.46','I','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(72,62,58,59,5,'com_contact.category.47','J','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(73,62,60,61,5,'com_contact.category.48','K','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(74,62,62,63,5,'com_contact.category.49','L','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(75,62,64,65,5,'com_contact.category.50','M','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(76,62,66,67,5,'com_contact.category.51','N','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(77,62,68,69,5,'com_contact.category.52','O','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(78,62,70,71,5,'com_contact.category.53','P','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(79,62,72,73,5,'com_contact.category.54','Q','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(80,62,74,75,5,'com_contact.category.55','R','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(81,62,76,77,5,'com_contact.category.56','S','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(82,62,78,79,5,'com_contact.category.57','T','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(83,62,80,81,5,'com_contact.category.58','U','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(84,62,82,83,5,'com_contact.category.59','V','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(85,62,84,85,5,'com_contact.category.60','W','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(86,62,86,87,5,'com_contact.category.61','X','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(87,62,88,89,5,'com_contact.category.62','Y','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(88,62,90,91,5,'com_contact.category.63','Z','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(100,8,123,124,2,'com_content.category.71','Milky Way','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(169,24,617,618,2,'com_users.notes.category.77','Uncategorised',''),(173,1,692,693,1,'com_joomlaupdate','com_joomlaupdate','{\"core.admin\":[],\"core.manage\":[],\"core.delete\":[],\"core.edit.state\":[]}'),(174,211,198,199,5,'com_content.article.71','Comprimindo os Data Packets no DataSnap','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(176,8,193,440,2,'com_content.category.79','Addicted 2 Delphi!','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(177,176,194,399,3,'com_content.category.80','Artigos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(178,176,400,439,3,'com_content.category.81','Tutoriais','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(179,196,138,145,5,'com_content.category.82','Componentes','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(182,195,152,161,3,'com_content.category.85','Notícias','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(183,195,128,135,3,'com_content.category.86','Informações','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(184,195,136,151,3,'com_content.category.87','Nossos produtos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(187,183,133,134,4,'com_content.article.72','Quem somos','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(188,183,129,130,4,'com_content.article.73','O que fazemos','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(189,183,131,132,4,'com_content.article.74','Nossa missão','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(195,8,127,178,2,'com_content.category.93','ZØST','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(196,184,137,146,4,'com_content.category.94','Delphi','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(197,184,147,150,4,'com_content.category.95','PHP','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(199,8,179,192,2,'com_content.category.96','Addicted 2 PHP!','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(200,199,180,189,3,'com_content.category.97','Artigos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(201,268,184,185,5,'com_content.article.78','Como funciona o breadcrumb','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(203,177,195,196,4,'com_content.article.80','Ordem de criação e execução de ApplyUpdates','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(204,211,200,201,5,'com_content.article.81','Alteração de conexão em servidor DataSnap','{\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1}}'),(211,177,197,204,4,'com_content.category.99','DataSnap','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(213,199,190,191,3,'com_content.category.101','Tutoriais','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(220,177,205,206,4,'com_content.article.89','10 razões para ser um desenvolvedor Delphi','{}'),(221,197,148,149,5,'com_content.category.105','Bibliotecas','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(222,177,207,208,4,'com_content.article.90','A verdade sobre o TDataModule e o consumo de memória','{}'),(223,1,694,695,1,'com_attachments','com_attachments','{}'),(224,177,209,210,4,'com_content.article.91','Avaliação booleana em modo \"curto-circuito\" e operandos do tipo Variant','{}'),(225,177,211,212,4,'com_content.article.92','Como obter a real diferença entre dois valores TDateTime','{}'),(226,211,202,203,5,'com_content.article.93','Corrigindo mensagens de erro EReconcileError truncadas','{}'),(227,250,96,97,3,'com_contact.category.106','Proprietários','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(228,179,139,140,6,'com_content.article.94','User Control DXC Edition','{}'),(230,1,696,697,1,'com_tags','com_tags','{}'),(231,1,698,699,1,'com_contenthistory','com_contenthistory','{}'),(232,1,700,701,1,'com_ajax','com_ajax','{}'),(233,1,702,703,1,'com_postinstall','com_postinstall','{}'),(235,1,704,705,1,'com_gantry','Gantry','{}'),(237,18,469,470,2,'com_modules.module.101','titulo.cus','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(238,18,471,472,2,'com_modules.module.103','login.log.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(239,18,473,474,2,'com_modules.module.93','zost.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(240,18,475,476,2,'com_modules.module.111','a2d.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(241,18,477,478,2,'com_modules.module.112','a2p.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(242,18,479,480,2,'com_modules.module.119','myprofile.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(247,1,706,707,1,'#__ucm_content.1','#__ucm_content.1','[]'),(248,18,481,482,2,'com_modules.module.107','whosonline.won.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(249,18,483,484,2,'com_modules.module.100','footer.ban','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(250,7,95,102,2,'com_contact.category.107','ZØST','{}'),(255,268,182,183,5,'com_content.article.96','Categorias e Itens de menu','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(256,1,708,709,1,'#__ucm_content.2','#__ucm_content.2','[]'),(257,177,213,214,4,'com_content.article.97','Serialização de Objetos & Persistência em Arquivos','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(258,177,215,216,4,'com_content.article.98','Quando o TClientDataSet e o TDataSetProvider são necessários?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(259,1,710,711,1,'#__ucm_content.3','#__ucm_content.3','{}'),(260,18,485,486,2,'com_modules.module.97','first.fed.beu','{}'),(261,18,487,488,2,'com_modules.module.98','second.fed.beu','{}'),(262,18,489,490,2,'com_modules.module.94','first.fed','{}'),(263,18,491,492,2,'com_modules.module.96','second.fed','{}'),(264,250,98,99,3,'com_contact.category.108','Colaboradores','{}'),(265,250,100,101,3,'com_contact.category.109','Parceiros','{}'),(267,1,712,713,1,'#__ucm_content.4','#__ucm_content.4','{}'),(268,200,181,188,4,'com_content.category.110','Joomla!','{}'),(269,1,714,715,1,'#__ucm_content.5','#__ucm_content.5','[]'),(270,1,716,717,1,'#__ucm_content.6','#__ucm_content.6','{}'),(271,1,718,719,1,'#__ucm_content.7','#__ucm_content.7','{}'),(272,1,720,721,1,'#__ucm_content.8','#__ucm_content.8','{}'),(273,1,722,723,1,'#__ucm_content.9','#__ucm_content.9','[]'),(274,177,217,218,4,'com_content.article.100','Quando devo registrar uma DLL?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(275,1,724,725,1,'#__ucm_content.10','#__ucm_content.10','[]'),(276,177,219,220,4,'com_content.article.101','XML Mapper: Convertendo um XML genérico em Data Packet','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(277,1,726,727,1,'#__ucm_content.11','#__ucm_content.11','{}'),(280,1,728,729,1,'#__ucm_content.12','#__ucm_content.12','{}'),(281,3,7,8,2,'com_banners.category.111','Banners inferiores','{}'),(282,18,493,494,2,'com_modules.module.108','footer.ban.beu','{}'),(284,177,221,222,4,'com_content.article.102','Como usar corretamente uma barra de progresso (TProgressBar)?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(285,1,730,731,1,'#__ucm_content.13','#__ucm_content.13','{}'),(286,177,223,224,4,'com_content.article.103','O lado negro do Application.ProcessMessages','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(287,1,732,733,1,'#__ucm_content.14','#__ucm_content.14','{}'),(288,177,225,226,4,'com_content.article.104','Entendendo a instalação de componentes','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(289,177,227,228,4,'com_content.article.105','Desmistificando as Interfaces no Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(290,177,229,230,4,'com_content.article.106','Como depurar um Serviço do Windows (Windows Service)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(291,1,734,735,1,'#__ucm_content.15','#__ucm_content.15','[]'),(292,18,495,496,2,'com_modules.module.123','donate.cus','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(293,18,497,498,2,'com_modules.module.124','donate.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(294,177,231,232,4,'com_content.article.107','Como validar um XML com um XSD usando o Delphi?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(295,1,736,737,1,'#__ucm_content.16','#__ucm_content.16','{}'),(296,18,499,500,2,'com_modules.module.125','articleshighlight.syf','{}'),(297,18,501,502,2,'com_modules.module.126','articlehighlight.syf.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(298,18,503,504,2,'com_modules.module.127','news.syf.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(299,18,505,506,2,'com_modules.module.128','news.syf','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(300,177,233,234,4,'com_content.article.108','Sobrecarga de operadores','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(301,1,738,739,1,'#__ucm_content.17','#__ucm_content.17','[]'),(302,18,507,508,2,'com_modules.module.129','statistics.cus','{}'),(303,18,509,510,2,'com_modules.module.130','statistics.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(304,177,235,236,4,'com_content.article.109','Windows Messages: A base da programação orientada a eventos','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(305,1,740,741,1,'#__ucm_content.18','#__ucm_content.18','[]'),(306,177,237,238,4,'com_content.article.110','Uso pleno do TClientDataSet e o Modelo de Maleta','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(307,1,742,743,1,'#__ucm_content.19','#__ucm_content.19','{}'),(308,18,511,512,2,'com_modules.module.131','language.gtr','{}'),(309,18,513,514,2,'com_modules.module.132','language.gtr.beu','{}'),(310,177,239,240,4,'com_content.article.111','Classes Mediadoras (interposer)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(311,18,515,516,2,'com_modules.module.133','consortium.cus','{}'),(312,18,517,518,2,'com_modules.module.134','consortium.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(314,1,744,745,1,'#__ucm_content.20','#__ucm_content.20','{}'),(315,177,241,242,4,'com_content.article.112','Assinando digitalmente aplicações Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(316,1,746,747,1,'#__ucm_content.21','#__ucm_content.21','{}'),(317,177,243,244,4,'com_content.article.113','Obtendo o serial físico de um HD','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(318,358,402,403,5,'com_content.article.114','DataSnap Sobre SOAP (Parte 1): Apache e DLL ISAPI','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(319,358,404,405,5,'com_content.article.115','DataSnap Sobre SOAP (Parte 2): SGBD e componentes de conexão','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(320,358,406,407,5,'com_content.article.116','DataSnap Sobre SOAP (Parte 3): Configurando o Apache','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(321,358,408,409,5,'com_content.article.117','DataSnap Sobre SOAP (Parte 4): A DLL ISAPI Básica','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(322,358,410,411,5,'com_content.article.118','DataSnap Sobre SOAP (Parte 5): Um Soap Server DataModule na DLL ISAPI','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(323,358,412,413,5,'com_content.article.119','DataSnap Sobre SOAP (Parte 6): Testando o WebService','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(324,358,414,415,5,'com_content.article.120','DataSnap Sobre SOAP (Parte 7): Estendendo o Soap Server DataModule','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(325,1,748,749,1,'#__ucm_content.22','#__ucm_content.22','{}'),(326,18,519,520,2,'com_modules.module.135','statistics.cus.mobile','{}'),(327,18,521,522,2,'com_modules.module.136','consortium.cus.mobile','{}'),(329,268,186,187,5,'com_content.article.121','Criando um sistema de notas de rodapé','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(330,177,245,246,4,'com_content.article.122','Open Tools API','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(331,1,750,751,1,'#__ucm_content.23','#__ucm_content.23','{}'),(333,1,752,753,1,'#__ucm_content.24','#__ucm_content.24','[]'),(335,1,754,755,1,'#__ucm_content.26','#__ucm_content.26','{}'),(336,182,153,154,4,'com_content.article.124','UserControl Suite Delphi Experts Consortium Edition','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(337,1,756,757,1,'#__ucm_content.27','#__ucm_content.27','{}'),(338,177,247,248,4,'com_content.article.125','Variant Open Array Parameters','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(339,1,758,759,1,'#__ucm_content.28','#__ucm_content.28','{}'),(340,182,155,156,4,'com_content.article.126','UCDXCE: Progresso dos testes','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(341,1,760,761,1,'#__ucm_content.29','#__ucm_content.29','{}'),(342,177,249,250,4,'com_content.article.127','Diretivas de compilação e versões do Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(343,177,251,252,4,'com_content.article.128','Compilando um projeto Delphi pela linha de comando','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(344,1,762,763,1,'#__ucm_content.30','#__ucm_content.30','{}'),(345,177,253,254,4,'com_content.article.129','Configurando e usando o MySQL Embedded','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(346,1,764,765,1,'#__ucm_content.31','#__ucm_content.31','{}'),(347,1,766,767,1,'#__ucm_content.32','#__ucm_content.32','{}'),(348,177,255,256,4,'com_content.article.130','Biometria básica com o U.are.U 4000B (Digital Persona / Crossmatch)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(349,1,768,769,1,'#__ucm_content.33','#__ucm_content.33','{}'),(350,371,173,174,4,'com_content.article.131','SSCCE: Uma necessidade pouco conhecida','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(351,1,770,771,1,'#__ucm_content.34','#__ucm_content.34','{}'),(352,1,772,773,1,'#__ucm_content.35','#__ucm_content.35','{}'),(353,18,523,524,2,'com_modules.module.138','left.ban.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(354,18,525,526,2,'com_modules.module.139','left.ban','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(355,3,9,10,2,'com_banners.category.112','Banners esquerdos','{}'),(357,1,774,775,1,'com_extplorer','eXtplorer','{}'),(358,178,401,416,4,'com_content.category.113','DataSnap','{}'),(359,177,257,258,4,'com_content.article.132','Manipulando XMLs com XPath no Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(360,1,776,777,1,'#__ucm_content.36','#__ucm_content.36','{}'),(361,179,141,142,6,'com_content.article.133','Anak Krakatoa Defined Crypt','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(362,1,778,779,1,'#__ucm_content.37','#__ucm_content.37','{}'),(363,179,143,144,6,'com_content.article.134','Zetta-Ømnis Packages Creator','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(364,1,780,781,1,'#__ucm_content.38','#__ucm_content.38','{}'),(365,177,259,260,4,'com_content.article.135','Por que os meus executáveis Delphi são tão grandes?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(366,1,782,783,1,'#__ucm_content.39','#__ucm_content.39','{}'),(369,182,157,158,4,'com_content.article.137','UCDXCE: Remoção completa do sistema de tradução','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(370,1,784,785,1,'#__ucm_content.41','#__ucm_content.41','[]'),(371,195,162,177,3,'com_content.category.114','Artigos','{}'),(372,371,163,164,4,'com_content.article.138','Instalação e configuração manual do MySQL no Windows','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(373,1,786,787,1,'#__ucm_content.42','#__ucm_content.42','{}'),(374,177,261,262,4,'com_content.article.139','Uso de BPLs para modularizar aplicações Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(375,1,788,789,1,'#__ucm_content.43','#__ucm_content.43','{}'),(376,1,790,791,1,'com_fields','com_fields','{}'),(377,1,792,793,1,'com_associations','com_associations','{}'),(378,371,165,166,4,'com_content.article.140','Instalação e configuração manual do PostgreSQL no Windows','{}'),(379,1,794,795,1,'#__ucm_content.44','#__ucm_content.44','{}'),(380,1,796,797,1,'com_fst','COM_FST','{}'),(383,18,527,528,2,'com_modules.module.143','testimonials.tes','{}'),(384,18,529,530,2,'com_modules.module.144','testimonials.tes.beu','{}'),(388,178,417,418,4,'com_content.article.141','Inno Setup (Parte 1): Introdução & Inno Script Studio','{}'),(389,1,798,799,1,'#__ucm_content.45','#__ucm_content.45','{}'),(390,178,419,420,4,'com_content.article.142','Inno Setup (Parte 2): Criando o projeto básico','{}'),(391,1,800,801,1,'#__ucm_content.46','#__ucm_content.46','{}'),(392,178,421,422,4,'com_content.article.143','Inno Setup (Parte 3): Instalando o PostgreSQL','{}'),(393,177,263,264,4,'com_content.article.144','WinInet + CryptoAPI + SSL: Use a API do Windows em seu favor','{}'),(394,1,802,803,1,'#__ucm_content.47','#__ucm_content.47','{}'),(395,178,423,424,4,'com_content.article.145','Inno Setup (Parte 4): Types, Components e Tasks','{}'),(396,1,804,805,1,'#__ucm_content.48','#__ucm_content.48','{}'),(397,1,806,807,1,'#__ucm_content.49','#__ucm_content.49','{}'),(398,178,425,426,4,'com_content.article.146','Inno Setup (Parte 5): Configurando o PostgreSQL','{}'),(399,177,265,266,4,'com_content.article.147','Entendendo o JSON (Parte 2)','{}'),(400,177,267,268,4,'com_content.article.148','Entendendo o JSON (Parte 1)','{}'),(401,1,808,809,1,'#__ucm_content.50','#__ucm_content.50','{}'),(402,1,810,811,1,'#__ucm_content.51','#__ucm_content.51','{}'),(403,371,167,168,4,'com_content.article.149','O limite da persistência ao buscar uma solução','{}'),(404,1,812,813,1,'#__ucm_content.52','#__ucm_content.52','{}'),(406,1,814,815,1,'#__ucm_content.53','#__ucm_content.53','{}'),(407,178,427,428,4,'com_content.article.150','Inno Setup (Parte 6): Página personalizada I','{}'),(408,1,816,817,1,'#__ucm_content.54','#__ucm_content.54','{}'),(410,18,531,532,2,'com_modules.module.149','maintainer.cus.beu','{}'),(411,18,533,534,2,'com_modules.module.150','maintainer.cus','{}'),(412,178,429,430,4,'com_content.article.151','Inno Setup (Parte 8): Página personalizada II','{}'),(413,177,397,398,4,'com_content.article.152','Correção para o erro «EditorLineEnds.ttr» ao iniciar o Delphi','{}'),(414,1,818,819,1,'#__ucm_content.55','#__ucm_content.55','{}'),(415,178,431,432,4,'com_content.article.153','Inno Setup (Parte 7): Melhorando a execução de programas externos','{}'),(416,1,820,821,1,'#__ucm_content.56','#__ucm_content.56','{}'),(417,1,822,823,1,'#__ucm_content.57','#__ucm_content.57','{}'),(418,178,433,434,4,'com_content.article.154','Inno Setup (Parte 9): Assinando digitalmente o instalador','{}'),(419,1,824,825,1,'#__ucm_content.58','#__ucm_content.58','{}'),(420,18,535,536,2,'com_modules.module.151','qrcode.cus.beu','{}'),(422,18,537,538,2,'com_modules.module.153','qrcode.cus','{}'),(423,178,435,436,4,'com_content.article.155','Inno Setup (Parte 10): Página personalizada III','{}'),(424,1,826,827,1,'#__ucm_content.59','#__ucm_content.59','{}'),(425,182,159,160,4,'com_content.article.156','Delphi & C++ Builder Community Edition!','{}'),(426,1,828,829,1,'#__ucm_content.60','#__ucm_content.60','{}'),(427,177,269,270,4,'com_content.article.157','Design Layout para Restaurantes com VCL (Parte 1)','{}'),(428,1,830,831,1,'#__ucm_content.61','#__ucm_content.61','{}'),(429,177,271,272,4,'com_content.article.158','Design Layout para Restaurantes com VCL (Parte 2)','{}'),(430,1,832,833,1,'#__ucm_content.62','#__ucm_content.62','{}'),(431,177,273,274,4,'com_content.article.159','Emissor NF-e e NFC-e Delphi - Parte 1: Instalação do ACBr no Delphi','{}'),(432,1,834,835,1,'#__ucm_content.63','#__ucm_content.63','{}'),(433,177,275,276,4,'com_content.article.160','Emissor NF-e e NFC-e Delphi - Parte 2: Instalação do ZeosLib no Delphi','{}'),(434,1,836,837,1,'#__ucm_content.64','#__ucm_content.64','{}'),(435,177,277,278,4,'com_content.article.161','Emissor NF-e e NFC-e Delphi - Parte 3: Instalação do banco de dados PostgreSQL','{}'),(436,1,838,839,1,'#__ucm_content.65','#__ucm_content.65','{}'),(437,177,279,280,4,'com_content.article.162','Emissor NF-e e NFC-e Delphi - Parte 4: Criação da estrutura do banco de dados','{}'),(438,1,840,841,1,'#__ucm_content.66','#__ucm_content.66','{}'),(439,177,281,282,4,'com_content.article.163','Emissor NF-e e NFC-e Delphi - Parte 5: Criação do menu de acesso do projeto','{}'),(440,1,842,843,1,'#__ucm_content.67','#__ucm_content.67','{}'),(441,177,283,284,4,'com_content.article.164','Emissor NF-e e NFC-e Delphi - Parte 6: Criação da conexão com o banco de dados utilizando o TZConnec','{}'),(442,1,844,845,1,'#__ucm_content.68','#__ucm_content.68','{}'),(443,177,285,286,4,'com_content.article.165','Apresentando as variáveis inline na linguagem Delphi','{}'),(444,1,846,847,1,'#__ucm_content.69','#__ucm_content.69','{}'),(445,177,287,288,4,'com_content.article.166','Emissor NF-e e NFC-e Delphi - Parte 7: Criação da Tela de Cadastro de Clientes','{}'),(446,1,848,849,1,'#__ucm_content.70','#__ucm_content.70','{}'),(447,177,289,290,4,'com_content.article.167','Suporte ao Per Monitor v2 e ao GetSystemMetrics na VCL chegando ao 10.3!','{}'),(448,1,850,851,1,'#__ucm_content.71','#__ucm_content.71','{}'),(449,1,852,853,1,'com_privacy','com_privacy','{}'),(450,1,854,855,1,'com_actionlogs','com_actionlogs','{}'),(451,18,539,540,2,'com_modules.module.154','left2.ban','{}'),(452,18,541,542,2,'com_modules.module.155','left2.ban.beu','{}'),(453,177,291,292,4,'com_content.article.168','Emissor NF-e e NFC-e Delphi - Parte 8: Gravando os dados e realizando a pesquisa','{}'),(454,1,856,857,1,'#__ucm_content.72','#__ucm_content.72','{}'),(455,177,293,294,4,'com_content.article.169','Emissor NF-e e NFC-e Delphi - Parte 9: Listar cidades e estados no cadastro de clientes','{}'),(456,1,858,859,1,'#__ucm_content.73','#__ucm_content.73','{}'),(457,177,295,296,4,'com_content.article.170','Resolvendo o problema dos breakpoints fora de sincronia','{}'),(458,1,860,861,1,'#__ucm_content.74','#__ucm_content.74','{}'),(459,178,437,438,4,'com_content.article.171','Inno Setup (Parte 11): Personalização Final (o \"Road Map\")','{}'),(460,1,862,863,1,'#__ucm_content.75','#__ucm_content.75','{}'),(461,177,297,298,4,'com_content.article.172','Como fazer uma \"tela de splash\" visualmente impressionante','{}'),(462,177,299,300,4,'com_content.article.173','Emissor NF-e e NFC-e Delphi - Parte 10: Criando o cadastro de transportadoras','{}'),(463,1,864,865,1,'#__ucm_content.76','#__ucm_content.76','{}'),(464,177,301,302,4,'com_content.article.174','Emissor NF-e e NFC-e Delphi - Parte 11: Criação das telas de produtos e certificados digitais','{}'),(465,1,866,867,1,'#__ucm_content.77','#__ucm_content.77','{}'),(466,177,303,304,4,'com_content.article.175','Emissor NF-e e NFC-e Delphi - Parte 12: Finalizando o cadastro de produtos','{}'),(467,1,868,869,1,'#__ucm_content.78','#__ucm_content.78','{}'),(468,177,305,306,4,'com_content.article.176','Emissor NF-e e NFC-e Delphi - Parte 13: Cadastro de emitente','{}'),(469,1,870,871,1,'#__ucm_content.79','#__ucm_content.79','{}'),(470,371,171,172,4,'com_content.article.177','Repositório de versões do Delphi e C++ Builder','{}'),(471,1,872,873,1,'#__ucm_content.80','#__ucm_content.80','{}'),(472,177,307,308,4,'com_content.article.178','Emissor NF-e e NFC-e Delphi - Parte 14: Consultando status do serviço da NF-e e NFC-e','{}'),(473,1,874,875,1,'#__ucm_content.81','#__ucm_content.81','{}'),(474,177,309,310,4,'com_content.article.179','Emissor NF-e e NFC-e Delphi - Parte 15: Criação da tela de emissão de NFC-e','{}'),(475,1,876,877,1,'#__ucm_content.82','#__ucm_content.82','{}'),(476,177,311,312,4,'com_content.article.180','Emissor NF-e e NFC-e Delphi - Parte 16: Inserindo itens na NFC-e','{}'),(477,1,878,879,1,'#__ucm_content.83','#__ucm_content.83','{}'),(478,177,313,314,4,'com_content.article.181','Emissor NF-e e NFC-e Delphi - Parte 17: Calculando a quantidade de itens e criando as pesquisas','{}'),(479,1,880,881,1,'#__ucm_content.84','#__ucm_content.84','{}'),(480,177,315,316,4,'com_content.article.182','Emissor NF-e e NFC-e Delphi - Parte 18: Totalizando o cupom fiscal','{}'),(481,1,882,883,1,'#__ucm_content.85','#__ucm_content.85','{}'),(482,177,317,318,4,'com_content.article.183','Emissor NF-e e NFC-e Delphi - Parte 19: Inserindo os pagamentos na venda','{}'),(483,1,884,885,1,'#__ucm_content.86','#__ucm_content.86','{}'),(484,177,319,320,4,'com_content.article.184','Emissor NF-e e NFC-e Delphi - Parte 20: Gravando e listando os dados da venda','{}'),(485,1,886,887,1,'#__ucm_content.87','#__ucm_content.87','{}'),(486,177,321,322,4,'com_content.article.185','Os tipos NativeInt e NativeUInt em Delphis pré 2009 #AQuemPossaInteressar','{}'),(487,1,888,889,1,'#__ucm_content.88','#__ucm_content.88','{}'),(488,177,323,324,4,'com_content.article.186','O TWebBrowser pode causar Access Violation ao fechar um programa #AQuemPossaInteressar','{}'),(491,177,325,326,4,'com_content.article.189','O que são e quais os tipos de Type Aliases #AQuemPossaInteressar','{}'),(492,177,327,328,4,'com_content.article.190','Qual a diferença entre New, GetMem e AllocMem #AQuemPossaInteressar','{}'),(493,177,329,330,4,'com_content.article.191','Erro intermitente ao conectar-se ao MySQL Embedded #AQuemPossaInteressar','{}'),(494,177,331,332,4,'com_content.article.192','Herança de interfaces e implementação explícita de interfaces-base #AQuemPossaInteressar','{}'),(495,177,333,334,4,'com_content.article.193','Interfaces que não se autodestroem #AQuemPossaInteressar ','{}'),(496,177,335,336,4,'com_content.article.194','Path do sistema, package output directory e como o Delphi encontra seus pacotes #AQuemPossaInteressa','{}'),(497,177,337,338,4,'com_content.article.195','Interdependência entre pacotes e sua relação com o \"library path\"','{}'),(498,177,339,340,4,'com_content.article.196','ID3v2 Editor Plus!','{}'),(499,1,890,891,1,'#__ucm_content.89','#__ucm_content.89','{}'),(500,177,341,342,4,'com_content.article.197','Campos agregados e GroupState no TClientDataSet','{}'),(501,1,892,893,1,'#__ucm_content.90','#__ucm_content.90','{}'),(502,1,894,895,1,'#__ucm_content.91','#__ucm_content.91','{}'),(503,177,343,344,4,'com_content.article.198','Dê nome as suas threads, mesmo aquelas criadas pelo Delphi!','{}'),(504,1,896,897,1,'#__ucm_content.92','#__ucm_content.92','{}'),(505,18,543,544,2,'com_modules.module.156','language.gtr.mobile','{}'),(506,18,545,546,2,'com_modules.module.157','language.gtr.beu.2','{}'),(507,1,898,899,1,'#__ucm_content.93','#__ucm_content.93','{}'),(508,18,547,548,2,'com_modules.module.158','basicblack-breadcrumbs','{}'),(510,18,549,550,2,'com_modules.module.160','basicblack-menu','{}'),(511,18,551,552,2,'com_modules.module.161','Acesso Rápido','{}'),(513,18,553,554,2,'com_modules.module.163','Fique por dentro','{}'),(514,18,555,556,2,'com_modules.module.164','DO NOT UNDERSTAND PORTUGUESE? CLICK ON THE FLAG TO CHANGE THE LANGUAGE!','{}'),(515,18,557,558,2,'com_modules.module.165','Fique por dentro','{}'),(516,18,559,560,2,'com_modules.module.166','Autenticação','{}'),(518,18,561,562,2,'com_modules.module.104','login.log','{}'),(519,371,169,170,4,'com_content.article.199','Você precisa conhecer o Chasys Draw IES!','{}'),(520,1,900,901,1,'#__ucm_content.94','#__ucm_content.94','{}'),(522,18,563,564,2,'com_modules.module.102','whosonline.won','{}'),(525,18,565,566,2,'com_modules.module.171','Visite Nosso Patrocinador','{}'),(526,3,11,12,2,'com_banners.category.115','Banners direitos (Basic Black)','{}'),(527,18,567,568,2,'com_modules.module.172','Visite Nosso Patrocinador','{}'),(528,18,569,570,2,'com_modules.module.173','Seções em ZØST','{}'),(529,18,571,572,2,'com_modules.module.174','Seções em A2D!','{}'),(530,18,573,574,2,'com_modules.module.175','Seções em A2P!','{}'),(533,3,13,14,2,'com_banners.category.116','Banners esquerdos (Basic Black)','{}'),(534,18,575,576,2,'com_modules.module.177','Meu Perfil','{}'),(535,16,457,458,2,'com_menus.menu.8','ZØST','{}'),(536,16,459,460,2,'com_menus.menu.9','Addicted 2 Delphi!','{}'),(537,16,461,462,2,'com_menus.menu.10','Addicted 2 PHP!','{}'),(538,16,463,464,2,'com_menus.menu.6','Menu principal','{}'),(539,18,577,578,2,'com_modules.module.178','Conteúdo Verificado!','{}'),(540,18,579,580,2,'com_modules.module.179','Gostou do conteúdo?','{}'),(541,18,581,582,2,'com_modules.module.180','Estatísticas em tempo real','{}'),(542,18,583,584,2,'com_modules.module.181','Marco Tech Blog','{}'),(543,18,585,586,2,'com_modules.module.182','The Art of Delphi Programming','{}'),(544,18,587,588,2,'com_modules.module.183','Visite Nosso Patrocinador (apague-me)','{}'),(545,18,589,590,2,'com_modules.module.184','Visite Nosso Patrocinador (apague-me)','{}'),(546,3,15,16,2,'com_banners.category.117','Banners inferiores #1 (Basic Black)','{}'),(547,18,591,592,2,'com_modules.module.185','Visite Nosso Patrocinador','{}'),(548,3,17,18,2,'com_banners.category.118','Banners inferiores #2 (Basic Black)','{}'),(549,18,593,594,2,'com_modules.module.186','Visite Nosso Patrocinador','{}'),(550,177,345,346,4,'com_content.article.200','O Delphi está morto!','{}'),(551,1,902,903,1,'#__ucm_content.95','#__ucm_content.95','{}'),(554,18,595,596,2,'com_modules.module.188','svg','{}'),(555,177,347,348,4,'com_content.article.201','13 motivos para não usar o Delphi','{}'),(556,1,904,905,1,'#__ucm_content.96','#__ucm_content.96','{}'),(557,18,597,598,2,'com_modules.module.189','Site Search','{}'),(558,177,349,350,4,'com_content.article.202','Usando o log de eventos do Windows','{}'),(563,1,906,907,1,'com_zost','com_zost','{}'),(564,177,351,352,4,'com_content.article.203','Desmistificando a Assinatura em XML','{}'),(565,1,908,909,1,'#__ucm_content.97','#__ucm_content.97','{}'),(568,177,353,354,4,'com_content.article.206','Desmistificando a Assinatura em XML','{}'),(569,1,910,911,1,'#__ucm_content.98','#__ucm_content.98','{}'),(570,177,355,356,4,'com_content.article.207','Emissor NF-e e NFC-e Delphi - Parte 21: Arrumando a Numeração da NFC-e','{}'),(571,1,912,913,1,'#__ucm_content.99','#__ucm_content.99','{}'),(572,177,357,358,4,'com_content.article.208','Emissor NF-e e NFC-e Delphi - Parte 22: Criando o Procedimento que Gera a NFC-e','{}'),(573,1,914,915,1,'#__ucm_content.100','#__ucm_content.100','{}'),(574,177,359,360,4,'com_content.article.209','Emissor NF-e e NFC-e Delphi - Parte 24: Procedimento para Gerar NFC-e','{}'),(575,1,916,917,1,'#__ucm_content.101','#__ucm_content.101','{}'),(576,177,361,362,4,'com_content.article.210','Emissor NF-e e NFC-e Delphi - Parte 23: Criação da função para tratar as Strings','{}'),(577,1,918,919,1,'#__ucm_content.102','#__ucm_content.102','{}'),(578,177,363,364,4,'com_content.article.211','Emissor NF-e e NFC-e Delphi - Parte 26: Fazendo os Últimos ajustes para a emissão da NFC-e','{}'),(579,1,920,921,1,'#__ucm_content.103','#__ucm_content.103','{}'),(580,177,365,366,4,'com_content.article.212','Emissor NF-e e NFC-e Delphi - Parte 27: Imprimindo a NFC-e','{}'),(581,1,922,923,1,'#__ucm_content.104','#__ucm_content.104','{}'),(582,177,367,368,4,'com_content.article.213','Emissor NF-e e NFC-e Delphi - Parte 28: Emitindo a NFC-e para Impressão','{}'),(583,1,924,925,1,'#__ucm_content.105','#__ucm_content.105','{}'),(584,177,369,370,4,'com_content.article.214','Emissor NF-e e NFC-e Delphi - Parte 29: Criar Coluna para gravar caminho do XML','{}'),(585,1,926,927,1,'#__ucm_content.106','#__ucm_content.106','{}'),(586,177,371,372,4,'com_content.article.215','Emissor NF-e e NFC-e Delphi - Parte 30: Criando a Tela de Emissão de NF-e','{}'),(587,1,928,929,1,'#__ucm_content.107','#__ucm_content.107','{}'),(588,177,373,374,4,'com_content.article.216','Emissor NF-e e NFC-e Delphi - Parte 31: Emissor de NFC-e e NF-e (1)','{}'),(589,1,930,931,1,'#__ucm_content.108','#__ucm_content.108','{}'),(590,177,375,376,4,'com_content.article.217','Emissor NF-e e NFC-e Delphi - Parte 32: Emissor de NFC-e e NF-e (2)','{}'),(591,1,932,933,1,'#__ucm_content.109','#__ucm_content.109','{}'),(592,177,377,378,4,'com_content.article.218','Emissor NF-e e NFC-e Delphi - Parte 33: Emissor de NFC-e e NF-e (3)','{}'),(593,1,934,935,1,'#__ucm_content.110','#__ucm_content.110','{}'),(594,177,379,380,4,'com_content.article.219','Emissor NF-e e NFC-e Delphi - Parte 34: Emissor de NFC-e e NF-e (4)','{}'),(595,1,936,937,1,'#__ucm_content.111','#__ucm_content.111','{}'),(596,177,381,382,4,'com_content.article.220','Emissor NF-e e NFC-e Delphi - Parte 35: Emissor de NFC-e e NF-e (5)','{}'),(597,1,938,939,1,'#__ucm_content.112','#__ucm_content.112','{}'),(598,177,383,384,4,'com_content.article.221','Emissor NF-e e NFC-e Delphi - Parte 36: Emissor de NFC-e e NF-e (6)','{}'),(599,1,940,941,1,'#__ucm_content.113','#__ucm_content.113','{}'),(600,177,385,386,4,'com_content.article.222','Emissor NF-e e NFC-e Delphi - Parte 37: Emissor de NFC-e e NF-e (7)','{}'),(601,1,942,943,1,'#__ucm_content.114','#__ucm_content.114','{}'),(602,177,387,388,4,'com_content.article.223','Emissor NF-e e NFC-e Delphi - Parte 38: Emissor de NFC-e e NF-e (8)','{}'),(603,1,944,945,1,'#__ucm_content.115','#__ucm_content.115','{}'),(604,177,389,390,4,'com_content.article.224','Emissor NF-e e NFC-e Delphi - Parte 39: Criando o procedimento que gera o XML da NF-e','{}'),(605,1,946,947,1,'#__ucm_content.116','#__ucm_content.116','{}'),(606,177,391,392,4,'com_content.article.225','Emissor NF-e e NFC-e Delphi - Parte 41: Ajustando o procedimento que gera o XML da NF-e','{}'),(607,1,948,949,1,'#__ucm_content.117','#__ucm_content.117','{}'),(608,177,393,394,4,'com_content.article.226','Emissor NF-e e NFC-e Delphi - Parte 25: Finalizando os Dados do Item no XML da NFC-e','{}'),(609,1,950,951,1,'#__ucm_content.118','#__ucm_content.118','{}'),(610,177,395,396,4,'com_content.article.227','Emissor NF-e e NFC-e Delphi - Parte 40: Emissor de NFC-e e NF-e (9)','{}'),(611,1,952,953,1,'#__ucm_content.119','#__ucm_content.119','{}'),(612,371,175,176,4,'com_content.article.228','A depuração com pato de borracha','{}'),(613,1,954,955,1,'#__ucm_content.120','#__ucm_content.120','{}');
187+INSERT INTO `joomla_assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES (1,0,1,958,0,'root.1','Root Asset','{\"core.login.site\":{\"6\":1,\"2\":1},\"core.login.admin\":{\"6\":1},\"core.admin\":{\"8\":1},\"core.manage\":{\"7\":1},\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1},\"attachments.delete.own\":{\"6\":1,\"3\":1},\"attachments.edit.state.own\":{\"6\":1,\"4\":1},\"attachments.edit.state.ownparent\":{\"6\":1,\"4\":1},\"attachments.edit.ownparent\":{\"6\":1,\"3\":1},\"attachments.delete.ownparent\":{\"6\":1,\"3\":1}}'),(2,1,2,3,1,'com_admin','com_admin','{}'),(3,1,4,19,1,'com_banners','com_banners','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(4,1,20,21,1,'com_cache','com_cache','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(5,1,22,23,1,'com_checkin','com_checkin','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(6,1,24,25,1,'com_config','com_config','{}'),(7,1,26,103,1,'com_contact','com_contact','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(8,1,104,443,1,'com_content','com_content','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(9,1,444,445,1,'com_cpanel','com_cpanel','{}'),(10,1,446,447,1,'com_installer','com_installer','{\"core.admin\":[],\"core.manage\":{\"7\":0},\"core.delete\":{\"7\":0},\"core.edit.state\":{\"7\":0}}'),(11,1,448,449,1,'com_languages','com_languages','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(12,1,450,451,1,'com_login','com_login','{}'),(13,1,452,453,1,'com_mailto','com_mailto','{}'),(14,1,454,455,1,'com_massmail','com_massmail','{}'),(15,1,456,457,1,'com_media','com_media','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":{\"5\":1}}'),(16,1,458,467,1,'com_menus','com_menus','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(17,1,45,46,1,'com_messages','com_messages','{\"core.admin\":{\"7\":1},\"core.manage\":{\"7\":1}}'),(18,1,470,601,1,'com_modules','com_modules','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(19,1,602,609,1,'com_newsfeeds','com_newsfeeds','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(20,1,610,611,1,'com_plugins','com_plugins','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(21,1,612,613,1,'com_redirect','com_redirect','{\"core.admin\":{\"7\":1},\"core.manage\":[]}'),(22,1,614,615,1,'com_search','com_search','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1}}'),(23,1,616,617,1,'com_templates','com_templates','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(24,1,618,621,1,'com_users','com_users','{\"core.admin\":{\"7\":1},\"core.manage\":[],\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(25,1,622,629,1,'com_weblinks','com_weblinks','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1,\"10\":0,\"12\":0},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1}}'),(26,1,630,631,1,'com_wrapper','com_wrapper','{}'),(33,1,692,693,1,'com_finder','com_finder','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1}}'),(36,7,31,32,2,'com_contact.category.11','Uncategorised','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(37,19,605,606,2,'com_newsfeeds.category.12','Uncategorised','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(41,7,33,94,2,'com_contact.category.16','Sample Data-Contact','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(42,19,607,608,2,'com_newsfeeds.category.17','Sample Data-Newsfeeds','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(59,41,34,35,3,'com_contact.category.34','Park Site','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(60,41,36,93,3,'com_contact.category.35','Shop Site','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(61,60,37,38,4,'com_contact.category.36','Staff','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(62,60,39,92,4,'com_contact.category.37','Fruit Encyclopedia','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(63,62,40,41,5,'com_contact.category.38','A','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(64,62,42,43,5,'com_contact.category.39','B','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(65,62,44,45,5,'com_contact.category.40','C','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(66,62,46,47,5,'com_contact.category.41','D','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(67,62,48,49,5,'com_contact.category.42','E','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(68,62,50,51,5,'com_contact.category.43','F','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(69,62,52,53,5,'com_contact.category.44','G','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(70,62,54,55,5,'com_contact.category.45','H','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(71,62,56,57,5,'com_contact.category.46','I','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(72,62,58,59,5,'com_contact.category.47','J','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(73,62,60,61,5,'com_contact.category.48','K','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(74,62,62,63,5,'com_contact.category.49','L','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(75,62,64,65,5,'com_contact.category.50','M','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(76,62,66,67,5,'com_contact.category.51','N','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(77,62,68,69,5,'com_contact.category.52','O','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(78,62,70,71,5,'com_contact.category.53','P','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(79,62,72,73,5,'com_contact.category.54','Q','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(80,62,74,75,5,'com_contact.category.55','R','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(81,62,76,77,5,'com_contact.category.56','S','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(82,62,78,79,5,'com_contact.category.57','T','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(83,62,80,81,5,'com_contact.category.58','U','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(84,62,82,83,5,'com_contact.category.59','V','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(85,62,84,85,5,'com_contact.category.60','W','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(86,62,86,87,5,'com_contact.category.61','X','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(87,62,88,89,5,'com_contact.category.62','Y','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(88,62,90,91,5,'com_contact.category.63','Z','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(100,8,123,124,2,'com_content.category.71','Milky Way','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(169,24,619,620,2,'com_users.notes.category.77','Uncategorised',''),(173,1,694,695,1,'com_joomlaupdate','com_joomlaupdate','{\"core.admin\":[],\"core.manage\":[],\"core.delete\":[],\"core.edit.state\":[]}'),(174,211,198,199,5,'com_content.article.71','Comprimindo os Data Packets no DataSnap','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(176,8,193,442,2,'com_content.category.79','Addicted 2 Delphi!','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(177,176,194,401,3,'com_content.category.80','Artigos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(178,176,402,441,3,'com_content.category.81','Tutoriais','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(179,196,138,145,5,'com_content.category.82','Componentes','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(182,195,152,161,3,'com_content.category.85','Notícias','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(183,195,128,135,3,'com_content.category.86','Informações','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(184,195,136,151,3,'com_content.category.87','Nossos produtos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(187,183,133,134,4,'com_content.article.72','Quem somos','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(188,183,129,130,4,'com_content.article.73','O que fazemos','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(189,183,131,132,4,'com_content.article.74','Nossa missão','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(195,8,127,178,2,'com_content.category.93','ZØST','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(196,184,137,146,4,'com_content.category.94','Delphi','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(197,184,147,150,4,'com_content.category.95','PHP','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(199,8,179,192,2,'com_content.category.96','Addicted 2 PHP!','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(200,199,180,189,3,'com_content.category.97','Artigos','{\"core.create\":[],\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"core.edit.own\":[]}'),(201,268,184,185,5,'com_content.article.78','Como funciona o breadcrumb','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(203,177,195,196,4,'com_content.article.80','Ordem de criação e execução de ApplyUpdates','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[]}'),(204,211,200,201,5,'com_content.article.81','Alteração de conexão em servidor DataSnap','{\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1}}'),(211,177,197,204,4,'com_content.category.99','DataSnap','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(213,199,190,191,3,'com_content.category.101','Tutoriais','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(220,177,205,206,4,'com_content.article.89','10 razões para ser um desenvolvedor Delphi','{}'),(221,197,148,149,5,'com_content.category.105','Bibliotecas','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(222,177,207,208,4,'com_content.article.90','A verdade sobre o TDataModule e o consumo de memória','{}'),(223,1,696,697,1,'com_attachments','com_attachments','{}'),(224,177,209,210,4,'com_content.article.91','Avaliação booleana em modo \"curto-circuito\" e operandos do tipo Variant','{}'),(225,177,211,212,4,'com_content.article.92','Como obter a real diferença entre dois valores TDateTime','{}'),(226,211,202,203,5,'com_content.article.93','Corrigindo mensagens de erro EReconcileError truncadas','{}'),(227,250,96,97,3,'com_contact.category.106','Proprietários','{\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}'),(228,179,139,140,6,'com_content.article.94','User Control DXC Edition','{}'),(230,1,698,699,1,'com_tags','com_tags','{}'),(231,1,700,701,1,'com_contenthistory','com_contenthistory','{}'),(232,1,702,703,1,'com_ajax','com_ajax','{}'),(233,1,704,705,1,'com_postinstall','com_postinstall','{}'),(235,1,706,707,1,'com_gantry','Gantry','{}'),(237,18,471,472,2,'com_modules.module.101','titulo.cus','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(238,18,473,474,2,'com_modules.module.103','login.log.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(239,18,475,476,2,'com_modules.module.93','zost.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(240,18,477,478,2,'com_modules.module.111','a2d.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(241,18,479,480,2,'com_modules.module.112','a2p.left.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(242,18,481,482,2,'com_modules.module.119','myprofile.men.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(247,1,708,709,1,'#__ucm_content.1','#__ucm_content.1','[]'),(248,18,483,484,2,'com_modules.module.107','whosonline.won.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(249,18,485,486,2,'com_modules.module.100','footer.ban','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(250,7,95,102,2,'com_contact.category.107','ZØST','{}'),(255,268,182,183,5,'com_content.article.96','Categorias e Itens de menu','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(256,1,710,711,1,'#__ucm_content.2','#__ucm_content.2','[]'),(257,177,213,214,4,'com_content.article.97','Serialização de Objetos & Persistência em Arquivos','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(258,177,215,216,4,'com_content.article.98','Quando o TClientDataSet e o TDataSetProvider são necessários?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(259,1,712,713,1,'#__ucm_content.3','#__ucm_content.3','{}'),(260,18,487,488,2,'com_modules.module.97','first.fed.beu','{}'),(261,18,489,490,2,'com_modules.module.98','second.fed.beu','{}'),(262,18,491,492,2,'com_modules.module.94','first.fed','{}'),(263,18,493,494,2,'com_modules.module.96','second.fed','{}'),(264,250,98,99,3,'com_contact.category.108','Colaboradores','{}'),(265,250,100,101,3,'com_contact.category.109','Parceiros','{}'),(267,1,714,715,1,'#__ucm_content.4','#__ucm_content.4','{}'),(268,200,181,188,4,'com_content.category.110','Joomla!','{}'),(269,1,716,717,1,'#__ucm_content.5','#__ucm_content.5','[]'),(270,1,718,719,1,'#__ucm_content.6','#__ucm_content.6','{}'),(271,1,720,721,1,'#__ucm_content.7','#__ucm_content.7','{}'),(272,1,722,723,1,'#__ucm_content.8','#__ucm_content.8','{}'),(273,1,724,725,1,'#__ucm_content.9','#__ucm_content.9','[]'),(274,177,217,218,4,'com_content.article.100','Quando devo registrar uma DLL?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(275,1,726,727,1,'#__ucm_content.10','#__ucm_content.10','[]'),(276,177,219,220,4,'com_content.article.101','XML Mapper: Convertendo um XML genérico em Data Packet','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(277,1,728,729,1,'#__ucm_content.11','#__ucm_content.11','{}'),(280,1,730,731,1,'#__ucm_content.12','#__ucm_content.12','{}'),(281,3,7,8,2,'com_banners.category.111','Banners inferiores','{}'),(282,18,495,496,2,'com_modules.module.108','footer.ban.beu','{}'),(284,177,221,222,4,'com_content.article.102','Como usar corretamente uma barra de progresso (TProgressBar)?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(285,1,732,733,1,'#__ucm_content.13','#__ucm_content.13','{}'),(286,177,223,224,4,'com_content.article.103','O lado negro do Application.ProcessMessages','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(287,1,734,735,1,'#__ucm_content.14','#__ucm_content.14','{}'),(288,177,225,226,4,'com_content.article.104','Entendendo a instalação de componentes','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(289,177,227,228,4,'com_content.article.105','Desmistificando as Interfaces no Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(290,177,229,230,4,'com_content.article.106','Como depurar um Serviço do Windows (Windows Service)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(291,1,736,737,1,'#__ucm_content.15','#__ucm_content.15','[]'),(292,18,497,498,2,'com_modules.module.123','donate.cus','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(293,18,499,500,2,'com_modules.module.124','donate.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(294,177,231,232,4,'com_content.article.107','Como validar um XML com um XSD usando o Delphi?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(295,1,738,739,1,'#__ucm_content.16','#__ucm_content.16','{}'),(296,18,501,502,2,'com_modules.module.125','articleshighlight.syf','{}'),(297,18,503,504,2,'com_modules.module.126','articlehighlight.syf.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(298,18,505,506,2,'com_modules.module.127','news.syf.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(299,18,507,508,2,'com_modules.module.128','news.syf','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(300,177,233,234,4,'com_content.article.108','Sobrecarga de operadores','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(301,1,740,741,1,'#__ucm_content.17','#__ucm_content.17','[]'),(302,18,509,510,2,'com_modules.module.129','statistics.cus','{}'),(303,18,511,512,2,'com_modules.module.130','statistics.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(304,177,235,236,4,'com_content.article.109','Windows Messages: A base da programação orientada a eventos','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(305,1,742,743,1,'#__ucm_content.18','#__ucm_content.18','[]'),(306,177,237,238,4,'com_content.article.110','Uso pleno do TClientDataSet e o Modelo de Maleta','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(307,1,744,745,1,'#__ucm_content.19','#__ucm_content.19','{}'),(308,18,513,514,2,'com_modules.module.131','language.gtr','{}'),(309,18,515,516,2,'com_modules.module.132','language.gtr.beu','{}'),(310,177,239,240,4,'com_content.article.111','Classes Mediadoras (interposer)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(311,18,517,518,2,'com_modules.module.133','consortium.cus','{}'),(312,18,519,520,2,'com_modules.module.134','consortium.cus.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(314,1,746,747,1,'#__ucm_content.20','#__ucm_content.20','{}'),(315,177,241,242,4,'com_content.article.112','Assinando digitalmente aplicações Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(316,1,748,749,1,'#__ucm_content.21','#__ucm_content.21','{}'),(317,177,243,244,4,'com_content.article.113','Obtendo o serial físico de um HD','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(318,358,404,405,5,'com_content.article.114','DataSnap Sobre SOAP (Parte 1): Apache e DLL ISAPI','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(319,358,406,407,5,'com_content.article.115','DataSnap Sobre SOAP (Parte 2): SGBD e componentes de conexão','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(320,358,408,409,5,'com_content.article.116','DataSnap Sobre SOAP (Parte 3): Configurando o Apache','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(321,358,410,411,5,'com_content.article.117','DataSnap Sobre SOAP (Parte 4): A DLL ISAPI Básica','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(322,358,412,413,5,'com_content.article.118','DataSnap Sobre SOAP (Parte 5): Um Soap Server DataModule na DLL ISAPI','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(323,358,414,415,5,'com_content.article.119','DataSnap Sobre SOAP (Parte 6): Testando o WebService','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(324,358,416,417,5,'com_content.article.120','DataSnap Sobre SOAP (Parte 7): Estendendo o Soap Server DataModule','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(325,1,750,751,1,'#__ucm_content.22','#__ucm_content.22','{}'),(326,18,521,522,2,'com_modules.module.135','statistics.cus.mobile','{}'),(327,18,523,524,2,'com_modules.module.136','consortium.cus.mobile','{}'),(329,268,186,187,5,'com_content.article.121','Criando um sistema de notas de rodapé','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(330,177,245,246,4,'com_content.article.122','Open Tools API','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(331,1,752,753,1,'#__ucm_content.23','#__ucm_content.23','{}'),(333,1,754,755,1,'#__ucm_content.24','#__ucm_content.24','[]'),(335,1,756,757,1,'#__ucm_content.26','#__ucm_content.26','{}'),(336,182,153,154,4,'com_content.article.124','UserControl Suite Delphi Experts Consortium Edition','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(337,1,758,759,1,'#__ucm_content.27','#__ucm_content.27','{}'),(338,177,247,248,4,'com_content.article.125','Variant Open Array Parameters','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(339,1,760,761,1,'#__ucm_content.28','#__ucm_content.28','{}'),(340,182,155,156,4,'com_content.article.126','UCDXCE: Progresso dos testes','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(341,1,762,763,1,'#__ucm_content.29','#__ucm_content.29','{}'),(342,177,249,250,4,'com_content.article.127','Diretivas de compilação e versões do Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(343,177,251,252,4,'com_content.article.128','Compilando um projeto Delphi pela linha de comando','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(344,1,764,765,1,'#__ucm_content.30','#__ucm_content.30','{}'),(345,177,253,254,4,'com_content.article.129','Configurando e usando o MySQL Embedded','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(346,1,766,767,1,'#__ucm_content.31','#__ucm_content.31','{}'),(347,1,768,769,1,'#__ucm_content.32','#__ucm_content.32','{}'),(348,177,255,256,4,'com_content.article.130','Biometria básica com o U.are.U 4000B (Digital Persona / Crossmatch)','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(349,1,770,771,1,'#__ucm_content.33','#__ucm_content.33','{}'),(350,371,173,174,4,'com_content.article.131','SSCCE: Uma necessidade pouco conhecida','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(351,1,772,773,1,'#__ucm_content.34','#__ucm_content.34','{}'),(352,1,774,775,1,'#__ucm_content.35','#__ucm_content.35','{}'),(353,18,525,526,2,'com_modules.module.138','left.ban.beu','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(354,18,527,528,2,'com_modules.module.139','left.ban','{\"core.delete\":[],\"core.edit\":[],\"core.edit.state\":[],\"module.edit.frontend\":[]}'),(355,3,9,10,2,'com_banners.category.112','Banners esquerdos','{}'),(357,1,776,777,1,'com_extplorer','eXtplorer','{}'),(358,178,403,418,4,'com_content.category.113','DataSnap','{}'),(359,177,257,258,4,'com_content.article.132','Manipulando XMLs com XPath no Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(360,1,778,779,1,'#__ucm_content.36','#__ucm_content.36','{}'),(361,179,141,142,6,'com_content.article.133','Anak Krakatoa Defined Crypt','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(362,1,780,781,1,'#__ucm_content.37','#__ucm_content.37','{}'),(363,179,143,144,6,'com_content.article.134','Zetta-Ømnis Packages Creator','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(364,1,782,783,1,'#__ucm_content.38','#__ucm_content.38','{}'),(365,177,259,260,4,'com_content.article.135','Por que os meus executáveis Delphi são tão grandes?','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(366,1,784,785,1,'#__ucm_content.39','#__ucm_content.39','{}'),(369,182,157,158,4,'com_content.article.137','UCDXCE: Remoção completa do sistema de tradução','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(370,1,786,787,1,'#__ucm_content.41','#__ucm_content.41','[]'),(371,195,162,177,3,'com_content.category.114','Artigos','{}'),(372,371,163,164,4,'com_content.article.138','Instalação e configuração manual do MySQL no Windows','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(373,1,788,789,1,'#__ucm_content.42','#__ucm_content.42','{}'),(374,177,261,262,4,'com_content.article.139','Uso de BPLs para modularizar aplicações Delphi','{\"core.admin\":{\"7\":1},\"core.manage\":{\"6\":1},\"core.create\":{\"3\":1},\"core.delete\":[],\"core.edit\":{\"4\":1},\"core.edit.state\":{\"5\":1},\"core.edit.own\":[]}'),(375,1,790,791,1,'#__ucm_content.43','#__ucm_content.43','{}'),(376,1,792,793,1,'com_fields','com_fields','{}'),(377,1,794,795,1,'com_associations','com_associations','{}'),(378,371,165,166,4,'com_content.article.140','Instalação e configuração manual do PostgreSQL no Windows','{}'),(379,1,796,797,1,'#__ucm_content.44','#__ucm_content.44','{}'),(380,1,798,799,1,'com_fst','COM_FST','{}'),(383,18,529,530,2,'com_modules.module.143','testimonials.tes','{}'),(384,18,531,532,2,'com_modules.module.144','testimonials.tes.beu','{}'),(388,178,419,420,4,'com_content.article.141','Inno Setup (Parte 1): Introdução & Inno Script Studio','{}'),(389,1,800,801,1,'#__ucm_content.45','#__ucm_content.45','{}'),(390,178,421,422,4,'com_content.article.142','Inno Setup (Parte 2): Criando o projeto básico','{}'),(391,1,802,803,1,'#__ucm_content.46','#__ucm_content.46','{}'),(392,178,423,424,4,'com_content.article.143','Inno Setup (Parte 3): Instalando o PostgreSQL','{}'),(393,177,263,264,4,'com_content.article.144','WinInet + CryptoAPI + SSL: Use a API do Windows em seu favor','{}'),(394,1,804,805,1,'#__ucm_content.47','#__ucm_content.47','{}'),(395,178,425,426,4,'com_content.article.145','Inno Setup (Parte 4): Types, Components e Tasks','{}'),(396,1,806,807,1,'#__ucm_content.48','#__ucm_content.48','{}'),(397,1,808,809,1,'#__ucm_content.49','#__ucm_content.49','{}'),(398,178,427,428,4,'com_content.article.146','Inno Setup (Parte 5): Configurando o PostgreSQL','{}'),(399,177,265,266,4,'com_content.article.147','Entendendo o JSON (Parte 2)','{}'),(400,177,267,268,4,'com_content.article.148','Entendendo o JSON (Parte 1)','{}'),(401,1,810,811,1,'#__ucm_content.50','#__ucm_content.50','{}'),(402,1,812,813,1,'#__ucm_content.51','#__ucm_content.51','{}'),(403,371,167,168,4,'com_content.article.149','O limite da persistência ao buscar uma solução','{}'),(404,1,814,815,1,'#__ucm_content.52','#__ucm_content.52','{}'),(406,1,816,817,1,'#__ucm_content.53','#__ucm_content.53','{}'),(407,178,429,430,4,'com_content.article.150','Inno Setup (Parte 6): Página personalizada I','{}'),(408,1,818,819,1,'#__ucm_content.54','#__ucm_content.54','{}'),(410,18,533,534,2,'com_modules.module.149','maintainer.cus.beu','{}'),(411,18,535,536,2,'com_modules.module.150','maintainer.cus','{}'),(412,178,431,432,4,'com_content.article.151','Inno Setup (Parte 8): Página personalizada II','{}'),(413,177,397,398,4,'com_content.article.152','Correção para o erro «EditorLineEnds.ttr» ao iniciar o Delphi','{}'),(414,1,820,821,1,'#__ucm_content.55','#__ucm_content.55','{}'),(415,178,433,434,4,'com_content.article.153','Inno Setup (Parte 7): Melhorando a execução de programas externos','{}'),(416,1,822,823,1,'#__ucm_content.56','#__ucm_content.56','{}'),(417,1,824,825,1,'#__ucm_content.57','#__ucm_content.57','{}'),(418,178,435,436,4,'com_content.article.154','Inno Setup (Parte 9): Assinando digitalmente o instalador','{}'),(419,1,826,827,1,'#__ucm_content.58','#__ucm_content.58','{}'),(420,18,537,538,2,'com_modules.module.151','qrcode.cus.beu','{}'),(422,18,539,540,2,'com_modules.module.153','qrcode.cus','{}'),(423,178,437,438,4,'com_content.article.155','Inno Setup (Parte 10): Página personalizada III','{}'),(424,1,828,829,1,'#__ucm_content.59','#__ucm_content.59','{}'),(425,182,159,160,4,'com_content.article.156','Delphi & C++ Builder Community Edition!','{}'),(426,1,830,831,1,'#__ucm_content.60','#__ucm_content.60','{}'),(427,177,269,270,4,'com_content.article.157','Design Layout para Restaurantes com VCL (Parte 1)','{}'),(428,1,832,833,1,'#__ucm_content.61','#__ucm_content.61','{}'),(429,177,271,272,4,'com_content.article.158','Design Layout para Restaurantes com VCL (Parte 2)','{}'),(430,1,834,835,1,'#__ucm_content.62','#__ucm_content.62','{}'),(431,177,273,274,4,'com_content.article.159','Emissor NF-e e NFC-e Delphi - Parte 1: Instalação do ACBr no Delphi','{}'),(432,1,836,837,1,'#__ucm_content.63','#__ucm_content.63','{}'),(433,177,275,276,4,'com_content.article.160','Emissor NF-e e NFC-e Delphi - Parte 2: Instalação do ZeosLib no Delphi','{}'),(434,1,838,839,1,'#__ucm_content.64','#__ucm_content.64','{}'),(435,177,277,278,4,'com_content.article.161','Emissor NF-e e NFC-e Delphi - Parte 3: Instalação do banco de dados PostgreSQL','{}'),(436,1,840,841,1,'#__ucm_content.65','#__ucm_content.65','{}'),(437,177,279,280,4,'com_content.article.162','Emissor NF-e e NFC-e Delphi - Parte 4: Criação da estrutura do banco de dados','{}'),(438,1,842,843,1,'#__ucm_content.66','#__ucm_content.66','{}'),(439,177,281,282,4,'com_content.article.163','Emissor NF-e e NFC-e Delphi - Parte 5: Criação do menu de acesso do projeto','{}'),(440,1,844,845,1,'#__ucm_content.67','#__ucm_content.67','{}'),(441,177,283,284,4,'com_content.article.164','Emissor NF-e e NFC-e Delphi - Parte 6: Criação da conexão com o banco de dados utilizando o TZConnec','{}'),(442,1,846,847,1,'#__ucm_content.68','#__ucm_content.68','{}'),(443,177,285,286,4,'com_content.article.165','Apresentando as variáveis inline na linguagem Delphi','{}'),(444,1,848,849,1,'#__ucm_content.69','#__ucm_content.69','{}'),(445,177,287,288,4,'com_content.article.166','Emissor NF-e e NFC-e Delphi - Parte 7: Criação da Tela de Cadastro de Clientes','{}'),(446,1,850,851,1,'#__ucm_content.70','#__ucm_content.70','{}'),(447,177,289,290,4,'com_content.article.167','Suporte ao Per Monitor v2 e ao GetSystemMetrics na VCL chegando ao 10.3!','{}'),(448,1,852,853,1,'#__ucm_content.71','#__ucm_content.71','{}'),(449,1,854,855,1,'com_privacy','com_privacy','{}'),(450,1,856,857,1,'com_actionlogs','com_actionlogs','{}'),(451,18,541,542,2,'com_modules.module.154','left2.ban','{}'),(452,18,543,544,2,'com_modules.module.155','left2.ban.beu','{}'),(453,177,291,292,4,'com_content.article.168','Emissor NF-e e NFC-e Delphi - Parte 8: Gravando os dados e realizando a pesquisa','{}'),(454,1,858,859,1,'#__ucm_content.72','#__ucm_content.72','{}'),(455,177,293,294,4,'com_content.article.169','Emissor NF-e e NFC-e Delphi - Parte 9: Listar cidades e estados no cadastro de clientes','{}'),(456,1,860,861,1,'#__ucm_content.73','#__ucm_content.73','{}'),(457,177,295,296,4,'com_content.article.170','Resolvendo o problema dos breakpoints fora de sincronia','{}'),(458,1,862,863,1,'#__ucm_content.74','#__ucm_content.74','{}'),(459,178,439,440,4,'com_content.article.171','Inno Setup (Parte 11): Personalização Final (o \"Road Map\")','{}'),(460,1,864,865,1,'#__ucm_content.75','#__ucm_content.75','{}'),(461,177,297,298,4,'com_content.article.172','Como fazer uma \"tela de splash\" visualmente impressionante','{}'),(462,177,299,300,4,'com_content.article.173','Emissor NF-e e NFC-e Delphi - Parte 10: Criando o cadastro de transportadoras','{}'),(463,1,866,867,1,'#__ucm_content.76','#__ucm_content.76','{}'),(464,177,301,302,4,'com_content.article.174','Emissor NF-e e NFC-e Delphi - Parte 11: Criação das telas de produtos e certificados digitais','{}'),(465,1,868,869,1,'#__ucm_content.77','#__ucm_content.77','{}'),(466,177,303,304,4,'com_content.article.175','Emissor NF-e e NFC-e Delphi - Parte 12: Finalizando o cadastro de produtos','{}'),(467,1,870,871,1,'#__ucm_content.78','#__ucm_content.78','{}'),(468,177,305,306,4,'com_content.article.176','Emissor NF-e e NFC-e Delphi - Parte 13: Cadastro de emitente','{}'),(469,1,872,873,1,'#__ucm_content.79','#__ucm_content.79','{}'),(470,371,171,172,4,'com_content.article.177','Repositório de versões do Delphi e C++ Builder','{}'),(471,1,874,875,1,'#__ucm_content.80','#__ucm_content.80','{}'),(472,177,307,308,4,'com_content.article.178','Emissor NF-e e NFC-e Delphi - Parte 14: Consultando status do serviço da NF-e e NFC-e','{}'),(473,1,876,877,1,'#__ucm_content.81','#__ucm_content.81','{}'),(474,177,309,310,4,'com_content.article.179','Emissor NF-e e NFC-e Delphi - Parte 15: Criação da tela de emissão de NFC-e','{}'),(475,1,878,879,1,'#__ucm_content.82','#__ucm_content.82','{}'),(476,177,311,312,4,'com_content.article.180','Emissor NF-e e NFC-e Delphi - Parte 16: Inserindo itens na NFC-e','{}'),(477,1,880,881,1,'#__ucm_content.83','#__ucm_content.83','{}'),(478,177,313,314,4,'com_content.article.181','Emissor NF-e e NFC-e Delphi - Parte 17: Calculando a quantidade de itens e criando as pesquisas','{}'),(479,1,882,883,1,'#__ucm_content.84','#__ucm_content.84','{}'),(480,177,315,316,4,'com_content.article.182','Emissor NF-e e NFC-e Delphi - Parte 18: Totalizando o cupom fiscal','{}'),(481,1,884,885,1,'#__ucm_content.85','#__ucm_content.85','{}'),(482,177,317,318,4,'com_content.article.183','Emissor NF-e e NFC-e Delphi - Parte 19: Inserindo os pagamentos na venda','{}'),(483,1,886,887,1,'#__ucm_content.86','#__ucm_content.86','{}'),(484,177,319,320,4,'com_content.article.184','Emissor NF-e e NFC-e Delphi - Parte 20: Gravando e listando os dados da venda','{}'),(485,1,888,889,1,'#__ucm_content.87','#__ucm_content.87','{}'),(486,177,321,322,4,'com_content.article.185','Os tipos NativeInt e NativeUInt em Delphis pré 2009 #AQuemPossaInteressar','{}'),(487,1,890,891,1,'#__ucm_content.88','#__ucm_content.88','{}'),(488,177,323,324,4,'com_content.article.186','O TWebBrowser pode causar Access Violation ao fechar um programa #AQuemPossaInteressar','{}'),(491,177,325,326,4,'com_content.article.189','O que são e quais os tipos de Type Aliases #AQuemPossaInteressar','{}'),(492,177,327,328,4,'com_content.article.190','Qual a diferença entre New, GetMem e AllocMem #AQuemPossaInteressar','{}'),(493,177,329,330,4,'com_content.article.191','Erro intermitente ao conectar-se ao MySQL Embedded #AQuemPossaInteressar','{}'),(494,177,331,332,4,'com_content.article.192','Herança de interfaces e implementação explícita de interfaces-base #AQuemPossaInteressar','{}'),(495,177,333,334,4,'com_content.article.193','Interfaces que não se autodestroem #AQuemPossaInteressar ','{}'),(496,177,335,336,4,'com_content.article.194','Path do sistema, package output directory e como o Delphi encontra seus pacotes #AQuemPossaInteressa','{}'),(497,177,337,338,4,'com_content.article.195','Interdependência entre pacotes e sua relação com o \"library path\"','{}'),(498,177,339,340,4,'com_content.article.196','ID3v2 Editor Plus!','{}'),(499,1,892,893,1,'#__ucm_content.89','#__ucm_content.89','{}'),(500,177,341,342,4,'com_content.article.197','Campos agregados e GroupState no TClientDataSet','{}'),(501,1,894,895,1,'#__ucm_content.90','#__ucm_content.90','{}'),(502,1,896,897,1,'#__ucm_content.91','#__ucm_content.91','{}'),(503,177,343,344,4,'com_content.article.198','Dê nome as suas threads, mesmo aquelas criadas pelo Delphi!','{}'),(504,1,898,899,1,'#__ucm_content.92','#__ucm_content.92','{}'),(505,18,545,546,2,'com_modules.module.156','language.gtr.mobile','{}'),(506,18,547,548,2,'com_modules.module.157','language.gtr.beu.2','{}'),(507,1,900,901,1,'#__ucm_content.93','#__ucm_content.93','{}'),(508,18,549,550,2,'com_modules.module.158','basicblack-breadcrumbs','{}'),(510,18,551,552,2,'com_modules.module.160','basicblack-menu','{}'),(511,18,553,554,2,'com_modules.module.161','Acesso Rápido','{}'),(513,18,555,556,2,'com_modules.module.163','Fique por dentro','{}'),(514,18,557,558,2,'com_modules.module.164','DO NOT UNDERSTAND PORTUGUESE? CLICK ON THE FLAG TO CHANGE THE LANGUAGE!','{}'),(515,18,559,560,2,'com_modules.module.165','Fique por dentro','{}'),(516,18,561,562,2,'com_modules.module.166','Autenticação','{}'),(518,18,563,564,2,'com_modules.module.104','login.log','{}'),(519,371,169,170,4,'com_content.article.199','Você precisa conhecer o Chasys Draw IES!','{}'),(520,1,902,903,1,'#__ucm_content.94','#__ucm_content.94','{}'),(522,18,565,566,2,'com_modules.module.102','whosonline.won','{}'),(525,18,567,568,2,'com_modules.module.171','Visite Nosso Patrocinador','{}'),(526,3,11,12,2,'com_banners.category.115','Banners direitos (Basic Black)','{}'),(527,18,569,570,2,'com_modules.module.172','Visite Nosso Patrocinador','{}'),(528,18,571,572,2,'com_modules.module.173','Seções em ZØST','{}'),(529,18,573,574,2,'com_modules.module.174','Seções em A2D!','{}'),(530,18,575,576,2,'com_modules.module.175','Seções em A2P!','{}'),(533,3,13,14,2,'com_banners.category.116','Banners esquerdos (Basic Black)','{}'),(534,18,577,578,2,'com_modules.module.177','Meu Perfil','{}'),(535,16,459,460,2,'com_menus.menu.8','ZØST','{}'),(536,16,461,462,2,'com_menus.menu.9','Addicted 2 Delphi!','{}'),(537,16,463,464,2,'com_menus.menu.10','Addicted 2 PHP!','{}'),(538,16,465,466,2,'com_menus.menu.6','Menu principal','{}'),(539,18,579,580,2,'com_modules.module.178','Conteúdo Verificado!','{}'),(540,18,581,582,2,'com_modules.module.179','Gostou do conteúdo?','{}'),(541,18,583,584,2,'com_modules.module.180','Estatísticas em tempo real','{}'),(542,18,585,586,2,'com_modules.module.181','Marco Tech Blog','{}'),(543,18,587,588,2,'com_modules.module.182','The Art of Delphi Programming','{}'),(544,18,589,590,2,'com_modules.module.183','Visite Nosso Patrocinador (apague-me)','{}'),(545,18,591,592,2,'com_modules.module.184','Visite Nosso Patrocinador (apague-me)','{}'),(546,3,15,16,2,'com_banners.category.117','Banners inferiores #1 (Basic Black)','{}'),(547,18,593,594,2,'com_modules.module.185','Visite Nosso Patrocinador','{}'),(548,3,17,18,2,'com_banners.category.118','Banners inferiores #2 (Basic Black)','{}'),(549,18,595,596,2,'com_modules.module.186','Visite Nosso Patrocinador','{}'),(550,177,345,346,4,'com_content.article.200','O Delphi está morto!','{}'),(551,1,904,905,1,'#__ucm_content.95','#__ucm_content.95','{}'),(554,18,597,598,2,'com_modules.module.188','svg','{}'),(555,177,347,348,4,'com_content.article.201','13 motivos para não usar o Delphi','{}'),(556,1,906,907,1,'#__ucm_content.96','#__ucm_content.96','{}'),(557,18,599,600,2,'com_modules.module.189','Site Search','{}'),(558,177,349,350,4,'com_content.article.202','Usando o log de eventos do Windows','{}'),(563,1,908,909,1,'com_zost','com_zost','{}'),(564,177,351,352,4,'com_content.article.203','Desmistificando a Assinatura em XML','{}'),(565,1,910,911,1,'#__ucm_content.97','#__ucm_content.97','{}'),(568,177,353,354,4,'com_content.article.206','Desmistificando a Assinatura em XML','{}'),(569,1,912,913,1,'#__ucm_content.98','#__ucm_content.98','{}'),(570,177,355,356,4,'com_content.article.207','Emissor NF-e e NFC-e Delphi - Parte 21: Arrumando a Numeração da NFC-e','{}'),(571,1,914,915,1,'#__ucm_content.99','#__ucm_content.99','{}'),(572,177,357,358,4,'com_content.article.208','Emissor NF-e e NFC-e Delphi - Parte 22: Criando o Procedimento que Gera a NFC-e','{}'),(573,1,916,917,1,'#__ucm_content.100','#__ucm_content.100','{}'),(574,177,359,360,4,'com_content.article.209','Emissor NF-e e NFC-e Delphi - Parte 24: Procedimento para Gerar NFC-e','{}'),(575,1,918,919,1,'#__ucm_content.101','#__ucm_content.101','{}'),(576,177,361,362,4,'com_content.article.210','Emissor NF-e e NFC-e Delphi - Parte 23: Criação da função para tratar as Strings','{}'),(577,1,920,921,1,'#__ucm_content.102','#__ucm_content.102','{}'),(578,177,363,364,4,'com_content.article.211','Emissor NF-e e NFC-e Delphi - Parte 26: Fazendo os Últimos ajustes para a emissão da NFC-e','{}'),(579,1,922,923,1,'#__ucm_content.103','#__ucm_content.103','{}'),(580,177,365,366,4,'com_content.article.212','Emissor NF-e e NFC-e Delphi - Parte 27: Imprimindo a NFC-e','{}'),(581,1,924,925,1,'#__ucm_content.104','#__ucm_content.104','{}'),(582,177,367,368,4,'com_content.article.213','Emissor NF-e e NFC-e Delphi - Parte 28: Emitindo a NFC-e para Impressão','{}'),(583,1,926,927,1,'#__ucm_content.105','#__ucm_content.105','{}'),(584,177,369,370,4,'com_content.article.214','Emissor NF-e e NFC-e Delphi - Parte 29: Criar Coluna para gravar caminho do XML','{}'),(585,1,928,929,1,'#__ucm_content.106','#__ucm_content.106','{}'),(586,177,371,372,4,'com_content.article.215','Emissor NF-e e NFC-e Delphi - Parte 30: Criando a Tela de Emissão de NF-e','{}'),(587,1,930,931,1,'#__ucm_content.107','#__ucm_content.107','{}'),(588,177,373,374,4,'com_content.article.216','Emissor NF-e e NFC-e Delphi - Parte 31: Emissor de NFC-e e NF-e (1)','{}'),(589,1,932,933,1,'#__ucm_content.108','#__ucm_content.108','{}'),(590,177,375,376,4,'com_content.article.217','Emissor NF-e e NFC-e Delphi - Parte 32: Emissor de NFC-e e NF-e (2)','{}'),(591,1,934,935,1,'#__ucm_content.109','#__ucm_content.109','{}'),(592,177,377,378,4,'com_content.article.218','Emissor NF-e e NFC-e Delphi - Parte 33: Emissor de NFC-e e NF-e (3)','{}'),(593,1,936,937,1,'#__ucm_content.110','#__ucm_content.110','{}'),(594,177,379,380,4,'com_content.article.219','Emissor NF-e e NFC-e Delphi - Parte 34: Emissor de NFC-e e NF-e (4)','{}'),(595,1,938,939,1,'#__ucm_content.111','#__ucm_content.111','{}'),(596,177,381,382,4,'com_content.article.220','Emissor NF-e e NFC-e Delphi - Parte 35: Emissor de NFC-e e NF-e (5)','{}'),(597,1,940,941,1,'#__ucm_content.112','#__ucm_content.112','{}'),(598,177,383,384,4,'com_content.article.221','Emissor NF-e e NFC-e Delphi - Parte 36: Emissor de NFC-e e NF-e (6)','{}'),(599,1,942,943,1,'#__ucm_content.113','#__ucm_content.113','{}'),(600,177,385,386,4,'com_content.article.222','Emissor NF-e e NFC-e Delphi - Parte 37: Emissor de NFC-e e NF-e (7)','{}'),(601,1,944,945,1,'#__ucm_content.114','#__ucm_content.114','{}'),(602,177,387,388,4,'com_content.article.223','Emissor NF-e e NFC-e Delphi - Parte 38: Emissor de NFC-e e NF-e (8)','{}'),(603,1,946,947,1,'#__ucm_content.115','#__ucm_content.115','{}'),(604,177,389,390,4,'com_content.article.224','Emissor NF-e e NFC-e Delphi - Parte 39: Criando o procedimento que gera o XML da NF-e','{}'),(605,1,948,949,1,'#__ucm_content.116','#__ucm_content.116','{}'),(606,177,391,392,4,'com_content.article.225','Emissor NF-e e NFC-e Delphi - Parte 41: Ajustando o procedimento que gera o XML da NF-e','{}'),(607,1,950,951,1,'#__ucm_content.117','#__ucm_content.117','{}'),(608,177,393,394,4,'com_content.article.226','Emissor NF-e e NFC-e Delphi - Parte 25: Finalizando os Dados do Item no XML da NFC-e','{}'),(609,1,952,953,1,'#__ucm_content.118','#__ucm_content.118','{}'),(610,177,395,396,4,'com_content.article.227','Emissor NF-e e NFC-e Delphi - Parte 40: Emissor de NFC-e e NF-e (9)','{}'),(611,1,954,955,1,'#__ucm_content.119','#__ucm_content.119','{}'),(612,371,175,176,4,'com_content.article.228','A depuração com pato de borracha','{}'),(613,1,956,957,1,'#__ucm_content.120','#__ucm_content.120','{}'),(614,177,399,400,4,'com_content.article.229','Cast direto versus Cast com o operador \"AS\" #AQuemPossaInteressar','{}');
188188 /*!40000 ALTER TABLE `joomla_assets` ENABLE KEYS */;
189189 UNLOCK TABLES;
190190
@@ -384,7 +384,7 @@
384384
385385 LOCK TABLES `joomla_banners` WRITE;
386386 /*!40000 ALTER TABLE `joomla_banners` DISABLE KEYS */;
387-INSERT INTO `joomla_banners` (`id`, `cid`, `type`, `name`, `alias`, `imptotal`, `impmade`, `clicks`, `clickurl`, `state`, `catid`, `description`, `custombannercode`, `sticky`, `ordering`, `metakey`, `params`, `own_prefix`, `metakey_prefix`, `purchase_type`, `track_clicks`, `track_impressions`, `checked_out`, `checked_out_time`, `publish_up`, `publish_down`, `reset`, `created`, `language`, `created_by`, `created_by_alias`, `modified`, `modified_by`, `version`) VALUES (28,9,1,'Google AdSense - ZOST: (468x60)','google-adsense-zost-468x60',0,890276,0,'',1,111,'','<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: Banner (234x60) (L) --><!-- ZOST: Banner (234x60) (R) -->\r\n<div style=\"padding-left: 301px; padding-right: 301px;\">\r\n<div style=\"background-color: rgba(255, 255, 255, 0.9);\">\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:234px;height:60px; float: left\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"8451446418\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:234px;height:60px; float: right\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"6048219328\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n</div>\r\n</div>\r\n<!-- ZOST: Banner (468x60) -->\r\n<div style=\"padding-left: 301px; padding-right: 301px;\">\r\n<div style=\"background-color: rgba(255, 255, 255, 0.9);\">\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:468px;height:60px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"1700791547\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n</div>\r\n</div>\r\n\r\n\r\n\r\n',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2016-10-22 00:00:00','2016-09-22 23:43:59','*',24,'','2018-12-03 17:20:04',24,46),(32,9,1,'Google AdSense - ZOST: (200x200) #1','google-adsense-zost-200x200',0,890319,0,'',1,112,'','<div style=\"margin-left: 9px; margin-right: 9px; background-color: rgba(255,255,255,0.90)\">\r\n<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: 200x200 -->\r\n<ins class=\"adsbygoogle\"\r\n style=\"display: contents;width:200px;height:200px\"\r\n data-ad-client=\"ca-pub-3110076814260873\"\r\n data-ad-slot=\"8448342346\"></ins>\r\n<script>\r\n(adsbygoogle = window.adsbygoogle || []).push({});\r\n</script>\r\n</div>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2017-08-10 00:00:00','2017-07-10 19:05:13','*',24,'','2020-05-29 00:21:56',24,8),(33,9,1,'Google AdSense - ZOST: (200x200) #2','google-adsense-zost-200x200-2',0,890566,0,'',1,112,'','<div style=\"margin-left: 9px; margin-right: 9px; background-color: rgba(255,255,255,0.90)\">\r\n<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: Banner (200x200) #2 -->\r\n<ins class=\"adsbygoogle\"\r\n style=\"display: contents;width:200px;height:200px\"\r\n data-ad-client=\"ca-pub-3110076814260873\"\r\n data-ad-slot=\"2605418240\"></ins>\r\n<script>\r\n(adsbygoogle = window.adsbygoogle || []).push({});\r\n</script>\r\n</div>',0,2,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2018-12-03 17:21:19','0000-00-00 00:00:00','2019-01-03 00:00:00','2018-12-03 17:20:27','*',24,'','2020-05-29 00:23:54',24,4),(34,9,1,'Banner 200x200 (Basic Black) #1','banner-200-200-basicblack-1',0,1079022,0,'',1,115,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (200x200) #1 -->\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:200px;height:200px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"8448342346\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2020-06-26 00:00:00','2020-05-26 23:32:16','*',24,'','2020-06-29 21:13:20',24,20),(36,9,1,'Banner 200x200 (Basic Black) #2','banner-200-200-basicblack-2',0,1079011,0,'',1,116,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (200x200) #2 -->\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:200px;height:200px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"2605418240\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,15,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2020-06-29 00:00:00','2020-05-29 01:38:00','*',24,'','2020-06-29 21:13:10',24,6),(37,9,1,'Banner 728x90 (Basic Black) #1','banner-728x90-basicblack-1',0,240350,0,'',1,117,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (728x90) -->\r\n<ins class=\"adsbygoogle\" style=\"display:contents;width:728px;height:90px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"6443009564\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2020-06-03 23:26:11','0000-00-00 00:00:00','2020-07-03 00:00:00','2020-06-03 23:24:36','*',24,'','2020-06-28 21:29:47',24,13),(38,9,1,'Banner 728x90 (Basic Black) #2','banner-728x90-basicblack-2',0,240362,0,'',1,118,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (728x90) #2 -->\r\n<ins class=\"adsbygoogle\" style=\"display:contents;width:728px;height:90px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"7210184376\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,17,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2020-06-03 23:26:11','0000-00-00 00:00:00','2020-07-03 00:00:00','2020-06-03 23:47:06','*',24,'','2020-06-28 21:30:12',24,5);
387+INSERT INTO `joomla_banners` (`id`, `cid`, `type`, `name`, `alias`, `imptotal`, `impmade`, `clicks`, `clickurl`, `state`, `catid`, `description`, `custombannercode`, `sticky`, `ordering`, `metakey`, `params`, `own_prefix`, `metakey_prefix`, `purchase_type`, `track_clicks`, `track_impressions`, `checked_out`, `checked_out_time`, `publish_up`, `publish_down`, `reset`, `created`, `language`, `created_by`, `created_by_alias`, `modified`, `modified_by`, `version`) VALUES (28,9,1,'Google AdSense - ZOST: (468x60)','google-adsense-zost-468x60',0,890276,0,'',1,111,'','<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: Banner (234x60) (L) --><!-- ZOST: Banner (234x60) (R) -->\r\n<div style=\"padding-left: 301px; padding-right: 301px;\">\r\n<div style=\"background-color: rgba(255, 255, 255, 0.9);\">\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:234px;height:60px; float: left\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"8451446418\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:234px;height:60px; float: right\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"6048219328\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n</div>\r\n</div>\r\n<!-- ZOST: Banner (468x60) -->\r\n<div style=\"padding-left: 301px; padding-right: 301px;\">\r\n<div style=\"background-color: rgba(255, 255, 255, 0.9);\">\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:468px;height:60px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"1700791547\"></ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>\r\n</div>\r\n</div>\r\n\r\n\r\n\r\n',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2016-10-22 00:00:00','2016-09-22 23:43:59','*',24,'','2018-12-03 17:20:04',24,46),(32,9,1,'Google AdSense - ZOST: (200x200) #1','google-adsense-zost-200x200',0,890319,0,'',1,112,'','<div style=\"margin-left: 9px; margin-right: 9px; background-color: rgba(255,255,255,0.90)\">\r\n<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: 200x200 -->\r\n<ins class=\"adsbygoogle\"\r\n style=\"display: contents;width:200px;height:200px\"\r\n data-ad-client=\"ca-pub-3110076814260873\"\r\n data-ad-slot=\"8448342346\"></ins>\r\n<script>\r\n(adsbygoogle = window.adsbygoogle || []).push({});\r\n</script>\r\n</div>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2017-08-10 00:00:00','2017-07-10 19:05:13','*',24,'','2020-05-29 00:21:56',24,8),(33,9,1,'Google AdSense - ZOST: (200x200) #2','google-adsense-zost-200x200-2',0,890566,0,'',1,112,'','<div style=\"margin-left: 9px; margin-right: 9px; background-color: rgba(255,255,255,0.90)\">\r\n<script async src=\"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n<!-- ZOST: Banner (200x200) #2 -->\r\n<ins class=\"adsbygoogle\"\r\n style=\"display: contents;width:200px;height:200px\"\r\n data-ad-client=\"ca-pub-3110076814260873\"\r\n data-ad-slot=\"2605418240\"></ins>\r\n<script>\r\n(adsbygoogle = window.adsbygoogle || []).push({});\r\n</script>\r\n</div>',0,2,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2018-12-03 17:21:19','0000-00-00 00:00:00','2019-01-03 00:00:00','2018-12-03 17:20:27','*',24,'','2020-05-29 00:23:54',24,4),(34,9,1,'Banner 200x200 (Basic Black) #1','banner-200-200-basicblack-1',0,1102711,0,'',1,115,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (200x200) #1 -->\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:200px;height:200px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"8448342346\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2020-06-26 00:00:00','2020-05-26 23:32:16','*',24,'','2020-06-29 21:13:20',24,20),(36,9,1,'Banner 200x200 (Basic Black) #2','banner-200-200-basicblack-2',0,1102691,0,'',1,116,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (200x200) #2 -->\r\n<ins class=\"adsbygoogle\" style=\"display:inline-block;width:200px;height:200px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"2605418240\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,15,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','2020-06-29 00:00:00','2020-05-29 01:38:00','*',24,'','2020-06-29 21:13:10',24,6),(37,9,1,'Banner 728x90 (Basic Black) #1','banner-728x90-basicblack-1',0,264039,0,'',1,117,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (728x90) -->\r\n<ins class=\"adsbygoogle\" style=\"display:contents;width:728px;height:90px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"6443009564\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,1,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2020-06-03 23:26:11','0000-00-00 00:00:00','2020-07-03 00:00:00','2020-06-03 23:24:36','*',24,'','2020-06-28 21:29:47',24,13),(38,9,1,'Banner 728x90 (Basic Black) #2','banner-728x90-basicblack-2',0,264051,0,'',1,118,'','<script async src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"> </script>\r\n<!-- ZOST: Banner (728x90) #2 -->\r\n<ins class=\"adsbygoogle\" style=\"display:contents;width:728px;height:90px\" data-ad-client=\"ca-pub-3110076814260873\" data-ad-slot=\"7210184376\"> </ins>\r\n<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>',0,17,'','{\"imageurl\":\"\",\"width\":\"\",\"height\":\"\",\"alt\":\"\"}',0,'',-1,0,0,0,'0000-00-00 00:00:00','2020-06-03 23:26:11','0000-00-00 00:00:00','2020-07-03 00:00:00','2020-06-03 23:47:06','*',24,'','2020-06-28 21:30:12',24,5);
388388 /*!40000 ALTER TABLE `joomla_banners` ENABLE KEYS */;
389389 UNLOCK TABLES;
390390
@@ -513,7 +513,7 @@
513513
514514 LOCK TABLES `joomla_contact_details` WRITE;
515515 /*!40000 ALTER TABLE `joomla_contact_details` DISABLE KEYS */;
516-INSERT INTO `joomla_contact_details` (`id`, `name`, `alias`, `con_position`, `address`, `suburb`, `state`, `country`, `postcode`, `telephone`, `fax`, `misc`, `image`, `email_to`, `default_con`, `published`, `checked_out`, `checked_out_time`, `ordering`, `params`, `user_id`, `catid`, `access`, `mobile`, `webpage`, `sortname1`, `sortname2`, `sortname3`, `language`, `created`, `created_by`, `created_by_alias`, `modified`, `modified_by`, `metakey`, `metadesc`, `metadata`, `featured`, `xreference`, `publish_up`, `publish_down`, `version`, `hits`) VALUES (1,'Contact Name Here','name','Position','Street Address','Suburb','State','Country','Zip Code','Telephone','Fax','<p>Information about or by the contact.</p>','images/powered_by.png','email@example.com',1,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Twitter\",\"linka\":\"http:\\/\\/twitter.com\\/joomla\",\"linkb_name\":\"YouTube\",\"linkb\":\"http:\\/\\/www.youtube.com\\/user\\/joomla\",\"linkc_name\":\"Facebook\",\"linkc\":\"http:\\/\\/www.facebook.com\\/joomla\",\"linkd_name\":\"FriendFeed\",\"linkd\":\"http:\\/\\/friendfeed.com\\/joomla\",\"linke_name\":\"Scribed\",\"linke\":\"http:\\/\\/www.scribd.com\\/people\\/view\\/504592-joomla\",\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,16,1,'','','last','first','middle','en-GB','2011-01-01 00:00:01',24,'','2011-12-27 12:23:32',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(2,'Webmaster','webmaster','','','','','','','','','','','webmaster@example.com',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"1\",\"show_email_copy\":\"1\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"1\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,34,1,'','','','','','en-GB','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(3,'Owner','owner','','','','','','','','','<p>I\'m the owner of this store.</p>','','',0,-2,0,'0000-00-00 00:00:00',2,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,36,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(4,'Buyer','buyer','','','','','','','','','<p>I am in charge of buying fruit. If you sell good fruit, contact me.</p>','','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"0\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,36,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(5,'Bananas','bananas','Scientific Name: Musa','Image Credit: Enzik\r\nRights: Creative Commons Share Alike Unported 3.0\r\nSource: http://commons.wikimedia.org/wiki/File:Bananas_-_Morocco.jpg','','Type: Herbaceous','Large Producers: India, China, Brasil','','','','<p>Bananas are a great source of potassium.</p>\r\n<p> </p>','images/sampledata/fruitshop/bananas_2.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"show_with_link\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"1\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"1\",\"show_postcode\":\"\",\"show_country\":\"1\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Banana English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Banana\",\"linkb_name\":\"Wikipedia: \\u0939\\u093f\\u0928\\u094d\\u0926\\u0940 \\u0915\\u0947\\u0932\\u093e\",\"linkb\":\"http:\\/\\/hi.wikipedia.org\\/wiki\\/%E0%A4%95%E0%A5%87%E0%A4%B2%E0%A4%BE\",\"linkc_name\":\"Wikipedia:Banana Portugu\\u00eas\",\"linkc\":\"http:\\/\\/pt.wikipedia.org\\/wiki\\/Banana\",\"linkd_name\":\"Wikipedia: \\u0411\\u0430\\u043d\\u0430\\u043d \\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439\",\"linkd\":\"http:\\/\\/ru.wikipedia.org\\/\\u0411\\u0430\\u043d\\u0430\\u043d\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,39,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(6,'Apples','apples','Scientific Name: Malus domestica','Image Credit: Fievet\r\nRights: Public Domain\r\nSource: http://commons.wikimedia.org/wiki/File:Pommes_vertes.JPG','','Family: Rosaceae','Large: Producers: China, United States','','','','<p>Apples are a versatile fruit, used for eating, cooking, and preserving.</p>\r\n<p>There are more that 7500 different kinds of apples grown around the world.</p>','images/sampledata/fruitshop/apple.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Apples English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Apple\",\"linkb_name\":\"Wikipedia: Manzana Espa\\u00f1ol \",\"linkb\":\"http:\\/\\/es.wikipedia.org\\/wiki\\/Manzana\",\"linkc_name\":\"Wikipedia: \\u82f9\\u679c \\u4e2d\\u6587\",\"linkc\":\"http:\\/\\/zh.wikipedia.org\\/zh\\/\\u82f9\\u679c\",\"linkd_name\":\"Wikipedia: Tofaa Kiswahili\",\"linkd\":\"http:\\/\\/sw.wikipedia.org\\/wiki\\/Tofaa\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,38,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(7,'Tamarind','tamarind','Scientific Name: Tamarindus indica','Image Credit: Franz Eugen Köhler, Köhler\'s Medizinal-Pflanzen \r\nRights: Public Domain\r\nSource:http://commons.wikimedia.org/wiki/File:Koeh-134.jpg','','Family: Fabaceae','Large Producers: India, United States','','','','<p>Tamarinds are a versatile fruit used around the world. In its young form it is used in hot sauces; ripened it is the basis for many refreshing drinks.</p>\r\n<p> </p>','images/sampledata/fruitshop/tamarind.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Tamarind English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Tamarind\",\"linkb_name\":\"Wikipedia: \\u09a4\\u09c7\\u0981\\u09a4\\u09c1\\u09b2 \\u09ac\\u09be\\u0982\\u09b2\\u09be \",\"linkb\":\"http:\\/\\/bn.wikipedia.org\\/wiki\\/\\u09a4\\u09c7\\u0981\\u09a4\\u09c1\\u09b2 \",\"linkc_name\":\"Wikipedia: Tamarinier Fran\\u00e7ais\",\"linkc\":\"http:\\/\\/fr.wikipedia.org\\/wiki\\/Tamarinier\",\"linkd_name\":\"Wikipedia:Tamaline lea faka-Tonga\",\"linkd\":\"http:\\/\\/to.wikipedia.org\\/wiki\\/Tamaline\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,57,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(8,'Shop Address','shop-address','','','Our City','Our Province','Our Country','','555-555-5555','','<p>Here are directions for how to get to our shop.</p>','','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,35,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(9,'Carlos B. Feitoza Filho','carlos-b-feitoza-filho-con','Fundador','','Olinda','Pernambuco','Brasil','','','','<p style=\"text-align: justify;\"><em>Desenvolvedor Delphi experiente e criador de ferramentas, componentes e aplicações usando API Win32 e Object Pascal puro. Possui experiência também em PHP, JavasCript, CSS e HTML.</em></p>\r\n<hr />\r\n<p style=\"text-align: justify;\"><em>Com experiência em Computação desde 1996, é autodidata e iniciou sua carreira entendendo o funcionamento dos sistemas operacionais Microsoft, naquela época, Windows \'95. Sua primeira experiência com linguagens de programação foi o Q-Basic da Microsoft, que vinha com o Sistema Operacional MS-DOS 6.22. Com esta linguagem o interesse no desenvolvimento de sistemas tornou-se extremamente forte.</em></p>\r\n<p style=\"text-align: justify;\"><em>Após primeiros experimentos com o Q-Basic, sentiu a necessidade de criar programas executáveis, coisa que o Q-Basic não era capaz de fazer. Então, sua próxima meta foi o CA Clipper e com ele, o entendimento do que era um compilador, um linker e bibliotecas. Com as crescentes necessidades do Mercado e o rápido avanço os sistemas operacionais gráficos (Windows), ele iniciou o aprendizado da programação visual, usando o Borland Turbo C onde começou a entender como aplicações gráficas funcionam. Pouco tempo depois ele descobriu o Delphi, IDE da Borland na sua versão 2.0. Neste período, consolidou-se como Desenvolvedor para Windows usando a ferramenta da Borland para a plataforma Win32. Ele desenvolveu sistemas em Delphi 2, 4, 5, 6, 7, BDS 2005, 2006, CRS 2009, ERS 2010, ERS XE e atualmente ERS XE5. Com o desenvolvimento de aplicações para a plataforma Win32 ele adquiriu um profundo conhecimento de sua API.</em></p>\r\n<p style=\"text-align: justify;\"><em>Durante a época em que estava estudando Delphi e Object Pascal, ele teve contato com outras tecnologias, especialmente para a Web, iniciando com o desenvolvimento básico de simples páginas HTML com CSS. Em seguida sentiu a necessidade de fazer suas páginas mais dinâmicas, então estudou JavaScript. Com o JavaScript ele aprendeu o que era uma linguagem de programação \"Client Side\" e passou a se interessar pela programação \"Server Side\", desenvolvendo alguns projetos em PERL (CGI) e subsequentemente em PHP, linguagem Server Side que ele domina.</em></p>\r\n<p style=\"text-align: justify;\"><em>Em bancos de dados ele conhece Interbase, Oracle, PostGres e MySQL, sendo especialista nos dois últimos.</em></p>','images/contacts/ID0009/FB_IMG_1440091529090.jpg','carlos.b.feitoza.filho@gmail.com',0,1,0,'0000-00-00 00:00:00',3,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"0\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',24,108,1,'','http://zettaomnis.net.br','','','','*','2016-07-26 20:48:19',24,'','2016-08-27 04:12:57',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',17,3712),(10,'Zetta-Ømnis Soluções Tecnológicas','zost-con','','','Olinda','Pernambuco','Brasil','','','','','images/contacts/ID0010/zo.png','',0,1,0,'0000-00-00 00:00:00',4,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,107,1,'','http://www.zettaomnis.net.br','','','','*','2016-08-06 18:19:51',24,'','2016-08-30 01:21:55',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',6,1914),(11,'Contato apague','contato-apague','desenvolvedor','','rec','pe','bra','','','','<p style=\"text-align: justify;\"><em>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at vehicula massa, id aliquam erat. Cras consectetur odio non facilisis blandit. Duis pulvinar tempus rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vitae efficitur ligula, vel semper enim. Proin laoreet elementum libero ut fringilla. Praesent fermentum, lacus sed mattis malesuada, libero metus sagittis neque, et sollicitudin augue libero sed ligula. Etiam pulvinar elit ac sapien dictum, sed venenatis dui consequat. Nulla placerat imperdiet felis, in ullamcorper sapien rutrum congue. Etiam vitae dui felis. Sed interdum tellus vel purus consectetur ornare et a sapien. Duis ac tortor non lectus tincidunt egestas. Phasellus quam purus, vehicula varius ultrices at, auctor in augue. Ut molestie tincidunt varius.</em></p>\r\n<p style=\"text-align: justify;\"><em>Donec pretium facilisis velit, faucibus ultricies sapien tempor sed. In pharetra in metus a varius. Duis dictum diam ut nisl elementum faucibus. Etiam nec fringilla augue. Etiam ultrices mollis nulla, vel sodales nisi pulvinar vitae. Nulla facilisi. Morbi gravida ipsum non aliquet suscipit. Nam in arcu laoreet, vehicula erat at, rhoncus libero. Praesent luctus maximus augue pretium condimentum. Aenean euismod, turpis quis aliquet suscipit, augue odio lobortis metus, posuere facilisis nulla enim non tellus. Phasellus at euismod magna. Suspendisse sodales posuere eros id tempus. Fusce in mollis neque. Donec ac neque tellus.</em></p>\r\n<p style=\"text-align: justify;\"><em>Duis quis nisi a lacus pulvinar bibendum. Nulla ante metus, tempor quis nulla sit amet, egestas viverra augue. Etiam viverra mollis enim, nec lacinia libero suscipit quis. Nam hendrerit velit a erat iaculis pellentesque. Aliquam varius pharetra eleifend. Aliquam aliquam ante et risus vestibulum, at venenatis libero ultricies. Praesent molestie libero arcu, vel cursus sem dapibus dictum. Interdum et malesuada fames ac ante ipsum primis in faucibus.</em></p>','','',0,1,0,'0000-00-00 00:00:00',5,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:34',24,'','2016-08-26 02:43:42',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',6,1639),(12,'Contato apague 2','contato-apague-2','','','','','','','','','','images/powered_by.png','',0,-2,0,'0000-00-00 00:00:00',6,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:42',24,'','2016-08-23 04:52:01',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',2,0),(13,'Contato apague 3','contato-apague-3','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',7,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:46',24,'','2016-08-23 05:05:06',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',3,0),(14,'Contato apague 4','contato-apague-4','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',8,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:57',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,1),(15,'Contato apague 5','contato-apague-5','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',9,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:35',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(16,'Contato apague 6','contato-apague-6','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',10,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:40',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(17,'Contato apague 7','contato-apague-7','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',11,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:44',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(18,'Contato apague 8','contato-apague-8','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',12,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:48',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(19,'Contato apague 9','contato-apague-9','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',13,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:53',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:32','0000-00-00 00:00:00',1,0),(20,'Contato apague 10','contato-apague-10','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',14,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:57',24,'','2016-08-23 05:05:14',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',3,0),(21,'Contato apague 11','contato-apague-11','','','','','','','','','','images/plus.png','',0,-2,0,'0000-00-00 00:00:00',15,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:01',24,'','2016-08-23 04:51:50',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',2,0),(22,'Contato apague 12','contato-apague-12','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',16,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:06',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(23,'Contato apague 13','contato-apague-13','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',17,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:10',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(24,'Contato apague 14','contato-apague-14','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',18,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:14',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(25,'Contato apague 15','contato-apague-15','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',19,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:18',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(26,'Contato apague 16','contato-apague-16','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',20,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:24',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(27,'Contato apague 17','contato-apague-17','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',21,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:28',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(28,'Contato apague 18','contato-apague-18','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',22,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:33',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(29,'Contato apague 19','contato-apague-19','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',23,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:37',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(30,'Contato apague 20','contato-apague-20','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',24,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:41',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0);
516+INSERT INTO `joomla_contact_details` (`id`, `name`, `alias`, `con_position`, `address`, `suburb`, `state`, `country`, `postcode`, `telephone`, `fax`, `misc`, `image`, `email_to`, `default_con`, `published`, `checked_out`, `checked_out_time`, `ordering`, `params`, `user_id`, `catid`, `access`, `mobile`, `webpage`, `sortname1`, `sortname2`, `sortname3`, `language`, `created`, `created_by`, `created_by_alias`, `modified`, `modified_by`, `metakey`, `metadesc`, `metadata`, `featured`, `xreference`, `publish_up`, `publish_down`, `version`, `hits`) VALUES (1,'Contact Name Here','name','Position','Street Address','Suburb','State','Country','Zip Code','Telephone','Fax','<p>Information about or by the contact.</p>','images/powered_by.png','email@example.com',1,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Twitter\",\"linka\":\"http:\\/\\/twitter.com\\/joomla\",\"linkb_name\":\"YouTube\",\"linkb\":\"http:\\/\\/www.youtube.com\\/user\\/joomla\",\"linkc_name\":\"Facebook\",\"linkc\":\"http:\\/\\/www.facebook.com\\/joomla\",\"linkd_name\":\"FriendFeed\",\"linkd\":\"http:\\/\\/friendfeed.com\\/joomla\",\"linke_name\":\"Scribed\",\"linke\":\"http:\\/\\/www.scribd.com\\/people\\/view\\/504592-joomla\",\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,16,1,'','','last','first','middle','en-GB','2011-01-01 00:00:01',24,'','2011-12-27 12:23:32',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(2,'Webmaster','webmaster','','','','','','','','','','','webmaster@example.com',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"1\",\"show_email_copy\":\"1\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"1\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,34,1,'','','','','','en-GB','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(3,'Owner','owner','','','','','','','','','<p>I\'m the owner of this store.</p>','','',0,-2,0,'0000-00-00 00:00:00',2,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,36,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(4,'Buyer','buyer','','','','','','','','','<p>I am in charge of buying fruit. If you sell good fruit, contact me.</p>','','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"0\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,36,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(5,'Bananas','bananas','Scientific Name: Musa','Image Credit: Enzik\r\nRights: Creative Commons Share Alike Unported 3.0\r\nSource: http://commons.wikimedia.org/wiki/File:Bananas_-_Morocco.jpg','','Type: Herbaceous','Large Producers: India, China, Brasil','','','','<p>Bananas are a great source of potassium.</p>\r\n<p> </p>','images/sampledata/fruitshop/bananas_2.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"show_with_link\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"1\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"1\",\"show_postcode\":\"\",\"show_country\":\"1\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Banana English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Banana\",\"linkb_name\":\"Wikipedia: \\u0939\\u093f\\u0928\\u094d\\u0926\\u0940 \\u0915\\u0947\\u0932\\u093e\",\"linkb\":\"http:\\/\\/hi.wikipedia.org\\/wiki\\/%E0%A4%95%E0%A5%87%E0%A4%B2%E0%A4%BE\",\"linkc_name\":\"Wikipedia:Banana Portugu\\u00eas\",\"linkc\":\"http:\\/\\/pt.wikipedia.org\\/wiki\\/Banana\",\"linkd_name\":\"Wikipedia: \\u0411\\u0430\\u043d\\u0430\\u043d \\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439\",\"linkd\":\"http:\\/\\/ru.wikipedia.org\\/\\u0411\\u0430\\u043d\\u0430\\u043d\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,39,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(6,'Apples','apples','Scientific Name: Malus domestica','Image Credit: Fievet\r\nRights: Public Domain\r\nSource: http://commons.wikimedia.org/wiki/File:Pommes_vertes.JPG','','Family: Rosaceae','Large: Producers: China, United States','','','','<p>Apples are a versatile fruit, used for eating, cooking, and preserving.</p>\r\n<p>There are more that 7500 different kinds of apples grown around the world.</p>','images/sampledata/fruitshop/apple.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Apples English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Apple\",\"linkb_name\":\"Wikipedia: Manzana Espa\\u00f1ol \",\"linkb\":\"http:\\/\\/es.wikipedia.org\\/wiki\\/Manzana\",\"linkc_name\":\"Wikipedia: \\u82f9\\u679c \\u4e2d\\u6587\",\"linkc\":\"http:\\/\\/zh.wikipedia.org\\/zh\\/\\u82f9\\u679c\",\"linkd_name\":\"Wikipedia: Tofaa Kiswahili\",\"linkd\":\"http:\\/\\/sw.wikipedia.org\\/wiki\\/Tofaa\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,38,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(7,'Tamarind','tamarind','Scientific Name: Tamarindus indica','Image Credit: Franz Eugen Köhler, Köhler\'s Medizinal-Pflanzen \r\nRights: Public Domain\r\nSource:http://commons.wikimedia.org/wiki/File:Koeh-134.jpg','','Family: Fabaceae','Large Producers: India, United States','','','','<p>Tamarinds are a versatile fruit used around the world. In its young form it is used in hot sauces; ripened it is the basis for many refreshing drinks.</p>\r\n<p> </p>','images/sampledata/fruitshop/tamarind.jpg','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"plain\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"1\",\"linka_name\":\"Wikipedia: Tamarind English\",\"linka\":\"http:\\/\\/en.wikipedia.org\\/wiki\\/Tamarind\",\"linkb_name\":\"Wikipedia: \\u09a4\\u09c7\\u0981\\u09a4\\u09c1\\u09b2 \\u09ac\\u09be\\u0982\\u09b2\\u09be \",\"linkb\":\"http:\\/\\/bn.wikipedia.org\\/wiki\\/\\u09a4\\u09c7\\u0981\\u09a4\\u09c1\\u09b2 \",\"linkc_name\":\"Wikipedia: Tamarinier Fran\\u00e7ais\",\"linkc\":\"http:\\/\\/fr.wikipedia.org\\/wiki\\/Tamarinier\",\"linkd_name\":\"Wikipedia:Tamaline lea faka-Tonga\",\"linkd\":\"http:\\/\\/to.wikipedia.org\\/wiki\\/Tamaline\",\"linke_name\":\"\",\"linke\":\"\",\"contact_layout\":\"beez5:encyclopedia\"}',0,57,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(8,'Shop Address','shop-address','','','Our City','Our Province','Our Country','','555-555-5555','','<p>Here are directions for how to get to our shop.</p>','','',0,-2,0,'0000-00-00 00:00:00',1,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":\"\",\"linkb_name\":\"\",\"linkb\":\"\",\"linkc_name\":\"\",\"linkc\":\"\",\"linkd_name\":\"\",\"linkd\":\"\",\"linke_name\":\"\",\"linke\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,35,1,'','','','','','*','2011-01-01 00:00:01',24,'','2011-01-01 00:00:01',42,'','','{\"robots\":\"\",\"rights\":\"\"}',1,'','0000-00-00 00:00:00','0000-00-00 00:00:00',1,0),(9,'Carlos B. Feitoza Filho','carlos-b-feitoza-filho-con','Fundador','','Olinda','Pernambuco','Brasil','','','','<p style=\"text-align: justify;\"><em>Desenvolvedor Delphi experiente e criador de ferramentas, componentes e aplicações usando API Win32 e Object Pascal puro. Possui experiência também em PHP, JavasCript, CSS e HTML.</em></p>\r\n<hr />\r\n<p style=\"text-align: justify;\"><em>Com experiência em Computação desde 1996, é autodidata e iniciou sua carreira entendendo o funcionamento dos sistemas operacionais Microsoft, naquela época, Windows \'95. Sua primeira experiência com linguagens de programação foi o Q-Basic da Microsoft, que vinha com o Sistema Operacional MS-DOS 6.22. Com esta linguagem o interesse no desenvolvimento de sistemas tornou-se extremamente forte.</em></p>\r\n<p style=\"text-align: justify;\"><em>Após primeiros experimentos com o Q-Basic, sentiu a necessidade de criar programas executáveis, coisa que o Q-Basic não era capaz de fazer. Então, sua próxima meta foi o CA Clipper e com ele, o entendimento do que era um compilador, um linker e bibliotecas. Com as crescentes necessidades do Mercado e o rápido avanço os sistemas operacionais gráficos (Windows), ele iniciou o aprendizado da programação visual, usando o Borland Turbo C onde começou a entender como aplicações gráficas funcionam. Pouco tempo depois ele descobriu o Delphi, IDE da Borland na sua versão 2.0. Neste período, consolidou-se como Desenvolvedor para Windows usando a ferramenta da Borland para a plataforma Win32. Ele desenvolveu sistemas em Delphi 2, 4, 5, 6, 7, BDS 2005, 2006, CRS 2009, ERS 2010, ERS XE e atualmente ERS XE5. Com o desenvolvimento de aplicações para a plataforma Win32 ele adquiriu um profundo conhecimento de sua API.</em></p>\r\n<p style=\"text-align: justify;\"><em>Durante a época em que estava estudando Delphi e Object Pascal, ele teve contato com outras tecnologias, especialmente para a Web, iniciando com o desenvolvimento básico de simples páginas HTML com CSS. Em seguida sentiu a necessidade de fazer suas páginas mais dinâmicas, então estudou JavaScript. Com o JavaScript ele aprendeu o que era uma linguagem de programação \"Client Side\" e passou a se interessar pela programação \"Server Side\", desenvolvendo alguns projetos em PERL (CGI) e subsequentemente em PHP, linguagem Server Side que ele domina.</em></p>\r\n<p style=\"text-align: justify;\"><em>Em bancos de dados ele conhece Interbase, Oracle, PostGres e MySQL, sendo especialista nos dois últimos.</em></p>','images/contacts/ID0009/FB_IMG_1440091529090.jpg','carlos.b.feitoza.filho@gmail.com',0,1,0,'0000-00-00 00:00:00',3,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"0\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',24,108,1,'','http://zettaomnis.net.br','','','','*','2016-07-26 20:48:19',24,'','2016-08-27 04:12:57',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',17,3767),(10,'Zetta-Ømnis Soluções Tecnológicas','zost-con','','','Olinda','Pernambuco','Brasil','','','','','images/contacts/ID0010/zo.png','',0,1,0,'0000-00-00 00:00:00',4,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,107,1,'','http://www.zettaomnis.net.br','','','','*','2016-08-06 18:19:51',24,'','2016-08-30 01:21:55',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','0000-00-00 00:00:00','0000-00-00 00:00:00',6,1960),(11,'Contato apague','contato-apague','desenvolvedor','','rec','pe','bra','','','','<p style=\"text-align: justify;\"><em>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis at vehicula massa, id aliquam erat. Cras consectetur odio non facilisis blandit. Duis pulvinar tempus rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vitae efficitur ligula, vel semper enim. Proin laoreet elementum libero ut fringilla. Praesent fermentum, lacus sed mattis malesuada, libero metus sagittis neque, et sollicitudin augue libero sed ligula. Etiam pulvinar elit ac sapien dictum, sed venenatis dui consequat. Nulla placerat imperdiet felis, in ullamcorper sapien rutrum congue. Etiam vitae dui felis. Sed interdum tellus vel purus consectetur ornare et a sapien. Duis ac tortor non lectus tincidunt egestas. Phasellus quam purus, vehicula varius ultrices at, auctor in augue. Ut molestie tincidunt varius.</em></p>\r\n<p style=\"text-align: justify;\"><em>Donec pretium facilisis velit, faucibus ultricies sapien tempor sed. In pharetra in metus a varius. Duis dictum diam ut nisl elementum faucibus. Etiam nec fringilla augue. Etiam ultrices mollis nulla, vel sodales nisi pulvinar vitae. Nulla facilisi. Morbi gravida ipsum non aliquet suscipit. Nam in arcu laoreet, vehicula erat at, rhoncus libero. Praesent luctus maximus augue pretium condimentum. Aenean euismod, turpis quis aliquet suscipit, augue odio lobortis metus, posuere facilisis nulla enim non tellus. Phasellus at euismod magna. Suspendisse sodales posuere eros id tempus. Fusce in mollis neque. Donec ac neque tellus.</em></p>\r\n<p style=\"text-align: justify;\"><em>Duis quis nisi a lacus pulvinar bibendum. Nulla ante metus, tempor quis nulla sit amet, egestas viverra augue. Etiam viverra mollis enim, nec lacinia libero suscipit quis. Nam hendrerit velit a erat iaculis pellentesque. Aliquam varius pharetra eleifend. Aliquam aliquam ante et risus vestibulum, at venenatis libero ultricies. Praesent molestie libero arcu, vel cursus sem dapibus dictum. Interdum et malesuada fames ac ante ipsum primis in faucibus.</em></p>','','',0,1,0,'0000-00-00 00:00:00',5,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:34',24,'','2016-08-26 02:43:42',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',6,1669),(12,'Contato apague 2','contato-apague-2','','','','','','','','','','images/powered_by.png','',0,-2,0,'0000-00-00 00:00:00',6,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:42',24,'','2016-08-23 04:52:01',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',2,0),(13,'Contato apague 3','contato-apague-3','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',7,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:46',24,'','2016-08-23 05:05:06',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',3,0),(14,'Contato apague 4','contato-apague-4','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',8,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:28:57',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,1),(15,'Contato apague 5','contato-apague-5','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',9,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:35',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(16,'Contato apague 6','contato-apague-6','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',10,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:40',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(17,'Contato apague 7','contato-apague-7','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',11,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:44',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(18,'Contato apague 8','contato-apague-8','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',12,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:48',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(19,'Contato apague 9','contato-apague-9','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',13,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:53',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:32','0000-00-00 00:00:00',1,0),(20,'Contato apague 10','contato-apague-10','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',14,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:29:57',24,'','2016-08-23 05:05:14',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',3,0),(21,'Contato apague 11','contato-apague-11','','','','','','','','','','images/plus.png','',0,-2,0,'0000-00-00 00:00:00',15,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:01',24,'','2016-08-23 04:51:50',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',2,0),(22,'Contato apague 12','contato-apague-12','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',16,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:06',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(23,'Contato apague 13','contato-apague-13','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',17,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:10',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(24,'Contato apague 14','contato-apague-14','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',18,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:14',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(25,'Contato apague 15','contato-apague-15','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',19,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:18',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(26,'Contato apague 16','contato-apague-16','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',20,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:24',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(27,'Contato apague 17','contato-apague-17','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',21,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:28',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(28,'Contato apague 18','contato-apague-18','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',22,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:33',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(29,'Contato apague 19','contato-apague-19','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',23,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:37',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0),(30,'Contato apague 20','contato-apague-20','','','','','','','','','','','',0,-2,0,'0000-00-00 00:00:00',24,'{\"show_contact_category\":\"\",\"show_contact_list\":\"\",\"presentation_style\":\"\",\"show_tags\":\"\",\"show_name\":\"\",\"show_position\":\"\",\"show_email\":\"\",\"show_street_address\":\"\",\"show_suburb\":\"\",\"show_state\":\"\",\"show_postcode\":\"\",\"show_country\":\"\",\"show_telephone\":\"\",\"show_mobile\":\"\",\"show_fax\":\"\",\"show_webpage\":\"\",\"show_misc\":\"\",\"show_image\":\"\",\"allow_vcard\":\"\",\"show_articles\":\"\",\"articles_display_num\":\"\",\"show_profile\":\"\",\"show_links\":\"\",\"linka_name\":\"\",\"linka\":false,\"linkb_name\":\"\",\"linkb\":false,\"linkc_name\":\"\",\"linkc\":false,\"linkd_name\":\"\",\"linkd\":false,\"linke_name\":\"\",\"linke\":false,\"contact_layout\":\"\",\"show_email_form\":\"\",\"show_email_copy\":\"\",\"banned_email\":\"\",\"banned_subject\":\"\",\"banned_text\":\"\",\"validate_session\":\"\",\"custom_reply\":\"\",\"redirect\":\"\"}',0,108,1,'','','','','','*','2016-08-23 02:30:41',24,'','2016-08-23 02:31:25',24,'','','{\"robots\":\"\",\"rights\":\"\"}',0,'','2016-08-26 02:32:26','0000-00-00 00:00:00',1,0);
517517 /*!40000 ALTER TABLE `joomla_contact_details` ENABLE KEYS */;
518518 UNLOCK TABLES;
519519
@@ -566,7 +566,7 @@
566566 KEY `idx_language` (`language`),
567567 KEY `idx_xreference` (`xreference`),
568568 KEY `idx_alias` (`alias`(191))
569-) ENGINE=InnoDB AUTO_INCREMENT=229 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
569+) ENGINE=InnoDB AUTO_INCREMENT=230 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
570570 /*!40101 SET character_set_client = @saved_cs_client */;
571571
572572 --
@@ -575,9 +575,9 @@
575575
576576 LOCK TABLES `joomla_content` WRITE;
577577 /*!40000 ALTER TABLE `joomla_content` DISABLE KEYS */;
578-INSERT INTO `joomla_content` (`id`, `asset_id`, `title`, `alias`, `introtext`, `fulltext`, `state`, `catid`, `created`, `created_by`, `created_by_alias`, `modified`, `modified_by`, `checked_out`, `checked_out_time`, `publish_up`, `publish_down`, `images`, `urls`, `attribs`, `version`, `ordering`, `metakey`, `metadesc`, `access`, `hits`, `metadata`, `featured`, `language`, `xreference`, `note`) VALUES (71,174,'Comprimindo os Data Packets no DataSnap','compressaodedatapacketxml-art','<p style=\"text-align: justify;\">Procure um meio de validar se sempre se usa base64 e se não tiver certeza, altere o texto para não falar a respeito disso</p>\r\n<p style=\"text-align: justify;\">A comunicação de dados no DataSnap é feita no modelo requisição/resposta, isto é, o cliente, conhecido formalmente como \"thin client\" (cliente magro) envia uma requisição ao middleware (servidor de aplicação) e o mesmo responde de acordo. Quanto mais rápido esse processo se dá, mais felizes seus clientes ficarão, mas existem duas coisas que podem desacelerar o ciclo <strong>requisição / processamento / resposta</strong>: o tempo de processamento e a quantidade de dados que trafegam durante a requisição ou resposta. Se você trabalha com DataSnap e geralmente faz consultas que retornam grande quantidade de dados, situação comum em relatórios, este artigo é para você! Continue lendo...</p>\r\n','\r\n<p style=\"text-align: justify;\">No modelo de requisição/resposta do DataSnap, bastante eficiente aliás, uma das maiores vantagens é justamente a redução drástica do tráfego de dados, pois todas as requisições são stateless e não ficam ativas mais tempo que o necessário. Grosso modo, o tempo em que uma conexão fica estabelecida entre um cliente e o middleware começa com a requisição, passando pelo processamento (por parte do servidor de aplicação) e finaliza quando este último envia a resposta de volta ao cliente. O tempo de processamento depende de como o middleware foi programado e não será abordado aqui. Neste artigo vou ensinar um meio através do qual os dados enviados na requisição e os recebidos nas respostas podem ser comprimidos drasticamente.</p>\r\n<p style=\"text-align: justify;\">Hoje em dia o Delphi já possui meios para utilizar JSON como formato para intercâmbio de informações no DataSnap, no entanto quero salientar que a compressão de <strong>Data Packets</strong> (<strong>DP</strong>) independe da forma como os dados são trafegados na rede. Usar XML, JSON ou outra forma mais antiga de transporte como sockets por exemplo não interfere no tamanho do DP, o qual é sempre enviado de forma codificada em Base64.</p>\r\n<p style=\"text-align: justify;\">De forma bem geral, no DataSnap (<strong>DS</strong>) as requisições e respostas são construídas de acordo com a tecnologia utilizada para transporte, por exemplo, ao se usar SOAP, será usado XML e o DP faz parte das mensagens que são enviadas entre o middleware e o cliente, ou seja, não importa se está sendo usado JSON ou XML, o DP está lá, codificado em Base64.</p>\r\n<p style=\"text-align: justify;\">Mas afinal, o que seria esse DP (DataPacket)? Novamente, não quero me estender neste assunto, mas basicamente o DP pode assumir dois significados. Ele pode ser a representação de um TClientDataSet contendo seus dados e opcionalmente algumas de suas características ou pode ser a representação de um Delta. E o que seria um Delta? Um Delta é o conjunto de todas as alterações sofridas por um TClientDataSet a partir de um estado inicial não alterado, por exemplo, quando inserimos 2 registros, excluímos 3 registros e atualizamos 4 registros em um TClientDataSet, ao confirmarmos todas estas operações, será enviado ao middleware um Delta contendo exatamente estas operações (duas inserções, três exclusões e quatro atualizações) e ao chegar lá estas operações são replicadas como se estivéssemos fazendo-as diretamente no servidor de aplicação. Ao terminar este processamento, o middleware envia de volta ao cliente um outro Delta, com o resultado das operações realizadas (sucessos e erros).</p>\r\n<p style=\"text-align: justify;\">Resumidamente, basta entender que cada operação confirmada no cliente gera um DP que é enviado ao middleware e que, após o conteúdo desse DP for processado, um outro DP será enviado de volta ao cliente com o resultado de todas as operações realizadas. Esses DPs trocados são codificados em Base64 e por este motivo, dependendo de quantas operações foram realizadas ou de quantos dados serão retornados do middleware, o tamanho desse código aumenta substancialmente.</p>\r\n<p style=\"text-align: justify;\">Antes de continuar quero informar que não sou especialista na forma tradicional de DataSnap, e nem nas formas mais modernas. De fato, eu resolvi aprender apenas uma forma (DataSnap sobre SOAP), a que eu achei mais interessante, e me aprofundei na mesma. Os procedimentos explicados aqui funcionaram pra minha realidade, mas eu imagino que com algumas modificações ele pode servir a qualquer tipo de forma de uso do DataSnap. Então finalmente vamos ao que interessa.</p>\r\n<p>Primeiramente, no servidor, abra o Remote Datamodule e em sua classe, sobrescreva os seguintes métodos na seção public, da forma como está abaixo:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function SAS_ApplyUpdates(const ProviderName: WideString; \r\n Delta: OleVariant; \r\n MaxErrors: Integer; \r\n out ErrorCount: Integer; \r\n var OwnerData: OleVariant): OleVariant; override; safecall;\r\n\r\nfunction SAS_GetRecords(const ProviderName: WideString; \r\n Count: Integer; \r\n out RecsOut: Integer; \r\n Options: Integer; \r\n const CommandText: WideString; \r\n var Params: OleVariant; \r\n var OwnerData: OleVariant): OleVariant; override; safecall;</code></pre>\r\n<p style=\"text-align: justify;\">Estes dois métodos são responsáveis por enviar as alterações feitas no cliente (Delta) e obter os registros de uma determinada tabela ou consulta (dependendo da sua implementação) respectivamente. É nestes dois métodos onde concentram-se a maior parte do tráfego de dados e por isso deve ser neles onde a compressão/descompressão deve ser realizada.</p>\r\n<p style=\"text-align: justify;\">A implementação destes dois métodos vem a seguir. Assumo que o nome da classe do Remote DataModule seja simplesmente <strong>TRemoteDataModule</strong>:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function TRemoteDataModule.SAS_ApplyUpdates(const ProviderName: WideString; \r\n Delta: OleVariant; \r\n MaxErrors: Integer; \r\n out ErrorCount: Integer; \r\n var OwnerData: OleVariant): OleVariant;\r\nbegin\r\n { Descomprime o Delta o qual foi comprimido na aplicação cliente }\r\n OleVariantByteArrayUCLDecompress(Delta);\r\n { Executa o método AS_ApplyUpdates original }\r\n Result := inherited;\r\n { Comprime o resultado, o qual é enviado de volta ao cliente no final do processamento }\r\n OleVariantByteArrayUCLCompress(Result);\r\nend;\r\n\r\nfunction TRemoteDataModule.SAS_GetRecords(const ProviderName: WideString; \r\n Count: Integer; \r\n out RecsOut: Integer;\r\n Options: Integer; \r\n const CommandText: WideString; \r\n var Params, \r\n OwnerData: OleVariant): OleVariant;\r\nbegin\r\n { Executa o método SAS_GetRecords com os parâmetros que foram fornecidos }\r\n Result := inherited;\r\n\r\n { Comprime o resultado, o qual é enviado de volta ao cliente no final do processamento }\r\n OleVariantByteArrayUCLCompress(Result);\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Note a presença dos dois procedures OleVariantByteArrayUCLDecompress e OleVariantByteArrayUCLCompress. Estes procedures são os responsáveis pela descompressão e compressão de um \"OleVariantByteArray\", respectivamente. Um OleVariantByteArray é como eu chamo os dados que são manipulados pelos métodos \"SAS_\". Após alguma depuração profunda descobri que o conteúdo dos retornos das funções e de alguns parâmetros que contém Data Packets, são salvos como Array de Bytes. Por isso eu chamo de OleVariantByteArray.</p>\r\n<p style=\"text-align: justify;\">UCL é o nome da biblioteca de compressão. A sigla significa \"Ultimate Compression Library\". Para saber mais sobre o UCL, siga este <a href=\"http://www.oberhumer.com/opensource/ucl/\">link</a>. Estes dois procedures foram elaborados por mim. Abaixo está a implementação de ambos:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>procedure OleVariantByteArrayUCLDecompress(var aOleVariant: OleVariant);\r\nvar\r\n MemoryStream: TMemoryStream;\r\nbegin\r\n if VarIsNull(aOleVariant) then\r\n Exit;\r\n\r\n MemoryStream := TMemoryStream.Create;\r\n try\r\n UclDeCompressStream(OleVariantByteArrayToMemoryStream(aOleVariant),MemoryStream);\r\n aOleVariant := OleVariantByteArrayFromMemoryStream(MemoryStream);\r\n finally\r\n MemoryStream.Free;\r\n end;\r\nend;\r\n\r\nprocedure OleVariantByteArrayUCLCompress(var aOleVariant: OleVariant);\r\nvar\r\n MemoryStream: TMemoryStream;\r\nbegin\r\n if VarIsNull(aOleVariant) then\r\n Exit;\r\n\r\n MemoryStream := TMemoryStream.Create;\r\n try\r\n UclCompressStream(OleVariantByteArrayToMemoryStream(aOleVariant),MemoryStream);\r\n aOleVariant := OleVariantByteArrayFromMemoryStream(MemoryStream);\r\n finally\r\n MemoryStream.Free;\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Perceba que ainda existem algumas funções desconhecidas. São elas <strong>UclDeCompressStream</strong>, <strong>OleVariantByteArrayToMemoryStream</strong>, <strong>OleVariantByteArrayFromMemoryStream</strong>, e <strong>UclCompressStream</strong>. As funções <strong>UclCompressStream</strong> e <strong>UclDeCompressStream</strong> são da biblioteca DiUCL a qual pode ser encontrada <a href=\"http://www.yunqa.de/delphi/products/ucl/index\">aqui</a>. Baixe esta biblioteca e use estas funções, as quais estão declaradas na unit DIUclStreams. Abaixo estão as implementações das outras funções:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function OleVariantByteArrayToMemoryStream(const aOleVariant: OleVariant): TMemoryStream;\r\nvar\r\n Data: Pointer;\r\n Size: integer;\r\nbegin\r\n Result := TMemoryStream.Create;\r\n try\r\n Size := OleVariantByteArraySize(aOleVariant);\r\n\r\n Data := VarArrayLock(aOleVariant);\r\n try\r\n Result.WriteBuffer(Data^, Size);\r\n finally\r\n Result.Position := 0;\r\n VarArrayUnlock(aOleVariant);\r\n end;\r\n except\r\n FreeAndNil(Result);\r\n end;\r\nend;\r\n\r\nfunction OleVariantByteArrayFromMemoryStream(const aMemoryStream: TMemoryStream): OleVariant;\r\nvar\r\n Data: Pointer;\r\n OldPosition: Int64;\r\nbegin\r\n Result := Unassigned;\r\n\r\n Result := VarArrayCreate([0, Pred(aMemoryStream.Size)], varByte);\r\n Data := VarArrayLock(Result);\r\n\r\n OldPosition := aMemoryStream.Position;\r\n try\r\n aMemoryStream.Position := 0;\r\n aMemoryStream.ReadBuffer(Data^,aMemoryStream.Size);\r\n finally\r\n aMemoryStream.Position := OldPosition;\r\n VarArrayUnlock(Result);\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Estas duas funções de conversão convertem um OleVariantByteArray de, e para, um TMemoryStream. Todos os bons algoritmos de compressão usam ou fornecem meios de comprimir/descomprimir dados em um TMemoryStream, por isso é necessário converter os dados em um TMemoryStream antes de poder manipulá-los. Ainda falta a implementação de uma função, a qual é usada numa das funções acima. A implementação segue:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function OleVariantByteArraySize(const aOleVariant: OleVariant): Cardinal;\r\nbegin\r\n Result := Succ(VarArrayHighBound(aOleVariant, 1) - VarArrayLowBound(aOleVariant, 1));\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Esta função, retorna o tamanho do Array de Bytes contido no OleVariant. Não é possível usar Length diretamente em um OleVariant e por isso tive de subtrair os índices do primeiro e do último elementos do array interno a fim de obter seu tamanho.</p>\r\n<p style=\"text-align: justify;\">Recomendo que todas as funções criadas acima sejam postas em uma unit comum, a qual será utilizada tanto na compilação do Servidor, como na compilação do Cliente. Agora vem a parte do cliente que usa um artifício pouco conhecido mas bastante poderoso e às vezes potencialmente perigoso: Classe Interposer. Uma Classe Interposer, ou \"mediadora\" é como uma Classe Helper, mas ao contrário desta última, a Classe Interposer se localiza hierarquicamente e obrigatoriamente abaixo da classe pai e por este motivo, sua implementação funciona exatamente como se estivéssemos estendendo as funcionalidades de uma classe e não simplesmente incluindo novas propriedades e métodos, como as Classes Helper fazem.</p>\r\n<p style=\"text-align: justify;\">Aqui faremos uma classe Interposer para o TClientDataSet, simplesmente porque o TClientDataSet é o \"outro lado da moeda\" do DataSnap; no Cliente o TClientDataSet e no Servidor o TDataSetProvider dois componentes complementares que juntos fazem tudo acontecer. A implementação da Classe Interposer segue:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>interface\r\n\r\ntype\r\n TClientDataSet = class (DBClient.TClientDataSet)\r\n private\r\n protected\r\n function DoApplyUpdates(Delta: OleVariant; \r\n MaxErrors: Integer; \r\n out ErrorCount: Integer): OleVariant; override;\r\n function DoGetRecords(Count: Integer; \r\n out RecsOut: Integer; \r\n Options: Integer; \r\n const CommandText: WideString; \r\n Params: OleVariant): OleVariant; override;\r\n public\r\n end;\r\n\r\nimplementation\r\n\r\nfunction TClientDataSet.DoApplyUpdates(Delta: OleVariant; \r\n MaxErrors: Integer; \r\n out ErrorCount: Integer): OleVariant;\r\nbegin\r\n OleVariantByteArrayUCLCompress(Delta);\r\n\r\n Result := inherited;\r\n\r\n OleVariantByteArrayUCLDecompress(Result);\r\nend;\r\n\r\nfunction TClientDataSet.DoGetRecords(Count: Integer; \r\n out RecsOut: Integer; \r\n Options: Integer; \r\n const CommandText: WideString; \r\n Params: OleVariant): OleVariant;\r\nbegin\r\n Result := inherited;\r\n\r\n OleVariantByteArrayUCLDecompress(Result);\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Não! O código acima não vai funcionar se você simplesmente copiar e colar. Ainda faltam os uses, os quais você terá de descobrir. Fica como lição de casa. Note que os métodos sobrescritos comprimem ou descomprimem Delta e Result de forma invertida daquilo que foi feito no servidor. Isso era esperado, já que, ao enviar dados do cliente ao servidor usando o método DoApplyUpdates, primeiramente eu devo comprimir o Delta, executar a função no servidor (Result := inherited) e descomprimir o resultado (Result) que vem do servidor. No caso do método DoGetRecords apenas executamos a função no servidor (Result := inherited) e imediatamente após isso, descomprimimos o resultado.</p>\r\n<p style=\"text-align: justify;\">Como se pode ver, a classe interposer tem o mesmo nome da classe original, por isso, se você declarar a classe interposer acima da classe de seu TForm ou TDataModule, TODOS os TClientDataSet que você incluir no seu TForm ou TDataModule, serão do tipo TClientDataSet, mas não daquele contido na unit DBClient e sim daquele que você declarou dentro da sua unit. Esta parte é meio confusa de primeira mas vou tentar explicar.</p>\r\n<p style=\"text-align: justify;\">Suponha que você tem a \"unitA\", que declara a classe \"TA\" então em uma \"unitB\" você precisa criar uma instância da classe \"TA\". Você então inclui a \"unitA\" na cláusula uses e assim, em um local qualquer você pode criar sua classe \"TA\". Isso todo mundo sabe. Agora suponha que dentro do código, em qualquer ponto APÓS a cláusula uses que contém a \"unitA\" e antes da declaração da variável do tipo \"TA\" você declare novamente a classe \"TA\" da seguinte maneira:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>type\r\n TA = class(unitA.TA)\r\n protected\r\n { este método é original em TA e está sendo sobrescrito em sua Interposer! }\r\n procedure Metodo1; override;\r\n end;</code></pre>\r\n<p style=\"text-align: justify;\">Você cria uma classe que herda de TA, mas que tem o mesmo nome da classe pai, o que \"engana\" todas as declarações subsequentes de forma que tudo que for declarado após a declaração da Interposer será do tipo da Interposer, que é uma classe filha da classe original! No exemplo, Metodo1 está sendo sobrescrito e qualquer implementação no mesmo será executada quando Metodo1 for executado. Criar uma classe interposer é como criar um componente baseado em outro, mas sem as complicações de instalação. O inconveniente é que você tem de se certificar de que a declaração da Interposer encontra-se após a declaração da classe original, do contrário, nada funcionará.</p>\r\n<p style=\"text-align: justify;\">Bom, com isso eu concluo este (breve?) artigo sobre como comprimir o tráfego de dados entre cliente e servidor DataSnap usando UCL como compressor. Qualquer outra biblioteca poderia ter sido usada, incluindo ZLib. Optei pelo uso do UCL por ser menos conhecido (segurança/criptografia) e possuir taxas de compressão e velocidade comparáveis às do ZLib/Zip.</p>',0,99,'2012-10-03 13:23:14',24,'','2018-10-05 20:53:30',24,0,'0000-00-00 00:00:00','2012-10-03 13:23:14','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/datasnap\\/ID000071\\/FullArticle.png\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"article_layout\":\"\",\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_associations\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_page_title\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',63,9,'','',1,980,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(72,187,'Quem somos','quemsomos-art','<p style=\"text-align: justify;\">A <strong>Zetta-&#216;mnis Solu&#231;&#245;es Tecnol&#243;gicas</strong>&#160;&#233; uma empresa formada por profissionais especialistas em Delphi e PHP, todos com experi&#234;ncia m&#233;dia de pelo menos 5 anos no mercado, desenvolvendo as mais diversas solu&#231;&#245;es nestas linguagens. Nossa base de funcionamento &#233; a coopera&#231;&#227;o entre nossos profissionais, cada um deles sendo, portanto, dono de um peda&#231;o da empresa</p>\r\n<p style=\"text-align: justify;\">&#160;</p>\r\n<p style=\"text-align: justify;\">&#160;</p>','',1,86,'2012-10-07 00:49:30',24,'','2020-07-16 17:31:54',24,0,'0000-00-00 00:00:00','2012-10-07 00:49:30','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',35,1,'','',1,3138,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(73,188,'O que fazemos','oquefazemos','<p style=\"text-align: justify;\">A <strong>Zetta-&#216;mnis Solu&#231;&#245;es Tecnol&#243;gicas</strong> &#233; uma empresa de Tecnologia da Informa&#231;&#227;o que desenvolve sistemas customizados e&#160;padronizadas para os mais diversos segmentos de mercado</p>','',1,86,'2012-10-07 00:49:47',24,'','2020-07-16 17:33:16',24,0,'0000-00-00 00:00:00','2012-10-07 00:49:47','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_intro\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',9,2,'','',1,2999,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(74,189,'Nossa missão','nossamissao','<p style=\"text-align: justify;\">Nossa missão é desenvolver sistemas de informação e prestar serviços na área de T.I. para a comunidade, com excelência e perfeição, tornando-se assim, referência nacional e internacional no desenvolvimento de soluções tecnológicas.</p>','',1,86,'2012-10-07 00:50:36',24,'','2016-07-27 19:54:38',24,0,'0000-00-00 00:00:00','2012-10-07 00:50:36','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":\"\",\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":\"\",\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":\"\",\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_intro\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',4,3,'','',1,2874,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(78,201,'Como funciona o breadcrumb','entendendoobreadcrumb-art','<p style=\"text-align: justify;\">Há um bom tempo eu tentei fazer com que o breadcrumb funcionasse da forma como eu queria, mostrando o caminho correto (hierarquia) do recurso sendo exibido no momento de acordo com a categoria do mesmo, no entanto a informação exibida sempre era diferente da esperada e eu sempre me frustrei. Busquei em fóruns a solução, procurei até mesmo um módulo que apresentasse o que eu queria, mas não o achei. O que achei foram mais e mais pessoas com o mesmo problema que o meu, até que um dia finalmente eu descobri como resolver o problema do breadcrumb, na verdade não havia problema algum, apenas era um entendimento inadequado deste módulo, o qual vou explicar a seguir.</p>\r\n','\r\n<p style=\"text-align: justify;\">O grande segredo oculto no funcionamento dos breadcrumbs do Joomla é que eles, na verdade, seguem a hierarquia dos menus e não a hierarquia das categorias e isso confunde bastante porque normalmente fazemos os menus com seus itens associados a categorias de alguma forma.</p>\r\n<p style=\"text-align: justify;\">Para facilitar o entendimento, primeiramente esqueça as categorias. Entenda que categorias apenas categorizam o conteúdo do site e não hierarquizam as coisas. Categorias podem ser hierarquizadas apenas para organizá-las e facilitar sua localização ao categorizar um artigo, mas não servem para os breadcrumbs.</p>\r\n<p style=\"text-align: justify;\">Por exemplo, neste site, existem 4 menus, 1 no topo e mais 3 laterais (que nunca são vistos ao mesmo tempo), então é como se existissem 4 breadcrumbs, pois cada menu \"configura\" um breadcrumb. Eu notei isso melhor quando desativem a exibição do item \"home\" no breadcrumb, pois a exibição desse item confundia as coisas e dava a impressão que todos os 4 menus eram um só, por conta da correlação com as categorias, as quais normalmente estão TODAS em uma única hierarquia que contempla o site como um todo.</p>\r\n<p style=\"text-align: justify;\">Por falar em item home home, ele está associado SEMPRE ao item de menu definido como home no backend, INDEPENDENTEMENTE do menu onde ele se encontra, por isso, com o item home habilitado, acontecia de que ele apontava para um item de uma hierarquia, mas o restante do breadcrumb estava apontando para outra hierarquia. Havia uma falta de sincronia entre o que deveria ser exibido e o que estava de fato sendo exibido.</p>\r\n<p style=\"text-align: justify;\">Ainda usando esse site como exemplo, a solução foi criar um item raiz para cada um dos menus laterais e configurar a exibição para ocultar este item. Se ele vai ser ocultado, porque então criá-lo? Simples! Porque o breadcrumb exibe este item sempre, e isso é um efeito desejado. Para exemplificar, clique no item <a href=\"index.php/a2p-mei\">Addicted 2 PHP!</a> Esse item acessa o menu raiz criado. Siga então a hierarquia e note que, no breadcrumb, ele sempre aparece, dando uma indicação visual de onde estamos. Este artigo, por exemplo, está em \"<a href=\"index.php/a2p-mei\">Addicted 2 PHP!</a> \\ <a href=\"index.php/a2p-mei/articles-a2p-mei\">Artigos</a> \\ <a href=\"index.php/a2p-mei/articles-a2p-mei/joomla-articles-a2p-mei\" rel=\"alternate\">Joomla!</a>\", ou seja, ele é um artigo sobre o Joomla! de Addicted 2 PHP! e isso fica bem claro.</p>\r\n<p style=\"text-align: justify;\">O menu do topo, contém apenas aliases para os itens raiz de cada um dos menus da esquerda, portanto, quando eles são clicados, o breadcrumb é exibido de forma adequada. Toda a lógica de apresentação do breadcrumb, ou melhor, dos breadcrumbs, já que são 3, está concentrada nos 3 menus da esquerda</p>',1,110,'2012-10-16 01:56:57',24,'','2016-08-31 14:38:34',24,0,'0000-00-00 00:00:00','2016-07-21 01:56:00','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_intro\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',30,1,'','',1,2989,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(80,203,'Ordem de criação e execução de ApplyUpdates','ordemdeexecucaodeapplyupdates','<pre xml:lang=\"ASM\">; #line 2128\r\npush offset aError_message ; \"ERROR_MESSAGE\"\r\npush ebx ; lpString1\r\ncall lstrcpyA\r\n; #line 2129\r\nmov dword ptr [ebx+20h], 1\r\n; #line 2130\r\nmov dword ptr [ebx+28h], 0FFh\r\n; #line 2131\r\nadd ebx, 4Ch ; \'L\'</pre>\r\n<p> </p>\r\n<pre xml:lang=\"CPP\">// 2128\r\nLdStrCpy((pCHAR)pFldDes-&gt;szName, szdsERRMESSAGE);\r\n// 2129\r\npFldDes-&gt;iFldType = fldZSTRING;\r\n// 2130\r\npFldDes-&gt;iUnits1 = 255;\r\n// 2131\r\npFldDes++;</pre>\r\n<p>Boa tarde,</p>\r\n<div> </div>\r\n<div>Tenho uma estrutura com 4 dataset relacionadas da seguinte maneira:</div>\r\n<div> </div>\r\n<div>Mestre</div>\r\n<div>    Detalhe 1</div>\r\n<div>    Detalhe 2</div>\r\n<div>        SubDetalhe 2.1 - aqui tenho uma FK apontando pra um registro do Detalhe 1</div>\r\n<div> </div>\r\n<div>A ordem de inclusão dos registros nos datasets é Mestre, Detalhe 1, Detalhe 2, SubDetalhe 2.1.</div>\r\n<div> </div>\r\n<div>Entretanto, a ordem de gravação, quando executado o método ApplyUpdates, parece ser Mestre, Detalhe 2, SubDetalhe 2.1, Detalhe 1.</div>\r\n<div> </div>\r\n<div>Isso gera o erro \"Foreign key reference target does not exist\", pois existe uma FK em SubDetalhe 2.1 que aponta para um registro incluído no Detalhe 1.</div>\r\n<div> </div>\r\n<div>Tenho como interferir na ordem de gravação dos registros? Ou existe outra maneira de contornar essa problema?</div>\r\n<div> </div>\r\n<div>----------------------------</div>\r\n<div> </div>\r\n<div>\r\n<div>Clique com o direito no DTM... e escolha “Create Order”...</div>\r\n<div> </div>\r\ncheque se a ordem de criação dos DataSet estão corretas.</div>\r\n<div> </div>\r\n<div>----------------------------</div>\r\n<div> </div>\r\n<div>\r\n<p>Obrigado pela resposta Caique.</p>\r\n<div> </div>\r\n<div>Conferi a ordem de criação e a mesma está correta, seguindo a hierarquia que apresentei.</div>\r\n<div> </div>\r\n<div>Antes de dar o ApplyUpdates, verifiquei a ordem dos campos no dataset e está assim:</div>\r\n<div> </div>\r\n<div>Fields = Campo1, Campo2, Detalhe1, Detalhe2.</div>\r\n<div> </div>\r\n<div>FieldDefs = Campo1, Campo2, Detalhe2, Detalhe1.</div>\r\n<div> </div>\r\n<div>Ou seja, a propriedade FieldDefs possui a lista de campos na ordem incorreta que estão sendo gravados os dados. Alterei a ordem dos FieldDefs pelo Index, mas não mudou a ordem de gravação.</div>\r\n<div> </div>\r\n<div>------------------------</div>\r\n<div> </div>\r\n<div>\r\n<p>Boas novas!!!</p>\r\n<div> </div>\r\n<div>Após muitos testes e experimentações, usando vários DataSources (um para cada detalhe), descobri que a sugestão do Caique fazia sentido, só que em ordem inversa!</div>\r\n<div> </div>\r\n<div>Então defini a ordem de criação dos datasets no \"Create Order\" do DTM da seguinte maneira: Mestre, Detalhe 2, SubDetalhe 2.1, Detalhe 1.</div>\r\n<div> </div>\r\n<div>E a ordem de gravação seguiu a ordem inversa da criação, portanto a correta!</div>\r\n<div> </div>\r\n<div>Obrigado pela dica Caique.</div>\r\n</div>\r\n</div>','',0,80,'2012-11-14 13:50:23',24,'','2016-07-26 19:17:06',24,0,'0000-00-00 00:00:00','2012-11-14 13:50:23','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":\"\",\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":\"\",\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":\"\",\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_intro\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',6,81,'','',1,586,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(81,204,'Alteração de conexão em servidor DataSnap','alteracao-de-conexao-em-servidor-datasnap','<div class=\"gmail_extra\">Oi Fellipe<br /><br /></div>\r\n<div class=\"gmail_extra\">(desculpe, não li as outras respostas por preguiça mesmo. Se eu estiver perguntando besteira, por favor, dá um desconto. Quero ajudar, mas estava muito ocupado ultimamente...)</div>\r\n<div class=\"gmail_extra\">Você tem apenas um middleware (MW) e quer que vários clientes de empresas distintas acessem este middleware único, mas ao fazer isso estejam manipulando dados em bancos de dados específicos de acordo com cada um deles?</div>\r\n<div class=\"gmail_extra\">Qual a tecnologia de transporte do teu Server App, isto é, trocando em miúdos, qual o componente de conexão DataSnap (DS) você está usando nas aplicações cliente?<br /><br /></div>\r\n<div class=\"gmail_extra\">Se você estivesse usando SOAP (TSOAPConnection) e teu middleware fosse um Webservice (WS) eu poderia dizer com certeza, que cada conexão de cliente cria uma thread separada (modelo apartment) e sendo assim a solução que você mesmo apresentou, via login, seria perfeita, contudo, há um ponto que precisa ser definido: o teu login deveria ser feito em uma base única, igual para todos os clientes, e cada cliente deve ter o código da empresa associado.<br /> <br />O problema com isso é que ao menos o WS é stateless, tudo acontece por requisição/resposta, ou seja, ao fazer o login você requisita uma autenticação e a resposta é OK ou NÃO OK. E depois disso, conexões subsequentes não vão mais saber que houve outras conexões anteriormente. A solução pra isso vem naturalmente quando você compara uma aplicação DS a um site dinâmico da web, feito, digamos em PHP. Ao fazer login, todas as próximas requisições e respostas precisam saber que você \"está logado\", e isso é feito com o uso de sessões.</div>\r\n<div class=\"gmail_extra\">Minha solução para uso de sessões no DS foi implementada por meio de um arquivo que é atualizado no servidor toda vez que um usuário faz login ou logout. Se existe uma solução para uso de sessões já pronta eu não usei, por simples falta de conhecimento profundo do DS. Estou usando Delphi XE. Não sei se já existe uma solução via componente pra isso. No lugar do arquivo poderia ser um banco de dados embarcado, por exemplo, como o MySQL Embeded (que dispensa um servidor de banco e roda localmente), que é muito bom e poderoso. Só não usei um banco de dados justamente porque seria desperdício de poder.<br /> <br />Criei uma função específica para login e logout no WS. Ao fazer login bem sucedido, um arquivo, cujo formato eu mesmo defino é atualizado. Este arquivo contém uma lista de usuários autenticados. No teu caso seriam todos os usuários, de todas as empresas. Cada registro neste arquivo é composto por 3 campos básicos:<br /><ol>\r\n<li>SessionID: String - um GUID gerado por uma função específica</li>\r\n<li>SessionData: String - Informações do teu usuário conectado. Pode ser uma string JSON. Eu uso um DFM Object</li>\r\n<li>SessonLastModified: TDateTime - Data e hora da última alteração em SessionData. A data é alterada quando o usuário troca alguns de seus dados, como a senha ou e-mail. A data também serve como um marcador para invalidar a sessão após um determinado período de tempo, caso você queira implementar isso.</li>\r\n</ol>\r\n<p>O campo SessionData é onde você guarda as informações do teu cliente, da forma que você quiser, eu guardo as seguintes informações:</p>\r\n<ol>\r\n<li>IDUsuario: SmallInt - ID na tabela de usuários</li>\r\n<li>IDEmpresa: SmallInt - ID da empresa na qual o usuário trabalha</li>\r\n<li>Nome: String - óbvio</li>\r\n<li>Login: String -  óbvio</li>\r\n<li>Senha: String - Hash da senha do usuário. Eu uso SHA-1</li>\r\n<li>Email: String - óbvio</li>\r\n<li>Superusuario: Boolean - No meu caso indica que o usuário é um administrador para algumas funções DS, de forma que validações de permissão não sejam executadas.</li>\r\n</ol></div>\r\n<div class=\"gmail_extra\">Após o login, eu tenho então, dentro do arquivo de sessões no servidor um registro que identifica cada usuário logado e suas empresas, ao mesmo tempo que no cliente eu salvo em memória algumas informações sobre o login, a saber:</div>\r\n<ol>\r\n<li>SessionID: String - GUID retornado pela função de login</li>\r\n<li>SessionData: TSessionData - Objeto ou Record com as mesmas informações do campo SessionData citado anteriormente. No meu caso eu uso um DFM Object aqui, para facilitar minha vida, mas como eu disse antes, pode ser um JSON.</li>\r\n</ol>\r\n<div class=\"gmail_extra\">O que fazer com isso? No meu caso, como eu estou usando o arquivo de sessões para identificar o usuário e suas permissões dentro do sitema eu tive de redefinir (override) os seguintes métodos DS tanto no servidor como no cliente:<br /><ol>\r\n<li>function SAS_ApplyUpdates(const ProviderName: WideString; Delta: OleVariant; MaxErrors: Integer; out ErrorCount: Integer; var <strong>OwnerData</strong>: OleVariant): OleVariant; override; stdcall;</li>\r\n<li>procedure SAS_Execute(const ProviderName: WideString; const CommandText: WideString; var Params: OleVariant; var <strong>OwnerData</strong>: OleVariant); override; stdcall;</li>\r\n<li>function SAS_GetParams(const ProviderName: WideString; var <strong>OwnerData</strong>: OleVariant): OleVariant; override; stdcall;</li>\r\n<li>function SAS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer; Options: Integer; const CommandText: WideString; var Params: OleVariant; var <strong>OwnerData</strong>: OleVariant): OleVariant; override; stdcall;</li>\r\n<li>function SAS_RowRequest(const ProviderName: WideString; Row: OleVariant; RequestType: Integer; var <strong>OwnerData</strong>: OleVariant): OleVariant; override; stdcall;</li>\r\n</ol>\r\n<p>Estes métodos (SAS_) são métodos em WebServices. Se você estiver usando outra tecnologia, você vai ter exatamente os mesmos métodos, mas com o prefixo \"AS_\" apenas, porém com a mesma assinatura. Note que todos eles tem um parâmetro chamado OwnerData.</p>\r\n<p>(Apartir deste ponto a técnica descrita não foi testada, cabe a você tentar e ver se dá certo, ok?)</p>\r\n<p>O problema de conectar a um banco diferente daquele definido em designtime ou no momento da criação do TRemoteDataModule, reside no fato de que no DS a conexão com o banco é iniciada sempre a partir de uma ação de Inserção, Atualização, Exclusão ou Seleção de dados, isto é:</p>\r\n<ol>\r\n<li>Você solicita uma consulta na tabela X no clinete</li>\r\n<li>A requisição é enviada ao MW</li>\r\n<li>O MW cria automaticamente a conexão com o banco de dados com as informações de conexão definidas em designtime ou arquivo de configuração externo</li>\r\n<li>O select que você solicitou no cliente é finalmente executado e a resposta é enviada de volta</li>\r\n<li>O cliente exibe o resultado da consulta</li>\r\n<li>A conexão com o MW é finalizada e neste momento o MW fecha a conexão com o BD</li>\r\n</ol></div>\r\n<div class=\"gmail_extra\">Como se pode ver não há um comando explicito para conectar ao banco de dados. O MW realiza a conexão porque houve uma requisição de consulta, de acordo com o exemplo, por isso o que tem de ser feito é forçar uma desconexão/reconfiguração/reconexão do banco de dados a partir da solicitação realizada. Usando o mesmo exemplo de consulta, é sabido que uma consulta no cliente executa o método SAS_GetRecords (AS_GetRecords) no servidor e sendo assim precisamos sobrescrever estes métodos tanto no cliente como no servidor (MW).<br /> <br />Note que os métodos \"AS\" tem um parâmetro comum OwnerData do tipo OleVariant. Este parâmetro coringa serve para várias coisas e eu estou usando ele para passagem de dados de sessão. No cliente, nós devemos sobrescrever os métodos AS e codificar em OwnerData apenas o SessionID.</div>\r\n<div class=\"gmail_extra\">No cliente os métodos \"AS\" tem ligação direta com eventos de TClientDataSet. No nosso exemplo, o método AS_GetRecords, gera eventos OnBeforeGetRecords, OnGetRecords e OnAfterGetRecords. Precisamos então criar um manipulador de evento apenas para o OnBeforeGetRecords, pois precisamos enviar dados ao MW antes de qualquer coisa. No meu caso eu criei uma classe interposer para o TClientDataSet e por isso eu sobrescrevi o método DoBeforeGetRecords, o qual é executado sempre imediatamente antes de uma requisição de consulta (AS_GetRecords). Ficaria mais ou menos assim:<br /> <br />procedure TClientDataSet.DoBeforeGetRecords(var OwnerData: OleVariant);<br />begin<br />  OwnerData := SessionID;<br />  inherited;<br />end;<br /><br /></div>\r\n<div class=\"gmail_extra\">Isso é suficiente para enviar ao servidor a identificação de nossa sessão. No servidor, devemos então sobrescrever o método AS_GetRecords assim:<br /> <br />function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer; Options: Integer; const CommandText: WideString; var Params, OwnerData: OleVariant): OleVariant;<br />begin<br />  if SessionExists(OwnerData) then<br />   begin<br />    DBConnectBySession(OwnerData);<br /><br />    Result := inherited;<br />  end<br />  else<br />    raise Exception.Create(\'Para usar este método é necessário que você seja um usuário autenticado no sistema\');<br /> end;<br /><br /></div>\r\n<div class=\"gmail_extra\">Explicando...<br /><br /></div>\r\n<div class=\"gmail_extra\">Caso uma sessão identificada pelo SessionID codificado em OwnerData existir então eu devo executar um métodos chamado DBConnectBySession e somente em seguida realizar o restante da ação que é simplesmente executar novamente AS_GetRecords. Caso uma sessão identificada pelo SessionID codificado em OwnerData NÃO existir. Eu levanto uma exceção pois a ação não é autorizada para usuários não autenticados.</div>\r\n<div class=\"gmail_extra\">O método DBConnectBySession não existe, você preicisa criá-lo, mas acho que isso é bem simples. Tudo que você precisa fazer é buscar o SessionID no arquivo local de sessões e obter no final o ID da empresa a partir dele. De posse do ID da empresa você realiza a desconexão do banco de dados, depois reconfigura ele, e conecta novamente. O importante é que ao chegar na linha que diz \"Result := inherited;\" você tenha efetivamente uma conexão com um banco de dados.</div>\r\n<div class=\"gmail_extra\">Esta mesma alteração deve ser realizada para os outros quatro métodos AS da mesma forma!<br /><br /></div>\r\n<p><em><strong>É isso. Espero que tenha ajudado em algo, apesar de que a tentativa de solucionar teu problema não foi testada por mim, mas se funcionar vai ser realmente uma mão na roda. Se não funcionar, ao menos vou saber que algumas pessoas puderam aprender algo, e isso é o que importa. Funcionando ou não, deixa a gente saber. Se tiver alguma dúvida, pergunta.</strong></em></p>','',0,99,'2013-02-27 18:01:05',24,'','2016-07-27 12:53:10',24,0,'0000-00-00 00:00:00','2013-02-27 18:01:05','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":\"\",\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":\"\",\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":\"\",\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_intro\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',3,8,'','',1,180,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(89,220,'10 razões para ser um desenvolvedor Delphi','10-razoes-para-ser-um-desenvolvedor-delphi','<p style=\"text-align: justify;\">Hoje li um artigo muito interessante que enumerava 10 raz&#245;es para ser um desenvolvedor Delphi. Resolvi ent&#227;o tomar a liberdade de traduzi-lo. O texto &#233; relativamente simpl&#243;rio, mas ele &#233; destinado aos iniciantes da programa&#231;&#227;o. Tomei a liberdade de incluir algumas coisas que faltavam e comentar algo que achei curioso, ou seja, esta &#233; uma tradu&#231;&#227;o livre e despretensiosa. Considere-a como uma \"vers&#227;o brasileira, eu mesmo!\" :)</p>\r\n','\r\n<p style=\"text-align: justify;\">Segue abaixo minha tradu&#231;&#227;o/vers&#227;o do texto original dispon&#237;vel em <a href=\"http://delphi.org/2016/07/top-10-reasons-to-be-a-delphi-developer/\">http://delphi.org/2016/07/top-10-reasons-to-be-a-delphi-developer/</a>. Como se trata de uma vers&#227;o, n&#227;o existe uma tradu&#231;&#227;o ao p&#233; da letra, mas sim uma interpreta&#231;&#227;o daquilo que o autor original escreveu. Esta interpreta&#231;&#227;o, contudo, n&#227;o alterou em nada o sentido do texto, mas facilitar&#225; bastante sua leitura.</p>\r\n<hr style=\"width: 100%;\" width=\"100%\" />\r\n<p style=\"text-align: justify;\">O trabalho de desenvolvedor de softwares &#233; muito interessante. Voc&#234; aprende uma linguagem de programa&#231;&#227;o para desenvolver um grande variedade de softwares e assim \"digitalizar o mundo\", mas enquanto faz isso, voc&#234; &#224;s vezes enfrenta situa&#231;&#245;es onde pequenos erros tiram seu sono por muitos dias e noites. A melhor parte dessa experi&#234;ncia &#233; quando voc&#234; finalmente encontra a solu&#231;&#227;o e d&#225; um tapa em si mesmo, com um sorriso no rosto, dizendo \"Meu Deus! Foi este probleminha que me tirou o sono?\". Isso pode acontecer com qualquer desenvolvedor de softwares, mas o resultado final &#233; sempre gratificante, e &#233; por isso que o desenvolvimento de softwares &#233; um trabalho que est&#225; agradando mais e mais jovens ao redor do mundo.</p>\r\n<p style=\"text-align: justify;\">Dependendo das linguagens de programa&#231;&#227;o que voc&#234; estudou e implementou, as chances de ficar travado em um pequeno problema pode variar. A utiliza&#231;&#227;o de uma linguagem complexa pode tirar seu sono muitas vezes durante o desenvolvimento de um software, por outro lado, a utiliza&#231;&#227;o de uma linguagem de programa&#231;&#227;o com uma sintaxe simples de escrever e recursos realmente &#250;teis pode transformar sua vida de desenvolvedor em uma vida que todos adorariam ter. A Linguagem Delphi (Object Pascal) &#233; este tipo de linguagem de programa&#231;&#227;o, largamente conhecida por ser uma das linguagens de sintaxe mais simples de escrever.</p>\r\n<p style=\"text-align: justify;\">Se voc&#234; pretende ser um desenvolvedor de softwares voc&#234; pode n&#227;o querer come&#231;ar com uma linguagem dif&#237;cil, que ponha seu moral pra baixo. Ent&#227;o, a fim de manter a sua paix&#227;o em ser um desenvolvedor no mais alto grau de entusiasmo, come&#231;ar com a Linguagem Delphi ser&#225; uma op&#231;&#227;o sem igual. Come&#231;ando sua carreira como um Desenvolvedor Delphi traz para voc&#234; muitos benef&#237;cios. Vejamos agora algumas das principais raz&#245;es que far&#227;o voc&#234; entender porque voc&#234; deve ser um Desenvolvedor Delphi:</p>\r\n<ol type=\"I\">\r\n<li>A Linguagem Delphi &#233; uma combina&#231;&#227;o de linguagem de programa&#231;&#227;o e SDK, o que permite o desenvolvimento de de aplica&#231;&#245;es para desktop, dispositivos m&#243;veis, <a title=\"Eu n&#227;o tenho conhecimento sobre a possibilidade de desenvolvimento para consoles usando o Delphi. Eu j&#225; vi, sim, ports de Doom e Quake 100% desenvolvidos em Delphi Language e que ficaram simplesmente perfeitos. Em conversa com outro especialista o mesmo me disse que isso pode ser poss&#237;vel, considerando que o XBOX One usa o Windows 10 como OS, e sendo assim, o Delphi de fato conseguiria desenvolver para consoles Microsoft\" href=\"#\" rel=\"bookmark\">consoles</a>&#160;e web;</li>\r\n<li>A Linguagem Delphi &#233; uma linguagem de programa&#231;&#227;o simples e com sintaxe limpa;</li>\r\n<li>C&#243;digo escrito em Delphi &#233; facilmente leg&#237;vel, por exemplo, voc&#234; pode concatenar strings usando o caractere \"+\" ao inv&#233;s de usar uma fun&#231;&#227;o para isso;</li>\r\n<li>A documenta&#231;&#227;o do Delphi &#233; bem organizada para ajud&#225;-lo a iniciar rapidamente;</li>\r\n<li>Vem com uma IDE que lhe permite desenvolver facilmente uma GUI usando arrastar &amp; soltar, adicionando manipuladores de eventos e muitas outras caracter&#237;sticas realmente &#250;teis;</li>\r\n<li>Suporta teste em tempo real (debug), tornando muito mais simples e r&#225;pido encontrar e corrigir problemas;</li>\r\n<li>Suporta o Desenvolvimento R&#225;pido de Aplica&#231;&#245;es --&#160;Rapid Application Development (RAD) -- com caracter&#237;sticas tais como, o framework de aplica&#231;&#227;o e o designer de layout de&#160;janelas totalmente visual (WYSIWYG);</li>\r\n<li>Suporta arquitetura cliente-servidor, arquitetura n-tier (DataSnap) e bancos de dados SQL;</li>\r\n<li>Suporta a API do Windows 100%;</li>\r\n<li>Permite a cria&#231;&#227;o de componentes que s&#227;o facilmente integr&#225;veis na IDE.</li>\r\n</ol>',1,80,'2016-07-22 14:15:16',24,'','2020-12-12 19:49:09',24,0,'0000-00-00 00:00:00','2016-07-22 14:15:16','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/zost\\/ourproducts\\/delphi\\/Delphi.png\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','',29,80,'Delphi, Addicted 2 Delphi, Desenvolver, Razões','Hoje li um artigo muito interessante que enumerava 10 razões para ser um desenvolvedor Delphi. Resolvi então tomar a liberdade de traduzi-lo. O texto é relativamente simplório, mas ele é destinado aos iniciantes da programação. Tomei a liberdade de incluir algumas coisas que faltavam e comentar algo que achei curioso, ou seja, esta é uma tradução livre e despretensiosa. Considere-a como uma \"versão brasileira, eu mesmo!\" :)',1,5151,'',1,'*','',''),(90,222,'A verdade sobre o TDataModule e o consumo de memória','a-verdade-sobre-o-tdatamodule-e-o-consumo-de-memoria','<p style=\"text-align: justify;\">Há algumas semanas tomei conhecimento de pelo menos duas publicações que estavam falando a respeito do TDataModule, acusando-o de ser um voraz consumidor de memória dentro das aplicações. Como tenho costume de usá-lo de todas as formas possíveis em meus projetos, fiquei curioso para saber como este, que é simplesmente um contêiner não visual, poderia consumir tanta memória como era dito. Depois de ler argumentações rasas e pseudo verdades eu resolvi pôr a mão na massa para tentar descobrir se o TDataModule realmente era tão mau assim.</p>\r\n','\r\n<p style=\"text-align: justify;\">Muito se fala e pouco se aprofunda, por isso tomei as dores do pobre TDataModule e, a fim de provar sua inocência, comecei verificando sua hierarquia, e notei que o TDataModule tem menos \"pais\" do que o TForm. Estou usando o TForm como exemplo porque, primariamente e da forma mais básica possível, um TDataModule é um contêiner de componentes não visuais e um TForm também aceita componentes não visuais e por isso um programa pode muito bem ser criado sem que haja sequer um TDataModule, contudo, TDataModules ajudam a modularizar um programa e, usando-o da forma mais básica, é possível manter as coisas organizadas, concentrando seus componentes não visuais em um TDataModule e evitando que um tela complexa (e com muitos componentes não visuais) fique poluída. A quantidade de hierarquias é sim um fator crucial para a contabilização do consumo de memória, e se um TDataModule tem menos hierarquias do que um TForm, as chances dele consumir menos memória do que este último é bem elevada. Achei isso muito curioso e fui investigar mais a fundo</p>\r\n<p style=\"text-align: justify;\">Algumas pessoas vão dizer que tudo pode ser criado dinamicamente e não é preciso ter quaisquer componentes não visuais em designtime, seja em forms, seja em data modules, mas entenda que o intuito desse artigo é mostrar a verdade sobre o TDataModule ser ou não um consumidor de memória. Além disso, iniciantes não vão jamais criar componentes em tempo de execução. É muito mais fácil soltar um TQuery num TForm (ou TDataModule) do que lidar com construtores, destrutores e atribuição programática de propriedades. <strong>Este texto é destinado aos iniciantes</strong>, para que eles não acreditem em tudo que lêem e usem os componentes da melhor forma possível, até que um dia resolvam \"complicar\", criando tudo em runtime, que trás poucas vantagens, diga-se. Minha opinião é de que se eu posso fazer as coisas de forma visual, eu vou fazer de forma visual porque isso facilita minha vida. Não existe um concurso secreto que dá prêmios em dinheiro pra programadores que fazem tudo de forma linda, OO ou sem gambiarras! Aliás, aquele que nunca fez uma gambiarra que atire o primeiro teclado :)</p>\r\n<h2>Sim, mas e o tamanho do TDataModule?</h2>\r\n<p style=\"text-align: justify;\">Colocar um TDataModule numa aplicação aumenta seu consumo de memória? Claro que aumenta! Tudo que é incluído numa aplicação, seja em designtime, seja em runtime, impacta no consumo final de memória. O que quero comprovar aqui é que, colocar um TDataModule em uma aplicação não é diferente de incluir um TForm, por exemplo. O consumo de memória de um TForm e de um TDataModule é similiar, o que significa que uma aplicação com um TForm e um TDataModule é maior do que uma aplicação com apenas um TForm, mas usar um TDataModule para organizar o código e concentrar componentes não visuais COMPENSA este leve aumento.</p>\r\n<p style=\"text-align: justify;\">Como foi que cheguei a esta conclusão a respeito do tamanho do TDataModule? Simples! Criei um projeto (que está anexado a esta publicação) que faz medições de consumo de memória antes e após a criação/destruição de diversos objetos. Baixe o projeto e execute-o. Ele é guiado passo-a-passo. Tire suas próprias conclusões</p>\r\n<h2>E daí?</h2>\r\n<p style=\"text-align: justify;\">E daí que, da próxima vez que alguém disser que a culpa é do TDataModule, você poderá dar o link deste artigo e esperar que a pessoa não seja muito cabeça dura pra entender de uma vez por todas que, normalmente, a culpa do consumo de memória desenfreado é de componentes de terceiros ou programação inadequada. Obrigado por ler :)</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-07-25 20:11:09',24,'','2020-06-26 17:22:15',24,0,'0000-00-00 00:00:00','2016-07-25 20:11:09','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000090\\/FullArticle.png\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','',15,79,'Delphi, Addicted 2 Delphi, Performance, TDataModule, DataModule, Memória, Consumo','Há algumas semanas tomei conhecimento de pelo menos duas publicações que estavam falando a respeito do TDataModule, acusando-o de ser um voraz consumidor de memória dentro das aplicações. Como tenho costume de usá-lo de todas as formas possíveis em meus projetos, fiquei curioso para saber como este, que é simplesmente um contêiner não visual, poderia consumir tanta memória como era dito. Depois de ler argumentações rasas e pseudo verdades eu resolvi pôr a mão na massa para tentar descobrir se o TDataModule realmente era tão mau assim.',1,6157,'',1,'*','',''),(91,224,'Avaliação booleana em modo \"curto-circuito\" e operandos do tipo Variant','avaliacao-booleana-em-modo-curto-circuito-nao-funciona-com-operandos-do-tipo-variant','<p style=\"text-align: justify;\">Você sabia que o modo curto-circuito de avaliação boolena não funciona bem com operandos do tipo Variant? Pois é, eu também não sabia. E isso estava acabando com minha lógica. Neste rápido artigo vou mostrar um exemplo de como isso pode atrapalhar toda a sua lógica, caso você não esteja ciente deste \"pequeno\" detalhe. </p>\r\n','\r\n<p style=\"text-align: justify;\">O modo curto-circuito de avaliação boolena é a forma padrão de avaliação lógica de todas as linguagens de programação. Basicamente o curto-circuito é um conceito que prega que uma expressão booleana complexa seja avaliada o mais rapidamente possível pelo compilador mediante o descarte de avaliações adicionais que são óbvias ou nulas dentro da referida expressão.</p>\r\n<p style=\"text-align: justify;\">Se ainda assim não consegue entender o que é uma avaliação boolean em curto-circuito, dê uma olhada em <a href=\"http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/compdirsbooleanshortcircuitevaluation_xml.html\">Boolean short-circuit evaluation (Delphi compiler directive)</a> e saiba que mesmo sem você saber da existência disso, provavelmente você usa, pois o curto-circuito é padrão do Delphi.</p>\r\n<p style=\"text-align: justify;\">Chega de bla bla bla. Tenho a seguinte função:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function CanSelect(const aTableName: String): Boolean;\r\nbegin\r\n Result := CurrentSession.Data.bo_superusuario \r\n or CLDSPermissoes.Lookup(\'ENTIDADE\',aTableName,\'LER\');\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">A lógica é simples: A função vai retornar TRUE se eu for um superusuário ou se eu tiver permissão de leitura para a tabela passada no parâmetro aTableName.</p>\r\n<p style=\"text-align: justify;\">Como a diretiva de compilação <strong>{$B-}</strong> está ativada como padrão, a lógica diz que se CurrentSession.Data.bo_superusuario for TRUE, o segundo operando nem mesmo vai ser avaliado pois apenas a condição do primeiro operando já é suficiente para saber o resultado da expressão booleana inteira. O que estava acontecendo é que o segundo operando, neste caso, estava sendo avaliado, mesmo quando o primeiro era TRUE, que, no meu caso gerava um exceção por conta de CLDSPermissoes estar inativo.</p>\r\n<p style=\"text-align: justify;\">Após algumas pesquisas atentei para o fato do segundo operando (Lookup) retornar um dado Variant e por este motivo o compilador não tem condições de saber se ele é realmente um booleano ou não, causando a avaliação completa da expressão booleana mesmo no modo <strong>{$B-}</strong>. Ao meu ver isso é algum tipo de bug relacionado ao modo <strong>{$B-}</strong> o qual deveria \"curtocircuitar\" a expressão APENAS após a conversão do dado Variant, mas isso é outro assunto.</p>\r\n<p style=\"text-align: justify;\">Após descobrir a causa do problema que impactava na minha lógica, foi simples resolver o problema. Simplesmente dei um cast no variant para Boolean, explicitando para o compilador que se trata de um operando BOOLEANO, assim:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function CanSelect(const aTableName: String): Boolean;\r\nbegin\r\n Result := CurrentSession.Data.bo_superusuario \r\n or Boolean(CLDSPermissoes.Lookup(\'ENTIDADE\',aTableName,\'LER\'));\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Desta forma a lógica funciona como deve. Fica a dica!</p>',1,80,'2016-07-25 20:52:54',24,'','2016-11-18 14:12:18',24,0,'0000-00-00 00:00:00','2016-07-25 20:52:54','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"right\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000091\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','',26,78,'Delphi, Addicted 2 Delphi!, Variant, Short Circuit, Boolean, Lógica Booleana, Avaliação Booleana','Você sabia que o modo curto-circuito de avaliação boolena não funciona bem com operandos do tipo Variant? Pois é, eu também não sabia. E isso estava acabando com minha lógica. Neste rápido artigo vou mostrar um exemplo de como isso pode atrapalhar toda a sua lógica, caso você não esteja ciente deste \"pequeno\" detalhe. ',1,4428,'',1,'*','',''),(92,225,'Como obter a real diferença entre dois valores TDateTime','como-obter-a-real-diferenca-entre-dois-valores-tdatetime','<p style=\"text-align: justify;\">Nas minhas andanças pela web, descobri que a unit DateUtils, continha vários problemas de arredondamento e que sua precisão era muito pobre. Descobri também que existia uma proposta no site da Embarcadero (Quality Central) para mudanças nesta unit de forma que ela seja tão precisa quanto um milissegundo. Hoje este problema de precisão não existe mais, no entanto ainda é válida a técnica usada para criação de uma função que obtém precisamente (1 milissegundo) a diferença entre duas datas passadas por parâmetro. O resultado é um record com anos, semanas, dias, horas, minutos, segundos e milissegundos que corresponde à diferença de datas completa! Existem por aí inúmeros algoritmos que realizam tal tarefa, mas não com esta precisão e não com esta velocidade ;)</p>\r\n','\r\n<p style=\"text-align: justify;\">Quem estiver interessado na proposta sobre mudança da VCL, é só dar uma olhada em <a href=\"http://qc.embarcadero.com/wc/qcmain.aspx?d=56957\">Report #56957 - A Fix for DateUtils Date-Time Compare Functions</a>. Eu não sei se esta página ainda está ativa, mas se não estiver, faça uma busca pelo seu título. Se você tiver sorte, achará o texto em algum outro local.</p>\r\n<h2 style=\"text-align: center;\">Datas e Pontos Flutuantes </h2>\r\n<p style=\"text-align: justify;\">Como se sabe, as datas no Delphi (TDate, TDateTime e TTime) são armazenadas como números do tipo extended, de ponto flutuante. Sabe-se também que números de ponto flutuante não tem uma precisão muito boa. Comparações e operações matemáticas com tais números causam erros de arredondamento que não são percebidos até que se precise manipular casas decimais com mais precisão, fato que acontece quando tentamos obter valores muito pequenos a partir de datas, como milissegundos. É neste ponto onde a leitura deste artigo pode ajudar você.</p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">Primeiramente quero salientar <span style=\"font-size: 12pt;\">que</span> existem inúmeros outros algoritmos que fazem o mesmo e que até retornam a quantidade de meses, mas estejam avisados; a quantidade de meses exatos entre duas datas não pode ser conseguida de forma direta, apenas usando mais um loop, o que deixaria a função mais lenta. Deixei propositalmente a quantidade de meses de fora para que o leitor tente implementar.</p>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">Antes de começar preciso dizer que não vou simplesmente colar aqui a solução, pretendo explicar de forma didática, e estou subentendendo que o leitor já possui conhecimento básico da linguagem Delphi, bem como termos desta linguagem. Estejam avisados. O que vem a seguir é um caminho com lacunas faltando. Não espere copiar, colar e compilar sem erros. Sem mais delongas, lá vamos nós....</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: center;\">As mudanças propostas para a VCL</h2>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">Infelizmente não lembro em qual Delphi a VCL foi corrigida, por isso não tenho como dizer com certeza se você vai ou não precisar utilizar as funções apresentadas aqui ou aquelas que VCL já dispõe. O exemplo de uso no final deste artigo demostra esta função para que ela retorne exatamente 1 milissegundo. Caso ao executar a função o valor retornado não seja 1 milissegundo, provavelmente seu Delphi não possui a VCL corrigida e assim será necessário usar as funções que estão aqui. Esta seção só será útil, portanto, caso seu Delphi ainda não tenha sido corrigido.</p>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">Precisamos criar duas funções para o cálculo preciso de milissegundos entre duas datas. Estas funções foram extraídas e modificadas a partir da proposta de alteração da unit DateUtils explicada anteriormente. O crédito por estas funções deve ser dado a John Herbster , que propôs as mudanças na unit DateUtils (<a href=\"http://qc.embarcadero.com/wc/qcmain.aspx?d=56957\">Report #56957 - A Fix for DateUtils Date-Time Compare Functions</a>). Os comentários originais, em inglês, foram preservados.</p>\r\n<pre class=\"line-numbers language-pascal\"><code>{ Converts a TDateTime variable to Int64 milliseconds from 0001-01-01.}\r\nfunction DateTimeToMilliseconds(aDateTime: TDateTime): Int64;\r\nvar\r\n TimeStamp: TTimeStamp;\r\nbegin\r\n { Call DateTimeToTimeStamp to convert DateTime to TimeStamp: }\r\n TimeStamp := DateTimeToTimeStamp(aDateTime);\r\n { Multiply and add to complete the conversion: }\r\n Result := Int64(TimeStamp.Date) * MSecsPerDay + TimeStamp.Time;\r\nend;\r\n\r\n{ Uses DateTimeToTimeStamp, TimeStampToMilliseconds, and DateTimeToMilliseconds. }\r\nfunction MillisecondsBetween(const aNow, aThen: TDateTime): Int64;\r\nbegin\r\n if aNow &gt; aThen then\r\n Result := DateTimeToMilliseconds(aNow) - DateTimeToMilliseconds(aThen)\r\n else\r\n Result := DateTimeToMilliseconds(aThen) - DateTimeToMilliseconds(aNow);\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">A unit DateUtils também possui uma função de nome MillisecondsBetween no entanto esta função não é tão precisa como parece. A experiência mostra que ao criar dois valores TDateTime usando a função EncodeDateTime e que distam entre si apenas 1 milissegundo, o retorno da função MillisecondsBetween não retorna 1, como era de se esperar, provando que ela não é precisa.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: center;\">Apresentando a função DecodeDateDiff</h2>\r\n<p style=\"text-align: justify;\">Primeiramente devemos declarar o tipo do resultado. Um record, com todas as variáveis retornáveis.</p>\r\n<pre class=\"line-numbers language-pascal\"><code>type\r\n TDecodedDateDiff = record\r\n Years: Word;\r\n Weeks: Byte;\r\n Days: Word;\r\n Hours: Byte;\r\n Minutes: Byte;\r\n Seconds: Byte;\r\n Milliseconds: Word;\r\n end;</code></pre>\r\n<p style=\"text-align: justify;\">Agora vamos à função que faz todo o trabalho. Comentários internos dão as dicas do que está sendo feito. Quero salientar que esta função foi criada há cerca de 10 anos e que provavelmente hoje em dia devem haver formas mais eficientes de se obter o mesmo resultado.</p>\r\n<pre class=\"language-pascal\"><code>function DecodeDateDiff(aStartDateTime, aFinishDateTime: TDateTime): TDecodedDateDiff;\r\nvar\r\n MilliSeconds: Int64;\r\n WholeStartDate, WholeEndDate: TDateTime;\r\n Days: Cardinal;\r\n Years: Word;\r\nbegin\r\n { Validando as datas, que devem ser passadas corretamente para função, isto é,\r\n a data final tem de ser maior ou igual à data inicial. Qualquer outro caso é\r\n inválido e lança a exceção }\r\n if aStartDateTime &gt;= aFinishDateTime then\r\n raise Exception.Create(\'A data final é menor que a data inicial\');\r\n\r\n { Zerando as variáveis que serão usadas no decorrer da função }\r\n ZeroMemory(@Result,SizeOf(TDecodedDateDiff));\r\n Years := 0;\r\n\r\n { Obtendo a quantidade exata de millissegundos entre as datas }\r\n MilliSeconds := MilliSecondsBetween(aStartDateTime,aFinishDateTime);\r\n\r\n { A partir da quantidade exata de millissegundos, podemos obter a quantidade\r\n exata de dias, já que sabemos quantos millissegundos hão exatamente em um dia }\r\n Days := MilliSeconds div MSecsPerDay;\r\n\r\n { Abaixo estamos normalizando as datas, de forma que a data inicial começe\r\n exatamente no início do ano subsequente a ela, e a data final termine\r\n exatamente no final do ano anterior a ela }\r\n WholeStartDate := IncMilliSecond(EndOfTheYear(aStartDateTime));\r\n WholeEndDate := IncMilliSecond(StartOfTheYear(aFinishDateTime),-1);\r\n\r\n { O loop abaixo vai realizar duas ações: Decrementar a quantidade de dias\r\n obtida anteriormente da quantidade de dias no ano sendo verificado no momento\r\n e incrementar a variável Years, de forma a obter a quantidade de anos. }\r\n while WholeStartDate &lt; WholeEndDate do\r\n begin\r\n Dec(Days,DaysInYear(WholeStartDate));\r\n\r\n Inc(Years);\r\n\r\n WholeStartDate := IncDay(WholeStartDate,DaysInYear(WholeStartDate));\r\n end;\r\n\r\n { Caso a quantidade de dias seja maior ou igual a quantidade de dias no ano\r\n final, precisamos realizar um último ajuste para incrementar anos e\r\n decrementar dias de acordo com a quantidade de dias no ano da data final }\r\n if Days &gt;= DaysInYear(aFinishDateTime) then\r\n begin\r\n Inc(Years);\r\n Dec(Days,DaysInYear(aFinishDateTime));\r\n end;\r\n\r\n { Neste ponto, a variável Years contém a quantidade de anos inteiros entre as\r\n datas inicial final ... }\r\n\r\n Result.Years := Years;\r\n\r\n { ... E a variável Days contém a quantidade de dias que sobraram. Obtemos\r\n portanto a quantidade de semanas, que é um valor exato }\r\n\r\n Result.Weeks := Days div 7;\r\n Result.Days := Days mod 7;\r\n\r\n { A partir daqui a verificação é simples matemática, extraindo horas, minutos\r\n e segundos dos millisegundos }\r\n MilliSeconds := MilliSeconds mod MSecsPerDay;\r\n\r\n Result.Hours := MilliSeconds div (SecsPerHour * MSecsPerSec);\r\n MilliSeconds := MilliSeconds mod (SecsPerHour * MSecsPerSec);\r\n\r\n Result.Minutes := MilliSeconds div (SecsPerMin * MSecsPerSec);\r\n MilliSeconds := MilliSeconds mod (SecsPerMin * MSecsPerSec);\r\n\r\n Result.Seconds := MilliSeconds div MSecsPerSec;\r\n MilliSeconds := MilliSeconds mod MSecsPerSec;\r\n\r\n { O que sobrar no final, será apenas milissegundos! }\r\n Result.Milliseconds := MilliSeconds;\r\nend;</code></pre>\r\n<h2 style=\"text-align: justify;\">Um exemplo de uso</h2>\r\n<pre class=\"language-apacheconf\"><code>var\r\n Data1, Data2: TDateTime;\r\n Diferenca: TDecodedDateDiff;\r\nbegin\r\n data1 := EncodeDateTime(2017,12,13,0,0,0,0);\r\n data2 := EncodeDateTime(2017,12,13,0,0,0,1);\r\n Diferenca := DecodeDateDiff(data1,data2);\r\n // Todos os membros de \"Diferenca\" devem ser zero, exceto o membro \"Milliseconds\"\r\n // que deve possuir o valor 1\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">É isso! Agora você pode obter um intervalo entre duas datas com precisão de milissegundos! Se você quiser modificar o algoritmo, sinta-se a vontade, mas compartilhe com todos (como eu fiz).</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-07-26 02:01:09',24,'','2020-07-10 20:41:49',24,0,'0000-00-00 00:00:00','2017-08-24 03:00:00','0000-00-00 00:00:00','{\"image_intro\":\"\",\"float_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000092\\/FullArticle.png\",\"float_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"article_layout\":\"\",\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_associations\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_page_title\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',20,77,'Delphi, Addicted 2 Delphi, Milissegundos, Precisão, Diferença, Comparação, Datas, TDateTime, Milliseconds, Precision, Diff, Comparing, Dates','Nas minhas andanças pela web, descobri que a unit DateUtils, continha vários problemas de arredondamento e que sua precisão era muito pobre. Descobri também que existia uma proposta no site da Embarcadero (Quality Central) para mudanças nesta unit de forma que ela seja tão precisa quanto um milissegundo. Hoje este problema de precisão não existe mais, no entanto ainda é válida a técnica usada para criação de uma função que obtém precisamente (1 milissegundo) a diferença entre duas datas passadas por parâmetro. O resultado é um record com anos, semanas, dias, horas, minutos, segundos e milissegundos que corresponde à diferença de datas completa! Existem por aí inúmeros algoritmos que realizam tal tarefa, mas não com esta precisão e não com esta velocidade ;)',1,5668,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(93,226,'Corrigindo mensagens de erro EReconcileError truncadas','corrigindo-mensagens-de-erro-ereconcileerror-truncadas','<p style=\"text-align: justify;\">Uma das primeiras coisas que se aprende ao começar a desenvolver em 3 camadas é como manipular mensagens de erro que são geradas pelo servidor de aplicações (middleware). O tipo destas mensagens de erro é <strong>EReconcileError</strong> e toda vez que há algum problema no middleware, o mesmo envia este erro de volta ao cliente que o gerou. Tudo funciona perfeitamente a não ser por um detalhe que só foi percebido por mim quando as mensagens de erro começaram a vir mais detalhadas do servidor. Mais texto era retornado e eu notei que esse texto vinha truncado em exatos 255 caracteres. Por que isso ocorre e como corrigir, é o que pretendo explicar neste artigo.</p>\r\n','\r\n<p style=\"text-align: justify;\">As mensagens de erro de conciliação (Reconcile Error) são enviadas ao cliente sempre que há algum problema na persistência dos dados no middleware. O cliente, por sua vez, captura e é capaz de manipular estes erros no evento <strong>OnReconcileError</strong> do componente <strong>TClientDataset</strong>. Através de um form padronizado, disponibilizado pelo próprio Delphi (Reconcile Error Dialog) podemos, dentro deste evento, manipular a mensagem de erro e exibir ao usuário uma tela com opções, permitindo que ele mesmo possa corrigir, ignorar ou cancelar a atualização dos dados (<strong>ApplyUpdates</strong>). </p>\r\n<p style=\"text-align: justify;\">Para começar, e para quem nunca viu, abaixo está um modelo da tela Reconcile Error Dialog com algumas alterações realizadas por mim. O modelo original desta tela pode ser obtido a partir do próprio Delphi, no caminho <em><strong>File &gt; New &gt; Other...</strong></em> e selecionando o item <em><strong>VCL Reconcile Error Dialog</strong></em>.</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/datasnap/ID000093/ReconcileErrorDialogModificado.jpg\" width=\"641\" height=\"401\" border=\"0\" /></p>\r\n<p style=\"text-align: justify;\">Como uso PostgreSQL em meus projetos eu tenho acesso a 3 tipos de informação na mensagem de erro gerada pelo banco de dados. O erro propriamente dito, um detalhe, que seria exatamente o porquê do erro ter ocorrido e um contexto, que seria o comando SQL que gerou a exceção. Fiz as alterações na caixa de diálogo e criei uma rotina de parse para obter as 3 partes da mensagem de erro separadamente. E ao testar tive uma infeliz descoberta. Nas duas primeiras abas as informações apareceram de forma completa, já na terceira (contexto) a mensagem foi cortada, veja:</p>\r\n<pre style=\"border: 2px solid white; font-family: monospace; background-color: black; color: white; padding: 3px;\">ERRO: duplicar valor da chave viola a restrição de unicidade \"uc_usu_va_login\"\r\nDETAIL: Chave (va_login)=(admin) já existe.\r\nCONTEXT: comando SQL \"INSERT INTO USUARIOS (VA_NOME\r\n ,VA_LOGIN\r\n ,CH</pre>\r\n<p style=\"text-align: justify;\">Mas na verdade, a mensagem que o banco gerou foi a seguinte:</p>\r\n<pre style=\"border: 2px solid white; font-family: monospace; background-color: black; color: white; padding: 3px;\">ERRO: duplicar valor da chave viola a restrição de unicidade \"uc_usu_va_login\"\r\nDETAIL: Chave (va_login)=(admin) já existe.\r\nCONTEXT: comando SQL \"INSERT INTO USUARIOS (VA_NOME\r\n ,VA_LOGIN\r\n ,CH_SENHA\r\n ,VA_EMAIL)\r\n VALUES (pVA_NOME\r\n ,pVA_LOGIN\r\n ,pCH_SENHA\r\n ,pVA_EMAIL)\"\r\n PL/pgSQL function \"idu_usuarios\" line 7 at comando SQL</pre>\r\n<p style=\"text-align: justify;\">Após muitas depurações (às vezes complexas) cheguei a conclusão de que quem estava cortando as mensagens era o DataSnap, mais especificamente a biblioteca Midas.dll ou, no meu caso, o midas.obj, já que eu não uso a biblioteca Midas.dll. Durante a depuração obtive mais uma curiosidade sobre o fato: a mensagem era realmente truncada exatamente em 255 caracteres.</p>\r\n<p style=\"text-align: justify;\">Por sorte as versões do Delphi a partir de 2010 trazem consigo o código-fonte do midas.dll (em C++), por isso eu pude buscar neste código-fonte o local exato onde as mensagens de erro eram montadas e finalmente descobri como aumentar a quantidade de caracteres na mensagem de erro \"Reconcile\".</p>\r\n<p style=\"text-align: justify;\">Após instalar a personalidade C++ do Delphi, de forma poder compilar o midas, encontrei a linha do erro e descobri inclusive que existe uma solicitação de conserto no QC (<a href=\"http://qc.embarcadero.com/wc/qcmain.aspx?d=84960\">http://qc.embarcadero.com/wc/qcmain.aspx?d=84960</a>) o qual parece ter sido ignorado pelo pessoal da Embarcadero, já que o campo \"Resolution\" está como \"Deferred to Next Rel\", algo como \"Adiado para o próximo release\". Só que a solicitação é de 2010 e eu estou usando o Delphi XE<a href=\"#obs1\"><sup>1</sup></a> que ao meu ver já deveria ter a solução mas cá estou eu corrigindo eu mesmo.</p>\r\n<p>O problema está dentro do método \"Clone\", da classe \"DSBASE\" dentro do fonte \"ds.cpp\" na linha 2133 (Delphi XE, Update1). Abaixo está o bloco de código. A linha 4 é a linha problemática:</p>\r\n<pre class=\"line-numbers language-cpp\"><code>// Set the third field for the error string.\r\nLdStrCpy((pCHAR)pFldDes-&gt;szName, szdsERRMESSAGE);\r\npFldDes-&gt;iFldType = fldZSTRING;\r\npFldDes-&gt;iUnits1 = 255; // Increased on request.. DBIMAXMSGLEN;\r\npFldDes++;</code></pre>\r\n<p style=\"text-align: justify;\">Note que é bem interessante a linha do problema. Ela possui um valor constante de 255, o qual limita o tamanho das mensagens de erro e um comentário \"Increased on request\" (Aumente quando pedirem). Note também que ao lado do comentário, existe a constante <strong>DBIMAXMSGLEN</strong>, a qual tem um mnemônico bem sugestivo (Tamanho Máximo de Mensagem). Eu já havia encontrado a declaração desta constante em outro fonte e já desconfiava dela como sendo a responsável pelo problema. Alterei o seu valor, mas como ela não estava sendo usada, a mensagem de erro sempre vinha truncada. Vale ressaltar ainda que após <strong>DBIMAXMSGLEN</strong> há um ponto-e-vírgula (;) o que me leva a pensar que anteriormente (não sei quando) esta linha era exatamente aquela que ficou após a minha correção, isto é:</p>\r\n<pre class=\"line-numbers language-cpp\"><code>pFldDes-&gt;iUnits1 = DBIMAXMSGLEN;</code></pre>\r\n<p style=\"text-align: justify;\">É como se alguém, deliberadamente tivesse fixado o valor do campo em 255, removendo a implementação anterior que era parametrizada e por isso mais correta. Após realizar a substituição da linha eu aumentei o valor de <strong>DBIMAXMSGLEN</strong> para <strong>1024</strong>. <strong>DBIMAXMSGLEN</strong> está declarada em \"bdetypes.h\" como um define. Após a correção a linha ficou assim:</p>\r\n<pre class=\"line-numbers language-cpp\"><code>#define DBIMAXMSGLEN 1024 // Max message len</code></pre>\r\n<p style=\"text-align: justify;\">Depois destas duas alterações em \"ds.cpp\" e \"bdetypes.h\" compilei, teste e o resultado foi o esperado: a mensagem de erro foi apresentada na íntegra na caixa de diálogo Reconcile, entretanto, havia um pequeno inconveniente. Após compilar o projeto do midas foi gerada a dll midas (midas.dll) só que eu não uso a biblioteca midas nos meus projetos. Ao invés disso, como muitos de nós programadores Delphi, eu uso o <strong>MidasLib</strong>.</p>\r\n<p style=\"text-align: justify;\">O <strong>MidasLib</strong> é um arquivo .pas (unit) que liga estaticamente o código da biblioteca midas na aplicação que estiver sendo compilada. O que muita gente talvez não saiba é que a ligação estática do midas.dll não usa efetivamente esta biblioteca, mas sim, o arquivo <strong>midas.obj</strong> o qual existe dentro da pasta LIB do Delphi. Se você der uma olhada no arquivo MidasLib.pas você vai entender exatamente o que eu estou dizendo.</p>\r\n<p style=\"text-align: justify;\">Não tenho muita experiência com C++. Tentei de várias maneiras compilar este arquivo (<strong>midas.obj</strong>) com o intuito de usá-lo ligado estaticamente ao meu projeto, mas não obtive sucesso. Procurei em vários locais na Internet como criar um arquivo .obj e finalmente cheguei a conclusão que no caso do midas isso não seria possível porque dentre os fontes do midas eu não tenho um fonte de nome <strong>midas.cpp</strong>.</p>\r\n<p style=\"text-align: justify;\">Arquivos .obj não são o arquivo final que um projeto cria, mas sim, arquivos intermediários. Numa comparação com o Delphi, os arquivos .obj, tem uma função semelhante a dos arquivos .dcu. Com esta comparação, fica claro que eu jamais geraria um arquivo <strong>midas.obj</strong> sem que houvesse um arquivo <strong>midas.cpp</strong>. A Embarcadero deixou de fora este fonte. Os motivos disso eu não sei, mas tenho certeza de que se eu entendesse mais de C++ eu poderia criar um arquivo midas.cpp e gerar meu próprio <strong>midas.obj</strong>.</p>\r\n<p style=\"text-align: justify;\">Como não tenho toda esta capacidade, usei um pouco de força-bruta para resolver meu problema. Lembrei que poderia fazer algo bem mais radical do que alterar o código-fonte. Eu posso alterar alguns bytes diretamente no arquivo obj e foi exatamente o que eu fiz. Basicamente eu, usando um editor hexadecimal, procurei pela seguinte sequencia de bytes:</p>\r\n<pre style=\"border: 2px solid white; font-family: monospace; background-color: black; color: white; padding: 3px; text-align: center; font-size: 12pt;\">C7 43 28 <span style=\"color: #ff0000;\">FF</span> 00 00 00</pre>\r\n<p>E a substituí exatamente por esta sequencia:</p>\r\n<pre style=\"border: 2px solid white; font-family: monospace; background-color: black; color: white; padding: 3px; text-align: center; font-size: 12pt;\">C7 43 28 <span style=\"color: #ff0000;\">00 04</span> 00 00</pre>\r\n<p style=\"text-align: justify;\">Note que após o byte de valor 28 havia FF que é o tamanho da mensagem de erro 255. O que eu fiz foi aumentar para 1024 (<strong>400h</strong>) caracteres, por isso usei 00 no lugar de FF e completei o byte seguinte com 04. Realmente é esquisito o fato de que esta alteração gere o hexa <strong>400h</strong>. Acredito que estes bytes devem estar em outro tipo de <a href=\"http://en.wikipedia.org/wiki/Endianness\">endianess</a>, assunto que ainda é um tanto confuso pra mim, mas que imagino mais ou menos como deve ser feito, veja:</p>\r\n<pre style=\"border: 2px solid white; font-family: monospace; background-color: black; color: white; padding: 3px; text-align: center; font-size: 12pt;\"><span style=\"color: #ff0000;\">00</span> 0<span style=\"color: #ff0000;\">4</span> 00 00 = 00 00 0<span style=\"color: #ff0000;\">4 00</span>h = <span style=\"color: #ff0000;\">400h</span> (zeros à esquerda não valem nada aqui)</pre>\r\n<p style=\"text-align: justify;\">A sequencia acima tem 4 bytes. Lendo da direita para esquerda, <span style=\"background-color: #ffff00;\">[o primeiro byte é zero zero]</span>, <span style=\"background-color: #ffff00;\">[o segundo é zero zero]</span>, <span style=\"background-color: #ffff00;\">[o terceiro é zero 4]</span> e o <span style=\"background-color: #ffff00;\">[quarto é zero zero]</span>. Escrevendo diretamente cada byte (entre colchetes) temos exatamente <strong>00 00 04 00</strong>. Desprezando os zeros à esquerda temos <strong>400</strong>, logo, achamos o porquê de a linha modificada ser deste jeito ;)</p>\r\n<p style=\"text-align: justify;\">A parte interessante começa aqui. Você me pergunta como eu achei esta sequencia e como eu sei que isso funciona. Aí é onde entra a grande maravilha chamada ASSEMBLY e o <a href=\"http://www.hex-rays.com/products/ida/support/download_freeware.shtml\">IDA - Interactive Disassembler</a> que é fantasticamente gratuito e não menos poderoso para quem entende um pouco de ASSEMBLY.</p>\r\n<p style=\"text-align: justify;\">Ao abrir o midas.obj no IDA e deixar que ele seja processado, eu vou na lista de funções exportadas \"Exports\" e busco pela função chamada \"Clone\" da classe \"DSBASE\". Na lista, esta função aparecerá como \"DSBASE::Clone(ulong,int,int,TDSBASE **)\". Após dar dois cliques eu sou enviado a aba \"IDA View-A\" que vai listar o código assembly da função. O cursor estará parado exatamente no início da implementação desta função, isto é, se fosse uma função Delphi, estaria posicionado exatemente em cima da primeira instrução após o \"begin\" de um procedure ou função. Descendo um pouco no código eu acho o seguinte trecho:</p>\r\n<pre class=\"line-numbers language-nasm\"><code>; #line 2128\r\npush offset aError_message ; \"ERROR_MESSAGE\"\r\npush ebx ; lpString1\r\ncall lstrcpyA\r\n; #line 2129\r\nmov dword ptr [ebx+20h], 1\r\n; #line 2130\r\nmov dword ptr [ebx+28h], 0FFh\r\n; #line 2131\r\nadd ebx, 4Ch ; \'L\'</code></pre>\r\n<p style=\"text-align: justify;\">Note que existem comentários que o próprio IDA inclui, sobre as linhas de onde cada instrução subsequente se aplica e sobre o valor de algumas constantes que foram utilizadas no fonte original. O código-fonte original é o ds.cpp que eu descobri quando consegui achar a linha de código com o problema. Abaixo, está o mesmo trecho de código acima, só que no bom e velho C++:</p>\r\n<pre class=\"line-numbers language-cpp\" style=\"counter-reset: linenumber 2127;\" data-start=\"2128\"><code>LdStrCpy((pCHAR)pFldDes-&gt;szName, szdsERRMESSAGE);\r\npFldDes-&gt;iFldType = fldZSTRING;\r\npFldDes-&gt;iUnits1 = 255;\r\npFldDes++;</code></pre>\r\n<p style=\"text-align: justify;\">Acima eu coloquei as linhas do arquivo onde cada linha de código aparece, para que olhando atentamente os dois blocos de código perceba-se inclusive como o compilador converte as linhas de código em instruções ASSEMBLY. É bem interessante. Como se pode ver, curiosamente, a função LdStrCpy se transforma em 3 linhas no ASSEMBLY. Note que os dois parâmetros desta função são colocados na pilha (push) antes da função ser chamada (call). Note que a colocação dos parâmetros na pilha é feita de trás pra frente, isso por conta da convenção de chamada usada no C++ (stdcall). Outra coisa interessante é que o nome da função mudou de LdStrCpy no C++ para lstrcpyA no ASSEMBLY. Isso porque LdStrCpy parece ser um tipo de alias (wrapper) para a função de api real (lstrcpyA).</p>\r\n<p style=\"text-align: justify;\">Voltando a explicação inicial, precisamos mudar no assembly a linha 2130 de forma que ela corresponda a</p>\r\n<pre class=\"line-numbers language-cpp\"><code>pFldDes-&gt;iUnits1 = 1024;</code></pre>\r\n<p style=\"text-align: justify;\">no ASSEMBLY, esta linha (2130) se torna</p>\r\n<pre class=\"line-numbers language-nasm\"><code>mov dword ptr [ebx+28h], 400h</code></pre>\r\n<p style=\"text-align: justify;\"><strong>400h</strong> é o valor <strong>1024</strong> em hexadecimal. No IDA ao clicar em cima da palavra \"mov\" e ir até a aba \"Hex View-A\", a sequencia <strong>C7 43 28 FF 00 00 00</strong> fica destacada. Esta sequencia de bytes aparentemente sem sentido é a que corresponde ao comando <strong>mov dword ptr [ebx+28h], 0FFh</strong> inteiro! Nesta sequencia o <strong>FF</strong> corresponde ao ao valor <strong>255</strong> o qual tem de ser substituido por <strong>1024</strong> que é <strong>400</strong> em hexadecimal, assim, fazendo a substituição da sequencia <strong>C7 43 28 FF 00 00 00</strong> pela sequencia <strong>C7 43 28 00 04 00 00</strong> conseguimos finalmente o resultado esperado e tudo estaria pronto para compilar, no entanto não é bem assim.</p>\r\n<p style=\"text-align: justify;\">Não sei porque, mesmo substituindo o arquivo <strong>midas.obj</strong> na pasta lib do Delphi, não consegui obter o comportamento esperado. Na verdade busquei todo o sistema para saber se não tinha algum arquivo <strong>midas.obj</strong> no path. Todos os que haviam eu apaguei, mantendo apenas aquele existente na pasta lib. Sem efeito. Foi aí que tive uma sacada de Dr. House. Apaguei o ultimo <strong>midas.obj</strong> existente (o da pasta LIB) e mesmo assim minha aplicação compilou! Isso prova que o Delphi esta usando um <strong>midas.obj</strong> contido em algum BPL ou outro arquivo similar e que aquele arquivo ali não serve pra nada. Para resolver o problema eu movi para os fontes da minha aplicação o arquivo <strong>MidasLib.pas</strong> e o arquivo <strong>midas.obj</strong>, assim, este fonte é compilado juntamente com a minha aplicação e usa efetivamente o meu <strong>midas.obj</strong> modificado.</p>\r\n<p style=\"text-align: justify;\">Agora sim! Tudo funciona como deve: minha aplicação retorna as mensagens de erro Reconcile completas (ou mais especificamente com até 1024 caracteres) e eu estou vinculando estaticamente o código do <strong>midas.obj</strong> no meu projeto tornando desnecessário o uso do <strong>midas.dll</strong>. Aliás, como uma observação final, é importante incluir o nosso <strong>MidasLib</strong> tanto no cliente quanto no Servidor.</p>\r\n<p style=\"text-align: justify;\">Para entender um pouco mais sobre algumas coisas que foram faladas aqui, seguem alguns links muito úteis</p>\r\n<ul>\r\n<li><a href=\"http://ref.x86asm.net/index.html\">X86 Opcode and Instruction Reference Home - Referência de instruções Assembly e seus opcodes correspondentes</a></li>\r\n<li><a href=\"http://pt.wikipedia.org/wiki/Opcode\">Código de operação - Definição geral de Opcode em português</a></li>\r\n<li><a href=\"http://www.hex-rays.com/index.shtml\">Hex Rays - Site oficial do IDA - Interactive Disassembler</a></li>\r\n</ul>\r\n<hr />\r\n<p style=\"text-align: justify;\"><sup><a name=\"obs1\"></a>1</sup> Quando este artigo foi publicado originalmente eu estava usando o Delphi XE. Não sei se versões mais recentes já corrigiram isso. O intuito de publicar este artigo sem verificar se a correção já foi realizada é que muitas pessoas ainda podem ter o problema por usarem Delphis mais antigos e também porque aqui eu mostro algumas técnicas interessantes para realizar patches diretamente em arquivos binários.</p>',0,99,'2016-07-26 19:52:24',24,'','2016-11-18 12:47:29',24,24,'2020-06-22 17:47:40','2016-07-26 19:52:24','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',42,7,'','',1,265,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(94,228,'User Control DXC Edition','usercontrol-dx-edition','<p style=\"text-align: justify;\">Esta é a <strong>página oficial</strong> da evolução do aclamado controle de usuários: <strong><span style=\"color: #ff0000;\">U</span>ser<span style=\"color: #ff0000;\">C</span>ontrol Suite <span style=\"color: #ff0000;\">D</span>elphi E<span style=\"color: #ff0000;\">x</span>perts <span style=\"color: #ff0000;\">C</span>onsortium <span style=\"color: #ff0000;\">E</span>dition</strong>, também conhecido como <strong>UCDXCE</strong>. Esta edição é focada na simplicidade de uso, retrocompatibilidade básica com a versão oficial final (2.31 RC4), organização de código-fonte, correção de bugs e adição de funcionalidades exclusivas.</p>\r\n','\r\n<h2>História</h2>\r\n<p style=\"text-align: justify;\">A finalidade desta distribuição do User Control (UCDXCE) é unificar todas as versões disponíveis a fim de tornar-se \"A\" distribuição definitiva deste que é um excelente componente para gerenciamento de usuários e permissões.</p>\r\n<p style=\"text-align: justify;\">Minha intenção não é usurpar o projeto dos outros, por isso, quero deixar bem claro aqui que <span style=\"text-decoration: underline;\">este componente originalmente não foi desenvolvido por mim, mas sim por um desenvolvedor principal e várias outras pessoas (colaboradores)</span> há alguns anos e o crédito por todo e qualquer desenvolvimento até a revisão 1 (inicial) dessa nova distribuição deve ser dado aos pioneiros. Todo o desenvolvimento a partir da revisão 2 será composto por customizações e <em>bugfixes</em> de autorias diversas, iniciadas por mim mesmo.</p>\r\n<p style=\"text-align: justify;\">A motivação para realizar este trabalho reside no fato de que, atualmente, a fonte original do UserControl (<a href=\"https://sourceforge.net/projects/usercontrol\">https://sourceforge.net/projects/usercontrol</a>) parece não conter quaisquer atualizações significativas há algum tempo e os arquivos existentes não parecem seguir qualquer ordem lógica, o que torna o uso do componente em projetos grandes um risco para a maioria dos desenvolvedores sérios, preocupados com a segurança em seus sistemas. A última versão disponível no SourceForge é a 2.31 RC4 e foi movimentada pela última vez em 2013. Ao que tudo indica, não houve muitas alterações no código, a não ser a inclusão de um conector para o FireDAC.</p>\r\n<p style=\"text-align: justify;\">No SF existe também uma versão 2.7, mas ela é de 2004 e é para Delphi 6! Outro fato curioso é que a última versão diz ser para Delphi XE4, mas a pasta contida dentro do arquivo compactado continha \"XE3\" no nome. Todas Estas incoerências, mais o fato de não haver mais atualizações, juntamente com o fato de que o código-fonte sempre foi muito desorganizado (não sou somente eu quem acha isso...) deixa qualquer desenvolvedor preocupado. Muitos de nós não podemos arriscar utilizar um componente crítico como esse sem que haja um mínimo de segurança em seu uso.</p>\r\n<p style=\"text-align: justify;\">Tudo isso me motivou a começar essa jornada de padronização/correção e melhorias, mas não tenho intenção de gerenciar milhares de solicitações de melhorias ou correções de bugs. Eu meramente me considero a pessoa que deu o pontapé inicial para elevar o User Control a um outro nível! Eventualmente uma ou outra correção poderá ser feita, mediante solicitação, contudo imagino que não sejam tantas assim, já que os desenvolvedores fizeram um bom trabalho, apesar do código despadronizado :)</p>\r\n<h2>Onde baixar? Como Instalar?</h2>\r\n<p style=\"text-align: justify;\">Os fontes do UCDXCE estão disponíveis gratuitamente no endereço abaixo:</p>\r\n<p style=\"text-align: center;\"><a href=\"https://osdn.net/projects/ucdxce\">https://osdn.net/projects/ucdxce</a></p>\r\n<p style=\"text-align: justify;\">Recomendo que se use o SVN para baixar os fontes, isto é, não baixe os fontes gerando um zip pelo site. Usando o SVN você poderá a qualquer momento baixar a última versão dos fontes de forma prática (SVN Update).</p>\r\n<p style=\"text-align: justify;\">Antes de instalar o UCDXCE instale o seu pré-requisito:</p>\r\n<p style=\"text-align: center;\"><a href=\"https://osdn.net/projects/pngcdxme\">https://osdn.net/projects/pngcdxme</a></p>\r\n<p style=\"text-align: justify;\">A instalação tanto do pré-requisito como do UCDXCE e de seus conectores segue o padrão de qualquer componente Delphi. Primeiro procure a pasta de projeto correspondente ao seu Delphi e instale os arquivos DPK. Arquivos DPK que que terminam com R, compilam BPLs de runtime e arquivos DPK que terminam com D, compilam BPLs de designtime. Ambos os pacotes precisam ser compilados, mas apenas o pacote D precisa ser instalado.</p>\r\n<p style=\"text-align: justify;\">Após a instalação bem sucedida, inclua no library path do Delphi as pastas dcu, res.</p>\r\n<h2>Considerações finais</h2>\r\n<p style=\"text-align: justify;\">Este componente ainda está sendo desenvolvido. Nem todas as suas funcionalidades foram testadas e algumas delas ainda não foram implementadas. Ele está em \"fase alpha\", por isso eu não recomendo sua utilização em ambientes finais (produção). Ele está sendo disponibilizado \"como está\" apenas para apreciação da comunidade. Sugestões e principalmente relatórios de bugs são bem vindos! Use os comentários abaixo deste artigo para interagir comigo.</p>\r\n<h2>Galeria de imagens</h2>\r\n<p style=\"text-align: center;\"><a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard01.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard01.png\" width=\"20%\" /></a> <a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard02.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard02.png\" width=\"20%\" /></a> <a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard04.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard04.png\" width=\"20%\" /></a> <a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard05.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard05.png\" width=\"20%\" /></a></p>\r\n<p style=\"text-align: center;\"><a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard06.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard06.png\" width=\"20%\" /></a> <a class=\"cbg1\" href=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard07.png\"><img src=\"images/zost/ourproducts/delphi/components/ucdxe/gallery/Clipboard07.png\" width=\"20%\" /></a></p>\r\n<p style=\"text-align: center;\"><span style=\"color: #ff0000; font-size: 8pt;\">As telas poderão sofrer alterações sem prévio aviso e poderão ser diferentes daquelas existentes na versão atual do UCDXCE</span></p>\r\n<h2 style=\"text-align: left;\">Diagrama de componentes e ligações</h2>\r\n<p style=\"text-align: left;\"><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/zost/ourproducts/delphi/components/ucdxe/ucdxce.png\" width=\"743\" height=\"537\" /></p>\r\n<p style=\"text-align: center;\"><span style=\"color: #ff0000; font-size: 8pt;\">Este diagrama poderá sofrer alterações sem prévio aviso. Componentes poderão ser removidos, adicionados ou terem seus ícones modificados, tornando-os diferentes daqueles instalados na versão atual do UCDXCE</span></p>\r\n<hr />\r\n<p style=\"text-align: center; font-style: italic;\">Fontes hospedados no<a href=\"https://osdn.net/\"><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"//osdn.net/sflogo.php?group_id=11343&amp;type=3\" alt=\"OSDN\" width=\"210\" height=\"63\" border=\"0\" /></a></p>',1,82,'2016-07-28 02:54:29',24,'','2019-07-30 00:17:24',24,0,'0000-00-00 00:00:00','2017-07-05 02:54:00','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/zost\\/ourproducts\\/delphi\\/components\\/ucdxe\\/ucdxe.png\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','',78,2,'Delphi, Addicted 2 Delphi, Delphi Experts Consortium, UC, UserControl, User Control, DXC, DXCE, UCDXCE','Esta é a página oficial da evolução do aclamado controle de usuários: UserControl Suite Delphi Experts Consortium Edition, também conhecido como UCDXCE. Esta edição é focada na simplicidade de uso, retrocompatibilidade básica com a versão oficial final (2.31 RC4), organização de código-fonte, correção de bugs e adição de funcionalidades exclusivas',1,8954,'',1,'*','',''),(96,255,'Categorias e Itens de menu','categorias-e-itens-de-menu','<p style=\"text-align: justify;\">Qual a relação entre as categorias e os itens de menu no Joomla? Será mesmo que você está usando estes dois recursos de forma correta? Neste rápido artigo vou abordar com exemplos, qual a relação entre estes dois conceitos essenciais!</p>\r\n','\r\n<p style=\"text-align: justify;\">Você usa corretamente as categorias e os menus no Joomla, mas provavelmente em algum momento de sua vida, ao começar a trabalhar com este CMS houve confusão entre estes dois recursos pelo simples fato de que ambos levam o programador a acreditar que sua estruturas hierarquizadas têm alguma relação direta. Se você é um iniciante, continue lendo!</p>\r\n<p style=\"text-align: justify;\">Deve-se entender que as categorias e os menus no Joomla nada tem a ver um com outro. Você pode criar um site sem qualquer menu e todo categorizado ou o contrário, um site com um menu totalmente hierarquizado e nenhuma categoria. Os menus são apenas isso, links agrupados hierarquicamente que dão acesso a seções do seu site e as categorias são apenas formas de classificar (categorizar) seu conteúdo. Tanto as categorias como os menus podem assumir uma estrutura hierarquizada, mas no caso dos menus esta estrutura organiza mais diretamente as seções do site, já a hierarquização das categorias serve mais como forma de facilitar a organização das próprias categorias. </p>\r\n<p style=\"text-align: justify;\">No Joomla, categorias devem ser usadas como agrupadores de mais de um item, seja de outras categorias, seja de artigos ou outros conteúdos. Imagine categorias como pastas. Para manter o site com os menus e o breadcrumb funcionando corretamente, cada item de menu que for efetivamente conter mais de um item deve ser configurado como Category Blog ou Category List, pois ambos representam a listagem do conteúdo de uma determinada categoria.</p>\r\n<p style=\"text-align: justify;\">Por exemplo, neste site, o menu ZOST contém o item \"Informações\", o qual tem 3 subitens. Cada um destes subitens aponta para um artigo único e cada um desses 3 artigos são da categoria \"Informações\", logo, o item de menu \"Informações\" é do tipo \"Category Blog\", e isso fará com que ao clicar neste item, seus 3 subitens apareçam, um após o outro, no layout de blog. Não é necessário criar uma categoria para cada um destes 3 itens porque como eu disse anteriormente, categorias são como agrupadores de mais de um item. Se um item aparece sozinho em uma categoria e não se planeja incluir mais itens nessa categoria, então este item não deveria ter uma categoria própria. Eu poderia ter ocultado estes 3 itens do menu e ter mantido as coisas mais simples, mas como estes itens são únicos eu resolvi facilitar o seu cesso expondo-os.</p>\r\n<p style=\"text-align: justify;\">Ainda usando este site como exemplo, o menu \"Addicted 2 Delphi\", tem um subitem \"Nossos produtos\", que tem um subitem \"Delphi\", quem tem um subitem \"Componentes\". Cada um destes itens de menu é do tipo \"Category List\". Note que nenhum item final (artigo) está sendo exibido no menu, portanto, todas eles podem ter uma categoria associada, porque todos eles representam agrupadores, como pastas.</p>\r\n<p style=\"text-align: justify;\">Resumindo: Se um item de menu representa uma \"pasta\" na hierarquia, então uma categoria deve ser criada para representá-lo e caso o item de menu não represente uma pasta, mas sim um conteúdo (artigo), não é necessário e nem correto se ter uma categoria para ele.</p>',1,110,'2016-08-06 19:24:26',24,'','2016-08-31 00:20:25',24,0,'0000-00-00 00:00:00','2016-08-06 19:24:26','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',6,2,'','',1,2449,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',0,'*','',''),(97,257,'Serialização de Objetos & Persistência em Arquivos','serializacao-de-objetos-persistencia-em-arquivos','<p style=\"text-align: justify;\">Não importa o quão sofisticada sua aplicação seja, mesmo que ela salve seus dados em bancos de dados ou mesmo na nuvem, frequentemente haverá a necessidade de salvar dados de forma local. Normalmente isso é necessário quando se precisa persistir configurações que só dizem respeito à instância do programa sendo executado no momento. Existem algumas formas de fazer isso, sendo as mais comuns, arquivos INI e registro do Windows. Neste artigo vou ensinar uma forma de salvamento de arquivos a partir de um objeto serializado, que, no meu humilde entendimento, é a melhor forma de se persistir informações localmente.</p>\r\n','\r\n<p style=\"text-align: justify;\">Enquanto está na memória, um objeto é simplesmente uma sequência de bytes, uma estrutura de dados binários. A serialização consiste em pegar todos estes bytes que representam o objeto e seus dados na memória e obter uma representação que possa ser facilmente portada. Normalmente a serialização gera dados em texto plano, que pode ser lido facilmente por humanos e esta seria a forma mais tradicional de serialização, contudo a outra característica da serialização, a portabilidade, faz com que mesmo se salvando os dados binários, desde que estes sejam de alguma forma portáveis, haja uma serialização, portanto, serialização, grosso modo, é sinônimo de portabilidade para objetos.</p>\r\n<h2>RTTI: A base da serialização no Delphi</h2>\r\n<p style=\"text-align: justify;\"><strong>RTTI</strong> significa <em><strong>Runtime Type Information</strong></em>, ou seja, <em><strong>Informações de Tipo em Tempo de Execução</strong></em>, mas o que isso tem a ver com a serialização? Na verdade tem tudo a ver! No Delphi os objetos que contém membros na seção published, automaticamente geram RTTI para tais membros e o mecanismo usado para serializar um objeto só é viável por conta do RTTI. Membros que possuem RTTI exportam em tempo de execução o seu tipo de dado além do dado propriamente dito e assim é possível, por meio de métodos específicos, perguntar a um objeto qual o tipo de uma de suas propriedades e, baseando-se na resposta, é possível formatar uma saída serializada que posteriormente pode ser convertida de volta no objeto sem qualquer esforço.</p>\r\n<p style=\"text-align: justify;\">Na forma como vou apresentar aqui neste artigo, toda essa conversão e obtenção de tipos de dados, bem como a geração de saída serializada, será feita pelo próprio Delphi! Nenhuma linha de código adicional será necessária porque o Delphi já serializa constantemente um de seus mais importantes objetos, os formulários.</p>\r\n<p style=\"text-align: justify;\">Se você não acredita em mim, abra agora um projeto vazio no Delphi e no TForm que vai aparecer, coloque um TButton, um TLabel e um TEdit. Altere algumas das propriedades do TForm e destes controles. Veja abaixo o TForm que eu criei como exemplo:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000097/Form.png\" width=\"223\" height=\"87\" /></p>\r\n<p style=\"text-align: justify;\">Agora clique com o botão direito do mouse em uma área vazia do TForm e clique em <em>View As Text</em>. A seguir está o que aparece ao clicar em View As Text:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>object FORM1: TFORM1\r\n Left = 0\r\n Top = 0\r\n BorderIcons = [biSystemMenu]\r\n Caption = \'Salvar nome\'\r\n ClientHeight = 57\r\n ClientWidth = 215\r\n Color = clBtnFace\r\n Font.Charset = DEFAULT_CHARSET\r\n Font.Color = clWindowText\r\n Font.Height = -11\r\n Font.Name = \'Tahoma\'\r\n Font.Style = []\r\n Icon.Data = {\r\n 0000010001001010100001000400280100001600000028000000100000002000\r\n 0000010004000000000000000000000000000000000010000000000000000101\r\n 01000C88160037C9630067EB8F00299D310045DB75002586280059E082002692\r\n 2D008AF5A6003FD46E0012911B0078F19A005AE8870024AA31004DDF7B000000\r\n 0000000000000000081111600000000006FA226000000000087A226000000000\r\n 0875A260000008888B75A21666600ED555F55A2222100ECDDDDFF55A22100EC3\r\n 3DDFFF55A2100E9999CDDF737FB004444B9DD5B8666000000493DA8000000000\r\n 0493358000000000049CC7800000000004EEEE80000000000000000000000000\r\n 0000000000000000000000000000000000000000000000000000000000000000\r\n 000000000000000000000000000000000000000000000000000000000000}\r\n OldCreateOrder = False\r\n PixelsPerInch = 96\r\n TextHeight = 13\r\n object LABE1: TLabel\r\n Left = 8\r\n Top = 8\r\n Width = 27\r\n Height = 13\r\n Caption = \'Nome\'\r\n end\r\n object BUTN1: TButton\r\n Left = 132\r\n Top = 27\r\n Width = 75\r\n Height = 21\r\n Caption = \'Salvar\'\r\n TabOrder = 0\r\n OnClick = BUTN1Click\r\n end\r\n object EDIT1: TEdit\r\n Left = 8\r\n Top = 27\r\n Width = 121\r\n Height = 21\r\n TabOrder = 1\r\n Text = \'Carlos\'\r\n end\r\nend</code></pre>\r\n<p style=\"text-align: justify;\">O que vai ser exibido para você pode ser ligeiramente diferente. Mas o que é isso? Isso é o TForm serializado em forma de texto legível e um mecanismo de stream carrega esta definição de uma vez só, toda vez que um TForm é criado, e seta todas as propriedades dele e de todos os controles que são de sua propriedade (tem TForm como Owner). Note o quão variados são os tipos das informações salvas. Neste exemplo básico você vê, números inteiros, strings, a atribuição de um manipulador de evento (na linha 42), um conjunto com um valor (na linha 4), um conjunto vazio (na linha 13), constantes (nas linhas 9 e 10) e por fim, mas não menos importante, um valor binário completo, que representa o ícone do TForm (na linha 14). Sofisticado, não é?</p>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Como seria legal se eu pudesse salvar meus arquivos de configuração nesse formato e com esta facilidade de carregamento instantâneo não é? Yes! You Can! Continue lendo ;)</p>\r\n<h2>Como salvar objetos completos como arquivos</h2>\r\n<p style=\"text-align: justify;\">Quando se usa arquivos INI ou mesmo o registro do Windows, precisamos lidar com funções específicas para salvamento de dados. É necessário, normalmente, criar uma instância de um objeto manipulador, TIniFile por exemplo, e informar o nome do arquivo, suas seções, suas variáveis e seus respectivos valores. Tudo sendo salvo como String e muitas vezes ocupando mais espaço do que o necessário.</p>\r\n<p style=\"text-align: justify;\">Ao carregar estes dados precisaríamos fazer todo o procedimento oposto e, dependendo do caso, ainda precisaríamos fazer conversões de dados (String para TDateTime por exemplo). Outra enorme desvantagem dos arquivos INI é que no mesmo não é possível salvar textos mais complexos com quebras de linha, muito menos dados binários. A serialização de um objeto e sua posterior persistência em um arquivo resolve todos os problemas de falta de suporte em arquivos INI e registro do Windows e habilita o programador a salvar QUALQUER TIPO DE INFORMAÇÃO num arquivo.</p>\r\n<p style=\"text-align: justify;\">String, Integer, Currency, Double, Float, TDateTime, Extended, conjuntos de dados constantes, constantes, além de coleções de tipos customizados e até mesmo dados binários crus (imagens, ícones, executáveis, dlls). Praticamente qualquer coisa pode ser salva no arquivo. O que você acharia de salvar e carregar um arquivo dessa forma?:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>procedure SalvarConfiguracoes;\r\nbegin\r\n Configuracoes.SaveText;\r\nend;\r\n\r\nprocedure CarregarConfiguracoes;\r\nvar\r\n FileName: TFileName;\r\nbegin\r\n FileName := ChangeFileExt(ParamStr(0),\'.config\');\r\n\r\n Configuracoes.LoadFromTextFile(FileName);\r\n\r\n if not FileExists(FileName) then\r\n Configuracoes.SaveText;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Os dois procedures acima já salvam e carregam <span style=\"text-decoration: underline;\"><strong>todas as configurações contidas no objeto</strong></span> \"Configurações\" <span style=\"text-decoration: underline;\"><strong>de uma só vez</strong></span>! Eu não sei você caro leitor, mas quando eu vi isso pela primeira vez eu achei genial :). Chega de falar, vamos ao que interessa. Primeiramente a unit \"mágica\" que torna tudo isso possível:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>unit UObjectFile;\r\n\r\ninterface\r\n\r\nuses\r\n Classes, SysUtils;\r\n\r\ntype\r\n TObjectFile = class(TComponent)\r\n private\r\n FFileName: String;\r\n public\r\n constructor Create(POwner: TComponent); override;\r\n destructor Destroy; override;\r\n procedure LoadFromTextFile(const aFileName: TFileName);\r\n procedure SaveToTextFile(const PFileName: TFileName);\r\n procedure SaveText;\r\n function ToString: String; override;\r\n procedure FromString(const aTextualRepresentation: String);\r\n end;\r\n\r\nimplementation\r\n\r\n{ TObjectFile }\r\n\r\nprocedure TObjectFile.SaveText;\r\nbegin\r\n if FFileName &lt;&gt; \'\' then\r\n SaveToTextFile(FFileName);\r\nend;\r\n\r\nprocedure TObjectFile.SaveToTextFile(const PFileName: TFileName);\r\nbegin\r\n with TStringList.Create do\r\n try\r\n Text := Self.ToString;\r\n SaveToFile(PFileName);\r\n finally\r\n Free;\r\n end;\r\nend;\r\n\r\nconstructor TObjectFile.Create(POwner: TComponent);\r\nbegin\r\n inherited;\r\n FFileName := \'\';\r\nend;\r\n\r\ndestructor TObjectFile.Destroy;\r\nbegin\r\n SaveText;\r\n\r\n inherited;\r\nend;\r\n\r\nprocedure TObjectFile.LoadFromTextFile(const aFileName: TFileName);\r\nbegin\r\n FFileName := aFileName;\r\n\r\n if FileExists(FFileName) then\r\n with TStringList.Create do\r\n try\r\n LoadFromFile(FFileName);\r\n FromString(Text);\r\n finally\r\n Free;\r\n end;\r\nend;\r\n\r\n{$HINTS OFF}\r\nprocedure TObjectFile.FromString(const aTextualRepresentation: String);\r\nvar\r\n BinStream: TMemoryStream;\r\n StrStream: TStringStream;\r\nbegin\r\n StrStream := TStringStream.Create(aTextualRepresentation);\r\n try\r\n BinStream := TMemoryStream.Create;\r\n try\r\n StrStream.Seek(0, sofrombeginning);\r\n ObjectTextToBinary(StrStream, BinStream);\r\n BinStream.Seek(0, sofrombeginning);\r\n Self := BinStream.ReadComponent(Self) as TObjectFile;\r\n finally\r\n BinStream.Free\r\n end;\r\n finally\r\n StrStream.Free;\r\n end;\r\nend;\r\n{$HINTS ON}\r\n\r\nfunction TObjectFile.ToString: String;\r\nvar\r\n BinStream: TMemoryStream;\r\n StrStream: TStringStream;\r\n S: string;\r\nbegin\r\n inherited;\r\n BinStream := TMemoryStream.Create;\r\n try\r\n StrStream := TStringStream.Create(S);\r\n try\r\n BinStream.WriteComponent(Self);\r\n BinStream.Seek(0, sofrombeginning);\r\n ObjectBinaryToText(BinStream, StrStream);\r\n StrStream.Seek(0, sofrombeginning);\r\n Result := StrStream.DataString;\r\n finally\r\n StrStream.Free;\r\n end;\r\n finally\r\n BinStream.Free\r\n end;\r\nend;\r\n\r\nend.</code></pre>\r\n<p style=\"text-align: justify;\">Como se pode ver, esta unit não tem muito código. Ela contém apenas wrappers e facilitadores para as funções <strong>ObjectBinaryToText</strong> e <strong>ObjectTextToBinary</strong>. São estas as funções mágicas de fato, as quais manipulam os membros published do objeto fazendo uso do RTTI.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Para usar esta unit e a classe <strong>TObjectFile</strong> é preciso primeiro criar uma classe com nossos membros que deverão ser serializados. Como estamos usando como exemplo um arquivo de configurações, nada mais justo do que criar uma classe <strong>TConfiguracoes</strong>. A unit completa está abaixo:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>unit UConfiguracoes;\r\n\r\ninterface\r\n\r\nuses\r\n UObjectFile;\r\n\r\ntype\r\n TValorEnum = (veItem0, veItem1, veItem2, veItem3);\r\n\r\n TValorSet = set of TValorEnum;\r\n\r\n TConfiguracoes = class (TObjectFile)\r\n private\r\n FValorCurrency: Currency;\r\n FValorInteger: Integer;\r\n FValorDouble: Double;\r\n FValorDateTime: TDateTime;\r\n FValorString: String;\r\n FValorBoolean: Boolean;\r\n FValorEnum: TValorEnum;\r\n FValorSet: TValorSet;\r\n published\r\n property ValorInteger: Integer read FValorInteger write FValorInteger default 0;\r\n property ValorCurrency: Currency read FValorCurrency write FValorCurrency;\r\n property ValorDouble: Double read FValorDouble write FValorDouble;\r\n property ValorDateTime: TDateTime read FValorDateTime write FValorDateTime;\r\n property ValorString: String read FValorString write FValorString;\r\n property ValorBoolean: Boolean read FValorBoolean write FValorBoolean default False;\r\n property ValorEnum: TValorEnum read FValorEnum write FValorEnum default veItem0;\r\n property ValorSet: TValorSet read FValorSet write FValorSet default [];\r\n end;\r\n\r\nimplementation\r\n\r\nend.</code></pre>\r\n<p style=\"text-align: justify;\">Esta unit é ainda menor, como esperado, já que todo trabalho duro é feito por TObjectFile. Incluí na classe TConfiguracoes vários membros de tipos de dados comuns. Eu poderia ter colocado um membro binário, mas isso complicaria na hora de atribuir um valor a ele, portanto apenas acredite que seria perfeitamente possível incluir um membro do tipo TImage, por exemplo. Os dados binários da imagem seriam gravados sem qualquer problema. Outras coisas que poderiam existir nesta classe seriam subclasses, incluindo coleções. Se você já criou classes com subclasses, isto é, membros que são de tipos de outras classes, bastaria incluir tais membros e inicializá-los corretamente que os dados da subclasse apareceriam no objeto serializado.</p>\r\n<p style=\"text-align: justify;\">Note que algumas das propriedades possuem a cláusula default. Essa cláusula instrui as funções <strong>ObjectBinaryToText</strong> e <strong>ObjectTextToBinary</strong> que se o valor da propriedade for igual àquele valor default ele não será incluído no objeto final serializado. Por exemplo, ValorInteger tem um valor default = 0. Na hora de serializar o objeto, caso ValorInteger = 0, ele não vai figurar na serialização, porque não é necessário. Isso é bom para economizar espaço no arquivo que vai receber o objeto serializado, pois ele não conterá referências a membros cujos valores são iguais aos seus respectivos valores default. Apesar do valor default ser importante para economizar espaço, infelizmente apenas membros dos tipos integer, boolean, enum e set podem ter valores default, em suma, apenas ordinais e conjuntos podem ter valores padrão, mesmo assim eu considero boa prática usá-los.</p>\r\n<p style=\"text-align: justify;\">Explore o exemplo anexado a este artigo para um melhor entendimento</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-08-12 05:17:38',24,'','2020-06-26 17:26:14',24,0,'0000-00-00 00:00:00','2016-08-12 05:17:38','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000097\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',19,82,'Delphi, Addicted 2 Delphi, DFM, Resource, RTTI','Não importa o quão sofisticada sua aplicação seja, mesmo que ela salve seus dados em bancos de dados ou mesmo na nuvem, frequentemente haverá a necessidade de salvar dados de forma local. Normalmente isso é necessário quando se precisa persistir configurações que só dizem respeito à instância do programa sendo executado no momento. Existem algumas formas de fazer isso, sendo as mais comuns, arquivos INI e registro do Windows. Neste artigo vou ensinar uma forma de salvamento de arquivos a partir de um objeto serializado, que, no meu humilde entendimento, é a melhor forma de se persistir informações localmente.',1,5416,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(98,258,'Quando o TClientDataSet e o TDataSetProvider são necessários?','devo-usar-tclientdataset-tdatasetprovider','<p style=\"text-align: justify;\">É surpreendente o número de programadores que insistem em seguir o caminho mais complexo por acharem que apenas assim é que se alcança o Nirvana Computacional. A verdade meu caro, é que a menos que você tenha muito tempo livre ou viva para fazer malabarismos com o teclado, digitando códigos e mais códigos sem necessidade aparente, você precisará muitas vezes desenvolver coisas muito rapidamente e não poderá divagar sobre aquilo que está desenvolvendo. O curioso é que, tal como os malabaristas de teclado, existem os malabaristas do arrasta-e-solta. Não é de hoje que tenho visto pessoas usando os componentes <strong>TClientDataSet</strong> e <strong>TDataSetProvider</strong> sem necessidade alguma, apenas porque acham que precisam usá-los a todo custo. <strong>Se você costuma usar o método Post seguido de um ApplyUpdates</strong>, ou se simplesmente você quer saber se está fazendo uso destes poderosos componentes à toa, continue lendo.</p>\r\n','\r\n<p style=\"text-align: justify;\">Pra começar este artigo vou logo dizendo que não, nem sempre estes dois componentes precisam ser usados e o ganho ao usá-los pode não ser compensador pois seu uso pode aumentar a complexidade do seu código indiretamente. Se você está com dúvidas a respeito disso, recomendo fortemente esta leitura.</p>\r\n<p style=\"text-align: justify;\">Antes de mais nada, entenda o que são estes dois componentes e evite gafes como programador, gafes estas que certamente vão introduzir complexidade desnecessária ao seu projeto:</p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">O <strong>TClientDataSet</strong> implementa um DataSet independente de banco de dados, representando <strong>um conjunto de dados na memória</strong>. Um TClientDataSet <strong>pode ser usado como</strong>:</p>\r\n<ol style=\"list-style-type: upper-alpha;\">\r\n<li style=\"text-align: justify;\">Um conjunto de dados stand-alone totalmente funcional <strong>baseado em arquivo</strong> para aplicações de banco de dados de camada única (<strong>single-tier</strong>). Quando usado dessa maneira, o TClientDataSet <strong>representa os dados armazenados num arquivo dedicado no disco rígido</strong> do usuário<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Um buffer</strong> local (<strong>na memória</strong>) dos registros <strong>de um outro conjunto de dados</strong> (TQuery, TTable ou similares). Este <em>conjunto de dados de origem</em> pode residir no mesmo TForm ou TDataModule onde o TClientDataSet estiver. <strong>Esta forma de uso é obrigatória quando o DataSet de origem é unidirecional</strong> (os componentes DB Express são, por exemplo), sendo a única maneira de fornecer suporte de navegação e edição para seus dados. O conjunto de dados de origem também pode residir em um sistema separado quando o TClientDataSet é usado para implementar a parte do cliente de um banco de dados, numa aplicação de várias camadas (<strong>n-tier</strong>)<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Um armazenamento temporário</strong> (na memória) <strong>de dados em forma de conjunto de dados</strong> facilmente navegável e com recursos já prontos para inserção, exclusão, seleção e alteração de seus itens, <strong>tornando-se assim um meio prático para manipulação de qualquer tipo de informação</strong>, bem como exibição dessa informação em componentes conscientes de dados, o que permite a interação simplificada do usuário</li>\r\n</ol>\r\n</blockquote>\r\n<p> </p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">O <strong>TDataSetProvider</strong>, como o nome sugere, fornece (provê) dados a partir de um conjunto de dados e resolve atualizações (inserções, exclusões e atualizações propriamente ditas) para esse conjunto de dados, o qual poderá aplicá-las ao SGBD associado a ele. De forma mais detalhada, o TDataSetProvider, empacota os dados de um conjunto de dados e passa este pacote em um ou mais DataPackets transportáveis para o TClientDataSet ou <a title=\"Nunca trabalhei com o XML Broker, mas pelo que pude entender lendo a ajuda do Delphi, ele é como um TClientDataSet, a diferença é que ao invés de converter os dados de um DataPacket, fornecido por um TDataSetProvider, em um conjunto de dados compatível com o TClientDataSet, ele converte esse DataPacket em XML, permitido uma utilização mais ampla de um servidor de aplicação desenvolvido em Delphi. Por exemplo, imagino que usando XML Brokers, seja possível converter os dados providos por um servidor de aplicação em XMLs que podem ser exibidos como páginas simples por um Browser (via XSLT) ou interpretados por outras linguagens, como PHP. Se você já trabalhou com o XML Broker, fique à vontade para comentar abaixo seu uso correto, ou simplesmente confirmar o que eu falei aqui ;)\" href=\"#\" rel=\"bookmark\">XML Broker</a>. O TClientDataSet, por sua vez, reconstrói os dados contidos no DataPacket a fim de criar uma cópia local (na memória), para o acesso simplificado do usuário. Quando o usuário termina de realizar suas ações nos dados (inserir, excluir, alterar), o TClientDataSet reempacota quaisquer dados alterados e envia estas alterações de volta para o TDataSetProvider, o qual aplica as atualizações no conjunto de dados original que por sua vez as replica no SGBD, terminando assim o ciclo \"requisição-resposta\". De forma resumida, um TDataSetProvider <strong>deve ser usado para</strong>:</p>\r\n<ul style=\"list-style-type: square;\">\r\n<li style=\"text-align: justify;\"><strong>Fornecer dados a partir de um conjunto de dados</strong> para um TClientDataSet ou XML Broker e <strong>resolver atualizações (inserções, exclusões e atualizações propriamente ditas)</strong> desse TClientDataSet ou XML Broker de volta para o conjunto de dados e consequentemente ao seu SGBD subjacente. O TDataSetProvider pode ser uma parte da mesma aplicação que o TClientDataSet ou XML Broker, ou <strong>pode ser colocado no servidor de aplicação (middleware) de uma aplicação de várias camadas (n-tier)</strong>. Neste último, ele serve como um provedor de dados, ficando entre um SGBD remoto e um TClientDataSet local (no cliente).</li>\r\n</ul>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">Eu espero que você tenha lido com cuidado (e entendido) as definições acima. Elas foram criadas a partir da definição dos componentes na ajuda do próprio Delphi e também a partir de observações minhas e de outras pessoas mais experientes, as quais usam este par de componentes como se deve.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: left;\">Interpretações errôneas sobre a função do TClientDataSet e do TDataSetProvider</h2>\r\n<p style=\"text-align: justify;\">De todas as coisas que eu já ouvi a respeito do uso desse par de componentes, a mais estúpida e absurda é a de que o simples fato de usar estes componentes já torna uma aplicação em uma aplicação n-tier. Sobre isso, eu lamento profundamente, mas se você acha isso eu creio que você não deve ter entendido bem o que é a divisão de uma aplicação em camadas e recomendo que você pare de ler este artigo e vá estudar sobre o assunto, tomando cuidado para não confundir camadas lógicas com camadas físicas. Neste artigo não está sendo aprofundado o assunto \"multicamadas\". Ele é apenas citado porque o TClientDataSet e o TDataSetProvider foram criados para permitir a criação de aplicações multicamadas com o Delphi (DataSnap), logo, é natural que alguns conceitos sejam citados.</p>\r\n<p style=\"text-align: justify;\">Outra coisa falada de forma recorrente a respeito do uso destes componentes fora da arquitetura de n camadas é que usar essa dobradinha economiza recursos de rede e aumenta a performance geral de um programa implementado desta maneira. É justamente por conta desta premissa que eu resolvi escrever este artigo, pois muita gente está usando de forma errada os componentes e achando que eles estão cumprindo seu papel de \"melhoradores de performance\", mas na verdade só estão introduzindo complexidade desnecessária nos programas.</p>\r\n<h2 style=\"text-align: justify;\">Como usar os componentes TClientDataSet e TDataSetProvider</h2>\r\n<p style=\"text-align: justify;\">A fim de tentar explicar os usos corretos desse par de componentes vou descrever abaixo as formas mais comuns de acesso a dados no Delphi:</p>\r\n<ol>\r\n<li style=\"text-align: justify;\">Seu programa acessa diretamente o SGBD utilizando componentes TQuery (ou similares), TUpdateSQL (ou similares) e TDatabase (ou similares). A figura abaixo mostra esta forma clássica de acesso a dados no Delphi, a qual é ensinada em praticamente todos os livros que tratam do assunto. Um iniciante certamente vai utilizar esta forma de acesso e a mesma pode ser usada em qualquer tipo de aplicação, pois é muito eficiente. Neste modelo o TQuery é automaticamente configurado para ser bidirecional (UniDirectional = False), o que permite sua ligação aos mais diversos controles conscientes de dados (DBAware) assim como permite a navegação para frente e para trás nos dados do TQuery, isto é, você pode usar <em>Prior</em> e <em>Next</em>. Aliás, vale salientar que você sempre só foi capaz de navegar no conjunto de dados porque a propriedade UniDirectional, por padrão, vem configurada como false.\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000098/ConexaoDireta.png\" width=\"211\" height=\"153\" /></p>\r\n</li>\r\n<li style=\"text-align: justify;\">Seu programa acessa diretamente o SGBD utilizando componentes TQuery (ou similares), TUpdateSQL (ou similares), TDataSetProvider, TClientDataSet e TDatabase (ou similares). A figura abaixo mostra esta forma de implementação. Nesta implementação <span style=\"background-color: #ffff00;\">o TQuery no qual o TClientDataSet está ligado deve ser configurado como unidirecional</span>, pois isso diminui o consumo de memória deste componente, que passa a utilizar internamente uma lista encadeada simples (onde cada registro conhece apenas o seu sucessor), ao invés de uma lista duplamente encadeada. Esta configuração pode diminuir até 50% do consumo de memória por registro no TQuery. Esta implementação também recomenda que a mecânica de funcionamento das telas seja baseada em múltiplas ações com apenas uma confirmação ao final. Em outras palavras, <span style=\"background-color: #ffff00;\">deve ser permitido ao usuário a realização várias ações (inserção, exclusão e alteração em qualquer ordem), as quais são mantidas em cache, para somente depois serem enviadas de uma só vez ao SGBD por meio de um ApplyUpdates</span>. Outra vantagem desse modelo de conexão é que ele permite que seja implementado um \"modelo de maleta\" (<a href=\"index.php/a2d-mei/articles-a2d-mei/110-modelo-de-maleta\" rel=\"alternate\">Briefcase Model</a>), onde um programa pode ficar totalmente desconectado de qualquer SGBD e apenas em momento oportuno a conexão seria feita e as alterações seriam efetivadas. <span style=\"background-color: #ffff00;\">Os componentes do DB Express (DBX) são unidirecionais, portanto esta forma de implementação é a única forma de trabalhar com eles e, neste caso, o <em>Post</em> pode ser seguido de <em>ApplyUpdates</em> caso você não queira implementar as ações em cache</span>.\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000098/ConexaoIndireta.png\" width=\"403\" height=\"153\" /></p>\r\n</li>\r\n<li style=\"text-align: justify;\">Seu programa acessa indiretamente o SGBD, neste caso, deve existir uma aplicação no meio do caminho entre seus programas-cliente e o SGBD. Isso caracteriza uma aplicação em n camadas e você deve estar usando DataSnap, neste caso você certamente sabe o que faz e por conseguinte deve estar usando o TClientDataSet e o TDataSetProvider de forma correta. A figura abaixo mostra o uso dos componentes TClientDataSet e TDataSetProvider em uma aplicação DataSnap usando SOAP como transporte de dados (existem outros meios de transporte disponíveis no Delphi). Note que tais componentes ficam fisicamente separados (máquinas distintas), ligados apenas pela internet ou intranet. O DataSnap obriga você a usar TDataSetProvider e o TClientDataSet, porque estes componentes são os dois lados da mesma moeda (conexão). Do lado do servidor (middleware) fica o TDataSetProvider e do lado do cliente (thin client) ficam todos os TClientDataSet, cada um deles conectados aos seus TDataSetProviders correspondentes no servidor. É interessante perceber que o TDataSetProvider no servidor (middleware) atua como um TDataSource numa aplicação comum (cliente/servidor). De fato, se o TDataSetProvider fosse substituído por um TDataSource, o middleware seria idêntico a uma aplicação cliente/servidor. Eu costumo dizer que, do ponto de vista do SGBD, o middleware é um simples programa cliente/servidor. A fim de diminuir o consumo de memória no servidor, é recomendável que todos os TQuery sejam configurados como unidirecionais. No cliente, cada TClientDataSet é bidirecional SEMPRE e por isso é possível usá-los conectados a controles conscientes de dados sem qualquer problema\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000098/ConexaoIndiretaDSSS.png\" width=\"721\" height=\"154\" /></p>\r\n</li>\r\n</ol>\r\n<p style=\"text-align: justify;\">O foco deste artigo está nas linhas destacadas no item 2 acima. Vamos finalmente falar a respeito do mal uso dos componentes TClientDataSet e TDataSetProvider.</p>\r\n<h2 style=\"text-align: left;\">Como não usar o TClientDatSet e o TDataSetProvider</h2>\r\n<p style=\"text-align: justify;\">A desculpa inicial para o uso destes componentes é a performance, porque olhando a figura do item 2 se nota que, claramente, a utilização deles não torna a implementação mais simples, muito pelo contrário. Do ponto de vista da performance, existem dois pontos principais, os quais foram destacados de amarelo no item 2. O primeiro deles seria a suposta diminuição do consumo de memória local e o segundo diz respeito à diminuição do tráfego de rede por meio do agrupamento de ações e aplicação das mesmas em lote.</p>\r\n<p style=\"text-align: justify;\">Se sua intenção é diminuir o consumo de memória então você não levou em conta algo muito simples: todo o ganho de memória obtido pelo uso de um cursor unidirecional no TQuery será compensado ou mesmo superado pela introdução do TDataSetProvider e do TClientDataSet, que é bidirecional tornando assim o consumo de memória SEMPRE MAIOR do que ao se usar a forma clássica de conexão (Item 1 acima). A recomendação é que o TQuery seja configurado como unidirecional não como uma vantagem opcional, mas sim como uma necessidade latente, já que a introdução do TClientDataSet duplicaria o consumo de memória e sendo assim, manter o TQuery como bidirecional nesta implementação é desperdício sério de memória e performance. Se nota que a configuração da propriedade UniDirectional no TQuery só faz mesmo sentido num middleware, pois lá não existe nada além de TQuery (ou similares). Considero, pois, que este mito do consumo de memória foi \"detonado\", como diriam os caras do Discovery Channel. Se sua única justificativa era essa, acho bom começar uma refatoração o mais rápido possível no seu código.</p>\r\n<p style=\"text-align: justify;\">Sobre a diminuição do tráfego de rede, preciso explicar que não existe componente mágico pra fazer isso sozinho. Apenas o conjunto \"implementação correta + componentes certos\" pode fazer o tráfego de rede diminuir e neste caso, sim, é possível diminuir drasticamente o consumo de banda da aplicação, mas <span style=\"text-decoration: underline;\">a utilização efetiva deste recurso requer que haja um botão adicional no seu TForm, que teria a função de enviar, por demanda, ao SGBD todas as alterações realizadas de uma só vez</span>, ou seja, a persistência das alterações no SGBD deve ser feita em duas etapas para que essa economia de dados seja efetiva.</p>\r\n<p style=\"text-align: justify;\">Se sua implementação usa recorrentemente <strong>Post + ApplyUpdates</strong>, e seus TDataSet não são unidirecionais por natureza (DBX), então eu lamento informar que você está subutilizando esta implementação e deveria repensar seriamente todo seu projeto. Em outras palavras, fazer Post + ApplyUpdates, transforma o conjunto TQuery + TDataSetProvider + TClientDataSet em uma redundância, pois o mesmo efeito pode ser conseguido com TQuery sozinho sem qualquer perda de performance. Se por acaso você estiver executando o ApplyUpdates TODA VEZ que uma operação for realizada, qual a vantagem de usar TDataSetProvider + TClientDataSet? Nenhuma! Pois seria o mesmo que realizar post ou delete diretamente no TQuery.</p>\r\n<h2>Conclusão</h2>\r\n<ol>\r\n<li style=\"text-align: justify;\">Usar TDataSetProvider + TClientDataSet em uma aplicação cliente/servidor é OBRIGATÓRIO apenas quando se usa componentes cujos TDataSet são unidirecionais, tal como ocorre com os componentes do <a title=\"Gostaria de agradecer aos amigos do grupo Delphi Experts que me alertaram sobre o fato de que os componentes do DB Express são unidirecionais e que apenas usando TDataSetProvider + TClientDataSet habilita seu uso com componentes DBAware\" href=\"#\" rel=\"bookmark\">DB Express</a>.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Usar TDataSetProvider + TClientDataSet em uma aplicação cliente/servidor com o <strong>intuito de diminuir o consumo de memória local é um mito</strong>, e se você estiver usando a dobradinha apenas por conta disso, pare, pense e refaça seu projeto.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Já do ponto de vista da economia de recursos de rede, usar TDataSetProvider + TClientDataSet em uma aplicação cliente/servidor só faz sentido se você pretende permitir ao usuário realizar várias operações e só no final confirmar todas ao mesmo tempo, ou seja, se você não está implementando em seu sistema uma forma de agrupar operações e fazer envio em lote das mesmas então o conjunto TDataSetProvider + TClientDataSet é desnecessário. Se você estiver fazendo Post + ApplyUpdates isso significa que você está subutilizando essa arquitetura e é desejável fazer tudo sem usar esses componentes, pois torna a codificação mais simples.</li>\r\n</ol>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-08-12 15:40:01',24,'','2020-06-26 17:27:03',24,0,'0000-00-00 00:00:00','2016-09-10 03:00:00','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000098\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',74,83,'Delphi, Addicted 2 Delphi, TClientDataSet, TDataSetProvider, Dados em Memória, Cache, ApplyUpdates, Briefcase Model','É surpreendente o número de programadores que insistem em seguir o caminho mais complexo por acharem que apenas assim é que se alcança o Nirvana Computacional. A verdade meu caro, é que a menos que você tenha muito tempo livre ou viva para fazer malabarismos com o teclado, digitando códigos e mais códigos sem necessidade aparente, você precisará muitas vezes desenvolver coisas muito rapidamente e não poderá divagar sobre aquilo que está desenvolvendo. O curioso é que, tal como os malabaristas de teclado, existem os malabaristas do arrasta-e-solta. Não é de hoje que tenho visto pessoas usando os componentes TClientDataSet e TDataSetProvider sem necessidade alguma, apenas porque acham que precisam usá-los a todo custo. Se você costuma usar o método Post seguido de um ApplyUpdates, ou se simplesmente você quer saber se está fazendo uso destes poderosos componentes à toa, continue lendo.',1,8782,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(100,274,'Quando devo registrar uma DLL?','quando-devo-registrar-uma-dll','<p style=\"text-align: justify;\">Existem duas coisas que me deixam profundamente irritado na informática: Pessoas que fecham janelas usando o menu popup (ou o caminho <strong>Arquivo &gt; Fechar</strong>) e pessoas que acham que toda DLL precisa ser registrada antes de ser usada. Este artigo é apenas para orientar os desavisados, porque pasme, já vi programadores experientes falando em registrar DLLs sem necessidade, seguindo e disseminando esse mito estúpido.</p>\r\n','\r\n<p style=\"text-align: justify;\">Para quem não sabe, <strong>DLL</strong> significa <em><strong>Dynamic Link Library</strong></em> ou <em><strong>Biblioteca de Vínculo Dinâmico</strong></em>. Como o nome sugere, uma DLL é ligada (ou vinculada) a algo dinamicamente. Esse \"algo\" seria um programa executável (ou outra DLL) e \"dinamicamente\" refere-se ao fato de que o programa executável utiliza código contido na DLL, que é um módulo separado, de forma dinâmica, sob demanda, pois tal código não foi compilado juntamente com o código do executável. Por falar em módulo separado, costuma-se chamar tanto programas executáveis quanto DLLs simplesmente de módulos porque tecnicamente, uma DLL também é um executável, mas suas características exclusivas fazem com que este \"executável\" não execute sem um \"programa host\", o qual tem a função de carregar a DLL no seu espaço de memória, tornando ambos (EXE e DLL) uma coisa só!</p>\r\n<p style=\"text-align: justify;\">Depois dessa encheção de linguiça inicial eu vou fazer aqui uma revelação. Sei que vai doer em muitos de vocês, mas a verdade tem que ser dita:</p>\r\n<h2>Não! Nem toda DLL precisa ser registrada, aliás, a grande maioria delas não precisa disso!</h2>\r\n<p style=\"text-align: justify;\">Quando você obtém uma DLL qualquer para usar, não há meios diretos de saber se esta DLL precisa ser registrada ou não, por isso, o primeiro passo é usar um pouco de lógica para supor seu uso. Primeiramente, ao obter uma DLL você o faz porque ela contém algo que você precisa, logo, você de algum modo sabe o que ela tem, logo, deveria saber se ela é uma DLL registrável ou não. Normalmente aquele que desenvolveu a DLL sabe exatamente o que ela é, portanto, se você obtiver uma DLL diretamente do fornecedor que a desenvolveu, este, com toda certeza, vai informar se esta DLL precisa ser registrada antes de ser usada de alguma forma. Normalmente, quando nada é especificado, a DLL <strong>NÃO PRECISA</strong> ser registrada e simplesmente exporta funções para uso direto.</p>\r\n<p style=\"text-align: justify;\">DLLs registráveis são todas aquelas que expõem/contém servidores COM, Objetos Active X, Objetos OLE e outras destas tecnologias exóticas que a Microsoft criou e que provavelmente você, que tenta registrar uma DLL qualquer sem saber se isso é necessário, provavelmente não vai usar. Em outras palavras, uma DLL só precisa ser registrada se você tiver certeza disso, do contrário ela não é registrável. Fica a dica.</p>\r\n<h2 style=\"text-align: justify;\">O DLL Export Viewer</h2>\r\n<p style=\"text-align: justify;\">Se mesmo assim você é destes que gosta de seguir receitas de bolo e não quer errar jamais, eu vou dar a dica definitiva pra você não se passar por <strong>noob retardado</strong> nos fóruns/grupos/listas dos quais participa, ao questionar sobre registro de DLLs. Baixe o programa <strong>DLL Export View</strong> (Freeware), que está disponível em <a href=\"http://www.nirsoft.net/utils/dll_export_viewer.html\">http://www.nirsoft.net/utils/dll_export_viewer.html</a>. Este programa simplesmente mostra todas as funções que uma DLL exporta. Como exemplo, eu usei a clássica <strong>capicom.dll</strong>, a qual <strong>é</strong> <strong>registrável</strong>. Veja abaixo a saída do programa:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000100/DLLRegistravel.png\" width=\"626\" height=\"473\" /></p>\r\n<p style=\"text-align: justify;\">Note que existem duas funções especiais, <strong>DllRegisterServer</strong> e <strong>DllUnregisterServer</strong>. Estas funções são as responsáveis por \"interagir\" com o programa <strong>RegSvr32</strong>, o qual promoverá o registro (ou desregistro) da DLL, portanto, se sua DLL tem estas duas funções, é certeza que ela precisa ser registrada, a não ser que algum <strong>troll zoeiro</strong> tenha criado funções com estes nomes propositalmente para enganar a todos, mas estou descartando esta hipótese.</p>\r\n<p style=\"text-align: justify;\">Só como forma de aparar todas as arestas, para não deixar nenhuma dúvida, segue o screenshot da saída do DLL Export Viewer para uma DLL \"comum\":</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000100/DLLComum.png\" width=\"626\" height=\"473\" /></p>\r\n<p style=\"text-align: justify;\">Note que não existem as duas funções especiais de registro, logo, esta DLL<strong> não é registrável</strong>. Use-a de forma tradicional.</p>\r\n<p style=\"text-align: justify;\">O DLL Export Viewer é uma mão na roda para inspecionar as funções exportadas por uma DLL. Isso é útil para qualquer bisbilhoteiro escovador de bits interessado em expandir seus conhecimentos. Use o programa para inspecionar funções exportadas por algumas DLLs do Windows, como <strong>User32.dll</strong> ou <strong>Kernel32.dll</strong>. Garanto que você verá algumas funções de nomes familiares usadas no Delphi e isso não é coincidência. Muitas das funções usadas no Delphi são funções de API do Windows ou wrappers para funções de API. Por exemplo, Application.MessageBox é uma função wrapper para as funções MessageBoxA ou MessageBoxW, dependendo de qual tipo de String se usa, \"A\" para AnsiStrings ou \"W\" para WideStrings. Estas funções encontram-se em User32.dll, como se pode ver no screenshot abaixo:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000100/User32.png\" width=\"626\" height=\"473\" /></p>\r\n<p style=\"text-align: justify;\">Note que existem outras versões desta mesma função e garanto que muitos de vocês leitores jamais as viram, portanto, mãos à obra e Google nelas! Falando em Google, não vou ensinar como usar o DLL Export Viewer, use sua inteligência e descubra (ou leia o manual em Inglês que vem junto do seu executável, dentro do zip).</p>\r\n<p style=\"text-align: justify;\">Eu espero, depois deste artigo, não mais ver dúvidas de pessoas nos locais onde eu ando (Fóruns, Grupos de Facebook, Listas de Discussão, Rua, etc.) a respeito de tal função não estar funcionando porque a DLL não foi registrada. Juro que vou responder jogando o link deste artigo. De nada!</p>',1,80,'2016-09-05 02:10:24',24,'','2016-11-18 13:23:20',24,0,'0000-00-00 00:00:00','2016-09-06 03:41:30','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000100\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{}',16,84,'Delphi, Addicted 2 Delphi, DLL, RegSvr32, Registrar, DLL Export Viewer, ActiveX, COM, OLE','Existem duas coisas que me deixam profundamente irritado na informática: Pessoas que fecham janelas usando o menu popup (ou o caminho Arquivo > Fechar) e pessoas que acham que toda DLL precisa ser registrada antes de ser usada. Este artigo é apenas para orientar os desavisados, porque pasme, já vi programadores experientes falando em registrar DLLs sem necessidade, seguindo e disseminando esse mito estúpido.',1,5999,'{}',1,'*','',''),(101,276,'XML Mapper: Convertendo um XML genérico em Data Packet','xml-mapper-convertendo-um-xml-generico-em-data-packet','<p style=\"text-align: justify;\">Então você recebe de um webservice um XML que representa um conjunto de dados e precisa exibir tais dados para o usuário de uma forma humanamente legível. Como você faria isso? Você pode usar <a href=\"index.php?option=com_content&amp;view=article&amp;id=132&amp;catid=80&amp;Itemid=493\" rel=\"alternate\">XPath</a> (ou XML Data Binding) para ler os nós (registros) em um laço e montar de forma livre uma visualização no Delphi, mas isso vai dar um bom trabalho. Prepare-se! E se eu te disser que existe uma forma de converter um XML genérico diretamente em algo que pode ser carregado por um TClientDataSet? Ficou curioso? Então este artigo é para você!</p>\r\n','\r\n<p style=\"text-align: justify;\">O XML Mapper é um utilitário capaz de gerar arquivos de <strong>Transformação XML</strong> (no caso do XML Mapper, arquivos de extensão .xtr). Um arquivo de transformação, como o próprio nome sugere, é um arquivo capaz de transformar, ou traduzir um XLM, gerando como resultado um outro arquivo XML com estrutura específica ou mesmo outro formato, como HTML ou texto plano. No caso do XML Mapper, o arquivo de transformação será responsável por converter um XML qualquer em um <strong>XML Data Packet</strong> que é compatível com o TClientDataSet. Em outras palavras, usando a transformação XML gerada pelo XML Mapper é possível transformar um XML genérico em um XML específico para uso direto no TClientDataSet!</p>\r\n<h2 style=\"text-align: center;\">Como gerar um arquivo de transformação XML</h2>\r\n<p style=\"text-align: justify;\">Utilizar o XML Mapper pode parecer difícil a primeira vista, entretanto é bem mais fácil do que você pensa. Na verdade o único requisito para uso sem maiores problemas é que você saiba interpretar exatamente o XML original. É como a tradução de um texto em outro idioma: não adianta você saber traduzir as palavras individualmente, você precisa entender de fato o que está escrito a fim de fazer uma tradução bem feita.</p>\r\n<p style=\"text-align: justify;\">Não pretendo neste artigo abordar todas as opções e possibilidades do XML Mapper. Cabe a você estudar o programa e descobrir todas as suas funcionalidades. O próprio XML Mapper possui um arquivo de ajuda facilmente acessível no seu menu Help. Não existe desculpa para não aprender.</p>\r\n<p style=\"text-align: justify;\">Para seguir o passo-a-passo de geração de um arquivo de Transformação XML, anexado a este artigo está um XML simples. Abaixo está uma amostra da estrutura geral do arquivo, com apenas um item:</p>\r\n<pre class=\"language-markup\"><code>&lt;Feriados&gt;\r\n &lt;item&gt;\r\n &lt;id&gt;638&lt;/id&gt;\r\n &lt;data&gt;2017-07-16T00:00:00-03:00&lt;/data&gt;\r\n &lt;descricao&gt;Dia da Padroeira Nossa Senhora do Carmo&lt;/descricao&gt;\r\n &lt;esfera&gt;M&lt;/esfera&gt;\r\n &lt;dataFixa&gt;S&lt;/dataFixa&gt;\r\n &lt;cidade&gt;\r\n &lt;id&gt;1&lt;/id&gt;\r\n &lt;nome&gt;Recife&lt;/nome&gt;\r\n &lt;uf&gt;PE&lt;/uf&gt;\r\n &lt;regiaoMetropolitana&gt;true&lt;/regiaoMetropolitana&gt;\r\n &lt;/cidade&gt;\r\n &lt;/item&gt;\r\n&lt;/Feriados&gt;</code></pre>\r\n<p>Como eu falei antes, é preciso entender o XML que se quer converter, por isso vou rapidamente explicar a estrutura do XML de exemplo: </p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">Este é um XML com os feriados do ano de 2017. O nó raiz é o nó <strong>&lt;Feriados&gt;</strong>, o qual contém vários nós de nome <strong>&lt;item&gt;</strong>. Cada um destes nós representa um feriado específico, logo, cada nó seria uma linha de nosso DataSet resultante. Cada linha, portanto, possui algumas colunas. No caso estas colunas são obtidas a partir dos nós <strong>&lt;id&gt;</strong>, <strong>&lt;data&gt;</strong>, <strong>&lt;descricao&gt;</strong>, <strong>&lt;esfera&gt;</strong>, <strong>&lt;dataFixa&gt;</strong> e <strong>&lt;cidade&gt;</strong>. O nó <strong>&lt;cidade&gt;</strong>, por sua vez, possui os subnós <strong>&lt;id&gt;</strong>, <strong>&lt;nome&gt;</strong>, <strong>&lt;uf&gt;</strong> e <strong>&lt;regiaoMetropolitana&gt;</strong>. O nó &lt;cidade&gt; é considerado no DataSet final como sendo um <strong>SubDataSet</strong> que é facilmente manipulado por qualquer TClientDataSet e pode ser renderizado em um segundo TDBGrid como um <strong>DataSet de detalhe</strong>! Quero ressaltar que todo XML a ser transformado precisa de um nó raiz. A ausência desse nó impossibilita a utilização do XML Mapper.</p>\r\n</blockquote>\r\n<div> </div>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Após o entendimento inicial da estrutura do XML de exemplo, vamos ao passo-a-passo para geração do arquivo de transformação XML:</p>\r\n<ol>\r\n<li style=\"text-align: justify;\">Abra o programa xmlmapper.exe, que está localizado na pasta bin do Delphi. A tela do XML Mapper é exibida a seguir:\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard01.png\" alt=\"\" width=\"100%\" /></p>\r\n</li>\r\n<li style=\"text-align: justify;\">Acesse o menu <strong>File &gt; Open</strong> e selecione o XML a ser processado. O XML será carregado na área da esquerda da tela (<strong>Document: Feriados.xml</strong>):\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard02.png\" alt=\"\" width=\"100%\" /></p>\r\nNote que a estrutura do XML é apresentada em forma de árvore.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Na estrutura do XML identifique os nós que representam sub-conjuntos de dados e, caso existam, selecione-os um a um e clique na aba <strong>Node Properties</strong> na parte de baixo da tela. No nosso exemplo apenas o nó &lt;cidade&gt; representa um SubDataSet, portanto, selecione-o e clique na aba Node Properties. Veja a imagem para maiores detalhes:\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard03.png\" alt=\"\" width=\"100%\" /></p>\r\nNa aba Node Properties para o nó  existe uma propriedade chamada <strong>Nested</strong> (aninhado), como este nó representa um SubDataSet, significa que seus dados (subnós) estão aninhados, logo, a propriedade Nested para o nó  precisa ser configurada como True. Note que até mesmo o ícone que representa este nó foi alterado para identificar visualmente que se trata de um nó que aninha subnós. Note que este ícone é igual ao ícone do nó  e, de fato, se você acessar as propriedades do nó , verá que ele tem a propriedade Nested = True!<br /><br /></li>\r\n<li style=\"text-align: justify;\">Aproveitando que a aba Node Properties está ativa, é hora de configurar os nós que você deseja mapear. A configuração básica consiste em informar o tipo de dado que cada nó precisa ter quando for convertido em TField de um TClientDataSet. Abaixo está o exemplo de seleção de tipo para o nó :\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard04.png\" alt=\"\" width=\"100%\" /></p>\r\nEste nó contém uma data logo, sua propriedade <strong>DataType</strong> é configurada como Date. Note também que, diferentemente do nó \"aninhador\" , existem várias propriedades disponíveis. Nós de dados realmente possuem mais opções as quais eu não vou explicar aqui. Por ora apenas a propriedade DataType precisa ser alterada. Outras propriedades podem se manter como estiverem.<br /><br />Repita este passo para todos os nós que você deseja mapear, alterando sua propriedade Data Type para corresponder ao tipo de dado correto após a transformação.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Clique novamente na aba Mapping a fim de exibir o mapeamento, o qual você vai definir agora. Você deve executar um duplo clique em cada nó que você deseja transformar em TField. Selecione todos os nós aplicáveis, incluindo os nós aninhados em &lt;cidade&gt;:\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard05.png\" alt=\"\" width=\"100%\" /></p>\r\nNa parte de cima da tela estão nós que selecionamos e que serão mapeados para campos (TFields) no DataSet final. Claro que você poderia ignorar completamente a transformação de nós aninhados em &lt;cidade&gt;, mas para manter o artigo abrangente eu considero que neste exemplo você deseja transformar todos os nós disponíveis. As opções que foram destacadas (parte de baixo da tela) são aquelas que precisam estar selecionadas para que a transformação funcione como queremos.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Clique com o botão direito do mouse em uma área vazia na parte da tela que mostra a estrutura do seu XML e nom menu popup selecione Create DataPacket from XML:\r\n<p align=\"center\"><img src=\"images/add2del/artigos/ID000101/Clipboard06.png\" alt=\"\" /></p>\r\nAo clicar nesta opção o mapeamento será criado e a tela do XML Mapper vai refletir esta criação:\r\n<p><img src=\"images/add2del/artigos/ID000101/Clipboard07.png\" width=\"100%\" /></p>\r\nNeste momento nenhum arquivo de transformação foi salvo. Ele ainda está na memória e para provar que a transformação está funcionando como deve, clique no botão <strong>Create and Test Transformation</strong>. A tela abaixo vai aparecer:\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard08.png\" /></p>\r\nEsta tela mostra a visualização em um grid dos dados que estão no XML original, utilizando um arquivo de transformação XML na memória! Perceba que a coluna cidade é diferente; ela representa um SubDataSet. Clicando no botão de reticências vai exibir um outro grid com os registros deste SubDataSet. No nosso XML de exemplo, existem apenas 2 registros que contém dados no SubDataSet, eles se encontram no final do grid. Veja abaixo a exibição dos subregistros:\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard09.png\" /></p>\r\nVocê pode inclusive navegar por entre os registros e perceber que o comportamento é de um relacionamento Mestre/Detalhe, ou seja, ao selecionar os registros <strong>638</strong> e <strong>639</strong> o grid que contém o SubDataSet vai mostrar os registros de detalhe!<br /><br /></li>\r\n<li style=\"text-align: justify;\">Salve o arquivo de transformação. Para fazer isso, clique com o botão direito do mouse numa área vazia da parte central da tela do XML Mapper e, no popup, clique no item <strong>Save Transformation</strong>:\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard10.png\" /></p>\r\nEscolha um nome de arquivo e salve o arquivo .xtr em um local pertinente. Eu recomendo usar o padrão sugerido (<strong>ToDp.xtr</strong>), que significa <strong>To DataPacket</strong>, indicando que trata-se de um arquivo de transformação usado para converter <strong>para um DataPacket</strong>.<br /><br /></li>\r\n<li style=\"text-align: justify;\">Salve o XML de definição dos campos. Este XML é um DataPacket sem dados, apenas com a estrutura. Ele será necessário para a criação dos campos persistentes. Para salvar este DataPacket, clique com o botão direito do mouse numa área vazia da parte direita da tela do XML Mapper e, no popup, clique no item <strong>Save DataPacket</strong>:\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard11.png\" /></p>\r\nEscolha um nome de arquivo e salve o arquivo .xml em um local pertinente. Eu recomendo salvar este arquivo com o mesmo nome do arquivo xml original, acrescido do sufixo DP (<strong>Feriados2017DP.xml</strong>)</li>\r\n</ol>\r\n<p>Após executar estes 8 passos, você concluiu a criação e o teste do arquivo de Transformação XML. Agora vamos aprender a usar este arquivo no Delphi :)</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: center;\">Como utilizar um arquivo de transformação XML</h2>\r\n<p style=\"text-align: justify;\">Como exemplo de utilização do arquivo de transformação vamos supor que precisemos exibir os dados contidos no arquivo XML em um programa Delphi. Como nosso conjunto de dados resultante contém um relacionamento mestre/detalhe, o exemplo será composto de dois TDBGrid e um botão que fará o carregamento.</p>\r\n<p style=\"text-align: justify;\">Para começar, crie uma aplicação VCL vazia, e inclua no TForm os dois TDBGrid, dois TClientDataSet, dois TDataSource e um TButton. A tela em tempo de desenvolvimento deve ficar assim:</p>\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard12.png\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\">Renomeie os dois TDBGrid de forma que o de cima seja DBGRMestre e o de baixo seja DBGRDetalhe. Renomeie o botão como BUTNCarregar. Ligue os componentes normalmente: <strong>TDBGrid + TDataSource +</strong><strong> TClientDataSet</strong>. Clique com o botão direito do mouse em CLDSMestre, selecione a opção <strong>Load from MyBase table...</strong> e carregue o arquivo de definição (<strong>Feriados2017DP.xml</strong>). Nesse momento o TClientDataSet será aberto (Active = true), mas não conterá qualquer registro, porque o XML carregado contém apenas a definição dos campos.</p>\r\n<p style=\"text-align: justify;\">O próximo passo é executar um duplo clique neste mesmo TClientDataSet (CLDSMestre) para exibir o <strong>Fields Editor</strong> o qual estará vazio. Clique com o botão direito na área vazia do Fields Editor e selecione a opção Add all fields. Neste momento todos os campos persistentes serão criados, incluindo o campo especial cidade, do tipo TDataSetField:</p>\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard13.png\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\">Agora selecione o segundo TClientDataSet (<strong>CLDSDetalhe</strong>), e configure sua propriedade <strong>DataSetField</strong> de forma que ele seja o campo cidade de CLDSMestre. Se você criou os campos automaticamente e não renomeou nenhum deles, a única opção disponível para escolha será <strong>CLDSMestrecidade</strong>, que é o campo persistente <strong>cidade</strong> de <strong>CLDSMestre</strong>.</p>\r\n<p style=\"text-align: justify;\">Ao realizar a configuração da propriedade DataSetField em CLDSDetalhe, ele será automaticamente aberto. Neste momento você já deve ter notado que, em tempo de desenvolvimento, os TDBGrid já mostram as colunas tanto do CLDSMestre, quanto do CLDSDetalhe:</p>\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard14.png\" alt=\"\" /></p>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Apesar de isso parecer bom, vamos fechar os TClientDataSet pois é uma boa prática manter todos os DataSets sempre fechados. Para fazer isso, basta fechar CLDSMestre, pois CLDSDetalhe faz parte de CLDSMestre. Ao fazer isso as colunas dos dois TDBGrids vão sumir e isso é natural, pois elas estavam sendo criadas dinamicamente após a abertura dos TClientDataSets. Para manter as colunas visíveis mesmo após o fechamento dos TClientDataSets, execute um duplo clique em cada TDBGrid a fim de exibir o <strong>Columns editor</strong> e nele, clique no botão Add All Fields. Veja a figura abaixo, onde o botão Add All Fields encontra-se destacado e as colunas estão criadas:</p>\r\n<p style=\"text-align: center;\"><img src=\"images/add2del/artigos/ID000101/Clipboard15.png\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\">Agora é hora de criar o código que faz a mágica acontecer. Coloque os arquivos xml e xtr na mesma pasta onde está sendo gerado seu executável. O arquivo XML é o arquivo original o qual você quer carregar (feriados2017.xml) e o arquivo XTR é o arquivo de transformação XML que você criou na seção anterior.</p>\r\n<p style=\"text-align: justify;\">Todo o código será posto no evento OnClick do botão BTNCarregar. Segue o código completo:</p>\r\n<pre id=\"transform\" class=\"line-numbers language-pascal\"><code>procedure TForm1.BUTNCarregarClick(Sender: TObject);\r\nvar\r\n XMLTransform: TXMLTransform;\r\nbegin\r\n XMLTransform := TXMLTransform.Create(Self);\r\n try\r\n XMLTransform.SourceXmlFile := ExtractFilePath(ParamStr(0)) + \'Feriados2017.xml\';\r\n XMLTransform.TransformationFile := ExtractFilePath(ParamStr(0)) + \'ToDp.xtr\';\r\n CLDSMestre.XMLData := XMLTransform.Data;\r\n finally\r\n XMLTransform.Free;\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Este código que já é minúsculo ficaria ainda menor se eu tivesse usado o componente TXMLTransform de forma visual. Eu decidi criá-lo dinamicamente apenas para que vocês entendam melhor o que ele faz. Na <a href=\"#transform.5\" rel=\"alternate\">linha 5</a> instanciamos o componente de transformação. Na <a href=\"#transform.7\" rel=\"alternate\">linha 7</a> informamos ao componente qual o XML que será transformado. Na <a href=\"#transform.8\" rel=\"alternate\">linha 8</a> informamos ao componente qual é o arquivo de transformação XML. Na <a href=\"#transform.9\" rel=\"alternate\">linha 9</a> nós atribuímos o valor da propriedade Data do componente de transformação à propriedade XMLData do Client DataSet mestre. Esta linha faz duas coisas ao mesmo tempo. Primeiramente, ao ler o valor da propriedade Data, automaticamente é feita a transformação do XML original e o valor da propriedade Data é um XML DataPacket correspondente. Em segundo lugar, ao atribuir esse valor à propriedade XMLData do Client DataSet o mesmo é automaticamente aberto (Active = true). A <a href=\"#transform.11\" rel=\"alternate\">linha 11</a>, finalmente, destrói o componente de transformação, que não é mais necessário.</p>\r\n<h2 style=\"text-align: center;\">Onde está o componente TXMLTransform?</h2>\r\n<p style=\"text-align: justify;\">Como eu disse anteriormente eu decidi não usar o componente TXMLTransform, mas mesmo assim eu fui conferir suas propriedades e não o encontrei na paleta de componentes. Eu tinha certeza que ele existia e por isso fiz uma busca e descobri que o pacote que faz este e outros componentes para manipulação de XML aparecerem não estava registrado na IDE. Estou usando Delphi XE5 e não sei porque ele estava assim, mas a solução foi muito simples. Acessei <strong>Components &gt; Install Packages</strong> na IDE, cliquei o botão <strong>Add...</strong> e selecionei o BPL <strong>dclwbm190.bpl</strong> que registrou o pacote <strong>Embarcadero InternetExpress Components</strong>, o qual contém o componente :)</p>\r\n<p style=\"text-align: justify;\">Se seu Delphi não for o XE5 e você não estiver achando este componente, procure pelo BPL adequado trocando o número pelo correspondente para seu Delphi. Se você não sabe qual é o número que corresponde ao seu Delphi, eu recomendo o artigo <a href=\"index.php?option=com_content&amp;view=article&amp;id=127&amp;catid=80&amp;Itemid=493\">Diretivas de compilação e versões do Delphi</a>. Nele, há uma tabela em cuja coluna <strong>Library Suffix / Package Version</strong> estão os números das versões dos pacotes. Use-a para identificar a versão correta para seu Delphi e assim buscar o BPL correto.</p>\r\n<h2 style=\"text-align: center;\">O caminho oposto...</h2>\r\n<p style=\"text-align: justify;\">Se você analisou bem o XML Mapper enquanto o usava, deve ter se perguntado ou desconfiado se não seria possível transformar os dados de um DataPacket em um XML qualquer e a resposta, claro, é sim! Isso não será abordado aqui, mas fique sabendo que com um pouco de dedicação é perfeitamente possível fazer algo que, por exemplo, receba o resultado de um WebService, liste-o em um TDBGrid e, posteriormente envie esse resultado de volta, modificado, ao WebService. É claro que isso dá um pouco de trabalho, mas é perfeitamente viável!</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-09-06 21:01:15',24,'','2020-07-10 20:57:30',24,0,'0000-00-00 00:00:00','2017-07-29 21:06:50','0000-00-00 00:00:00','{\"image_intro\":\"\",\"float_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000101\\/FullArticle.png\",\"float_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"article_layout\":\"\",\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_associations\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_page_title\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',49,85,'Delphi, Addicted 2 Delphi, DataPacket, XML, XML Mapper, TClientDataSet, dclwbm190.bpl, dclwbm, Embarcadero InternetExpress Components','Então você recebe de um webservice um XML que representa um conjunto de dados e precisa exibir tais dados para o usuário de uma forma humanamente legível. Como você faria isso? Você pode usar XPath (ou XML Data Binding) para ler os nós (registros) em um laço e montar de forma livre uma visualização no Delphi, mas isso vai dar um bom trabalho. Prepare-se! E se eu te disser que existe uma forma de converter um XML genérico diretamente em algo que pode ser carregado por um TClientDataSet? Ficou curioso? Então este artigo é para você!',1,8140,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(102,284,'Como usar corretamente uma barra de progresso (TProgressBar)?','como-usar-corretamente-uma-barra-de-progresso','<p style=\"text-align: justify;\">Chutando por baixo, acredito que 90% dos programadores usam o componente TProgressBar de forma errada. At&#233; mesmo eu o usei de forma errada porque a forma correta &#233; trabalhosa. Mesmo assim eu acredito que vale muito a pena conhecer o modo correto de se trabalhar com esse componente e caso seu programa fa&#231;a uso constante dele, porque n&#227;o criar uma classe que facilita a implementa&#231;&#227;o correta? &#201; isso que pretendo mostrar neste artigo.</p>\r\n','\r\n<p style=\"text-align: justify;\">Quando comecei a programar, uma das coisas mais legais e que me chamavam sempre a aten&#231;&#227;o eram as barras de progresso. Eu n&#227;o sei porque, mas eu sempre olhava a barrinha enchendo e achava muito engenhoso. No in&#237;cio, eu queria porque queria, que meus projetos utilizassem aquilo e cheguei at&#233; mesmo a utilizar uma barra de progresso na inicializa&#231;&#227;o de meus programas, na tela de <em>splash</em>, para indicar o progresso do carregamento de cada um dos TForm que eram criados automaticamente. Aboli este uso quando descobri que n&#227;o era correto carregar todos os TForm na inicializa&#231;&#227;o e foi a&#237; que eu entendi que uma barra de progresso s&#243; faz sentido quando ela &#233; realmente necess&#225;ria, ou seja, n&#227;o adianta for&#231;ar seu uso apenas para tornar seu programa mais legal de alguma forma.</p>\r\n<p style=\"text-align: justify;\">Use uma barra de progresso APENAS quando seu programa precisar indicar ao usu&#225;rio o andamento de uma tarefa realmente demorada <span style=\"text-decoration: underline;\">da qual voc&#234; conhe&#231;a o evento no qual o processamento termina</span>. Este \"evento\" pode ser qualquer coisa que seja representada por um n&#250;mero.&#160;<strong>O processamento dos bytes de um arquivo</strong>&#160;<span style=\"text-decoration: underline;\">de tamanho conhecido</span>, <strong>o processamento de arquivos num diret&#243;rio</strong> <span style=\"text-decoration: underline;\">quando voc&#234; previamente sabe a quantidade de arquivos</span>, <strong>a valida&#231;&#227;o de um arquivo XML com um arquivo XSD</strong>, <span style=\"text-decoration: underline;\">desde que voc&#234; obtenha previamente a quantidade total de n&#243;s dentro do XML</span>,&#160;etc., s&#227;o exemplos de processamento onde uma barra de progresso pode ser usada. Sua utiliza&#231;&#227;o &#233; v&#225;lida tamb&#233;m quando voc&#234; n&#227;o conhece o evento final, mas tem meios de consegu&#237;-lo de forma muito r&#225;pida, por exemplo, &#233; poss&#237;vel contar de forma relativamente r&#225;pida a quantidade de arquivos dentro de uma estrutura de diret&#243;rios, dada uma raiz inicial, recursivamente ou mesmo a quantidade total de n&#243;s dentro de um arquivo XML, usando XPATH. O exemplo anexado a este artigo, o qual vou explicar passo-a-passo, faz uso da contagem pr&#233;via de arquivos dentro de uma estrutura de diret&#243;rios recusivamente, e em um teste ele contou 300.000 arquivos em pouco menos de 10 segundos.</p>\r\n<p style=\"text-align: justify;\">A regra b&#225;sica &#233;: se voc&#234; <strong>n&#227;o tiver</strong>&#160;condi&#231;&#245;es de saber o evento no qual o processamento termina <strong>antes&#160;do processamento come&#231;ar</strong>&#160;ou <strong>se a obten&#231;&#227;o deste evento for muito complexa ou demorada</strong>, ent&#227;o uma barra de progresso n&#227;o se aplica e voc&#234; deve informar ao usu&#225;rio que algo est&#225; acontecendo, mas que n&#227;o tem meios de dizer quando vai acabar. Normalmente nesse caso, se usa uma anima&#231;&#227;o qualquer para indicar que algo est&#225; sendo feito em segundo plano.</p>\r\n<p style=\"text-align: justify;\">A seguir vou come&#231;ar a explicar como converter uma rotina que realiza um processamento lento para que ela possa ser usada com uma barra de progresso da forma correta. Quero salientar que todos os procedimentos que eu vou explicar foram criados por mim para diminuir a complexidade dessa convers&#227;o e que existem outros meios de se fazer a mesma coisa.&#160;Por exemplo, aqui eu recomendo que as rotinas demoradas sejam agrupadas em um m&#233;todo simples que faz todo o processamento, mas isso n&#227;o &#233; requerido, apenas escolhi esse meio porque <strong>EU</strong> achei mais f&#225;cil. O importante &#233; entender o que est&#225; sendo feito e seguir minha recomenda&#231;&#227;o ou criar seu pr&#243;prio modo de fazer a mesma coisa. Fica a seu crit&#233;rio, caro leitor.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">Uma thread, claro!</h2>\r\n<p style=\"text-align: justify;\">N&#227;o existe m&#225;gica alguma, quando eu falei que era mais complexo usar uma barra de progresso da forma correta, era disso que eu estava falando: <strong>processos demorados devem ser postos em uma thread</strong>. N&#227;o s&#227;o todos que tem paci&#234;ncia ou mesmo conhecimento para&#160;criar threads da forma correta, quanto mais uma apenas para fazer funcionar uma simples barra de progresso. Muitos de n&#243;s, eu me inclu&#237;a neste meio, preferimos usar <em>Application.ProcessMessages</em> e obter o mesmo efeito, contudo, esta sensa&#231;&#227;o de que est&#225; tudo bem, &#233; falsa! O uso indiscriminado de <em>ProcessMessages</em> pode causar problemas&#160;dif&#237;ceis de debugar, access violations inesperados e outros tipos de comportamentos bizarros em programas mais complexos. J&#225; tive problemas em um programa que fazia uso de FTP ass&#237;ncrono e s&#243; depois de muito penar, descobri que ele era causado pelos <em>ProcessMessages</em>. Resolvi todos os problemas passando a usar threads. No artigo <a href=\"index.php?option=com_content&amp;view=article&amp;id=103&amp;catid=80&amp;Itemid=493\">O lado negro do Application.ProcessMessages</a>, s&#227;o apresentados alguns motivos para evitar seu uso indiscriminado.</p>\r\n<p style=\"text-align: justify;\">Eu falei no&#160;par&#225;grafo anterior que eu me incu&#237;a no rol de pessoas que usam ProcessMessages, mas ao escrever este artigo eu bolei uma forma mais simples de implementar de forma correta o uso de&#160;barras de progresso e por isso, vou passar a usar sempre. Eu s&#243; tenho a ganhar e voc&#234; tamb&#233;m, caro leitor, caso entenda como tudo foi feito e tenha um pouco menos de pregui&#231;a ;) Abaixo eu lhes apresento uma unit com uma classe que configura uma thread b&#225;sica e introduz alguns eventos, propriedades e m&#233;todos que v&#227;o ser de grande ajuda para fazer tudo funcionar como um rel&#243;gio:</p>\r\n<pre id=\"UProgressThread\" class=\"line-numbers language-pascal\"><code>unit UProgressThread;\r\n\r\ninterface\r\n\r\nuses\r\n Classes;\r\n\r\ntype\r\n TOnProgress = procedure (const PText: String; const PNumber: Cardinal) of object;\r\n TOnMax = procedure (const PMax: Int64) of object;\r\n\r\n TProgressThread = class (TThread)\r\n private\r\n FText: String;\r\n FNumber: Cardinal;\r\n FOnProgress: TOnProgress;\r\n FMax: Int64;\r\n FOnMax: TOnMax;\r\n procedure CallOnProgress;\r\n procedure CallOnMax;\r\n protected\r\n procedure DoProgress;\r\n procedure DoMax;\r\n property Text: String read FText write FText;\r\n property Number: Cardinal read FNumber write FNumber;\r\n property Max: Int64 read FMax write FMax;\r\n public\r\n constructor Create; reintroduce;\r\n property OnProgress: TOnProgress read FOnProgress write FOnProgress;\r\n property OnMax: TOnMax read FOnMax write FOnMax;\r\n end;\r\n\r\nimplementation\r\n\r\n{ TProgressBarThread }\r\n\r\nprocedure TProgressThread.CallOnMax;\r\nbegin\r\n if Assigned(FOnMax) then\r\n FOnMax(FMax);\r\nend;\r\n\r\nprocedure TProgressThread.CallOnProgress;\r\nbegin\r\n if Assigned(FOnProgress) then\r\n FOnProgress(FText,FNumber);\r\nend;\r\n\r\nprocedure TProgressThread.DoMax;\r\nbegin\r\n if Assigned(FOnMax) then\r\n Synchronize(CallOnMax);\r\nend;\r\n\r\nprocedure TProgressThread.DoProgress;\r\nbegin\r\n if Assigned(FOnProgress) then\r\n Synchronize(CallOnProgress);\r\nend;\r\n\r\nconstructor TProgressThread.Create;\r\nbegin\r\n inherited Create(True);\r\n FreeOnTerminate := True;\r\nend;\r\n\r\nend.</code></pre>\r\n<p style=\"text-align: justify;\">A classe <strong>TProgressThread </strong>&#233; simplesmente uma descendente de <strong>TThread</strong>&#160;(linha <a href=\"#UProgressThread.12\" rel=\"alternate\">12</a>) que cria uma thread em estado suspenso (linha <a href=\"#UProgressThread.63\" rel=\"alternate\">63</a>) por padr&#227;o e instrui a mesma a ser liberada da mem&#243;ria automaticamente (linha <a href=\"#UProgressThread.64\" rel=\"alternate\">64</a>). Dessa forma, basta fazer <strong>TProgressThread.Create</strong> e automaticamente &#160;a thread &#233; criada em modo suspenso e ser&#225; liberada da mem&#243;ria t&#227;o logo ela termine. Esta classe exp&#245;e dois eventos essenciais nesta implementa&#231;&#227;o: <strong>OnProgress</strong> e <strong>OnMax</strong> (linhas <a href=\"#UProgressThread.29\" rel=\"alternate\">29</a> e <a href=\"#UProgressThread.30\" rel=\"alternate\">30</a>). O primeiro &#233; executado a cada itera&#231;&#227;o do processo demorado e o segundo &#233; executado quando h&#225; a necessidade de contagem pr&#233;via da quantidade total de itera&#231;&#245;es, permitindo a configura&#231;&#227;o da barra de progresso antes do in&#237;cio do processamento. As propriedades <strong>Text</strong>, <strong>Number</strong> e <strong>Max</strong> (linhas <a href=\"#UProgressThread.24\" rel=\"alternate\">24</a>, <a href=\"#UProgressThread.25\" rel=\"alternate\">25 </a>e <a href=\"#UProgressThread.26\" rel=\"alternate\">26</a>) s&#227;o retornadas&#160;pelos eventos OnProgress e OnMax. Os m&#233;todos <strong>DoProgress</strong> e <strong>DoMax</strong> (linhas <a href=\"#UProgressThread.22\" rel=\"alternate\">22 </a>e <a href=\"#UProgressThread.23\" rel=\"alternate\">23</a>) s&#227;o m&#233;todos que, ao serem executados, executam os eventos correspondentes.</p>\r\n<p style=\"text-align: justify;\">Esta classe n&#227;o foi feita para ser usada diretamente, ela precisa ser estendida para cada rotina demorada que precisa habilitar barras de progresso. Eu sei que ainda est&#225; nebuloso at&#233; aqui, mas continue lendo, no final tudo ficar&#225; claro.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">Agrupar &#233; preciso</h2>\r\n<p style=\"text-align: justify;\">Se voc&#234; j&#225; tem um projeto que, em algum ponto, realiza algum processamento demorado o primeiro passo &#233; pegar este processamento e coloc&#225;-lo dentro de um m&#233;todo (function ou procedure) adaptado para que o mesmo, sozinho, realize todo o processamento. Foi exatamente isso que foi feito com uma rotina que obt&#233;m o tamanho de todos os arquivos dentro de uma estrutura de diret&#243;rios recursivamente. &#201; uma fun&#231;&#227;o simples, com um par&#226;metro para passar o diret&#243;rio inicial e que, ao final, retorna o valor dos tamanhos de todos os arquivos encontrados somados. Veja como ficou:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function DirectoryTreeSize(PInitialDir: String): Int64;\r\nvar\r\n SearchRecord: TSearchRec;\r\nbegin\r\n Result := 0;\r\n\r\n if FindFirst(PInitialDir + \'*.*\', faAnyFile, SearchRecord) = 0 then\r\n try\r\n repeat\r\n if ((SearchRecord.Attr and faDirectory) = faDirectory) then\r\n begin\r\n if (SearchRecord.Name &lt;&gt; \'.\') and (SearchRecord.Name &lt;&gt; \'..\') then\r\n Inc(Result,DirectoryTreeSize(PInitialDir + SearchRecord.Name + \'\\\' + ExtractFileName(PInitialDir)));\r\n end\r\n else\r\n Inc(Result,FileSize(PInitialDir + SearchRecord.Name));\r\n until FindNext(SearchRecord) &lt;&gt; 0;\r\n finally\r\n FindClose(SearchRecord)\r\n end;\r\nend;\r\n</code></pre>\r\n<p style=\"text-align: justify;\">Esta fun&#231;&#227;o &#233; bem demorada, porque ela usa um m&#233;todo redundante&#160;para obter o tamanho de um arquivo. Este&#160;m&#233;todo &#233; redundante porque o tamanho dos arquivos j&#225; poderia ser obtido instantaneamente lendo <strong>SearchRecord.FileSize</strong>. Utilizei uma fun&#231;&#227;o para leitura gen&#233;rica do tamanho de um arquivo apenas para desacelerar o processo de forma a fazer sentido o uso de uma barra de progresso. &#160;A fun&#231;&#227;o FileSize, para leitura gen&#233;rica do tamanho de um arquivo, &#233; definida como segue:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function FileSize(PFileName: TFileName): Cardinal;\r\nvar\r\n FileHandle: THandle;\r\nbegin\r\n FileHandle := CreateFile(PChar(PFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);\r\n try\r\n Result := GetFileSize(FileHandle, nil);\r\n finally\r\n CloseHandle(FileHandle);\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Como foi dito anteriormente, a fun&#231;&#227;o&#160;DirectoryTreeSize percorre recursivamente uma estrutura de diret&#243;rios e l&#234; o tamanho de cada arquivo encontrado. N&#227;o h&#225; como saber quantos arquivos existem dentro de um diret&#243;rio recursivamente, logo, a &#250;nica solu&#231;&#227;o &#233; varrer a mesma estrutura e simplesmente contar cada arquivo. Isso parece est&#250;pido, pois vamos acabar percorrendo a mesma estrutura de diret&#243;rios duas vezes, uma para obter a quantidade de arquivos e a outra exatamente igual, para process&#225;-los, mas a varredura para contar os arquivos &#233; extremamente r&#225;pida, pelo menos &#233; MUITO MAIS R&#193;PIDA que a obten&#231;&#227;o do tamanho de cada arquivo e sendo assim esse procedimento &#233; v&#225;lido para este exemplo. Abaixo est&#225; a fun&#231;&#227;o que retorna o total de arquivos a processar dentro da estrutura de diret&#243;rios:</p>\r\n<pre class=\"line-numbers language-pascal\"><code>function TDirectoryTreeSize.DirectoryTreeFileCount(PInitialDir: String): Cardinal;\r\nvar\r\n SearchRecord: TSearchRec;\r\nbegin\r\n Result := 0;\r\n\r\n if FindFirst(PInitialDir + \'*.*\', faAnyFile, SearchRecord) = 0 then\r\n try\r\n repeat\r\n if ((SearchRecord.Attr and faDirectory) = faDirectory) then\r\n begin\r\n if (SearchRecord.Name &lt;&gt; \'.\') and (SearchRecord.Name &lt;&gt; \'..\') then\r\n Inc(Result,DirectoryTreeFileCount(PInitialDir + SearchRecord.Name + \'\\\' + ExtractFileName(PInitialDir)));\r\n end\r\n else\r\n Inc(Result);\r\n until FindNext(SearchRecord) &lt;&gt; 0;\r\n finally\r\n FindClose(SearchRecord)\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Note que a fun&#231;&#227;o&#160;<strong>DirectoryTreeFileCount</strong> &#233; praticamente igual &#224; fun&#231;&#227;o <strong>DirectoryTreeSize</strong>. Isso era esperado neste caso, j&#225; que precisamos passar pelos arquivos que ser&#227;o processados, mas apenas precisamos cont&#225;-los.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">Estendendo a classe&#160;TProgressThread</h2>\r\n<p style=\"text-align: justify;\">Agora que temos o procedimento demorado isolado em uma fun&#231;&#227;o, e temos uma segunda fun&#231;&#227;o que nos dar&#225; de forma r&#225;pida a quantidade de elementos que ser&#227;o processados, podemos adapt&#225;-las dentro de uma classe filha da classe TProgressThread. O nome da classe e o nome da unit que a cont&#233;m eu convenciono como sendo o mesmo nome da fun&#231;&#227;o original, logo, a classe se chama <strong>TDirectoryTreeSize</strong> e sua unit <strong>UDirectoryTreeSize</strong>. A implementa&#231;&#227;o completa voc&#234; v&#234; abaixo:</p>\r\n<pre id=\"udirectorytreesize\" class=\"line-numbers language-pascal\"><code>unit UDirectoryTreeSize;\r\n\r\ninterface\r\n\r\nuses\r\n UProgressThread;\r\n\r\ntype\r\n TDirectoryTreeSize = class (TProgressThread)\r\n private\r\n FInitialDir: String;\r\n FResult: Int64;\r\n function DirectoryTreeSize(PInitialDir: String): Int64;\r\n function DirectoryTreeFileCount(PInitialDir: String): Cardinal;\r\n public\r\n procedure Execute; override;\r\n property InitialDir: String write FInitialDir;\r\n property Result: Int64 read FResult;\r\n end;\r\n\r\nimplementation\r\n\r\nuses\r\n Windows, SysUtils;\r\n\r\nfunction FileSize(PFileName: TFileName): Cardinal;\r\nvar\r\n FileHandle: THandle;\r\nbegin\r\n FileHandle := CreateFile(PChar(PFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);\r\n try\r\n Result := GetFileSize(FileHandle, nil);\r\n finally\r\n CloseHandle(FileHandle);\r\n end;\r\nend;\r\n\r\n{ TDirectoryTreeSize }\r\n\r\nfunction TDirectoryTreeSize.DirectoryTreeFileCount(PInitialDir: String): Cardinal;\r\nvar\r\n SearchRecord: TSearchRec;\r\nbegin\r\n Result := 0;\r\n\r\n if FindFirst(PInitialDir + \'*.*\', faAnyFile, SearchRecord) = 0 then\r\n try\r\n repeat\r\n if ((SearchRecord.Attr and faDirectory) = faDirectory) then\r\n begin\r\n if (SearchRecord.Name &lt;&gt; \'.\') and (SearchRecord.Name &lt;&gt; \'..\') then\r\n Inc(Result,DirectoryTreeFileCount(PInitialDir + SearchRecord.Name + \'\\\' + ExtractFileName(PInitialDir)));\r\n end\r\n else\r\n Inc(Result);\r\n until FindNext(SearchRecord) &lt;&gt; 0;\r\n finally\r\n FindClose(SearchRecord)\r\n end;\r\nend;\r\n\r\nfunction TDirectoryTreeSize.DirectoryTreeSize(PInitialDir: String): Int64;\r\nvar\r\n SearchRecord: TSearchRec;\r\nbegin\r\n Result := 0;\r\n\r\n if FindFirst(PInitialDir + \'*.*\', faAnyFile, SearchRecord) = 0 then\r\n try\r\n repeat\r\n if ((SearchRecord.Attr and faDirectory) = faDirectory) then\r\n begin\r\n if (SearchRecord.Name &lt;&gt; \'.\') and (SearchRecord.Name &lt;&gt; \'..\') then\r\n Inc(Result,DirectoryTreeSize(PInitialDir + SearchRecord.Name + \'\\\' + ExtractFileName(PInitialDir)));\r\n end\r\n else\r\n begin\r\n Text := SearchRecord.Name;\r\n Number := FileSize(PInitialDir + Text);\r\n DoProgress;\r\n Inc(Result,Number);\r\n end;\r\n until FindNext(SearchRecord) &lt;&gt; 0;\r\n finally\r\n FindClose(SearchRecord)\r\n end;\r\nend;\r\n\r\nprocedure TDirectoryTreeSize.Execute;\r\nbegin\r\n inherited;\r\n Max := DirectoryTreeFileCount(FInitialDir);\r\n DoMax;\r\n FResult := DirectoryTreeSize(FInitialDir);\r\nend;\r\n\r\nend.</code></pre>\r\n<p style=\"text-align: justify;\">Calma, calma, n&#227;o entre em p&#226;nico!&#160;Eu vou explicar tudo o que foi feito nesta unit da maneira mais simples e direta quanto for poss&#237;vel.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">Como TDirectoryTreeSize foi implementada?&#160;(E como criar a sua pr&#243;pria classe)&#160;</h2>\r\n<p style=\"text-align: justify;\">Anteriormente eu falei que seria necess&#225;rio agrupar em um m&#233;todo (function ou procedure) todo o processamento demorado, portanto estou considerando que voc&#234; j&#225; fez isso. Siga os passos a seguir e olhe com cuidado a classe TDirectoryTreeSize. Use os links nos n&#250;meros das linhas para pular para o ponto exato no c&#243;digo da classe acima.</p>\r\n<ol>\r\n<li style=\"text-align: justify;\"><strong>Declare na se&#231;&#227;o private o m&#233;todo que &#233; o respons&#225;vel por gerar o processamento demorado</strong>, doravante chamado simplesmente de <strong>MD</strong> (M&#233;todo Demorado). No nosso exemplo, este m&#233;todo &#233; o <strong>DirectoryTreeSize</strong>, o qual pode ser visto declarado na linha <a href=\"#udirectorytreesize.13\" rel=\"alternate\">13</a>. A linha <a href=\"#udirectorytreesize.14\" rel=\"alternate\">14</a> mostra a declara&#231;&#227;o de nosso m&#233;todo&#160;adicional (doravante chamado simplesmente de <strong>MA</strong>) que tem o objetivo de contar a quantidade de elementos que ser&#227;o processados (<strong>DirectoryTreeFileCount</strong>). Ainda na&#160;se&#231;&#227;o private declare quaisquer outros m&#233;todos adicionais (<strong>MAs</strong>) que ser&#227;o necess&#225;rios para que o MD possa funcionar. Use a classe como voc&#234; faria com qualquer classe comum, declarando todos os m&#233;todos como privados. N&#227;o use vari&#225;veis globais ou locais na unit UDirectoryTreeSize. Caso precise de vari&#225;veis, use campos da classe e todos eles tamb&#233;m privados e com propriedades p&#250;blicas correspondentes. Se voc&#234; j&#225; criou uma classe em sua vida, vai notar que nada disso &#233; novo ou especial;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Altere a defini&#231;&#227;o do seu MD, de forma a incluir nele o m&#233;todo DoProgress</strong>, o qual gera o evento <strong>OnProgress</strong>&#160;no qual o <strong>TProgressBar</strong> pode ser atualizado&#160;na aplica&#231;&#227;o. O local exato da coloca&#231;&#227;o do DoProgress depende da sua implementa&#231;&#227;o. Normalmente ele deve ser posto dentro de um&#160;loop que vai \"rodar\" na mesma quantidade de vezes que o n&#250;mero de itera&#231;&#245;es informado, conhecido ou, no caso do nosso exemplo, obtido pelo MA de contagem (linha <a href=\"#udirectorytreesize.92\" rel=\"alternate\">92</a>). As linha <a href=\"#udirectorytreesize.78-80\" rel=\"alternate\">78 a 80</a>, mostram como deve ser feita&#160;a implementa&#231;&#227;o do m&#233;todo DoProgress. O evento OnProgress tem dois par&#226;metros, um par&#226;metro <strong>PText</strong> do tipo String e outro par&#226;metro <strong>PNumber</strong> do tipo&#160;Cardinal (DWord). Toda vez que o evento OnProgress &#233; ativado sua aplica&#231;&#227;o pode ler os valores de PText e PNumber a fim de atualizar um TLabel com informa&#231;&#245;es relevantes, por exemplo.&#160;Por este motivo, antes de executar o DoProgress as propriedades <strong>Text</strong> e <strong>Number</strong> (declaradas em&#160;<strong>TProgressThread</strong>) foram preenchidas, com o nome do arquivo e seu tamanho, respectivamente. Assim, quando o evento OnProgress for ativado pelo DoProgress, os par&#226;metros PText e PNumber estar&#227;o preenchidos com informa&#231;&#245;es que podem ser exibidas na aplica&#231;&#227;o. <strong>Usar estes dois par&#226;metros &#233; absolutamente <span style=\"text-decoration: underline;\">opcional</span></strong>. Eles existem apenas como um b&#244;nus. O mais importante &#233; chamar DoProgress, porque ele gerar&#225; o evento que informa que o TProgressBar precisa ser atualizado, usando seu m&#233;todo StepIt, ou incrementando sua propriedade Position;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Para cada par&#226;metro do MD, crie um campo privado na classe, que seja do mesmo tipo do par&#226;metro</strong>. No nosso exemplo o MD possui o par&#226;metro <strong>PInitialDir</strong>, logo, criamos um campo <strong>FInitialDir</strong>&#160;(linha <a href=\"#udirectorytreesize.11\" rel=\"alternate\">11</a>). Caso houvesse mais par&#226;metros, cada um deles se transformaria em um campo na classe;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Para cada par&#226;metro dos MAs,&#160;crie campos privados que sejam dos mesmos tipos de cada par&#226;metro</strong>. No nosso exemplo o MA <strong>DirectoryTreeFileCount</strong> possui o mesmo par&#226;metro que o MD (<strong>PInitialDir</strong>), logo, a cria&#231;&#227;o de um campo privado para ele (<strong>FInitialDir</strong>) j&#225; foi coberta no passo 3;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Para cada campo criado nos passos 3&#160;e 4 crie uma&#160;propriedade correspondente</strong>. Na linha <a href=\"#udirectorytreesize.17\" rel=\"alternate\">17</a> foi criada&#160;a propriedade <strong>InitialDir</strong>. A&#160;classe precisa conhecer todas as vari&#225;veis que ser&#227;o necess&#225;rias para que seus m&#233;todos internos possam funcionar, portanto, se seus m&#233;todos internos precisarem de mais informa&#231;&#245;es, cada uma destas precisa ser informada na classe e isso deve ser feito por meio de propriedades. Note que a propriedade InitialDir possui uma restri&#231;&#227;o de acesso, ou seja, esta propriedade &#233; somente para escrita (<strong>write-only</strong>). Isso n&#227;o &#233; necess&#225;rio, mas como o par&#226;metro <strong>PInitialDir &#233; somente de entrada</strong>, eu resolvi criar&#160;a propriedade mantendo o mesmo padr&#227;o. <strong>Se houvesse um par&#226;metro out</strong>, a propriedade correspondente deveria ser read-write. Em suma, por motivos &#243;bvios, as propriedades que representam par&#226;metros devem ter sempre acesso para que possam ser \"escritas\", elas nunca devem ser read-only, mas podem ser write-only;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Caso seu MD seja uma fun&#231;&#227;o (retorna um valor) crie um campo privado de nome FResult</strong>, do mesmo tipo do retorno do MD; Na linha <a href=\"#udirectorytreesize.12\" rel=\"alternate\">12</a> podemos ver a declara&#231;&#227;o do campo privado. Note que ele tem o mesmo tipo do retorno do MD;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Caos voc&#234; tenha precisado executar o passo 6, crie agora uma propriedade Result correspondente</strong> (linha <a href=\"#udirectorytreesize.18\" rel=\"alternate\">18</a>). Esta propriedade precisa ser somente leitura para evitar utiliza&#231;&#227;o incorreta da classe, al&#233;m disso, faz todo sentido que esta propriedade seja somente leitura, j&#225; que ela representa o <span style=\"text-decoration: underline;\">retorno</span> do MD;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Declare o m&#233;todo Execute&#160;na se&#231;&#227;o public da classe</strong> (linha <a href=\"#udirectorytreesize.16\" rel=\"alternate\">16</a>). Este &#233; o m&#233;todo que deve conter a l&#243;gica da thread, em outras palavras &#233; nele onde o MD precisa ser executado. <strong>V&#225; para a implementa&#231;&#227;o do m&#233;todo Execute e realize os dois passos a seguir</strong>;<br /><br />\r\n<ol style=\"list-style-type: upper-roman;\">\r\n<li style=\"text-align: justify;\"><strong>Caso voc&#234; tenha precisado implementar um MA para calcular a quantidade de itera&#231;&#245;es do seu MD</strong>, chame primeiramente o MA e retorne na <strong>propriedade Max</strong> a quantidade de itera&#231;&#245;es calculadas, em seguida, execute o <strong>m&#233;todo DoMax</strong>. Ao executar o m&#233;todo DoMax, um <strong>evento OnMax ser&#225; ativado</strong> e sua propriedade <strong>PMax</strong> conter&#225; aquilo que foi retornado na propriedade Max. Na sua aplica&#231;&#227;o, no manipulador do evento OnMax, <strong>voc&#234; configura a propriedade Max do seu TProgressBar</strong>. As linhas <a href=\"#udirectorytreesize.92-93\" rel=\"alternate\">92 e 93</a>&#160;mostram&#160;como deve ser feito;&#160;primeiro chamamos o m&#233;todo <strong>DirectoryTreeFileCount</strong>, o qual retorna na propriedade Max e logo em seguida h&#225; a chamada ao m&#233;todo DoMax, o qual vai gerar o evento OnMax, que pode ser manipulado na aplica&#231;&#227;o principal para configurar o TProgressBar. Note que DirectoryTreeFileCount foi chamada com o par&#226;metro FInitialDir, o qual deve ter sido&#160;configurado ap&#243;s a cria&#231;&#227;o da inst&#226;ncia de TDirectoryTreeSize. <strong>N&#227;o se preocupe, isso ser&#225; mostrado&#160;posteriormente</strong>;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Imediatamente ap&#243;s a execu&#231;&#227;o do MA, caso haja um, &#233; hora de chamar o MD</strong>. Caos seu MD seja uma fun&#231;&#227;o, execute-o exatamente como no exemplo (linha <a href=\"#udirectorytreesize.94\" rel=\"alternate\">94</a>). Note que o retorno da fun&#231;&#227;o &#233; colocado em <strong>FResult</strong>, o que &#233; esperado, j&#225; que a propriedade associada (<strong>Result</strong>) serve exatamente para isso. Caso seu MD n&#227;o precise retornar nenhum valor, apenas processar algo, ent&#227;o haveria apenas a chamada ao MD e nem mesmo FResult (ou sua propriedade) teria sido criado (passos 6 e 7)<br /><br /></li>\r\n</ol>\r\n</li>\r\n<li style=\"text-align: justify;\"><strong style=\"font-family: var(--text-font-family); color: var(--text-color); font-size: 1rem;\">Caso alguns de seus campos privados&#160;precisem de inicializa&#231;&#227;o pr&#233;via (cria&#231;&#227;o), voc&#234; deve, na se&#231;&#227;o public da classe, declarar o m&#233;todo construtor da seguinte forma \"constructor Create; override;\"</strong><span style=\"font-family: var(--text-font-family); background-color: var(--module-background-color); color: var(--text-color); font-size: 1rem;\">&#160;e n&#227;o se esque&#231;a de implementar o m&#233;todo destrutor \"</span><strong style=\"font-family: var(--text-font-family); color: var(--text-color); font-size: 1rem;\">destructor Destroy; override;</strong><span style=\"font-family: var(--text-font-family); background-color: var(--module-background-color); color: var(--text-color); font-size: 1rem;\">\" tamb&#233;m na se&#231;&#227;o public, destruindo (Free), cada um dos campos criados no construtor.&#160;</span></li>\r\n</ol>\r\n<div>&#160;</div>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>Como utilizar a classe TDirectoryTreeSize? (ou sua pr&#243;pria classe, como preferir)</h2>\r\n<p style=\"text-align: justify;\">Esta &#233; a parte mais f&#225;cil e mais compensadora deste artigo. Abaixo est&#225; uma parte da unit&#160;<strong>UFORMPrincipal</strong>, que cont&#233;m a classe&#160;<strong>TFORMPrincipal</strong>, da qual removi algumas partes para facilitar o entendimento:</p>\r\n<pre id=\"uformprincipal\" class=\"line-numbers language-pascal\"><code>unit UFORMPrincipal;\r\n\r\ninterface\r\n\r\nuses\r\n Forms, StdCtrls, Classes, Controls, UDirectoryTreeSize, ExtCtrls, ComCtrls;\r\n\r\ntype\r\n TFORMPrincipal = class(TForm)\r\n BUTNProcessamentoPesado: TButton;\r\n EDITDiretorioInicial: TEdit;\r\n PRBAProgresso: TProgressBar;\r\n LABEArquivo: TLabel;\r\n LABEPercentual: TLabel;\r\n procedure BUTNProcessamentoPesadoClick(Sender: TObject);\r\n private\r\n { Private declarations }\r\n FStartTime: TTime;\r\n FDirectoryTreeSize: TDirectoryTreeSize;\r\n procedure DoProgress (const PText: String; const PNumber: Cardinal);\r\n procedure DoMax(const PMax: Int64);\r\n procedure DoTerminate(PSender: TObject);\r\n public\r\n { Public declarations }\r\n end;\r\n\r\nvar\r\n FORMPrincipal: TFORMPrincipal;\r\n\r\nimplementation\r\n\r\n{$R *.dfm}\r\n\r\nuses\r\n Windows, SysUtils, Dialogs;\r\n\r\n{ TFORMPrincipal }\r\n\r\nprocedure TFORMPrincipal.BUTNProcessamentoPesadoClick(Sender: TObject);\r\nbegin\r\n FDirectoryTreeSize := TDirectoryTreeSize.Create;\r\n\r\n with FDirectoryTreeSize do\r\n begin\r\n InitialDir := EDITDiretorioInicial.Text;\r\n OnMax := DoMax;\r\n OnProgress := DoProgress;\r\n OnTerminate := DoTerminate;\r\n\r\n LABEPercentual.Caption := \'0.00%\';\r\n FStartTime := Now;\r\n BUTNProcessamentoPesado.Enabled := False;\r\n EDITDiretorioInicial.Enabled := False;\r\n\r\n Resume;\r\n end;\r\nend;\r\n\r\nprocedure TFORMPrincipal.DoMax(const PMax: Int64);\r\nbegin\r\n PRBAProgresso.Step := 1;\r\n PRBAProgresso.Position := 0;\r\n PRBAProgresso.Max := PMax;\r\n PRBAProgresso.DoubleBuffered := True;\r\nend;\r\n\r\nprocedure TFORMPrincipal.DoProgress(const PText: String; const PNumber: Cardinal);\r\nbegin\r\n PRBAProgresso.StepIt;\r\n LABEArquivo.Caption := \'Arquivo \' + IntToStr(PRBAProgresso.Position) + \' / \' + IntToStr(PRBAProgresso.Max) + \': \' + FormatFloat(\'(###,###,###,###,##0 bytes) \',PNumber) + PText;\r\n LABEPercentual.Caption := FormatFloat(\'##0.00%\',PRBAProgresso.Position / PRBAProgresso.Max * 100);\r\nend;\r\n\r\nprocedure TFORMPrincipal.DoTerminate(PSender: TObject);\r\nbegin\r\n Application.MessageBox(PChar(\'O tamanho total dos arquivos contidos na estrutura de diret&#243;rios \"\' + EDITDiretorioInicial.Text + \'\" &#233; \' + FormatFloat(\'###,###,###,###,##0 bytes\',FDirectoryTreeSize.Result)),PChar(Format(\'Processamento conclu&#237;do em %s\',[FormatDateTime(\'hh:nn:ss\',Now - FStartTime)])),MB_ICONINFORMATION);\r\n BUTNProcessamentoPesado.Enabled := True;\r\n EDITDiretorioInicial.Enabled := True;\r\nend;\r\n\r\nend.</code></pre>\r\n<p style=\"text-align: justify;\">Para um entendimento ainda melhor, abra o exemplo anexado neste artigo. Abaixo segue a explica&#231;&#227;o detalhada:</p>\r\n<ol>\r\n<li style=\"text-align: justify;\"><strong>Declare um campo privado na classe TFORMPrincipal do tipo TDirectoryTreeSize</strong>. O campo <strong>FDirectoryTreeSize</strong> pode ser visto na linha <a href=\"#uformprincipal.19\" rel=\"alternate\">19</a>;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Declare o manipulador do evento OnProgress</strong> (<strong>DoProgress</strong>) na se&#231;&#227;o private de <strong>TFORMPrincipal</strong> (linha <a href=\"#uformprincipal.20\" rel=\"alternate\">20</a>);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Implemente o manipulador DoProgress</strong> (linhas <a href=\"#uformprincipal.69-71\" rel=\"alternate\">69&#160;a&#160;71</a>). No nosso exemplo,&#160;este manipulador &#233; ativado sempre que um arquivo tem seu tamanho lido. Na linha <a href=\"#uformprincipal.69\" rel=\"alternate\">69</a> <strong>o valor de TProgressBar &#233; incrementado</strong>. <strong>TProgressBar.StepIt &#233; um m&#233;todo que adiciona o valor da propriedade TProgressBar.Step &#224; propriedade TProgressBar.Position</strong>. Existem pessoas que preferem atribuir diretamente &#224; propriedade&#160;TProgressBar.Position seu valor&#160;+1, mas eu prefiro ser mais pr&#225;tico e usar&#160;TProgressBar.StepIt, que j&#225; faz isso. Na linha <a href=\"#uformprincipal.70\" rel=\"alternate\">70</a> o <strong>nome do arquivo</strong>, contido em <strong>PText</strong>, e seu <strong>tamanho</strong>, contido em <strong>PNumber</strong>, s&#227;o atribu&#237;dos de forma formatada a um TLabel. Na linha <a href=\"#uformprincipal.71\" rel=\"alternate\">71</a>, como uma caracter&#237;stica adicional, eu fa&#231;o um <strong>calculo simples que retorna em um TLabel o percentual atual</strong>, porque todos n&#243;s amamos percentuais que incrementam :);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Declare o manipulador do evento OnMax</strong> (<strong>DoMax</strong>) na se&#231;&#227;o private de&#160;<strong>TFORMPrincipal</strong> (linha <a href=\"#uformprincipal.21\" rel=\"alternate\">21</a>);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Implemente o manipulador DoMax</strong> (linhas <a href=\"#uformprincipal.61-64\" rel=\"alternate\">61 a 64</a>). Em nosso exemplo, evento <strong>OnMax</strong> &#233; ativado quando o MA de contagem de arquivos retorna a quantidade total de arquivos que ser&#227;o processados. Este evento tem apenas um par&#226;metro (<strong>PMax</strong>), o qual retorna esta quantidade. &#201; neste evento onde devemos configurar o <strong>TProgressBar</strong>. Na linha <a href=\"#uformprincipal.61\" rel=\"alternate\">61</a>&#160;<strong>&#233; configurado o Step</strong> (passo) do TProgressBar <strong>como 1</strong>, de forma que ao se usar <strong>TProgressBar.StepIt</strong>, <strong>TProgressbar.Position seja automaticamente incrementada em 1 unidade</strong>. Na linha <a href=\"#uformprincipal.62\" rel=\"alternate\">62</a> <strong>TProgressBar.Position &#233; configurada como zero</strong> para que o TProgressBar \"esvazie\". Na linha <a href=\"#uformprincipal.63\" rel=\"alternate\">63</a> &#233; configurada a propriedade <strong>TProgressBar.Max com o valor do par&#226;metro PMax</strong>. &#201; exatamente para isso que o evento OnMax serve! Finalmente, na linha <a href=\"#uformprincipal.64\" rel=\"alternate\">64</a>, <strong>a fim de evitar flickering, a propriedade TProgressBar.DoubleBuffered &#233; configurada como True</strong>;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Declare o manipulador do evento OnTerminate</strong> (<strong>DoTerminate</strong>) na se&#231;&#227;o private de&#160;<strong>TFORMPrincipal</strong> (linha <a href=\"#uformprincipal.22\" rel=\"alternate\">22</a>);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Implemente o manipulador DoTerminate</strong> (linhas <a href=\"#uformprincipal.76-78\" rel=\"alternate\">76 a 78</a>).&#160;O evento <strong>OnTerminate</strong> &#233; ativado <strong>quando o m&#233;todo Execute de uma thread termina</strong>. O fim do m&#233;todo Execute <strong>sinaliza o fim do MD</strong> e por isso, caso o MD seja uma fun&#231;&#227;o, <strong>&#233; neste evento onde devemos obter o valor retornado pela mesma</strong>. &#201; tamb&#233;m neste evento onde devemos <strong>reabilitar controles que foram desabilitados antes do in&#237;cio da thread</strong>. Na linha <a href=\"#uformprincipal.76\" rel=\"alternate\">76</a> exibimos uma mensagem para o usu&#225;rio informando o tamanho total de todos os arquivos somados na estrutura de diret&#243;rios. Esse valor est&#225; em <strong>FDirectoryTreeSize.Result</strong>. Exibimos tamb&#233;m o tempo que o procedimento levou para ser conclu&#237;do (<strong>Now - FStartTime</strong>). As linhas <a href=\"#uformprincipal.77-78\" rel=\"alternate\">77 e 78</a> <strong>reabilitam os controles que foram desabilitados antes do in&#237;cio da thread</strong> (veja mais adiante neste passo-a-passo);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Crie um m&#233;todo para iniciar e configurar a inst&#226;ncia de TDirectoryTreeSize</strong>. Isso tamb&#233;m pode ser feito diretamente num manipulador de eventos, como eu fiz, mas admito que criar um m&#233;todo para isso &#233; mais elegante. Como o intuito aqui &#233; ser o mais direto poss&#237;vel nas explica&#231;&#245;es, codificar tudo no manipulador do evento OnClick de um bot&#227;o &#233; perfeitamente v&#225;lido e vai funcionar &#224; contento.&#160;As linhas <a href=\"#uformprincipal.41-56\" rel=\"alternate\">41 a 56</a>&#160;mostram exatamente tudo que precisa ser feito. Abaixo segue o detalhamento;<br /><br />\r\n<ol style=\"list-style-type: upper-roman;\">\r\n<li style=\"text-align: justify;\"><strong>Instancie a classe TDirectoryTreeSize</strong> (linha <a href=\"#uformprincipal.41\" rel=\"alternate\">41</a>) no campo criado para este prop&#243;sito (<strong>FDirectoryTreeSize</strong>);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Configure as propriedades requeridas pela classe</strong> <strong>TDirectoryTreeSize</strong> (linha <a href=\"#uformprincipal.45\" rel=\"alternate\">45</a>). No caso do exemplo, existe apenas uma propriedade (<strong>InitialDir</strong>), a qual deve ser preenchida com o diret&#243;rio inicial, a partir do qual ser&#225; feita a varredura recursiva. <strong>EDITDiretorioInicial</strong> &#233; um componente <strong>TEdit</strong> que existe em <strong>TFORMPrincipal</strong> para este fim. Se houvessem mais propriedades, elas deveriam ser preenchidas aqui, uma ap&#243;s a outra, a fim de manter o c&#243;digo organizado;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Atribua os manipuladores de evento aos eventos da classe</strong> <strong>TDirectoryTreeSize</strong> (linhas <a href=\"#uformprincipal.46-48\" rel=\"alternate\">46 a 48</a>). O manipulador do evento <strong>OnMax</strong> (<strong>DoMax</strong>) s&#243; precisa ser criado e&#160;atribu&#237;do&#160;<strong>caso haja um m&#233;todo interno que calcula a quantidade de elementos (itens) iter&#225;veis ANTES da realiza&#231;&#227;o do MD</strong>. Caso a quantidade de elementos iter&#225;veis seja conhecida previamente, voc&#234; n&#227;o deve ter criado um MA para calcular este valor e consequentemente o evento OnMax nunca ser&#225; ativado, porque n&#227;o &#233; necess&#225;rio. Como no nosso exemplo n&#243;s precisamos calcular a quantidade total de arquivos dos quais o tamanho deve ser retornado, ent&#227;o <strong>o evento OnMax ser&#225; ativado assim que o total de arquivos for obtido </strong>e o par&#226;metro <strong>PMax conter&#225; este total</strong>.&#160;O evento <strong>OnProgress</strong> ser&#225; ativado a cada vez que um arquivo tiver seu tamanho obtido. No manipulador desse evento (<strong>DoProgress</strong>) &#233; poss&#237;vel obter o nome do arquivo e o seu tamanho individual nos par&#226;metros <strong>PText</strong> e <strong>PNumber</strong>. O evento <strong>OnTerminate</strong>, manipulado pelo m&#233;todo <strong>DoTeminate</strong>, &#233; um evento de <strong>TThread</strong> e <strong>&#233; ativado sempre que uma thread termina, e imediatamente ANTES dela ser liberada da mem&#243;ria (caso ela tenha sido criada com FreeOnTerminate = True)</strong>. <strong>&#201; neste evento onde obtemos o valor de retorno do MD</strong>, pois ele sinaliza que o MD terminou de realizar sua tarefa, logo, caso o MD seja uma fun&#231;&#227;o, seu retorno j&#225; &#233; conhecido;<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Execute procedimentos \"pr&#233;-MD\"</strong>. As linhas <a href=\"#uformprincipal.50-53\" rel=\"alternate\">50 a 53</a> cont&#233;m c&#243;digo que <strong>deve ser executado ANTES do MD ser executado na&#160;thread</strong> e o que vai nestas linhas, depende de sua implementa&#231;&#227;o. N&#227;o h&#225; nada de muito especial. No caso do exemplo,&#160;um TLabel&#160;est&#225; sendo \"zerado\" na linha <a href=\"#uformprincipal.50\" rel=\"alternate\">50</a>, um campo de contagem de tempo est&#225; sendo preenchido com o valor atual (Now)&#160;na linha <a href=\"#uformprincipal.51\" rel=\"alternate\">51</a>, o TButton&#160;onde todo este c&#243;digo est&#225;, &#233; desabilitado (para evitar cliques m&#250;ltiplos) na linha <a href=\"#uformprincipal.52\" rel=\"alternate\">52</a>&#160;e, finalmente, o TEdit onde se digita o par&#226;metro InitialDir &#233; desabilitado (linha <a href=\"#uformprincipal.53\" rel=\"alternate\">53</a>);<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Inicialize TDirectoryTreeSize (TThread) usando o m&#233;todo Resume</strong> (linha <a href=\"#uformprincipal.55\" rel=\"alternate\">55</a>). Como por padr&#227;o nossa classe <strong>TDirectoryTreeSize &#233; uma neta&#160;de TThread com CreateSuspended = True</strong>, ent&#227;o, para iniciar a thread, simplesmente executamos seu m&#233;todo Resume, o qual tem por finalidade continuar a execu&#231;&#227;o de uma thread suspensa. Se voc&#234; tem um Delphi mais recente, no lugar de Resume coloque Start, pois o m&#233;todo Resume foi&#160;depreciado;</li>\r\n</ol>\r\n</li>\r\n</ol>\r\n<p>Ap&#243;s realizar todos estes passos, execute e teste! Use o exemplo anexado a este artigo para ver exatamente como tudo foi implementado e comece agora mesmo a converter seus m&#233;todos demorados para usarem corretamente o TProgressBar e TThreads :)</p>\r\n<h2>Esse trabalho todo, compensa?</h2>\r\n<p style=\"text-align: justify;\">Voc&#234; agora deve estar pensando que isso tudo foi feito apenas para implementar o uso correto de uma simples TProgressBar, mas n&#227;o &#233; bem assim. Primeiramente, n&#227;o &#233; tanto trabalho como parece. O artigo ficou grande porque ele &#233; did&#225;tico, mas ao olhar o c&#243;digo fonte do exemplo anexado, se nota que n&#227;o tem muita coisa escrita e se voc&#234; levar em conta que precisa implementar apenas uma classe (TDirectoryTreeSize no exemplo) e depois us&#225;-la, menos c&#243;digo ainda vai sobrar para ser escrito.</p>\r\n<p style=\"text-align: justify;\">Em segundo lugar, mas n&#227;o menos importante, apesar do t&#237;tulo do artigo falar do TProgressBar, este &#233; apenas a ponta do iceberg dentro do contexto, em outras palavras, o \"pretexto\", para se usar um TProgressBar de forma correta &#233; que deve ser levado em conta: <strong>o uso de uma thread para executar um processamento demorado</strong>.</p>\r\n<p style=\"text-align: justify;\">A dica de ouro &#233;: <strong>Sempre que voc&#234; tiver algo que vai demorar um tempo consider&#225;vel, &#233; preciso colocar esse \"algo\" em uma thread, isso garante que sua aplica&#231;&#227;o permane&#231;a responsiva e processando outras mensagens (Windows Messages) importantes sem imprevistos. Al&#233;m disso, para n&#227;o deixar seu usu&#225;rio a ver navios, voc&#234; precisa mant&#234;-lo informado acerca do andamento da tarefa e &#233; a&#237; onde o TProgressBar entra.</strong></p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-09-11 23:33:55',24,'','2020-12-10 18:58:22',24,0,'0000-00-00 00:00:00','2016-09-23 00:42:15','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000102\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',42,86,'Delphi, Addicted 2 Delphi, TProgressBar, Barra de Progresso, Indicador de Andamento, Processo Demorado, Threads','Chutando por baixo, acredito que 90% dos programadores usam o componente TProgressBar de forma errada. Até mesmo eu uso de forma errada porque a forma correta é trabalhosa. Mesmo assim eu acredito que vale muito a pena conhecer o modo correto de se trabalhar com esse componente e caso seu programa faça uso constante dele, porque não criar uma classe que facilita a implementação correta? É isso que pretendo mostrar neste artigo',1,10074,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(103,286,'O lado negro do Application.ProcessMessages','o-lado-negro-do-application-processmessages','<p style=\"text-align: justify;\">Esses dias eu estava escrevendo um artigo e cheguei num ponto onde eu estava justificando o uso de uma thread em detrimento do Application.ProcessMessages. Nesse momento eu lembrei que este comando não deve ser usado de forma leviana, só não tinha uma boa explicação, então fui atrás e achei um artigo muito bom a respeito. Esta é mais uma tradução/versão by myself ;)</p>\r\n','\r\n<p style=\"text-align: justify;\">Mais uma vez quero dizer que parte deste texto é uma tradução/versão do texto original disponível em <a href=\"http://delphi.about.com/od/objectpascalide/a/delphi-processmessages-dark-side.htm\" rel=\"alternate\">http://delphi.about.com/od/objectpascalide/a/delphi-processmessages-dark-side.htm</a>. Eu tomei a liberdade de incluir mais informações sobre mensagens do Windows e corrigir alguns pontos que ficaram nebulosos.</p>\r\n<hr />\r\n<h2>Você usa Application.ProcessMessages? Deveria reconsiderar!</h2>\r\n<p style=\"text-align: justify;\">Ao programar um manipulador de eventos no Delphi (como o evento OnClick de um TButton), chega o momento em que a sua aplicação precisa ficar ocupada por um tempo, por exemplo, o código precisa escrever um grande arquivo ou compactar alguns dados. Se você fizer isso você vai perceber que a sua aplicação parece ficar bloqueada. Seu formulário não pode mais ser movido e os botões não mostram sinais de vida. A aplicação parece ter travado.</p>\r\n<p style=\"text-align: justify;\">A razão para isso acontecer é que uma aplicação Delphi tem apenas uma thread. O código que você está escrevendo representa apenas um monte de procedimentos que são executados pela thread principal da aplicação sempre que o evento ocorre. O resto do tempo esta thread principal está manipulando mensagens de sistema e outras coisas tais como funções de manipulação de forms e componentes. Então, se dentro de um manipulador de eventos você executar uma tarefa demorada, você vai terminar impedindo sua aplicação de manipular estas mensagens e uma solução comum para este tipo de problema é realizar chamadas a <strong>Application.ProcessMessages</strong>, doravante referido simplesmente como <strong>ProcessMessages</strong>.</p>\r\n<p style=\"text-align: justify;\">O ProcessMessages manipula todas as mensagens que estão \"aguardando\" para serem manipuladas, tais como movimentação de janelas, cliques em botões, dentre outras. Ele é usado normalmente como uma solução simples que mantém sua aplicação rodando sem ficar bloqueada. Infelizmente o mecanismo por trás do ProcessMessages tem suas próprias características, as quais podem causar uma grande confusão!</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>Mas exatamente o que o ProcessMessages faz?</h2>\r\n<p style=\"text-align: justify;\">O Windows usa mensagens (<a href=\"https://msdn.microsoft.com/pt-br/library/windows/desktop/ff381405(v=vs.85).aspx\" rel=\"alternate\">Windows Messages</a>) para \"conversar\" com todas as aplicações que estão em execução. As interações do usuário são enviadas ao formulário através mensagens, as quais são processadas no <a href=\"https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows\" rel=\"alternate\">loop de mensagens da aplicação</a>. Sim! Todo programa tem um loop infinito que fica ativo enquanto o programa estiver em execução e a cada iteração deste loop um item da fila de mensagens é processado. Por exemplo, se o botão esquerdo do mouse for pressionado enquanto o cursor se encontra em cima de um TButton, uma mensagem (<a href=\"https://msdn.microsoft.com/pt-br/library/windows/desktop/ms645607(v=vs.85).aspx\" rel=\"alternate\">WM_LBUTTONDOWN</a>) é enviada ao TButton. Além da mensagem relacionada ao clique em si, existem outras que serão automaticamente geradas para complementar esta ação realizando tudo que precisa ser feito. Uma delas é a pintura (<a href=\"https://msdn.microsoft.com/pt-br/library/windows/desktop/dd145213(v=vs.85).aspx\" rel=\"alternate\">WM_PAINT</a>) do TButton para um estado \"pressionado\" (baixo relevo) e, ao soltar o botão do mouse (ou sair da área-cliente deste botão), uma outra mensagem de pintura é enviada ao botão, de forma que ele seja repintado no estado \"não pressionado\" (alto relevo). Como o TButton pertence ao programa, estas mensagens são enviadas para a fila de mensagens da aplicação em questão e serão processadas em um momento qualquer dentro das iterações do loop de mensagens da aplicação.</p>\r\n<p style=\"text-align: justify;\">Ao executar um procedimento demorado o loop de mensagens da aplicação para até que o procedimento demorado termine. Como o loop de mensagens está parado, a aplicação não processará qualquer mensagem da fila e é por isso que a aplicação parece ter travado, ela fica literalmente sem responder a nenhuma mensagem. Nesta situação o ProcessMessages faz exatamente o que seu nome diz, ele percorre TODAS as mensagens que estão na fila aguardando processamento, processa TODAS elas (executa seus manipuladores) e depois volta o controle para a thread principal, que continua o procedimento demorado. </p>\r\n<p style=\"text-align: justify;\">Para tentar entender melhor, verifique o pseudocódigo abaixo:</p>\r\n<pre id=\"message-loop\" class=\"line-numbers language-pascal\"><code>while true do \r\nbegin\r\n GetMessage(Msg, 0, 0, 0);\r\n case Msg of\r\n WM_LBUTTONDOWN: begin\r\n for i := 0 to 99999999999 do \r\n begin\r\n ResolvaOsProblemasDoMundo(i);\r\n CalcularPiComUmBilhaoDeCasasDecimais;\r\n Application.ProcessMessages;\r\n end;\r\n end;\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">O loop mais externo (linha <a href=\"#message-loop.1\" rel=\"alternate\">1</a>) seria o loop de mensagens. Note que a primeira coisa que ele faz (linha <a href=\"#message-loop.3\" rel=\"alternate\">3</a>) é obter uma mensagem da fila de mensagens. Esta mensagem é então verificada por um seletor (linha <a href=\"#message-loop.4\" rel=\"alternate\">4</a>) e o código do manipulador é executado (linhas <a href=\"#message-loop.6-11\" rel=\"alternate\">6 a 11</a>). Se o código do manipulador for muito demorado o loop mais externo não vai completar sua iteração até que este código termine, logo, outras mensagens essenciais que seriam obtidas pelo <strong>GetMessage</strong> não serão obtidas e a aplicação fica travada.</p>\r\n<p style=\"text-align: justify;\">Ao utilizar o ProcessMessages (linha <a href=\"#message-loop.10\" rel=\"alternate\">10</a>), (muito) grosso modo, o que acontece é que o processo demorado (neste caso o loop interno) é suspenso, e todos os manipuladores de todas as mensagens da fila de mensagens serão executados, até que a fila se esvazie. Quando isso acontece o controle volta para o processo demorado e a linha de código subsequente à linha do ProcessMessages será executada.</p>\r\n<p style=\"text-align: justify;\">À primeira vista isso não parece ser algo muito crítico, mas olhando mais de perto o que acontece, é possível notar que <span style=\"text-decoration: underline;\">existe uma sequencia de acontecimentos e que por mais que você pense que várias coisas estão acontecendo ao mesmo tempo, na verdade elas ocorrem de forma ordenada, sequencial.</span> <strong>Ao usar o ProcessMessages, esse ordem é quebrada</strong>. No momento em que o procedimento demorado é suspenso, mensagens que deveriam ser processadas apenas após seu término serão processadas imediatamente.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">Por que eu devo evitar o ProcessMessages?</h2>\r\n<p style=\"text-align: justify;\">Pode ser que você nunca tenha problemas, mas certamente furar a fila de execução das mensagens pode causar uma grande confusão, pois executar ProcessMessages de qualquer maneira pode habilitar chamadas recursivas para qualquer manipulador de eventos novamente. Use o exemplo anexado a este artigo para entender melhor.</p>\r\n<p style=\"text-align: justify;\">No trecho de código simplificado a seguir temos o manipulador de um evento OnClick. O loop FOR simula um processamento longo com chamadas ao ProcessMessages sendo executadas a cada iteração:</p>\r\n<pre id=\"onclick1\" class=\"line-numbers language-pascal\"><code>{in MyForm:}\r\n WorkLevel: Integer; \r\n{OnCreate:} \r\n WorkLevel := 0;\r\n\r\nprocedure TForm1.WorkBtnClick(Sender: TObject);\r\nvar\r\n cycle: Integer; \r\nbegin\r\n inc(WorkLevel);\r\n \r\n for cycle := 1 to 5 do\r\n begin\r\n Memo1.Lines.Add(\'- Work \' + IntToStr(WorkLevel) + \', Cycle \' + IntToStr(cycle);\r\n Application.ProcessMessages;\r\n sleep(1000) ; // ou alguma outra coisa demorada\r\n end;\r\n\r\n Memo1.Lines.Add(\'Work \' + IntToStr(WorkLevel) + \' ended.\');\r\n \r\n dec(WorkLevel);\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\"><strong>Sem ProcessMessages</strong> (linha <a href=\"#onclick1.15\" rel=\"alternate\">15</a>) as seguintes linhas serão escritas no TMemo, se o botão for pressionado <strong>duas vezes</strong> em um curto intervalo de tempo:</p>\r\n<pre><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 1 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 2 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 3 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 4 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 5 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">Work 1 ended. </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 1 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 2 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 3 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 4 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 5 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">Work 1 ended.</span></pre>\r\n<p style=\"text-align: justify;\">Enquanto o processamento estiver em execução, o formulário não mostra qualquer reação, mas o segundo clique foi colocado na fila de mensagens pelo Windows, logo, imediatamente após o manipulador do evento OnClick terminar ele será chamado novamente.</p>\r\n<p style=\"text-align: justify;\"><strong>Incluindo o ProcessMessages</strong>, a saída será muito diferente, veja:</p>\r\n<pre style=\"text-align: justify;\"><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 1 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 2 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 3 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 2, Cycle 1 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 2, Cycle 2 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 2, Cycle 3 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 2, Cycle 4 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 2, Cycle 5 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">Work 2 ended. </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 4 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">- Work 1, Cycle 5 </span><br /><span style=\"font-family: \'courier new\', courier, monospace;\">Work 1 ended.</span></pre>\r\n<p style=\"text-align: justify;\">Desta vez o formulário aparenta estar funcionando e aceita qualquer interação do usuário, então o botão é pressionando mais uma vez, mas agora, no meio do caminho durante o primeiro processamento. O ProcessMessages fará com que este segundo clique seja manipulado imediatamente. Todos os eventos de entrada serão manipulados, bem como quaisquer outras chamadas de função. Na teoria, durante cada chamada a ProcessMessages, qualquer quantidade de cliques e mensagens em geral serão manipuladas instantaneamente.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Além deste efeito de sobreposição de resultados, existe um efeito colateral mais evidente provocado indiretamente pelo ProcessMessages. No exemplo anexado a este artigo, após clicar no botão \"Begin Work\" com \"Enable ProcessMessages\" habilitado, mova a janela. Note que o processamento para completamente e só retorna quando você deixa de mover a janela. Isso acontece porque o ProcessMessages está tentando esvaziar a fila de mensagens, mas você, ao mover a janela, está introduzindo, a cada pixel movido, mais mensagens (<a href=\"https://msdn.microsoft.com/pt-br/library/windows/desktop/ms632631(v=vs.85).aspx\" rel=\"alternate\">WM_MOVE</a>) à fila. Neste caso curioso, o ProcessMessages acaba se tornando o processamento demorado, porque dentro do loop, ao executá-lo, ele só vai devolver o controle ao mesmo, quando a fila de mensagens esvaziar, só que a fila nunca vai esvaziar enquanto mais mensagens de movimento estiverem entrando nela. Acho que já deu para entender que o ProcessMessages não serve para ser usado dessa forma, <strong>então, seja muito cuidadoso com seu código, ao usá-lo</strong>.</p>\r\n<p style=\"text-align: justify;\">Vamos ver um exemplo diferente. Observe este simples pseudocódigo:</p>\r\n<pre id=\"filewrite\" class=\"line-numbers language-pascal\"><code>procedure OnClickFileWrite();\r\nvar \r\n myfile := TFileStream;\r\nbegin\r\n myfile := TFileStream.create(\'myOutput.txt\');\r\n \r\n try\r\n while BytesReady &gt; 0 do\r\n begin\r\n myfile.Write(DataBlock);\r\n dec(BytesReady,sizeof(DataBlock));\r\n DataBlock[2] := #13;\r\n Application.ProcessMessages;\r\n DataBlock[2] := #13;\r\n end;\r\n finally\r\n myfile.free;\r\n end;\r\nend;</code></pre>\r\n<p style=\"text-align: justify;\">Este procedure escreve uma grande quantidade de dados e tenta manter a aplicação descongelada usando o ProcessMessages a cada vez que um bloco de dados é escrito.</p>\r\n<p style=\"text-align: justify;\">Se o usuário clicar no botão que executa este procedure, enquanto ele já estiver em execução, o mesmo código será executado enquanto o arquivo ainda está sendo escrito. O arquivo não pode ser aberto uma segunda vez e consequentemente o procedure falha. Como resultado dessa falha, talvez haja alguma implementação para liberar buffers, então, DataBlock estaria vazio e uma possível terceira chamada ao procedure (ou uma chamada que já estivesse em execução anteriormente) iria subitamente levantar um Access Violation ao tentar acessá-lo. Neste caso, o código na linha <a href=\"#filewrite.12\" rel=\"alternate\">12</a> poderia funcionar, mas o código na linha <a href=\"#filewrite.14\" rel=\"alternate\">14</a> iria falhar. Mais uma vez se nota que a quebra na ordem dos acontecimentos (furar a fila de mensagens com o ProcessMessages) causa uma imensa bagunça e torna a lógica impossível de se entender.</p>\r\n<p style=\"text-align: justify;\">Uma forma fácil de se contornar estes problemas seria bloquear o acesso aos botões do form configurando sua propriedade Enabled como false. Isso bloquearia qualquer interação com o usuário mas manteria os controles visivelmente ativos, o que não é uma boa ideia. Uma ideia melhor seria desabilitar cada um dos controles do formulário, menos aqueles que porventura precisem ficar ativos (um botão para cancelar o processamento, por exemplo), mas isso é mais complexo, pois seria necessário percorrer todos os controles e desabilitar por demanda cada um, além disso, ao terminar o processamento demorado, os controles precisariam ser percorridos novamente para serem habilitados, mas, digamos, você precisaria manter alguns deles desabilitados, caso estes já estivessem desabilitados ANTES do procedimento demorado. Resumindo, é muito trabalho pra permanecer usando algo que, na maioria dos contextos, não é correto.</p>\r\n<h2 style=\"text-align: justify;\">Não tenha preguiça, use threads!</h2>\r\n<p style=\"text-align: justify;\">Desde o começo deste artigo eu apenas falei de algo demorado sendo feito ao clicar num botão, mas poderia ser um TMenuItem o um TAction. Não importa o que o procedimento demorado faça, na grande maioria das vezes ele é desencadeado por algo simples, como um clique. O OnClick é um evento do tipo <strong>TNotifyEvent</strong> e como o próprio nome da classe diz, ele deveria ser usado para procedimentos de curta duração. Para código pesado, a melhor forma é mover toda a codificação lenta para sua própria thread e manter no evento de curta duração apenas a criação e execução desta thread.</p>\r\n<p style=\"text-align: justify;\">Levando em conta os problemas decorrentes do uso indiscriminado do ProcessMessages, bem como o trabalho adicional de ter que habilitar/desabilitar controles para manter o usuário na linha, o uso de uma segunda thread parece não ser assim tão complicado. Lembre-se de que mesmo poucas linhas de código podem travar uma aplicação por alguns segundos, por exemplo, abrir um arquivo do disco e ter que esperar pelo spin-up do disco terminar. Não seria muito legal se sua aplicação parecesse travada por conta de algum HD lento ou problemático não é mesmo?</p>\r\n<h2 style=\"text-align: justify;\">Afinal o ProcessMessages é inútil?</h2>\r\n<p style=\"text-align: justify;\">Não, eu nunca disse isso! O que deve ser evitado é seu uso indiscriminado, mais especificamente, se você o utiliza dentro de um loop ou dentro de algo que é executado dentro de um loop, com certeza você está fazendo isto errado e seria melhor alterar seu código para usar uma thread separada. Regra geral, fica a dica: <strong>Se seus ProcessMessages estiverem em um loop, então está errado e deve ser evitado</strong>.</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-09-14 00:21:59',24,'','2020-06-26 17:31:02',24,0,'0000-00-00 00:00:00','2016-09-16 21:13:37','0000-00-00 00:00:00','{\"image_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"float_intro\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000103\\/FullArticle.jpg\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\",\"float_fulltext\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_layout\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',29,87,'Delphi, Addicted 2 Delphi, Threads, ProcessMessages, Windows Messages, Messages Loop','Esses dias eu estava escrevendo um artigo e cheguei num ponto onde eu estava justificando o uso de uma thread em detrimento do Application.ProcessMessages. Nesse momento eu lembrei que este comando não deve ser usado de forma leviana, só não tinha uma boa explicação, então fui atrás e achei um artigo muito bom a respeito. Esta é mais uma tradução/versão by myself ;)',1,12747,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(104,288,'Entendendo a instalação de componentes','como-instalar-corretamente-componentes','<p style=\"text-align: justify;\">Existem na web centenas de artigos que ensinam a criar componentes no Delphi e apesar de eu poder fazer um artigo abordando este tema no futuro, no momento eu prefiro mesmo é falar a respeito de algo que é tão importante quanto o próprio componente em si. Muitas pessoas acham que sabem instalar corretamente um componente, mas o fato de ter o componente funcionando não significa que a instalação foi correta. Você agora deve estar se perguntando \"Ora, mas se está funcionando, porque eu preciso me preocupar?\". Continue lendo e descubra.</p>\r\n','\r\n<p style=\"text-align: justify;\">Então, por que você deveria se preocupar, se um componente está funcionando corretamente? Sabemos que essa pergunta, proveniente do Axioma #19 do <a href=\"http://www.gohorseprocess.com.br/extreme-go-horse-(xgh)\" rel=\"alternate\">XGH</a> não se aplica muito bem no munto real. Um programador responsável não quer apenas fazer com que seus programas funcionem, eles se interessam em entender COMO eles funcionam. A curiosidade é o motor que nos torna especialistas em nossa profissão e se você não tem curiosidade, lamento muito, mas seu lugar não é aqui e te aconselho a parar de ler imediatamente. Se você for um programador Delphi de verdade, ou se considera como tal, pode continuar!</p>\r\n<p style=\"text-align: justify;\">Eu deveria ter escrito este artigo ANTES de começar a falar a respeito do <a href=\"index.php?option=com_content&amp;view=article&amp;id=122&amp;catid=80&amp;Itemid=493\">Open Tools API</a>, mas o OTA é tão interessante que eu não resisti e terminei publicando o artigo sobre ele de forma prematura. Prematura apenas porque um dos pré-requisitos do OTA é saber o mínimo sobre instalação de pacotes no Delphi. Bom, antes tarde do que nunca, vou falar a respeito disso.</p>\r\n<h2>A quem este artigo é destinado?</h2>\r\n<p style=\"text-align: justify;\">Este artigo é destinado a desenvolvedores comuns e desenvolvedores de componentes. Eu estou especificando bem isso porque tanto um como outro podem tirar proveito das explicações que vou fazer.</p>\r\n<p style=\"text-align: justify;\">Desenvolvedores comuns precisam entender como os componentes são instalados a fim de poderem resolver eventuais problemas de instalação devido a componentes mal desenvolvidos (por desenvolvedores de componentes) e com documentação insuficiente.</p>\r\n<p style=\"text-align: justify;\">Desenvolvedores de componente precisam entender como os componentes são instalados a fim de poderem desenvolver e distribuir seus componentes de forma correta, causando assim o mínimo de impacto aos usuários finais (desenvolvedores comuns).</p>\r\n<p style=\"text-align: justify;\">O que é o Library Path? O que é o Search Path? Onde os arquivos são salvos e onde eles precisam estar? Estas são algumas das perguntas que eu pretendo responder neste artigo.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>Considerações iniciais (O básico)</h2>\r\n<p style=\"text-align: justify;\">Antes de falar a respeito da instalação de componentes é necessário citar alguns conceitos que são relacionados aos componentes (e ao Delphi) e que muitos de vocês simplesmente ignoram porque querem apenas começar a programar o mais rápido possível. Primeiramente o termo \"componente\" que eu utilize no título deste artigo é errado. Usei-o propositalmente para chamar a atenção de programadores iniciantes, mas para falar a verdade este artigo trata da instalação de pacotes no Delphi. Calma! Não queira me matar, você não foi enganado. Vou explicar melhor.</p>\r\n<p style=\"text-align: justify;\">Todo componente é encapsulado em um pacote, mas nem todo pacote contém componentes de fato! Quando você instala um componente, na verdade você está instalando um pacote e este pacote pode conter nenhum, um, ou mais componentes. Convenciona-se, para facilitar, dizer \"instalar um componente\", mas na verdade você está instalando um pacote que pode conter bem mais que o componente em si sendo instalado. Tenha sempre isso em mente a fim de não cometer erros ao referenciar componentes ou pacotes. Em suma, pacotes podem conter componentes</p>\r\n<hr class=\"system-pagebreak\" title=\"Tipos de arquivo que o Delphi manipula\" alt=\"Tipos de arquivo que o Delphi manipula\" />\r\n<h2>Tipos de arquivo que o Delphi manipula</h2>\r\n<p style=\"text-align: justify;\">Gostaria de fazer uma revisão sobre os tipos de arquivos que o Delphi gera ou manipula dentro do contexto dos pacotes. É importante conhecê-los para não cometer erros ao instalar componentes e, principalmente, conhecer seus significados a fim de saber como referenciá-los no Library Path. Sem mais delongas, ei-los:</p>\r\n<div class=\"autooverflowx\">\r\n<table>\r\n<thead>\r\n<tr>\r\n<th style=\"width: 10%;\">Extensão</th>\r\n<th style=\"width: 90%;\">Descrição</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n<tr>\r\n<th style=\"text-align: right;\" colspan=\"2\">Arquivos de código-fonte (arquivos de texto plano)</th>\r\n</tr>\r\n<tr style=\"display: none;\">\r\n<td colspan=\"2\"> </td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.dpk</td>\r\n<td style=\"text-align: justify;\"><strong>Delphi Package Project File</strong> - Este é o arquivo de projeto principal de um pacote. Em comparação com um projeto padrão do Delphi, este arquivo equivale ao arquivo .dpr (Delphi Project). O arquivo de projeto de um pacote contém várias configurações adicionais, ao contrário do arquivo .dpr. A maioria destas configurações pode ser modificada por meio da caixa de diálogo \"Project Options\". Algumas das configurações mais básicas encontram-se no item (ou aba) \"Description\" desta caixa de diálogo, cujos campos que merecem destaque são: Description, Usage options e LIB suffix. Falarei mais a respeito destas opções posteriormente neste artigo</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.pas</td>\r\n<td style=\"text-align: justify;\"><strong>Pascal Source File</strong> - Todo e qualquer projeto Delphi, seja um pacote, um executável, ou uma biblioteca, normalmente possui ao menos um arquivo de fonte. Bibliotecas (dll) ou aplicações de console, quando muito simples, podem conter apenas o arquivo .dpr, sem qualquer arquivo .pas. O arquivo .dpr, pode conter o fonte completo, mas por organização você não vai querer que todo o seu programa seja escrito em um único arquivo, logo, é desejável sempre ter ao menos um arquivo .pas para organizar seu código-fonte. Arquivos .pas são compiláveis e ao serem compilados geram arquivos .dcu como resultado</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.inc</td>\r\n<td style=\"text-align: justify;\"><strong>Include File</strong> - Um arquivo de inclusão pode ter qualquer extensão, mas convenciona-se que arquivos desta natureza tenham a extensão .inc. O uso mais comum dos arquivos de inclusão é o agrupamento de diretivas de compilação, mas eles são bem mais que isso. Arquivos de inclusão são arquivos de texto plano que podem conter basicamente qualquer coisa que você colocaria em um arquivo .pas, mas com uma diferença muito importante: arquivos usados como arquivos de inclusão NÃO SÃO COMPILADOS SOZINHOS como os arquivos .pas, eles precisam ser incluídos em algum fonte compilável. Esta característica, que a princípio parece ser uma desvantagem, na verdade permite que arquivos de inclusão possuam trechos completos de código, classes, constantes, variáveis e qualquer outro tipo de código-fonte que podem ser incluídos em pontos específicos de arquivos .pas, sem necessidade de replicar código.<br /><br />Como um exemplo bem simples e, por isso mesmo, não tão usual, suponha que você possui uma mensagem que precisa ser exibida da mesma forma em vários locais distintos dentro do seu código-fonte. Você pode escrever um arquivo <strong>minhamensagem.inc</strong> da seguinte maneira:<br />\r\n<pre class=\"language-pascal\"><code>Application.MessageBox(\'Eu fui definida em um arquivo .inc\'\r\n ,\'Mensagem do arquivo de inclusão\'\r\n ,MB_ICONWARNING);</code></pre>\r\nPosteriormente você pode em um código-fonte propriamente dito (arquivo .pas) inclur este seu arquivo .inc, em um ponto do código-fonte onde ele faz sentido, isto é, em um local onde o conteúdo do arquivo .inc, <strong>SE FOSSE DIGITADO</strong>, seria correto. Como no arquivo .inc há apenas a chamada a Application.MessageBox, nós podemos incluir nosso arquivo em um local onde a chamada a esta função pode ser aplicada, por exemplo, o clique de um botão:<br />\r\n<pre class=\"language-pascal\"><code>procedure TForm1.Button1Click(Sender: TObject);\r\nbegin\r\n {$i minhamensagem.inc}\r\nend;</code></pre>\r\nComo se pode ver, para referenciar um arquivo de inclusão, se usa a diretiva {$I nomedoarquivo.inc}. A grande vantagem dos arquivos de inclusão só é percebida quando se entende que o trecho de código acima, na verdade é interpretado pelo compilador como:<br />\r\n<pre class=\"language-pascal\"><code>procedure TForm1.Button1Click(Sender: TObject);\r\nbegin\r\n Application.MessageBox(\'Eu fui definida em um arquivo .inc\'\r\n ,\'Mensagem do arquivo de inclusão\'\r\n ,MB_ICONWARNING);\r\nend;</code></pre>\r\nComo se pode observar o conteúdo do arquivo de inclusão é \"digitado\" no local onde ele for incluído, logo, o ponto no código-fonte onde arquivos de inclusão podem ser colocados depende unicamente de seu conteúdo. Você poderia colocar uma classe inteira, com todos os seus métodos definidos, dentro de um arquivo de inclusão, no entanto ele não poderia ser incluído dentro do clique de um botão, pois se você substituir, na posição do include, o conteúdo do arquivo de inclusão, o fonte .pas não vai compilar.</td>\r\n</tr>\r\n<tr>\r\n<th style=\"text-align: right;\" colspan=\"2\">Arquivos gerados (arquivos binários)</th>\r\n</tr>\r\n<tr style=\"display: none;\">\r\n<td colspan=\"2\"> </td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.dcu</td>\r\n<td style=\"text-align: justify;\"><strong>Delphi Compiled Unit</strong> - Todo arquivo .pas, ao ser compilado, gera um arquivo correspondente .dcu. Arquivos .dcu, em outras palavras, são a versão binária de um arquivo .pas. Linguagens como C e C++, possuem um arquivo chamado .obj que são gerados a partir de arquivos .c ou .cpp. Pode-se dizer que arquivos .dcu estão para arquivos .pas assim como arquivos .obj estão para arquivos .c ou .cpp. Arquivos .dcu são diferentes quando compilados por compiladores diferentes, isto é, se você tem um mesmo fonte .pas e compila este fonte no Delphi 2006 e no Delphi XE5, os arquivos .dcu gerados serão completamente diferentes, apesar de fazerem a mesma coisa. É este um dos motivos pelos quais não se pode instalar componentes sem fontes (sem arquivos .pas) em qualquer Delphi, porque os arquivos .pas, .bpl e .dcp são dependentes da versão do compilador e simplesmente são incompatíveis. Você só consegue instalar componentes sem fontes, quando estes 3 arquivos foram compilados exclusivamente para a versão do Delphi onde você pretende instalá-los</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.bpl</td>\r\n<td style=\"text-align: justify;\"><strong>Borland Package Library</strong> - Arquivos de projeto .dpr geram arquivos .exe ou .dll. Arquivos de projeto .dpk geram sempre dois arquivos. Um deles é o arquivo .bpl o outro é o arquivo .dcp (vide próximo ítem). Arquivos .bpl estão para projetos .dpk assim como arquivos .exe e .dll estão para projetos .dpr, logo, os arquivos .bpl são o resultado final mais importante da compilação de um pacote. Eles se assemelham estruturalmente a uma dll e como tal podem ser carregados por executáveis (Runtime Packages) e, no seu uso mais simples, carregadas pelo próprio Delphi (Designtime Packages). O carregamento por executáveis não será coberto neste artigo, apenas o carregamento simples, pela IDE, o qual é essencial para o entendimento de como ocorre a instalação de pacotes. Quando um pacote é instalado, na verdade, nós estamos informando ao Delphi que aquele determinado arquivo .bpl gerado, deve ser carregado pela IDE. A instalação deste arquivo fará com que componentes apareçam na paleta de componentes e experts/wizards sejam registrados (vide artigo <a href=\"index.php?option=com_content&amp;view=article&amp;id=122&amp;catid=80&amp;Itemid=493\">Open Tools API</a>).</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.dcp</td>\r\n<td style=\"text-align: justify;\"><strong>Delphi compiled package</strong> - O arquivo .dcp é gerado juntamente com o arquivo .bpl. Ele é um arquivo binário especial que contém o cabeçalho do pacote BPL e a concatenação de todos os arquivos .dcu deste pacote, bem como toda informação necessária requerida pelo compilador e pelo ligador (linker).<br /><br />Como se pode observar, o arquivo .dcp é como se fosse um resumo binário de todo o código-fonte do pacote, por isso, uma característica muito interessante deste arquivo é que ele substitui a presença de todos os arquivos .dcu que ele contém! De fato, quando um pacote faz referência em sua cláusula <strong>requires</strong> (veja mais adiante) a um arquivo .dcp, este pacote pode usar units que estão neste arquivo .dcp, como se as units compiladas (.dcu) estivessem fisicamente disponíveis! Em suma, eu não preciso ter nenhum arquivo .dcu disponível, caso eu possua o arquivo .dcp que o contenha.<br /><br />O papel do arquivo .dcp é muito relevante dentro desenvolvimento de pacotes no Delphi. Os arquivos .dpk possuem uma seção especial chamada <strong>requires</strong>, na qual outros pacotes são referenciados, veja:<br /><br /><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/requires.jpg\" alt=\"\" /><br />Como se pode ver, este pacote possui 3 dependências de outros pacotes. Significa que dentro do pacote nós estamos usando componentes, funções ou recursos de uma forma geral que estão disponíveis em outros pacotes. No pacote do exemplo acima eu estou fazendo referências ao TClientDataSet, o qual é definido na unit <em>DBClient</em> que foi compilada no pacote <a title=\"Dependendo da configuração da propriedade Lib Suffix o XXX pode ser substituído por uma string qualquer. Normalmente o Lib Suffix indica a versão do compilador. Por exemplo, se este pacote tivesse sido compilado no Delphi 2006, o nome do BPL gerado deveria ser dsnap100.bpl, pois a versão do compilador do Delphi 2006 é 10\" href=\"#\" rel=\"bookmark\">dsnapXXX.bpl</a> e por isso eu preciso fazer referência direta ao \"resumo\" deste pacote. Para isso eu uso seu arquivo .dcp correspondente (<a title=\"Arquivos DCP, ao contrário dos arquivos BPL não recebem o Lib Suffix, o qual é usado apenas nas saídas principais do compilador, isto é, apenas arquivos .exe, .dll e .bpl utilizam o Lib Suffix para formar o nome do arquivo\" href=\"#\" rel=\"bookmark\">dsnap.dcp</a>) na cláusula requires do .dpk, pois dentro de dsnap.dcp existe o arquivo DBClient.dcu.<br /><br />Apesar de eu estar falando que o arquivo .dcu está dentro do arquivo .dcp, isso é apenas para facilitar o entendimento. Arquivos .dcp não são contêineres, logo, não é possível extrair um arquivo .dcu de dentro do arquivo .dcp. O arquivo .dcp possui todo conteúdo binário de todos os arquivos .dcu de um pacote. O Delphi, seu compilador e seu linker fazem referência a parte desse código de forma nomeada, usando o mesmo nome da unit original, por exemplo, dentro de um pacote que requer dsnap.dcp, caso em uma unit eu declare na cláusula uses DBClient, o Delphi vai saber que o código desta unit está disponível. No momento da compilação, o compilador entende que deve procurar o código binário de DBClient dentro de dsnap.dcp.<br /><br />Arquivos .dcp são muito importantes quando precisamos nos referenciar ao nosso pacote a partir de outro, logo, isso não é algo que um iniciante no desenvolvimento de componentes vá fazer, portanto, não precisa se preocupar com os arquivos .dcp no momento. Apenas entenda que eles são necessários e não devem ser negligenciados.</td>\r\n</tr>\r\n<tr>\r\n<th style=\"text-align: right;\" colspan=\"2\">Arquivos de recurso (arquivos binários e de texto plano)</th>\r\n</tr>\r\n<tr style=\"display: none;\">\r\n<td colspan=\"2\"> </td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.res / .dcr</td>\r\n<td style=\"text-align: justify;\"><strong>Resource File</strong> - Arquivos de recurso com a extensão .res ou .dcr <span style=\"text-decoration: underline;\">são arquivos binários</span> que podem conter ícones, cursores, imagens, strings, teclas de atalho, menus, caixas de diálogo, dados binários sem formato específico (raw) e informações de versão. Normalmente no Delphi você não precisa se preocupar com arquivos de recurso, pois eles são criados automaticamente e incluídos no binário final (.exe, .dll, .bpl), contudo, ao desenvolver componentes especificamente, eventualmente você vai precisar incluir ao menos recursos de imagem e ícones no seu BPL e a única forma de fazer isso é por meio do uso de arquivos de recurso. Você pode criar um arquivo .res / .dcr usando um editor de recursos e vincular este arquivo de recurso ao seu projeto, incluindo a diretiva <strong>{$R nomedoarquivo.res}</strong> ou <strong>{$R nomedoarquivo.dcr}</strong> em algum fonte do mesmo (ou no seu arquivo de projeto). A inclusão pode usar um arquivo de texto plano também (vide .rc abaixo). Não existem diferenças práticas entre um .dcr e um .res, apenas convenciona-se usar a extensão .dcr para indicar um arquivo de recurso que possui os ícones de um componente que serão apresentados na paleta de componente do Delphi. DCR significa \"Delphi Component Resource\"</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.rc</td>\r\n<td style=\"text-align: justify;\"><strong>Compiler Resource File</strong> - Arquivos de recurso com a extensão .rc <span style=\"text-decoration: underline;\">são arquivos de texto plano</span> e que podem ser considerados \"código-fonte\" de recurso, pois é possível gerar um arquivo .res a partir de um arquivo .rc utilizando um compilador de recurso (<strong>Resource Compiler</strong>). A extensão .rc, portanto, remete ao nome Resource Compiler, já que este arquivo sempre precisa ser compilado antes de ser usado. Arquivos .rc podem conter exatamente os mesmos itens que um arquivo .res, a diferença é que estes ítens são incluídos no arquivo .rc de forma textual, \"legível por humanos\". Arquivos .rc não podem ser vinculados diretamente a um binário, tal como acontece com os arquivos .res, é necessário compilá-lo antes e, por este motivo, o Delphi possui uma sintaxe especial da diretiva {$R} que permite compilar e vincular um arquivo .rc. Utilizando <strong>{$R nomedoarquivo.res nomedoarquivo.rc}</strong>, <strong>nomedoarquivo.rc</strong> será automaticamente compilado e gerará o arquivo <strong>nomedoarquivo.res</strong>, o qual, finalmente, será vinculado pela diretiva</td>\r\n</tr>\r\n<tr>\r\n<td style=\"vertical-align: top;\">.dfm</td>\r\n<td style=\"text-align: justify;\"><strong>Delphi Form File</strong> - Você deve estar se perguntando porque arquivos .dfm estão incluídos nesta lista de recursos, bom, se segure na cadeira meu caro, mas <strong>arquivos .dfm são arquivos de recurso</strong>! Você não leu errado. Arquivos .dfm são arquivos de recurso especiais e exclusivos do Delphi e que contém referências a todas as propriedades publicadss do TForm e de todos os componentes nele incluídos. Propriedades publicadas, ou published, são propriedades que geram Informações de Tipo em Tempo de Execução, ou RTTI. Se você abrir um executável, por exemplo, em um editor de recurso, e for na seção <strong>RCData</strong>, você verá todos os seus formulários lá, veja:<br /><br /><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/rcdata.jpg\" alt=\"\" /><br />Note que as propriedades publicadas do TForm aparecem, bem como as propriedades publicadas de outros componentes inseridos no TForm, tal como o TButton que se pode ver na imagem acima. Você deve estar pensando agora se é possível modificar algumas destas propriedades diretamente no arquivo binário usando o editor de recurso, e, bem, sim, isso é totalmente possível! Qualquer uma destas propriedades pode ser alterada e salva diretamente no arquivo binário, no caso no .exe, sem necessidade de recompilá-lo, e isso vai alterar o resultado da aplicação em tempo de execução, porém, devo alertar que algumas coisas não devem ser alteradas, sob pena de você inutilizar seu executável. Arquivos .dfm podem ser salvos de forma binária o que não é recomendável, mas mesmo quando eles são salvos desta forma, dentro do binário compilado sua representação sempre é textual. Isso significa que o modo binário de salvamento de arquivos .dfm só afeta de fato o arquivo em si e não a forma como ele é vinculado ao projeto finalizado (.exe, .dll ou .bpl).<br /><br />Outra prova inegável de que arquivos .dfm são, também, arquivos de recuso, é a forma como eles são vinculados aos projetos. Se você criar um projeto novo e olhar o código-fonte do único formulário você verá a seguinte linha <strong>{$R *.dfm}</strong>. A diretiva {$R} você já conhece, ela serve para vincular um arquivo de recurso ao projeto, logo, o nome de arquivo que vem depois dela, é um arquivo de recurso. Mas tem algo diferente, você diz, \"não existe um nome de arquivo, mas sim um caractere curinga com a extensão .dfm\". Se você pensou isso você está errado. O asterisco parece, mas <strong>não é um caractere curinga e *.dfm não significa, portanto, todos os arquivos com extensão .dfm</strong>. A diretiva {$R} interpreta o asterisco como sendo o nome-base da unit atual, isto é, o nome da unit sem a extensão, logo, se sua unit se chama UFormPrincipal.pas, usar a diretiva {$R *.dfm} nela vai instruir ao Delphi para vincular ao projeto o arquivo UFormPrincipal.dfm. É por este motivo que toda vez que você salva a unit de um TForm, um arquivo .dfm de mesmo nome será gerado juntamente com ela. Se você alterar a diretiva e colocar o nome do arquivo .dfm completo, vai funcionar do mesmo modo, no entanto, isso é desencorajado, na maioria das situações, quando você não sabe o que está fazendo, pois, caso você altere o nome da unit, um novo .dfm será criado para ela, mas, internamente, ela estará vinculada a um outro arquivo .dfm, o que pode gerar uma grande confusão. O caractere especial \"*\" também pode ser usado ao fazer referência a um arquivo .res propriamente dito, tendo, pois, o mesmo significado!<br /><br />Para saber um pouco mais sobre RTTI, arquivos .dfm e um uso inusitado dessa combinação de tecnologias, leia o artigo <a href=\"index.php?option=com_content&amp;view=article&amp;id=97&amp;catid=80&amp;Itemid=493\">Serialização de Objetos &amp; Persistência em Arquivos</a>.</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n</div>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>Arquivos gerados pela compilação de um pacote</h2>\r\n<p style=\"text-align: justify;\">Ao contrário de um executável ou de um biblioteca (dll) a compilação de um pacote gera 3 tipos de arquivo importantes:</p>\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Arquivo BPL</strong> - Cada pacote gera um e apenas um arquivo BPL. Arquivos BPL podem ser compilados de acordo com o uso que eles terão. Esta configuração chama-se \"Usage Option\" e está disponível no item (ou aba) \"Description\" da caixa de diálogo \"Project Options\". Existem 3 formas de uso para um BPL:<br /><br />\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Designtime Only</strong> - BPLs desse tipo são desenvolvidos para serem instalados na IDE e por este motivo eles normalmente possuem apenas código que só faz sentido dentro da IDE. Este código inclui basicamente editores de componente, editores de propriedade e código de registro que normalmente é colocado dentro do procedure especial \"Register\". Não é comum desenvolver um BPL deste tipo que não contenha alguns destes códigos específicos. Se sua intenção é desenvolver um pacote que contenha apenas units e funções utilizáveis por projetos, você deve desenvolver um pacote \"Runtime Only\"<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Runtime Only</strong> - BPLs desse tipo são desenvolvidos para serem usados como pacote em tempo de execução por executáveis ou internamente pela IDE em tempo de desenvolvimento por projetos. Este tipo de BPL não é instalável, então ele não pode conter códigos dos tipos mencionados no item anterior (Designtime Only). Pacotes deste tipo podem conter, portanto, todo o restante de possíveis códigos, incluindo o código de componentes que são instalados em pacotes do tipo Designtime Only<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Designtime and Runtime</strong> - BPLs deste tipo possuem uma junção de características dos dois tipos anteriores. Em outras palavras, pacotes deste tipo contém componentes e também podem ser carregados por executáveis em tempo de execução</li>\r\n</ul>\r\n</li>\r\n<li style=\"text-align: justify;\"><strong>Arquivo DCP</strong> - Concatenação binária de todas as units de um pacote sendo compilado (BPL). Vide explicação sobre arquivos .dcp na tabela acima.</li>\r\n</ul>\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Arquivo DCU</strong> - Arquivos de fonte compilados (arquivos .pas compilados). Vide explicação sobre arquivos .dcu na tabela acima. Os arquivos .dcu são tão importantes em um pacote quanto o próprio arquivo .bpl que é gerado. Enquanto para um executável normal ou biblioteca, arquivos .dcu são apenas arquivos intermediários, para os pacotes estes arquivos são essenciais para que o componente possa ser usado. Arquivos .dcu de um pacote são SEMPRE arquivos intermediários de outros projetos que usam units desse pacote. De forma mais simples, arquivos .dcu de um componente são arquivos intermediários quando compilamos projetos que usam este componente e é por isso que os arquivos .dcu de um pacote precisam sempre estar disponíveis via \"paths do Delphi\" (leia mais adiante)</li>\r\n</ul>\r\n<hr class=\"system-pagebreak\" title=\"Como o Delphi encontra os arquivos de um pacote?\" alt=\"Como o Delphi encontra os arquivos de um pacote?\" />\r\n<h2>Como o Delphi encontra os arquivos de um pacote?</h2>\r\n<p style=\"text-align: justify;\">É de extrema importância conhecer como o Delphi funciona para poder saber resolver problemas comuns. Entender como o Delphi encontra os arquivos de um pacote é um requisito básico, seja você um desenvolvedor comum ou um desenvolvedor de componentes. Como desenvolvedor comum, por exemplo, se você já programa há algum tempo e já instalou componentes, certamente você já deve ter visto uma mensagem parecida com esta:</p>\r\n<blockquote>\r\n<p style=\"text-align: center;\">Unit MinhaUnit was compiled with a different version of MinhaOutraUnit.TMinhaClasse</p>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">Este é um dos erros mais frequentes causados por uma instalação inadequada de pacotes e pode ocorrer até mesmo dentro de projetos comuns (não pacotes), sendo mais raros nestes últimos. Ao entender como o Delphi encontra os arquivos de um projeto qualquer ficará mais fácil resolver problemas como este, bem como evitar que eles ocorram, fazendo sempre o uso correto das configurações de \"Paths\" que o Delphi considera.</p>\r\n<p style=\"text-align: justify;\">A forma como o Delphi procura os arquivos de um pacote é a mesma forma que ele usa para encontrar os arquivos de qualquer projeto que nele se compila. Antes de explicar como isso é feito, é necessário entender que uma unit pode estar disponível de forma compilada (.dcu) ou código-fonte (.pas) e o Delphi tem preferências especiais quando encontra estes arquivos:</p>\r\n<ul>\r\n<li style=\"text-align: justify;\">Se estiver disponível apenas o arquivo .pas ele será usado, sendo compilado normalmente<br /><br /></li>\r\n<li style=\"text-align: justify;\">Se estiver disponível apenas o arquivo .dcu ele será usado, mas não será compilado, porque não é necessário<br /><br /></li>\r\n<li style=\"text-align: justify;\">Se ambos os arquivos estiverem disponíveis, será usado sempre o arquivo .pas, o qual será compilado normalmente</li>\r\n</ul>\r\n<p style=\"text-align: justify;\">De agora em diante ao me referenciar a <strong>uma unit</strong> eu estarei falando de um arquivo que representa uma unit do Delphi e que pode ser, ou um .dcu, ou um .pas. Isso servirá apenas para que eu não tenha que me referir aos dois arquivos, que no final representam a mesma coisa de formas diferentes.</p>\r\n<p style=\"text-align: justify;\">Finalmente, conhecendo a ordem de preferência que o Delphi usa para selecionar uma unit, podemos agora verificar de forma simples e linear (em ordem de busca), como ele faz para achar as units que estão referenciadas nas cláusulas uses:</p>\r\n<ol>\r\n<li style=\"text-align: justify;\">Procura dentre as units listadas explicitamente no arquivo .dpk<br /><br /></li>\r\n<li style=\"text-align: justify;\">Procura no mesmo diretório que contém o arquivo .dpk<br /><br /></li>\r\n<li>Procura dentre os caminhos listados no Search Path (projeto)<br /><br /></li>\r\n<li>Procura dentre os caminhos listados no Library Path (global)</li>\r\n</ol>\r\n<p>Caso uma unit não esteja em nenhum destes 4 lugares o seu projeto não vai compilar de jeito nenhum, mas gostaria de relatar aqui algo que constatei. Vou até deixar este relato destacado.</p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">Nos testes que eu fiz para determinar os 4 locais de busca, aconteceu algo muito estranho. Eu compilei um projeto de teste com uma unit na mesma pasta do arquivo .dpk, em seguida a apaguei esperando receber um erro de compilação, já que a unit não existia mais. Para minha surpresa o projeto compilou normalmente e até mesmo o arquivo .dcu correspondente ao arquivo .pas que eu apaguei foi criado! Não consegui descobrir como o compilador fez isso, mas ao fechar e abrir o Delphi o comportamento foi o esperado, isto é, o projeto não mais compilou. Até onde eu sei, isso é um comportamento muito bizarro, portanto, fica como dica de boa prática, fechar o Delphi e abri-lo novamente, sempre que se mover ou apagar units, principalmente quando se estiver desenvolvendo componentes, já que é imprescindível que os arquivos sendo referenciados pelo projeto existam de fato e não por conta de algum <strong>cache sobrenatural</strong></p>\r\n</blockquote>\r\n<div> </div>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">Além de units, um esquema de busca semelhante é usado para outros arquivos do projeto, tais como arquivos .res, .dfm e .inc. Estes arquivos são incluídos no projeto por diretivas especiais {$R}, para arquivos .res e .dfm, e {$I}, para arquivos .inc. Ambas as diretivas aceitam o caractere especial \"*\" (veja o significado deste caractere na explicação sobre arquivos .dfm, mais acima) e também um caminho que pode ser absoluto ou relativo. Vejamos alguns pormenores de cada uma destas formas de uso das diretivas:</p>\r\n<ul>\r\n<li style=\"text-align: justify;\">Ao usar caminhos absolutos, caso este caminho contenha espaços, aspas simples devem ser usadas em volta do mesmo. Referências por caminhos absolutos, como é de se imaginar, não têm ambiguidades, logo não há dúvidas de que um arquivo referenciado desta forma deve existir impreterivelmente no local indicado e ponto final. Já ao usar caminhos relativos, será considerado como ponto de partida o diretório onde a unit com a referência a {$R} ou {$I} estiver. A regra de uso de aspas simples também se aplica aqui, bem como o fato de que o caminho é totalmente conhecido e sem ambiguidades<br /><br /></li>\r\n<li style=\"text-align: justify;\">Ao usar o caractere <strong>*</strong> é necessário entender que ele se transforma meramente no nome da unit onde a referência a {$R} ou {$I} estiver, portanto, <strong>{$I *.inc}</strong> dentro de uma unit de nome <strong>teste.pas</strong>, na verdade deve ser lida como <strong>{$I teste.inc}</strong></li>\r\n</ul>\r\n<p>No segundo uso mostrado acima, como teremos apenas o nome de um arquivo, sem caminhos relativos ou completos, a busca por ele seguirá a seguinte regra:</p>\r\n<ol>\r\n<li style=\"text-align: justify;\">Procura no mesmo diretório onde a unit com a referência a {$R} ou {$I} estiver<br /><br /></li>\r\n<li style=\"text-align: justify;\">Procura no mesmo diretório que contém o arquivo .dpk<br /><br /></li>\r\n<li>Procura dentre os caminhos listados no Search Path (projeto)<br /><br /></li>\r\n<li>Procura dentre os caminhos listados no Library Path (global)</li>\r\n</ol>\r\n<p style=\"text-align: justify;\">Foi detectado que o problema do <em>cache sobrenatural</em> descrito no quadro acima também afeta estes arquivos especiais, só que, ao contrário das units, o problema ocorreu ao remover um arquivo .inc que estava na mesma pasta de uma unit que o usava. Mesmo sem o arquivo .inc presente, ainda assim a compilação foi bem sucedida e o arquivo .inc carregado era aquele que estaria na pasta. Bizarro! Ao reiniciar o Delphi o comportamento foi o esperado mais uma vez, portanto, muito cuidado ao mover ou excluir tais arquivos. Lembre-se sempre de reiniciar o Delphi.</p>\r\n<blockquote>\r\n<p style=\"text-align: justify;\">O Delphi não busca arquivos em caminhos listados no Path do Windows. Isso é uma má prática hoje em dia. Não polua seu sistema ou o de seus clientes com arquivos desnecessariamente. <strong>Apenas arquivos .bpl que são carregados pelo Delphi</strong>, precisam estar em caminhos listados no Path do Windows e mesmo assim estes caminhos são exclusivos no Delphi, ou seja, não espere encontrar arquivos .bpl dentro de pastas como C:\\Windows\\System32, C:\\Windows\\System ou C:\\Windows\\SysWOW64. <strong>A prática de colocar estes arquivos nestes caminhos de sistema foi felizmente abolida! Se você é um programador das antigas, já deve ter colocado algumas BPLs na pasta System ou System32, mas não faça mais isso!</strong> Existe uma pasta específica para este tipo de arquivo. Esta pasta pode ser configurada no mesmo local onde se encontram o Library Path e o Browsing Path (explicados posteriormente neste artigo). A configuração se chama <strong>Package Output Directory</strong>. Os nome desta configuração pode variar um pouco, mas não será difícil identificá-la.</p>\r\n</blockquote>\r\n<hr class=\"system-pagebreak\" title=\"Apresentando os vilões: Search Path &amp; Library Path\" alt=\"Apresentando os vilões: Search Path &amp; Library Path\" />\r\n<h2>Apresentando os vilões: Search Path &amp; Library Path</h2>\r\n<p style=\"text-align: justify;\">Sim! Estas duas configurações são maliciosas e são a causa de muitos problemas de instalação de pacotes e até mesmo de compilação de projetos em geral. Na verdade a maior vantagem de ambas é também sua maior desvantagem: <strong>a versatilidade!</strong> De tão versáteis, estas propriedades se tornam perigosas aos incautos e eu vou explicar o porquê.</p>\r\n<p style=\"text-align: justify;\">Bem, um path funciona listando vários diretórios (pastas) de busca. Suponha que você tenha uns 100 diretórios listados, neste caso os arquivos que o Delphi procura podem estar em quaisquer destes diretórios, inclusive em mais de um deles e é aí onde está o lado negro dessa propriedade. Se você faz referência a <strong>MinhaUnit</strong> em uma cláusula uses e existe MinhaUnit.pas (ou .dcu) em mais de um desses 100 diretórios, o Delphi vai usar aquele que achar primeiro, segundo a ordem da lista de diretórios. Veja, por exemplo, a lista de um Library Path típico:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/LibraryPath.jpg\" width=\"479\" height=\"305\" /></p>\r\n<p style=\"text-align: justify;\">Acima, a ordem que o Delphi realiza a busca por um arquivo é, de fato, de cima para baixo. Se nossa unit estiver em todos estes caminhos, o Delphi vai usar a versão que está no primeiro diretório listado e vai ignorar a presença de tal unit nos demais. Se a versão contida no primeiro diretório for mais antiga do que aquela que está nos outros, podem haver erros de compilação ou comportamentos errados de um programa que use esta unit.</p>\r\n<p style=\"text-align: justify;\">Caso no path escolhido pelo Delphi esteja uma versão compilada (.dcu) ela será usada, tal como foi dito anteriormente, mas caso este arquivo .dcu seja uma compilação de uma versão diferente daquela que se espera, a famosa mensagem \"Unit MinhaUnit was compiled with a different version of MinhaOutraUnit.TMinhaClasse\" será exibida! Ignore a posição de MinhaUnit nesta mensagem. Ela poderia estar no lugar de MinhaOutraUnit, não importa, o que importa é que este tipo de erro acontece por existirem versões de arquivos .dcu diferentes daquelas que deveriam existir.</p>\r\n<p style=\"text-align: justify;\">Se você estiver tendo alguns dos problemas listados aqui, o primeiro passo é procurar nos caminhos listados tanto no Library Path como no Search Path do projeto as units problemáticas e verificar se elas não se repetem, mantendo apenas uma cópia de cada uma no seu caminho correto. Procure sempre por nomedaunit.* e mantenha inicialmente apenas arquivos .pas. Isso é uma regra geral para ajudar a resolver problemas rapidamente, mas como eu explicarei posteriormente neste artigo, devemos manter no Library Path apenas arquivos .dcu, .res, .inc e .dfm, enquanto que no Search Path só devem existir arquivos .pas.</p>\r\n<p style=\"text-align: justify;\">A fim de tirar você da ignorância quanto à instalação de pacotes eu fiz este artigo e a partir deste ponto eu vou explicar para que servem cada uma das configurações, de forma que você as use corretamente e possa amaldiçoar quem as usa de forma errada.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>O que é o Search Path?</h2>\r\n<p style=\"text-align: justify;\">Todos os projetos no Delphi possuem o Search Path que nada mais é do que uma coleção de caminhos (paths) onde o Delphi busca por arquivos que são referenciados dentro do projeto em cláusulas uses ou diretivas {$R} ou {$I}. O Search Path deve ser considerado como uma lista privada de caminhos acessíveis apenas pelo projeto onde ele for configurado.</p>\r\n<p style=\"text-align: justify;\">Suponha que você possui um sistema dividido em módulos executáveis. Neste caso você terá n projetos Delphi, e caso dentro deste sistema, projetos distintos utilizem uma mesma unit, esta unit pode ficar em um único local e ser referenciada por cada um dos projetos por meio do Search Path, configurado individualmente em cada um deles.</p>\r\n<p style=\"text-align: justify;\">Um exemplo de uso real disso é quando se desenvolve uma aplicação DataSnap, a qual tem no mínimo dois projetos, um para o cliente (Thin Client) e outro para a camada do meio (MiddleWare). Ambos os módulos fazem parte de um único sistema (separado pelo DataSnap), logo eles podem compartilhar arquivos entre si e estes arquivos devem ser referenciadas por meio do Search Path de cada um dos projetos (Thin Client e MiddleWare).</p>\r\n<p style=\"text-align: justify;\">Falando especificamente de units, tanto arquivos .dcu como arquivos .pas podem existir nos caminhos do Search Path, no entanto, como ele é uma coleção de <strong>caminhos de busca de um projeto específico</strong>, fica claro que <strong>arquivos listados no Search Path fazem parte do código-fonte do projeto</strong> onde ele for definido, logo, as units presentes nos caminhos de um Search Path <strong>devem ser arquivos .pas</strong>.</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/SearchPath.jpg\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\">Acima podemos ver, mais ao fundo, a caixa de diálogo Project Options, que pode ser acessada através do menu <strong>Project &gt; Options</strong> ou através da combinação de teclas <strong>Shift+Ctrl+F11</strong>. A localização da configuração do Search Path varia de acordo com a versão do Delphi. A imagem mostra a versão do Delphi XE5, mas se seu Delphi não apresentar a caixa de diálogo como na imagem, certamente será fácil de achar esta configuração.</p>\r\n<p style=\"text-align: justify;\">Clicando no botão de reticências vai exibir o editor do Search Path, o qual, na imagem, mostra 3 caminhos. Ao compilar este projeto estes 3 caminhos serão vasculhados em busca de arquivos referenciados em cláusulas uses e diretivas {$R} e {$I}.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2 style=\"text-align: justify;\">O papel do Search Path nos pacotes</h2>\r\n<p style=\"text-align: justify;\">O Search Path parece ser bem útil para organização de projetos, no entanto, no tocante aos pacotes especificamente, seu uso deve ser limitado apenas para indicar caminhos com arquivos .res, .dcr, .rc, .dfm e .inc. O motivo disso é que o Delphi não permite que pacotes distintos contenham units compartilhadas entre si.</p>\r\n<p style=\"text-align: justify;\">Se você usar o Search Path para compartilhar units entre pacotes distintos, duas coisas vão acontecer. No caso mais brando será emitido um aviso ao compilar, e no caso mais grave seu pacote não será compilado ou não poderá ser carregado pelo Delphi.</p>\r\n<p style=\"text-align: justify;\">No primeiro caso, a referência indireta por meio de Search Path vai gerar o seguinte aviso:</p>\r\n<blockquote>\r\n<p style=\"text-align: center;\">[dcc32 Warning] MeuPacote.dpk(88): W1033 Unit \'UMinhaUnit\' implicitly imported into package \'MeuPacote\'</p>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">A ajuda do Delphi é clara a respeito deste aviso, quando diz \"<em>This message will help the programmer avoid violating the rule that a unit may not reside in more than one related package</em>\", ou seja, pacotes relacionados não podem conter referências às mesmas units. Um pacote está relacionado a outro quando, por exemplo, <strong>PackageB.bpl</strong> depende de <strong>PackageA.bpl</strong>, porque <strong>PackageB.bpl</strong> contém em sua cláusula requires uma referência a <strong>PackageA.dcp</strong>. Quando dois pacotes estão relacioados desta forma apenas um dos pacotes precisa conter diretamente todas as units, por exemplo, suponha que <strong>PackageA.bpl</strong> contenha as units <strong>Unit1.pas</strong>, <strong>Unit2.pas</strong> e <strong>Unit3.pas</strong>. Suponha que <strong>PackageB.bpl</strong> também precise destas units (todas ou algumas delas, não importa). Neste caso, é suficiente que <strong>PackageB.bpl</strong> contenha na sua cláusula requires uma referência a <strong>PackageA.dcp</strong> para que ele \"enxergue\" e use todas as units que existem em <strong>PackageA.bpl</strong>, sem necessidade de duplicar ou compartilhar units.</p>\r\n<p style=\"text-align: justify;\">O segundo problema vai acontecer se você carregar (instalar) um pacote e depois tentar compilar um outro pacote que tem units compartilhadas com o primeiro, o seguinte erro de compilação vai aparecer:</p>\r\n<blockquote>\r\n<p style=\"text-align: center;\">[dcc32 Error] MeuPacote.dpk(45): E2200 Package \'MeuOutroPacote\' already contains unit \'MinhUnit\'</p>\r\n</blockquote>\r\n<p>Caso você consiga compilar os dois pacotes com units compartilhadas entre si e carregar um deles, ao tentar carregar o segundo, o seguinte erro será exibido:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/SearchPathErro.jpg\" alt=\"\" /></p>\r\n<p>Em suma, o Delphi vai dar um jeito de evitar que você faça esse tipo de coisa, portanto, vou deixar abaixo um aviso importante:</p>\r\n<blockquote>\r\n<p style=\"text-align: center;\"><span style=\"color: #ffff00;\">NÃO USE O SEARCH PATH PARA COMPARTILHAR UNITS ENTRE PACOTES. AO INVÉS DISSO, COLOQUE TODAS AS UNITS COMPARTILHÁVEIS EM UM DOS PACOTES E FAÇA COM QUE OUTROS PACOTES DEPENDAM DELE</span></p>\r\n</blockquote>\r\n<h2>O que é o Library Path?</h2>\r\n<p style=\"text-align: justify;\">O Library Path é uma configuração que afeta todos os projetos (configuração global) e sua definição é basicamente a mesma do Search Path. Ele é, pois, uma coleção de paths onde o Delphi busca por arquivos. A diferença entre o Library Path e o Search Path é apenas quanto aos tipos de units que devem ser encontradas em cada um deles e quanto a sua especificidade.</p>\r\n<p style=\"text-align: justify;\">Quanto aos tipos de units, enquanto no Search Path devemos ter apenas units não compiladas (.pas), no Library Path devemos ter apenas units compiladas (.dcu). A especificidade refere-se ao quão as units estão relacionadas ao projeto. Observe a imagem a seguir:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/ordemdebusca.png\" width=\"400\" height=\"400\" /></p>\r\n<p style=\"text-align: justify;\">Nesta imagem, a busca por units se dá no sentido das setas. Inicialmente se busca dentre as units do próprio projeto, em seguida se tenta encontrar as units no Search Path e por fim no Library Path. <strong>Units que pertencem diretamente ao projeto devem ser exclusivamente arquivos .pas</strong>, pois estes arquivos podem ser editados por nós e compilados posteriormente para gerar o arquivo final de nosso projeto (.exe, .dll, .bpl, etc.).</p>\r\n<p style=\"text-align: justify;\"><strong>Units que estão no Search Path também devem ser arquivos .pas, e também pertencem ao projeto, pois o Search Path é uma configuração específica de cada projeto</strong>, a diferença é que as units acessadas via Search Path também podem ser usadas por outros projetos em um sistema que utiliza vários módulos (várias DLLs, vários executáveis, etc.). Faz sentido que projetos distintos façam uso de units em comum, quando estas units compartilharem código que pertença exclusivamente a estes projetos, seja por conterem regras de negócios específicas, seja por fazerem parte de algum framework customizado para alguns projetos apenas. Estas units, portanto, podem ser colocadas em diretórios que estão fora da hierarquia de diretórios dos projetos e poderão ser encontradas via Search Path.</p>\r\n<p style=\"text-align: justify;\"><strong>Units que estão no Library Path devem ser exclusivamente arquios .dcu</strong>. Esta é a dica de ouro que justifica a existência de todo este artigo. Observe novamente a tela de edição do Library Path:</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/LibraryPath.jpg\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\">O primeiro path referenciado no Library Path informa ao Delphi onde encontrar todas as units compiladas (.dcu) de sistema. Units de sistema são units do próprio Delphi, que nós usamos frequentemente, tais como StdCtrls, SysUtils, StrUtils, dentre outras. Se você remover este path o Delphi vai parar de funcionar. No caminho indicado, caso você tenha curiosidade, todos os arquivos presentes são binários e lá, além de encontrarmos arquivos .dcu, também encontraremos alguns arquivos .dfm.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<p style=\"text-align: justify;\">O Library Path, claro, também funciona apontando para caminhos com arquivos .pas, no entanto, por esta ser uma configuração global, não faz sentido que projetos completamente distintos compilem esses arquivos .pas toda vez, que é justamente o que acontece quando arquivos .pas existem no Library Path.</p>\r\n<p style=\"text-align: justify;\">Isso mesmo, arquivos de código-fonte .pas encontrados via Library Path são compilados separadamente por cada projeto que fizer referência a suas units, e estas units são salvas no <strong>Unit Output Directory</strong> (veja mais adiante neste artigo) do projeto, dando a falsa impressão de que aquela unit pertence ao projeto diretamente, quando na verdade ela deveria ter sido apenas referenciada de forma binária indiretamente, para apenas ser usada na fase de linking de um projeto.</p>\r\n<p style=\"text-align: justify;\">Units encontradas via Library Path não precisam ser modificadas e consequentemente não precisam ser compiladas, além disso, elas podem ser usadas por quaisquer de nossos projetos, portanto, elas não podem estar ligadas a projetos específicos, como acontece com o Search Path.</p>\r\n<p style=\"text-align: justify;\">Quando o Library Path está configurado corretamente, nenhuma de suas units será incluída no Unit Output Directory de nenhum projeto e consequentemente projetos diferentes não conterão sua própria versão de um .dcu que deveria ser único, por nunca precisar sofrer alterações por ser genérico (utilizável em vários projetos diferentes).</p>\r\n<p style=\"text-align: justify;\">O fato de encontrarmos apenas units compiladas no Library Path nos leva a concluir que em algum momento elas foram compiladas, portanto, units presentes no Library Path foram criadas durante a compilação de algum pacote, logo, normalmente os caminhos existentes no Library Path pertencem, de uma forma ou de outra, a pacotes. </p>\r\n<hr class=\"system-pagebreak\" title=\"Outros paths que o Delphi considera\" alt=\"Outros paths que o Delphi considera\" />\r\n<h2>O que é o Browsing Path?</h2>\r\n<p style=\"text-align: justify;\">O Browsing Path é uma configuração global que nada mais é do que uma lista de diretórios onde nós encontramos os códigos-fonte correspondentes de units que estão disponíveis para compilação apenas em formato binário. Se você configurou corretamente o seu Library Path para apontar apenas para arquivos .dcu, vai notar que, dentro de algum projeto, ao tentar acessar uma unit disponível no Library Path via CTRL+ENTER, ou executar um CTRL+Clique em um identificador declarado numa destas units, o Delphi vai emitir um aviso igual ao da imagem abaixo (ou mostrará uma caixa de diálogo padrão \"Open File\"):</p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/Browsing.jpg\" alt=\"\" /></p>\r\n<p style=\"text-align: justify;\"><strong>O Browsing Path informa à IDE onde estão os arquivos .pas com o intuito apenas de abrí-los, e não de compilá-los!</strong> O Browsing Path pode até ficar vazio, no entanto você não terá a facilidade de navegar (browse) facilmente através das units. Se você quiser ter essa facilidade enquanto estiver trabalhando, certifique-se de que no Browsing Path estejam incluídos todos os diretórios que contém os arquivos .pas correspondentes aos arquivos .dcu encontrados via Library Path.</p>\r\n<h2>O que é o Package Output Directory?</h2>\r\n<p style=\"text-align: justify;\">O Package Output Directory é uma configuração global na qual é definido o caminho padrão onde o Delphi salva e encontra arquivos BPL. Ao compilar um pacote o arquivo BPL gerado é posto sempre neste diretório. É possível alterar o local de salvamento do BPL nas opções específicas do projeto de um pacote (arquivo .dpk), por meio da configuração \"Output Directory\" (veja mais adiante), mas isso é totalmente desencorajado! O correto é sempre definir o Package Output Directory e manter o Output Directory dos projetos de pacotes sempre em branco.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>O que é o DCP Output Directory?</h2>\r\n<p style=\"text-align: justify;\">O DCP Output Directory é uma configuração global e local (a nível de projeto) na qual é definido o caminho padrão onde o Delphi salva e encontra arquivos DCP. Ao compilar um pacote o arquivo DCP gerado é posto sempre neste diretório. É possível alterar o local de salvamento do DCP nas opções específicas do projeto de um pacote (arquivo .dpk), por meio da configuração de mesmo nome (DCP Output Directory), mas isso é totalmente desencorajado! O correto é sempre definir o DCP Output Directory global e manter o DCP Output Directory dos projetos de pacotes sempre em branco.</p>\r\n<h2>O que é o Output Directory?</h2>\r\n<p style=\"text-align: justify;\">O Output Directory é uma configuração local de cada projeto e serve para indicar o local onde os binários finalizados serão salvos. Um binário finalizado é o resultado final de uma compilação. Para projetos comuns este binário pode ser um executável ou uma dll. Para projetos de pacotes são gerados dois binários, um é o BPL e o otro é o DCP. A recomendação é que, em projetos comuns, o Output Directory seja sempre configurado como um diretório que esteja preferencialmente dentro da hierarquia do projeto e para projetos de pacotes a recomendação é que esta configuração seja deixada em branco, de forma que os arquivos BPL sejam gerados no local especificado pela configuração global \"Package Output Directory\".</p>\r\n<h2>O que é o Unit Output Directory?</h2>\r\n<p style=\"text-align: justify;\">O Unit Output Directory é uma configuração local de cada projeto e serve para indicar o local onde as units compiladas (arquivos .dcu) serão salvas. Apenas para projetos de pacotes, o Unit Output Directory deve ser incluído no Library Path a fim de que outros projetos que utilizem tais units as encontrem. Em outras palavras, quando instalamos componentes construídos de forma correta, sempre é necessário incluir no Library Path o caminho definido no Unit Output Directory do projeto do pacote, de forma que projetos que fazem uso destes componentes compilem sem problemas.</p>\r\n<hr class=\"system-pagebreak\" title=\"Paths e tipos de arquivo (resumo)\" alt=\"Paths e tipos de arquivo (resumo)\" />\r\n<h2>Paths e tipos de arquivo (resumo)</h2>\r\n<p style=\"text-align: justify;\">Abaixo está uma tabela que resume quais arquivos podem existir em cada um dos paths que o Delphi considera. Obviamente caso seu projeto não utilize alguns dos arquivos mencionados, não significa que você precisa usá-los, mas caso faça uso deles, esta tabela será sua grande amiga daqui pra frente. Eu não vou chamar esta tabela de recomendação pessoal, porque eu tenho visto muita gente fazendo uso dos paths de forma totalmente errada, portanto, eu considero a minha abordagem como um <strong>guia definitivo para minimizar problemas</strong>. Tem horas que, para o bem maior, a gente não pode ser um \"falso modesto\". Use a tabela ou continue fazendo errado. A escolha é sua</p>\r\n<div class=\"autooverflowx\">\r\n<table>\r\n<thead>\r\n<tr>\r\n<th style=\"width: 34%;\"> </th>\r\n<th style=\"width: 6%;\">.pas</th>\r\n<th style=\"width: 6%;\">.dcu</th>\r\n<th style=\"width: 6%;\">.res</th>\r\n<th style=\"width: 6%;\">.rc</th>\r\n<th style=\"width: 6%;\">.dcr</th>\r\n<th style=\"width: 6%;\">.dfm</th>\r\n<th style=\"width: 6%;\">.inc</th>\r\n<th style=\"width: 6%;\">.bpl</th>\r\n<th style=\"width: 6%;\">.dcp</th>\r\n<th style=\"width: 6%;\">.exe</th>\r\n<th style=\"width: 6%;\">.dll</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n<tr>\r\n<td>Search Path</td>\r\n<td>X *</td>\r\n<td> </td>\r\n<td>X</td>\r\n<td>X</td>\r\n<td>X</td>\r\n<td>X</td>\r\n<td>X</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n<tr>\r\n<td>Library Path</td>\r\n<td> </td>\r\n<td>X</td>\r\n<td>X **</td>\r\n<td> </td>\r\n<td> </td>\r\n<td>X **</td>\r\n<td>X **</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n<tr>\r\n<td>Browsing Path</td>\r\n<td>X</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n<tr>\r\n<td>Package Output Directory</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td>X</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n<tr>\r\n<td>DCP Output Directory</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td>X</td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n<tr>\r\n<td>Output Directory</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td>X</td>\r\n<td>X</td>\r\n</tr>\r\n<tr>\r\n<td>Unit Output Directory</td>\r\n<td> </td>\r\n<td>X</td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n<td> </td>\r\n</tr>\r\n</tbody>\r\n<caption>* Este arquivo só deve ser incluído no Search Path caso você esteja compilando um projeto normal. O Search Path não deve ser usado para referenciar units em projetos de pacotes porque o Delphi não gosta de units com o mesmo nome em pacotes (BPLs) distintos.<br /> <br />** Este arquivo só deve ser incluído no Library Path caso ele seja requerido durante a compilação de outros projetos. No caso dos arquivos res e inc, se eles forem utilizados apenas pelo pacote no momento da geração do BPL, eles não precisam ser incluídos no Library Path. No caso dos arquivos dfm, se eles representarem telas que são acessadas apenas em tempo de projeto, tais como telas de editores de propriedade e de componentes, eles não precisam ser incluídos no Library Path</caption></table>\r\n</div>\r\n<hr class=\"adsensesnippet\" />\r\n<h2>Proposta de organização de projetos e pacotes</h2>\r\n<p style=\"text-align: justify;\">Organização é tudo, então resolvi terminar esse artigo com uma proposta de organização de pastas de projetos que vai facilitar sua vida, caso você decida começar a usar os paths da forma certa.</p>\r\n<h2>Para projetos</h2>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/projeto.png\" alt=\"\" /></p>\r\n<p><em><strong>Detalhes</strong></em></p>\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\bin</strong> - Arquivo binário finalizado. Configure esta pasta como <strong>Output Directory</strong> nas propriedades do projeto<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\bin\\dcu</strong> - Units compiladas. Configure esta pasta como <strong>Unit Output Directory</strong>, nas propriedades do projeto<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\dev</strong> - Arquivos de suporte relacionados ao projeto, mas que não são compiláveis<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\dev\\doc</strong> - Arquivos de documentação a respeito do projeto<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\prj</strong> - Arquivo .dpr do projeto e todos os arquivos que forem criados automaticamente pelo Delphi<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\res</strong> - Arquivos de recurso que são utilizados pelo projeto na hora da compilação do mesmo. Podem ser arquivos .res, imagens, ícones ou qualquer outro tipo de arquivo que é carregado pelo projeto e é incluído no binário finalizado, isso inclui textos, scripts, etc. Você pode incluir esta pasta no <strong>Search Path</strong> do projeto a fim de facilitar a referência dos recursos<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Projeto\\src</strong> - Arquivos de código-fonte .pas exclusivos deste projeto</li>\r\n</ul>\r\n<p><em><strong>Observações</strong></em></p>\r\n<ul>\r\n<li style=\"text-align: justify;\">Se seu projeto tiver mais de um módulo ele conterá mais de um arquivo de projeto (.dpr). Todos estes arquivos deverão estar em <strong>Meu Projeto\\prj</strong>. Você pode, se quiser, colocar cada arquivo de projeto em uma pasta separada abaixo de <strong>prj</strong> a fim de separar cada projeto. Você pode também, neste caso, diretamente em <strong>Meu Projeto\\prj</strong>, colocar o arquivo de grupo de projetos (.bdsgroup ou .groupproj), o qual vai aglutinar todos os projetos de módulos individuais de forma que você possa ter acesso simplificado a partir da IDE a todos os projetos<br /><br /></li>\r\n<li style=\"text-align: justify;\">Se seu projeto tiver mais de um módulo ele conterá fontes de mais de um projeto. Todos estes arquivos deverão estar em Meu Projeto\\src, mas você pode, se quiser, criar pastas abaixo de <strong>Meu Projeto\\src</strong> a fim de separar os códigos-fonte dos módulos<br /><br /></li>\r\n<li style=\"text-align: justify;\">Se mais de um módulo utilizar um mesmo código-fonte .pas, crie a pasta <strong>Meu Projeto\\lib</strong> e dentro desta coloque tais arquivos. Em seguida, em cada projeto, inclua no <strong>Search Path</strong> a pasta Meu Projeto\\lib</li>\r\n</ul>\r\n<h2>Para pacotes</h2>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"images/add2del/artigos/ID000104/pacote.png\" alt=\"\" /></p>\r\n<p><em><strong>Detalhes</strong></em></p>\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\dcu</strong> - Units compiladas. Configure esta pasta como <strong>Unit Output Directory</strong>, nas propriedades do projeto e inclua ela no <strong>Library Path</strong> do Delphi<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\dev</strong> - Arquivos de suporte relacionados ao pacote, mas que não são compiláveis<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\dev\\doc</strong> - Arquivos de documentação a respeito do pacote<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\prj</strong> - Nesta pasta deve haver uma subpasta para cada versão de Delphi na qual este pacote é utilizável e dentro de cada uma destas subpasta deve ser colocado o arquivo de projeto do pacote específico daquela versão de Delphi (arquivo .dpk)<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\res</strong> - Arquivos de recurso que são utilizados pelo pacote na hora da compilação do mesmo. Podem ser arquivos .res, .dcr, imagens, ícones ou qualquer outro tipo de arquivo que é carregado pelo projeto do pacote e é incluído no binário finalizado (.bpl), isso inclui textos, scripts, etc. Você pode incluir esta pasta no <strong>Search Path</strong> do projeto do pacote a fim de facilitar a referência dos recursos. Ela também poderá ser incluída no <strong>Library Path</strong> dependendo da interpretação de seu conteúdo. Por favor, veja as observações mais adiante<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\res\\dfm</strong> - Arquivos de formulário exclusivamente. Por favor, veja as observações a seguir<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Meu Pacote\\src</strong> - Arquivos de código-fonte .pas exclusivos deste pacote</li>\r\n</ul>\r\n<p><em><strong>Observações</strong></em></p>\r\n<ul>\r\n<li style=\"text-align: justify;\">Não configure em hipótese alguma a propriedade <strong>Output Directory</strong> do projeto do pacote. Verifique-a e <strong>mantenha-a em branco</strong><br /><br /></li>\r\n<li style=\"text-align: justify;\">Não configure em hipótese alguma a propriedade <strong>DCP Output Directory</strong> do projeto do pacote. Verifique-a e <strong>mantenha-a em branco</strong><br /> </li>\r\n<li style=\"text-align: justify;\">Na pasta <strong>Meu Pacote\\res</strong> também podem ser incluídos arquivos de recurso que serão utilizados por outros projetos que utilizem o seu pacote. Para entender melhor, devemos considerar que existem dois pontos de vista: ao compilar um pacote e ao compilar um projeto que use seu pacote. Diante destes dois pontos de vista, devemos entender que:\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Quando você está desenvolvendo e compilando o seu pacote</strong>, ele está em tempo de projeto, portanto arquivos existentes na pasta <strong>Meu Pacote\\res</strong> poderão ser usados para a geração do BPL final e esta pasta deverá estar listada no <strong>Search Path</strong> do projeto do pacote</li>\r\n<li style=\"text-align: justify;\">No momento em que você compila um pacote e ele é carregado pelo Delphi, ele se torna algo em execução, logo, seu pacote estará em tempo de execução e não mais em tempo de projeto</li>\r\n<li style=\"text-align: justify;\"><strong>Ao compilar um projeto que use seu pacote</strong>, a pasta <strong>Meu Pacote\\res</strong>, deverá estar listada no <strong>Library Path</strong> <span style=\"text-decoration: underline;\">APENAS</span> se ela contiver recursos que precisarão estar disponíveis para o projeto sendo compilado. Imagens e ícones são um bom exemplo disso</li>\r\n</ul>\r\n</li>\r\n<li style=\"text-align: justify;\">A pasta <strong>Meu Pacote\\res\\dfm</strong> tem uma função importante, mas negligenciada. Como se sabe, arquivos .dfm por padrão sempre são salvos juntamente com seu arquivo .pas correspondente. Suponha que seu pacote esteja sendo carregado pelo Delphi e suponha que você esteja desenvolvendo algo que use units de seu pacote. Suponha também que você esteja referenciando alguma unit que contenha um .dfm associado. Neste caso o .dfm precisará estar disponível para seu projeto sendo compilado e para que ele saiba onde estão estes arquivos .dfm eles precisam estar listados no <strong>Library Path</strong> obviamente, mas, você <strong>NÃO PODERÁ</strong> incluir este path no Library Path porque ele contém units não compiladas (arquivos .pas) e isso seria <strong>ERRADO</strong>. Existem duas formas de resolver este problema. A forma clássica é copiar os arquivos .dfm que estão na pasta <strong>Meu Pacote\\src</strong> para a mesma pasta onde os arquivos .dcu são gerados, ou seja, <strong>Meu Pacote\\dcu</strong>. Eu não gosto dessa forma porque eu convencionei que na pasta <strong>Meu Pacote\\dcu</strong> devem existir apenas units compiladas (arquivos .dcu). Para resolver esse problema conceitual, já que arquivos .dfm são arquivos de recurso e não units compiladas, eu crio a pasta <strong>Meu Pacote\\res\\dfm</strong>, copio todos os arquivos .dfm que estão na pasta <strong>Meu Pacote\\src</strong> para lá e em seguida eu adiciono <strong>Meu Pacote\\res\\dfm</strong> ao Library Path. Se eu criar um novo formulário eu preciso apenas me lembrar de copiar o arquivo .dfm para a pasta correta. Uma variação dessa forma, que exige um controle maior, é copiar APENAS os arquivos .dfm que efetivamente precisarão ser vistos fora do projeto do pacote. A desvantagem dessa forma de trabalho com arquivos .dfm é que toda vez que você alterar um formulário, precisará se lembrar de copiar o arquivo .dfm para a pasta <strong>Meu Pacote\\res\\dfm</strong> </li>\r\n</ul>\r\n<h2>Conclusão</h2>\r\n<p style=\"text-align: justify;\">Esta artigo ficou maior do que eu esperava, mas foi necessário devido a grande utilidade do seu conteúdo. Se você leu tudo com cuidado será capaz de entender e notar quando um componente ou pacote está mal elaborado quanto a distribuição de seus artefatos e poderá organizá-lo da forma correta a fim de evitar problemas futuros. Se você é um desenvolvedor de componentes e leu este artigo, não existem mais desculpas para que seus componentes sejam distribuídos de forma errada. Estejam avisados! Eu torço para que as informações compartilhadas aqui atinjam o maior número de pessoas que usam o Delphi. Nós que utilizamos esta ferramenta precisamos conhecê-la a fundo a fim de podermos tirar o máximo de proveito da mesma.</p>\r\n<hr class=\"adsensesnippet\" />',1,80,'2016-09-17 03:22:35',24,'','2020-07-13 03:22:05',24,0,'0000-00-00 00:00:00','2017-01-20 02:26:51','0000-00-00 00:00:00','{\"image_intro\":\"\",\"float_intro\":\"\",\"image_intro_alt\":\"\",\"image_intro_caption\":\"\",\"image_fulltext\":\"images\\/add2del\\/artigos\\/ID000104\\/package.png\",\"float_fulltext\":\"\",\"image_fulltext_alt\":\"\",\"image_fulltext_caption\":\"\"}','{\"urla\":false,\"urlatext\":\"\",\"targeta\":\"\",\"urlb\":false,\"urlbtext\":\"\",\"targetb\":\"\",\"urlc\":false,\"urlctext\":\"\",\"targetc\":\"\"}','{\"article_layout\":\"\",\"show_title\":\"\",\"link_titles\":\"\",\"show_tags\":\"\",\"show_intro\":\"\",\"info_block_position\":\"\",\"info_block_show_title\":\"\",\"show_category\":\"\",\"link_category\":\"\",\"show_parent_category\":\"\",\"link_parent_category\":\"\",\"show_associations\":\"\",\"show_author\":\"\",\"link_author\":\"\",\"show_create_date\":\"\",\"show_modify_date\":\"\",\"show_publish_date\":\"\",\"show_item_navigation\":\"\",\"show_icons\":\"\",\"show_print_icon\":\"\",\"show_email_icon\":\"\",\"show_vote\":\"\",\"show_hits\":\"\",\"show_noauth\":\"\",\"urls_position\":\"\",\"alternative_readmore\":\"\",\"article_page_title\":\"\",\"show_publishing_options\":\"\",\"show_article_options\":\"\",\"show_urls_images_backend\":\"\",\"show_urls_images_frontend\":\"\"}',217,51,'Delphi, Addicted 2 Delphi, BPL, DCP, DCU, Arquivo BPL, Arquivo DCP, Arquivo DCU, BPL File, BCP File, DCU File, Pacotes, Packages, Runtime Packages, Designtime Packages, Instalação de Pacotes, Package Installation, Instalação de Componentes, Component Installation, Search Path, Library Path, Browsing Path, Output Directory, Unit Output Directory, .bpl, .dcp, .dcu','Existem na web centenas de artigos que ensinam a criar componentes no Delphi e apesar de eu poder fazer um artigo abordando este tema no futuro, no momento eu prefiro mesmo é falar a respeito de algo que é tão importante quanto o próprio componente em si. Muitas pessoas acham que sabem instalar corretamente um componente, mas o fato de ter o componente funcionando, não significa que a instalação foi correta. Você agora deve estar se perguntando \"Ora, mas se está funcionando, porque eu preciso me preocupar?\". Continue lendo e descubra.',1,35621,'{\"robots\":\"\",\"author\":\"\",\"rights\":\"\",\"xreference\":\"\"}',1,'*','',''),(105,289,'Desmistificando as Interfaces no Delphi','entendendo-interfaces','<p style=\"text-align: justify;\">Meu primeiro contato com interfaces foi lendo o livro \"A Bíblia do Delphi 5\". Nele eu aprendi que interfaces, grosso modo, são classes puramente abstratas (todos os seus métodos são virtuais e abstratos) e que ela obriga as classes que as suportam a implementar todos os seus métodos. Na época não consegui enxergar a utilidade das interfaces no Delphi. Desde então, tudo que eu precisei fazer eu fiz com simples classes. Já passei por alguns empregos e alguns projetos e nunca precisei usar de fato interfaces. Este artigo aborda as interfaces no Delphi, por isso é possível que você não possa aplicar o que está escrito aqui em outras linguagens. Se quer entender um pouco a respeito, continue lendo.</p>\r\n','\r\n<p style=\"text-align: justify;\">Até pouco tempo atrás eu não entendia as interfaces. Eu lia a respeito e não conseguia ver onde eu poderia usá-las. De fato, vivi até hoje e ainda vivo sem precisar usá-las não mais que uma vez perdida, mas calma, isso não as torna inúteis.</p>\r\n<p style=\"text-align: justify;\">Assim como qualquer coisa nessa vida, você não é obrigado a usar nenhuma técnica específica apenas porque alguém te falou que era genial. Você também não precisa usar alguma coisa porque ela está na moda, aliás, esse é o pior caso. É por isso que eu quero deixar aqui um pensamento que você, caro leitor, pode usar não apenas no contexto computacional, mas também na sua vida de uma forma geral:</p>\r\n<blockquote>\r\n<p style=\"text-align: center;\">A necessidade é o motorista que o conduz na estrada da resolução de um problema</p>\r\n</blockquote>\r\n<p style=\"text-align: justify;\">Depois dessa tentativa frustrada de ser intelectual eu me sinto no dever de falar de forma clara que <strong>você só precisa usar interfaces se ela for a única forma de conseguir resolver um problema ou se você quiser manter seu código mais organizado em alguma situação MUITO ESPECÍFICA</strong>. Ignore o tom drástico da frase anterior, trabalhar com interfaces nem sempre é complicado, mas seu uso desnecessário pode tornar seu código complexo sem necessidade, algo que evito a todo custo. Sou defensor ferrenho do <a href=\"https://pt.wikipedia.org/wiki/Keep_It_Simple\" rel=\"alternate\">KISS Principle</a> ;) E por falar nisso, chega de conversa fiada vamos ao que interessa.</p>\r\n<hr class=\"adsensesnippet\" />\r\n<h2><a title=\"Esta é uma interpretação pessoal, sem rodeios e que sintetiza o conceito de interface ao máximo, de forma que um leigo possa entender. Não cito, propositalmente, qualquer definição técnica ou justificativa embasada em &quot;programação teórica&quot;. Aqui tudo é real!\" href=\"#\" rel=\"bookmark\">Para que serve uma interface?</a></h2>\r\n<p style=\"text-align: justify;\">Uma interface tem basicamente duas utilidades, as quais devem ser observadas antes de se decidir por utilizá-las. São elas:</p>\r\n<ul>\r\n<li style=\"text-align: justify;\"><strong>Obrigar a implementação de métodos</strong>. Usando a terminologia mais difundida, \"obrigar a implementação\" significa estabelecer uma espécie de \"contrato\", no qual uma classe se compromete a implementar todos os métodos da interface. Não é à toa que o termo correto utilizado entre classes e interfaces é \"A classe implementa a(s) interface(s)\", isso é absolutamente correto, já que, todos os métodos da interface precisam ser implementados OBRIGATORIAMENTE na classe que a implementa.<br /><br /></li>\r\n<li style=\"text-align: justify;\"><strong>Introduzir comportamentos adicionais a uma classe</strong>. Normalmente ao trabalhar com orientação a objetos, tudo é muito simples; uma classe herda de outra, que herda de outra, que herda de outra e assim sucessivamente. Você vive feliz com isso até perceber que vai precisar implementar uma classe que vai ter comportamentos conjuntos de duas outras classes distintas, classes que não pertencem a uma mesma hierarquia. No Delphi não existe herança múltipla, logo, ao usar interfaces é possível separar os comportamentos que serão compartilhados e fazer com que apenas uma classe herde de uma classe pai e implemente n interfaces, as quais vão introduzir os comportamentos adicionais requeridos.</li>\r\n</ul>\r\n<p style=\"text-align: justify;\">Se você planeja usar interfaces, mas os motivos não forem um dos citados acima, então eu lamento informar que você só está introduzindo complexidade a seu código.</p>\r\n<p style=\"text-align: justify;\">Mesmo que você tenha motivos para usar interfaces, você <strong>não precisa</strong> usar interfaces para cada uma das classes que você tiver. Isso é estupidez! Como qualquer coisa em qualquer contexto, você só deve usar se for necessário em algum ponto. Um programa feito em Delphi pode conter classes simples, interfaces, e classes implementando interfaces. Tudo convivendo de forma harmoniosa.</p>\r\n<p style=\"text-align: justify;\">Por fim, ainda que você tenha motivos para usar interfaces é opção sua usá-las. <strong>Praticamente tudo que se faz com interfaces pode ser feito com classes simples</strong>. Interprete este artigo apenas como um guia muito básico que tem por objetivo desmistificar as interfaces, dando a você conhecimento sobre mais uma <em>feature</em> que o Object Pascal disponibiliza para você sem obrigá-lo a usar.</p>\r\n<hr class=\"system-pagebreak\" title=\"Um exemplo simples (?)\" alt=\"Um exemplo simples (?)\" />\r\n<h2>Um exemplo simples (?)</h2>\r\n<p style=\"text-align: justify;\">Gostaria de p

Part of diff was cut off due to size limit. Use your local client to view the full diff.

Show on old repository browser