{"id":1569,"date":"2022-07-08T14:08:47","date_gmt":"2022-07-08T17:08:47","guid":{"rendered":"https:\/\/gladiston.net.br\/?page_id=1569"},"modified":"2024-08-27T16:59:04","modified_gmt":"2024-08-27T19:59:04","slug":"tchau-showmessage-oi-taskdialog","status":"publish","type":"page","link":"https:\/\/gladiston.net.br\/en\/programacao\/lazarus-ide\/tchau-showmessage-oi-taskdialog\/","title":{"rendered":"Tchau ShowMessage, MessageBox e MessageDlg, Ol\u00e1 TaskDialog"},"content":{"rendered":"\n<p>Por muito tempo, a maneira mais f\u00e1cil de criar um aviso textual foi usando o ShowMessage(&#8216;Hello World&#8217;). Claro que o ShowMessage n\u00e3o vem sozinho, com eles uma s\u00e9rie de janelas de dialogos que podemos ver no link abaixo:<\/p>\n\n\n\n<p><a href=\"https:\/\/wiki.freepascal.org\/Dialog_Examples\">https:\/\/wiki.freepascal.org\/Dialog_Examples<\/a><\/p>\n\n\n\n<p>Neste artigo vamos ver como substituir o ShowMessage, MessageBox e MessageDlg por uma varia\u00e7\u00e3o moderna chamada de TaskDialog que funciona no Lazarus e seu comportamento \u00e9 o mesmo em qualquer sistema operacional. A documenta\u00e7\u00e3o do TaskDialog pode ser encontrada aqui:<\/p>\n\n\n\n<p><a href=\"https:\/\/wiki.freepascal.org\/TTaskDialog\">https:\/\/wiki.freepascal.org\/TTaskDialog<\/a><\/p>\n\n\n\n<p>Para usar o TaskDialog, basta incluir a unit <strong>Dialogs<\/strong> ao seu uses, na realidade, ela \u00e9 t\u00e3o comum que provavelmente voc\u00ea j\u00e1 a possui em todos os seus projetos e apenas desperdi\u00e7a a possibilidade de usar TaskDialog. Voc\u00ea pode usar o componente TaskDialog, mas perceber\u00e1 que \u00e9 mais f\u00e1cil evitar o componente e ir implement\u00e1-lo com c\u00f3digo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Porque usar TaskDialog?<\/h2>\n\n\n\n<p>A resposta mais simples de porque usar o TaskDialog \u00e9 porque ele pode ser usado em todas as situa\u00e7\u00f5es de intera\u00e7\u00e3o com o usu\u00e1rio, enquanto as outras formas de Dialogs usam comandos diferentes para cada situa\u00e7\u00e3o e no caso do MessageBox e MessageDlg, o texto em seus bot\u00f5es podem n\u00e3o estar traduzidos causando o efeito indesejado de pergunta em portugu\u00eas e tendo que clicar em Yes, No, Cancel&#8230; <\/p>\n\n\n\n<p>Com o TaskDialog \u00e9 poss\u00edvel acrescentar \u00edcone indicador, titulo de janela, titulo de texto, bot\u00f5es, radiogroups, &#8230; deixando-o com cara de Assistente(Wizard). Veja esse exemplo de como o TaskDialog pode ficar se incluir todos os recursos:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/wiki.freepascal.org\/images\/3\/3d\/ttaskdialog.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Podemos configurar a janela de dialogo para incluir o que desejarmos<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">ShowMessage, MessageBox e MessageDlg &#8211; a queda<\/h2>\n\n\n\n<p>O ShowMessage \u00e9 usado dessa forma:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ShowMessage('N\u00e3o h\u00e1 quem goste de dor, que a procure e a queira ter, simplesmente porque \u00e9 dor...');<\/code><\/pre>\n\n\n\n<p>E exibido assim para o usu\u00e1rio:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"362\" height=\"128\" src=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage.png\" alt=\"\" class=\"wp-image-1573\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage.png 362w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage-300x106.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage-18x6.png 18w\" sizes=\"auto, (max-width: 362px) 100vw, 362px\" \/><\/figure>\n\n\n\n<p>N\u00e3o tem beleza alguma e basta ent\u00e3o clicar em &#8220;OK&#8221; e a janela ser\u00e1 finalizada. Uma forma diferente de exibir essa mesma mensagem usando o TaskDialog \u00e9:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">  with TTaskDialog.Create(self) do\n  try\n    Caption := 'Titulo da janela';\n    Title := 'Titulo do texto';\n    Text := 'N\u00e3o h\u00e1 quem goste de dor, que a procure e a queira ter, simplesmente porque \u00e9 dor...';\n    CommonButtons := [tcbOk];   \/\/ (tcbOk, tcbYes, tcbNo, tcbCancel, tcbRetry, tcbClose);\n    MainIcon := tdiInformation;    \/\/ (tdiNone, tdiWarning, tdiError, tdiInformation, tdiShield, tdiQuestion);\n    Execute;\n  finally\n    Free;\n  end  <\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"362\" height=\"159\" src=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage_alt.png\" alt=\"\" class=\"wp-image-1574\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage_alt.png 362w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage_alt-300x132.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/lazdemo_taskdialogs_showmessage_alt-18x8.png 18w\" sizes=\"auto, (max-width: 362px) 100vw, 362px\" \/><figcaption class=\"wp-element-caption\">TaskDialog sendo exibida como mensagem no Windows<\/figcaption><\/figure>\n\n\n\n<p>Agora temos um titulo na janela, temos um titulo para o texto e o texto propriamente dito. Sei o que est\u00e1 pensando: &#8220;mas \u00e9 muito mais c\u00f3digo para s\u00f3 mostrar uma mensagem&#8221;. O que voc\u00ea n\u00e3o est\u00e1 pensando \u00e9:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Posso refatorar o TaskDialog para substituir ShowMessage<\/li>\n\n\n\n<li>Totalmente personaliz\u00e1vel<\/li>\n<\/ul>\n\n\n\n<p>Como assim refatorar? Simplesmente Crie um procedimento chamado ShowMessage2 que use o TaskDialog:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">procedure ShowMessage2(\n  ATexto: String; \n  ATitle: String='Informa\u00e7\u00e3o:'; \n  ACaption: String='');\nbegin\n  if ACaption=emptyStr\n    then ACaption:=ExtractFileName(Application.ExeName);\n  if ATitle=emptyStr\n    then ATitle:='Informa\u00e7\u00e3o:';\n  with TTaskDialog.Create(self) do\n  try\n    Caption := ACaption;\n    Title := ATitle;\n    Text := ATexto;\n    CommonButtons := [tcbOk];   \/\/ (tcbOk, tcbYes, tcbNo, tcbCancel, tcbRetry, tcbClose);\n    MainIcon := tdiInformation;    \/\/ (tdiNone, tdiWarning, tdiError, tdiInformation, tdiShield, tdiQuestion);\n    Execute;\n  finally\n    Free;\n  end\nend;<\/pre><\/div>\n\n\n\n<p>E pronto, agora posso substituir todos os ShowMessages por ShowMessages2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ShowMessage2('N\u00e3o h\u00e1 quem goste de dor, que a procure e a queira ter, simplesmente porque \u00e9 dor...');<\/code><\/pre>\n\n\n\n<p>E em termos de c\u00f3digo ser\u00e1 igual. Basta agora fazer o search\/replace em todo o seu projeto. <\/p>\n\n\n\n<p>Mas e a personaliza\u00e7\u00e3o que falei agora a pouco? Muito bem, o TaskDialog \u00e9 totalmente personaliz\u00e1vel, voc\u00ea pode acrescentar bot\u00f5es, texto expandido, checkbox, radiogroup,&#8230;tudo numa \u00fanica chamada e a parte legal \u00e9 que obt\u00eam o resultado selecionado sem complica\u00e7\u00e3o. J\u00e1 demonstrei em como substituir o ShowMessage, agora falta os outros dois: MessageBox e MessageDlg que s\u00e3o basicamente duas fun\u00e7\u00f5es diferentes com o mesmo proposito. <\/p>\n\n\n\n<p>A base para voc\u00ea entender como o TaskDialog funciona com m\u00faltiplas op\u00e7\u00f5es \u00e9 a seguinte:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">with TTaskDialog.Create(self) do\ntry\n  Caption := 'Confirma\u00e7\u00e3o:';\n  Title := 'Posso remover o item?';\n  Text := 'Posso remover o item selecionado?';\n  \/\/ CommonButtons \u00e9 para mostrar os bot\u00f5es padr\u00f5es que podem ser exibidos:\n  \/\/ tcbOk, tcbYes, tcbNo, tcbCancel, tcbRetry, tcbClose e retornam ModalResult:\n  \/\/ mrOK, mrYes, mrNo, mrCancel, mrRetry, mrClose&lt;\/strong&gt;\n  CommonButtons := [tcbYes, tcbNo];\n  \/\/ MainIcon \u00e9 para exibir um \u00edcone padr\u00e3o que pode ser:\n  \/\/ tdiNone, tdiWarning, tdiError, tdiInformation, tdiShield, tdiQuestion\n  MainIcon := tdiQuestion;\n  if Execute then\n  begin\n    \/\/ aqui analisamos a op\u00e7\u00e3o selecionada com o ModalResult\n    if ModalResult = mrYes then\n    begin\n      \/\/ Clicou em Sim\n      ShowMessage2('Sim!');\n    end;\n    if ModalResult = mrNo then\n    begin\n      \/\/ Clicou em N\u00e3o\n      ShowMessage2('N\u00e3o!');\n    end\n  end;\nfinally\n  Free;\nend;<\/pre><\/div>\n\n\n\n<p>Vamos a explica\u00e7\u00e3o do c\u00f3digo acima:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A propriedade <strong>CommonButtons <\/strong>indica quais bot\u00f5es dever\u00e3o aparecer, s\u00e3o eles: <strong>tcbOk, tcbYes, tcbNo, tcbCancel, tcbRetry, tcbClose<\/strong> que retornar\u00e3o respectivamente o ModalResult <strong>mrOK, mrYes, mrNo, mrCancel, mrRetry, mrClose<\/strong>. Os nomes s\u00e3o autoexplicativos indicando o texto que ir\u00e1 aparecer dentro desses bot\u00f5es e seu \u00edcone, o texto s\u00e3o constantes e n\u00e3o pode ser modificado, se usar tcbYes e tcbNo ser\u00e1 respectivamente dois bot\u00f5es &#8220;Sim&#8221; e &#8220;N\u00e3o&#8221;.<\/li>\n\n\n\n<li>A propriedade <strong>MainIcon <\/strong>pode ser definida com o valor: <strong>tdiNone, tdiWarning, tdiError, tdiInformation, tdiShield, tdiQuestion<\/strong>. O nome de cada um deles \u00e9 autoexplicativo e indicar\u00e1 o tipo de \u00edcone que ser\u00e1 exibido ao lado da mensagem.<\/li>\n\n\n\n<li>O m\u00e9todo <strong>Execute <\/strong>(obrigat\u00f3rio) submete a exibi\u00e7\u00e3o da janela de dialogo e retornar\u00e1 quase sempre verdadeiro para indicar que a mesma foi exibida para o usu\u00e1rio e uma das op\u00e7\u00f5es escolhida, mas retorna falso se o usu\u00e1rio optar por abandonar sem selecionar nenhuma das op\u00e7\u00f5es.<\/li>\n\n\n\n<li>A propriedade <strong>ModalResult <\/strong>s\u00f3 \u00e9 obtida depois que o m\u00e9todo Execute for executado, recebendo um desses valores: <strong>mrOK, mrYes, mrNo, mrCancel, mrRetry, mrClose<\/strong> em conformidade com a propriedade CommonButtons.<\/li>\n<\/ul>\n\n\n\n<p>Tendo em mente o que acabei de dizer, ter\u00e1 o suficiente para substituir MessageBox e MessageDlg pelo TaskDialog. Novamente, repita a t\u00e9cnica de refatora\u00e7\u00e3o para criar MessageBox2 e\/ou MessageDlg2. <\/p>\n\n\n\n<p>Como eu havia dito usar <strong>CommonButtons <\/strong>faz com que o texto dentro dos bot\u00f5es sejam inalter\u00e1veis, mas \u00e9 possivel personalizar esses textos criando nossos pr\u00f3prios bot\u00f5es. Para isso funcionar, ter\u00e1 de atribuir a cada um desses bot\u00f5es um ModalResult diferente, por isso a quantidade de bot\u00f5es \u00e9 limitada. Por exemplo, se eu acrescentar dois bot\u00f5es &#8220;Remover&#8221; e &#8220;Manter&#8221; eu terei de dizer que o primeiro ter\u00e1 um ModalResult=mrYes enquanto o segundo escolherei ModalResult=mrNo e somente assim saberei qual foi o bot\u00e3o que o usu\u00e1rio escolheu ap\u00f3s o <strong><em>Execute<\/em><\/strong>. Importante saber tamb\u00e9m que caso voc\u00ea opte por usar bot\u00f5es com texto personalizado n\u00e3o poder\u00e1 usar a propriedade CommonButtons, veja este exemplo simples e f\u00e1cil de entender:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">with TTaskDialog.Create(self) do\ntry\n  Caption := 'Confirma\u00e7\u00e3o:';\n  Title := 'Posso remover o item?';\n  Text := 'Posso remover o item selecionado?';\n  \/\/ CommonButtons deve estar vazio porque irei constituir meus pr\u00f3prios bot\u00f5es\n  CommonButtons := [];\n  \/\/ Note que cada bot\u00e3o acrescentado, devo ter um ModalResult atribu\u00eddo para ele\n  with TTaskDialogButtonItem(Buttons.Add) do\n  begin\n    Caption := 'Remover';\n    ModalResult := mrYes;\n  end;\n  with TTaskDialogButtonItem(Buttons.Add) do\n  begin\n    Caption := 'Manter';\n    ModalResult := mrNo;\n  end;\n  MainIcon := tdiQuestion;\n  if Execute then\n  begin\n    \/\/ como cada bot\u00e3o tem seu pr\u00f3prio ModalResult ent\u00e3o fica f\u00e1cil\n    \/\/ detectar o bot\u00e3o que foi clicado.\n    if ModalResult = mrYes then\n    begin\n      ShowMessage2('Item removido!');\n    end;\n    if ModalResult = mrNo then\n    begin\n      ShowMessage2('Item mantido!');\n    end;\n  end;\nfinally\n  Free;\nend;<\/pre><\/div>\n\n\n\n<p>Novamente, se voc\u00ea estiver desligado, deve se perguntar, porque vou usar um c\u00f3digo gigante acima para fazer uma pergunta de sim ou n\u00e3o? Da\u00ed novamente vou responder, voc\u00ea n\u00e3o aprendeu a fatorar? Quando tiver que repetir um mesmo c\u00f3digo mais de uma vez, crie uma fun\u00e7\u00e3o ou procedimento que torne mais f\u00e1cil repetir c\u00f3digo, veja esse outro exemplo:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">function MessageDlg2(\n    ACaption:String;\n    ATitle:String;\n    AText:String;\n    AButtonText1:String;\n    AButtonText2:String):TModalResult;\nbegin\n  Result:=mrNone;\n  if ACaption=emptyStr\n    then ACaption:=ExtractFileName(Application.ExeName);\n  if ATitle=emptyStr\n    then ATitle:='Quest\u00e3o:';\n  with TTaskDialog.Create(self) do\n  try\n    Caption := ACaption;\n    Title := ATitle;\n    Text := AText;\n    \/\/ CommonButtons deve estar vazio porque irei constituir meus pr\u00f3prios bot\u00f5es\n    CommonButtons := [];\n    \/\/ Note que cada bot\u00e3o acrescentado, devo ter um ModalResult atribu\u00eddo para ele\n    with TTaskDialogButtonItem(Buttons.Add) do\n    begin\n      Caption := AButtonText1;\n      ModalResult := mrYes;\n    end;\n    with TTaskDialogButtonItem(Buttons.Add) do\n    begin\n      Caption := AButtonText2;\n      ModalResult := mrNo;\n    end;\n    MainIcon := tdiQuestion;\n    if Execute then\n    begin\n      Result:=ModalResult;\n    end;\n  finally\n    Free;\n  end;\nend; <\/pre><\/div>\n\n\n\n<p>Da\u00ed temos uma simp\u00e1tica fun\u00e7\u00e3o para perguntar algo ao usu\u00e1rio:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">var\n  mrResposta:TModalResult;\nbegin\n  mrResposta:=MessageDlg2(\n       'Voc\u00ea tem certeza?',\n       'Devo realmente apagar todos os dados?',\n       'Se apagar todos os usu\u00e1rios n\u00e3o ser\u00e1 mais poss\u00edvel recuper\u00e1-los.',\n       'Sim, apague tudo',\n       'N\u00e3o, retorne');\n    if mrResposta=mrYes then\n    begin\n      \/\/ respondeu &quot;Sim, apague tudo&quot;\n    end;\n    if mrResposta=mrNo then\n    begin\n      \/\/ respondeu &quot;N\u00e3o, retorne&quot;\n    end;\n    if mrResposta=mrNone then\n    begin\n      \/\/ n\u00e3o respondeu nada, abandonou a quest\u00e3o\n    end;\nend;<\/pre><\/div>\n\n\n\n<p>Voc\u00ea pode fatorar ou criar fun\u00e7\u00f5es para obter uma resposta onde h\u00e1 duas op\u00e7\u00f5es dispon\u00edveis como fiz acima e obter\u00e1 algo semelhante a isso:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"669\" height=\"438\" src=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/taskdialog1.png\" alt=\"\" class=\"wp-image-1598\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/taskdialog1.png 669w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/taskdialog1-300x196.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/07\/taskdialog1-18x12.png 18w\" sizes=\"auto, (max-width: 669px) 100vw, 669px\" \/><figcaption class=\"wp-element-caption\">TaskDialog sendo exibida com duas op\u00e7\u00f5es de escolha no ambiente Linux<\/figcaption><\/figure>\n\n\n\n<p>Lembre-se que este foi apenas um exemplo e voc\u00ea pode criar outras fun\u00e7\u00f5es para a quantidade de op\u00e7\u00f5es tantas quanto forem necess\u00e1rias dum jeito elegante e produtivo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Bot\u00f5es com RadioButton<\/h2>\n\n\n\n<p>Agora vamos incrementar ainda mais nossas op\u00e7\u00f5es juntando Bot\u00f5es como foram apresentados nos paragrafos anteriores com RadioButtons que s\u00e3o op\u00e7\u00f5es mais flexiveis quando temos uma variade maior de op\u00e7\u00f5es:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">function QueroEscolher(\n    ACaption:String;\n    ATitle:String;\n    AText:String;\n    AOptions:Array of String;\n    AIcon:TTaskDialogIcon=tdiNone;\n    AProsseguirCaption:String='Prosseguir';\n    ADesistirCaption:String='Desistir'):SmallInt;\nvar\n  i:Integer;\n  iCount:Cardinal;\n  sBotaoCap:String;\n  bDefault:Boolean;\n  mrResposta:TModalResult;\nbegin\n  Result:=-1;\n  iCount:=0;\n  if Length(AOptions)=0 then\n    Exit;\n\n  bDefault:=false;\n  if ACaption=emptyStr\n    then ACaption:=ExtractFileName(Application.ExeName);\n  if ATitle=emptyStr\n    then ATitle:='Escolha uma das op\u00e7\u00f5es abaixo:';\n  with TTaskDialog.Create(nil) do\n  try\n    Caption := ACaption;\n    Title := ATitle;\n    Text := AText;\n    \/\/ \/\/ tdiNone = 0;  tdiWarning = 1;  tdiError = 2;  tdiInformation = 3;  tdiShield = 4; tdiQuestion=5\n    MainIcon := AIcon; \n    \/\/ CommonButtons deve estar vazio porque irei constituir meus pr\u00f3prios bot\u00f5es\n    CommonButtons := [];\n    \/\/ Caso inclua mais boto\u00f5es, as opcoes validas na sequencia s\u00e3o:\n    \/\/ mrYes(0), mrNo(1), mrOk(2), mrCancel(3), mrAbort(4), mrRetry(5),\n    \/\/ mrIgnore(6), mrAll(7), mrNoToAll(8), mrYesToAll(9), mrClose(10);\n    with TTaskDialogButtonItem(Buttons.Add) do\n    begin\n      Caption := AProsseguirCaption;\n      ModalResult := mrYes;\n    end;\n    with TTaskDialogButtonItem(Buttons.Add) do\n    begin\n      Caption := ADesistirCaption;\n      ModalResult := mrNo;\n    end;\n\n    \/\/ Note que cada bot\u00e3o acrescentado, devo ter um ModalResult atribu\u00eddo para ele\n    for i := Low(AOptions) to High(AOptions) do\n    begin\n      sBotaoCap:=Trim(AOptions[i]);\n      bDefault:=false;\n      if (RightStr(sBotaoCap,1)='*') then\n      begin\n        bDefault:=true;\n        sBotaoCap:=LeftStr(sBotaoCap, Length(sBotaoCap)-1);\n      end;\n\n      if (sBotaoCap&lt;&gt;emptystr) then\n      begin\n        with RadioButtons.Add do\n        begin\n          Caption := sBotaoCap;\n          Default:=bDefault;\n          Inc(iCount);\n        end;\n      end;\n    end;\n    \/\/ s\u00f3 executo o TaskDialog se houverem op\u00e7\u00f5es dispon\u00edveis\n    if iCount&gt;0 then\n    begin\n      if Execute then\n      begin\n        mrResposta:=ModalResult;\n        if mrResposta = mrYes then\n           Result:=RadioButton.Index;\n      end;\n    end;\n  finally\n    Free;\n  end;\nend;<\/pre><\/div>\n\n\n\n<p>Se voc\u00ea notar o c\u00f3digo acima,  ao inv\u00e9s de usar &#8220;with TTaskDialogButtonItem(Buttons.Add)&#8221; para acrescentar novos bot\u00f5es usamos &#8220;with RadioButtons.Add&#8221; e temos ao inv\u00e9s de novos bot\u00f5es, apenas novas op\u00e7\u00f5es de radiobutton. <\/p>\n\n\n\n<p>Adicionalmente, fizemos com que nossas escolhas sejam um array de strings ent\u00e3o o numero de op\u00e7\u00f5es \u00e9 limitada apenas pela quantidade de elementos que couberem na tela. E fiz um pequeno mimo a mim mesmo, se uma das op\u00e7\u00f5es terminar com &#8220;*&#8221; no texto da op\u00e7\u00e3o ent\u00e3o a mesma ser\u00e1 considerada um radiobutton default.<\/p>\n\n\n\n<p>Veja a forma de usar a fun\u00e7\u00e3o acima:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;pascal&quot;,&quot;mime&quot;:&quot;text\/x-pascal&quot;,&quot;theme&quot;:&quot;default&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:true,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;Pascal&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;pascal&quot;}\">var\n  iResposta:Smallint;\nbegin\n  iResposta:=QueroEscolher(\n    'Gerar planilha contendo os dados', \/\/ ACaption:String;\n    'Gerar planilha contendo os dados sigilosos?', \/\/ ATitle:String;\n    'Ao prosseguir voc\u00ea concorda com os termos LGPD e manter\u00e1 os dados dessa planilha '+\n    'sob controle absoluto e restringindo o seu acesso apenas a si mesmo ou para uso '+\n    'apenas de uma das op\u00e7\u00f5es abaixo.', \/\/ AText:String;\n    [ 'Planilha b\u00e1sica sem dados que possam ligar os dados \u00e0 pessoa',\n      'Planilha b\u00e1sica sem dados que possam ligar os dados \u00e0 pessoa, apenas enviar por email',\n      'Planilha escondendo apenas o CPF e CNPJ*',\n      'Planilha com todos os detalhes restritos',\n      'Planilha contendo todos os colaboradores que solicitaram esta planilha'\n    ]); \n\n  if iResposta&lt;0 then\n    Exit;\n  \/\/ prosseguindo com a planilha...<\/pre><\/div>\n\n\n\n<p>E o resultado ser\u00e1 algo assim num ambiente Windows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"395\" height=\"329\" src=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/09\/image.png\" alt=\"\" class=\"wp-image-2004\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/09\/image.png 395w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/09\/image-300x250.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/09\/image-14x12.png 14w\" sizes=\"auto, (max-width: 395px) 100vw, 395px\" \/><\/figure>\n\n\n\n<p>Ao mostrar como usar bot\u00f5es e radiobuttons numa janela de dialogo do TaskDialog creio que cobrimos 90% do uso pr\u00e1tico para ele, mas isso n\u00e3o quer dizer que restam apenas 10% de recursos novos que n\u00e3o detalhei, vou repetir <strong>&#8220;cobrimos 90% do uso pr\u00e1tico&#8221;<\/strong> pois ainda h\u00e1 muitas outras formas de uso com inclus\u00e3o de hyperlinks, checkboxes, rodap\u00e9s, \u00edcones personalizados&#8230; mas que particularmente n\u00e3o considero o feij\u00e3o com arroz que precisamos para o dia a dia, mas caso queira consider\u00e1-los poder\u00e1 visitar os links que mencionei.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclus\u00e3o<\/h2>\n\n\n\n<p>O TaskDialog \u00e9 uma excelente op\u00e7\u00e3o para cria\u00e7\u00e3o de janelas de dialogo personaliz\u00e1veis. E neste artigo usamos ele para fatorar janelas de di\u00e1logos repetitivos onde as op\u00e7\u00f5es de respostas est\u00e3o previamente definidas como foi feito acima com as fun\u00e7\u00f5es ShowMessage2 e MessageDlg2. <\/p>\n\n\n\n<p>Voc\u00ea pode criar dentro do seu projeto fun\u00e7\u00f5es gen\u00e9ricas usando o TaskDialog por baixo do cap\u00f4 como eu demonstrei aqui, assim voc\u00ea evitar trocentas linhas de programa\u00e7\u00e3o a cada vez que usar o TaskDialog.<\/p>\n\n\n\n<p>Se voc\u00ea est\u00e1 preocupado com o Delphi, o Delphi tem uso bastante similar ao que mencionei aqui, alias creio que o c\u00f3digo ser\u00e1 o mesmo para Lazarus e Delphi. Minha experiencia com o Lazarus \u00e9 que h\u00e1 constantes novas no Lazarus que n\u00e3o existem no Delphi, por exemplo o Delphi n\u00e3o possui a constante <strong>tdiQuestion <\/strong>para usarmos na propriedade MainIcon.<\/p>\n\n\n\n<p>Escrevam bons c\u00f3digos e at\u00e9+<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Por muito tempo, a maneira mais f\u00e1cil de criar um aviso textual foi usando o ShowMessage(&#8216;Hello World&#8217;). Claro que o ShowMessage n\u00e3o vem sozinho, com eles uma s\u00e9rie de janelas de dialogos que podemos ver no link abaixo: https:\/\/wiki.freepascal.org\/Dialog_Examples Neste artigo vamos ver como substituir o ShowMessage, MessageBox e MessageDlg por uma varia\u00e7\u00e3o moderna chamada [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"parent":159,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"templates\/template-full-width.php","meta":{"footnotes":""},"class_list":["post-1569","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1569","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/comments?post=1569"}],"version-history":[{"count":25,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1569\/revisions"}],"predecessor-version":[{"id":2570,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1569\/revisions\/2570"}],"up":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/159"}],"wp:attachment":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/media?parent=1569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}