Loop com CheckBox

Tire suas dúvidas sobre programação em AutoHotkey

Moderator: Gio

Eldorado
Posts: 7
Joined: 24 Oct 2018, 08:53

Loop com CheckBox

24 Oct 2018, 10:28

Meu Loop só funciona uma vez após clicar no checkbox

Code: Select all

my_picturefile = %A_Temp%\lol.jpg
FileInstall, lol.jpg, %my_picturefile%, 1
Gui, Add, Picture,w454 h379, %my_picturefile%

Gui, Add, CheckBox, x36 y156 w60 h20 vAnti_Idle gChkAnti_Idle_onClick, Anti-Idle
Gui, Add, Text, x136 y106 w30 h0 , Text
; Generated using SmartGUI Creator 4.0
Gui, Show, x131 y91 h379 w454, XXXXXXX
Return


ChkAnti_Idle_onClick: 
Sleep, 1500
Loop, 2  
{
GuiControlGet, Anti_Idle
		If(Anti_Idle)
			{			
				Send, {f1}
			}
		
		Else{
	

			}
}
Return


GuiClose:
ExitApp
Last edited by Eldorado on 25 Oct 2018, 10:00, edited 1 time in total.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Loop com CheckBox

24 Oct 2018, 11:07

Bom dia Eldorado.

Seja bem-vindo ao fórum da comunidade do AutoHotkey.

Trocando o comando Send, {f1} pelo comando msgbox % "TESTE", vejo que a linha em questão está sendo executada 2 vezes sim. No entanto, tenho algumas observações a fazer sobre o seu código:

O Sleep está fora do bloco do loop, o que significa que a rotina espera 1,5 segundos e depois executa os dois Send F1 imediatamente um após o outro. Muitos programas ignoram sinais de teclas que tenham sido emitidos muito rapidamente em sucessão e talvez seja isso que está ocorrendo. Se você deseja esperar 1,5 segundo antes de executar o segundo Send F1, o comando Sleep, 1500 deverá ser trago para dentro do bloco do loop.

:arrow: Dica: uma forma de saber se a rotina está executando da forma esperada é executar o script e durante a sua execução clicar com o botão direito do mouse no ícone de H verde que fica na bandeja do tray e depois clicar em Open (o ícone de H verde fica no canto inferior direito da tela, e as vezes fica escondido dentro da setinha que tem lá). Quando você clica em Open, uma janela se abrirá com uma descrição das últimas linhas executadas. Quando executo o seu script, clico no checkbox e abro essa tela, ela me mostra que de fato a linha Send F1 foi executada 2 vezes.

Espero ter ajudado, se precisar de mais ajuda, basta postar abaixo :thumbup:
Eldorado
Posts: 7
Joined: 24 Oct 2018, 08:53

Re: Loop com CheckBox

24 Oct 2018, 14:12

Agradeço pelo feedback, e agora colocando o Sleep dentro funcionou.
Seguindo meu programa criei um outro checkbox para outra funcionalidade e preciso que as duas rodem junto quando ambas estiverem marcadas
Mas pelo que observei no código o meu Loop não permite que a outra rode até acabar a quantidade de vezes do loop referente ao outro checkbox.

EU preciso fazer várias funcionalidades que rodem junto, como Anti-Idle, Rune e Outra com click do mouse, e para cada uma colocarei um checkbox, porém não sei como fazer uma lógica sem utilizar o loop.

Tentei envolver todo o código dentro de um loop, mas ele só roda 1vez, coloquei sleep pra evitar um crash.

Code: Select all

; my_picturefile = %A_Temp%\lol.jpg
FileInstall, lol.jpg, %my_picturefile%, 1
Gui, Add, Picture,w454 h379, %my_picturefile%

Gui, Add, CheckBox, x36 y156 w60 h20 vAnti_Idle gChkAnti_Idle_onClick, Anti-Idle
Gui, Add, Text, x136 y106 w30 h0 , Text

Gui, Add, CheckBox, x120 y156 w60 h20 vRune gChkRune_onClick, Rune
Gui, Add, Text, x136 y106 w30 h0 , Text

; Generated using SmartGUI Creator 4.0
Gui, Show, x131 y91 h379 w454, XXXXXXX
Return

Loop, 999 {
Sleep 500

; CheckBox de Runar
ChkRune_onClick:
Sleep 2000
GuiControlGeT, Rune
		if(Rune)
		    {
				Send, {f1}
				Sleep 500
			}
		Else{
		}
	
; CheckBox do Anti-Idle
ChkAnti_Idle_onClick: 
Sleep 2000	
GuiControlGet, Anti_Idle
		If(Anti_Idle)
			{			
				Send, ^{Up}
				Sleep 500
				Send, ^{Down}
				Sleep 500
			}		
		Else{
		}
Return
}

GuiClose:
ExitApp
Last edited by Eldorado on 25 Oct 2018, 10:00, edited 1 time in total.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Loop com CheckBox

24 Oct 2018, 16:16

EU preciso fazer várias funcionalidades que rodem junto...
(...)
Mas pelo que observei no código o meu Loop não permite que a outra rode até acabar a quantidade de vezes do loop referente ao outro checkbox.
Você vai precisar modificar a lógica do seu código para que isso aconteça. No momento, ao clicar na checkbox (este clique é o gatilho atual) o script executa uma label que contém um loop que checa apenas o estado daquela checkbox e roda um loop se aquela checkbox estiver marcada.

Você pode fazer:
1. O mesmo loop checar o estado de mais de uma checkbox e realizar todas as ações correspondentes a todas checkboxes que estiverem marcadas em ordem.
2. Todas as checkbox executarem a mesma g-label OU o mesmo código ser executado em várias g-labels (basta colocar os nomes das g-label um encima do outro).
3. Se as quantidades de loop forem diferentes para cada ação, você também pode adicionar condicionais que checam a iteração atual para que parte do loop só funcione até a enésima vez (A variável embutida A_Index contém a iteração atual do loop).

Exemplo do 1 e 2 (Veja que no código abaixo, as msgbox de cada checkbox aparecem somente se aquela checkbox está marcada:

Code: Select all

Gui, Add, CheckBox, x36 y156 w60 h20 vAnti_Idle gChkAnti_Idle_onClick, Anti-Idle
Gui, Add, CheckBox, x120 y156 w60 h20 vAnti_Idle2 gChkAnti_Idle_onClick, Anti-Idle2
Gui, Add, Text, x136 y106 w30 h0 , Text
; Generated using SmartGUI Creator 4.0
Gui, Show, x131 y91 h379 w454, MasterCores
Return


ChkAnti_Idle_onClick: 
Sleep, 1500
Loop, 2  
{
GuiControlGet, Anti_Idle
GuiControlGet, Anti_Idle2
		If(Anti_Idle)
			{			
				MsgBox % "Anti 1 ativo"
			}
		If (Anti_Idle2)
			{
				Msgbox % "Anti 2 Ativo"
			}
		Else
		{
			
		}
}
Return


GuiClose:
ExitApp
Exemplo do 3 (Dentro de um loop de 10 repetições, uma msgbox repete 5x e a outra 10x):

Code: Select all

Loop 10 ; Executamos um loop de 10 vezes
{
	If (A_Index <= 5)
	{
		msgbox % "Estamos na vez " A_Index "`nEsta msgbox roda 5 vezes!"
	}
	msgbox % "Estamos na vez " A_Index "`nEsta outra msgbox roda 10 vezes!"
}
Eldorado
Posts: 7
Joined: 24 Oct 2018, 08:53

Re: Loop com CheckBox

25 Oct 2018, 09:13

Está funcionando e suprindo meu objetivo, porém os laços tornaram cada função dependente do término da antecessora. Eu vou precisar colocar um Sleep longo em alguma delas e isso vai comprometer o restante que já deveria ser executada no tempo estipulado. No caso não sei o que fazer.

Code: Select all

my_picturefile = %A_Temp%\lol.jpg
FileInstall, lol.jpg, %my_picturefile%, 1
Gui, Add, Picture,w454 h379, %my_picturefile%

Gui, Add, CheckBox, x36 y156 w60 h20 vAnti_Idle gChkFunctions_onClick, Anti-Idle
Gui, Add, Text, x136 y106 w30 h0 , Text

Gui, Add, CheckBox, x120 y156 w60 h20 vRune gChkFunctions_onClick, Rune
Gui, Add, Text, x136 y106 w30 h0 , Text

Gui, Add, CheckBox, x190 y156 w60 h20 vFood_Eat gChkFunctions_onClick, EatFood
Gui, Add, Text, x136 y250 w30 h0 , Text

; Generated using SmartGUI Creator 4.0
Gui, Show, x131 y91 h379 w454, XXXXXXXX
Return

; Global timerAntiIdle:= 3000 


ChkFunctions_onClick: 
Sleep, 2000
Loop, 999  
{
GuiControlGet, Rune
GuiControlGet, Anti_Idle
GuiControlGet, Food_Eat

		If(Rune)
			{	
				IfWinExist, XXXXXXXX
				{
					ControlSend ,, {f1}, ahk_class otclient
					Sleep 2500
				}
			}
		If (Anti_Idle)
			{
				ControlSend,, ^{Down},  ahk_class otclient
				Sleep, 1500
				ControlSend,, ^{Left},  ahk_class otclient
				Sleep, 1500
			}
		If(Food_Eat)
			{
				Click right 1195, 360 
				Sleep 6000
			}
		Else
		{
			
		}
}
Return

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

Re: Loop com CheckBox

25 Oct 2018, 10:42

O comando Sleep é uma pausa do próprio script. Se você deseja simplesmente pausar a rotina (e não o script), deve usar outro comando.

Eu acho que já entendi a sincronia que você quer fazer entre as tarefas. Isso é possível sim, porém tem que ser bem planejado. Eu sugiro uma rotina ativada através do comando SetTimer, de modo que a cada 1 segundo (ou seja qual for a sua unidade de tempo referencial) verifique todas as checkboxes e execute as ações correspondentes.

Para verificar se a execução atual deve rodar determinada rotina, você deve fazer o cálculo do módulo (o resto da divisão) da iteração atual pelo tempo de espera daquela rotina, implementando uma condicional que rode se o resultado for 0 (adicione uma variável para contar as iterações e determinar a iteração atual, pois o A_Index só funciona para loops). A função embutida Mod() vai te ajudar nisso.

A explicação acima pode ter ficado um tanto quanto confusa, mas não se preocupe que os conceitos são simples. Aqui vai um exemplo onde:
  • 1. Implementamos um SetTimer que rode a rotina a cada 2 segundos (no caso definimos essa como a unidade de tempo de referência, o que significa que todas as rotinas só podem rodar em múltiplos de 2 segundos. Você pode definir como sendo 1 segundo também se quiser, coloquei 2 para enteder melhor o conceito)
  • 2. A rotina computa a iteração atual através da variável "ITERACAO" que inicia em 0 e acrescenta 2 a cada vez que a rotina roda.
  • 3. As condicionais verificam os módulos (o resto da divisão) da iteração atual pela demora esperada em executar a rotina, e se o resultado é 0, rodamos a condicional pois isso significa que estamos em um múltiplo perfeito da rotina, ou seja, o lapso atual deve rodar a rotina sim.
  • 4. Depois que a rotina termina, sabemos que o SetTimer vai rodá-la de novo sempre que o tempo da unidade de referência passar novamente.
:arrow: O código abaixo possui comentários nas linhas mais importantes.

Code: Select all

#Persistent
#SingleInstance, Force ; RECOMENDADO PARA NÃO EXECUTAR 2 SCRIPTS AO MESMO TEMPO SEM QUERER
SetBatchLines, -1 ; RECOMENDADO PARA CONTAGENS DE TEMPO MUITO CURTO
ITERACAO := 0 ; DEFINIMOS COMO 0 NO INÍCIO DO SCRIPT PARA QUE O VALOR INICIE EM 0 (E NÃO EM BRANCO).
SetTimer, EXECUTAR_ACOES, 2000 ; UNIDADE DE TEMPO REFERÊNCIA DE 2 SEGUNDOS. ISSO SIGNIFICA QUE A ROTINA EXECUTAR_ACOES RODA A CADA 2 SEGUNDOS.
Return


EXECUTAR_ACOES:
ITERACAO := ITERACAO + 1 ; CONTAMOS AS ITERACOES. SE A UNIDADE DE TEMPO REFERENCIA É 2 SEGUNDOS, ENTÃO CADA ITERAÇÃO REPRESENTA DOIS SEGUNDOS.
If (mod(ITERACAO, 5) = 0) ; SE CADA ITERAÇÃO REPRESENTA 2 SEGUNDOS, O MÓDULO DA ITERAÇÃO POR 5 VAI DAR ZERO A CADA 10 SEGUNDOS (5 x 2 unidades de referencia).
{
	TrayTip, ROTINA 10 segundos, Esta outra condicional roda a cada 10 segundos
}
If (mod(ITERACAO, 3) = 0)
{
	TrayTip, ROTINA 6 segundos, Esta condicional roda a cada 6 segundos
}
Return
NOTA: Se a contagem atual for um múltiplo comum entre 6 e 10, somente a contagem da rotina 6 vai aparecer, mas a rotina 10 está sim sendo executada (é que o traytip é um só e atualiza com o último comando chamado).
Eldorado
Posts: 7
Joined: 24 Oct 2018, 08:53

Re: Loop com CheckBox

26 Oct 2018, 20:33

Implementei o código acima e rodou perfeito.

Return to “Ajuda e Suporte Geral”

Who is online

Users browsing this forum: No registered users and 75 guests