{"id":1134,"date":"2026-09-16T18:55:18","date_gmt":"2026-09-16T21:55:18","guid":{"rendered":"https:\/\/www.pascalscada.com\/?page_id=1134"},"modified":"2026-09-16T19:06:02","modified_gmt":"2026-09-16T22:06:02","slug":"expressions-in-properties","status":"publish","type":"page","link":"https:\/\/www.pascalscada.com\/pb\/expressions-in-properties\/","title":{"rendered":"Express\u00f5es no Object Inspector"},"content":{"rendered":"<p><\/p>\n<h5>Introdu\u00e7\u00e3o<\/h5>\n<p>Configurar dezenas de tags \u00e0 m\u00e3o \u2014 um endere\u00e7o por vez, um \u00edndice por vez \u2014 \u00e9 onde se perde tempo e se erram n\u00fameros. Para isso, v\u00e1rias propriedades num\u00e9ricas dos componentes do PascalSCADA aceitam, no <strong>Object Inspector<\/strong>, uma <strong>express\u00e3o<\/strong> em vez de um n\u00famero: voc\u00ea digita <code>memaddress+2<\/code>, <code>Tag*4<\/code> ou <code>selindex*30<\/code> e a IDE calcula o valor. Combinado com a <strong>sele\u00e7\u00e3o m\u00faltipla<\/strong> do Lazarus, isso configura uma centena de componentes em uma digita\u00e7\u00e3o.<\/p>\n<p>\u00c9 um recurso de <strong>tempo de projeto<\/strong>: a express\u00e3o \u00e9 avaliada quando voc\u00ea pressiona Enter e o que fica gravado no <code>.lfm<\/code> \u00e9 o n\u00famero resultante. Em tempo de execu\u00e7\u00e3o nada muda \u2014 para valores calculados em tempo de execu\u00e7\u00e3o, use o <a href=\"\/pb\/tags\/#TNumericExprTag\"><code>TNumericExprTag<\/code><\/a>.<\/p>\n<p>O recurso foi anunciado no post <a href=\"\/pb\/2016\/11\/22\/expressions-on-all-properties-of-base-tags\/\">Express\u00f5es em todas as propriedades dos tags base<\/a>; o v\u00eddeo abaixo mostra o uso:<\/p>\n<p><iframe loading=\"lazy\" title=\"PascalSCADA: expressions on all base tags\" width=\"800\" height=\"600\" src=\"https:\/\/www.youtube.com\/embed\/1E1MeYGuH8s?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<h5>Como digitar<\/h5>\n<p>No Object Inspector, no campo da propriedade, digite a express\u00e3o e pressione Enter. Duas formas:<\/p>\n<table>\n<thead>\n<tr>\n<th>Voc\u00ea digita<\/th>\n<th>O que acontece<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>100<\/code><\/td>\n<td>Valor normal.<\/td>\n<\/tr>\n<tr>\n<td><code>10*8+3<\/code><\/td>\n<td>Express\u00e3o <strong>absoluta<\/strong>: a propriedade recebe o resultado (83).<\/td>\n<\/tr>\n<tr>\n<td><code>+2<\/code>, <code>-10<\/code>, <code>*2<\/code>, <code>\/2<\/code><\/td>\n<td>Express\u00e3o <strong>relativa<\/strong>: come\u00e7a com um operador, e o valor atual da propriedade \u00e9 colocado na frente. <code>+2<\/code> em um <code>MemAddress = 40<\/code> d\u00e1 42; <code>*2<\/code> d\u00e1 80.<\/td>\n<\/tr>\n<tr>\n<td><code>memaddress+2<\/code><\/td>\n<td>Express\u00e3o com <strong>vari\u00e1veis<\/strong> (a lista de cada propriedade est\u00e1 abaixo).<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>O resultado \u00e9 sempre inteiro: divis\u00f5es s\u00e3o truncadas (<code>7\/2<\/code> \u2192 3). Com a sele\u00e7\u00e3o m\u00faltipla, a express\u00e3o \u00e9 avaliada <strong>uma vez para cada componente selecionado<\/strong>, com as vari\u00e1veis daquele componente \u2014 \u00e9 isso que permite <code>memaddress+100<\/code> deslocar dez tags de uma vez, cada um a partir do seu pr\u00f3prio endere\u00e7o.<\/p>\n<h5>Sintaxe<\/h5>\n<p>O avaliador \u00e9 o <code>TFPExpressionParser<\/code> do Free Pascal, com as fun\u00e7\u00f5es matem\u00e1ticas ligadas:<\/p>\n<ul>\n<li>operadores: <code>+ - * \/ ^<\/code> (pot\u00eancia), <code>mod<\/code>, par\u00eanteses;<\/li>\n<li>compara\u00e7\u00e3o e l\u00f3gica: <code>= &lt;&gt; &lt; &gt; &lt;= &gt;=<\/code>, <code>and<\/code>, <code>or<\/code>, <code>not<\/code>;<\/li>\n<li><code>if(condi\u00e7\u00e3o, seVerdadeiro, seFalso)<\/code> e <code>case(seletor, v1, r1, v2, r2, \u2026, padr\u00e3o)<\/code>;<\/li>\n<li>fun\u00e7\u00f5es: <code>abs<\/code>, <code>sqr<\/code>, <code>sqrt<\/code>, <code>round<\/code>, <code>trunc<\/code>, <code>int<\/code>, <code>frac<\/code>, <code>exp<\/code>, <code>ln<\/code>, <code>log<\/code>, <code>sin<\/code>, <code>cos<\/code>, <code>arctan<\/code>, <code>pi<\/code>;<\/li>\n<li>os nomes das vari\u00e1veis n\u00e3o diferenciam mai\u00fasculas de min\u00fasculas (<code>MemAddress<\/code> e <code>memaddress<\/code> s\u00e3o a mesma coisa).<\/li>\n<\/ul>\n<p>N\u00e3o existe <code>div<\/code>: use <code>trunc(a\/b)<\/code> (ou s\u00f3 <code>a\/b<\/code>, que j\u00e1 \u00e9 truncado ao gravar).<\/p>\n<h5>Onde funciona e quais vari\u00e1veis existem<\/h5>\n<p><strong>Propriedades de endere\u00e7o dos tags<\/strong> \u2014 em <code>TPLCTagNumber<\/code>, <code>TPLCBlock<\/code>, <code>TPLCStruct<\/code> e <code>TPLCString<\/code>, as propriedades <code>PLCRack<\/code>, <code>PLCSlot<\/code>, <code>PLCStation<\/code>, <code>MemFile_DB<\/code>, <code>MemAddress<\/code>, <code>MemSubElement<\/code>, <code>MemReadFunction<\/code>, <code>MemWriteFunction<\/code> e, nos blocos e estruturas, <code>Size<\/code>. Vari\u00e1veis dispon\u00edveis: <strong>as outras propriedades dessa lista<\/strong> (<code>plcrack<\/code>, <code>plcslot<\/code>, <code>plcstation<\/code>, <code>memfile_db<\/code>, <code>memaddress<\/code>, <code>memsubelement<\/code>, <code>memreadfunction<\/code>, <code>memwritefunction<\/code>) e <strong><code>Tag<\/code><\/strong> (a propriedade <code>Tag<\/code> do componente, um inteiro livre). A pr\u00f3pria propriedade que est\u00e1 sendo editada n\u00e3o entra, para n\u00e3o haver refer\u00eancia circular.<\/p>\n<p><strong><code>Index<\/code><\/strong> \u2014 em <code>TPLCBlockElement<\/code>, <code>TPLCStructItem<\/code> e <code>TPLCStructString<\/code>. Vari\u00e1vel: <strong><code>Tag<\/code><\/strong>. (No <code>TPLCBlockElement<\/code>, a lista suspensa do campo tamb\u00e9m oferece os \u00edndices v\u00e1lidos do bloco.)<\/p>\n<p><strong>Posi\u00e7\u00e3o e tamanho de qualquer controle<\/strong> \u2014 <code>Left<\/code>, <code>Top<\/code>, <code>Width<\/code> e <code>Height<\/code> de todo <code>TControl<\/code> do form, n\u00e3o s\u00f3 dos controles do PascalSCADA. Vari\u00e1veis: <code>left<\/code>, <code>top<\/code>, <code>width<\/code>, <code>height<\/code>, <code>tag<\/code> e <strong><code>selindex<\/code><\/strong>.<\/p>\n<p><strong><code>Tag<\/code><\/strong> \u2014 a propriedade <code>Tag<\/code> de qualquer <code>TComponent<\/code>. Vari\u00e1veis: as mesmas de posi\u00e7\u00e3o (<code>left<\/code>\u2026 se for um controle) e <code>selindex<\/code>.<\/p>\n<p><strong><code>selindex<\/code><\/strong> \u00e9 o \u00edndice do componente dentro da sele\u00e7\u00e3o atual (0 para o primeiro selecionado, 1 para o segundo\u2026). \u00c9 a vari\u00e1vel que transforma a sele\u00e7\u00e3o m\u00faltipla em numera\u00e7\u00e3o autom\u00e1tica.<\/p>\n<h5>Receitas<\/h5>\n<p>Todas partem de uma sele\u00e7\u00e3o m\u00faltipla no form ou no datamodule (Shift+clique, ou arrastando uma moldura).<\/p>\n<p><strong>Numerar os elementos de um bloco.<\/strong> Selecione os 16 <code>TPLCBlockElement<\/code> criados \u00e0 m\u00e3o, na ordem desejada:<\/p>\n<ol>\n<li>em <code>Tag<\/code>, digite <code>selindex<\/code> \u2192 cada um recebe 0, 1, 2\u2026 15;<\/li>\n<li>em <code>Index<\/code>, digite <code>Tag<\/code> \u2192 <code>Index<\/code> = 0, 1, 2\u2026 15.<\/li>\n<\/ol>\n<p>O mesmo vale para <code>TPLCStructItem<\/code> com offsets regulares: <code>Index<\/code> = <code>Tag*2<\/code> para campos <code>INT<\/code>, <code>Tag*4<\/code> para <code>REAL<\/code>.<\/p>\n<p><strong>Tags consecutivos.<\/strong> Dez <code>TPLCTagNumber<\/code> que devem apontar para D100, D101, \u2026 D109: selecione os dez, <code>Tag<\/code> = <code>selindex<\/code>, depois <code>MemAddress<\/code> = <code>100+Tag<\/code>.<\/p>\n<p><strong>Deslocar um conjunto de endere\u00e7os.<\/strong> O DB mudou de lugar e todos os tags precisam avan\u00e7ar 50 bytes: selecione-os e digite <code>+50<\/code> em <code>MemAddress<\/code>. Trocou o DB: <code>MemFile_DB<\/code> = <code>12<\/code> na sele\u00e7\u00e3o inteira.<\/p>\n<p><strong>Struct copiada.<\/strong> Voc\u00ea copiou os itens de uma <code>TPLCStruct<\/code> para representar um segundo equipamento cuja estrutura fica 64 bytes adiante: selecione os itens copiados e digite <code>+64<\/code> em <code>Index<\/code>.<\/p>\n<p><strong>Escrita coerente com a leitura.<\/strong> Em tags Modbus, <code>MemWriteFunction<\/code> = <code>if(memreadfunction=1, 15, 16)<\/code> escolhe a fun\u00e7\u00e3o de escrita de bloco certa para cada tag, conforme ele l\u00ea coils ou registradores.<\/p>\n<p><strong>Alinhar controles.<\/strong> Selecione dez <code>THMILabel<\/code> e digite <code>selindex*24+8<\/code> em <code>Top<\/code> e <code>16<\/code> em <code>Left<\/code>: uma coluna com 24 px de passo. Uma grade de bot\u00f5es 4\u00d74: <code>Left<\/code> = <code>(selindex mod 4)*90<\/code>, <code>Top<\/code> = <code>trunc(selindex\/4)*40<\/code>.<\/p>\n<p><strong>Empilhar controles de tamanhos diferentes.<\/strong> <code>Top<\/code> = <code>selindex*(height+4)<\/code> s\u00f3 funciona quando todos t\u00eam a mesma altura; para alturas diferentes, alinhe em duas passadas ou use o <em>Anchor Editor<\/em> do Lazarus.<\/p>\n<h5>Limites<\/h5>\n<ul>\n<li>S\u00f3 no Object Inspector do Lazarus: n\u00e3o vale para c\u00f3digo, nem para propriedades editadas em outros di\u00e1logos (Tag Builder, editores de cole\u00e7\u00e3o).<\/li>\n<li>As vari\u00e1veis leem o valor <strong>atual<\/strong> dos outros componentes selecionados; uma express\u00e3o que dependa de uma propriedade que voc\u00ea ainda vai alterar precisa ser digitada depois dela.<\/li>\n<li>S\u00f3 propriedades inteiras listadas acima. <code>RefreshTime<\/code>, <code>MinValue<\/code>, <code>Value1<\/code> das zonas e outras n\u00e3o aceitam express\u00f5es (por enquanto \u2014 a lista est\u00e1 em <code>src\/scada_dsng\/scadareg.pas<\/code> e <code>src\/hmi\/hmiregister.pas<\/code>, e estend\u00ea-la \u00e9 registrar mais um <code>TTagAddressPropertyEditor<\/code>).<\/li>\n<li>Um erro de sintaxe \u00e9 reportado pela IDE e a propriedade n\u00e3o muda.<\/li>\n<\/ul>\n<h5>Exemplos relacionados<\/h5>\n<ul>\n<li><a href=\"https:\/\/github.com\/fluisgirardi\/pascalscada_v0\/tree\/master\/examples\/laz_isotcp_demonstration\"><code>examples\/laz_isotcp_demonstration<\/code><\/a> e <a href=\"https:\/\/github.com\/fluisgirardi\/pascalscada_v0\/tree\/master\/examples\/laz_isotcp_hourmeter\"><code>examples\/laz_isotcp_hourmeter<\/code><\/a> \u2014 dezenas de <code>TPLCBlockElement<\/code> e <code>TTagBit<\/code> com \u00edndices sequenciais, o cen\u00e1rio t\u00edpico das receitas acima.<\/li>\n<li><a href=\"https:\/\/github.com\/fluisgirardi\/pascalscada_v0\/tree\/master\/examples\/TagTypes\"><code>examples\/TagTypes<\/code><\/a> \u2014 elementos e itens de estrutura com offsets calculados.<\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Introdu\u00e7\u00e3o Configurar dezenas de tags \u00e0 m\u00e3o \u2014 um endere\u00e7o por vez, um \u00edndice por vez \u2014 \u00e9 onde se perde tempo e se erram n\u00fameros. Para isso, v\u00e1rias propriedades &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-fullwidth.php","meta":{"footnotes":""},"class_list":["post-1134","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/pages\/1134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/comments?post=1134"}],"version-history":[{"count":4,"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/pages\/1134\/revisions"}],"predecessor-version":[{"id":1190,"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/pages\/1134\/revisions\/1190"}],"wp:attachment":[{"href":"https:\/\/www.pascalscada.com\/pb\/wp-json\/wp\/v2\/media?parent=1134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}