Tutoriais Básicos de Programação em AutoHotkey!

Artigos, manuais, conselhos e dicas sobre programação em AutoHotkey

Moderator: Gio

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 03 Apr 2018, 12:47

Seja bem-vindo :angel:

Este tópico tem o objetivo de apresentar uma série de tutoriais em português para os que querem aprender a programar o seu computador. O AutoHotkey é uma excelente ferramenta para aprendizagem de programação que permite que você, em pouco tempo, já esteja escrevendo seus programas e automatizando as tarefas do seu computador. Por esta razão, ele atende aos mais diversos tipos de usuários, podendo ser utilizado para fazer desde pequenas ações no computador até programas inteiros com dezenas de telas e conexão via banco de dados ou via web.

Apesar de já termos uma tradução dos tutoriais oficiais neste fórum, acredito que eles se apresentam de uma forma um tanto quanto resumida, e são mais indicados para quem quer iniciar de uma forma rápida o uso da ferramenta, sem se aprofundar nos conceitos. E como o assunto programação é bastante extenso, decidi escrever esta série com o objetivo de auxiliar quem está começando agora de uma forma mais didática, explicando de forma clara todos os conceitos básicos para que fique mais fácil e mais rico este início na programação.

Portanto, se você já leu os tutoriais oficiais e quer rever alguma coisa com mais detalhe ou se quer simplesmente aprender e consolidar desde o nível básico os conceitos envolvidos na programação, sinta-se livre para ler estes tutoriais e solidificar seu aprendizado. Recomendo que leia um tutorial a cada dia, dedicando um tempo a pensar sobre os conceitos desenvolvidos, e também que leia os tutoriais do primeiro ao último, pois os conceitos aprendidos em um tutorial servirão aos tutoriais seguintes.

Um forte abraço.

Tutoriais desta Série

I . Básico de Scripts, Programação e Automação
:arrow: Neste primeiro tutorial você vai aprender o que é um script, bem como a forma básica de como este se organiza e como pode ser criado e editado por você. Além disso, será apresentado aos conceitos de programação e automação, que serão explicados através de analogias e outras ferramentas de linguagem que permitem um melhor entendimento.

II . Básico de Variáveis, Expressões e Comandos em AutoHotkey
:arrow: Neste segundo tutorial, você verá o que são variáveis, bem como as questões referentes aos diferentes tipos de dados e ainda iniciaremos um estudo dos comandos, que são uma das principais ferramentas que usamos para resolver os problemas através de programação no AutoHotkey.

III. Desenvolvimento de um Programa Funcional Básico em AutoHotkey
:arrow: No terceiro tutorial desta série, aproveitamos para consolidar nosso aprendizado com um exemplo prático de projeto em AutoHotkey. Para isso nós vamos projetar e escrever um programa gerador de relatórios, que servirá para o nosso usuário criar relatórios personalizados, com título escolhido por ele e data equivalente a data em que foram criados. Este tutorial cobrirá tudo isso passo a passo, de modo que fique mais fácil entender como funciona o desenvolvimento de sistemas, desde o planejamento até a execução. Também aproveitamos para introduzir algumas novas ferramentas que o AutoHotkey possui para auxiliar seus desenvolvedores na criação dos seus scripts, como as variáveis embutidas e outros comandos.

IV. Básico de Condicionais de Execução e Blocos de Códigos
:arrow: No quarto tutorial desta série, vamos falar sobre as Condicionais de Execução, que permitem que apenas uma parte do código do script seja executada se uma ou mais condições impostas por nós venha a ocorrer. Faremos isto apresentando o exemplo de um programa que pede uma senha e depois verifica se essa senha corresponde a uma que ele tinha guardada em seu código. Se o usuário acertar a senha, o programa exibe uma caixa de texto, mas se ele errar, nada será exibido. As condicionais de execução são fundamentais para implementarmos programas complexos, que precisam interagir com o usuário de várias formas e agir de formas diferentes em cada caso.

V. Básico de Funções e Labels
:arrow: O quinto tutorial de nossa série será destinado ao aprendizado de funções e labels (rótulos). Estas funcionalidades permitem que possamos criar códigos mais complexos de forma fácil e organizada, assim como programar ações separadas no script e também permitem que possamos usar facilmente códigos escritos por outras pessoas em nossos scripts. Praticamente todos os scripts maiores, com telas e controles, utilizam funções e/ou labels, então vale muito a pena conferir este assunto.

VI. Básico de Telas em AutoHotkey
:arrow: Neste sexto tutorial de nossa série, vamos aprender a criar telas (também chamadas de janelas) para os nosso programas em AutoHotkey. Aqui, você encontrará uma explicação do que são as telas, para que servem, como elas são feitas e ainda um exemplo passo a passo de criação de uma tela totalmente funcional em AutoHotkey, que implementa uma agenda de contatos. Se você deseja criar programas profissionais em AutoHotkey, vale muito a pena conferir este tutorial (mas somente após os outros!).

VII. Básico de Arquivos
:arrow: No sétimo tutorial desta série, veremos o que são os arquivos de computador. É comum hoje em dia que trabalhemos com computadores praticamente a vida toda sem nunca saber de verdade o que são esses arquivos. Como programadores, convém conhecer um pouco mais a fundo os arquivos de computador, de modo que possamos trabalhar com eles de forma avançada, coletando informações deles ou até mesmo elaborando nossos próprios arquivos. Se você está seguindo esta série e deseja conhecer mais sobre os arquivos de computador, não perca este tutorial!

VIII. Desenvolvimento de um Programa com Telas e Arquivos
:arrow: No oitavo tutorial desta série, vamos consolidar os conhecimentos adquiridos nos dois últimos tutoriais através de um programa exemplo que gerencia telas e arquivos. Para isso, executaremos um projeto de um programa Gerenciador de Tarefas, que permite ao usuário organizar suas tarefas e trabalhos de modo a não ter de se ver com aquela sensação de urgência desconfortável quando as datas de entrega vão se aproximando. Se você deseja aprender como criar um programa completo, com telas, arquivos e lógica de rotinas, não perca este tutorial!

IX. Paradigmas (estilos) de programação: Programação Orientada a Objetos (OOP)
:arrow: O nono tutorial desta série fecha com chave de ouro o básico de programação em AutoHotkey. Até aqui já fizemos bastante coisa e chegamos até a criar programas completos. Agora, vamos discutir um pouco sobre paradigmas de programação, que são estilos através dos quais pensamos e implementamos os nossos programas. O AutoHotkey atualmente oferece suporte para Programação Procedural e Programação Orientada a Objetos. A primeira você já conhece (embora que não tenha sido chamada assim até aqui) e a segunda eu te convido a conhecer neste tutorial.

Mais tutoriais em breve!
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 16:31

I. Tutorial Básico de Scripts, Programação e Automação

Olá :angel:

Este tutorial é o primeiro de uma série que tem por objetivo ensinar aos iniciantes do AutoHotkey como escrever seus próprios programas. O assunto aqui tratado será bem básico e teórico, portanto, se você já consegue escrever algum script qualquer, este tutorial servirá apenas para consolidar conceitos e tirar dúvidas. Do contrário, se você nunca escreveu nenhum script, este tutorial pode ser a melhor maneira para você iniciar neste novo mundo chamado programação.

Vamos lá? :thumbup:

1. Script: o que é isso?
Script.png
Script.png (4.22 KiB) Viewed 76394 times
A grosso modo, um script é um arquivo de texto com comandos escritos linha a linha que permitem a um programador (você) dizer a um programa (o AutoHotkey) o que você quer que ele faça. Se você já tiver o AutoHotkey instalado em seu computador, criar um script é tão fácil quanto clicar com o botão direito do mouse na área de trabalho do Windows e selecionar Novo -> AutoHotkey Script. Você verá que um arquivo será adicionado à sua área de trabalho com um ícone de letra H. Depois, para abrir o arquivo em um editor de texto e começar a escrever nele, basta clicar encima dele com o botão direito do mouse e selecionar "Edit script". Além disso, quando o seu arquivo já contiver comandos escritos na linguagem do AutoHotkey, basta salvá-lo e depois ir na área de trabalho e clicar duas vezes encima dele (o arquivo com ícone de H) para que o AutoHotkey execute todos os comandos que você programou nele.

Uma segunda forma de criar um script é abrir o Bloco de Notas do Windows e salvar o arquivo com uma extensão .ahk. Para fazer isso, basta você clicar em Arquivo -> Salvar Como, selecionar o Tipo: como Todos os Arquivos e depois colocar um nome qualquer seguido de .ahk no seu arquivo. Depois é só clicar em Salvar que o seu script será criado na posta onde salvou o arquivo.

Para facilitar ainda mais o entendimento, podemos pensar no script de programação através da analogia com o script de uma peça de teatro: o script diz o que será feito por cada ator e atriz, incluindo suas falas, organizadamente e de forma sequencial, de modo que a peça seja executada por toda a equipe em uma sincronia e planejamento previamente definidos pelo autor que escreveu a peça.


2. O Script: Como se escreve?

A forma de escrever o script é obedecendo a sua linguagem de programação. Uma linguagem de programação nada mais é do que um conjunto de normas de escrita e organização que permite que haja uma comunicação efetiva entre o programador e o software interpretador dos comandos (o AutoHotkey no nosso caso). A linguagem de programação é conhecida pelo software interpretador e deve ser aprendida pelo programador para que este possa escrever os comandos e entender o que vai acontecer.

Parece difícil? :crazy:

Não se preocupe, você não deve ter nenhum receio de aprender uma linagem de programação: essas linguagens são projetadas para serem extremamente simples e de fácil aprendizado. Além disso, seu aprendizado é gradual, o que significa que você já consegue fazer uso da linguagem desde o primeiro dia do aprendizado (é muito mais fácil aprender uma linguagem de programação do que aprender inglês ou qualquer outra língua falada :lol: )

:arrow: Se você seguir os tutoriais desta série, logo vai estar escrevendo seus primeiros scripts, lembrando que a maioria dos exemplos apresentados contém códigos que podem ser executados copiando e colando no seu script.

3. O Script: A importante sequência de execução dos comandos

O principal conceito aplicado à criação de um script é o conceito de ordem (ou tempo) de execução dos comandos. Podemos dizer a grosso modo que em um script com vários comandos escritos linha a linha, há sempre uma ordem de execução definida pela posição da linha, pois a linha de cima é geralmente executada antes da linha de baixo. Isto permite que possamos encadenar vários comandos, de modo que o programa os execute passo a passo, seguindo uma lógica definida pelo programador.

Assim, quando abrimos um script de AutoHotkey, a primeira linha do mesmo será onde vamos escrever o primeiro comando a ser executado. Da mesma forma, na segunda linha do script, colocaremos o segundo comando, que só será executado após o primeiro comando. Isto é o que permite, por exemplo, que solicitemos um número ao usuário do programa e depois apresentemos a ele o resultado de multiplicar aquele número por 10. Na primeira linha, escrevemos o comando que solicita o número. Na segunda, colocamos o comando que multiplica o número. E na terceira, finalmente, vai o comando que apresenta o resultado a ele.

Essa ordem é bem simples e racional, e é também necessária: Se tentarmos escrever a apresentação do resultado na primeira ou na segunda linha, o programa não terá o resultado ainda, pois ainda não se executou o comando da multiplicação do valor.

:arrow: Cada linha deve conter apenas um comando. De maneira geral, não se pode colocar dois comandos em uma mesma linha. Desta forma, para escrever um outro comando em um script, você deve teclar enter no seu editor de texto, de modo que o próximo comando seja escrito na próxima linha!

Tendo dito isto, vamos dar uma pausa da teoria. Que tal um pouco de prática agora? :thumbup:

4. O primeiro script

Preste atenção no código que apresentarei abaixo. Em um primeiro momento, você ainda não saberá o que ele faz, mas usando o que dissemos nos itens 1 e 2, você pode criar um novo script do AutoHotkey, editar ele, e depois colar este pedaço de código na janela de editor de texto que se abre, substituindo tudo o que estiver lá. Depois é só salvar e clicar duas vezes no script para executá-lo.

Code: Select all

msgbox olá mundo!
msgbox este é o meu primeiro script de AutoHotkey
msgbox e com ele eu aprenderei o básico de programação
Conseguiu executar o código? Se você fez da forma correta, devem ter sido exibidas três caixa de texto, sendo que a primeira continha a mensagem "olá mundo!" e a segunda e terceira continham as mensagens das outras linhas. Você observou que estas linhas contém um comando cada uma e esses comandos foram executados na mesma ordem das linhas, da primeira até a terceira?

Veja também que cada linha na verdade é um comando chamado msgbox. Este comando é o comando que exibe uma caixa de texto no AutoHotkey. O que define que ele foi chamado (e não um outro comando qualquer) é o seu nome escrito no início da linha. Da mesma forma, após o nome do comando, temos três frases diferentes, uma em cada linha. Estas frases são exatamente o quê será exibido em cada caixa de texto, e você pode alterá-las e salvar o script para mudar as mensagens exibidas quando abrir o script de novo (mas mantenha o nome msgbox no inicio de cada linha, pois isso é necessário!).

:arrow: Manter o nome msgbox e em seguida escrever a mensagem que quer que seja exibida é uma regra simples que obedece à sintaxe (forma de escrever) do comando msgbox. Se você tentar colocar outro nome no início, o AutoHotkey provavelmente não entenderá o seu comando e vai apresentar um erro se você tentar executar o script (ele também lhe dirá em que linha estará o erro, para que você possa corrigir).

5. De forma básica: o que é Programação?

Agora que já temos uma ideia do que é um script e como ele funciona, vamos discutir um pouco o trabalho de programação. Programação é um processo. Através desse processo, criamos os programas, que são planejamentos de execução de instruções de forma organizada sequencialmente, com o objetivo de realizar um trabalho.

Simples não? :angel:

A isto segue-se o como se programa: A resolução de um problema complexo (do tipo "como criar um editor de texto parecido com o Word") é encontrada através da divisão do mesmo em várias tarefas simples e graduais, que serão resolvidas como passos individuais da tarefa maior.

Assim para nos tornarmos programadores, temos que simplesmente adquirir os meios de dividir uma tarefa complexa (que NÃO significa difícil, mas sim abstrata) em várias tarefas simples, que possam ser implementadas sequencialmente até que se cumpra a tarefa complexa.

Dessa forma, a resposta para uma pergunta do tipo como fazer um programa que nem o Excel? é simplesmente identificar os elementos menores que esse programa deve possuir, para então criarmos novas perguntas do tipo como crio um botão em uma janela?, que (essas sim) são prontamente respondidas pela implementação das ferramentas que temos disponíveis (E você sabia que o AutoHotkey tem um comando que cria um botão em uma janela? :thumbup: ).

:arrow: Coletar o conhecimento sobre as ferramentas disponíveis (ou seja, aprender os comandos) é o que vai permitir que você faça uma melhor divisão das tarefas complexas em tarefas simples e possa então implementá-las conforme o seu projeto.

6. E o que é Automação?

Ser uma ferramenta de automação é uma outra vantagem do AutoHotkey. Automação é fazer com que tarefas que antes eram executadas com o trabalho de um operador humano passem a ser executadas por uma máquina (ou software).

Assim, o AutoHotkey permite que programemos a automação de tarefas em ambiente windows. Isto pode ser feito de várias maneiras, através dos vários comandos de automação que o AutoHotkey possui, como o comando Click (que simula o clicar do mouse em um ponto qualquer da tela), o comando Send (que simula o envio de comandos do teclado para a janela ativa) e o comando Sleep (que simula uma pausa entre comandos).

Lembrando da importância da sequência de execução e de como definimos isso pela posição das linhas do script, é fácil perceber que podemos usar esses três comandos acima para automatizar várias tarefas diferentes (Seria mais menos como esse exemplo: clicar em um arquivo, depois enviar um enter, depois dar uma pausa de 5 segundos, depois clicar na tela que se abriu, depois escrever alguma coisa... Cada ação dessas corresponderia a um comando escrito em uma linha do script).

:arrow: Se você executa alguma tarefa repetitiva no seu computador, ou se alguma tarefa que você executa tem uma parte repetitiva, saiba que está diante de uma tarefa que pode ser uma excelente candidata à automação: valorize seu tempo criando hotkeys e scripts para não ter de ficar clicando ou digitando sempre a mesma coisa!

7. Ferramentas para auxiliar na escrita de códigos

Agora que já sabemos o que é um script, e como usamos scripts do AutoHoktey para automação e programação em ambiente Windows, convém destacar um ponto importante: escrever códigos em um editor de texto como o Bloco de Notas do windows não é o ideal. Isso ocorre porque o Bloco de Notas é um editor de texto muito básico, que não possui uma série de funcionalidades que outros editores de texto possuem e que são muito úteis para auxiliar o desenvolvedor.

Um exemplo dessas funcionalidades é o syntax highlight que é basicamente colorir com diferentes cores as palavras chaves (como nomes de comandos) que sejam escritas pelo programador. Essa funcionalidade é muito importante porque facilita muito a leitura do código. Se você olhar o código escrito na imagem ao fundo da página principal do AutoHotkey, verá que foi escrito com Syntax Highlight. Veja como fica mais fácil identificar ao que corresponde cada parte dos comandos escritos: isso é muito importante para se trabalhar com códigos extensos.

Além dessa funcionalidade, algumas outras também podem ajudar muito. Outro exemplo de funcionalidade que eu particularmente uso bastante é o botão de execução. Com ele, você não precisa salvar o script, abrir a pasta e clicar no ícone do arquivo salvo: basta acionar o botão de dentro do próprio editor de texto e o script será executado imediatamente. Isso é muito útil, pois durante o desenvolvimento do programa é comum realizar vários testes de execução conforme você vai escrevendo as linhas. Isso serve para certificar-se de que não houveram erros silenciosos na escrita das últimas linhas. Erros silenciosos são aqueles que estão de acordo com a sintaxe da linguagem de programação, mas que produzem um efeito diferente do que você esperava: eles não são detectados pelo interpretador como sendo erros, e portanto, devem ser detectados sempre pelo próprio programador. Um exemplo de erro silencioso é escrever uma caixa de texto com uma mensagem que contém uma palavra errada, tipo "pograma" ao invés de "programa". Não tem como o interpretador saber que você errou a palavra. Por isso é bem mais fácil detectar um erro silencioso se você testar seu código sempre que alterar uma linha ou no máximo duas, prestando atenção no que mudou de fato. Dessa forma, é melhor que nos acostumemos a programar assim: escrevemos uma linha ou duas e já testamos novamente o programa observando a mudança ocorrida e vendo se ficou exatamente como queríamos. É possível testar novos valores de variáveis e resultados de expressões após uma linha simplesmente usando um comando de caixa de texto para exibi-los! (Você apaga esse comando "a mais" depois que executar o teste).

Essas facilidades vão ajudar muito na escrita de códigos, seja no início do aprendizado ou mais à frente, quando você já estiver experiente.

:arrow: Para conferir os principais editores de texto específicos para programar com o AutoHotkey (e disponíveis para download sem custo algum), basta ir no fórum de editores de texto. Eu particularmente lhe recomendo um desses dois: SciTE4AutoHotkey ou AHK Studio :thumbup:

8. Considerações finais

Se você seguiu este tutorial até aqui parabéns! :bravo:

Saiba que já aprendeu muito do que será necessário para criar os seus próprios scripts. Os próximos tutoriais dessa série serão focados em apresentar-lhe os outros princípios básicos necessários para iniciar a programação em AutoHotkey. Se tiver quaisquer dúvidas sobre o conteúdo deste tutorial, sinta-se livre para postar abaixo ou criar um tópico no fórum Eu Preciso de Ajuda.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 18:43

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 18:43

II. Tutorial Básico de Variáveis, Expressões e Comandos em AutoHotkey

Olá novamente :angel:

Decidi escrever este tutorial porque o uso das variáveis e das expressões em comandos confunde muito os iniciantes na programação no AutoHotkey, e isso pode fazer com que um script aparentemente normal não execute da forma planejada. Uma situação muito comum é quando o desenvolvedor escreve um comando e não coloca os símbolos de percentuais em um parâmetro (ou os coloca) e na verdade esse parâmetro não esperava (ou esperava) o uso desses percentuais. Como saber se um parâmetro requer percentuais ou não?

Ler este tutorial com certeza vai ajudar muito a quem deseja iniciar a programação em AutoHotkey.

Vamos lá? :thumbup:

1. Variáveis: o que são?

Image

A grosso modo, variáveis são repositórios de valores. Quando desejamos programar um trabalho a ser executado em um script e temos de lidar com valores que podem ser diferentes dependendo do que ocorra na execução do programa, precisamos de uma ou mais variáveis. Um exemplo bem básico é de um programa que pede a um usuário um número e o multiplica por 10, apresentando depois o resultado. Não sabemos que número o usuário vai escolher, então como programaremos isso?

Simples! vamos usar uma variável. Para facilitar nosso entendimento do que é a variável, vamos imaginar que a variável é como um endereço fixo na memória. A forma como esse conceito resolve nosso problema é a seguinte: primeiro programamos o colocar do número escolhido pelo usuário em um exato endereço e depois (em uma linha posterior) programamos a multiplicação do que estiver naquele exato endereço por 10.

Assim, se o usuário digitar 3, o programa coloca 3 naquela variável (que é como um endereço) e depois multiplica o que está naquela variável (ou seja, 3) por 10, obtendo 30. Já se o usuário digitar 5, da mesma forma o programa vai colocar o 5 naquela variável e depois multiplicar o que está naquela variável (ou seja, 5 agora) por 10, obtendo 50. É assim que o programa consegue trabalhar com qualquer valor que o usuário insira: basta usar uma variável. Dessa forma, programamos as rotinas de trabalho e não os valores diretamente, mas ainda assim obtemos no final um trabalho da rotina sobre os valores no momento em que o programa rodar (pois os valores das variáveis, ainda que não sejam conhecíveis ao desenvolvedor no momento da programação, são sempre conhecíveis ao programa no momento em que ele roda, pois é nesse momento que o usuário os digitará ou que o programa os coletará de algum outro lugar).

Desta forma, quando se roda um programa calculador, como o que multiplica por 10, podemos inserir nele valores diferentes em cada execução do programa e assim obter resultados diferentes. A possibilidade de se trabalhar com valores diferentes é o que faz com que chamemos a variável de variável (ou seja, uma palavra que remete ao conceito de "valor modificável").

Ficou mais fácil de entender? :)

:arrow: Existem outras analogias do que é a variável: podemos pensar que é uma caixa onde podemos pedir a alguém que coloque alguma coisa para que saibamos depois onde estará e assim possamos indicar uma ação para fazer com o que estiver lá, podemos também imaginar que é um espaço na nossa agenda onde podemos em algum momento marcar data e horário de um evento de modo que depois saibamos qual evento e em que data vai acontecer apenas consultando a agenda, e etc.

2. Tipos de Dados

Como qualquer linguagem de programação, o AutoHotkey as vezes precisa lidar com dados que têm um mesmo valor, mas que podem significar coisas diferentes. Um exemplo bem básico é o seguinte: suponha que tenha colocado em uma variável o seguinte valor: 2 + 2

Agora suponha que eu queira apresentar esse valor em uma tela para que o usuário possa ver. O dilema que temos aqui é o seguinte: será que o valor deve ser apresentado do jeito que eu escrevi (ou seja, 2 + 2) ou será que deve ser apresentado na forma de resultado (ou seja, 4)?

:arrow: O AutoHotkey pode interpretar e trabalhar dados de duas formas simples: de forma matemática ou de forma literal. Sabendo disso, em cada situação onde esses dados serão usados, seja dentro de comandos ou na hora de colocar os valores nas variáveis, temos que ter em mente como queremos que esses valores sejam interpretados pelo AutoHotkey para que possamos escrever os valores da exata forma que queremos que eles sejam interpretados.

Vamos ver como fazer isso a seguir :thumbup:

3. Escrevendo variáveis com cada tipo de dados

Agora que sabemos que temos de tomar o cuidado de pensar na forma como os dados serão interpretados quando escrevemos seus valores, como faremos para identificar estas formas de interpretação ao escrever códigos de inserção de valores em variáveis? Simples: usaremos operadores (ou seja, símbolos do teclado) que vão forçar o AutoHotkey a interpretar os dados da forma que queremos.

O primeiro tipo de operadores que lida com a forma como os dados são interpretados são os operadores de inserção de dados em variáveis. Temos dois principais operadores nesse caso: o primeiro é o símbolo de igual (ou seja, =), que será usado para que a interpretação dos valores seja estritamente literal, e o segundo é o símbolo de dois pontos seguido do símbolo de igual (ou seja, :=), que será usado para que a interpretação seja matemática.

Veja no exemplos abaixo a sintaxe (a forma de escrever) que usamos para inserir valores em variáveis nos dois casos:

Primeiro caso (escrita literal):

Code: Select all

Var1 = 2 + 2
Segundo caso (escrita matemática):

Code: Select all

Var2 := 2 + 2
Primeiro indicamos o nome da variável. Os nomes de variáveis podem conter letras e números, mas não podem conter espaços e nem alguns símbolos.
Depois usamos um operador de inserção de dados. Você viu a diferença nos dois operadores usados nos dois casos acima? No caso da variável Var1 usamos o operador =, portanto estamos inserindo o valor 2+2 nela. Já no caso da variável Var2, usamos o operador :=, portanto estamos inserindo o valor 4 em Var2. Isto ocorre porque dissemos ao AutoHotkey que no segundo caso o valor 2 + 2 deve ser intepretado de forma matemática, o que faz com que ele primeiro resolva o 2 + 2 em simplesmente 4 e daí armazene este 4 na variável.

:arrow: Você não pode usar espaços nos nomes de variáveis, mas pode usar underlines (ou seja, _) e também pode usar maiúsculas e minúsculas. Assim, se quiser indicar um nome que seria escrito com mais de uma palavra, tipo "idade do usuário", você pode escrevê-lo como IDADE_DO_USUARIO, IdadeDoUsuario ou mesmo Idade_Do_Usuario. Lembre-se apenas de não colocar acentos!

Agora vamos ver um último caso de escrita de valores em variáveis também muito importante :D

4. Escrevendo variáveis com os dois tipos de dados

Agora que já sabemos como escrever os valores nas variáveis de modo a controlar a forma como serão interpretados, imagine a seguinte situação: preciso escrever isto numa variável: João tem 2 + 2 maçãs.

Escrever de forma estritamente literal é fácil (embora não seja o que queiramos, já que o 2 + 2 vai continuar sendo 2 + 2):

Code: Select all

Var1 = João tem 2 + 2 maçãs
Mas escrever de forma matemática e ainda permitir que os números sejam trabalhados em um valor final vai requerer algo a mais, pois essa frase tem letras e palavras no meio, portanto não resolve imediatamente de forma matemática. O que fazemos então é usar outro operador que permite que unamos em qualquer caso uma frase literal e uma expressão matemática. O operador que vou apresentar para resolver o caso é o de aspas duplas (ou seja, "). Ele deve ser colocado no início e no fim de todas as frases estritamente literais que estiverem dentro de expressões matemáticas.

Code: Select all

Var2 := "João tem " 2 + 2 " maçãs"
Pronto! Se você exibir o conteúdo da variável Var2 acima em uma caixa de texto vai ter como conteúdo de Var2 a frase João tem 4 maçãs (vamos tratar sobre a exibição de valores em caixas de texto logo adiante, então não se preocupe com isso agora: por enquanto apenas pense em como o código acima chegou a esse valor para inserir em Var2)

5. Variáveis dentro de expressões matemáticas e literais

Como dissemos no item 1 deste tutorial, as variáveis são muito importantes para escrevermos nossos scripts, pois elas nos permitem guardar valores e depois recuperá-los. Sendo assim, agora que já sabemos como escrever dados em variáveis de forma literal e de forma matemática, como fazemos para recuperar esses dados delas?

Para recuperar os valores que estiverem dentro de uma variável também precisamos lembrar se estamos escrevendo algo que será interpretado de forma matemática ou de forma literal. Dentro de uma expressão com interpretação matemática, recuperar valores de variáveis é tão simples quanto escrever o nome da variável em questão.

Code: Select all

Var1 = João tem 
Var2 := 2 + 8 - 1
Var3 = maçãs
Var4 := Var1 Var2 Var3
No código acima, o resultado que será inserido em Var4 é João tem9maçãs. Como isso ocorreu? Veja que na linha 1 coloquei o valor João tem dentro da variável Var1 de forma literal, pois usei o operador =. Na linha 2, coloquei o resultado matemático de 2 + 8 - 1 dentro de Var2, pois o inseri de forma matemática usando :=. Na linha 3, coloquei o valor maçãs dentro de Var3 de forma literal, e na linha 4, juntei tudo simplesmente recuperando os valores que estavam em cada variável na sequência correta. Isso funcionou porque o operador da linha 4 é o operador matemático, logo, cada uma das variáveis nomeadas foram resolvidas automaticamente para apresentar os seus respectivos valores, que foram então inseridos na ordem em Var4.

Agora vejamos um segundo caso. Como faço para fazer a mesma coisa (inserir os resultados de variáveis) em uma variável usando o operador literal? Bom, nesse caso, precisaremos usar o operador percentual (ou seja, %) que será colocado imediatamente antes e também imediatamente depois do nome de cada variável. Assim, um código equivalente ao de cima, mas usando operador literal para inserir dados na Var4 seria:

Code: Select all

Var1 = João tem 
Var2 := 2 + 8 - 1
Var3 = maçãs
Var4 = %Var1% %Var2% %Var3%
Veja que o resultado foi o mesmo, mas agora temos espaços entre as variáveis. Isso é um bônus, mas não esqueça que também pode ser feito em uma expressão matemática usando as já descritas aspas duplas!

Code: Select all

Var1 = João tem 
Var2 := 2 + 8 - 1
Var3 = maçãs
Var4 := Var1 " " Var2 " " Var3
6. Valores matemáticos e literais dentro de parâmetros de comandos

Uma das grandes vantagens do AutoHotkey é que ele possui uma série de comandos que automatizam tarefas do computador, como clicar em um lugar ou escrever um texto em um campo. Usar esses comandos requer uma noção básica da sintaxe deles e também os conhecimentos que você já adquiriu neste tutorial. Para entender a sintaxe dos comandos, pense o seguinte: o comando deve ser escrito em uma nova linha do script colocando:

o nome dele, seguido de uma vírgula e depois do seus parâmetros na ordem correta, todos separados por vírgulas.

Ou seja, para o comando msgbox, que exibe uma caixa de texto, a forma de escrita é

msgbox, parametro1, parametro2, parametro3, parametro4

Lembrando que o padrão depois disso continuará por quantos parâmetros tiver aquele comando (alguns comandos tem 1 parametro, outros 2, outros um número qualquer. Todos os parâmetros serão dispostos sequencialmente e separados por vírgulas, logo após o nome do comando).

:arrow: Em cada página dos documentos de ajuda do AutoHotkey, você encontra em amarelo na parte superior a sintaxe e o nome dos parâmetros do comando. Os parâmetros que forem opcionais naquele comando (ou seja, que não são totalmente necessários) normalmente são os últimos e são apresentados entre colchetes (ou seja, entre [ e ]). Mas se por exemplo você quiser usar o quinto parâmetro e a partir do terceiro todos forem opcionais, não esqueça de colocar todas as vírgulas!

Exemplo de caixa de sintaxe (cada linha é uma sintaxe diferente que você pode usar):
Caixa de Sintaxe.png
Caixa de Sintaxe.png (2 KiB) Viewed 76374 times
:arrow: A descrição dos parâmetros está na página de ajuda do comando logo após a caixa de sintaxe, e as descrições de cada parâmetro são separadas na página de ajuda pelo nome dos parâmetros correspondentes.
DESCRICAO DOS PARAMETROS.png
DESCRICAO DOS PARAMETROS.png (35.9 KiB) Viewed 75575 times
Dessa forma, fica mais fácil entender o que deve ser escrito em cada parâmetro: basta ler a descrição dele no arquivo de ajuda (traduzindo com o Google se for necessário). Você também pode fazer perguntas em português sobre os parâmetros ou qualquer outra dúvida em nosso fórum Eu Preciso de Ajuda.

A lista de páginas de ajuda de comandos pode ser conferida aqui.

Tendo dito isto, creio que agora você já entende um pouco sobre a sintaxe dos comandos. Assim, vamos falar então sobre como escrever os parâmetros dos comandos de um modo geral. Além de saber qual valor você deve escrever em cada parâmetro, você também deve prestar um pouco de atenção sobre a forma como o valor vai ser interpretado pelo parâmetro. Da mesma forma que quando escrevemos variáveis, teremos que nos atentar para a interpretação do valor inserido. Cada parâmetro de cada comando pode esperar, a princípio, uma só dessas três hipóteses: que o valor nele escrito seja algo estritamente literal, ou que seja uma única variável, ou então que seja uma expressão matemática.

Estas três hipóteses tem que ser verificadas quando vamos escrever um parâmetro. Será que esse parâmetro espera uma variável? Ou será que espera um texto? ou será que espera uma expressão matemática? É exatamente essa resposta que vai definir como vamos escrever o valor daquele parâmetro.

De um modo geral, o arquivo de ajuda e o nome do parâmetro nos dizem quase de cara que tipo de valor escrever. A maioria dos parâmetros esperam um valor literal, e muitos deles esperam valores específicos (que você pode encontrar listados no arquivo de ajuda). Além disso, um parâmetro que se chame text ou Title ou qualquer palavra que remeta a uma frase obviamente vai esperar um valor literal. Já se o parâmetro se chamar OutPutVar, InPutVar ou qualquer outra coisa com Var no meio, ele deve esperar o nome de uma única variável e somente isso (sem percentuais nem nada). Por fim, se o nome do parâmetro for expression ou algo parecido, podemos subentender que devemos escrever os dados em forma de expressão matemática, onde por exemplo 2 + 2 será interpretado como 4 e qualquer palavra escrita será entendida como uma variável que deve ser resolvida para o valor que estiver guardado nela.

Muito conteúdo até aqui? Então vamos tirar as dúvidas na prática! :D

7. Exibindo valores: somatório do que foi discutido

Agora que já concluímos uma breve discussão acerca de variáveis, expressões, tipos de dados e sintaxe de comandos, podemos passar para a melhor parte: a prática. Como fazemos para exibir o resultado de José tem 20 + 5 - 4 maçãs e 16 + 2 são verdes. em uma caixa de texto?

Ora, é só fazer o que aprendemos! Primeiro vamos dividir a sentença em valores em literais e matemáticos. Depois, vamos estudar a sintaxe do comando msgbox para entender como ele quer que escrevamos os parâmetros. Por fim, vamos escrever isso de forma lógica e racional usando os operadores que aprendemos.

Após estudar a frase proposta, vemos que podemos dividir os valores em: literal José tem, seguido de matemático 20 + 5 - 4, seguido de literal maçãs e, seguido de matemático 16 + 2, seguido finalmente de literal são verdes..

Agora, estudamos a sintaxe do comando msgbox, dentro do arquivo de ajuda que você pode acessar aqui.

A caixa de sintaxe (a com fundo em amarelo) nos dá duas possibilidades:
Caixa de Sintaxe.png
Caixa de Sintaxe.png (2 KiB) Viewed 76374 times
Logo, se olharmos a primeira sintaxe (ou seja, msgbox, text) esse comando só tem 1 parâmetro, e o nome dele é text. Assim, podemos perceber que esse parâmetro deve esperar um valor literal (pois seu nome é nada mais nada menos que texto em inglês).

Assim, escreveremos esse parâmetro usando o nosso conhecimentos sobre as formas de inserir valores em variáveis e também de como escrever quando a interpretação vai se dar de forma literal.

Code: Select all

Var1 := 20 + 5 - 4
Var2 := 16 + 2
msgbox Jose tem %Var1% maçãs e %Var2% são verdes.
Se você executar o código acima, verá que a coisa saiu exatamente como deveria sair: o texto foi tratado como texto, os valores matemáticos foram resolvidos e as variáveis fizeram seu papel, trazendo os valores matemáticos resolvidos ao texto que inserimos no parâmetro de msgbox. Como fizemos a escrita do parâmetro na forma em que sua sintaxe esperava, o comando executou de forma correta e a caixa de texto foi exibida de forma correta.

Sucesso :dance:

8. Considerações finais

Se você seguiu este tutorial do inicio ao fim, deve estar bem mais preparado para começar a escrever comandos em AutoHotkey. Tudo que falta agora é estudar as páginas dos comandos e testá-los para aprender o que pode ser feito por eles. Parabéns pela dedicação e por escolher seguir o caminho da automação e da programação, este caminho com certeza lhe levará bem longe :bravo:

Para finalizar este tutorial, aqui vão algumas dicas:

1. A maioria dos parâmetros de comandos espera que você os escreva de forma literal, mas em muitos deles você pode forçar uma interpretação de expressão matemática. Para fazer isso, basta usar um único símbolo de percentual % seguido de um espaço. A partir daquele ponto, todos os parâmetros subsequentes serão interpretados como expressões matemáticas.
MsgBox % "Este texto precisa de aspas duplas, pois forçamos uma interpretação literal aqui. Veja o cálculo a seguir ser resolvido: " 2 + 13 - 1
2. Se você tentar executar um comando escrevendo um texto e o resultado que você escreveu "não aparecer", mas o comando executar normalmente é provável que o comando esteja esperando um valor matemático ou o nome de uma variável naquele parâmetro, pois se você escrever uma palavra ou texto, ele vai tentar resolver como variável e vai trabalhar considerando que você colocou um valor vazio (pois é o que estaria lá se fosse mesmo uma variável).
3. Se você escrever o nome de uma variável e o comando executar, mas o resultado "não aparecer", você pode tentar colocar os percentuais ao redor do nome da variável, pois é possível que o parâmetro esteja esperando um texto.
4. Não se esqueça que quaisquer dúvidas que você tiver com comandos que aparentam não estar funcionando podem ser perguntadas no nosso fórum Eu Preciso de Ajuda, onde a comunidade vai fazer o que puder para respondê-lo o mais rapidamente possível.

Um abraço e fiquem todos na paz :angel:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 18:53

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 18:54

III. Desenvolvimento de um Programa Funcional Básico em AutoHotkey

Bom dia :angel:

Neste terceiro tutorial desta série, aproveito para demonstrar passo a passo o funcionamento de um pequeno programa em autohotkey, de modo que possamos começar a nos habituar à forma de escrita dos scripts e assim nos seja mais fácil desenvolver nossos próprios scripts ou analisar os códigos que a comunidade já escreveu e que podemos utilizar também.

Ler este tutorial com certeza vai ajudar muito a quem deseja iniciar a programação em AutoHotkey.

Vamos lá? :thumbup:

1. Formando o projeto

Suponha que eu deseje fazer o seguinte. Quero criar um formatador de formulário de relatórios. Isso significa, basicamente, que eu quero que o script me ajude a criar relatórios customizados por mim e padronizados, de modo que a leitura desses relatórios seja clara e precisa, e que eles sempre tenham as informações que eu mais preciso colocadas adequadamente nos campos corretos.

Como fazer isso? :wtf:

Simples! :angel:

Vamos dividir esta tarefa em várias tarefas menores e depois vamos usar as ferramentas que o AutoHotkey possui para resolvê-las. É pensando assim que criaremos o nosso projeto.

:arrow: O primeiro passo é pensar nas partes que um formulário de relatório deve ter (ou normalmente tem) e usar cada uma delas como uma divisão do trabalho de criar o relatório. Para fazer isso cabe imaginar o formulário pronto (ou mais ou menos pronto) na nossa mente. Se tivermos dificuldade de fazer isso de imediato, podemos ir à internet e buscar imagens de formulários de relatórios para nos inspirar antes de formar a imagem do nosso próprio relatório, e podemos ainda desenhar em uma folha A4 a nossa ideia inicial de relatório só pra ver como fica. O importante é que tenhamos uma ideia inicial sólida, que podemos mudar conforme avançamos no desenvolvimento, mas que servirá de ponto de partida.

Pensando um pouco, vejo basicamente que um formulário de relatórios legal deve ser um arquivo que possa ser aberto pelo usuário e deve ter um título, deve ter a palavra relatório em letras maiúsculas, um número qualquer de linhas para se escrever, todas numeradas e com ponto e espaço, e ainda a data e campo de assinatura embaixo. Desejo que o sistema cuide de tudo o que puder para que o usuário só precise preencher as informações que forem necessárias.

2. Desenvolvendo o script

Agora que temos uma ideia do que queremos (criar o gerador de formulário de relatórios) e já conseguimos dividir a tarefa maior em várias tarefas menores:

TAREFAS:
  • 1. criar um arquivo de texto
  • 2. colocar título à escolha do usuário
  • 3. colocar a palavra relatório
  • 4. colocar linhas numeradas
  • 5. data e campo de assinatura

Os comados que vamos utilizar para a primeira versão desse projeto são os seguintes:

COMANDOS:
  • 1. Run: Este comando executa um programa ou roda um arquivo com o programa associado ao seu tipo. Também pode abrir páginas da web.
  • 2. Sleep: Este comando cria uma pausa entre a execução dos vários comandos do script.
  • 3. WinActivate: Este comando ativa (torna principal) uma janela aberta que você escolher.
  • 4. Send: Este comando envia sinais de teclas do teclado para a janela ativa.
  • 5 .Também utilizaremos outra funcionalidades do AutoHotkey: Variáveis embutidas. Essas variáveis já contém dados conhecidos e importantes para você usar sempre que precisar (exemplo: o dia de hoje).
Veja que de alguma forma a lista acima é muito próxima à lista de tarefas que elencamos. Isso porque a divisão em pequenas tarefas foi bem executada, o que nos permitiu tratar o problema complexo como vários probleminhas simples.

3. Escrevendo o script

Para escrever o script, tudo que temos que fazer é escrever as linhas na sequência da ordem de execução (de cima para baixo, a partir da primeira linha) colocando um comando por linha e escrevendo seus parâmetros adequadamente, de modo a cumprir cada tarefa sequencialmente. Por exemplo, para resolver a primeira tarefa (criar um arquivo de texto), vamos primeiramente usar o comando Run para abrir uma janela do Bloco de Notas.

Run, notepad.exe

Pronto, agora já podemos começar a escrever o nosso arquivo. Mas antes de escrever qualquer comando de enviar teclas, precisamos ter em mente que o programa não se abre instantâneamente. Por isso, precisamos programar uma pausa, que deve ser adequada ao tempo necessário para que tenhamos quase certeza de que o programa terminou de abrir.

Sleep, 5000 ; Assinalamos com este comando que queremos uma pausa de 5 segundos antes de continuar a execução do script (o número indicado se refere a milisegundos, por isso escrevermos 5000)

Na linha acima, colocamos comentários dentro do código[/b]. Fazemos isso colocando o ponto-e-vírgula ;. Os comentários são úteis para organizar os códigos. Nada que for escrito após o ponto-e-vírgula em uma linha será executado pelo AutoHotkey (serve apenas como anotação do programador).

Em seguida programamos a ativação da janela que se abriu (se ela não estava ativa ainda por qualquer motivo, irá se ativar agora. Este passo não é totalmente necessário, mas aumenta a confiabilidade do nosso script (pois as vezes, um pop-up de outra janela acaba interferindo aqui).

WinActivate, ahk_class Notepad

No comando acima, veja que utilizamos uma opção de classe de janela para identificar a janela que queremos ativar. Esta opção pode ser encontrada no arquivo de ajuda do comando WinActivate. Ao invés de usar a classe de janela, também é possível usar o nome da janela (que normalmente é Sem título - Bloco de notas). Os parâmetros existem exatamente para que possamos ter várias opções, para que escolhamos a que melhor cabe ao caso.

Agora passamos a escrever os comandos que formatarão o relatório. O primeiro passo é o título do relatório. Como queremos que nosso relatório tenha vários título possíveis, vamos perguntar ao usuário qual titulo colocar em cada execução do script, e vamos utilizar o título que ele indicar escrever no relatório. Para fazer isso, primeiro coletamos o título, o que podemos fazer usando o comando InputBox. Esse comando cria uma caixa onde o usuário pode escrever uma mensagem, e depois salvar a mensagem escrita em uma variável que indicamos (lembre-se, como não sabemos o título antecipadamente, temos de usar uma variável).

InputBox, TITULO_ESCOLHIDO, Escolha de Título, Escreva uma título abaixo para o relatório:

Agora que já coletamos o título e o colocamos dentro da variável TITULO_ESCOLHIDO, podemos usá-lo para escrever no nosso programa. Mas antes, vamos ativar novamente a janela do Bloco de Notas, pois o usuário pode ter clicado em outras janelas antes de escrever o título.

WinActivate, ahk_class Notepad

Agora vamos escrever o comando que vai escrever o título. Este comando é o comando Send.

Send %TITULO_ESCOLHIDO%

Veja que o comanod Send espera um parâmetro do tipo literal. Assim, temos de colocar parêntesis imediatamente antes e depois do nome da variável, de modo a informar ao AutoHotkey que TITULO_ESCOLHIDO não é literalmente o que está escrito, mas sim, uma variável que deve ser transformada no valor que contiver naquele momento. Como fizemos com o que o usuário escrevesse um título e colocamos nessa variável na linha anterior, sabemos que o que estiver lá será na verdade o que o usuário quer que seja o título do relatório.

Ufa! Até aqui já fizemos bastante coisa não :thumbup:
Agora vamos unir os códigos!

Code: Select all

Run, notepad.exe
Sleep, 5000
WinActivate, ahk_class Notepad
InputBox, TITULO_ESCOLHIDO, Escolha de Título, Escreva uma título abaixo para o relatório:
WinActivate, ahk_class Notepad
Send %TITULO_ESCOLHIDO%
Execute o bloco de códigos acima em um script do AutoHotkey e você verá como essa sequência de códigos se traduz em uma ordem racional de comandos que vai construindo aquilo que queremos fazer. É sempre bom ir executando o bloco conforme você vai escrevendo linha a linha, pois se você errar um único comando, vai ficar mais fácil de identificar qual foi. Isso é muito importante no início do aprendizado da linguagem.

bom, mas nosso relatório não é feito apenas de um título!

Conforme a nossa lista de tarefas, ainda precisamos colocar a palavra relatório, as linhas numeradas, a data e o local de assinatura. Faremos tudo isso tudo com sucessivas chamadas ao comando Send, que é o comando que envia os sinais de teclas. O código completo com os send ficaria como este:

Code: Select all

Run, notepad.exe
Sleep, 5000
WinActivate, ahk_class Notepad
InputBox, TITULO_ESCOLHIDO, Escolha de Título, Escreva uma título abaixo para o relatório:
WinActivate, ahk_class Notepad
Send %TITULO_ESCOLHIDO%
Send {Enter}
Send RELATÓRIO
Send {Enter}{Enter}
Send 1. ______________________________________________________{Enter}2. ______________________________________________________{Enter}3. ______________________________________________________{Enter}4. ______________________________________________________{Enter}5. ______________________________________________________{Enter}6. ______________________________________________________{Enter}7. ______________________________________________________{Enter}8. ______________________________________________________{Enter}9. ______________________________________________________{Enter}10. _____________________________________________________{Enter}
Send {Enter}{Enter}
Send %A_DD%/%A_MM%/%A_YYYY%
Send {Enter}___________________________
Send {Enter}ASSINATURA
Fizemos bastante coisa com o comando Send, mas não se preocupe, vamos explicar! :D

Primeiro execute o código para ver o que acontece. Veja que fizemos várias chamadas ao comando. Isso NÃO é necessário, mas ajuda na leitura do script organização. Quando escrevemos {Enter} dentro do parâmetro text do comando Send, fazemos com que o comando Send interprete que queremos que ele envie um enter (logo, criando uma nova linha no Bloco de Notas) e não simplesmente escreva Enter. Esta informação consta na página do arquivo de ajuda do comando Send, ela não foi inventada. Além disso, veja como escrevemos todos as informações respeitando a forma de escrita literal, que é a que esse parâmetro espera. Por isso, todas as variáveis foram escritas entre percentuais. Isso inclui as variáveis A_DD, A_MM, e A_YYYY que são variáveis embutidas do AutoHotkey que contém respectivamente o dia de hoje, o mês de hoje e o ano de hoje. "Hoje" nesse caso, refere-se ao dia da execução do script, e será coletado automaticamente do relógio do Windows no computador. Veja também que a lógica da escrita leva em consideração o que deve ser escrito primeiro e o que deve ser escrito depois. Primeiro vem o título, depois a palavra RELATÓRIO, depois dois sinais de tecla enter, depois as linhas separadas por enter, depois mais dois sinais de tecla enter, depois dia, mês e ano conforme o relógio do windows (obtidos pelas variáveis embutidas e separados por / para organização), e depois um enter, seguido de uma linha menor, seguido da palavra ASSINATURA.

Ufa! quanta coisa hein? Mas não se preocupe, veja que nosso projeto já está quase pronto :dance:

O que falta a seguir é salvar o arquivo. Temos maneiras de fazer isso com o AutoHotkey também, mas como este é um tutorial cujo objetivo é ensinar o passo-a-passo para fazer um script da forma correta, vamos seguir outro caminho agora. Faremos isso porque o script como construímos até aqui funciona, mas poderia ser melhor.

:arrow: Em programação, a otimização dos códigos é muito importante, e é por isso que é constante o trabalho na atualização dos softwares que vemos ao nosso redor. A versão 1.01 funciona, mas a versão 1.02 normalmente vem com melhorias em relação à ela. Então vamos exercitar isso também e já vamos melhorar o nosso código aumentando nosso conhecimento a partir de agora! :thumbup:

4. Melhorando o script

Para iniciar nosso processo de melhoria do código, devemos análisá-lo e, usando o nosso conhecimento, tentar reescrever o código de forma a obter melhores resultados. Olhando pelo código antigo, podemos ver que escolhemos anteriormente uma forma pouco confiável de criar o nosso relatório. Se o usuário tentar operar o computador enquanto o nosso script executa, tudo vai virar uma bagunça. Não é assim que trabalhamos em programação: precisamos que os programas sejam altamente confiáveis. E para fazer isso, o importante é aprender que temos mais de um jeito de fazer alguma coisa, e usar as ferramentas certas é o que vai tornar nosso script melhor em relação a outro que faça a mesma coisa.

Assim, vamos aprender outro comando do AutoHotkey: o FileAppend. Este comando basicamente escreve um arquivo de texto para nós usando simplesmente dados como o endereço onde escrever (tipo c:/meu_arquivo), o nome do arquivo (como Relatório de TITULO_ESCOLHIDO) e ainda o texto que queremos que seja escrito no arquivo. Se usarmos esse comando, toda a escrita do arquivo ocorrerá independente do que o usuário estiver fazendo no computador, e não será interrompida por ela. Além disso, o arquivo já estará salvo quando o comando executar com sucesso.

Viu as vantagens? Se nós aprendermos pelo menos mais um comando ou funcionalidade do AutoHotkey por dia, logo estaremos capazes de fazer scripts de nível altamente profissional! :bravo:

Veja como fica o nosso script usando o FileAppend. Primeiro, vamos coletar do usuário o título do relatório, exatamente como fizemos antes.

InputBox, TITULO_ESCOLHIDO, Escolha de Título, Escreva uma título abaixo para o relatório:

Depois, vamos coletar do usuário o local onde salvar o arquivo. Faremos isso usando o comando FileSelectFile.

FileSelectFile, NOVO_ARQUIVO_RELATORIO, S8,, Salvar Novo Arquivo de Relatório, Arquivos de texto (*.txt)

Depois, podemos criar uma variável com todas as informações que queremos que sejam escritas.

Code: Select all

TEXTO_A_ESCREVER = %TITULO_ESCOLHIDO%`nRELATÓRIO`n`n1. ______________________________________________________`n2. ______________________________________________________`n3. ______________________________________________________`n4. ______________________________________________________`n5. ______________________________________________________`n6. ______________________________________________________`n7. ______________________________________________________`n8. ______________________________________________________`n9. ______________________________________________________`n10. _____________________________________________________`n`n%A_DD%/%A_MM%/%A_YYYY%`n___________________________`nASSINATURA
Veja que no caso da sintaxe de escrita literal em variáveis (usamos =, portanto, indicamos a sintaxe literal), não usamos o {Enter} e sim `n. Estes dois símbolos é o que se traduzem em um enter neste caso. Também colocamos tudo junto, mas poderíamos criar várias variáveis se quiséssemos e depois unir elas.

Finalmente, chamamos o FileAppend para escrever nosso arquivo!

FileAppend, %TEXTO_A_ESCREVER%, %NOVO_ARQUIVO_RELATORIO%.txt

E depois, como nosso novo script opera de forma silenciosa, informamos ao usuário a conclusão da escrita do arquivo. O usuário poderá então encontrar o arquivo de relatório criado na pasta em que escolheu para salvá-lo.

MsgBox, Arquivo escrito com sucesso!

Tudo junto:

Code: Select all

InputBox, TITULO_ESCOLHIDO, Escolha de Título, Escreva uma título abaixo para o relatório:
FileSelectFile, NOVO_ARQUIVO_RELATORIO, S8,, Salvar Novo Arquivo de Relatório, Arquivos de texto (*.txt)
TEXTO_A_ESCREVER = %TITULO_ESCOLHIDO%`nRELATÓRIO`n`n1. ______________________________________________________`n2. ______________________________________________________`n3. ______________________________________________________`n4. ______________________________________________________`n5. ______________________________________________________`n6. ______________________________________________________`n7. ______________________________________________________`n8. ______________________________________________________`n9. ______________________________________________________`n10. _____________________________________________________`n`n%A_DD%/%A_MM%/%A_YYYY%`n___________________________`nASSINATURA
FileAppend, %TEXTO_A_ESCREVER%, %NOVO_ARQUIVO_RELATORIO%.txt
MsgBox, Arquivo escrito com sucesso!
Execute o código acima, escolha para salvar o arquivo na sua área de trabalho e depois veja o arquivo ser criado. Percebeu que tudo ocorreu de forma silenciosa e rápida, sem possibilidade de o usuário interromper a escrita sem querer? :dance:

Isto conclui nosso terceiro tutorial dessa série. Lembro que o objetivo é que estudemos a linguagem passo a passo, de forma mais aprofundada e explicada, por isso, vamos aprendendo novos comandos e ferramentas a cada momento, com o objetivo de aumentar nossa capacidade de criar scripts. Você viu que usamos variáveis embutidas neste tutorial? Elas são muito úteis e você pode encontrar uma lista das variáveis embutidas disponíveis aqui neste link.

Fiquem todos na paz e um forte abraço. Até o próximo tutorial :wave:

Gio.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Básico de variáveis, expressões e comandos em AutoHotkey

Post by Gio » 03 Apr 2018, 18:55

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 03 Apr 2018, 18:57

IV. Tutorial Básico de Condicionais de Execução e Blocos de Códigos

Olá :thumbup:

Se você chegou até este quarto tutorial desta série, parabéns! saiba que você já viu e aprendeu bastante coisa sobre programação e sobre o AutoHotkey. Mas como dissemos anteriormente, não podemos nos esquecer que programação é um aprendizado contínuo, e se a cada dia agregarmos mais e mais conhecimento, a cada dia nos tornaremos melhores programadores.

Assim, neste quarto tutorial de nossa série, vamos nos ater às expressões condicionais e aos blocos de código. Você sabe o que eles são e para que servem?

1. Nem sempre devemos executar todo o código do script

Como vimos anteriormente, o AutoHotkey executa as linhas do nosso script uma a uma, da primeira até a última. Mas será que sempre vamos querer que isso ocorra? Vamos supor que você deseja escrever um programa, mas quer que esse programa só possa ser usado por uma determinada pessoa. Isso significa basicamente que queremos de alguma forma criar uma condição para executar esse programa, ou seja, uma parte do código só deve executar se o usuário for mesmo aquela pessoa. Afinal, não queremos que o programa abra todas as janelas e execute todo o código se ele tiver sido executado por um terceiro!

Como faremos isso?

Ora, a melhor maneira de garantir que o usuário que executou o script seja uma determinada pessoa é através de uma chave e/ou senha. Se você seguiu os tutoriais anteriores, deve ter percebido que já aprendemos a coletar informações do usuário através do comando InputBox. Então, o primeiro passo para implementar uma rotina de senha é coletar a senha do usuário. Mas e depois? Como fazemos para verificar se a senha coletada é a senha correta?

Para fazer isso, vamos criar uma expressão condicional. As expressões condicionais são expressões lógicas que se resolvem para um valor de Verdadeiro ou Falso. Se a condição que escrevemos nela for atendida pelos dados inseridos, ela vai retornar um Verdadeiro, e se não for, vai retornar um Falso.
No caso do AutoHotkey, podemos agregar blocos de códigos à expressões condicionais, de forma que estes só executem se aquela condicional resultar em verdadeiro.

E o que são esses blocos de códigos? São códigos escrito entre duas linhas de chaves, sendo uma abrindo { e a outra fechando }, de modo que o código fique separado, como se estivesse dentro dessas chaves. Esses blocos de códigos servem para, entre outras coisas, dizer quais comandos queremos (ou não queremos) que sejam executados em determinada situação.

Assim, os blocos normalmente se encontram ligados à uma expressão condicional ou a alguma outra funcionalidade que comanda a sua execução.

2. Escrevendo condicionais

A forma mais básica de escrevermos condicionais é utilizar a sintaxe If (Expression). If em inglês significa se, então podemos ler essa sintaxe como se esta expressão for verdadeira então execute...

Uma expressão desse tipo normalmente usa um operador lógico-matemático, que pode ser:
  • igual-a: =
  • maior-que: >
  • menor-que: <
  • maior-ou-igual-a: >=
  • menor-ou-igual-a <=
:arrow: É importante lembrar que não existe igual-ou-maior-que e nem igual-ou-menor-que, uma vez que estes são equivalentes para todos os efeitos aos dois últimos da lista acima (que existem!).

Assim, vamos ver como escrevemos uma expressão condicional usando tudo isto!

Code: Select all

Var := 150
If (Var = 149)
{
	msgbox, O valor da variável é 149!
}
O que fizemos no código acima foi o seguinte: Colocamos o valor 150 em uma variável. Depois, criamos uma expressão condicional que diz se o valor de Var for igual a 149 então.... E aí colocamos uma bloco de códigos logo após essa condicional contendo um MsgBox que diz "O valor da variável é 149!".

Ora, se você observou bem o que dissemos até aqui, já deve ter sacado que o bloco de códigos acima NÃO VAI EXECUTAR. Isso significa que essa MsgBox nunca vai aparecer se executarmos esse script. Podemos entender isso se pensarmos que a nossa condicional, após trabalhar o valor contido na variável, vai simplesmente dizer "Se 150 for igual a 149 então..." e isso é simplesmente falso. Uma forma de fazer com que essa condicional executasse seria trocar o valor da variável para 149, ou então, usamos o operador menor-que < ou o operador menor-ou-igual-a <=.

:arrow: Com as expressões condicionais, impomos condições para executar os blocos de códigos à elas atrelados, e essas condições são apresentadas através de expressões matemáticas com operadores lógicos (>, <, =, <=, >=).

É importante lembrar ainda que expressões condicionais usando esta sintaxe são expressões matemáticas para todos os efeitos, o que significa que podemos adicionar, subtrair, multiplicar, recuperar valores de variáves e somente o resultado final será comparado com os operadores lógicos.

Code: Select all

If (10 + 8 = 9 + 9)
{
	msgbox, Os resultados são equivalentes !
}
Veja que o código acima executa a MsgBox. Isso ocorreu porque 10 + 8 será trabalhado em 18, assim como 9 + 9 será trabalho em 18 antes que o operador lógico compare os lados da expressão. Neste caso, como os dois lados resultam no mesmo valor, que é 18, a condicional resulta em Verdadeiro, e o bloco de códigos a ela associado executa normalmente.

:arrow: Os operadores lógico-matemáticos possuem uma baixa ordem de precedência, o que significa que em uma mesma expressão, os operadores comuns serão avaliados primeiro, e somente depois será avaliada a expressão lógica. É isto que nos permite dizer que na condicional acima, a igualdade será avaliada depois da soma 9 + 9 (mesmo que esta esteja à direita daquela). A ordem de precedência dos operadores existe para que saibamos como uma expressão será avaliada e possamos programá-la tendo isso em mente. Se você se lembra das aulas de matemática, sabe que a multiplicação ocorre antes da soma, e o mesmo acontece com as expressões no AutoHotkey.

3. Resolvendo o problema da senha

Agora que já cobrimos a forma como a condicional If (Expression) trabalha, vamos usá-la para resolver o problema da senha, que apresentamos no início do tutorial.

Já vimos que para obter um valor do usuário, usaremos o comando InputBox. Então o que demos fazer a seguir?

Simples! Vamos criar uma condicional que compare o valor que o usuário inseriu (e que foi colocado na variável escolhida) para sabermos se ele é igual a uma senha qualquer que vamos criar. O script ficará conforme abaixo.

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa de texto executou porque você inseriu a senha certa!
}
Execute o código acima algumas vezes. Ele pede uma senha. Se você digitar abacaxi, uma caixa de texto será exibida. Mas se você digitar outra coisa, o script simplesmente termina a execução. Tudo isso é feito graça à condicional de execução que criamos.

4. Aprofundando um pouco mais a lógica das condicionais

Acredito que neste ponto já deve ter ficado mais claro a forma como utilizamos as expressões condicionais. Mas veja o código abaixo. Temos duas caixas de texto. Você sabe dizer quais executam de acordo com a condicional?

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa de texto executou porque você inseriu a senha certa!
}
MsgBox, Esta caixa executará independente do que aconteceu acima.
Somente o código que estiver dentro do bloco de códigos (ou seja, entre { e }) vai estar atrelado àquela condicional. Assim, a segunda MsgBox vai executar não importa se o usuário escreveu a senha certa ou não!

Podemos resolver isso colocando a segunda MsgBox dentro do bloco.

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa de texto executou porque você inseriu a senha certa!
	MsgBox, Agora sim esta caixa também será dependente do resultado da condicional.
}
Mas também podemos resolver de outras formas. Uma delas é simplesmente criar uma interrupção do script e colocá-la dentro do bloco de códigos. Assim, se o bloco for executado (ou seja, se a senha estiver errada), o script terminará e não executará o que estiver abaixo. Faremos isso usando o comando ExitApp, que termina o script em qualquer lugar que queiramos.

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa de texto executou porque você inseriu a senha certa!
	ExitApp
}
MsgBox, Pela lógica do script, se o bloco acima executou, este código nunca chegará a executar, pois o script terminou assim que o ExitApp foi executado.
E há ainda outras formas de trabalharmos as condicionais aqui. Pelo caso acima, o nosso bloco executa se a senha inserida for Abacaxi. E como faríamos para fazer ele executar se a senha inserida NÃO for abacaxi?

Para isso podemos usar o operador ! (ou NOT), que basicamente significa que estamos perguntando com a nossa condicional se o resultado é Falso ao invés de perguntar se é verdadeiro. Podemos colocar o operador ! (ou NOT) junto ao operador lógico igual ou então junto à expressão inteira:

Junto ao operador lógico (criando uma espécie de novo operador não-é-igual-a):

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada != "Abacaxi")
{
	MsgBox, Esta caixa só aparece se você digitar a senha errada!
}
Ou Junto à expressão inteira (ou seja, executando o bloco somente se a expressão avaliar para falso):

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If !(Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa só aparece se você digitar a senha errada!
}
:arrow: IMPORTANTE: Embora neste caso negar a igualdade seja o mesmo que negar a expressão inteira, nem sempre funciona assim. Se tivermos mais de uma condicional dentro da expressão (vamos ver isso adiante), negar a expressão inteira pode ter outro resultado!

Outra possibilidade ainda de trabalharmos com a negativa das condições impostas é usarmos a expressão condicional Else. Else em inglês signfica "De outra forma", e basicamente é uma nova expressão condicional atrelada a uma primeira que opera caso a primeira não tenha executado. Assim, podemos escrever o seguinte código se desejarmos apresentar duas caixas (uma para quando a senha está correta, e outra para quando não está):

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Esta caixa de texto executou porque você inseriu a senha certa!
}
Else
{
	MsgBox, Já esta caixa de texto executou porque você inseriu a senha errada!
}
Veja que no código acima, somente uma caixa será exibida em cada execução do script, pois o Else requer que o If não tenha executado. A vantagem do Else é que os dois casos possíveis (Verdadeiro ou Falso) são levado a blocos de códigos específico, ao invés de apenas um levar a um bloco e o outro levar a linha soltas.

:arrow: Um comando Else sempre se conecta ao If mais próximo acima dele.

Uma variante do comando Else sozinho é o comando Else If (Expression). Este comando forma uma segunda possibilidade, de modo que podemos ter uma segunda senha, por exemplo. Se a primeira condicional não executar, a segunda pode executar (ou não) baseado em uma nova condição. Desta forma, não se trata de uma negativa da primeira por si só, mas de uma segunda condição. Podemos usar o Else If (Expression) para impor quantas condições mais queiramos, e ainda podemos usar um Else no final para verificar se nenhuma dessas condições foi atendida.

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If (Senha_Digitada = "Abacaxi")
{
	MsgBox, Abacaxi é amarelo dentro!
}
Else If (Senha_Digitada = "Goiaba")
{
	MsgBox, Goiaba é um fruto saboroso!
}
Else If (Senha_Digitada = "Laranja")
{
	MsgBox, Laranja faz um suco muito bom!
}
Else
{
	MsgBox, Não sei o que você escreveu, mas não foi Abacaxi, nem Goiaba e nem Laranja!.
}
Execute algumas vezes o código acima e estude-o. Você pode testar escrever Abacaxi, Goiaba, Laranja ou outra coisa qualquer e em cada uma dessas quatro situações, a caixa de texto será diferente!

5. Entendendo as Condicionais Compostas

Agora que já entendemos um pouco mais acerca das condicionais básicas e da negação das mesmas, vamos nos ater a outra possibilidade em relação às condionais: Condicionais Compostas.

Pode ser que dentro de uma condiciona If (Expression) queiramos impor mais uma condição. E pode ser ainda que essas condições precisem ser ambas atendidas, ou somente uma atendida. Podemos fazer isso com If (Expression), Else If (Expression) e Else, mas podemos também fazer somente com If (Expression). Isso pode ser feito usando os operadores & (ou AND) e || (ou OR). O primeiro significa e e o segundo significa ou. Assim, veja o código abaixo.

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If ((Senha_Digitada = "Abacaxi") OR (Senha_Digitada = "Goiaba"))
{
	MsgBox, Você escreveu Abacaxi ou Goiaba!
}
Perceba que como usamos o operador OR (que poderia se escrito como ||), a condicional externa agora entende que seu valor pode ser Verdadeiro se qualquer das duas condicionais internas forem verdadeiras. (Coloquei as duas condicionais internas entre parênteses internos, você percebeu?)

E o que acontece se tentar agora substituir no código acima o OR por AND?

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If ((Senha_Digitada = "Abacaxi") AND (Senha_Digitada = "Goiaba"))
{
	MsgBox, Você escreveu Abacaxi e Goiaba!
}
O código acima nunca poderá apresentar a MsgBox!

Isto ocorre porque o valor inserido não tem como ser somente "Abacaxi" e somente "Goiaba" ao mesmo tempo.

Mas veja que há situações onde duas condicionais podem ser verdadeiras ao mesmo tempo. O código abaixo executa a caixa de texto se o usuário inseriu a senha abacaxi e se o dia de hoje (do mês) for diferente de 01 (Usamos A_DD aqui, que é uma variável embutida. Você lembra dela? usamos ela no tutorial III).

Code: Select all

InputBox, Senha_Digitada, Senha, Digite a senha correta abaixo:
If ((Senha_Digitada = "Abacaxi") AND !(A_DD = "01"))
{
	MsgBox, Você escreveu Abacaxi e hoje não é o primeiro dia do mês!
}
:arrow: Você pode alterar o código acima para verificar outros dias do mês ou outras condições. Teste sempre as alterações e veja o que funciona e o que não funciona em cada caso. Se tiver dúvidas, não se esqueça que pode perguntar abaixo ou no fórum Eu Preciso de Ajuda! :thumbup:

:arrow: Podemos escrever uma condicional maior com quantas condicionais menores quisermos usanso AND e OR, mas é importante ter em mente que condicionais muito longas costumam dificultar nossa compreensão da lógica de execução. Prefira sempre deixar o seu código o mais simples possível e use as outras ferramentas diponíveis (Como o Else If (Expression) e o Else) para que tudo fique mais fácil de ler.


6. Comandos condicionais e outras condicionais em AutoHotkey

Além do If (Expression), o AutoHotkey possui alguns comandos condicionais e outras funcionalidade que operam condicionais de modo a facilitar a vida do programador. De uma maneira geral, todos possuem a palavra If seguida de outra palavra que indique o que será testado pela condicional. Um exemplo é o comando IfWinActive. Este comando verifica se (If) uma janela (Win) está ativa (Active). O código abaixo, por exemplo, só exibe uma caixa de texto se após 10 segundos do início da execução, for detectado que uma janela do Bloco de Notas estiver ativa (uma janela ativa é um janela que além de estar aberta no computador está também na frente das outras, sendo usada pelo usuário naquele momento).

Code: Select all

Sleep 10000
IfWinActive, ahk_class Notepad
{
	MsgBox, Uma janela do Bloco de Notas está ativa!
}
Como este tutorial já está longo, não entraremos em detalhes sobre todos os comandos If. Se você desejar, não esqueça que pode procurar no índice de comandos do AutoHotkey por outros comandos que contenham If em seu nome se você quiser conhecer os outros comandos que implementam condicionais no AutoHotkey.


7. Ternário (operador de condicional dentro de expressões)

Como um adendo neste tutorial cabe destacar que é possível executar condicionais dentro de expressões matemáticas. Para isso, usamos o ternário ?:. Este operador normalmente dificulta bastante a leitura do script, mas tem a vantagem de reduzir a quantidade de caracteres escritos. Não recomendo seu uso para iniciantes do AutoHotkey (prefira escrever o If (Expression) e o Else), e mesmo aos usuários avançados, somente recomendaria se a vantagem de reduzir o tamanho do código for de grande valor. A forma de escrita do operador é conforme abaixo (lembrando que só pode ser usado dentro de expressões!)

Code: Select all

Alguma_Variavel := ((3 = 3) ? (Var := "sim") : (var := "não"))
msgbox % var
O código acima faz o seguinte. Implementei a expressão de inserir valores de forma matemática na variável Alguma_Variavel somente para pode escrever o ternário, pois este necessita estar dentro de uma expressão matemática. Depois, escrevi o ternário que diz o seguinte: Se 3 for igual a 3, então Var terá o valor sim inserido nela, mas do contrário (ou seja, se 3 não for igual a 3), o valor inserido será não.

Veja que com o ternário, tudo foi escrito em uma linha só, que contém tanto uma forma de If quanto uma forma de Else. A sintaxe do ternário é esta:

(Condicional) ? (Expressão a executar se Verdadeiro) : (Expressão a executar se Falso)

:arrow: É costume colocar o ternário dentro de um novo nível de parêntesis para facilitar um pouco a leitura do mesmo. Portanto, o ternário vazio costuma ficar assim (() ? () : ()) e depois são adicionados os componentes das expressões em cada parêntesis interno.

É também comum, já que o ternário tem que estar dentro de uma expressão matemática, encontrar linhas de ternários que iniciam simplesmente com um forçar de expressão.

% () ? () : ()

8. Considerações Finais

E assim chegamos ao fim deste tutorial. Espero que tenham gostado, pois aprendemos muita coisa nele :thumbup:

Com os conhecimentos adquiridos nestes quatro tutoriais iniciais, saiba que você já é capaz de escrever vários programas em AutoHotkey. Para fazer isso, basta observar a sempre a ordem de execução dos comandos e as condicionais escritas, bem como o que cada comando faz (pois cada um é um pequeno passo da execução do programa).

:arrow: É importante destacar que é possível escrever condicionais sem blocos de execução, mas não recomendo isso. Se você escrever uma condicional sem um bloco de execução, a condicional vai operar somente sobre a linha subsequente do script. Isto pode diminuir o número de linhas escritas, mas diminui também a organização e facilidade de leitura do script. Quanto mais legível for o seu script, melhor será para você trabalhar com ele e mais fácil será para os outros lhe ajudarem a resolver algum problema que venha a surgir. Você percebeu que dentro dos blocos de códigos, escrevi os comandos dando alguns espaços antes do nome deles? Isto se chama indentação e facilita muito a leitura do script. Se o script tiver mais de um nível de blocos de execução (e scripts complexos normalmente tem), esta forma de organização das linhas ajudará muito na leitura do mesmo.

Fiquem todos na paz e sigamos em frente com a aprendizagem da programação! :thumbup:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 09 Apr 2018, 11:15

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 16 Apr 2018, 12:11

V. Tutorial Básico de Funções e Labels

Olá :angel:

Neste quinto tutorial, vamos investigar o conceito de função, e como as funções são implementadas no AutoHotkey para permitir ao programador escrever seus programas de forma mais fácil.

Vamos lá? :thumbup:

1. Função: o que é isso?

Quando falamos de função, estamos falando de um conceito matemático que foi adotado pelas linguagens de programação. Uma função é essencialmente uma fórmula matemática que pode realizar um mesmo trabalho conhecido por nós em diferentes valores que podemos inserir como parâmetros de um comando.

Um exemplo matemático de função é este: f(x) = 2x + 5

A função possui dois momentos distintos: Um no qual definimos ela (ou seja, criamos o seu corpo, escrevendo o trabalho que será feito), como por exemplo o f(x) = 2x + 5 e um segundo momento onde chamamos a função definindo valores para os seus parâmetros (que é onde pedimos que ela realize o trabalho que está programada para realizar), como por exemplo f(4), cujo resultado seria 13 (afinal, 2 x 4 + 5 = 13).

:arrow: No AutoHotkey, o conceito é bem parecido, mas a sintaxe do corpo de uma função é um pouco diferente da sintaxe matemática, e pode ser vista abaixo:

Code: Select all

NomeDaFuncao(NomeDoParametro1, NomeDoParametro2)
{
    ; Aqui vão as linhas que trabalham os Parametros da função. São linhas de códigos normais, que podem ser comandos, outras funções e etc. Os parâmetros podem ser referidos nestas linhas como variáveis com os nome que colocamos acima.
    Return ExpressãoMatemática ; Aqui vai uma expressão matemática que trará a resposta da função, ou seja, o resultado final da chamada.
}
O exemplo mais básico de função em AutoHotkey talvez seja uma função de soma, que na linguagem do AutoHotkey, pode ter sua definição escrita assim:

Code: Select all

Soma(Numero1, Numero2)
{
	Return Numero1 + Numero2
}
O código acima é o que chamamos uma definição de função (ou o corpo da função). Veja que Numero1 e Numero2 são duas variáveis, que definimos como sendo os parâmetros da nossa função. Isso significa basicamente que a função Soma é capaz de somar quaisquer dois números que lhe apresentemos. O corpo de uma função é normalmente colocado na parte de baixo do script, sempre depois do primeiro comando Return do script (o comando Return é o que limita uma seção de código, criando uma pausa ou retornando a ordem de execução das linhas do script para outra linha). A sintaxe do corpo da função pode ser descrita textualmente assim:

Primeiro vem o Nome da função (que segue as mesmas regras de nomenclatura de variáveis, ou seja, nada de espaços, e quase nenhum símbolo ou acento), seguido de parêntesis (onde se inserem os parâmetros que a função terá, separados por vírgula e escritos na ordem em que a função será chamada), seguido de um bloco de códigos com as linhas de códigos que executaremos quando esta função for chamada.

Opcionalmente, neste bloco de códigos, teremos uma linha que se inicia com o comando Return. O comando Return quando dentro de uma função tem um segundo propósito além de delimitar o fim do corpo da função: Ele pode conter em seguida uma expressão cujo resultado será a resposta da função quando a chamarmos.

Assim, um exemplo de script completo com uma definição de função e três chamamentos distintos a ela pode ser visualizado abaixo.

Code: Select all

Msgbox % Soma(3,9)
Msgbox % Soma(4, 13)
Msgbox % Soma(41, 18)
Return

Soma(Numero1, Numero2)
{
	Return Numero1 + Numero2
}
Execute o código acima e veja o que acontece. Você viu que as MsgBox apresentaram o resultado da soma dos números que colocamos entre parêntesis? Isso ocorreu porquê a chamada à função retornou a soma dos números, graças a linha Return Numero1 + Numero2 no corpo da função.

:arrow: Importante ! O corpo da função deve sempre ser escrito em uma linha ABAIXO da linha de chamamento da função. Inverter esta ordem trará um erro ao executar o script. Também é muito importante que o corpo da função seja colocado depois de um comando Return do script, de modo que fique em uma seção de execução separada.

O chamamento de uma função faz com que a ordem de execução das linhas do script se altere: ela pula da linha de chamada para o corpo da função, executando-o com os parâmetros informados na chamada. Depois que todas as linhas do corpo da função são executadas (ou a execução encontra alguma linha de comando return), a ordem de execução pula de volta para a linha subsequente à linha da chamada e continua dali. Por isso é importante colocar o corpo das funções em separado (abaixo) do restante do script.

2. Funções: para que servem?

Se você entendeu o que fizemos no item 1, talvez esteja se perguntando: mas porquê não somar os números direto nas linhas de MsgBox? Bom, temos algumas razões para isso. A primeira razão é que este foi um exemplo básico. Normalmente, as função executam trabalhos que precisam de várias linhas de códigos. Com uma função, você pode escrever essas linhas apenas uma vez e fazer com que o conjunto delas seja chamado integralmente em cada chamada da função (cada chamada só toma 1 linha). Dessa forma, a função implementa o que chamamos de reutilização do código, e ajuda a organizar e desenvolver o script. Além disso, a função tem um nome que, via de convenção, é uma dica para o que aquela função faz. Isso permite, entre outras coisas, que um trabalho complexo (criar um Excel) seja dividido em trabalhos menores, mesmo que ainda sejam grandes demais para uma única linha de código (como CriarATelaDoprograma(), ou ainda AtualizarAsFormulasInseridas(), que são tarefas com várias linhas cada). Também vale a pena destacar que a facilidade de reutilização do código atribuída às funções permite que as funções sejam compartilhadas entre scripts e até mesmo entre desenvolvedores.

:arrow: Você sabia que os fórums do AutoHotkey têm uma sala com milhares de funções escritas por usuários, e que essas funções podem ser usadas por você para criar programas complexos de forma rápida e organizada? Esta sala pode ser conferida assim que você terminar este tutorial neste link. Também temos uma sala para funções desenvolvidas por usuários falantes de português, e embora tenha menos opções no momento, você poderá conferi-la neste outro link e até mesmo criar tópicos lá para compartilhar suas próprias funções conosco!

Vejamos um exemplo de função que utilizo regularmente para organizar meus códigos, reutilizá-los e ainda reduzir o número de linhas do script. Suponha que eu tenha um campo para o usuário digitar um número. Quero multiplicas este número por 30. No entanto, sei que como as convenções de escrita são diferentes aqui e nos Estados Unidos, este número pode acabar sendo escrito separado por vírgula, separado por ponto, pode ter ponto entre as unidades de milhares, ou ainda não ter ponto nenhum. O AutoHotkey trabalha com número no formato: sem pontos de milhares e com pontos nos decimais.

:arrow: Como fazer para deixar o AutoHotkey somar dois números que podem ter sido escrito tanto no formato americano quanto no formato brasileiro?

O código abaixo simplesmente não funciona!

Code: Select all

MsgBox % 1.035,37 + 4002.32 ; Esta linha de soma NÃO FUNCIONA pois os números estão em desacordo com o formato adotado pelo AutoHotkey para números e decimais !
Mas não se preocupe. Para somarmos estes dois números só temos que primeiro trabalhá-los para o formato adequado, e faremos isso usando uma função!

Code: Select all

Numero1 := "1.035,37"
Numero2 := "4002.32"
Msgbox % TrabalharFormato(Numero1) + TrabalharFormato(Numero2)
Return

TrabalharFormato(ByRef Valor, Casas = 2) 
{
   stringreplace Valor, Valor, %A_Space%
   stringgetpos commapos, Valor, `,
   stringgetpos dotpos, Valor, .
   if (dotpos > commapos and dotpos > 0 and commapos > 0)
   {
      stringreplace Valor, Valor, `,
   }
   if Valor is not number
   {
      stringreplace Valor, Valor, .
      stringreplace Valor, Valor, `,,.
   }
   Valor := Round(Valor, Casas)
   return Valor
}
Você percebeu que usamos aspas entre os valores? Isso ocorreu porque já que o AutoHotkey não os reconhece como números válidos ainda, tenho que tratá-los como texto. Já o resultado da função está no formato adequado e portanto pode ser somado diretamente. Esta função pode ser utilizada com várias situações que envolvam possíveis modelos de números brasileiros ou americanos e é muito útil. Se você precisar, pode copiá-la para usar em algum script seu.

O exemplo abaixo usa extensivamente a função acima e nele você poderá ver como usando a função estamos basicamente reutilizando as linhas de código escritas na função, de modo que não precisamos ficar copiando e colando as muitas linhas de comandos StringReplace e StringGetPos, pois apenas a chamada da função é repetida com os valores diferentes.

Code: Select all

MsgBox % TrabalharFormato("1.038,45") + TrabalharFormato("1.32")
MsgBox % TrabalharFormato("405.17") + TrabalharFormato("405,32")
MsgBox % TrabalharFormato("1,009.4") + TrabalharFormato("2.8")
MsgBox % TrabalharFormato("9.3") + TrabalharFormato("10,4")
MsgBox % TrabalharFormato("1,000") + TrabalharFormato("5.7")
MsgBox % TrabalharFormato("8,99") + TrabalharFormato("0.01")
MsgBox % TrabalharFormato("100") + TrabalharFormato("16,17")
Return

TrabalharFormato(ByRef Valor, Casas = 2) 
{
   stringreplace Valor, Valor, %A_Space%
   stringgetpos commapos, Valor, `,
   stringgetpos dotpos, Valor, .
   if (dotpos > commapos and dotpos > 0 and commapos > 0)
   {
      stringreplace Valor, Valor, `,
   }
   if Valor is not number
   {
      stringreplace Valor, Valor, .
      stringreplace Valor, Valor, `,,.
   }
   Valor := Round(Valor, Casas)
   return Valor
}
3. Funções embutidas no AutoHotkey

O conceito de função é tão útil que alguns "comandos" do AutoHotkey são escritos em forma de funções, que podem ser chamadas sem que escrevamos nós mesmos o corpo delas. É o que chamamos de funções embutidas. Algumas das vantagens dessas funções em relação aos comandos normais são as seguintes:
  • 1. Todos os parâmetros das funções são escritos em sintaxe de expressão matemática, assim não é preciso testar ou supor se o parâmetro espera outro tipo de escrita;
  • 2. As funções podem ser escritas dentro de expressões matemáticas, enquanto que os comandos tem que ser escritos em linhas próprias;
  • 3. As funções permitem chamadas dinâmicas, de modo que podem ser usadas, por exemplo, para obfuscar um script ou para criar uma única linha que chama funções diferentes baseando-se em alguma condicional de execução
Por este motivo, os desenvolvedores do AutoHotkey estão adicionando funções equivalentes à maioria dos comandos, e espera-se que a partir da versão 2.0 do AutoHotkey, a sintaxe dos comandos normais seja integralmente substituída pela sintaxe de funções.

:arrow: Você percebeu que a página de lista de comandos do arquivo de ajuda contém vários comandos terminados em parêntesis? Isso significa que estes comandos estão implementados na forma de funções.

Para exemplificar este item, vamos utilizar agora uma função embutida do AutoHotkey chamada SubStr(). Esta função permite que retiremos um pedaço de uma frase, determinando simplesmente a posição e o número de caracteres que vamos tirar de lá. Suponhamos que eu tenha por exemplo a frase "João comeu uma maçã verde que quase não cabia em sua mão". Esta frase é bastante longa. Se eu quisesse exibí-la em uma tela, poderia ter problemas. Talvez seja melhor cortá-la, exibindo apenas os primeiros 20 caracteres. Farei isso usando o comando Substr().

Code: Select all

Var1 := "João comeu uma maçã verde que quase não cabia em sua mão"
MsgBox % SubStr(Var1, 1, 20)
Este tipo de ação pode parecer simples, mas é muito útil quando não sabemos os valores que estarão na variável, mas sabemos que só podemos (ou só queremos) trabalhar com uma parte deles.

4. Variáveis Locais, Globais e Super-Globais

Quando estamos programando funções em AutoHotkey, é importante entendermos que as variáveis dentro de funções são do tipo local por padrão. Isso significa que, via de regra, as funções não "enxergam" variáveis que estejam fora do seu corpo (ou seja, fora do bloco que contém a definição da função). Como exeplo, imagine que, por padrão, ainda que uma variável possua um valor definido na primeira linha do script, ela vai estar vazia dentro do corpo da função. Veja o código abaixo:

Code: Select all

Var1 := "Abacaxi"
Funcao()
Return

Funcao()
{
    MsgBox % "Eu gosto de " Var1
}
Se você executar o código acima, verá que a palavra abacaxi NÃO aparece na MsgBox. Isso ocorre porque dentro de uma função todas as variáveis são locais a princípio. Em outras palavras, se eu quisesse usar a variável Var1 nessa função, eu teria que criar um parâmetro e passá-la através dele, ou então definir novamente o seu valor dentro da própria função. O problema da primeira opção é que se estivermos trabalhando com muitas variáveis, vamos terminar com muitos parâmetros na função e o problema da segunda opção é que as duas variáveis seriam para todos os efeitos distintas, o que significa que uma alteração posterior em Var1 fora da função NÃO atualizaria o Var1 dentro da função.

Para resolver esse problema, podemos definir que as variáveis sejam globais ou super gobais.

Variáveis Globais são enxergadas dentro e fora de uma função. Para definir que uma variável é global, basta escrever o nome global seguido de espaço antes do nome da variável, logo no início do corpo da função.

Code: Select all

Var1 := "Abacaxi"
Funcao()
Return

Funcao()
{
    Global Var1
    MsgBox % "Eu gosto de " Var1
}
Pronto! agora o código acima mostra a palavra abacaxi, e além disso, se a variável for alterada fora da função, também será alterada dentro da função.

Além disso, podemos definir que todas as variáveis de uma função sejam globais. Para fazer isso, basta escrever a palavra Global sozinha na primeira linha do corpo da função.

Code: Select all

Var1 := "Abacaxi"
Funcao()
Return

Funcao()
{
    Global
    MsgBox % "Eu gosto de " Var1
}
No código acima, não precisei dizer que Var1 era global, pois como defini que todas as variáveis fossem globais nesta função, Var1 está automaticamente conectada com a Var1 externa, visto que é também global agora (como qualquer outra variável que existisse no script).

Outra opção que temos é criar variáveis super-globais. Este tipo de variável é uma variável externa que é acessível a todas as funções do script, independente de se declará-la global em cada função. É obtida declarando uma variável como global fora de qualquer corpo de função e logo no início do script.

Code: Select all

Global Var1
Var1 := "Abacaxi"
Funcao()
Return

Funcao()
{
    MsgBox % "Eu gosto de " Var1
}
:arrow: A razão das variáveis serem locais por padrão nas funções é que estas têm o propósito de serem reutilizadas em vários scripts, uma vez que executam trabalhos pré-definidos e indicados pelos seus nomes. Assim, um programador que cole uma função em seu script não precisa se preocupar em ter problemas com variáveis do seu programa sendo atualizadas pela função. Por falar nisso, você já começou a planejar como vai montar sua biblioteca de funções depois deste tutorial? :thumbup:

5. Outras possibilidades das funções em AutoHotkey

As funções em AutoHotkey possuem algumas opções que podem nos ajudar a escrever o código. A primeira é que os parâmetros das funções podem ser escritos com valores padrão. Isso significa que se o usuário quiser, pode mudar esses valores, mas se não quiser fazê-lo, ainda assim a função executará usando o valor padrão. Você percebeu que a função TrabalharFormato() que usei no item 2 possuía dois parâmetros, mas nós chamados elas várias vezes fornecendo apenas 1? Isso foi possível porque no corpo da função definimos que o parâmetro2 teria um valor padrão igual a 2.

Outra opção que utilizei na função TrabalharFormato() foi a opção ByRef no primeiro parâmetro. Esta opção permite que passemos à função o nome de uma variável (ao invés de passar os valores dela). Isto permite que a função trabalhe com aquela variável diretamente (pois do contrário, como os parâmetro tem sintaxe de expressão matemática, as variáveis seriam automaticamente resolvidas para os seus valores).

6. Labels

Assim como as funções, o AutoHotkey também implementa o conceito de labels (cuja tradução seria "rótulos"). As labels são porções de códigos que podem ser chamadas a qualquer momento e implementam uma versão mais baixo nível de reutilização do código que as funções. As labels podem ser utilizadas para organização do script e também são utilizadas na criação de controles de telas no AutoHotkey (botões, etc).

Para definir uma label basta escrever seu nome, sem espaços, seguido de dois pontos. Uma label promove um novo início da ordem de execução, de modo que uma vez chamada, a ordem de execução "pula" para a primeira linha da label e continua dali em diante. Se a ordem de execução encontrar uma linha com o comando Return, no entanto, a ordem de execução pulará de volta à linha subsequente ao chamamento da label e continuará dali em diante (exceto se a chamada ocorreu através de Goto, o que não se recomenda mais fazer).

Veja no script abaixo o funcionamento de uma label:

Code: Select all

msgbox % "Linha 1 fora da label"
msgbox % "linha 2 fora da label"
Gosub LabelABC ; Nesta linha 3 fora da label, chamamos a label.
msgbox % "Linha 4 fora da label"
msgbox % "Linha 5 fora da label"
Return


LabelABC:
msgbox % "Linha 1 da label"
msgbox % "Linha 2 da label"
Return
Veja que na linha 3, chamamos a label LabelABC através do comando Gosub. Por este motivo, a ordem de execução pula para a primeira linha da label e continua ali, até encontrar o Return. Quando isso acontece, a ordem de execução então pula novamente para a seção externa da label, voltando para a primeira linha subsequente ao chamamento da label. Você pode conferir isso executando o código acima e prestando atenção na ordem de exibição das MsgBox.

:arrow: O comando return também serve para delimitar o final da chamada "seção de auto-execução" do script. Esta seção é o que chamamos de "fora da label" no código acima. Ela é a seção normal do script, e se inicia na primeira linha do script. Quando colocamos um return, estamos definindo um fim para a nossa seção atual e se este comando estiver na seção de auto-execução, será o final dela também. O objetivo de definir o final dessa seção é a organização, uma vez que funções e labels são melhor organizadas se os seus corpos estiverem fora da seção de auto-execução. Por este motivo, coloque sempre os corpos das funções e labels abaixo do primeiro return do script, de modo a organizar estas seções em separado da seção principal do script. Isso vai permitir que você observe com maior clareza o fluxo da ordem de execução do script.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 17 Apr 2018, 11:04

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 17 Apr 2018, 11:04

VI. Tutorial Básico de Telas em AutoHotkey

Oi :angel:

Agora que já aprendemos muitos conceitos necessários para criar programas mais complexos, vamos finalmente explorar neste nosso sexto tutorial o conceito de telas (ou janelas) do Windows. Você sabia que o AutoHotkey é capaz de criar telas detalhadas e lhe permite gerenciar as mesmas da forma que melhor convier ao seu projeto?

Vamos em Frente! :thumbup:

1. O que são as telas e para que servem

Quando pensamos em um programa windows, sempre nos vem à mente uma tela com botões, menus, imagens, icones e mais uma série de controles que nos permitem operar o software em questão. Já vimos, no entanto, no tutorial III, que nem todo programa possui uma tela, mas como programadores, podemos fazer com que nossos programas as tenham se quisermos.

A próposito, você sabe o que são as telas? As telas são uma interface gráfica entre o usuário e a máquina (e chamamos isto de GUI, que em inglês é Graphical User Interface). Isso significa basicamente que as telas são o que permite a comunicação do usuário com o programa de uma forma gráfica (ou seja, através de imagens). Antes desse tipo de tela, toda comunicação entre usuário e máquina (ou software) era feita através de códigos escritos (ou seja, comandos), de uma forma muito semelhante a como nós programamos os nossos scripts.

Com a implementação das telas, os computadores passaram a ser tão fáceis de usar que as pessoas comuns começaram a comprá-los para suas casas e usá-los para trabalho e lazer.

Assim, podemos dizer que as GUIs (ou seja, as telas) nos permitem criar ambientes intuitivos para que o usuários possam controlar os programas da forma como permitimos que eles os controlem, sem terem de fazer um curso específico para isso.

2. E como são criadas essas telas?

As telas que vemos comumente nos computadores e celulares são basicamente criadas pelo sistema operacional daquela máquina, através de comandos enviados à eles pelos programas. Em outras palavras, é o Windows quem cria as telas do AutoHotkey (e de qualquer outro programa que rode nele). No entanto, essas telas são criadas mediante comandos e especificações passadas pelo AutoHotkey, que é quem comunica quais botões, campos, imagens e etc. que a tela vai ter, e onde eles serão posicionados. Chamamos estes componentes da tela de Controles da tela.

:arrow: Então basicamente quando queremos criar uma tela, só temos que usar o comandos adequados para dizer ao AutoHotkey como criar cada um dos componentes da tela, e como configurá-los adequadamente para fazerem o que queremos que eles façam. O AutoHotkey cuidará então de levar esses comandos traduzidos ao Windows (o sistema operacional) para que as telas sejam criadas.

Vamos para a prática? :thumbup:

3. Pensando a primeira tela

Antes de criar a primeira tela, precisamos pensar no que essa tela vai conter. O que queremos que ela exiba ao usuário? Uma tabela? uma foto? um botão? O que queremos que o programa faça quando esse usuário apertar o botão? Convém primeiramente imaginar e até desenhar esta tela em um papel para entender como ficaria cada um dos controles na sua posição adequada.

Imagine que eu queria criar uma tela que funcione como uma agenda de contatos. Assim, ela deve ter uma tabela de nomes, um campo para o usuário escrever os nomes e um botão para o usuário adicionar o nome escrito na tabela. Desenhando a tela em um papel (ou no computador), eu imagino a seguinte disposição gráfica dos controles:
TELA DE NOMES.png
TELA DE NOMES.png (3.49 KiB) Viewed 76200 times
Após olhar para o desenho um pouco, percebo que seria interessante colocar também o telefone desse contato (afinal, a tela tem que funcionar como agenda). Assim, desenho isso também.
TELA DE CONTATOS.png
TELA DE CONTATOS.png (3.82 KiB) Viewed 76200 times
Agora vejo que está bom. Se ainda faltasse algo, bastava ir adicionando até que a tela esteja bem planejada. Toda tela tem que ser bem clara para o usuário e o mais intuitiva possível.

4. Criando a primeira tela

Agora que já tenho um projeto de tela completo, com todos os controles nas suas devidas posições, chegou a hora de programarmos a tela em si. No AutoHotkey o principal comando que gera os controles de tela é o comando GUI. Exibimos uma tela inicial ao chamarmos o comando GUI com o primeiro parâmetro Show, seguido de um parâmetro de opções com a altura e a largura da tela que queremos criar. A largura será um número de pixels que escreveremos no segundo parâmetro do comando GUI juntamente (e após) a letra h (h vem de height, que em inglês significa altura). Já a largura, será também um número de pixels que escreveremos também no segundo parâmetro, mas será colocada juntamente (e após) a letra w (w vem de width, que em inglês significa largura). Já no terceiro parâmetro do comando GUI, colocamos o nome (ou título) da tela.

Você pode ver tudo isso no código abaixo. Execute-o para criar uma tela em branco com 600 pixels de largura e 400 pixels de altura.

Code: Select all

Gui, Show, w600 h400, Tela de Nomes
Tela em Branco.png
Tela em Branco.png (3.55 KiB) Viewed 76196 times
Agora que já criamos uma tela vazia, devemos colocar os demais controles. Para fazer isso, só temos que seguir uma regra de ouro: todos os comandos de criação de controles serão escritos ANTES do comando Show.

Assim, para adicionar um botão, por exemplo, basta usar o comando GUI seguido do primeiro parâmetro Add e do segundo parâmetro Button.No terceiro parâmetro, escolhemos a posição e opcionalmente a altura e largura desse botão. Todas estas coordenadas são relativas à parte superior-esquerda da tela. Temos assim a coordenada X, que significa a posição horizontal e a coordenada Y, que significa a posição vertical. Assim, se eu colocar uma posição x de 50, o meu controle será posicionado a partir do 50º pixel da tela que eu criei. Já se eu colocar uma posição Y de 100, o meu controle será posicionado a partir do 100º pixel da tela que eu criei.

:arrow: Obs: Não se preocupe demasiadamente em decorar agora todas as letras de posicionamento e tamanho de controles e telas, como h, w, x e y: você pode ver uma tabela com os principais no final deste tutorial. Matenha-a como referência até que esteja acostumado às letras.

Se a minha tela tem 600 pixels de largura e eu quero colocar um controle no meio, parece óbvio que a posição x deve ser de 300 pixels. Mas se quisermos centralizar perfeitamente, temos que descontar ainda descontar a metade da largura do controle que vamos criar. Vou criar um botão com 60 pixels de largura, assim, calculo a metade disso e deduzo de 300. O resultado é uma posição X de 270 onde vou colocar o botão.

O mesmo procedimento pode ser feito com a posição Y para centralizar o botão, lembrando que agora a dimensão relevante é a altura (logo, 400 de altura para a tela e um valor à escolha para o botão). O meu botão terá 20 pixels de altura, logo, deduzo a metade da altura do botão da metade da altura total da tela e assim consigo centralizar o controle.

O quarto parâmetro do comando que cria o botão é o nome do botão, que no caso, será Salvar.

Você pode ver tudo isso no código abaixo.

Code: Select all

Gui, Add, Button, x270 y190 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Execute o código acima para ver como a tela agora será criada com um botão centralizado.

Porém, vamos lembrar que conforme o nosso desenho, o botão não fica no centro. Na verdade, ele fica mais embaixo e na parte direita da tela. Para colocar o botão mais embaixo, basta aumentar o número do Y e para colocá-lo mais à direita, basta aumentar o número do X (o inverso também funciona para mandar o controle mais para a esquerda ou mais para cima).

Code: Select all

Gui, Add, Button, x400 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Tela com botao.png
Tela com botao.png (4.02 KiB) Viewed 76196 times
Ok, já temos nosso botão na posição correta (ou próximo dela). Cabe agora criar o campo para o usuário escrever. Farei isso chamando novamente o comando GUI, seguido do parâmetro Add, seguido do parâmetro Edit e depois das coordenadas do controle.

Como quero que ele fique à esquerda do botão e na mesma altura, eu vou repetir a coordenada Y e vou diminuir a coordenada X. Devo lembrar ainda novamente que todos os controles devem ser criados ANTES do comando show.

Code: Select all

Gui, Add, Edit, x280 y260 w100 h20
Gui, Add, Button, x400 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Tela com campo.png
Tela com campo.png (4.01 KiB) Viewed 76196 times
Quase bom! Agora vamos criar um texto para que o usuário saiba que o campo que criamos é para inserção do nome. O comando é novamente o GUI, seguido do parâmetro Add, seguido do parâmetro Text, seguido das coordenadas da posição do texto e finalmente seguido do parâmetro que contém o texto em si.

Code: Select all

Gui, add, Text, x280 y240, Nome
Gui, Add, Edit, x280 y260 w100 h20
Gui, Add, Button, x400 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Execute o código acima e veja como já criamos três controles e exibimos a nossa janela. Veja também que coloquei uma coordenada Y de 240 no texto. Isso foi feito para que ficasse somente um pouco acima do campo Edit, que está na posição Y260.

Agora vamos colocar outro campo para o usuário adicionar o telefone. Será basicamente a mesma coisa que já fizemos antes, um comando para adicionar um controle Edit e um comando para adicionar um controle de texto (com o nome do campo). Todos os controles devem ser criados antes do comando Show.

Code: Select all

Gui, add, text, x280 y300, Telefone
Gui, add, Edit, x280 y320 w100 h20
Gui, add, Text, x280 y240, Nome
Gui, Add, Edit, x280 y260 w100 h20
Gui, Add, Button, x400 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Quase tudo indo conforme o planejado. Agora vamos fazer o seguinte: quero colocar os controles mais ao centro. Isso significa basicamente que devo levar todos mais à esquerda. Se a posição X (que é horizontal) é contada de forma crescente da esquerda para a direita, então basta diminuir o número X em todos os controles para movê-los em conjunto para à esquerda. Vou diminuir a mesma quantidade para manter o alinhamento entre os controles!

Code: Select all

Gui, add, text, x230 y300, Telefone
Gui, add, Edit, x230 y320 w100 h20
Gui, add, Text, x230 y240, Nome
Gui, Add, Edit, x230 y260 w100 h20
Gui, Add, Button, x350 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Está ficando bom. Agora falta criar a tabela que ficará encima desses controles. Para fazer isso, vou usar o comando GUI, seguido do parâmetro Add, seguido do parâmetro ListView. O próximo parâmetro será o das coordenadas e depois, será uma lista separada pelo símbolo | (ou pipe) que conterá os nomes das colunas. Como temos duas colunas (nome e telefone) o código ficará assim:

Code: Select all

Gui, add, ListView, x230 y100 h120 w180, Nome|Telefone
Gui, add, text, x230 y300, Telefone
Gui, add, Edit, x230 y320 w100 h20
Gui, add, Text, x230 y240, Nome
Gui, Add, Edit, x230 y260 w100 h20
Gui, Add, Button, x350 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Tela com Tabela.png
Tela com Tabela.png (5.32 KiB) Viewed 76196 times
Ok, já temos basicamente tudo que precisamos na nossa tela. Mas ainda faltam alguns ajustes (posições, tamanho, etc). O primeiro desses ajustes é o das colunas da ListView (a tabela que criamos). Para ajustá-la, usarei uma função embutida chamada Lv_ModifyCol(). Devo usar esta função APÓS criar a ListView (logo, numa linha seguinte). O primeiro parâmetro desta função é o número da coluna que quero modificar. Já o segundo parâmetro é o novo tamanho para aquela coluna.

Como o nome normalmente é maior que o telefone, e a nossa listview tem 180 pixels de largura (coordenada w), vou colocar 100 pixels de largura na coluna nome. Já a coluna telefone, pode ser um pouco menor. Vou colocá-la como tendo 70 pixels de largura (não vai ser 80, pois se eu colocar uma coluna muito próxima à largura total da listview, será criada uma barra para escorregar a visão da tabela).

Code: Select all

Gui, add, ListView, x230 y100 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x230 y300, Telefone
Gui, add, Edit, x230 y320 w100 h20
Gui, add, Text, x230 y240, Nome
Gui, Add, Edit, x230 y260 w100 h20
Gui, Add, Button, x350 y260 w60 h20, Salvar
Gui, Show, w600 h400, Tela de Nomes
Ok, com isso nossa tela está praticamente completa! Mas olhando bem, os controles ficaram bem folgados na tela. Acho melhor diminuir um pouco o tamanho da tela, mas para fazer isso tenho que ter em mente a posição dos controles!

Lembre-se sempre que a posição é um número crescente relativo ao pixel superior-esquerdo da tela. Tendo isso em mente, diminua o mesmo número do X de cada controle para que eles possam ficar todos mais à esquerda sem bagunçar suas distâncias. Da mesma forma, diminua o mesmo número do Y de cada controle para que eles possam ficar todos mais acima sem bagunçar as distâncias. No final, diminua a tela mudando no comando Show a largura e a altura.

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20
Gui, Add, Button, x140 y180 w60 h20, Salvar
Gui, Show, w240 h300, Tela de Nome
tela final.png
tela final.png (4.23 KiB) Viewed 76196 times
Ufa! agora sim! está pronta a tela! :bravo:

Tudo que falta agora é programar as ações que serão executadas quando os controles forem operados. Vamos lá?

5. Configurando as ações da primeira tela

Agora que já temos a tela criada, vamos passar para o passo seguinte: configurar as ações dos controles. No item anterior vimos uma dica muito importante sobre a ordem de execução dos comandos de criação de tela: todos os comandos de criação de controles são escritos antes do show.

Agora vamos ver outra máxima para nos ajudar com as ações: todos os comandos de ações dos controles escritos DEPOIS do show. Isso signfica que na linha em que escrevemos os controles, escreveremos apenas a chamada para essas ações, mas os códigos a serem executados virão depois do show.

Em primeiro lugar, vamos entender que todo comando (ou quase todo) pode ter associado a ele no parâmetro de opções (o mesmo parâmetro onde escrevemos as coordenadas) uma g-label. A g-label nada mais é doque o nome de uma label (vimos o que são labels no tutorial V) que indicamos para ser executada quando o controle for pressionado ou operador pelo usuário. Colocamos uma letra g antes do nome da label nas opções do controle (por isso chamamos de g-label), mas a label em si não tem essa letra g no nome.

Para exemplificar, vamos criar uma label simples que vai ser chamada quando clicarmos no botão salvar. Essa label vai inicialmente mostrar uma MsgBox (apenas para exemplo). Para configurar que o botão chame esta label, vamos nas opções dele e colocamos o nome dessa label precedido da letra g.

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20
Gui, Add, Button, x140 y180 w60 h20 gLABEL_DE_MSGBOX, Salvar
Gui, Show, w240 h300, Tela de Nome
Return

LABEL_DE_MSGBOX:
msgbox % "Você clicou no botão!"
Return
Execute o código acima e clique no botão Salvar. Uma caixa de mensagem aparece quando fazemos isso. Se você fechar e clicar de novo, aparecerá outra caixa com a mesma mensagem. Isso acontece porque a label é uma forma de reutilização do código, e é chamada sempre que apertamos o botão.

Muito bem! já conseguimos criar a g-label. E agora?

:arrow: Agora vamos configurá-la para fazer o que realmente queremos que ela faça!

Primeiro, precisamos pensar em que ações devem acontecer quando o usuário clicar em salvar. Ora, preciso que o que ele tiver escrito nos campos seja adicionado na tabela.

Para fazer isso, inicialmente precisamos definir variáveis atreladas aos controles dos campos. Faremos isso colocando uma v-variável nas opções daqueles controles. Da mesmoa forma que a g-label, a v-variável nada mais é do que o nome de uma variável que vai conter o conteúdo do campo (ou seja, o que o usuário digitar) precedida da letra v.

Outro ponto importante é que a v-variável não vai conter os dados automaticamente: Para que a v-variável seja atualizada com os dados do campo, nós precisamos chamar o comando Gui, Submit, Nohide. Isso existe para que possamos controlar quando as variáveis serão atualizadas. Para a maioria dos casos (e para o nosso caso), esse momento é precisamente o momento em que o usuário aperta o botão. Logo, vamos adicionar o comando Gui, Submit, Nohide no início da g-label do nosso botão!

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20 vCAMPO_DE_TELEFONE
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20 vCAMPO_DE_NOME
Gui, Add, Button, x140 y180 w60 h20 gLABEL_DE_MSGBOX, Salvar
Gui, Show, w240 h300, Tela de Nome
Return

LABEL_DE_MSGBOX:
Gui, submit, nohide
msgbox % "Você digitou: " CAMPO_DE_NOME "`ne também: " CAMPO_DE_TELEFONE
Return
Execute o código acima, escreva algo nos campos e depois clique em Salvar. Viu que a MsgBox exibiu o conteúdo digitado nos campos? Você pode até mesmo alterar e apertar salvar de novo, pois as v-Variáveis serão atualizadas com os dados dos campos sempre que o comando Gui, Submit, Nohide for chamado (e ele é chamado no início da g-label atribuída ao botão).

Para concluir o nosso código agora, basta programa a inserção dos dados na tabela (ou seja, no controle ListView). Para fazer isso, usamos a função embutida Lv_Add(). Esta função adiciona uma entrada à ListView padrão do script. Seu primeiro parâmetro é um parâmetro de opções, que deixaremos em branco. Já do segundo parâmetro em diante, colocamos os valores a serem adicionados nas colunas EM ORDEM, do primeiro ao último.

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20 vCAMPO_DE_TELEFONE
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20 vCAMPO_DE_NOME
Gui, Add, Button, x140 y180 w60 h20 gLABEL_DE_MSGBOX, Salvar
Gui, Show, w240 h300, Tela de Nome
Return

LABEL_DE_MSGBOX:
Gui, submit, nohide
Lv_Add("", CAMPO_DE_NOME, CAMPO_DE_TELEFONE)
msgbox % "Tabela atualizada!"
Return
Pronto! agora sim nossa tela está completa e funcionando! :dance:

6. Criando múltiplas telas

Agora que já vimos todos os passos envolvidos na criação de uma tela, será muito fácil entender como criar múltiplas telas no AutoHotkey. O conceito básico é que a partir da segunda tela de um mesmo script, todos os comandos referentes a uma tela precisam ser numerados ou nomeadas com a tela correspondente. Comandos que sejam numerados com um 2 vão se referir somente à tela 2, e comandos numerados com um 5 vão se referir à tela 5. Os comandos referentes à primeira tela, no entanto, vão continuar sem numeração!

Assim, vamos criar um novo botão na tela que criamos antes. Este novo botão vai criar a nossa segunda tela. Veja como funciona a numeração de telas subsequentes aqui.

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20 vCAMPO_DE_TELEFONE
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20 vCAMPO_DE_NOME
Gui, Add, Button, x140 y180 w60 h20 gLABEL_DE_MSGBOX, Salvar
Gui, Add, Button, x140 y240 w80 gCRIAR_TELA_2, Tela 2
Gui, Show, w240 h300, Tela de Nome
Return

LABEL_DE_MSGBOX:
Gui, submit, nohide
Lv_Add("", CAMPO_DE_NOME, CAMPO_DE_TELEFONE)
msgbox % "Tabela atualizada!"
Return

CRIAR_TELA_2:
Gui, 2: Add, Text, x20 y20, Esta é a tela 2!
Gui, 2: Show, w400 h200
Return
Tela 2.png
Tela 2.png (8.43 KiB) Viewed 76196 times


7. Fechando telas

É costume pensar que quando o usuário clica no botão X que fica na parte superior direita da tela, a tela é fechada. No entanto, isso não é de todo verdade. O que acontece quando isso ocorre é que o programa recebe um sinal de fechamento de tela e deve decidir o que fazer com ele. Isso existe para que o programador possa configurar ações para ocorrerem antes do fechamento das telas. No AutoHotkey o comportamento padrão é que uma tela onde o usuário clicou no X seja escondida (mas não destruída), mas se existir uma label de nome GuiClose (ou 2GuiClose, 3GuiClose e etc, dependendo de qual tela foi fechada), ela não será escondida (muito menos destruída) e o sinal recebido pelo programa será usado para ativar esta label (de modo que o programador possa escrever na label exatamente o que quer que ocorra naquele momento).

O importante é saber que isso ocorre, para que como programadores não sejamos pegos de surpresa com erros "estranhos". Um exemplo é que se rodarmos uma rotina de criação de tela duas vezes (como fazemos no código do item 6 se clicarmos duas vezes no botão "tela 2") e essa rotina de criação de telas tiver variáveis associadas aos controles, teremos um erro, uma vez que cada variável só pode estar associada a um controle de tela. Assim, ao programar múltiplas telas, com uma delas abrindo as outras, temos de ter o cuidado de programar as labels de fechamento para que as janelas sejam devidamente destruídas quando usuário clicar no X (e também o que mais quisermos que ocorra antes disso, se for o caso).

Como exemplo de rotinas de fechamento, veja como atualizamos o último código do item 6 para exibir uma MsgBox e depois destruir a tela 2 da forma correta. Também coloquei uma label que encerra o programa se o usuário fechar a tela principal (você tinha percebido que isso não estava ocorrendo antes? :lol: )

Code: Select all

Gui, add, ListView, x20 y20 h120 w180, Nome|Telefone
Lv_ModifyCol(1, 100)
Lv_ModifyCol(2, 70)
Gui, add, text, x20 y220, Telefone
Gui, add, Edit, x20 y240 w100 h20 vCAMPO_DE_TELEFONE
Gui, add, Text, x20 y160, Nome
Gui, Add, Edit, x20 y180 w100 h20 vCAMPO_DE_NOME
Gui, Add, Button, x140 y180 w60 h20 gLABEL_DE_MSGBOX, Salvar
Gui, Add, Button, x140 y240 w80 gCRIAR_TELA_2, Tela 2
Gui, Show, w240 h300, Tela de Nome
Return

LABEL_DE_MSGBOX:
Gui, submit, nohide
Lv_Add("", CAMPO_DE_NOME, CAMPO_DE_TELEFONE)
msgbox % "Tabela atualizada!"
Return

CRIAR_TELA_2:
Gui, 2: Add, Text, x20 y20, Esta é a tela 2!
Gui, 2: Show, w400 h200
Return

GuiClose:
ExitApp
Return

2GuiClose:
MsgBox % "Você clicou no X da tela 2!"
MsgBox % "Mas ela só será fechada quando você fechar esta MsgBox!"
Gui, 2: Destroy
Return
8. Considerações Finais

Se você seguiu este tutorial até o fim, deve ter aprendido bastante sobre como funcionam as telas do Windows e do AutoHotkey. Vale lembrar, no entanto, que o assunto é bem extenso, e temos um grande número de outras opções parar criamos nossas telas no AutoHotkey. Você sabia que podemos adicionar outros controle, como uma checkbox (uma caixa que pode ser marcada pelo usuário) e um DropDownList (um campo com valores predefinidos que o usuário seleciona com o mouse)?

Se tiver interesse em aprender mais sobre telas, e ver todas as opções disponíveis, basta verificar o arquivo de ajuda do AutoHotkey na seção GUI ou então na seção Gui Control types (estão em inglês).

Um forte abraço e boa programação! :thumbup:

:arrow: Caracteres indicadores de posicionamento e tamanho dos controles e telas (devem ser colocados separados por espaços nos parâmetros de opções, juntamente com os valores respectivos à direita deles):
Caracteres de Posicao e Tamanho.png
Caracteres de Posicao e Tamanho.png (18.4 KiB) Viewed 76001 times
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 17 Apr 2018, 17:36

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 17 Apr 2018, 17:36

VII. Tutorial Básico de Arquivos

Olá mais uma vez :angel:

Parabéns por ter acompanhado esta série até aqui. Neste ponto, saiba que você já adquiriu uma boa noção dos principais elementos necessários para desenvolver um programa. Você sabia que os computadores possuem dois tipos de memória? E que os programas rodam em memória volátil (Memória RAM)? Isso significa que uma vez terminada a execução do programa, seja pela conclusão normal ou por uma interrupção abrupta, tudo o que fizemos nele será perdido. Mas há uma maneira de impedirmos a perda desses dados: salvando eles em arquivos, que são guardados em memória não-volátil (Disco Rígido). Agora que sabemos criar os programas, está na hora de investigarmos o que são os arquivos de computador, como eles são armazenados e identificados, quais são as suas características, como podemos desenvolver nossos próprios modelos de arquivos e como podemos usar os modelos de arquivos já existentes para guardar nossos dados de forma fácil e rápida.

Venha conosco :thumbup:

1. Arquivos de computador: o que são?

Quando ponderamos a respeito do que são os arquivos de computador, convém talvez lembrar um pouco dos objetos que os inspiraram. Trata-se dos "arquivos" do mundo real, ou seja, aqueles pesados "armários" de escritórios onde podemos abrir as gavetas e pendudar pastas com documentos diversos.

Image

Estes móveis de escritório contêm basicamente o que chamamos coletivamente de arquivos, e servem para que possamos guardar e classificar documentos diversos, que são individualmente cada qual um arquivo.

:arrow: Arquivar é basicamente armazenar de forma classificada, de modo que fique fácil e rápido encontrar cada documento individual pelo simples fato de que criamos um sistema de gavetas e pastas que implementam uma ordem de endereçamento conhecida por nós. Assim, podemos imaginar o escritório de um médico, por exemplo, onde pode haver em seu móvel de arquivos uma gaveta chamada "pacientes", onde foi colocada uma pasta com o nome de cada cliente, e em cada pasta destas foram colocados os documentos daquele respectivo cliente. Assim, se quisermos encontrar o prontuário do cliente "joão", basta nos dirigirmos até aquele móvel, abrir a gaveta de "clientes", procurar pela pasta "joão" e dentro dela encontraremos o prontuário do cliente joão. Esta sistemática de armazenamento endereçado é praticamente a mesma que encontramos em um computador.

2. Arquivo de computador: o que é?

Quando falamos individualmente "arquivo" nos referimos normalmente a um documento armazenado. Este documento, no mundo real, seria um papel com dados escritos, que podem ser lidos e interpretados por uma ou mais pessoas, de forma a proverem informações para aquelas pessoas. É importante destacar que esses dados não significam a mesma coisa para toda e qualquer pessoa: Se o documento estiver escrito em francês, por exemplo, somente alguém que saiba ler francês poderá tirar informações dali.

:arrow: A diferença entre dados e informações é que os dados não tem sentido por si só: eles precisam ser interpretados para gerar informações para alguém. Podemos dizer, assim, que as informações são dados que foram trabalhados de modo a obter algo útil. Para criar uma analogia com o mundo real, imagine que dados são como tijolos e que informações são como casas. Um serve apenas para construir alguma coisa, já o outro, adquire uma serventia nova: serve de morada. Da mesma forma, é possível construir algo completamente inútil com tijolos (dados inúteis), mas também é possível construir algo de extrema utilidade, como uma casa. Tudo depende da forma como estão dispostos estes dados e de como vamos interpretar essa disposição.

Assim, podemos dizer que um arquivo de computador, assim como um documento em papel, é um conjunto de dados armazenados e endereçados. No mundo da computação, isso significa basicamente que arquivos de computador são coleções de bits (0s e 1s), com início e fim, armazenadas de forma organizada e endereçada, no disco rígido do computador. O disco rígido do computador, como dissemos anteriormente, é uma memória não-volátil, ou seja, que não se apaga facilmente, como quando desligamos a máquina. Por isso é a memória ideal para guardarmos arquivos de computador.

Para enterdemos melhor como os arquivos são sequências de bits com início de fim, veja o exemplo hipótetico de um arquivo de computador abaixo:

011011110110110001100001001000000111000001110010011011110110011101110010011000010110110101100001011001000110111101110010

3. Arquivo de computador: como se interpretam os dados?

Tente olhar um pouco para a sequência de bits apresentada no final do item acima. Se tentarmos tirar alguma informação dela (ou seja, daquele arquivo), provavelmente falharemos. Isso ocorre porque não temos ainda os meios de interpretar estes dados. Estes meios não estão contidos no próprio arquivo porque eles nada mais são do que o conhecimento necessário para enxergar nos bits de um arquivo específico alguma informação útil. No mundo da computação, os responsáveis por deter este conhecimento são os programadores que desenvolveram ou estudaram aquele tipo de arquivos, e com isso estes programadores são capazes de desenvolver programas que interpretam estes arquivos, criando texto, imagem, audio, e tudo o mais que vemos no computador.

Assim, imagine que no arquivo acima, o programador que o desenvolveu tenha determinado que os dados deveriam ser interpretados assim: a cada byte (ou seja, a cada sequência de 8 bits, iniciando da esquerda) o valor numérico encontrado se refere a um caractere da tabela Windows-1252 (ANSI).

:arrow: De posse desse conhecimento, o que acontece se tertarmos traduzir os bits da mensagem?

Code: Select all

BASE BINÁRIA:			01101111 01101100 01100001 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01100001 01100100 01101111 01110010
EQUIVALENTE DECIMAL:		111		108		97		32			112		114		111		103			114		97		109		97			100		111		114
CARACTERE CORRESPONDENTE:	o		l		a					p		r		o		g			r		a		m		a			d		o		r
Veja que agora conseguimos uma informação! Aquela sequência de caracteres na verdade queria dizer a mensagem "olá programador".

:arrow: Os arquivos de computador são desenvolvidos de forma a facilitar a armazenagem de dados. Estes dados por sua vez, podem ser qualquer coisa, a depender apenas da forma como devem ser interpretados, podendo significar desde uma sequência de caracteres, até os valores das cores dos pixels de uma imagem, ou até mesmo às mudanças de frequência e amplitude em um sinal sonoro a ser emitido pelas caixas de som. Por isso podemos ter arquivos de texto, arquivos de imagem, arquivos de audio e outros tantos tipos de arquivos!

4. Arquivo de computador: como funciona o endereçamento?

Quando tentamos acessar arquivos de computador, normalmente abrimos as pastas e clicamos no arquivo à nossa escolha. Mas você já percebeu que se você entrar no windows explorer (o programa que se abre quando você abre qualquer pasta) e selecionar uma pasta qualquer e clicar na barra de endereço dela, aparecerá algo como C:\Arquivos de Programas\AutoHotkey ?

Esta sequência de nomes entrelaçados por barras que pendem para trás \ é o endereço daquela pasta que você está olhando. Se você entrar em uma pasta que esteja dentro dessa pasta e olhar novamente o endereço, verá que foi acrescido mais um nível ao endereço apresentado. Ficará algo como
C:\Arquivos de Programas\AutoHotkey\Compiler

É assim que são endereçadas as pastas dentro do computador: primeiro vem a letra da partição do disco, que pode ser C:, seguida de uma barra e depois da pasta principal acessada Arquivos de Programas (que se encontrar imediatamente dentro da pasta do disco C), seguida de uma nova barra e depois da pasta secundária acessada AutoHotkey (que se encontra imediatamente dentro da pasta anterior, ou seja, dentro de Arquivos de Programas), e depois esta sequência de barras e pastas vai se repetir para cada uma das subpastas que tivermos acessado no momento. E no fim, teremos os arquivos, que também têm um endereço que adiciona ao endereço da pasta, mas com uma singela diferença, a ser explicada abaixo.

:arrow: Todo arquivo tem um nome e uma extensão. Os nomes dos arquivos podem conter letras e números, e até alguns símbolos, salvo por barras (de modo a não atrapalhar o endereçamento) e outros símbolos específicos. No fim do nome do arquivo, tem um ponto e segue-se a ele uma quantidade de letras, que normalmente são 3. Esta sequência de letras após o ponto no final do nome do arquivo é o que chamados de extensão.

As extensões dos arquivos são usadas pelo windows para determinar que tipo de programa abre aquele arquivo. Assim, arquivos que são abertos pelo Microsoft Word, por exemplo, têm normalmente uma extensão .doc ou .docx. De forma semelhante, arquivos do Microsoft Excel possuem extensões próprias, que normalmente são .xls ou .xlsx. E arquivos de scripts do AutoHotkey têm uma extensão .ahk, e é assim que o seu computador sabe que quando você clicar para executar aquele arquivo, ele deverá ser rodado junto com o AutoHotkey.

Logo, o endereço completo do instalador do AutoHotkey, que é um arquivo com extensão .ahk, que fica dentro de uma pasta, que fica dentro de outra pasta, que fica no disco C é:
C:\Arquivos de Programas\AutoHotkey\Installer.ahk

Se você colar este endereço na barra de endereços do Windows Explorer (o explorador de pastas que abre quando você abre qualquer pasta), vai ver que o instalador do AutoHotkey será executado imeditamente (caso o AutoHotkey esteja instalado no seu computador, e considerando que está na pasta padrão).

:arrow: Muitos comandos do AutoHotkey operam em arquivos do computador, por isso, você deverá escrever os endereços desses arquivos em algum dos parâmetros do comando. E agora você já sabe como fazê-lo :bravo:

5. Arquivo de computador: vale a pena desenvolver um novo tipo?

Primeiramente, cabe destacar que desenvolver um arquivo é algo raro hoje em dia. Já existem muitos tipos de arquivos que atendem a padrões amplamente difundidos, e normalmente, estes padrões foram definidos por times de programadores muito experientes que buscavam otimizar ao máximo as qualidades do arquivo.

Por isso, se você procurar uma imagem em seu computador, verá que normalmente ela vai estar em um arquivo de tipo .png, ou .bmp ou então .jpg. Isso ocorre porque estes formatos foram padronizados e todos foram desenvolvidos tendo em mente coisas como densidade de informação, facilidade de leitura, implementação de transparência, ou coisas do tipo. Se você quiser criar um programa que trabalhe com imagens, por exemplo, é muito importante que seu programa tenha meios de acessar as informações dos arquivos desses tipos, o que pode ser feito através de uma API ou outra biblioteca de códigos, ou, somente em último caso, estudando o padrão do arquivo e programando o acesso e interpretação dos bits.

Digo isto não para desencorajar, mas porque desenvolver um padrão novo é bastante trabalhoso e ainda fará com que somente o seu programa saiba interpretar aquele arquivo (um arquivo de imagem do seu programa com um padrão novo não seria exibido pelo Visualizador de Fotos do windows, por exemplo). Também cabe destacar que a maioria das linguagens de programação, incluindo o AutoHotkey, têm comandos, funções, e até códigos escritos por integrantes da comunidade que trabalham com tipos já desenvolvidos de arquivos. Isso facilita muito o desenvolvimento de programas que trabalhem com eles.

Tendo dito tudo isso, vale destacar finalmente que, embora não recomendado na maioria dos casos, é sim possível que as vantagens de criar um padrão novo superem as vantagens de usar um padrão existente. Uma das situações onde você pode querer isso é caso você realmente queira um alto nível de segurança nos dados dos arquivos. Quase todos os programas gestores de bancos de dados, por exemplo, tem arquivos de tipo único, que somente eles podem ler.

6. Arquivo de computador: como escrever um programa para trabalhar com os padrões existentes?

Se você desejar escrever um programa para trabalhar com arquivos de imagens, e quiser trabalhar com arquivos do tipo .bmp, por exemplo, a primeira coisa fazer é consultar as bibliotecas de códigos já disponíveis que permitam trabalhar com estes arquivos de forma mais fácil. A comunidade do AutoHotkey possui em seus fórums varias funções e bibliotecas escritas por usuários programadores que se dedicaram para fazer sua vida mais fácil nesse sentido. Um exemplo é a biblioteca GDI+ escrita por Tic. Com essa biblioteca, você pode trabalhar com arquivos de imagens de forma mais fácil, sem precisar ter que abrir os padrões e ler os bytes um por um. Dessa forma, desenhar uma linha na imagem com a GDI+ é tão fácil como dizer as coordenadas de inicio e fim da linha nos parâmetros de uma função (já se fosse fazer pelos bytes, teríamos que mudar os valores de cada byte a cada x posições a serem calculadas de acordo com o ângulo da linha e a largura total da imagem, por exemplo).

Se o padrão que você escolher não tiver ainda um código em AutoHotkey, você ainda pode verificar a existência de uma API do windows específica para tratamento daquele tipo de arquivo (APIs dos Windows podem ser acessadas por scripts de AutoHotkey através da função DllCall(), que será tratada em outro tutorial). Além disso, mesmo que não haja uma API do windows, também é possível que um programador que trabalhe com outra linguagem de programação tenha denvolvido uma Dll para tratamento daquele tipo de arquivo (DLLs podem ser escritas em várias linguagens de programação, como C++, e podem ser acessadas pelo AutoHotkey também).

:arrow: Na programação, a reutilização do código é muito importante e somente graças a ela podemos construir programas avançados nas linguagens de alto nível que levariam muito tempo para ser escritos em uma linguagem de baixo nível.

Se tudo isso falhar, ou se as ferramentas encontradas ainda não forem adequadas para o trabalho em questão, ou se quisermos mesmo, poderemos finalmente procurar documentos que elaborem sobre o padrão do arquivo. Estes documentos normalmente trazem detalhes sobre a estrutura do arquivo, dizendo de forma clara em quais bytes estão as informações que procuramos (tanto os endereços em relação ao byte inícial do arquivo quanto os chamados Offsets, que são os endereços em relação a outros bytes).

Podemos verificar o padrão do formato .bmp, por exemplo, que é um formato de arquivo de imagens muito difundido, juntamente com a sua estrutura até mesmo na página do padrão na wikipedia. Outros formatos com disponibilização do padrão grátis podem ser conferidos em sites especializados ou podemos ainda encontrar alguns formatos proprietários disponíveis para aquisição de algum meio através das companhias que os desenvolveram.

7. Escrevendo um arquivo de texto (tipo de arquivo já padronizado) com ferramentas já disponíveis (método de programação em alto nível)

:arrow: Como dito anteriormente, existem métodos bem mais fáceis para cumprir estas tarefas se o tipo de arquivo for um tipo padrão. No caso dos arquivos de texto, escrever uma mensagem como "ola programador" seria bem mais fácil usando o comando FileAppend, por exemplo. Usando este comando, não precisaríamos nos preocupar com valores binarios e nem com questões específicas como Offsets.

Code: Select all

Endereco_Do_Arquivo := A_ScriptDir . "\exemplo2.txt"
FileAppend, ola programador, %Endereco_Do_Arquivo%
8. Arquivo de computador: se eu realmente quiser, como desenvolver um novo tipo?

Caso você queira realmente desenvolver um tipo novo de arquivo, vale a pena pensar primeiramente em que tipo de dados serão guardados no arquivo. Serão dados que se traduzirão em texto? ou serão dados de imagens? ou talvez serão dados de arquivos de audio? Ou ainda dados de modelos tridimensionais para jogos?

Se você quiser guardar dados em formato de texto, talvez valha a pena elaborar uma tabela de tradução dos bits em caracteres, parecida com a tabela Windows-1252 (ANSI). No entanto, se for um arquivo de imagem, convém pensar que cada sequência de bits pode significar os valores de cores dos pixels da imagem, ordenados da esquerda para a direita e depois de cima para baixo na imagem e ordenados da esquerda para a direita no arquivo, por exemplo. Já se for um arquivo de audio, podemos pensar que os bits devem conter informações sobre os tempos das alterações da frequência e da amplitude dos sinais, por exemplo.

Lembre-se disso: Os padrões se orientam sempre pelas posições em relação ao inicio e ao fim do arquivo. Assim, o byte que contém informações sobre o terceiro pixel de uma imagem, por exemplo, pode ser o terceiro byte do arquivo (ou pode ser o antepenúltimo). Também é importante saber que um mesmo arquivo pode conter mais de um tipo de dados. Isso é extremamente comum. Um arquivo de video, por exemplo, pode conter dados de imagens e de audio, por exemplo.

Mas como isso é organizado?

:arrow: Os arquivos podem conter metadados. Metadados são basicamente dados sobre dados. Assim, eu posso definir que o primeiro byte do arquivo conterá a posição inicial da sequência de bytes que contém dados de imagem, e que o segundo byte do arquivo contém a posição final. Da mesma forma, o terceiro byte pode conter a posição inicial da sequência de bytes que contém dados de audio, e o quarto byte do arquivo pode conter a posição final da sequência de dados de audio. Assim, um determinado arquivo pode ter a sequência de audio iniciada no 57º byte, enquanto que outro arquivo do mesmo tipo pode ter a sequência iniciada no 92º byte (ou mesmo no 374655º byte).

Assim, vale a pena descrever a estrutura dos bytes do seu arquivo em um documento que será o padrão dele. Desta forma, poderá consultar o padrão sempre que quiser, e se desejar (caso não queira manter o padrão em segredo), poderá ainda publicar este documento.

9. Escrevendo um arquivo de texto byte a byte (método de programação em baixo nível)

Como dito anteriormente, na maioria das vezes não é recomendado criar padrões novos de arquivos, pois existem métodos bem mais fáceis de lidar com os tipos de arquivos padrão. Mas caso decidamos fazê-lo, isso também é possível. Assim, vamos ver na prática como podemos criar um arquivo escrevendo-o byte a byte, de modo que mesmo que seja uma implementação de um tipo totalmente novo, possamos programar funções e rotinas para inserir e retirar informações dele. Para cumprir este objetivo, usaremos a função FileOpen(), que retorna um objeto, e depois usaremos o método RawWrite deste objeto. Objetos e métodos serão tratados em um tutorial mais a frente: o importante no momento é a explicação dos conceitos.

Veja no código abaixo como criamos o arquivo de texto contendo a mensagem "ola programador" byte a byte.

Code: Select all

Endereco_Do_Arquivo := A_ScriptDir . "\Exemplo.txt"
VarSetCapacity(Mensagem, 15, 0)
NumPut(111, Mensagem, 0, "UChar")
NumPut(108, Mensagem, 1, "UChar")
NumPut(97, Mensagem, 2, "UChar")
NumPut(32, Mensagem, 3, "UChar")
NumPut(112, Mensagem, 4, "UChar")
NumPut(114, Mensagem, 5, "UChar")
NumPut(111, Mensagem, 6, "UChar")
NumPut(103, Mensagem, 7, "UChar")
NumPut(114, Mensagem, 8, "UChar")
NumPut(97, Mensagem, 9, "UChar")
NumPut(109, Mensagem, 10, "UChar")
NumPut(97, Mensagem, 11, "UChar")
NumPut(100, Mensagem, 12, "UChar")
NumPut(111, Mensagem, 13, "UChar")
NumPut(114, Mensagem, 14, "UChar")

oFILE := FileOpen(Endereco_Do_Arquivo, "w")
oFILE.RawWrite(Mensagem, 15)
O código acima faz o seguinte:
  • 1. Define um endereço de arquivo na mesma pasta do script (Fazemos iso atráves da variável embutida A_ScriptDir, que contém o endereço completo da pasta do script em execução). Veja que usamos um nome de arquivo com a extensão .txt. Isso vai dizer ao windows que programa queremos que ele use para abrir (e interpretar) o arquivo (neste caso, é um editor de texto).
  • 2. Utilizamos a função embutida VarSetCapacity() para definir uma variável chamada "mensagem" cujo tamanho é de exatamento 15 bytes.
  • 3. Colocamos valores numéricos em cada posição de byte da variável mensagem (chamamos as posições de Offsets). Os Offsets vão do 0 ao 14, porque iniciam no 0 e são um total de 15. Os valores inseridos correspondem aos valores numéricos de caracteres da tabela ANSI (fazemos isso porque definimos que o propósito deste código é escrever um arquivo de texto, portanto, os bytes têm que ser escritos tendo em mente que serão interpretados através do padrão de arquivo texto, que é byte-a-byte significando caractere-a-caractere da tabela ANSI. Neste padrão, o primeiro byte é o primeiro caractere, o segundo é o segundo, e assim sucessivamente, da esquerda para a direita).
  • 4. Nas duas últimas linhas, primeiro criamos um objeto-arquivo com a função embutida FileOpen() e depois usamos o método RawWrite do objeto criado para escrever os valores da variável de forma crua, isto é, através dos valores binários, no arquivo aberto.
  • Pronto, agora é só ir na pasta do script e olhar o arquivo criado. Se você abri-lo com um editor de texto, verá a mensagem "ola programador", que foi escrita pelos valores binários byte a byte.
10. Considerações finais

Com o conhecimento de arquivos de computador, você se tornou capaz de criar programas que salvem os dados inseridos pelo usuário, de modo que mesmo que ele feche o programa, o programa "lembre" do que foi feito na próxima vez que for executado. Também se tornou apto a utilizar um número maior de comandos do AutoHotkey, pois agora você já sabe como endereçar os arquivos e prover os endereços corretos nos parâmetros do comandos. Nós também discutimos bastante sobre os diferentes tipos de arquivos, e como eles são feitos, e até mesmo criamos um arquivo seguindo o padrão dos arquivos de texto de forma totalmente baixo nível, costurando-o byte a byte.

Você viu como foi mais fácil criar o arquivo pela maneira do item 7 do que pela do item 9? Isso ocorreu porque usamos um comando do AutoHotkey (alto nível) para resolver o problema sem ter de lidar com as questões mais esmiuçadas do padrão do arquivo. Essa é quase sempre a melhor forma de programar rotinas com arquivos, e deve ser preferida pela facilidade que traz ao programador, pois valoriza nosso tempo e permite que façamos programas com mais recursos dentro de um mesmo tempo de execução do projeto.

Acredito que este tutorial foi bastante descritivo. Espero que tenha servido para dar uma visão geral muito boa sobre o que são os arquivos de computador. Se você ainda tiver alguma dúvida sobre o assunto, sinta-se livre para perguntar abaixo ou para usar o nosso fórum Eu Preciso de Ajuda.

Obrigado por ler mais este tutorial e até a próxima :thumbup:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 19 Apr 2018, 11:57

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 19 Apr 2018, 11:57

VIII. Desenvolvimento de um Programa com Telas e Arquivos

Olá :angel:

Se você vem acompanhando esta série de tutoriais, já deve ter aprendido muita coisa sobre programação. Para consolidar esse aprendizado, decidi dedicar este oitavo tutorial a apresentar um projeto concluído de um programa com vários dos conceitos que aprendemos nos últimos tutoriais. O objetivo desta etapa é entender como aplicamos os conceitos aprendidos até aqui de forma a construir um programa que servirá para um propósito comum em nosso dia a dia.

Você alguma vez já se viu com um monte de tarefas diferentes para fazer e percebeu que era difícil distribuir o seu tempo de forma organizada entre elas? É comum estarmos bem atarefados no nosso dia-a-dia profissional ou estudantil e quando as datas de entrega dos trabalhos ou das provas vão se aproximando, nós sempre ficamos com aquela sensação de que perdemos muito do nosso tempo ou que temos sempre muita coisa para entregar de uma só vez em alguma semana específica.

A razão desta sensação normalmente não é o número de tarefas, mas a forma empírica como nós controlamos as tarefas fazendo uso somente da nossa mente. Demonstrar isso é fácil: basta perceber que na semana anterior tinhamos praticamente o mesmo número de tarefas, mas não tínhamos a mesma sensação de urgência e sobrepeso desta semana!

Portanto, se quisermos melhorar nossa vida e distribuir melhor a nossa carga de compromissos ao longo do nosso tempo, precisamos fazer uso de ferramentas informativas que melhorem o nosso controle sobre as nossas tarefas pendentes.

Desta forma, este tutorial se dedica a demonstrar e explicar o desenvolvimento e o código de um programa gestor de tarefas.

Vamos lá?

1. Desenvolvendo os aspectos conceituais

Conforme vimos nos tutoriais I e III, todo projeto nasce de uma ideia, e esta surge normalmente a partir da constatação de um problema e de nosso conhecimento prévio sobre o que podemos usar para melhor resolver este problema. Dessa forma, podemos definir o nosso para este tutorial como sendo como controlar melhor as nossas tarefas e gerir o nosso tempo gasto com elas.

Assim, nos vem a mente, graças ao nosso conhecimento prévio sobre as possibilidades da programação, a ideia de criar um programa que nos permita gerenciar essas tarefas.

O próximo passo é então planejar este programa, transformando-o em um projeto. Isso significa que devemos nos esforçar para criar um esboço, onde fique mais fácil elencar que informações vamos precisar controlar e que telas, tabelas, e outros controles vão ajudar nosso usuário a realizar este controle de forma fácil e efetiva.

Pensando um pouco sobre como se executa a maioria das tarefas, vejo que elas tem alguns momentos distintos que podem ser relativamente bem definidos. O primeiro é o momento inicial, aquele no qual descobrimos que teremos que cumprir a tarefa. Esse momento pode ser o momento em que o professor ou chefe nos passa a tarefa, ou o momento em que decidimos que vamos implementar essa tarefa. Quando este primeiro momento chega a tarefa ganha forma e passamos a conhecer alguns aspectos importantes dela. O primeiro é a descrição da tarefa, ou seja, o trabalho que precisa ser feito. Além disso, temos a data e/ou hora inicial, aquela na qual tomamos conhecimento da necessidade de executar a tarefa. Também podemos descobrir naquele momento o responsável pela tarefa, que pode ser a pessoa principal caso a tarefa seja delegada a um time. Outro ponto importante da tarefa é a data máxima para a sua conclusão, ou seja, até quando podemos entregar a tarefa, que vai nos dizer ainda o prazo que temos para concluir a tarefa. Além disso, como esta tarefa provavelmente não será a única que teremos para entregar em um mesmo momento, podemos ainda indicar para a mesma uma prioridade em relação às outras tarefas que temos para entrega. Mas aqui cabe uma ressalva: muita gente define a prioridade com base na data de entrega. Isso não é necessariamente verdade: a prioridade serve para sabermos em qual tarefa devemos trabalhar primeiro caso já tenhamos, ou caso apareça depois, uma outra tarefa para concluir, mas não significa que podemos deixar as tarefas para depois. Lembre-se: deixar tarefas para depois é o que nos faz sentir sobrecarregados próximo às datas de entrega!

Basicamente são estes os principais pontos que as tarefas têm em comum e que podem ser conhecidos assim que recebemos a tarefa. Isso signfica que estas são as informações que precisamos controlar no nosso programa e que serão inseridas no momento do cadastro da tarefa. Mas um ponto importante precisa ser destacado também: muitas tarefas têm outros pontos específicos que podem ser muito importantes de se controlar. Para estes casos especiais, precisamos ter em nosso programa um ou mais campos genéricos, que permitam ao usuário uma certa flexibilidade no controle das informações importantes das tarefas. Por este motivo, é importante em quase qualquer programa pelo menos um campo de observações.

Após o momento inicial, temos também momentos secundários da conclusão da tarefa. Estes momentos são os andamentos que damos à tarefa ao longo do tempo de execução. Tirando algumas tarefas menores, as tarefas normalmente envolvem um tempo de execução longo, onde precisamos avançar passo-a-passo antes de concluir a tarefa. Por exemplo, para construir uma casa, é preciso primeiro esquadrejar as medidas e cavar a vala da fundação. Depois, precisamos construir a fundação, e daí poderemos levantar os pilaretes e construir as paredes, que precisarão mais à frente serem rebocadas, emassadas e pintadas. Também temos a construção do telhado e do forro. Todas essas tarefas menores são andamentos da tarefa maior (que é a construção da casa). Assim, vemos que uma tarefa longa pode ser dividida em andamentos menores, e controlar esses andamentos é uma forma mais adequada de controlar a tarefa maior. Se hoje nós terminamos de cavar a vala, é importante poder colocar isso no nosso programa, de modo que fique claro que concluímos um passo importante para a construção da casa!

Resumindo, o programa deve:
  • 1. Permitir a inclusão de tarefas e controle de seus principais aspectos conhecidos no início.
  • 2. Permitir a inclusão de cada andamentos em cada tarefa, de modo que fique claro o passo-a-passo para a solução da tarefa.
  • 3. Permitir a indicação da conclusão da tarefa (para que saibamos o que está pendente e o que já foi feito). Isso pode vir através do status de conclusão e do status de finalização da tarefa.
2. Desenvolvendo as telas

Para desenvolver as telas do nosso programa, precisamos pensar em como utilizaremos os controles disponíveis (botões, campos, tabelas, etc) para controlar adequadamente o que elencamos no final do item anterior.

Pensando um pouco, vejo que seria interessante um formulário de inclusão de tarefas, e também uma tabela mostrando cada tarefa pendente. Além disso, como as tarefas têm andamentos que devem ser controláveis, precisamos de um formulário de inclusão de andamentos e de uma tabela que mostra os andamentos de cada tarefa. Precisamos colocar tudo isso em um (ou mais) espaços de tela, vejo que seria interessante que os andamentos fossem dispostos em uma tabela à parte, e que essa tabela mostrasse os andamentos da tarefa selecionada na tabela de tarefas.
ESBOCO FORMULARIO INCLUIR TAREFA.jpg
ESBOCO FORMULARIO INCLUIR TAREFA.jpg (45.78 KiB) Viewed 72500 times
ESBOCO DO GESTOR DE TAREFAS.jpg
ESBOCO DO GESTOR DE TAREFAS.jpg (109.1 KiB) Viewed 72500 times
ESBOCO INCLUIR ANDAMENTO.jpg
ESBOCO INCLUIR ANDAMENTO.jpg (39.26 KiB) Viewed 72500 times

Está quase bom. Mas ainda faltam algumas coisas. Primeiro, precisamos de uma forma de separar as tarefas finalizadas. Para isso, podemos usar simplesmente outra tela com uma tabela própria para as tarefas finalizadas. Isso significa também colocar um botão para o usuário indicar a finalização da tarefa. Além disso, precisamos pensar onde vai ficar o formulário de inclusão de andamentos. Acredito que o melhor lugar é a própria tela de tarefas em aberto (colocaremos na parte de baixo dela).

Com isso, já temos uma boa ideia sobre como vai funcionar o programa!

3. Desenvolvendo os arquivos

Conforme vimos no tutorial VII, se quisermos controlar informações que não podem ser perdidas caso o programa seja fechado ou o computador seja desligado, precisamos salvar estas informações em arquivos no disco rígido do computador. Para isso precisamos projetar nossos arquivos.

A melhor maneira de fazer isso é pensar em que tipo de informações estaremos salvando nesse arquivo. Todas as informações que vamos trabalhar são de certa forma descrições textuais das tarefas e andamentos, inseridas pelo usuário. Assim, podemos perceber que trabalharemos com uma espécie de arquivo de texto.

Mas há um porém: algumas informações que precisamos salvar não são exatamente texto. Imagine que precisamos que o programa saiba que porção do texto que o usuário inseriu se refere à observação de determinado andamento de determinada tarefa. Temos que salvar isso também!

Estes dados sobre dados são, conforme vimos no tutorial VII, chamados de metadados. Eles são importantes para que o programa saiba tratar corretamente a informação recebida. No nosso caso, isso significa que o programa precisa ter uma forma de saber o que é uma observação, o que é uma data, e assim sucessivamente.

Podemos fazer isso de várias formas. Uma delas é desenvolver um novo tipo de arquivo, que permita indicar as posições no texto que se referem a cada campo. Mas como vimos no tutorial VII, isso vai demandar muito tempo e trabalho. Talvez seja melhor procurar outro tipo de arquivo já existente que permita fazer isso de forma mais fácil.

Consultando o arquivo de ajuda do AutoHotkey, vemos que ele possui suporte para um tipo de arquivo de texto chamado .ini. Os arquivos desse tipo são normalmente arquivos de parâmetros de configuração, e se organizam através de chaves descritivas de cada informação. Parece bastante com o que queremos!

Portanto, vamos investigar se o arquivo .ini nos permitiria grava tudo o que precisamos sobre os andamentos e tarefas.

Um arquivo .ini se organiza da seguinte forma:

Code: Select all

[seção1]
chave1=valor
chave2=valor
chave3=valor
...

[seção2]
chave1=valor
chave2=valor
...
Assim posso imaginar que a informação que preciso pode ser escrita mais ou menos assim:

Code: Select all

[1]
descricao=CONSTR. CASA
data_inic=22/05/2018
resp=CICRANO
status=40
prior=media

[1.1]
data=23/05/2018
hora=08:00
descricao=VALA DA FUNDACAO CAVADA
novo_status=10
observ=PEDREIRO BELTRANO


[1.2]
data=25/05/2018
hora=10:30
descricao=CONSTRUCAO DO BALDRAME
novo_status=20
observ=PEDREIRO CICRANO
:arrow: A ideia é simples. O nome de cada seção diz se é uma tarefa ou um andamento, e no caso do andamentos, diz ainda a qual tarefa se refere. Isso será feito através dos códigos numéricos. Assim, a seção 8 por exemplo, que não tem decimais, será uma seção de tarefa, e a seção 8.1, que tem um decimal, será o primeiro andamento da tarefa da seção 8.

Além disso, as chaves de uma seção sem decimais, como a 5, se referem as informações de uma tarefa, e as chaves de seção com decimais, tipo 5.3, se referem as informações de um andamento.

Agora, podemos fazer uso dos comandos do AutoHotkey que tratam de arquivos do tipo .ini para botar esta ideia em prática!

:arrow: Um detalhe: Os comandos de arquivos do tipo .ini não necessitam que o arquivo seja normeado com a extensão .ini. Podemos usar isso como um nível de segurança, fazendo com que o usuário não consiga abrir o arquivo automaticamente em um editor de texto, como faria se ele estivesse nomeado corretamente com a extensão .ini (embora caiba destacar que esse nível de segurança extremamente básico, afinal, o arquivo ainda pode ser abertos em um editor de texto se o usuário souber que isso é possível!).

:arrow: Se quiséssemos, poderíamos aumentar ainda mais o nível de segurança das informações de várias formas. Uma delas é encriptar as informações no arquivo .ini. Para este tutorial, isso não será feito, pois este programa é somente para estudo. Mas é importante dizer que cabe ao programador definir o nível de segurança das informações do seu programa, lembrando que maior segurança pode requerer maior trabalho.


4. Escrevendo o código

Agora que já temos um projeto adequado, está na hora de executá-lo. Isso significa basicamente escrever o código e tornar real o nosso programa. Podemos iniciar escrevendo os códigos das telas, e você pode consultar o tutorial VI para ver como isso é feito.

Em resumo: mostramos uma tela com o comando show, e seguimos duas máximas: os preparativos da tela (colocar botões, campos, etc) são escritos ANTES DO SHOW e as ações dos personagens (ou seja, o que vai acontecer quando o usuário ativar os controles) serão escritos APÓS O SHOW.

Assim, as ações dos controles são o que ativa as labels de escrita dos arquivos. Essa labels contém os comandos de tratamento do arquivo .ini que renomeamos com .bdgt para que somente nós saibamos a princípio que se trata de um arquivo de texto.

Lembre-se também de uma coisa muito importante: como vamos escrever um código longo, é extremamente importante comentar bastante o código e também dividí-lo em labels e funções com nomes bem indicativos do que os códigos fazem. Isso signifca que apesar de nosso código ter mais de 350 linhas, será relativamente fácil analisá-lo e ainda entender onde teremos que mexer se quisermos alterar alguma coisa. ASSIM, PARA LER O CÓDIGO ABAIXO, PENSE NOS NOMES DAS LABELS E FUNCOES E COMO ISSO INDICA O QUE A PORÇÃO DE CÓDIGO FAZ. LEIA TAMBÉM OS COMENTÁRIOS (QUE FICAM NAS PRÓPRIAS LINHAS APÓS O SÍMBOLO ;).

Assim, o código final do programa Gestor de Tarefas pode ser conferido abaixo. Execute o código e cadastre algumas tarefas. Depois, cadastre andamentos para algumas das tarefas. Veja como o programa se comporta e como ele exibe as informações de forma organizada. Veja também que o programa cria um arquivo chamado BD.dbgt na pasta em que se encontra quando você o executa. Este arquivo é o arquivo .INI (embora com uma extensão diferente). Depois de incluir algumas tarefas e andamentos, você pode abrir este arquivo em um editor de texto para ver como o programa o usou para salvar as informações!

:arrow: A SENHA É ABACAXI.

Code: Select all

; GESTOR DE TAREFAS.AHK
; AUTOR: GIO
; LINK DO POST: https://autohotkey.com/boards/viewtopic.php?p=213650#p213650
; DATA DE ESCRITA: 21/05/2018
; DESCRIÇÃO DO PROGRAMA: GERENCIADOR DE TAREFAS COM ROTINAS DE INCLUSAO E VISUALIZAÇÃO DE TAREFAS E DE SEUS ANDAMENTOS EM TABELAS
; O PROGRAMA INICIA AQUI
; ESTA PORÇÃO INICIAL ABRE A PRIMEIRA TELA, ONDE O USUÁRIO DEVE COLOCAR A SENHA ABACAXI.

Gui, Font, s16 w700
Gui, Add, Text, x20 y20 w560 Center, Bem-Vindo!
Gui, Font
Gui, Font, s12 w700
Gui, Add, Text, x20 y280 w560 Center, Insira a senha abaixo para continuar
Gui, Add, Text, 
Gui, add, Edit, Password x200 y310 w200 Limit12 vSENHA_INSERIDA
Gui, add, Button, x250 y350 w100 gAbrir_Agenda, Entrar ; AQUI TEM UMA G-LABEL! ISSO SIGNIFICA QUE QUANDO ESSE BOTAO DA PRIMEIRA TELA É PRESSIONADO, A LABEL ABRIR_AGENDA É EXECUTADA!
Gui, show, w600 h400, SisOrg v0.1
Return




Abrir_Agenda:
Gui, Submit, nohide
If !(SENHA_INSERIDA = "ABACAXI") ; ESTA CONDICIONAL CHECA SE O USUÁRIO NÃO ESCREVEU ABACAXI NO CAMPO DE SENHA DA PRIMEIRA TELA. SE ELE NÃO ESCREVEU, EXIBE UM ERRO E RETORNA A EXECUÇÃO SEM PROSSEGUIR.
{
	msgbox, 0x10, Erro, A senha digitada está incorreta! Tente novamente ou procure o suporte! `n`n`n(OBS: A SENHA ESTÁ NO POST, ACIMA DO CÓDIGO! OU VEJA ELA NO CÓDIGO DO SCRIPT!)
	Return
}
; SE A EXECUÇÃO CHEGAR AQUI, ISSO SIGNFICA QUE O USUÁRIO ESCREVEU A SENHA ABACAXI (POIS SE NÃO TIVESSE ESCRITO, A LINHA DE RETORNO TERIA SIDO EXECUTADA).
; ENTENDEMOS PORTANTO QUE O USUÁRIO ESCREVEU A SENHA CERTA E ASSIM CONTINUAMOS OS COMANDOS PARA ABRIR A AGENDA.
IniRead, MAXIMA_ENTRADA, %A_SCriptDir%/BD.bdgt, MAXIMA_ENTRADA, CODIGO
If (MAXIMA_ENTRADA = "ERROR") ; ESTA CONDICIONAL CHECA SE O ARQUIVO INI NÃO POSSUI UMA SEÇÃO COM A MÁXIMA ENTRADA. USAMOS ESSA INFORMAÇÃO PARA CONTROLE DOS CODIGOS DAS TAREFAS.
{
	; SE A EXECUÇÃO ENTRAR AQUI, O ARQUIVO INI NÃO POSSUI UMA SEÇÃO COM A MÁXIMA ENTRADA (MÁXIMO CÓDIGO DE TAREFA). ENTENDEMOS QUE SE ISSO ACONTECEU, ESTA PODE SER A PRIMEIRA VEZ QUE 
	; O PROGRAMA É EXECUTADO OU ENTÃO O ARQUIVO INI FOI CORROMPIDO.
	CAMINHO_DO_ARQUIVO_DB := A_SCriptDir . "/BD.bdgt"
	If !(FileExist(CAMINHO_DO_ARQUIVO_DB)) ; AQUI VERIFICAMOS SE EXISTE UM ARQUIVO INI NO CAMINHO QUE DEVERIA ESTAR (NA PASTA DO PROGRAMA).
	{
		Msgbox, 0x14, Erro, O sistema não detectou a presença de um arquivo de banco de dados na pasta principal. Deseja criar um novo arquivo de banco de dados em branco?
		IfMsgBox, no ; ESTA CONDICIONAL VERIFICA SE O USUARIO ESCOLHEU "NÃO" NA CAIXA DE TEXTO. SE ESCOLHEU, TERMINAMOS A EXECUÇÃO DO PROGRAMA, POIS ESTE NÃO PODE TRABALHAR SEM O ARQUIVO INI.
		{
			msgbox, 0x10, Erro, O sistema não pôde se comunicar com o banco de dados. Reinicie ou contacte o suporte.
			ExitApp
		}
		; SE A EXECUÇÃO CHEGAR AQUI, O USUÁRIO ESCOLHEU "SIM" NA CAIXA DE TEXTO (SABEMOS DISSO POR ELIMINAÇÃO, VEZ QUE O CÓDIGO DO "NÃO" NÃO FOI EXECUTADO).
		IniWrite, 0, %A_SCriptDir%/BD.bdgt, MAXIMA_ENTRADA, CODIGO ; ESCREVEMOS UM NOVO ARQUIVO INI COM A MAXIMA ENTRADA 0 (ZERO) PARA INICIO DE CONTROLE DE CODIGOS DE TAREFAS.
		Goto, Abrir_Agenda
		Return
	}
}
CriarGui2() ; NESTA LINHA CHAMAMOS A FUNÇÃO CRIARGUI2().  ASSIM, A EXECUÇÃO PULARÁ ATÉ O CÓDIGO DELA (PROCURE POR ELE ABAIXO). A FUNÇÃO NOS PERMITE SEPARAR E ORGANIZAR O CÓDIGO LONGO, VEZ QUE AQUI IRIAM MUITAS LINHAS RELACIONADAS SOMENTE A CRIAR A JANELA, POR ISSO, SEPARAMOS ELAS EM UMA FUNÇÃO PRÓPRIA. ASSIM, SE QUISER VER AS LINHAS QUE LIDAM COM A CRIAÇÃO DA TELA 2, BASTA IR NO CORPO DA FUNÇÃO CRIARGUI2(), QUE É AGORA UM PASSO SEPARADO DA ROTINA ABRIR_AGENDA.

Loop % MAXIMA_ENTRADA ; NESTA LINHA INICIAMOS UM LOOP, QUE É UMA REPETIÇÃO DE UM BLOCO DE COMANDOS. NO CASO DESTE LOOP, ELE VAI REPETINDO O CÓDIGO ABAIXO PARA LER CADA LINHA DO ARQUIVO INI E ADICONAR AS INFORMAÇÕES DA TAREFA NA TABELA DE TAREFAS DA TELA 2. VEJA COMO USAMOS A VARIAVEL EMBUTIDA A_INDEX PARA MUDAR A LEITURA EM CADA REPETIÇÃO DO LOOP (ITERAÇÃO). NA PRIMEIRA EXECUÇÃO, A_INDEX CONTÉM O NÚMERO 1, NA SEGUNDA CONTÉM O NÚMERO 2, E ASSIM SUCESSIVAMENTE ATÉ A ÚLTIMA REPETIÇÃO, QUE NADA MAIS É DO QUE O NÚMERO CONTIDO NA SEÇÃO MAXIMA_ENTRADA, QUE INDICA O NÚMERO DE TAREFAS ESCRITO NO ARQUIVO INI. É IMPORTANTE ENTENDER ESTE PONTO, POIS TODO O PROGRAMA TRABALHA CORRIGINDO ESSA INFORMAÇÃO: POR EXEMPLO, QUANDO ADICIONAMOS UMA NOVA TAREFA, O PROGRAMA VAI NO ARQUIVO INI E ADICIONA 1 AO NÚMERO QUE ESTÁ NA SEÇÃO MÁXIMA ENTRADA E SALVA O ARQUIVO. ASSIM, NA PRÓXIMA EXECUÇÃO, O PROGRAMA VAI SABER QUANTAS TAREFAS TEM (UMA A MAIS)..
{
	IniRead, CODIGO, %A_SCriptDir%/BD.bdgt, %A_Index%, CODIGO
	IniRead, DATA_INICIAL, %A_SCriptDir%/BD.bdgt, %A_Index%, DATA_INICIAL
	IniRead, HORA_INICIAL, %A_SCriptDir%/BD.bdgt, %A_Index%, HORA_INICIAL
	IniRead, DESCRICAO, %A_SCriptDir%/BD.bdgt, %A_Index%, DESCRICAO
	IniRead, RESPONSAVEL, %A_SCriptDir%/BD.bdgt, %A_Index%, RESPONSAVEL
	IniRead, STATUS, %A_SCriptDir%/BD.bdgt, %A_Index%, STATUS
	IniRead, FINALIZADA, %A_SCriptDir%/BD.bdgt, %A_Index%, FINALIZADA
	IniRead, OBSERVACAO, %A_SCriptDir%/BD.bdgt, %A_Index%, OBSERVACAO
	If (FINALIZADA = "NAO") ; SE A TAREFA QUE ESTÁ SENDO LIDA TEM A INFORMAÇÃO "NAO" NA CHAVE FINALIZADA, ELA VAI PARA A TABELA DE TAREFAS EM ABERTO.
	{
		Gui, 2: Default
		Gui, 2: ListView, VIEW_TAREFAS
		Lv_Add("", CODIGO, DATA_INICIAL, HORA_INICIAL, DESCRICAO, RESPONSAVEL, STATUS, OBSERVACAO)
	}
	If (FINALIZADA = "SIM") ; MAS SE TIVER A INFORMAÇÃO "SIM" NA CHAVE FINALIZADA, ELA VAI PARA A TABELA DE TAREFAS FINALIZADAS. QUANDO FINALIZAMOS A TAREFA, O SISTEMA MUDA A INFORMAÇÃO DESTA CHAVE NESTA TAREFA, É ASSIM QUE CONTROLAMOS QUAIS TAREFAS ESTAO FINALIZADAS.
	{
		Gui, 2: Default
		Gui, 2: ListView, VIEW_TAREFAS_FIN
		Lv_Add("", CODIGO, DATA_INICIAL, HORA_INICIAL, DESCRICAO, RESPONSAVEL, STATUS, OBSERVACAO)
	}
}
GoSub, GuiClose
Return




; A FUNÇÃO ABAIXO CRIA A TELA 2. VEJA QUE TODOS OS COMANDOS VEM ANTES DO COMANDO SHOW (QUE É O ÚLTIMO).
CriarGui2()
{
	global
	Gui, 2: Font, s12 w700
	Gui, 2: Add, Tab2, x20 y20 w760 h560, Nova Tarefa|Tarefas Em Aberto|Tarefas Finalizadas
	Gui, 2: Add, GroupBox, x40 y60 w720 h400, NOVA TAREFA
	Gui, 2: Add, Text, x60 y90, Descrição
	Gui, 2: Add, Edit, x60 y110 h100 w600 UPPERCASE vDESCRICAO_NOVA_TAREFA
	Gui, 2: Add, Text, x60 y220, Responsável
	Gui, 2: Add, Edit, x60 y240 w600 UPPERCASE -MULTI vRESPONSAVEL_NOVA_TAREFA
	Gui, 2: Add, Text, x60 y280, Observação
	Gui, 2: Add, Edit, x60 y300 h100 w600 UPPERCASE vOBSERVACAO_NOVA_TAREFA
	Gui, 2: Add, Button, x60 y420 gSALVAR_TAREFA, SALVAR NOVA TAREFA
	Gui, 2: Tab, 2
	Gui, 2: Add, Text, x40 y60 w660 Center, TAREFAS
	Gui, 2: Add, ListView, x40 y80 w720 r6 Grid vVIEW_TAREFAS gSELECIONAR_TAREFA AltSubmit, Cód|Data Inicial|Hora Inicial|Descrição|Responsável|Status|Observação ; MUITO IMPORTANTE!! VEJA A G-LABEL AQUI INIDICADA. QUANDO CLICAMOS NESSA TABELA, ELA EXECUTA: É ASSIM QUE ATUALIZAREMOS A TABELA DE ANDAMENTOS CADA VEZ QUE O USUÁRIO CLICAR EM UMA TAREFA DIFERENTE!
	Gui, 2: Default
	Gui, 2: ListView, VIEW_TAREFAS
	LV_ModifyCol(1, 50), LV_ModifyCol(2, 120), LV_ModifyCol(3, 110), LV_ModifyCol(4, 220), LV_ModifyCol(5, 140), LV_ModifyCol(6, 80), LV_ModifyCol(7, 500)
	Gui, 2: Add, Text, x40 y280 w660 Center, ANDAMENTOS
	Gui, 2: Add, ListView, x40 y300 w720 r5 Grid vVIEW_ANDAMENTOS, Cód|Data|Hora|Descrição|Novo Status|Observação
	Gui, 2: Default
	Gui, 2: ListView, VIEW_ANDAMENTOS
	LV_ModifyCol(1, 50), LV_ModifyCol(2, 120), LV_ModifyCol(3, 110), LV_ModifyCol(4, 280), LV_ModifyCol(5, 120), LV_ModifyCol(6, 500)
	Gui, 2: Add, GroupBox, x40 y460 w720 h100, NOVO ANDAMENTO
	Gui, 2: Font, s10 w700
	Gui, 2: Add, Text, x60 y480, Descrição
	Gui, 2: Add, Edit, x60 y500 w280 UPPERCASE vDESCRICAO_ANDAMENTO
	Gui, 2: Add, Text, x360 y480, Novo Status
	Gui, 2: Add, Edit, x360 y500 w80 Number Limit3 vSTATUS_ANDAMENTO
	Gui, 2: Add, Text, x460 y480, Observações
	Gui, 2: Add, Edit, x460 y500 w280 UPPERCASE vOBSERVACOES_ANDAMENTO
	Gui, 2: Add, Button, x60 y530 gINCLUIR_ANDAMENTO, INCLUIR ANDAMENTO
	Gui, 2: Add, Button, x580 y530 w160 gFINALIZAR_TAREFA, FINALIZAR TAREFA
	Gui, 2: Tab, 3
	Gui, 2: Add, Text, x40 y60 w660 Center, TAREFAS FINALIZADAS
	Gui, 2: Add, ListView, x40 y80 w720 r8 Grid vVIEW_TAREFAS_FIN gSELECIONAR_TAREFA_FINALIZADA AltSubmit, Cód|Data Inicial|Hora Inicial|Descrição|Responsável|Status|Observação
	Gui, 2: Default
	Gui, 2: ListView, VIEW_TAREFAS_FIN
	LV_ModifyCol(1, 50), LV_ModifyCol(2, 120), LV_ModifyCol(3, 110), LV_ModifyCol(4, 220), LV_ModifyCol(5, 140), LV_ModifyCol(6, 80), LV_ModifyCol(7, 500)
	Gui, 2: Add, Text, x40 y280 w660 Center, ANDAMENTOS TOTAIS
	Gui, 2: Add, ListView, x40 y300 w720 r10 Grid vVIEW_ANDAMENTOS_FIN, Cód|Data|Hora|Descrição|Novo Status|Observação
	Gui, 2: Default
	Gui, 2: ListView, VIEW_ANDAMENTOS_FIN
	LV_ModifyCol(1, 50), LV_ModifyCol(2, 120), LV_ModifyCol(3, 110), LV_ModifyCol(4, 280), LV_ModifyCol(5, 120), LV_ModifyCol(6, 500)
	Gui, 2: Show, w800 h600, Tarefas Atuais
}
Return



; A LABEL ABAIXO É CHAMADA QUANDO O USUARIO CLICA EM UMA ENTRADA NA TABELA DE TAREFAS (POIS FOI COLOCADA COMO G-LABEL DAQUELA TABELA). ELA ATUALIZA A TABELA DE ANDAMENTOS COM AS ENTRADAS CORRESPONDENTE AOS ANDAMENTOS DA TAREFA QUE FOI SELECIONADA QUANDO O USUARIO CLICOU.
SELECIONAR_TAREFA:
If (CHAMAR_EVENTO = "")  ; Devido à opção Alt_Submit, necessária para que a g-label seja chamada ao clique no controle, a g-label é chamada duas vezes. Abaixo, a primeira chamada é descartada.
{
	CHAMAR_EVENTO := 1
	Return
}
If (CHAMAR_EVENTO = 1)
{
	CHAMAR_EVENTO := ""
}
Gui, 2: Default
Gui, 2: Submit, nohide
Gui, 2: ListView, VIEW_TAREFAS
Count := ""
Count := Lv_GetCount("Selected")
If (Count < 1)
{
	Return
}
ControlGet, TAREFA_SELECIONADA, List, Selected, SysListView321, A
StringSplit, TAREFA_SELECIONADA_, TAREFA_SELECIONADA, `t`n
IniRead, ANDAMENTOS, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, ANDAMENTOS
Gui, 2: Default
Gui, 2: ListView, VIEW_ANDAMENTOS
Lv_Delete()
Loop % ANDAMENTOS ; NESTE LOOP ENTRAMOS NOS REGISTROS DO ARQUIVO INI. VEJA QUE O LOOP CORRE POR QUANTOS ANDAMENTOS TEM AQUELA TAREFA (CHAVE ANDAMENTOS DA SEÇÃO DA TAREFA SELECIONADA). CADA ANDAMENTO DEVE TER UMA SEÇÃO PRÓPRIA CUJO NÚMERO É O MESMO NUMERO DA TAREFA E O DECIMAL É O NÚMERO DO ANDAMENTO. ASSIM, SEÇÃO 4.7 É O SÉTIMO ANDAMENTO DA TAREFA 4.
{
	SECAO_PARA_USO := TAREFA_SELECIONADA_1 . "." . A_Index
	IniRead, CODIGO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, CODIGO
	IniRead, DATA, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DATA
	IniRead, HORA, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, HORA
	IniRead, DESCRICAO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DESCRICAO
	IniRead, NOVO_STATUS, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, NOVO_STATUS
	IniRead, OBSERVACAO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, OBSERVACAO
	Gui, 2: Default
	Gui, 2: ListView, VIEW_ANDAMENTOS
	Lv_Add("", CODIGO, DATA, HORA, DESCRICAO, NOVO_STATUS, OBSERVACAO)
}
Return


; ESTA LABEL É SEMELHANTE À LABEL ACIMA, MAS PARA TAREFAS FINALIZADAS.
SELECIONAR_TAREFA_FINALIZADA:
If (CHAMAR_EVENTO = "")  ; Devido à opção Alt_Submit, necessária para que a g-label seja chamada ao clique no controle, a g-label é chamada duas vezes. Abaixo, a primeira chamada é descartada.
{
	CHAMAR_EVENTO := 1
	Return
}
If (CHAMAR_EVENTO = 1)
{
	CHAMAR_EVENTO := ""
}
Gui, 2: Default
Gui, 2: Submit, nohide
Gui, 2: ListView, VIEW_TAREFAS_FIN
Count := ""
Count := Lv_GetCount("Selected")
If (Count < 1)
{
	Return
}
ControlGet, TAREFA_SELECIONADA, List, Selected, SysListView323, A
StringSplit, TAREFA_SELECIONADA_, TAREFA_SELECIONADA, `t`n
IniRead, ANDAMENTOS, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, ANDAMENTOS
Gui, 2: Default
Gui, 2: ListView, VIEW_ANDAMENTOS_FIN
Lv_Delete()

Loop % ANDAMENTOS
{
	SECAO_PARA_USO := TAREFA_SELECIONADA_1 . "." . A_Index
	IniRead, CODIGO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, CODIGO
	IniRead, DATA, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DATA
	IniRead, HORA, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, HORA
	IniRead, DESCRICAO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DESCRICAO
	IniRead, NOVO_STATUS, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, NOVO_STATUS
	IniRead, OBSERVACAO, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, OBSERVACAO
	Gui, 2: Default
	Gui, 2: ListView, VIEW_ANDAMENTOS_FIN
	Lv_Add("", CODIGO, DATA, HORA, DESCRICAO, NOVO_STATUS, OBSERVACAO)
}
Return


; ESTA LABEL É CHAMADA QUANDO O USUÁRIO CLICA NO BOTÃO "SALVAR NOVA TAREFA"
; ELA BASICAMENTE ESCREVE UMA NOVA SEÇÃO NO ARQUIVO INI, CUJO NÚMERO É O NÚMERO MÁXIMO ANTERIOR ADICIONADO DE 1 E AS INFORMAÇÕES SÃO AS QUE O USUÁRIO ESCREVEU NO FORMULÁRIO E AS QUE SÃO
;  COLETADAS AUTOMATICAMENTE (DATA DE INCLUSAO, POR EXEMPLO).
SALVAR_TAREFA:
Msgbox, 0x04, Aviso, Confirma a inclusão da tarefa?
IfMsgbox, No
{
	Msgbox, 0x10, Aviso, Inclusão da tarefa cancelada pelo usuário.
	Return
}
Gui, 2: Submit, Nohide
Gui, 2: Default
Gui, 2: ListView, VIEW_TAREFAS
DATA_INICIAL := A_DD . "/" . A_MM . "/" . A_YYYY
HORA_INICIAL := A_HOUR . ":" . A_MIN
StringReplace, DESCRICAO_NOVA_TAREFA, DESCRICAO_NOVA_TAREFA, `n, %A_Space%, All
StringReplace, OBSERVACAO_NOVA_TAREFA, OBSERVACAO_NOVA_TAREFA, `n, %A_Space%, All

MAXIMA_ENTRADA += 1
IniWrite, %MAXIMA_ENTRADA%, %A_SCriptDir%/BD.bdgt, MAXIMA_ENTRADA, CODIGO

IniWrite, %MAXIMA_ENTRADA%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, CODIGO
IniWrite, %DATA_INICIAL%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, DATA_INICIAL
IniWrite, %HORA_INICIAL%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, HORA_INICIAL
IniWrite, %DESCRICAO_NOVA_TAREFA%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, DESCRICAO
IniWrite, %RESPONSAVEL_NOVA_TAREFA%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, RESPONSAVEL
IniWrite, 0, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, STATUS
IniWrite, NAO, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, FINALIZADA
IniWrite, %OBSERVACAO_NOVA_TAREFA%, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, OBSERVACAO
IniWrite, 0, %A_SCriptDir%/BD.bdgt, %MAXIMA_ENTRADA%, ANDAMENTOS
;MAXIMA_ENTRADA += 1
Lv_Add("", MAXIMA_ENTRADA, DATA_INICIAL, HORA_INICIAL, DESCRICAO_NOVA_TAREFA, RESPONSAVEL_NOVA_TAREFA, 0, OBSERVACAO_NOVA_TAREFA)
ControlSetText, Edit1,
ControlSetText, Edit2,
ControlSetText, Edit3,
Msgbox,, Aviso, Tarefa incluída com sucesso!
Return


; ESTA LABEL TROCA O VALOR DA CHAVE "FINALIZADA" DA SEÇÃO DO ARQUIVO INI CORRESPONDENTE À TAREFA SELECIONADA. DE "NAO" PARA "SIM".
FINALIZAR_TAREFA:
Gui, 2: Default
Gui, 2: Submit, nohide
Gui, 2: ListView, VIEW_TAREFAS
Count := ""
Count := Lv_GetCount("Selected")
If (Count < 1)
{
	msgbox, 0x10, Erro, Selecione uma tarefa na lista de cima para indicar a finalização.
	return
}
ControlGet, TAREFA_SELECIONADA, List, Selected, SysListView321, A
StringSplit, TAREFA_SELECIONADA_, TAREFA_SELECIONADA, `t`n
msgbox, 0x4, Aviso, Confirma a finalização da tarefa %TAREFA_SELECIONADA_1%?
IfMsgbox, No
{
	Msgbox, 0x1, Aviso, Finalização cancelada pelo usuário.
	Return
}
IniWrite, SIM, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, FINALIZADA
LINHA_A_EXCLUIR := Lv_GetNext(0)
Lv_Delete(LINHA_A_EXCLUIR)
Gui, 2: ListView, VIEW_TAREFAS_FIN
Lv_Add("", TAREFA_SELECIONADA_1, TAREFA_SELECIONADA_2, TAREFA_SELECIONADA_3, TAREFA_SELECIONADA_4, TAREFA_SELECIONADA_5, TAREFA_SELECIONADA_6, TAREFA_SELECIONADA_7)
Gui, 2: ListView, VIEW_ANDAMENTOS
Lv_Delete()
Msgbox, 0x1, Aviso, Tarefa finalizada com sucesso!
Return



; ESTA LABEL CRIA UMA NOVA SEÇÃO NO ARQUIVO INI CUJO NUMERO É IGUAL AO DA TAREFA SELECIONADA E CUJO DECIMAL É 1 MAIOR QUE O NÚMERO DE ANDAMENTOS ANTERIOR DAQUELA TAREFA. ELA TAMBÉM ATUALIZA O NUMERO DE ANDAMENTOS INDICADO NA SECAO DA TAREFA, ADICIONANDO 1 A ELE.
INCLUIR_ANDAMENTO:
Gui, 2: Default
Gui, 2: Submit, nohide

If (DESCRICAO_ANDAMENTO = "")
{
	Msgbox, 0x10, Erro, Informe uma descrição para este andamento.
	Return
}

If (STATUS_ANDAMENTO > 100)
{
	Msgbox, 0x10, Erro, O novo status informado deve ser um número entre 0 e 100.
	Return
}

If (STATUS_ANDAMENTO = "")
{
	Msgbox, 0x10, Erro, Informe o novo status da tarefa mediante este andamento!
	Return
}

Gui, 2: ListView, VIEW_TAREFAS
Count := ""
Count := Lv_GetCount("Selected")
If (Count < 1)
{
	msgbox, 0x10, Erro, Selecione uma tarefa na lista de cima na qual queira incluir o andamento.
	return
}
ControlGet, TAREFA_SELECIONADA, List, Selected, SysListView321, A
StringSplit, TAREFA_SELECIONADA_, TAREFA_SELECIONADA, `t`n

IniRead, ANDAMENTOS_ATUAIS, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, ANDAMENTOS

PROXIMO_ANDAMENTO := ANDAMENTOS_ATUAIS + 1
SECAO_PARA_USO := TAREFA_SELECIONADA_1 . "." . PROXIMO_ANDAMENTO
IniWrite, %PROXIMO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, CODIGO
DATA_DO_ANDAMENTO := A_DD . "/" . A_MM . "/" . A_YYYY
IniWrite, %DATA_DO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DATA
HORA_DO_ANDAMENTO := A_Hour . ":" . A_Min
IniWrite, %HORA_DO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, HORA
IniWrite, %HORA_DO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, HORA
IniWrite, %HORA_DO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, HORA
IniWrite, %DESCRICAO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, DESCRICAO
IniWrite, %STATUS_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, NOVO_STATUS
IniWrite, %OBSERVACAO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %SECAO_PARA_USO%, OBSERVACAO

; TAMBEM ATUALIZAMOS DUAS CHAVES DA SECAO DA TAREFA
IniWrite, %PROXIMO_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, ANDAMENTOS
IniWrite, %STATUS_ANDAMENTO%, %A_SCriptDir%/BD.bdgt, %TAREFA_SELECIONADA_1%, STATUS

Gui, 2: ListView, VIEW_ANDAMENTOS
Lv_Add("", PROXIMO_ANDAMENTO, DATA_DO_ANDAMENTO, HORA_DO_ANDAMENTO, DESCRICAO_ANDAMENTO, STATUS_ANDAMENTO, OBSERVACAO_ANDAMENTO)
Gui, 2: ListView, VIEW_TAREFAS
Lv_Modify(Lv_GetNext(0), "Col6", STATUS_ANDAMENTO)
Msgbox, 0x1, Aviso, Andamento incluído com sucesso.
Return



; ESTA LABEL EXECUTA QUANDO O USUÁRIO OU O PROGRAMA FECHA A TELA 1. ELA APENAS TERMINA O PROGRAMA (SE O USUARIO FECHOU) OU DESTROI A TELA 1 (SE O PROGRAMA FECHOU PARA ABRIR A TELA 2).
GuiClose:
IfWinNotExist, Tarefas Atuais
{
	ExitApp
}
Gui, 1: Destroy
Return


; ESTA LABEL EXECUTA QUANDO O USUARIO FECHA A TELA 2. ELA APENAS DESTROI A TELA 2 E DEPOIS REINICIA O PROGRAMA.  PARA FECHAR O PROGRAMA, O USUARIO DEVE FECHAR A TELA 1 CLICANDO NO X.
2GuiClose:
Gui, 2: Destroy
Reload
Return

5. Considerações Finais

Se você dedicou um pouco de ler o código do programa acima e a testar o programa, deve ter aprendido um monte de coisas! Aposto que muita coisa que coloquei nesse código você não sabia ainda (por exemplo, como fazer para atualizar uma tabela com base no clique em outra tabela). Talvez essa questão da quantidade de informações novas para fazer esse programa tenha lhe assustado um pouco, mas não se preocupe: todos os comandos escritos podem ser buscados no arquivo de ajuda e aprendidos! Em programação nós nunca saberemos fazer absolutamente tudo, e ter contato com códigos novos é importante para aumentar nossa bagagem de conhecimento. Se você estudar o código acima, poderá ver e aprender muita coisa, e quando estiver projetando outro programa, poderá usar o que aprendeu para melhorar o seu programa!

Este código tem o objetivo de consolidar as informações do últimos tutoriais. Acredito que com ele estamos muito perto de concluir esta série de tutoriais básicos de programação em AutoHotkey. Dos principais conceitos da linguagem, a maioria já foi explicada. O que achou de nossa jornada até aqui? Vale a pena dedicar um tempo diário a aprender coisas novas não é?

:arrow: Ah, um detalhe! algumas das ideias que escrevemos no tutorial não foram implementadas ainda no código. Esse será o seu dever de casa: para consolidar seu conhecimento adicione ao programa o código de controle das datas finais das entregas das tarefas, a contagem de prazos restante, e o campo para indicação da prioridade da tarefa. Dica: Você deve lembrar que tem de alterar o código de criação da tabela, o código de busca dos dados no arquivo, o código de inserção dos dados na tabela e também os códigos que inserem os dados no arquivo quando do cadastro da nova tarefa. Mas como o código está organizado, você poderá encontrar facilmente as linhas correspondentes a cada caso se olhar os nomes da labels e funções!

Parabéns pela dedicação e vamos em frente :thumbup:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 21 May 2018, 13:58

Reservado.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 21 May 2018, 13:58

IX. Paradigmas (estilos) de programação: Programação Orientada a Objetos (OOP)

Olá :)

Estamos chegando ao fim de nossa série de tutoriais básicos de programação. Ainda há muito a ser explorado no assunto programação, mas acredito que já cobrimos uma boa parte do básico. Dessa forma, saiba que você já viu tudo o que precisa para iniciar o desenvolvimento de programas no AutoHotkey.

Digo isto porque o normal é iniciar a programação neste nível de conhecimento mesmo, e depois o resto do conhecimento virá a ser agregado com o tempo e experiência. A partir daqui vá em frente, mas nunca pare de estudar e buscar novas ferramentas, novos comandos, novas funções, e ler scripts escritos por outros usuários, estudar conceitos novos e etc. É assim que você irá longe nessa carreira.

Este tutorial tem por objetivo demonstrar que, embora já possamos criar programas da forma como aprendemos a fazê-lo, existem outras formas também. Por isso, vamos falar um pouco sobre os dois principais tipos (ou paradigmas) de programação para os quais o AutoHotkey oferece suporte.

A propósito, você sabia que existem diferentes tipos de programação (Paradigmas de como se programa, na verdade)?

Vamos conhecer isso melhor agora :thumbup:

1. Tipos de programação: como assim?

No primeiro tutorial, aprendemos os conceitos de automação e programação, e vimos as suas diferenças. Agora vamos dividir este conceito de programação em paradigmas (ou estilos) para discernirmos algo a mais.

Se você observar a forma como escrevemos nossos programas até aqui, verá que escrevemos tudo linha a linha, através de comandos, rotinas, funções, labels e outras ferramentas, e que criamos os nossos programas escrevendo basicamente as interações entre esses elementos. Isso é uma paradigma (uma forma) de programação chamada programação procedural. O que define ela é exatamente isso: foco no passo-a-passo, através de rotinas pensadas cada uma de forma individual. Mas existem outras formas de programação, e o que quero dizer com essa frase é isso: A forma como pensamos um programa pode ser diferente.

Vou demonstrar isso explicando uma segunda forma (ou paradigma) de programação para a qual o AutoHotkey oferece suporte, que é a Programação Orientada a Objetos (Object Oriented Programming ou simplesmente OOP, em inglês). Essa forma de programação difere bastante da programação procedural que aprendemos até aqui, e embora não possamos dizer que uma seja melhor do que a outra, vamos evoluir bastante se aprendermos as duas, pois como veremos adiante, mudar o paradigma pode sim trazer vantagens em alguns casos.

2. Programação Procedural e Programação Orientada a Objetos (OOP)

Antes de discernirmos as duas, convém dizer que até agora nestes tutoriais, nós utilizamos basicamente somente a Programação Procedural. Para descrever o que isso significa, vamos ver um caso prático: a programação de um jogo. Vou começar planejando este jogo através do paradigma procedural e depois, vamos planejá-lo de outra forma a partir do paradigma dos objetos.

Vamos lá :thumbup:

Neste jogo, conforme minha ideia, terei personagens que devem interagir com um mundo artifical de diversas formas. Imagine que um desses personagens é o João. João é um jogador de futebol (e nosso jogo é um jogo de futebol). Para trazer joão à realidade do mundo do jogo, concretizando minha ideia em um programa, preciso definir o que é o João nesse contexto. Ora, como já disse, joão é um jogador (e não uma bola ou uma trave). E um jogador, neste mundo virtual, tem algumas características. Primeiro, ele tem uma cor de camisa, uma cor de calção, e até uma cor de chuteira, pois é assim que os times se diferenciam. Além disso, como ele é um esportista, ele deve também ter algumas habilidades pessoais para o jogo. Dessa forma, precisamos diferenciá-lo em relação aos outros jogadores também por algumas características não-físicas, como velocidade, estamina e posição de jogo (atacante, zagueiro, goleiro) e etc.

Para trazer todas essas características ao programa, eu preciso primeiro definir variáveis para cada uma delas. Por exemplo:

Code: Select all

Tipo := "Jogador"
Velocidade := 90
Estamina := 50
Posição := "Zagueiro"
Camisa := "Amarelo"
Calcao := "Azul"
Chuteira := "Branca"
Até aí tudo bem. Agora vamos imaginar que além de características, um jogador precisa realizar ações neste mundo virtual. Ele deve ser capaz de, por exemplo, mudar sua posição no campo, se aproximando ou se afastando do gol. A posição de João em qualquer momento também pode ser guardada em variáveis, como fizemos anteriormente, mas a ação de mudar a posição é outra história: para trazer isso ao programa, preciso de rotina, como uma função.

Assim, imagino que o campo de futebol é um campo com duas coordenadas (X e Y), onde o eixo Y é a distância entre os dois gols e o eixo X é a distância entre as linhas laterais do campo. Dessa forma, imagino inicialmente a ação de mudança de posição como:

Code: Select all

Mudar_a_posicao(Pos_X_anterior, Pos_Y_anterior)
{
Pos_X_Novo := Pos_X_Anterior + 1
Return Pos_X_Novo
}
Ocorre que, olhando bem essa função, vejo que ela só permite a João se delocar em uma única direção e em um único sentido (aumentando o X) e João deve ser capaz de realizar vários movimentos (para frente, para trás, para um lado e para o outro), assim a função a ser escrita vai ter que se tornar um pouco mais complexa (ou então vamos ter que criar várias funções). Se eu fizer isso através de várias funções, acredito que uma delas pode ser chamada de aproximar do gol e a outra seria afastar-se do gol, por exemplo. As outras duas seriam então aproximar-se do lado esquerdo e do lado direito.

Code: Select all

Aproximar_do_gol(Pos_X_anterior, Pos_Y_anterior)
{
Pos_Y_Novo := Pos_Y_Novo + 1
Return Pos_Y_Novo
}

Afastar_se_do_gol(Pos_X_anterior, Pos_Y_anterior)
{
Pos_Y_Novo := Pos_Y_Novo - 1
Return Pos_Y_Novo
}

Aproximar_se_do_lado_esquerdo(Pos_X_anterior, Pos_Y_anterior)
{
Pos_X_Novo := Pos_X_Anterior - 1
Return Pos_X_Novo
}

Aproximar_se_do_lado_direito(Pos_X_anterior, Pos_Y_anterior)
{
Pos_X_Novo := Pos_X_Anterior + 1
Return Pos_X_Novo
}
Pronto! agora João pode se mover pelo campo livremente (1 pixel por movimento).

Mas tem um problema. Não estamos considerando a velocidade de joão. A velocidade vai ser um problema aqui, pois cada jogador tem a sua. Como posso fazer para que ela afete a mudança de posição do jogador?

Ora, pensando bem, eu ainda não defini o tamanho do campo. Assim, penso agora que o campo deve ter uma dimensão em pixels bem grande, para que o jogador precise se mover muito até chegar ao outro lado. E nessa dimensão, também posso fazer com que um único movimento resulte em um deslocamento de vários pixels, desde que o campo seja grande o bastante. Assim, posso fazer com o que o valor em pixels do deslocamento de um único movimento seja exatamente a velocidade do jogador.

Code: Select all

Aproximar_do_gol(Pos_X_anterior, Pos_Y_anterior, Velocidade)
{
Pos_Y_Novo := Pos_Y_Novo + (1 * velocidade)
Return Pos_Y_Novo
}
Assim, joão, cuja velocidade é 90, se move 90 pixels em um único movimento, precisando de vários movimentos para atravessar o campo. Da mesma forma, um jogador com uma velocidade de 80 precisa de mais movimentos ainda (sendo portanto mais lento) e um jogador com velocidade 100 seria mais rápido.

:arrow: Continuando por este caminho, vamos programar todas as situações possíveis para joão, ou seja, todas as suas características e as sua ações que não comentamos ainda, como chutar a bola, imprimir uma velocidade ao chute, etc, etc, etc.... É importante termos em mente que se seguirmos fazendo isso passo-a-passo, vamos conseguir fazer nosso jogo. Mas temos que ter em mente uma coisa antes de continuarmos a programar da forma como temos feito: joão é somente um dos jogadores. E existem vários outros em um time: José, Ronaldo, Roberto carlos, etc.

Se nós focarmos em fazer tudo pensando no programa de forma individual e sequencial, como fizemos até agora com a programação de João, enfrentaremos um problema sério logo logo. Para entendermos que problema é esse, imagine que depois de terminar João, vamos ter que iniciar a escrita das características de José, por exemplo, que é outro jogador, e assim vamos perceber que teremos que copiar a colar um monte de código e ainda que alterar muita coisa do que foi escrito até que cada jogador seja diferenciado corretamente do outro.

Ou seja, seguindo essa estratégia, atualizar o código que já tínhamos vai dar muito trabalho.

Basta ver quanto coisa vou ter que escrever para determinar as características (fora as ações) de apenas 4 (quatro) jogadores:

Disso:

Code: Select all

Tipo := "Jogador"
Velocidade := 90
Estamina := 50
Posição := "Zagueiro"
Camisa := "Amarelo"
Calcao := "Azul"
Chuteira := "Branca"
Vou ter que fazer isso:

Code: Select all

Joao_Tipo := "Jogador"
Joao_Velocidade := 90
Joao_Estamina := 50
Joao_Posição := "Zagueiro"
Joao_Camisa := "Amarelo"
Joao_Calcao := "Azul"
Joao_Chuteira := "Branca"

Jose_Tipo := "Jogador"
Jose_Velocidade := 80
Jose_Estamina := 50
Jose_Posição := "Meio de Campo"
Jose_Camisa := "Amarelo"
Jose_Calcao := "Azul"
Jose_Chuteira := "Branca"

Ronaldo_Tipo := "Jogador"
Ronaldo_Velocidade := 90
Ronaldo_Estamina := 60
Ronaldo_Posição := "Atacante"
Ronaldo_Camisa := "Amarelo"
Ronaldo_Calcao := "Azul"
Ronaldo_Chuteira := "Branca"


Roberto_Carlos_Tipo := "Jogador"
Roberto_Carlos_Velocidade := 70
Roberto_Carlos_Estamina := 50
Roberto_Carlos_Posição := "Meio de Campo"
Roberto_Carlos_Camisa := "Amarelo"
Roberto_Carlos_Calcao := "Azul"
Roberto_Carlos_Chuteira := "Branca"
Veja que fomos levados a copiar e reescrever muita coisa! Isso dá bastante trabalho. Imagine fazer isso para mais dezenas de outros jogadores! :crazy:

Além disso, imagine que decidamos mais tarde que queremos mudar algumas coisas em relação aos jogadores. Por exemplo, imagine que decidamos que cada jogador terá duas cores na camisa. Teremos que procurar todas as linhas das variáveis camisa entre centenas ou milhares e alterá-las uma a uma. Isso vai dar muito trabalho!

Mas será que não existem outras formas de criamos esse jogo sem ter que escrever tanto? Talvez haja sim. Vamos tentar imaginar como podemos mudar a forma como estamos programando este jogo de forma a facilitar as coisas. Primeiramente, vejamos que cada jogador tem basicamente características e ações. Todos os jogadores têm isso. E são bem parecidas na verdade, só mudando o valor. Assim, se pararmos para pensar um pouco antes de ficar escrevendo e escrevendo tudo individualmente, veremos que as semelhanças entre alguns elementos do programa podem ser usadas como uma estratégia para facilitar a criação dos jogadores, desde que pensemos nele como um conjunto e não como algo individual

Assim, tenho a seguinte ideia: Vamos criar uma única função que servirá para criar vários jogadores!

Code: Select all

CRIAR_JOGADOR("Joao", 90, 50, "Zagueiro", "Amarelo", "Azul", "Branca")
CRIAR_JOGADOR("Jose", 80, 50, "Meio de Campo", "Amarelo", "Azul", "Branca")
Return

CRIAR_JOGADOR(Nome, Tipo, Velocidade, Estamina, Posicao, Camisa, Calcao, Chuteira)
{
%Nome%_Tipo := Tipo
%Nome%_Velocidade := Velocidade
%Nome%_Estamina := Estamina
%Nome%_Posicao := Posicao
%Nome%_Camisa := Camisa
%Nome%_Chuteira := Chuteira
}
Ok! Agora será bem mais fácil criar dezenas de jogadores, e teremos ainda mais uma vantagem: alterar a forma como definimos a camisa dos jogadores também ficou mais fácil, já que as linhas das chamadas estão próximas e a função é uma só.

:arrow: Que tal parar um pouco agora e pensar ainda mais sobre a estratégia de programação que usamos aqui? Veja que basicamente nós conseguimos facilitar a nossa vida quando usamos uma sintaxe que melhor agregou o que os jogadores tinham em comum. Foi isso que facilitou nossa vida. E fizemos isso simplesmente entendendo primeiramente o que todos os jogadores têm em comum, de modo que os nomes das linhas de criação das variáveis puderam ser reaproveitadas em uma única função, o que nos permitiu criar vários jogadores trocando apenas os valores de cada um nas chamadas da função.

Assim, vamos falar agora (finalmente) sobre o que é o paradigma da Programação Orientada a Objetos (OOP).

3. O paradigma de Criar Programas Orientado pelo Conceito de Objetos

A Programação Orientada a Objetos é outra forma de programar que o AutoHotkey oferece a você. Ela faz basicamente a mesma coisa que acabamos de fazer para facilitar a criação do nosso jogo e tem exatamente o mesmo intuito: agregar o que há de comum entre os elementos do programa, de modo a permitir uma grande reutilização do que foi escrito. Só que a OOP faz isso mudando um pouco a forma como enxergamos certos aspectos da programação, utilizando-se de elementos de sintaxe próprios que facilitam e incentivam os agrupamentos de características e ações. Assim, seu objetivo é permitir que adotemos uma postura diferente desde a hora de iniciarmos o planejamento do nosso programa.

Dessa forma, ao invés de nos preocuparmos com cada passinho individual, como fizemos lá no inicio do nosso planejamento do código do jogo com a programação procedural, vamos nos preocupar desde o início em programar todos os passos do programa pensando em conjuntos, valendo-nos de conceitos como classes, objetos e métodos com o objetivo simples de reaproveitar ao máximo possível os conjuntos criados.

Assim, veremos agora uma série de novos elementos de sintaxe que têm o objetivo de nos ajudar a fazer isso. Vamos conhecê-los?

4. Classes, objetos e métodos

Imagine o conceito de objeto como sendo uma unidade mista de características e de ações. Esse conceito tem tudo a ver com o mundo real, afinal, podemos encontrar nos objetos ao nosso redor esses dois elementos (características e ações) quase sempre reunidos em conjunto, e não soltos ou independentes.

Tomemos como exemplo o mouse do computador. Ele tem características: tem uma cor, um conector que pode ser USB ou PS2, um fio ou um receptor wireless, pode ser grande ou pequeno, pode ter 3 botões ou até mais de 10... Além disso, ele pode realizar algumas ações: Pode enviar um sinal de clique esquerdo, pode enviar um sinal de clique direito, pode enviar um sinal de mudar a posição da seta mais para baixo...

Assim, podemos dizer que pensando um pouco, conseguimos enxergar um conceito abstrato de mouse, que vai se aplicar a praticamente todos os de mouses. Essas características e ações que são comuns a todos (ou quase todos) os mouses formam o que podemos chamar de a classe Mouse.

A classe Mouse é basicamente uma ideia abstrata, porém racionalmente formulada, do que é um mouse. A partir dela, poderemos criar um número grande de mouses diferentes, simplesmente aproveitando tudo o que eles tem de semelhante da própria classe Mouse e depois indicando somente o que eles têm de diferente individualmente. Assim, a classe é uma ideia abstrata sobre um tipo de objeto (como "mouse" na forma genérica da palavra), e um objeto é a realização da ideia da classe em uma unidade (aquele mouse especificamente, com 5 botões, cor vermelha, sem fio...)

Está confuso? :crazy:

Não se preocupe! Basta pensarmos no exemplo dos nossos jogadores!

:arrow: Todos os jogadores que criamos até agora são unidades mistas de características (que guardamos em variáveis) e de ações (que programamos com funções) e têm alguns elementos em comum: Todos eles podem se movimentar no campo através de uma única fórmula que considera as velocidades individuais, e todos eles também partilham características comuns (como a camisa amarela). Assim, podemos definir uma classe de objetos chamada "jogador" e elencar as características comuns entre eles. Também podemos aproveitar para criar características padrão nesta classe, de forma que mesmo que elas variem entre alguns objetos (jogadores), a maioria vai se aproveitar dos padrões e você não terá que indicar muitas diferenças.

Perceba no código a seguir como a criação da classe jogador me permite criar os quatro objetos jogadores (João, José, Ronaldo e Roberto_Carlos) de forma fácil, sem precisar reescrever muita coisa.

Code: Select all

Joao := New Jogador()

Jose := New Jogador()
Jose.Velocidade := 80
Jose.Posicao := "Meio de Campo"

Ronaldo := New Jogador()
Ronaldo.Estamina := 60
Ronaldo.Posicao := "Atacante"

Roberto_Carlos := New Jogador()
Roberto_Carlos.Velocidade := 70
Ronaldo.Posicao := "Meio de Campo"


Msgbox % Ronaldo.Camisa ; Camisa Amarelo, pois o padrão da classe foi aproveitado!
Msgbox % Ronaldo.Estamina ; Estamina 60, pois a diferença de estamina foi indicada.

Msgbox % Ronaldo.Pos_Y ; A posicao Y inicial de ronaldo é 20.
Ronaldo.Aproximar_Do_Gol() ; Agora, chamamos uma das ações (chamadas de métodos na sintaxe OOP) que o objeto ronaldo herdou da classe jogador, de modo a mudar a posicao Y de ronaldo.
Msgbox % Ronaldo.Pos_Y ; E então, a posição Y de ronaldo passa a ser 21. (Perceba que assim como ronaldo, todos os outros jogadores herdaram essa açõe, e podemos chamá-la para qualuqer deles)
Msgbox % Joao.Pos_Y ; E veja que a de Joao continua 20, pois os objetos são independentes!

Return
Class Jogador
{
	Tipo := "Jogador"
	Velocidade := 90
	Estamina := 50
	Posição := "Zagueiro"
	Camisa := "Amarelo"
	Calcao := "Azul"
	Chuteira := "Branca"
	Pos_X := 20
	Pos_Y := 20
	
	Aproximar_Do_Gol()
	{
		this.Pos_Y := this.Pos_Y + 1
	}
	
	Afastar_se_do_gol()
	{
		this.Pos_Y := this.Pos_Y - 1
	}
	
	Aproximar_se_do_lado_esquerdo()
	{
		this.Pos_X := this.Pos_X - 1
	}
	
	Aproximar_se_do_lado_direito()
	{
		this.Pos_X := this.Pos_X + 1
	}
}
Se você observou e executou o código acima, deve ter visto que uma vez criada a classe, só foi preciso indicar velocidade e posição para que o jogador josé estivesse completo. Isso significa que através de somente essas 3 linhas:

Code: Select all

Jose := New Jogador()
Jose.Velocidade := 80
Jose.Posicao := "Meio de Campo"


José já tem cor de camisa, posição de jogo, estamina e inclusive pode se mover pelo campo considerando a sua velocidade. Ele herdou tudo isso da classe jogador. Além disso, sua velocidade e posição são únicas e diferem das dos outros jogadores porque nós podemos alterar livremente o objeto que foi criado a partir da classe, dando-lhe suas particularidades. Compare isso com a quantidade de linhas e de caracteres que tivemos que escrever antes para atribuir todas as características a José.

Como utilizamos no código acima alguns elementos de sintaxe próprios de OOP no AutoHotkey, vou explicar o que fizemos nas linhas do código:
  • 1. Criamos uma classe jogador, que continha uma ideia abstrata de jogador, com as características e ações mais comuns que um jogador pode possuir.
  • 2. Usamos a classe jogador para criar 4 (quatro) objetos jogadores distintos: Joao, Jose, Ronaldo e Roberto_Carlos. Fizemos isso usando o elemento de sintaxe New. Assim, Cada criação só tomou uma linha e isso foi o suficiente para que o jogador herdasse várias características e ações padrão, sendo um jogador completo desde o início.
  • 3. Alteramos algumas características de alguns jogadores. Veja que só alteramos o que realmente quisemos alterar: os padrões nos ajudaram em não ter que indiciar tudo novamente!
  • 4. Exibimos algumas características do objeto Ronaldo (pertencente à classe jogador), sendo uma herdada do padrão (camisa) e outra alterada por nós (estamina).
  • 5. Executamos uma ação do objeto Ronaldo (aproximar_do_gol), de modo que a posicao Y de ronaldo foi modificada de 20 para 21. (a dos outros jogadores permanceu como estava!)
Já consegue perceber o quanto a OOP, enquanto paradigma de programação, pode facilitar nossa vida se adotada desde o começo do planejamento? :beer:

:arrow: Veja no código acima que nos referimos às variáveis e métodos dos objetos ("método" é o termo como nos referimos às funções de objetos e classes). A sintaxe é simples: primeiro criamos um objeto indicando a classe através a palavra-chave New. Depois, trabalhamos as variáveis e métodos escrevendo o nome do objeto, seguido de um ponto, seguido do nome do método ou variável.

Você viu também como utilizamos o this dentro dos métodos (funções) para dizer que nos referíamos à variável do próprio objeto? Estes elementos de sintaxe são apenas alguns dos que encontramos quando programamos em OOP usando o AutoHotkey. Saiba que além deles, existe uma série de métodos (funções de objetos) que o AutoHotkey embute implicitamente em cada objeto que cria, e que esses métodos estão todos documentados no arquivos de ajuda do AutoHotkey, e que eles podem te ajudar bastante a programar usando OOP. Para este tutorial básico, no entanto, o objetivo não é explicar todos esses elementos de sintaxe, mas sim os fundamentos da OOP. De qualquer forma, saiba que essas ferramentas existem e que você pode consultá-las nos arquivos de ajuda do AutoHotkey relativos a objetos.

Assim, vamos a um outro tópico que também importa comentar!

5. Programação procedural VS Programação Orientada a Objetos

Bom, agora que já demos alguns exemplos e explicações sobre OOP, você deve estar se perguntando: Se a OOP é mais vantajosa que a programação procedural, porque ainda usamos programação procedural? A resposta é a OOP não é necessariamente mais vantajosa, isso vai depender de como você utiliza cada paradigma (procedural ou OOP).

Em primeiro lugar, cumpre reconhecer que praticamente tudo o que pode ser feito através de OOP pode também ser feito através de programação procedural (e vice-versa). Dessa forma, a OOP não vai trazer uma vantagem no quesito possibilidades, pois o grande ganho está simplesmente em uma nova abordagem da forma com a qual pensamos em realizar as tarefas através da programação. Assim, as duas formas são na verdade diferentes paradigmas de programação, ou seja, modelos de como fazer programação de sistemas, e uma não é necessariamente melhor do que a outra. Existem programadores que utilizam somente programação procedural e conseguem chegar a um alto nível de reutilização do código sem precisar dos elementos de sintaxe próprios da OOP.

Algumas linguagens, como o java, Javascript e etc, forçam o programador a adotar o paradigma de OOP. Isso quer dizer que a sintaxe dessas linguagens está intrinsecamente relacionada com este paradigma, de modo que é praticamente impossível programar nelas sem ter noções de OOP. No AutoHotkey a história é diferente e atualmente a disposição é a seguinte:
  • Versão 1.0 (também chamada Basic, o antigo ramo principal do AutoHotkey, não é mais atualizado): Não havia elementos de OOP. Era uma linguagem quase que puramente procedural.
  • Versão 1.1 (Também chamada _L, que é o ramo principal atualmente e ainda está sendo atualizada e desenvolvida constantemente): Foram incluídos elementos de OOP e a linguagem permite tanto a programação procedural quanto a programação com elementos de OOP.
  • Versão 2.0 (Em desenvolvimento e atualmente em estado beta): A sintaxe será fortemente direcionada aos conceitos de OOP.
Assim, é interessante que aprendamos a programar através de sintaxe OOP por várias razões, visto que como descrito neste tutorial, conhecer outro paradigma de programação válido pode facilitar a criação de programas e também vai nos dar uma proximidade com a versão 2.0 do AutoHotkey e uma facilidade de aprender outras linguagens de programação mais à frente.

6. Considerações finais

Este tutorial na verdade foi bastante resumido. Tem muitos conceitos de OOP que o AutoHotkey adota que não entramos em detalhe aqui (propriedades, métodos embutidos, etc). Se você se interessou por Programação Orientada a Objetos, sinta-se livre para aprender mais consultando os arquivos de ajuda do AutoHotkey ou perguntando neste tópico ou no fórum Eu Preciso de Ajuda.

Um forte abraço e até a próxima :thumbup:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Gio » 12 Jul 2018, 17:14

Reservado.
Ardente07
Posts: 5
Joined: 23 Apr 2019, 14:35

Re: Tutoriais Básicos de Programação em AutoHotkey!

Post by Ardente07 » 13 May 2019, 13:35

Estranho, sempre que você reserva vem um novo tutorial, mas já vai fazer um ano e nada do tópico X. :(
Sou fã do seu trabalho, pelo menos nos dê um gostinho do tópico X, faz um especial, por favor. :ugeek:
Post Reply

Return to “Tutoriais”