Dúvida para Implementar Ideia

120 respostas
programação
R

Olá pessoal, bom dia.

Gostaria de uma luz quanto a uma possível programação, minha ideia é que ao utilizar a tecla de pesquisa Ctrl+F e informar um numero especifico, ao clicar Enter o botão seja sensível para identificar o numero e selecionar uma caixinha que no sistema o qual utilizo habilita um outro botão para que eu realize uma impressão de documentos.
Não sei se ficou claro e sou leiga quanto ao assunto, mas caso possam ajudar com o conhecimento de você, fico agradecida.

Ideia

120 Respostas

B

é um sistema Web ou Desktop? se for Web vc usa algum framework? dê mais detalhes pra gente pode te ajudar

D

Se for apenas um número, seria melhor mudar o nome “localizar” para “selecionar”.

Se for vários, poderia usar um “textarea” em que digita vários números separados por espaços, depois com um botão “selecionar todas” marcasse todos os números.

Também poderia criar uma forma de intervalos, exemplo entra “123~330” e marca todos dentro do intervalo.

R

Olá Diego,

Acho interessante a idéia eu vou dar uma pesquisada sobre o assunto. Eu pensei em ter uma ferramenta com a função do clicador, porem com a inteligência que ele não possui em selecionar números específicos no qual vou possuir uma massiva em arquivo excel, por isso exemplifiquei a funçao ctrl+f porque realizo a busca do número exato, e gostaria que no momento do enter ele não só me mostrasse o número pesquisado como também selecionasse a caixa na linha do número qie indiquei. Como utilizamos um sistema já desenvolvido não consigo fazer alterações, por isso pensei em uma ferramenta a mais, usando o clicador ele faria o processo sozinha apenas com o meu comando repetido.

D

Acho melhor deixar o Enter somente para pesquisa pois isso pode bagunçar as marcações. Não sei como a busca funciona, mas supondo que ao digitar a busca seja feita automaticamente, então tudo bem em usar o “Enter” para marcar ou desmarcar.

Uma outra sugestão seria usar uma outra lista que adiciona aqueles que seriam marcados, assim não perderia de vista as marcadas caso fizesse nova busca, como um componente PickList, exemplo no link:
https://www.primefaces.org/showcase/ui/data/pickList.xhtml

R

A busca que é o grande problema, porque eu queria exemplificando que quando eu utilizasse a função Ctrl + F e clicasse para pesquisar ele de imediato já selecionasse a linha com o numero correto,nesse tela que mandei anteriormente veja que o numero 119738 / 69059 esta na função Ctrl+F ele indicou, porem não consegue selecionar. Para que eu use a tecla “Enter” para marcar ou desmarcar, consegue me ajudar a como programar?

J

O sistema é de terceiro ?

Se for ai daria mais trabalho porque você teria de ler o site, buscar a tabela e procurar elemento por elemento.

Mas caso o sistema seja feito por você mesmo, o que da pra fazer é criar um input para buscar dentro do campo da tabela “n° contr…” o valor digitado, e caso ele ache você pode usar a função .parent() do jquery e selecionar a linha da tabela.

Com essa linha da tabela selecionada basta você buscar pelo check box e dar um checked nele.

Abraços.

R

Olá John,

Sim, é de terceiro. :weary:
Sou bem leiga quanto ao assunto mas agradeço sua ideia, vou pesquisar para entender melhor e realizar alguns testes.

Abraços, muito obrigada.

D

Eu acho que a sugestão do @John-Jones está no caminho certo. Pelo que entendi, você usa um sistema web - acessado pelo navegador - que não pode modificar o código, mas você deve conseguir sim fazer o que você quer! eu vejo três formas:

  1. Crie uma extensão para o Navegador, é fácil se for o Chrome (os outros eu não sei), mas você vai precisar de conhecimento de javascript e html.
  2. Use o Selenium IDE, talvez você consiga implementar sua ideia até mesmo sem o conhecimento de javascript ou de outra linguagem de programação com ele (nuca usei ele mas vi que tem umas interfaces gráficas pra ele). Também sei que ele pode ser conectado ao java para controlar a página web no Navegador através de código java.
  3. Crie um “Clicador” (um programa Robô) que identifica o número selecionado e a CheckBox que está na mesma linha, ele vai cuidar então de clicar nessa checkbox.

Criar um clicador desse pode ser bem fácil, na verdade:

  1. Ele precisa buscar dois retângulos compridos de pixels que estejam a uma determinada distância uns dos outros, onde os pixels serão dessa cor:
    image
    Essa é a cor que o Navegador usou para selecionar os Números, seu programa iria buscar as faixas de pixels dessa cor que estão acima e abaixo do número Selecionado, mais ou menos assim:
    image
    Seu programa buscaria pela tela o que está dentro dos retângulos de contorno azul acima.

  2. Ao encontrar, seu programa já sabe a (ou tem noção suficiente da) posição Y em que estará a CheckBox, então ele pode buscar pelos pixels da checkbox dentro da Faixa Y descoberta:
    image

  3. Quando seu programa encontrar a checkbox, é só ele clicar nela quando você teclar Enter (seu programa precisará ouvir os Eventos Nativos do teclado).

Eu implementei algo semelhante a isso em Java a pouco tempo, usando a classe Robot, não é difícil não. O problema, é que basta um pixel diferente e o programa já não vai funcionar, porque ele compara pixel por pixel. Mas o meu tem funcionado muito bem :slight_smile:
Para ouvir os Eventos Nativos do Teclado com Java, dá pra usar o JNativeHook, que também é fácil de usar.

Em qualquer uma das opções que você escolher, você não vai precisar de muito código, mas, infelizmente, pode gastar um bom tempo aprendendo o necessário pra implementar.

R

Douglas,

Achei fantástica a ideia, muito obrigada pelas alternativas, vou pesquisar e tentar executar.
No caso do clicador, não querendo abusar, mas já abusando, se não for dar muito trabalho e puder me ajudar com os códigos e a forma de fazer, agradeço, mas de qualquer forma vou pesquisando e agradeço demais pelo direcionamento.

Abraço. :wink:

D

A desvantagem do clicador em relação as implementações com Selenium/Extensão-de-Navegador é que estas últimas são muito mais resilientes, ou seja:

  • o Clicador pode “quebrar” se as coias mudarem de lugar, alterar o Zoom da página ou não deixar o navegador em tela cheia já pode ser o suficiente para quebrá-lo;
  • Ele se baseia em comparação de pixels, então a mudança na renderização também pode quebrá-lo (usar um Navegador diferente, ou, uma nova versão do Navegador que gera uma renderização diferente).
  • Uma resolução de Tela diferente também pode quebrá-lo, pois as coisas podem aparecer em lugares diferentes, ou a renderização pode mudar por serem mais/menos pixels.

Se sua utilização é sempre igual, o Clicador pode funcionar, pelo menos por um bom tempo.

Pra mim te ajudar a fazer um clicador para sua necessidade, vou precisar que envie PrintScreens da sua tela toda, sem cortar nada, onde haja os números selecionados na página após utilizar o Ctrl+F.

D

Ocultar as informações dos clientes assim não deve causar problemas, há menos que você precise cobrir a área laranja que o Ctrl+F do navegador destaca, porque o programa vai varrer uma área da tela buscando por esses pixels.

Hum, não sei se essas imagens vão dar certo, você colocou o Navegador em tela cheia? É assim que você vai usar no dia-a-dia? Caso contrário, você precisa me dar o printscreen da tela por completo mesmo, sem recortar as bordas dela; isso inclui a barra de tarefas do windows (ou do seu S.O.), as abas do chrome, etc.

Você pode cobrir as informações, mas não pode cortar a imagem, nem redimensionar, porque se não a posição dos pixels muda (redimensionar é pior ainda, aí nem dá para usar a imagem). Seria algo como essa imagem que peguei da internet:

Deve dar certo você colocar as imagens aqui no GUJ, tem a opção de baixar, e eu acho (e espero que) o GUJ não as modifique ao rodar algum algoritmo de otimização de imagens.

Acho que essa 1ª imagem que você postou, a de cima, é do tipo que vai dar certo; tira uns 3 printscreens selecionando números diferentes, uns com o número XXXXXX e outras com o número com barra XXXXXX / XXXXX. Eu quero ver se os pixels laranja aparecem bem nítidos em cima e em baixo dos números sem contaminação de outras cores.

Essa imagem de baixo eu não entendi, é uma tela bem diferente. O programa teria que lidar com essa tela também? Você vai usar Ctrl+F nela? O que o programa teria que fazer nesta tela?

A minha ideia é um programa que roda no Tray do sistema, em Java. Ele iria simplesmente detectar os pixels laranja da área destacada pelo Ctrl+F, para descobrir a posição Y da checkbox, e então buscar a checkbox certa comparando pixels.

D

Ainda não está pronto, mas o código abaixo já consegue fazer o seguinte:

  1. Detectar a linha Selecionada pelo Navegador (na cor laranja) ao usar Ctrl+F;
  2. Determinar uma Área onde a Checkbox dessa Linha específica está;
  3. Encontrar a posição dessa Checkbox na Tela e mover o cursor para cima dela.

Fazer o cursor clicar nela vai ser fácil, já fiz um método “clicar(…)”.

No futuro será necessário usar o JNativeHook para que todo esse processamento ocorra sempre que você teclar Enter.

Agora acho bom você testar, para testar faça o seguinte:

  1. Abra o Navegador no seu sistema e use Ctrl+F para selecionar alguma das linhas, como na “tela teste 2.PNG”;
  2. Coloque as classes abaixo na sua IDE e compile, rode o código do Main;
  3. Após iniciar a execução do Código, você terá 5 segundos para alternar para o navegador deixando-o maximizado como “tela teste 2.PNG”, pois após esse tempo o Clicador ira dar um prinscreen e irá buscar a linha selecionada e checkbox.

Se tudo der certo, o cursor deve ir parar em cima da checkbox, e você deve ver algo assim:

package main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class Main {

	private static BufferedImage checkBoxImage;
	private static JFrame tela;
	private static Robot robo;

	private static boolean isFechar = false;
	private static BuscadorDaCheckboxDaLinhaSelecionada buscadorDaCheckboxDaLinhaSelecionada;

	public static void main(String[] args) {
		try {
			dormir(5000);
			robo = new Robot();
			checkBoxImage = ImageIO.read(new File("src/images/partedecheckbox.png"));
			BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada = new BuscadorDeLinhaSelecionada(
					new Color(255, 150, 50), 5, 5);
			Rectangle areaDaSelecao = new Rectangle(674, 318, 103, 492);
			buscadorDaCheckboxDaLinhaSelecionada = new BuscadorDaCheckboxDaLinhaSelecionada(checkBoxImage,
					buscadorDeLinhaSelecionada, areaDaSelecao, 365, 400, robo);
			Rectangle boundsDaCheckboxEncontrada = buscadorDaCheckboxDaLinhaSelecionada
					.buscarCheckboxDaLinhaSelecionada();
			System.out.println(boundsDaCheckboxEncontrada);
			if (boundsDaCheckboxEncontrada != null) {
				robo.mouseMove(boundsDaCheckboxEncontrada.x, boundsDaCheckboxEncontrada.y);
			}
		} catch (Exception e1) {
			e1.printStackTrace();
			saidaComErro(e1);
		}

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					tela = new Tela();
					// tela.setExtendedState(JFrame.ICONIFIED);
				} catch (Exception e) {
					e.printStackTrace();
					saidaComErro(e);
				}
			}
		});
	}

	public static void dormir(int tempo) {
		try {
			Thread.sleep(tempo);
		} catch (InterruptedException e) {
			e.printStackTrace();
			saidaComErro(e);
		}
	}

	private static void saidaComErro(Exception e) throws HeadlessException {
		JOptionPane.showMessageDialog(null, e);
		System.exit(1);
	}

	/** Clica na posição x e y passadas. */
	private static void clicar(int x, int y) {
		robo.mouseMove(x, y);
		robo.mousePress(InputEvent.BUTTON1_DOWN_MASK);
		robo.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
	}

	@SuppressWarnings("serial")
	private static class Tela extends JFrame {
		TrayIcon trayIcon;
		SystemTray tray;

		Tela() {
			super("Clicador em Checkbox de linha Selecionada");
			System.out.println("creating instance");
			try {
				System.out.println("setting look and feel");
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			} catch (Exception e) {
				System.out.println("Unable to set LookAndFeel");
				saidaComErro(e);
			}
			if (SystemTray.isSupported()) {
				System.out.println("system tray supported");
				tray = SystemTray.getSystemTray();

				ActionListener exitListener = new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						System.out.println("Exiting....");
						isFechar = true;
						System.exit(0);
					}
				};
				PopupMenu popup = new PopupMenu();
				MenuItem defaultItem = new MenuItem("Sair");
				defaultItem.addActionListener(exitListener);
				popup.add(defaultItem);
				defaultItem = new MenuItem("Abrir");
				defaultItem.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						setVisible(true);
						setExtendedState(JFrame.NORMAL);
					}
				});
				popup.add(defaultItem);
				// trayIcon = new TrayIcon(checkBoxImage, "Clicador de Checkbox", popup);
				// trayIcon.setImageAutoSize(true);
			} else {
				System.out.println("system tray not supported");
			}
			addWindowStateListener(new WindowStateListener() {

				public void windowStateChanged(WindowEvent e) {
					if (e.getNewState() == ICONIFIED || e.getNewState() == 7) {
						System.out.println("ICONIFIED: " + ICONIFIED);
						try {
							// tray.add(trayIcon);
							setVisible(false);
							System.out.println("added to SystemTray");
						} catch (Exception ex) {
							System.out.println("unable to add to tray");
							saidaComErro(ex);
						}
					}
					if (e.getNewState() == MAXIMIZED_BOTH || e.getNewState() == NORMAL) {
						// tray.remove(trayIcon);
						setVisible(true);
						System.out.println("Tray icon removed");
					}
				}
			});

			setIconImage(checkBoxImage);

			setSize(230, 500);
			// setResizable(false);
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			add(new Painel());
			setAlwaysOnTop(true);
			setVisible(true);
		}
	}

	@SuppressWarnings("serial")
	private static class Painel extends JPanel {
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.DARK_GRAY);
			g.fillRect(0, 0, getWidth(), getHeight());

			BufferedImage areaDaSelecao = buscadorDaCheckboxDaLinhaSelecionada.areaDaSelecaoBuscada.get();
			if (areaDaSelecao != null) {
				g.drawImage(areaDaSelecao, 20, 20, null);
				BufferedImage areaDaCheckbox = buscadorDaCheckboxDaLinhaSelecionada.areaComCheckboxBuscada.get();
				if (areaDaCheckbox != null) {
					g.drawImage(areaDaCheckbox, areaDaSelecao.getWidth() + 30, 20, null);
					g.drawImage(checkBoxImage, areaDaSelecao.getWidth() + 30, areaDaCheckbox.getHeight() + 30, null);
				}
			}
		}

	}

}

Busca a linha com a cor laranja:

package main;

import java.awt.Color;
import java.awt.image.BufferedImage;

public class BuscadorDeLinhaSelecionada {

	private Color corDaSelecao;

	private int margemSuperiorAdicionada; // valor em pixels
	private int margemInferiorAdicionada; // valor em pixels

	public BuscadorDeLinhaSelecionada(Color corDaSelecao, int margemSuperiorAdicionada, int margemInferiorAdicionada) {
		this.corDaSelecao = corDaSelecao;
		this.margemSuperiorAdicionada = margemSuperiorAdicionada;
		this.margemInferiorAdicionada = margemInferiorAdicionada;
	}

	public LinhaDaSelecao encontrarInicioEFimDaLinhaSelecionada(BufferedImage areaDaSelecaoScreenshot, int margemY) {
		LinhaDaSelecao linha = encontrarInicioEFim(areaDaSelecaoScreenshot, corDaSelecao, margemY);
		if (linha == null)
			return null;
		System.out.println("inicioY: " + linha.inicioY + " / linha.fimY: " + linha.fimY);
		linha.inicioY = linha.inicioY - margemSuperiorAdicionada;
		linha.fimY = linha.fimY + margemInferiorAdicionada;
		System.out.println("inicioY: " + linha.inicioY + " / linha.fimY: " + linha.fimY);
		return linha;
	}

	private LinhaDaSelecao encontrarInicioEFim(BufferedImage img, Color cor, int margemY) {
		boolean encontrou = false;
		LinhaDaSelecao linhaDaSelecao = new LinhaDaSelecao();
		linhaDaSelecao.inicioY = Integer.MAX_VALUE;
		linhaDaSelecao.fimY = Integer.MIN_VALUE;
		for (int x = 0; x < img.getWidth(); x++) {
			for (int y = 0; y < img.getHeight(); y++) {
				if (new Color(img.getRGB(x, y)).equals(corDaSelecao)) {
					int posicaoYRealDoPixel = y + margemY;
					if (linhaDaSelecao.inicioY > posicaoYRealDoPixel) {
						encontrou = true;
						linhaDaSelecao.inicioY = posicaoYRealDoPixel;
					}
					if (linhaDaSelecao.fimY < posicaoYRealDoPixel) {
						encontrou = true;
						linhaDaSelecao.fimY = posicaoYRealDoPixel;
					}
				}
			}
		}
		return (encontrou) ? linhaDaSelecao : null;
	}

	public static class LinhaDaSelecao {
		public int inicioY;
		public int fimY;
	}
}

Busca a checkbox dentro da área onde ela pode estar:

package main;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;

public class BuscadorDeImagemDentroDeImagem {

	/**
	 * Busca a 'imagemFilho' dentro da 'imagemPai' retornando um {@link Rectangle}
	 * com a informação (x, y, width e height) de onde ela foi encontrada na
	 * 'imagemPai'; ou retorna null caso não a encontre.
	 */
	public static Rectangle buscarFilho(BufferedImage imagemPai, BufferedImage imagemFilho) {
		for (int x = 0; x < imagemPai.getWidth(); x++) {
			for (int y = 0; y < imagemPai.getHeight(); y++) {
				if (contemFilho(imagemPai, imagemFilho, x, y)) {
					return new Rectangle(x, y, imagemFilho.getWidth(), imagemFilho.getHeight());
				}
			}
		}
		return null;
	}

	/**
	 * Retorna true apenas se a 'imagemFilho' for encontrada na 'imagemPai' na
	 * posição 'offsetX' e 'offsetY' passadas; retorna false caso contrário.
	 */
	public static boolean contemFilho(BufferedImage imagemPai, BufferedImage imagemFilho, int offsetX, int offsetY) {
		if (!filhoCabeDentroDoPai(imagemPai, imagemFilho, offsetX, offsetY)) {
			return false; // não contém o filho se ele não cabe dentro do pai
		}
		for (int x = 0; x < imagemFilho.getWidth(); x++) {
			for (int y = 0; y < imagemFilho.getHeight(); y++) {
				if (imagemPai.getRGB(offsetX + x, offsetY + y) != imagemFilho.getRGB(x, y)) {
					return false;
				}
			}
		}
		return true;
	}

	private static boolean filhoCabeDentroDoPai(BufferedImage imagemPai, BufferedImage imagemFilho, int offsetX,
			int offsetY) {
		if ((offsetX + imagemFilho.getWidth()) > imagemPai.getWidth()) {
			return false;
		}
		if ((offsetY + imagemFilho.getHeight()) > imagemPai.getWidth()) {
			return false;
		}
		return true;
	}

}

Basicamente cuida de tudo que implementei:

package main;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import main.BuscadorDeLinhaSelecionada.LinhaDaSelecao;

public class BuscadorDaCheckboxDaLinhaSelecionada {

	private Robot robo;

	private BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada;

	private Rectangle areaDaSelecao;
	private int bordaEsquerdaDaAreaDeCheckbox;
	private int bordaDireitaDaAreaDeCheckbox;

	private BufferedImage imagemDaCheckbox;

	/** Não altere o valor desta property. */
	public final ObjectProperty<BufferedImage> areaComCheckboxBuscada = new SimpleObjectProperty<>();
	/** Não altere o valor desta property. */
	public final ObjectProperty<BufferedImage> areaDaSelecaoBuscada = new SimpleObjectProperty<>();

	public BuscadorDaCheckboxDaLinhaSelecionada(BufferedImage imagemDaCheckbox,
			BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada, Rectangle areaDaSelecao,
			int bordaEsquerdaDaAreaDeCheckbox, int bordaDireitaDaAreaDeCheckbox, Robot robo) throws AWTException {
		this.robo = robo;
		this.imagemDaCheckbox = imagemDaCheckbox;
		this.buscadorDeLinhaSelecionada = buscadorDeLinhaSelecionada;
		this.areaDaSelecao = areaDaSelecao;
		this.bordaEsquerdaDaAreaDeCheckbox = bordaEsquerdaDaAreaDeCheckbox;
		this.bordaDireitaDaAreaDeCheckbox = bordaDireitaDaAreaDeCheckbox;
	}

	public Rectangle buscarCheckboxDaLinhaSelecionada() {
		areaDaSelecaoBuscada.set(robo.createScreenCapture(areaDaSelecao));
		LinhaDaSelecao linhaSelecionada = buscadorDeLinhaSelecionada
				.encontrarInicioEFimDaLinhaSelecionada(areaDaSelecaoBuscada.get(), areaDaSelecao.y);
		if (linhaSelecionada != null) {
			int width = bordaDireitaDaAreaDeCheckbox - bordaEsquerdaDaAreaDeCheckbox;
			int height = linhaSelecionada.fimY - linhaSelecionada.inicioY;
			Rectangle boundsDaAreaComCheckboxBuscada = new Rectangle(bordaEsquerdaDaAreaDeCheckbox,
					linhaSelecionada.inicioY, width, height);
			System.out.println("boundsDaAreaComCheckboxBuscada: " + boundsDaAreaComCheckboxBuscada);
			areaComCheckboxBuscada.set(robo.createScreenCapture(boundsDaAreaComCheckboxBuscada));
			Rectangle boundsDaCheckbox = BuscadorDeImagemDentroDeImagem.buscarFilho(areaComCheckboxBuscada.get(),
					imagemDaCheckbox);
			if (boundsDaCheckbox != null) {
				boundsDaCheckbox.x += boundsDaAreaComCheckboxBuscada.x;
				boundsDaCheckbox.y += boundsDaAreaComCheckboxBuscada.y;
			}
			System.out.println("boundsDaCheckbox: " + boundsDaCheckbox);
			return boundsDaCheckbox;
		}

		return null;
	}

}

Atenção para essa imagem “src/images/partedecheckbox.png”, você recortar a imagem da checkbox obtida pelo seu printscreen garantindo que a parte recortada é igual - em todos os pixels - a todas as outras checkbox da tela. O programa busca na tela (dentro da área onde a checkbox buscada pode estar) por essa “partedecheckbox” conferindo pixel-a-pixel. Veja se essa imagem abaixo dará certo para ser a “partedecheckbox.png”:

partedecheckbox_teste

A estrutura do projeto:
image

R

Douglas,

Muito obrigada, você é demais … Ainda não consegui realizar os testes mas fico imensamente agradecida pelo seu tempo dedicado, preciso solicitar alguns acessos para o ambiente de teste e execução do programa pode listar pra mim o que vou precisar solicitar instalação para ambiente de teste e posterior executar o clicador? Devido ao acesso restrito por ser ambiente corporativo, vou precisar solicitar a área de TI a instalação, pra dai então conseguir testar. Desculpa pelo abuso.

D

Hum… parece que testar o programa aí é meio complicado, talvez seja melhor ter o programa já pronto (ou quase pronto) pra mandar para o teste.

De qualquer forma, esse programa vai ter que fazer coisas que podem ser vistas como perigosas: o Robot do Java permite fazer screenshots e emitir eventos de mouse e teclado, então ele poderia ser usado para vazar dados (através dos screenshots) ou mesmo dar controle da máquina a um hacker (controle de mouse/teclado)!

O JNativeHook é uma biblioteca, que pode ser ainda mais perigosa: é muito fácil usá-la para criar um KeyLogger, já que ele tem como objetivo ficar ouvindo os Eventos do Sistema Operacional.

Um programa Java pode ser exportado em um arquivo JAR, sendo meio que um “executável portátil”, não precisando instalar nada. Mas o Computador que vai rodá-lo precisa ter a JVM instalada, que roda os programas Java. Acho que quase todo computador tem a JVM, mas não sei. Qualquer coisa dá pra baixar e instalar, “instalar o Java”.

Acho que o melhor que você pode fazer é conversar com o pessoal da TI, eles podem analisar o código pra ver que não é malicioso, e para determinar se abrirá vulnerabilidades no sistema ou não.

Você programa em Java? tem acesso a uma IDE pra compilar, editar e/ou rodar o código que te mandei?

Eu estou te ajudando com isso porque acredito que a vontade de Deus é que façamos pelos outros o que gostaríamos que fizessem por nós, eu amo Deus e com isso tenho a vontade de fazer o bem no meu coração (vontade que Ele mesmo colocou); eu acho que esse Clicador pode ser uma benção no seu dia-a-dia e que seria muito mais díficil pra você fazê-lo do que pra mim, por isso decidi fazê-lo. :slight_smile:

Que Deus te abençoe.

D

Eu também não tenho muito conhecimetno nessa área, mas acho que os problemas são:

  1. Existem malwares que se aproveitam de bibliotecas instaladas no computador infectado, utilizando-as a seu serviço. Se um malware infectar uma máquina com a biblioteca JNativeHook, talvez ele consiga utilizar essa biblioteca para ficar “escutando” tudo que é digitado. Mas talvez precise ser um malware projetado para reconhecer essa biblioteca e saber como consumí-la, algo um tanto específico.

  2. A documentação da classe Robot diz (o negrito é meu):

Using the class to generate input events differs from posting events to the AWT event queue or AWT components in that the events are generated in the platform’s native input queue. For example, Robot.mouseMove will actually move the mouse cursor instead of just generating mouse move events.

Note that some platforms require special privileges or extensions to access low-level input control. If the current platform configuration does not allow input control, an AWTException will be thrown when trying to construct Robot objects. For example, X-Window systems will throw the exception if the XTEST 2.2 standard extension is not supported (or not enabled) by the X server.

Applications that use Robot for purposes other than self-testing should handle these error conditions gracefully.

Veja que para rodar o Robot o computador pode precisar de “privilégios especiais”, eu imagino que esses privilégios seriam dados em alguma configuração da JVM, ou em alguma configuração do computador, mas não sei. De qualquer forma, sempre que é necessário “aumentar os privilégios” a segurança cai, pois malwares talvez consigam se aproveitar desses privilégios.

Em qualquer caso, o programa sózinho não faz nenhum mal, mas, se a máquina for infectada por um malware talvez esse malware consiga se aproveitar dos recursos/privilégios consumidos pelo programa.

Seria necessário uma pesquisa mais profunda para saber sobre vulnerabilidades abertas pela classe Robot e pelo JNativeHook. Preferencialmente uma pesquisa em inglês.

Dá para reaproveitar quase todo o código que fiz mudando a implementação do Robô e do Listener-de-Eventos-Nativos (JNativeHook), por outras bibliotecas que a equipe de TI preferir. Talvez dê até para evitar a utilização de um Listener-de-Eventos-Nativos, se o robô conseguir monitorar a tela para saber em qual momento deve clicar na checkbox; mas no fim, o programa precisará fazer screenshots e dar clicks, então será necessário usar algum robô (mesmo que seja de outra biblioteca, ou, de algum modo, implementado em outro programa que seria controlado pelo programa que fiz).

Talvez isso dê certo para aumentar a segurança (precisa ser mais pesquisado, pra ver se ajuda mesmo):

  1. Veja se é possível rodar navegador com o sistema web numa Máquina Virtual, como o VirtualBox, dentro dessa Máquina Virtual você colocaria o Clicador também, para usá-lo junto. Com isso, você pode estar isolando o Clicador e o SistemaWeb do resto dos Sistema, mantendo-os ativos apenas enquanto está usando. A ideia é que, como o Clicador está rodando na Máquina Virtual, se um malware tentar controlar alguma biblioteca dele essa biblioteca também estará limitada à Máquina Virtual e suas restrições.

  2. O programa é um JAR, pode ficar todo dentro de uma pasta, não precisa ser instalado; com isso, você pode: Comprimir e Criptogravar a pasta do Programa enquanto não estiver usando, evitando o acesso a ele, depois, na hora de usar, descomprimir/descriptografar. Se você vai ficar usando-o o tempo todo (como imagino), isso nem deve adiantar; mas a ideia é que, enquanto comprimido e criptografado, nenhum malware conseguiria usufruir do JNativeHook no programa.

Dei uma pesquisada rápida sobre a segurança do Robot e do JNativeHook, e não encontrei praticamente nada relevante. Apenas alguns dizendo que o Robot pode trazer vulnerabilidades como eu disse, sem maiores explicações ou fontes confiáveis. Para o JNativeHook, o que encontrei foi um malware feito em java que - aparentemente - já vem com o JNativeHook para usá-lo em suas atividades (os criadores do malware colocaram o JNativeHook no malware deles), mas não vi nada sobre ele se aproveitar do JNativeHook já presente em outro programa:

Pode ser uma boa coisa perguntar sobre isso no StackOverFlow, de preferência o inglês se você sabe escrever bem em inglês (me negativaram lá uma vez por escrever mau em inglês :frowning: ). Perguntar sobre vulnerabilidades da classe awt.Robot e do JNativeHook, se existem exploits para eles, e o que pode ser feito para se proteger.

No primeiro link que te mandei eu vi algo sobre as AWTPermissions, que não sei quase nada, diz assim:

AWTPermission - Permissions are defined in the policy file which modules should not have access to, but still a good thing to take note of.

Pelo que entendi, são algumas dessas AWTPermissions que o Robot vai precisar, e parece que elas são definidas em um arquivo; seria necessário pesquisar sobre isso e ver se é possível fazer as permissões serem dadas apenas ao Clicador, com segurança de que nenhum malware pode se aproveitar dessas Permissions.

Eu não tenho conhecimento suficiente para dizer o quão inseguro seria usar esse Clicador, talvez não diminua em quase nada a segurança, imagino que isso depende do qual difícil/fácil é criar um malware que conseguiria se aproveitar. Se for fácil, deve ser fácil também encontrar exploits para o Robot e para o JNativeHook, e deve ser fácil encontrar pessoas experientes no StackOverflow em inglês dizendo como o uso dessas bibliotecas podem ser exploradas por malwares.

No fim, me diga qual decisão você tomou, se vai seguir adiante com esse programa ou não, se você for seguir adiante eu continuando implementando. Acho que falta bem pouquinho pra terminá-lo.

Que bom que você consegue editar o código, assim você será capaz de alterar os valores de Configuração. Percebi que o programa, na verdade, ficou até bem resiliente:

  • Apenas alterando as Configurações o Programa pode ser adaptado para funcionar:
    1. Em outra Resolução da Tela;
    2. Em outro Navegador e/ou outra Versão do mesmo Navegador;
    3. Em uma versão um pouco diferente do Layout do site, caso este venha a ser alterado;
    4. Com Zoom no Navegador;
    5. Com a Janela do Navegador não-maximizada (mas precisa estar em lugar específico da tela, de acordo com a Configuração);
    6. Em outro Computador.
D

Bem, acredito que está pronto, depois vou ter que te explicar sobre as Configurações para você poder reconfigurar caso precise. Eu centralizei todas as configurações no método “iniciarConfiguracoes()”, então você já sabe o ponto de todo o código que precisará alterar, e não ficará perdida.

Você vai ter que baixar o JNativeHook e importar o JAR dele para o seu Projeto, eu fiz no Eclipse seguindo o que está escrito aqui, veja como é no NetBeans. Eu usei a versão 2.0.3, acho que já deve ter novas versões, mas não sei se são compatíveis ou se você terá que mudar o código.

Assim fica a estrutura do Projeto:

image

Classe Main:

package main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import main.listener.ListenerDeEventosNativos;
import main.listener.ProcessadorDeEventosNativos;

public class Main {

	private static BufferedImage checkBoxImage;
	private static JFrame tela;
	private static Robot robo;

	private static BuscadorDaCheckboxDaLinhaSelecionada buscadorDaCheckboxDaLinhaSelecionada;

	public static void main(String[] args) {

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					tela = new Tela();
				} catch (Exception e) {
					e.printStackTrace();
					saidaComErro(e);
				}
			}
		});

		try {
			ListenerDeEventosNativos.iniciar();
			iniciarConfiguracoes();
			Clicador clicador = new Clicador(robo, buscadorDaCheckboxDaLinhaSelecionada);
			ListenerDeEventosNativos
					.addNativeKeyListener(new ProcessadorDeEventosNativos(clicador::clicarNaCheckbox, () -> {
						SwingUtilities.invokeLater(() -> tela.repaint());
					}));
		} catch (Exception e1) {
			e1.printStackTrace();
			saidaComErro(e1);
		}
	}

	/** Altere as configurações para corresponder as suas necessidades. */
	private static void iniciarConfiguracoes() throws Exception {
		robo = new Robot();
		checkBoxImage = ImageIO.read(new File("src/images/partedecheckbox.png"));
		BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada = new BuscadorDeLinhaSelecionada(new Color(255, 150, 50),
				5, 5);
		Rectangle areaDaSelecao = new Rectangle(674, 318, 103, 492);
		buscadorDaCheckboxDaLinhaSelecionada = new BuscadorDaCheckboxDaLinhaSelecionada(checkBoxImage,
				buscadorDeLinhaSelecionada, areaDaSelecao, 365, 400);
	}

	private static void saidaComErro(Exception e) throws HeadlessException {
		JOptionPane.showMessageDialog(null, e);
		System.exit(1);
	}

	@SuppressWarnings("serial")
	private static class Tela extends JFrame {

		Tela() {
			super("Clicador em Checkbox de linha Selecionada");
			System.out.println("creating instance");
			setSize(230, 500);
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			add(new Painel());
			setAlwaysOnTop(true);
			setVisible(true);
		}
	}

	@SuppressWarnings("serial")
	private static class Painel extends JPanel {
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.DARK_GRAY);
			g.fillRect(0, 0, getWidth(), getHeight());

			BufferedImage areaDaSelecao = buscadorDaCheckboxDaLinhaSelecionada.areaDaSelecaoBuscada.get();
			if (areaDaSelecao != null) {
				g.drawImage(areaDaSelecao, 20, 20, null);
				BufferedImage areaDaCheckbox = buscadorDaCheckboxDaLinhaSelecionada.areaComCheckboxBuscada.get();
				if (areaDaCheckbox != null) {
					g.drawImage(areaDaCheckbox, areaDaSelecao.getWidth() + 30, 20, null);
					g.drawImage(checkBoxImage, areaDaSelecao.getWidth() + 30, areaDaCheckbox.getHeight() + 30, null);
				}
			}
		}

	}

}

Clicador:

package main;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.InputEvent;

public class Clicador {

	private Robot robo;
	private BuscadorDaCheckboxDaLinhaSelecionada buscadorDaCheckboxDaLinhaSelecionada;

	public Clicador(Robot robo, BuscadorDaCheckboxDaLinhaSelecionada buscadorDaCheckboxDaLinhaSelecionada) {
		this.robo = robo;
		this.buscadorDaCheckboxDaLinhaSelecionada = buscadorDaCheckboxDaLinhaSelecionada;
	}

	/**
	 * Retorna true apenas se encontrou e clicou na Checkbox, false caso contrário.
	 */
	public boolean clicarNaCheckbox() {
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Rectangle boundsDaCheckboxEncontrada = buscadorDaCheckboxDaLinhaSelecionada.buscarCheckboxDaLinhaSelecionada(
				robo.createScreenCapture(new Rectangle(0, 0, screenSize.width, screenSize.height)));
		System.out.println(boundsDaCheckboxEncontrada);
		if (boundsDaCheckboxEncontrada != null) {
			int centroDaCheckBox_X = boundsDaCheckboxEncontrada.x + (boundsDaCheckboxEncontrada.width / 2);
			int centroDaCheckBox_Y = boundsDaCheckboxEncontrada.y + (boundsDaCheckboxEncontrada.height / 2);
			clicar(centroDaCheckBox_X, centroDaCheckBox_Y);
			System.out.println("Clicou na Checkbox - x: " + centroDaCheckBox_X + ", y: " + centroDaCheckBox_Y);
			return true;
		}
		return false;
	}

	/** Clica na posição x e y passadas. */
	private void clicar(int x, int y) {
		robo.mouseMove(x, y);
		robo.mousePress(InputEvent.BUTTON1_DOWN_MASK);
		robo.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
	}
}

Buscador da Linha Selecionada pelo Ctrl+F:

package main;

import java.awt.Color;
import java.awt.image.BufferedImage;

public class BuscadorDeLinhaSelecionada {

	private Color corDaSelecao;

	private int margemSuperiorAdicionada; // valor em pixels
	private int margemInferiorAdicionada; // valor em pixels

	public BuscadorDeLinhaSelecionada(Color corDaSelecao, int margemSuperiorAdicionada, int margemInferiorAdicionada) {
		this.corDaSelecao = corDaSelecao;
		this.margemSuperiorAdicionada = margemSuperiorAdicionada;
		this.margemInferiorAdicionada = margemInferiorAdicionada;
	}

	public LinhaDaSelecao encontrarInicioEFimDaLinhaSelecionada(BufferedImage areaDaSelecaoScreenshot, int margemY) {
		LinhaDaSelecao linha = encontrarInicioEFim(areaDaSelecaoScreenshot, corDaSelecao, margemY);
		if (linha == null)
			return null;
		System.out.println("inicioY: " + linha.inicioY + " / linha.fimY: " + linha.fimY);
		linha.inicioY = linha.inicioY - margemSuperiorAdicionada;
		linha.fimY = linha.fimY + margemInferiorAdicionada;
		System.out.println("inicioY: " + linha.inicioY + " / linha.fimY: " + linha.fimY);
		return linha;
	}

	private LinhaDaSelecao encontrarInicioEFim(BufferedImage img, Color cor, int margemY) {
		boolean encontrou = false;
		LinhaDaSelecao linhaDaSelecao = new LinhaDaSelecao();
		linhaDaSelecao.inicioY = Integer.MAX_VALUE;
		linhaDaSelecao.fimY = Integer.MIN_VALUE;
		for (int x = 0; x < img.getWidth(); x++) {
			for (int y = 0; y < img.getHeight(); y++) {
				if (new Color(img.getRGB(x, y)).equals(corDaSelecao)) {
					int posicaoYRealDoPixel = y + margemY;
					if (linhaDaSelecao.inicioY > posicaoYRealDoPixel) {
						encontrou = true;
						linhaDaSelecao.inicioY = posicaoYRealDoPixel;
					}
					if (linhaDaSelecao.fimY < posicaoYRealDoPixel) {
						encontrou = true;
						linhaDaSelecao.fimY = posicaoYRealDoPixel;
					}
				}
			}
		}
		return (encontrou) ? linhaDaSelecao : null;
	}

	public static class LinhaDaSelecao {
		public int inicioY;
		public int fimY;
	}
}

Buscador de uma Imagem que está também dentro de outra Imagem (talvez a classe mais reutilizável!):

package main;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;

public class BuscadorDeImagemDentroDeImagem {

	/**
	 * Busca a 'imagemFilho' dentro da 'imagemPai' retornando um {@link Rectangle}
	 * com a informação (x, y, width e height) de onde ela foi encontrada na
	 * 'imagemPai'; ou retorna null caso não a encontre.
	 */
	public static Rectangle buscarFilho(BufferedImage imagemPai, BufferedImage imagemFilho) {
		for (int x = 0; x < imagemPai.getWidth(); x++) {
			for (int y = 0; y < imagemPai.getHeight(); y++) {
				if (contemFilho(imagemPai, imagemFilho, x, y)) {
					return new Rectangle(x, y, imagemFilho.getWidth(), imagemFilho.getHeight());
				}
			}
		}
		return null;
	}

	/**
	 * Retorna true apenas se a 'imagemFilho' for encontrada na 'imagemPai' na
	 * posição 'offsetX' e 'offsetY' passadas; retorna false caso contrário.
	 */
	public static boolean contemFilho(BufferedImage imagemPai, BufferedImage imagemFilho, int offsetX, int offsetY) {
		if (!filhoCabeDentroDoPai(imagemPai, imagemFilho, offsetX, offsetY)) {
			return false; // não contém o filho se ele não cabe dentro do pai
		}
		for (int x = 0; x < imagemFilho.getWidth(); x++) {
			for (int y = 0; y < imagemFilho.getHeight(); y++) {
				if (imagemPai.getRGB(offsetX + x, offsetY + y) != imagemFilho.getRGB(x, y)) {
					return false;
				}
			}
		}
		return true;
	}

	private static boolean filhoCabeDentroDoPai(BufferedImage imagemPai, BufferedImage imagemFilho, int offsetX,
			int offsetY) {
		if ((offsetX + imagemFilho.getWidth()) > imagemPai.getWidth()) {
			return false;
		}
		if ((offsetY + imagemFilho.getHeight()) > imagemPai.getWidth()) {
			return false;
		}
		return true;
	}

}

Buscador da Checkbox que será clicada:

package main;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import main.BuscadorDeLinhaSelecionada.LinhaDaSelecao;

public class BuscadorDaCheckboxDaLinhaSelecionada {

	private BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada;

	private Rectangle areaDaSelecao;
	private int bordaEsquerdaDaAreaDeCheckbox;
	private int bordaDireitaDaAreaDeCheckbox;

	private BufferedImage imagemDaCheckbox;

	/** Não altere o valor desta property. */
	public final ObjectProperty<BufferedImage> areaComCheckboxBuscada = new SimpleObjectProperty<>();
	/** Não altere o valor desta property. */
	public final ObjectProperty<BufferedImage> areaDaSelecaoBuscada = new SimpleObjectProperty<>();

	public BuscadorDaCheckboxDaLinhaSelecionada(BufferedImage imagemDaCheckbox,
			BuscadorDeLinhaSelecionada buscadorDeLinhaSelecionada, Rectangle areaDaSelecao,
			int bordaEsquerdaDaAreaDeCheckbox, int bordaDireitaDaAreaDeCheckbox) {
		this.imagemDaCheckbox = imagemDaCheckbox;
		this.buscadorDeLinhaSelecionada = buscadorDeLinhaSelecionada;
		this.areaDaSelecao = areaDaSelecao;
		this.bordaEsquerdaDaAreaDeCheckbox = bordaEsquerdaDaAreaDeCheckbox;
		this.bordaDireitaDaAreaDeCheckbox = bordaDireitaDaAreaDeCheckbox;
	}

	/**
	 * Recebe um screenshot de toda a tela, e retorna um Rectangle com as bouds do
	 * checkbox a ser clicado, ou retorna null caso não tenha encontrado ele ou a
	 * linha Selecionada.
	 */
	public Rectangle buscarCheckboxDaLinhaSelecionada(BufferedImage screenshot) {
		areaDaSelecaoBuscada.set(
				screenshot.getSubimage(areaDaSelecao.x, areaDaSelecao.y, areaDaSelecao.width, areaDaSelecao.height));
		LinhaDaSelecao linhaSelecionada = buscadorDeLinhaSelecionada
				.encontrarInicioEFimDaLinhaSelecionada(areaDaSelecaoBuscada.get(), areaDaSelecao.y);
		if (linhaSelecionada != null) {
			int width = bordaDireitaDaAreaDeCheckbox - bordaEsquerdaDaAreaDeCheckbox;
			int height = linhaSelecionada.fimY - linhaSelecionada.inicioY;
			Rectangle boundsDaAreaComCheckboxBuscada = new Rectangle(bordaEsquerdaDaAreaDeCheckbox,
					linhaSelecionada.inicioY, width, height);
			System.out.println("boundsDaAreaComCheckboxBuscada: " + boundsDaAreaComCheckboxBuscada);
			areaComCheckboxBuscada
					.set(screenshot.getSubimage(boundsDaAreaComCheckboxBuscada.x, boundsDaAreaComCheckboxBuscada.y,
							boundsDaAreaComCheckboxBuscada.width, boundsDaAreaComCheckboxBuscada.height));
			Rectangle boundsDaCheckbox = BuscadorDeImagemDentroDeImagem.buscarFilho(areaComCheckboxBuscada.get(),
					imagemDaCheckbox);
			if (boundsDaCheckbox != null) {
				boundsDaCheckbox.x += boundsDaAreaComCheckboxBuscada.x;
				boundsDaCheckbox.y += boundsDaAreaComCheckboxBuscada.y;
			}
			System.out.println("boundsDaCheckbox: " + boundsDaCheckbox);
			return boundsDaCheckbox;
		}

		return null;
	}

}

Classe que consome o JNativeHook:

package main.listener;

import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyListener;

public class ListenerDeEventosNativos {

	public static void iniciar() throws NativeHookException {
		removerLogDoJNativeHook();
		registrarONativeHook();
	}

	private static void registrarONativeHook() throws NativeHookException {
		try {
			GlobalScreen.registerNativeHook();

		} catch (NativeHookException ex) {
			System.err.println("There was a problem registering the native hook.");
			throw ex;
		}
	}

	private static void removerLogDoJNativeHook() {
		// Clear previous logging configurations.
		LogManager.getLogManager().reset();

		// Get the logger for "org.jnativehook" and set the level to off.
		Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
		logger.setLevel(Level.OFF);
	}

	public static void addNativeKeyListener(NativeKeyListener listener) {
		// Construct the example object and initialze native hook.
		GlobalScreen.addNativeKeyListener(listener);
	}

}

Classe que processa quando “Enter” é teclado:

package main.listener;

import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class ProcessadorDeEventosNativos implements NativeKeyListener {

	/**
	 * Esses algoritmos serão executados toda vez que a Tecla ENTER for pressionada.
	 */
	private Runnable[] algoritmosParaExecutar;

	/**
	 * Os 'algoritmosParaExecutar' serão executado toda vez que a Tecla ENTER for
	 * pressionada.
	 */
	public ProcessadorDeEventosNativos(Runnable... algoritmosParaExecutar) {
		this.algoritmosParaExecutar = algoritmosParaExecutar;
	}

	@Override
	public void nativeKeyPressed(NativeKeyEvent e) {
		// System.out.println(arg0.getKeyChar());
		if (e.getKeyCode() == NativeKeyEvent.VC_ENTER) {
			System.out.println("Tecla ENTER pressionada!");
			for (Runnable algoritmo : algoritmosParaExecutar) {
				if (algoritmo != null) {
					System.out.println(algoritmo);
					algoritmo.run();
				}
			}
		}
	}

	@Override
	public void nativeKeyReleased(NativeKeyEvent arg0) {
	}

	@Override
	public void nativeKeyTyped(NativeKeyEvent arg0) {
	}

}

Veja que esta última classe usa um NativeKeyEvent.VC_ENTER, talvez você vá precisar usar também o NativeKeyEvent.VC_KP_ENTER, (não li a documentação para saber a diferença).

Bem, eu testei aqui e funciou muito bem. Sempre que você teclar Enter a Janela do programa mostra o que ele capturou da Tela, que é a Área-da-Seleção (onde os Números estão, e onde aparece a Seleção laranja do Ctrl+F), Caso a Seleção Laranja tenha sido detectada aparece também a “areaComCheckboxBuscada”, que é a área da Tela em que o programa acredita que estará a Checkbox correta a ser Clicada.
Essa Janela também mostrará a imagem que você criou para ser a partedecheckbox.png.

O programa clica na Checkbox encontrada (se ele encontrou) sempre que você Teclar Enter. Ele não vai desmarcar a Checkbox, porque os pixels dela vão estar diferentes quando ela estiver com o visto dentro.

D

A respeito do que eu falei da versão do JNativeHook:

  • Se você usar a mesma versão que eu, provavelmente não terá que mexer no código (quase certo);
  • Se você usar a versão mais recente que houver, talvez precise mexer no código se a forma de usar o JNativeHook tiver mudado, mas a vantagem é que a última versão sempre deve ser mas segura contra exploits, pois a biblioteca já deve ter sido alterada para inutilizar os exploits já conhecidos.

JNativeHook é open-source e , acho que isso aumenta segurança: muita gente olhando o código e avisando sobre bugs e problemas de segurança.

R

Boa noite, Douglas.

Acredito que vai atender as minhas expectativas e colaborar muito quando estiver executando, vou te agradecer a toda hora a cada post aqui viu rss, vai cansar de ler, mas não vou me cansar de agradecer, muito obrigada mesmo pela atenção e pelo programa.
Já fiz o download das imagens das imagens para configuração, assim que conseguir testar te aviso como ta rolando aqui, pode demorar um pouco porque vou depender dos acessos, mas vou verificar se consigo acesso externo pra isso. :blush:

R

Entendido Douglas, eu vou ver se dou conta de realizar os ajustes necessários, e pela segurança optar por algo mais recente então como sugeriu.
Obrigadassa por todas as informações, esclarecimentos e pelo programa, você é demais, eu fico admirada com esses códigos, e o que podem fazer. :smiley:

Me da uma ajuda por favor quanto as imagens por conter o nome e link da empresa oculta pra mim por favor, acredito que não de problemas, mas melhor evitar, já realizei o download.

D

Na testagem do programa, preste atenção no seguinte:

  • Se o programa fechar sozinho sem mostrar nada, provavelmente o que ocorreu é que ele lançou uma Exception que não foi tratada. Se isso acontecer após pressionar Enter, então a Exception deve ter ocorrido dentro do método ProcessadorDeEventosNativos#nativeKeyPressed(NativeKeyEvent e), aí você pode colocar um try/catch lá dentro que captura a Exception e exibe na Tela.
  • Se você testar o programa na IDE ela já deve mostrar qualquer Exception, mas se testar com o JAR exportado, talvez só apareça essas Exceptions não capturadas se rodar o programa pelo console.
  • Fique atenta ao que a Janela do programa exibe:
    1) Ao iniciar deve ser tudo cinza;
    2) Ao teclar Enter deve capturar e mostrar uma parte da Tela, que é a areaDaSelecao configurada, e que deve conter os números que podem ser selecionados pelo Ctrl+F;
    3) Se dentro dessa área capturada houver algum daqueles pixels laranja que são colocados pela Seleção do Ctrl+F, exatamente daquela cor, então a Janelinha deve mostrar também a área em que ela acredita que está a Checkbox.

Portanto, se “Área-da-Checkbox” não aparecer na Janelinha, significa que o programa não encontrou nenhum pixel laranja (exatamente daquela cor: R=225, G=150, B=50) dentro da “Área-da-Seleção”.

Se a “Área-da-Checkbox” aparecer na Janelinha mas não mostrar a checkbox a ser clicada por inteiro, ou mostrar partes de outras checkbox junto, você precisará mexer nas configurações:

  • margemInferiorAdicionada
  • margemSuperiorAdicionada
  • bordaEsquerdaDaAreaDeCheckbox
  • bordaDireitaDaAreaDeCheckbox

Se a checkbox a ser clicada aparecer por inteiro mas o programa não clicar nela, as causas podem ser:

  • O robô não conseguiu mover o cursor e clicar, mas eu acho que isso lançaria uma Exception e fecharia o programa.
  • Causa mais provável: a partedecheckbox.png não foi encontrada (não deu “match”) dentro da Área-de-Checkbox, se esse é o caso o console deve mostrar "boudsDaCheckbox: null" devido a isso:

Aí vai ser preciso gerar uma nova imagem partedecheckbox.png, talvez com um recorte menor para aumentar as chances de “match”.

Se der problema, me envia um recorte da tela com a Janelinha do programa.

R

Olá, Douglas.

Tudo bem, eu não consegui ainda permissão para testar na empresa :frowning:
Estou esperando que alguém la me ajude, mas é no tempo deles, vou tentar executar aqui conforme vem me explicando.
Uma duvida e talvez muito boba, eu consigo tornar o programa um executável ou algo portátil, acho que dessa forma eles me dariam mais atenção, acredito que não vão avaliar os códigos. Assim acredito que me deixariam executar, liberaram o Mouse Recorder Pro la, acredito que a sua implementação é meio que com a mesma função.
De qualquer forma assim que avançar aqui te aviso como rodou tudo, muito obrigada por toda ajuda. :blush:

D

Sim, dá pra fazer qualquer um dos dois. Eu acho que o melhor é ter o JAR exportado, acho que é o “mais portátil” possível, pois é simplesmente:

  • um arquivo .jar;
  • uma pasta “irmã” do Jar (fica dentro do mesmo diretório do Jar, um do lado do outro) chamada “images”;
  • e dentro dessa pasta “images” temos a “partedecheckbox.png”

Pra rodar, é só dar dois clicks no Jar. Também dá pra fazer um atalho dele, por praticidade.

Tem como gerar instalador também.

D

Você pode pesquisar por “exportar JAR” no NetBeans, no Eclipse é:

Clicar com botão direito no Projeto -> Export… -> Runnable Jar File -> (escolher a classe Main no assistente e a pasta de destino, dando um nome pro Jar) -> Finish.

Eu acho que o JAR roda em qualquer Sistema Operaciona com uma JVM que o aceite (aceite os recursos utilizados por ele e a versão do Java dele), deve ser aí que entra o “escreva uma vez e rode em qualquer lugar”.

Vou estar esperando pra saber o que aconteceu aí :slight_smile:

R

Ótimo então, vou tentar essa opção.
Obrigada mais vez. :smiley:

D

“images” é uma pasta dentro da pasta “src”, só isso. Dentro da pasta “images” tem a imagem partedecheckbox.png.

Não vejo porque o projeto teria uma estrutura diferente no NetBeans, no máximo, o NetBeans colocaria o import do JNativeHook em um lugar diferente.

Se o programa não encontrar a imagem na pasta e com o nome que está no código, lança uma Exception. Se as classes forem colocadas em packages errados, nem compila.

Você precisa prestar atenção nisso: As Configurações que falei, incluíndo a imagem partedecheckbox.png precisam ser alteradas/feitas sob-medida para o computador que vai rodar o programa (resolução da tela, sistema operacional, navegador). Tirando um PrinScreen da Tela desse computador com o sistema-web aberto do jeito que você me mandou aquelas imagens já deve ser o suficiente para você conseguir configurar para esse Computador.

Você tem que saber em qual computador irá testar o programa lá na empresa, e preparar as Configurações para que funcionem nesse computador.

Acho que um próximo passo nesse programa, seria colocar as configurações em um arquivo .txt que o programa iria ler e carregar; aí seria só editar esse arquivo .txt para alterar as configurações, sem ter que editar o código fonte e sem ter que re-exportar o Jar.

Posso te mandar a imagem partedecheckbox.png recortada de acordo com os printscreens que você me mandou, entretanto, é importante que você aprenda a criar essa imagem por si só, pra refazer sempre que necessário:

Para criar essa imagem, vá no Computador que rodará o programa, e faça o seguinte:

  1. Abra a Tela do Sistema-Web (como nas imagens que você me mandou);
  2. Tecle “PrintScreen”;
  3. Abra o Paint, dê Ctrl+V, a imagem deve aparecer no Paint;
  4. Dê Zoom no Paint sobre uma das Checkbox da imagem;
  5. Use a Ferramenta de Seleção Retangular do Paint image e selecione o interior da Checkbox, ou uma parte desse interior (anteriormente eu te enviei uma imagem "recortar partedecheckbox.png" que explica sobre o recorte do interior da checkbox);
  6. Após criar a Seleção Retangular, clique em Cortar image;
  7. Vá em “Salvar Como…” -> “Imagem PNG” -> salve com o nome partedecheckbox.png (tudo em letras minúsculas), dentro da pasta “images” do programa.

Se não ficou claro, veja aqui:


Vou te mandar no e-mail o projeto como tenho aqui.

:slight_smile:

D

Seu serviço de e-mail rejeitou meu e-mail (aparentemente por causa dos anexos zip):

D

JNativeHook-2.0.3.zip (611,9 KB)
ProjClicadorDeCheckbox.zip (20,7 KB)
ClicadorDeCheckbox.zip (196,0 KB)

Vi aqui que o GUJ permite anexar arquivos, são esses aí em cima.

Tem o programa exportado em JAR, eu percebi depois de exportar que é necessário que a pasta “images” fique dentro da pasta “src” como está no anexo, devido ao caminho relativo que eu coloquei no código: “src/images/partedecheckbox.png”.

Também estou enviando o Projeto do Eclipse, veja que precisa do JNativeHook na minha versão (mais antiga) para rodá-lo, colocando-o na pasta:

C:/Java/JNativeHook-2.0.3/JNativeHook/jar/jnativehook-2.0.3.jar (caminho escrito no arquivo .classpath do projeto).

Se você quiser a versão mais nova do JNativeHook, precisará baixá-la e importá-la pro projeto, e então usá-la.

Veja se consegue fazê-lo rodar aí :slight_smile:

R

Muito obrigada Douglas, e me desculpe por todo trabalho, preciso estudar bem mais sobre o assunto, pra mim ainda é tudo novo, e venho tentando aprender um pouquinho pela internet dentro do tempo que tenho um espacinho, mas vou procurar fazer um curso para tornar as coisas mais claras pra mim, tenho muito a aprender ainda. :open_mouth:
Obrigada de verdade pela paciência e ajuda quanto a tudo.

R

Oxe mais que estranho o e-mail ter rejeitado.
De qualquer forma, download realizado aqui, vou levar para empresa e verificar se consigo testar, depois vou ajustando conforme comentou, mas acredito que vai rodar lindamente. :smiley:
Muito mas muito obrigada mesmo.

D

De nada, vou ficar aguardando pra saber se deu certo :slight_smile:

R

Douglas, bom dia.

Acabei de realizar o teste, esta funcionando lindamente como disse rss, vou continuar testando durante o meu dia a dia, mas acredito que não vai ocorrer problemas. Fiz o recorte e ele identifica com sucesso, muitíssimo obrigada, e parabéns por esse projeto, você é demais. :smiley:
Estou eufórica com isso, é muito demais esse projeto, você não faz ideia do quanto me ajudou e otimizou minha vida aqui, no momento eu não consigo te pagar por isso, mas gostaria de mais a frente te dar uma $ por isso, se não tiver problemas tenta me encaminhar sua conta nesse e-mail que posso te transferir, veja se não vai voltar, pode demorar um pouquinho porque ainda não to podendo, e considera uma lembrança pela minha gratidão, mas conta com isso.
Que Deus continue te abençoando, obrigada.

R

Douglas,

Uma duvida, e não me mate por isso, quando o clicador realiza a função de encontrar o checkbox especifico o que esta rodando muito bem,ele habilita pra mim um botão “Imprimir Capa” , onde eu preciso clicar com mouse, e ira gerar um download, sabe me dizer o que consigo fazer para que no momento que o checkbox encontre o numero e eu clique enter alem de selecionar, ele também já pressione o botão “Imprimir Capa”, a logica é a mesma utilizada para os números, porem somente com a função “Imprimir Capa” percebi um pouco tarde esse detalhe, ele não mantem uma altura padrão . Muda muita coisa pra incluir mais essa função no clicador, ele poderia ser reconhecido pelo Ctrl-F também, mas dai não sei qual a maneira mais simples de executar, tem alguma ideia?

Obrigadaaaaa.

D

Fico muito feliz que deu certo e que Deus te abençou através da minha vida, essa alegria já é meu pagamento :smiley: Que Deus continue te abençoando!

Eu acho que, o código que o programa já tem pode ser bem reutilizado para implementar essa nova funcionalidade; principalmente através da classe BuscadorDeImagemDentroDeImagem.

É só uma questão de criar uma nova Área Retangular para buscar pelo botão, ter uma imagem do botão na Pasta “images”, e usar a classe BuscadorDeImagemDentroDeImagem para buscar pelo Botão dentro desta nova Área Retangular.

Pra clicar no Botão, o programa precisará de um gatilho, que pode ser uma outra Tecla do Teclado (talvez a tecla “Pause Break” ou “Scroll Lock” que parecem ser inúteis rsrs), ou, ele pode ser programado para clicar no botão após clicar na checkbox.

O que acontece é que o programa não tem uma Arquitetura bem pensada para o crescimento dele, porque pra fazer isso é preciso ter uma visão clara de como ele irá crescer. Começar adicionar funcionalidades nele sem refatorá-lo provavelmente vai transformá-lo em uma bagunça, dificultando mexer no código dele cada vez mais.

Outro ponto importante que você precisa levar em consideração é que um Clicador como esse está longe de ser a forma ideal para esse tipo de problema. Pelo que pesquisei, seria com uma Extensão no Navegador, que permite fazer mais que o Clicador, é mais fácil de fazer, tem menos chance de errar, pode dispensar configurações, e foram pensadas justamente pra isso (pelo que me lembro, se entendi bem, os criadores do sistema de extensões do chrome dizem que uma ótima finalidade em criar extensões é adicionar funcionalidades em páginas web por si só, sem depender dos criadores da página para adicionar funcionalidades, como é o seu caso).
Parece-me que teria sido muito mais rápido e fácil, e o resultado seria melhor, se essa solução tivesse sido feita (ou venha a ser feita) com uma extensão para o navegador.

Eu não fiz com uma extensão porque não sei nem o básico de Javascript, mas se você pretende seguir automatizando seu fluxo de trabalho nesse sistema web, o melhor que tem a fazer é aprender Javascript e HTML, e talvez um pouquinho de CSS; com esse conhecimento você já vai conseguir fazer uma Extensão e permitir que ela cresça.

Então agora acho que você precisa refletir sobre isso:

  • O que você espera desse programa para o futuro? Deseja continuar aumentando as funcionalidades de automação dele? Se sim, acho melhor você deixar esse programa como ele está e partir para a criação de uma Extensão de Navegador, vai ser bem melhor.
  • Se essa é a última funcionalidade a ser adicionada ao programa, se você está certa que não precisará modificá-lo depois para adicionar novas funcionalidades, então é viável mexer no código dele para adicionar essa funcionalidade apenas; ela seria então adicionada “rapidamente” (talvez alguns dias?) meio que na gambiarra, porque adicioná-la direito exigiria uma refatoração lenta na arquitetura (muitos dias, e muita análise para saber “pra onde” o programa vai crescer) que eu acho que não vale a pena fazer nesse programa porque ele não é uma boa solução pra esse tipo de problema: ele é a ferramenta errada, a Extensão seria a ferramenta certa.

Se bem que, também há outras opções que não havia pensado, como consumir uma API REST do sistema (se ele tiver), ou utilizar um Navegador sem GUI que é controlado pelo código. Essas opções automatizariam o processo fazendo o trabalho sem que você tenha que abrir o Navegador. Talvez o sistema também ofereça outro tipo de API que você poderia criar um programa para consumir.

Para automatizar o máximo, você teria que analisar todo seu fluxo de trabalho e separar o que um programa pode fazer do que só você pode fazer, assim, seria possível criar um programa onde você faz só o necessário e o programa faz o resto. Por exemplo, você usa Ctrl+F para digitar esses Números, mas da onde vem esses Números? Não seria possível fazer um programa que pega todos esses números automaticamente para que você não tenha que inserí-los manualmente? E depois que você clica em “Imprimir Capa” e os downloads são feitos, o que deve ser feito com esses Dowloads? Mandar para Imprimir? Enviar por e-mail? Você precisa analisar seu fluxo de trabalho e criar sua estratégia de automação a longo prazo.

Automatizar um fluxo de trabalho ao máximo não é algo trivial, precisa de análise e planejamento.

R

Amém Douglas, que abençoe a nos todos, muito obrigada.
No momento o clicador vai atender, conseguindo incluir essa funcionalidade de clicar no Imprimir dai já funciona exatamente como preciso, quando ele gera o download, clico em imprimir, depois Ctrl+P e o envio gera uma capa, dai é processo manual de novo, infelizmente a função ainda depende muito do processo manual, os números são extraídos de documentos físicos, então eu vou precisar digitar caso a caso, ou no minimo selecionar e fazer um check antes, mas consigo manusear o processo usando um Excel a base de Ctrl+C e Ctrl+V e exclusão, usando o Mouse Pro que havia comentado com você, ele vai repetir meu comando, ele só não atende em caso como esses no qual implementou pra mim, mas se fizer um comando no qual ele clica em um mesmo ponto não tem erro. Acredito que talvez tenha muita coisa a melhorar e que é possível sim obter essa base, mas la tudo entra como melhoria e ninguém da muita atenção sabe até porque gera custos, então estou tentando melhorar os pontinhos que tenho visibilidade e acesso. Mas acho super interessante a ideia da Extensão no Navegador, eu vou pesquisar sobre, não estou tendo muito tempo para me dedicar, mas vou estudando aos poucos, e entendendo melhor vou desenvolvendo e trocando ideias com vocês.

D

Vou ver se consigo implementar então.

Em que momento o programa deveria clicar no botão “Imprimir Capa”? Sempre após clicar numa checkbox? Após ter clicado em várias checkbox? Ou ao teclar uma outra Tecla específica (que não seja Enter nem nenhuma outra usada pelo Navegador/Sistema-Operacional)?

Acho que ter uma outra tecla te daria mais controle sobre o programa.

E depois de clicar em “Imprimir Capa”? O TextField do Navegador aberto pelo Ctrl+F perde o foco e não é possível digitar nele até clicar nele de novo; você gostaria que o programa então clicasse nele? Gostaria também que o programa fizesse Ctrl+A para selecionar tudo no campo deixando-o pronto para digitar um novo valor apagando o antigo?

Veja certinho como deve ser todo o fluxo de trabalho do programa para não ficar nada errado ou faltando, daí me diga; vou estar aguardando, e quando tiver um tempo implemento. :slight_smile:

R

DOUGLAS: Em que momento o programa deveria clicar no botão “Imprimir Capa”? Sempre após clicar numa checkbox? Após ter clicado em várias checkbox? Ou ao teclar uma outra Tecla específica (que não seja Enter nem nenhuma outra usada pelo Navegador/Sistema-Operacional)?

R: Deve clicar no “Imprimir Capa” sempre após clicar na Checkbox.

Ele nunca vai selecionar varias checkbox de uma só vez, sera uma para cada impressão gerada.

Como estou usando o Mouse Record Pro ele não está selecionando a Checkbox quando clico Enter, ate tentei usar o teclado virtual mas não sei porque não esta selecionando, ele só funciona quando eu gravo o primeiro comando, quando aperto play para executar como um robo ele nao entende o Enter e não seleciona a checkbox.

O clicador funciona de forma manual corretamente, apenas com o Mouse Record Pro, que ele esta dando erro.

Pensei nesse caso em apenas habilitar a área da Checkbox para que eu pudesse clicar de forma manual mesmo, ao invés de pressionar o “Enter” gostaria de clicar com o mouse na checkbox, isso é possível?

DOUGLAS: E depois de clicar em “Imprimir Capa”? O TextField do Navegador aberto pelo Ctrl+F perde o foco e não é possível digitar nele até clicar nele de novo; você gostaria que o programa então clicasse nele?

Depois de imprimir a capa o que seria legal é que fosse possivel limpar a Checkbox selecionada, assim conseguiria selecionar outra Checkbox, mas isso é só um detalhe viu, da forma que esta, to conseguindo utilizar.

DOUGLAS: Gostaria também que o programa fizesse Ctrl+A para selecionar tudo no campo deixando-o pronto para digitar um novo valor apagando o antigo?

Se esse procedimento for capaz de limpar a Checkbox isso ajuda bastante, mas caso for dar trabalho demais não precisa mexer.

Pontos que já resolveria :

Acionar o botão “Imprimir Capa” , se for por comando do Mouse acredito que vai rodar melhor devido ao uso da ferramenta Mouse Record Pro.

Alterar o gatilho da Checkbox para clique do Mouse.

Se possível : opção para limpar o Chekbox após todas ações.

R

Fluxo : Mouse Record Pro + Clicador

1 - Pagina Web e Excel com n° xxxx ou xxxx / xxxx abertos.
2 - Ctrl+F pagina web
3 - Ctrl+C / Ctrl+V - Campo Ctrl+F
4 - Executar Clicador
5 - Checkbox Selecionado
6 - Imprimir Capa
7 - Download Realizado
8 - Ctrl+P
9 - Impressão Realizada.
10 - Processo Manual
Posterior o Mouse Pro ira repetir tudo isso para o próximo número.

D

Esse problema que você relatou provavelmente indica que o JNativeHook não consegue ouvir os Eventos de mouse e teclado lançados pelo Mouse Record Pro.

Vou te enviar um programinha que fiz aqui para você testar isso:
OuveTudo.jar (195,4 KB)

Coloca esse programinha para rodar e depois coloca o Mouse Record Pro para teclar Enter, teclar outras Teclas (como A, B e C), mover o cursor, e dar clicks.

Esse programinha tá usando o JNativeHook na mesma versão, para ouvir “tudo”, vamos ver se ele consegue ouvir os eventos do Mouse Record Pro.

Eu não sabia que você estava usando algo como o Mouse Record Pro para ativar o Clicador (falta de levantar bem os requisitos e de uma boa análise dos casos de uso né? rs), mas agora que sei, tive uma ideia que pode dispensar o JNativeHook do Clicador: O Clicador pode ter apenas um botão numa Janelinha que ficaria sempre visível (alwaysOnTop), aí o Mouse Record Pro simplesmente clica nesse botão para ativar o Clicador!

O que você acha? Testa essa nova versão:

ClicadorDeCheckbox.zip (196,5 KB)

R

Douglas, bom dia.

É exatamente isso, a versão nova super atende, fiz o teste e funciona muito bem, para acionar o botão “Imprimir Capa” é possível fazer da mesma forma? Eu só não sei se vai dar mais trabalho porque o pixel dele tem vários na mesma cor, não é como o selecionador do Ctrl+F na cor laranja que fixa no exato.
Acho que cheguei a comentar sobre o Mouse Pro sim, mas não detalhei como agora, me desculpe, e mais uma vez agradeço pelo seu tempo dedicado, muito obrigada mesmo, não conseguiria fazer tão rápido e sozinha isso tudo, é muita informação rss, quanto mais vejo as coisas funcionando, mais vontade da de aprender tudo logo , você é muitoooo bom. :scream:
O programa “OuveTudo” a empresa bloqueia a instalação, mas a nova versão esta incrivelmente funcionando. :smiley:

D

É verdade, você já havia falado que estava usando Mouse Record Pro em conjunto, eu não tinha percebido que isso seria importante rs. Bem, já que o Clicador será ativado por um botão na Janela dele, vou remover o JNativeHook dele e assim ele vai parar de funcionar ao Teclar Enter, vai funcionar só por Click no Botão dele, ok?

Para o Clicador conseguir reconhecer o botão “Imprimir Capa” vou precisar que você me envie um recorte deste Botão estando habilitado (roxo mais forte, quando ele fica clicável, logo após selecionar uma checkbox). Faça esse recorte tirando um PrintScreen da tela, colando no Paint, e cortando no Paint mesmo, como eu expliquei para fazer com a “partedecheckbox.png”.

Sobre limpar a checkbox selecionada, faça esse teste: selecione uma checkbox e experimente dar um F5 para atualizar a página e veja se a checkbox selecionada é limpa.

Se isso não funcionar, provavelmente o Clicador vai precisar clicar na checkbox para deselecioná-la. A forma mais fácil de implementar seria fazer o Clicador guardar as coordenadas X e Y da checkbox que ele clicou, e clicar nessas mesmas coordenadas logo após clicar em “Imprimir Capa”; mas para isso funcionar a checkbox não pode mudar de lugar após clicar em “Imprimir Capa”, e eu acho que ela vai mudar de lugar porque o Chrome faz aparecer uma faixa de downloads em andamento no fim da janela dele:


Veja se a checkbox aí mudará de lugar. Se essa barra já estivesse visível antes de toda a execução do Clicador, provavelmente a Checkbox não mudaria de lugar e essa implementação daria certo.

A melhor forma de fazer, e um pouco mais trabalhosa, é fazer o Clicador buscar pela(s) Checkbox(es) Seleciona(s) na Área-de-Checkboxes e clicar nela(s). Para fazer isso, vou precisar que você também me envie um recorte de uma checkbox selecionada (✓), feito com PrintScreen->Paint também, para que nenhum pixel seja alterado.

Fiquei com dúvidas sobre o que ocorre após clicar em “Imprimir Capa”:

  1. Um Download começa, mas como um programa irá saber quando esse Download terminou para poder dar continuidade aos processos sem intervenção humana? É o Mouse-Pro que será o responsável por detectar quando o Download terminar e por dar continuidade ao trabalho automaticamente?
  2. O Atalho Ctrl+P é feito automaticamente, mas ele é feito na Janela do Chrome? Se sim, isso abre uma tela para configurar a impressão que tem um botão “Imprimir”, será o Mouse-Pro que fará o “Ctrl+P” e que clicará nesse botão “Imprimir”? Se sim, você já verificou se esse botão “Imprimir” sempre aparecerá no mesmo lugar da Tela para que o Mouse-Pro sempre consiga clicar nele?
    2.1 Na verdade, eu imagino que o que você deve ter feito é isso: Após o Download terminar você configurou o Chrome para “Sempre abrir arquivos deste tipo” ou está usando o Mouse-Pro para abrir o Arquivo, e, com o Arquivo aberto (não sei se é imagem, PDF, ou outro) o Mouse-Pro faz o “Ctrl+P” para abrir o diálogo de impressão do programa que abriu o arquivo (Visualizador-de-Imagens/Visualizador-de-PDFs?), e, o prórprio Mouse-Pro clica em imprimir. é isso? Bem, se é isso, você verificou se o Mouse-Pro sempre conseguirá fazer tudo isso sozinho?

image

Essas dúvidas são importantes porque, se o Mouse-Pro não for capaz de automatizar esses processos o Clicador precisará ser, aí tenho que ter em mente o que ele precisará fazer para prepará-lo pra isso.

D

Encontrei uma extensão no Chrome que pode ser usada (talvez até pelo Mouse-Pro) para desmarcar todas as checkbox, veja o que você acha:

image

R

Belezinha Douglas, pode desabitar sim a tecla Enter para seleção do Checkbox.

Segue o recorte, fiz dentro e ele por completo.

ImprimirCapaCompleta

ImprimirCapaDentro

Sobre o limpar a Checkbox pode desconsiderar, eu testei o F5 mas o Mouse Pro se perde, porem verifiquei um botão no sistema que consigo limpar, ele não muda de lugar e vai funcionar bem.

  1. Um Download começa, mas como um programa irá saber quando ele terminou para poder dar continuidade aos processos sem intervenção humana? É o Mouse-Pro que será o responsável por detectar quando o Download terminar e por dar continuidade ao trabalho automaticamente?

Não havia pensado nesse ponto, mas pelo teste que fiz é cerca de 5 segundos para o arquivo abrir, não é pesado, o meu Chrome eu habilitei para abertura do documento direto com o Adobe, então ele não tem aquela faixa de download do Chrome, porem acho que corro um risco aqui talvez, mas seguro o Mouse Pro por 5 segundos de espera e depois aciono o Ctrl+P, essa seria minha ideia.

  1. O Atalho Ctrl+P é feito automaticamente, mas ele é feito na Janela do Chrome? Se sim, isso abre uma tela para configurar a impressão que tem um botão “Imprimir”, será o Mouse-Pro que fará o “Ctrl+P” e que clicará nesse botão “Imprimir”? Se sim, você já verificou se esse botão “Imprimir” sempre aparecerá no mesmo lugar da Tela para que o Mouse-Pro sempre consiga clicar nele?

Exatamente isso,todo o processo será conduzido pelo Mouse Pro, quando eu clicar Imprimir Capa, ira abrir direto a pagina do Adobe Reader maximizada e não aquela barra do download do Chrome, a janela é fixa nesse procedimento até clicar imprimir que é o final do processo, testado com o Mouse Pro, ele consegue. rss

R

Douglas muito interessante a extensão, já instalei funciona lindamente, vou usar. :smiley:

D

Eu estava vendo sobre um Mouse Recorder aqui, não sei se é o seu, veja:
http://www.mouserecorder.com/docs/09/manual.htm

diz haver a opção de fazer o programa esperar até um pixel da tela assumir determinada cor:

Acho que você poderia usar essa opção para esperar o Adobe Reader abrir, fazendo o programa detectar um dado pixel da tela que muda de cor quando o Adobe Reader abrir. Experimente testar isso.

Funcionaria assim:

  1. O Mouse-Recorder clicaria no Botão do Clicador ativando-o, e então fica aguardando aparecer o pixel do Adobe Reader;
  2. O Clicador clica na Checkbox e no botão “Imprimir Capa”, o Chrome faz o Download e então abre o PDF no Adobe Reader;
  3. O Mouse-Recorder percebe o pixel do Adobe Reader e executa os comandos de Impressão (Ctrl+P, etc.)

E depois disso? o Mouse-Recorder vai conseguir fechar o Adobe Reader deixando tudo pronto para reiniciar todo o processo?

Testa aí, vamos ver se ele consegue. :smiley:

R

Esse parece bem mais completo e inteligente, o que uso é o Mouse Record Pro eles são diferentes, não sei se ele possui essa função. Vou dar uma analisada depois … Já sai da empresa agora, vou baixar esse que enviou e conseguindo instalar la eu faço o teste pela manhã e já te conto como foi, Isso seria ótimo , porque em caso de uma página não abrir entendo que ele pause por motivo do pixel não ser identificado, ou vai se perder mesmo. Rss
Com o Mouse Pro que uso, ele consegue sim fechar o Adobe e reiniciar o processo, so não tenho como mensurar o exato tempo do download, no caso quando a página do Adobe abre.

D

Bem, alterei o Clicador para ele conseguir clicar no Botão Imprimir, mas não testei aqui.

Também adicionei um Arquivo de Configurações, dentro da pasta src; você vai poder alterar a posição e tamanho da Janela do Clicador, e as demais configurações. Você pode adicionar comentários nesse arquivo se a linha deles começar com //, assim:

//Esta é uma linha de Comentário
IMAGEM_DE_UMA_CHECKBOX: "src/images/partedecheckbox.png"
IMAGEM_DO_BOTAO_IMPRIMIR: "src/images/botaoimprimir.png"
//Este é outro Comentário
COR_DA_SELECAO_RED: 255
COR_DA_SELECAO_GREEN: 150
   //Essa linha não começa com // pois começa com espaços, o programa pode "bugar" por causa disso.
COR_DA_SELECAO_BLUE: 50

ClicadorDeCheckbox.zip (16,0 KB)

R

Bom dia. :grin:

Vou testar e jaja te conto, muito mas muito obrigada mesmo. Não faz idéia do quanto esta me ajudando. Que Deus te abençoe muito e sempre.

R

Douglas,

Duvida: Como o botão Imprimir Capa vai funcionar, automático apos selecionar o Checkbox?

D

Sim, após clicar na checkbox ele já vai clicar no Botão “Imprimir Capa”, não tem nenhum delay também.

R

Humm, entao não funcionou, o que pode ser, faz idéia? Ele só ta selecionando a Checkbox, mas não acionou o botão Imprimir.
Não sei se daria mais trabalho, mas se tivesse junto ao botão Checkbox o botão Imprimir Capa eu poderia acionar com o Mouse também, acho que automático se ele clicar errado é um problema apesar de mais prático.
Obrigada.

D

Se não clicou no botão “Imprimir Capa” provavelmente foi porque ele não identificou o botão.

Você pode tentar fazer um novo recorte do botão e substituir a imagem “botaoimprimir.png” com esse novo recorte; pode até tentar recortar uma área menor para aumentar as chances de match.

Também pode ser um problema na configuração da Área-do-Botão, verifique se o botão fica dentro dessa área (veja o arquivo de configurações para saber a posição e tamanho dessa área).

O Clicador não está buscando pela cor roxa do botão, está analisando os pixels do botão o que inclui os pixels do texto dentro dele. Por causa disso, ele não vai clicar no botão errado, o que pode acontecer é ele não clicar, como ocorreu.

Se não for um desses problemas de configuração, deve ser problema na lógica dele, aí vou ter que dar um jeito de testá-lo aqui.

R

Entendi, vou testar um novo recorte e te aviso se funcionou. :wink:

D

Pelos testes que fiz aqui, funciona quando se aumenta o valor de AREA_DO_BOTAO_IMPRIMIR_WIDTH: para uns 300 ou mais:

AREA_DO_BOTAO_IMPRIMIR_WIDTH: 300

Não sei porque, com um width menor o botão já era capturado por completo.

de qualquer modo, você pode experimentar aumentar o WIDTH e o HEIGHT, e, diminuir o valor de AREA_DO_BOTAO_IMPRIMIR_X e de AREA_DO_BOTAO_IMPRIMIR_Y.

Desde que você tenha um recorte “botaoimprimir.png” que contém o texto “Imprimir Capa” sem estar cortado, o Clicador não irá clicar no botão errado.

Tenha em mente que a AREA_DO_BOTAO_IMPRIMIR não pode ficar maior que a tela (veja a resolução da sua tela), se não vai lançar uma exception após clicar na checkbox e vai finalizar sozinho. Nenhum dos valores de AREA_DO_BOTAO_IMPRIMIR podem ser negativos.

Hum… no teste que fiz aqui, mudando as configurações ele funcionou para 2 das três imagens “print-screen” que você havia me mandado, não funcionou para aquela em que o botão fica bem mais em baixo.

Se alterar as configurações não resolver, será necessário alterar a forma como o Clicador procura pelo botão.

R

Douglas,

Aqui não consegui, a não ser que estiver fazendo da forma errada.
Me manda a imagem e a configuração que esta usando pra que eu teste aqui.

Obrigada.

D

Qual a resolução do seu monitor aí? 1600x900?

Dá pra colocar pra buscar o botão em toda a tela, seria assim:

AREA_DO_BOTAO_IMPRIMIR_X: 0
AREA_DO_BOTAO_IMPRIMIR_Y: 0
AREA_DO_BOTAO_IMPRIMIR_WIDTH: 1600
AREA_DO_BOTAO_IMPRIMIR_HEIGHT: 900

Com essa configuração ele conseguiu encontrar o botão nas 3 imagens print-screen que você havia me mandado. Só que eu estou utilizando uma imagem do botão desabilitado, porque nas imagens que você me mandou esse botão estava desabilitado.

R

Isso mesmo 1600x900.

D

Tenta com as cofigurações que passei acima (editei a resposta de cima após você respondê-la), e com o recorte do interior do botão feito no Paint como havia explicado, se isso não funcionar:

  • tenta rolar a página e clicar no botão do Clicador para ver se com o botão “Imprimir Capa” em uma nova posição ele detecta, tente isso algumas vezes. Talvez os pixels do botão “Imprimir Capa” mudem ao rolar a página, talvez por questões renderização (mas acho pouco provável).

No fim, se não der certo mesmo, vou ter que tentar outra coisa no algoritmo do Clicador.

D

Já baixei essa imagem.

Descobri +1 bug aqui na lógica do clicador:

Ele tira um printscreen antes de clicar na checkbox, e não tira um novo para procurar pelo botão “Imprimir Capa”, por isso, se o botão “Imprimir Capa” estava desabilitado antes do Clicador clicar na checkbox, ele não encontrara esse botão.

Você pode testar isso de duas formas:

A) clique em uma checkbox qualquer para habilitar o botão “Imprimir Capa”, depois selecione com Ctrl+F o número de outra checkbox e clique no botão do Clicador para que ele marque essa outra checkbox. O clicador deverá ser capaz então de clicar no botão “Imprimir Capa” porque ele estava habilitado no momento em que você acionou o Clicador.

B) Substitua a imagem “botaoimprimir.png” por um recorte do botão “Imprimir Capa” desabilitado, como esse:btdesabilitado, o Clicador irá então procurar pelo botão desabilitado na imagem que ele capturou enquanto esse botão ainda estava desabilitado.

Continue usando essas configurações:

AREA_DO_BOTAO_IMPRIMIR_X: 0
AREA_DO_BOTAO_IMPRIMIR_Y: 0
AREA_DO_BOTAO_IMPRIMIR_WIDTH: 1600
AREA_DO_BOTAO_IMPRIMIR_HEIGHT: 900

Depois vou tentar corrigir esses bugs, assim que tiver um tempo.

Obs: você precisa excluir suas respostas com imagens, apenas remover a imagem da resposta irá fazer com que a imagem continue no histórico de edições.

R

Douglas,

Muito obrigada viu, e desculpa todo o trabalho, amanha vou testar as alternativas e te aviso.
Obrigada por avisar das imagens também, vou excluir aqui. :blush:

R

Douglas,

Realizei os testes aqui mas não funcionou ele não identifica o botão “Imprimir Capa” mesmo desabilitado.
Não teria que programar a Checkbox assim que selecionada para depois acionar o botão Imprimir Capa ou sei la, é possível programar a quantidade de caracteres da palavra Imprimir Capa.
Estou dando ideias sem noção da possibilidade viu, então me desculpa se estiver falando bobagem.

Pensei de outra forma também, talvez criar um botão no clicador igual ao Checkbox para que eu também consiga acionar clicando com o Mouse, mesmo que tenha que digitar no Ctrl+F para buscar a o “Imprimir Capa” não teria problemas, se funcionar e não der muito trabalho poderia ser. Veja o pixel selecionado com o Ctrl+F na imagem.

sele%C3%A7%C3%A3opixel_ImprimirCapa

D

Vou tentar fazer uma extensão para o chrome que clica nesse botão.

Pequei aqui uma extensão do GitHub, e já consegui fazer ela clicar no botão “Developer Jobs” do StackOverflow.

Para funcionar, precisa do “id” html do botão, que no caso aqui era “nav-jobs”:

Vou precisar que você consiga esse id para o botão “Imprimir Capa”, basta clicar nele com o botão direito do mouse e clicar em “Inspecionar”, o Chrome abre então uma janela como a de cima, onde você deve encontrar o “id” do botão, como mostrado acima.

Essa é a extensão como está agora:

ImprimirCapa.zip (7,2 KB)

Atualmente, ao acioná-la ela vai tentar clicar num botão de id “nav-jobs” que esteja presente na página, e não faz nada se não encontrar na página algo com esse id.

Você pode testá-la no site https://stackoverflow.com, ao usá-la nesse site, ela irá abrir a aba “Developer Jobs”.

Antes de acionar o botão, ela mostra uma mensagem “Vou clicar no Botao!”, que serve para testar se ela está funcionando; essa mensagem poderá ser removida.

O único código que precisa ser alterado nela está no arquivo alert.js, que atualmente é assim:

alert("Vou clicar no Botao!");
document.getElementById("nav-jobs").click();

você poderá remover essa linha “alert("Vou clicar no Botao!");”, e, terá que mudar o “nav-jobs” pelo id do botão “Imprimir Capa” (que você terá que descobrir qual é), ficando algo assim:

document.getElementById("imprimir-capa").click();

Para adicionar essa extensão ao chrome, você pode seguir os passos desse artigo que ensina a criar sua primeira extensão e testá-la no chrome.

Veja que, na hora de adicioná-la ao chrome você precisará simplesmente procurar e selecionar a pasta “ImprimirCapa” que te mandei dentro desse zip (extraia a pasta do zip ao invés de tentar selecionar o zip).


Obs.: Quando editar os arquivos da extensão, certifique-se de que você não colocou nenhuma letra com acento ou símbolo “estranho”, digo isso porque quando eu escrevi “Botão” ao invés de “Botao” não funcionou, “bugou” por causa do “ã” e nem mostrou mensagem de erro. Deve ter como configurar a codificação de caracters, mas não sei como.

D

A respeito do Clicador nem sempre encontrar todos os pixels laranja do Ctrl+F, na hora de selecionar um dos Números, talvez o problema seja a configuração da AREA_DA_SELECAO; pela imagem que você me mandou, você pode ver que a captura está cortando o comecinho dos números. Talvez essa área também não tenha um Height grande o suficiente.

Faça o seguinte, role a página para uma posição em que o Clicador não encontra os pixels laranja, acione o Clicador e veja a Captura dele (pode redimensionar a Janela do Clicador se necessário): Veja se o número Selecionado de laranja coube bem dentro da imagem capturada, ou se está cortado.

Se o número com sua seleção laranja couberam bem dentro da imagem capturada, o problema não é de configuração e vai ser mais difícil resolver. Caso contrário, deve ser problema de configuração mesmo.

A área da seleção é controlada por essas propriedades, mude os valores delas conforme o necessário:

AREA_DA_SELECAO_X: 674
AREA_DA_SELECAO_Y: 318
AREA_DA_SELECAO_WIDTH: 103
AREA_DA_SELECAO_HEIGHT: 492

R

Que máximo, Douglas. :scream:
Ja estou ansiosa pra testar, na segunda eu vejo como funciona no sistema da empresa.
Muito muitooo obrigada por tudo!!!

R

Essa parte de não selecionar o pixel laranja só ocorreu quando tentamos selecionar o botão imprimir capa, dai as vezes não capaturava, mas ta funcionando totalmente, quando estiver tudo ok, dai vou realizar um teste com uma massiva pra ver se o Mouse Pro acompanha. Mas ta perfeito Douglas, o que for ocorrendo tento ajustar as configurações como falou. Conseguindo acionar o botão Imprimir Capa com a extensão já devo conseguir executar a demanda. Muito muito obrigada :pray:

D

Se funcionar com essa extensão, acho uma boa ideia remover do Clicador o código no qual ele tenta encontrar o botão “Imprimir Capa” e clicar nele, assim diminuirá a chance dele fazer algo errado após clicar na checkbox.
Daí eu te envio também o Projeto do Clicador para que você possa editá-lo no futuro, se precisar.

Mas por agora, vamos ver se a extensão vai dar certo. :slight_smile:

R

Bom dia, Douglasssss.

Teste realizado com sucesso, funcionou!!! :star_struck::star_struck:
Você é o cara, muito muito obrigada :blush:
Ah me manda sim o projeto por favor, se necessário eu edito, você é demais. Obrigadaaa mesmo.

D

Que bom que funcionou :smile: estou enviando o Clicador e o Projeto:

ClicadorDeCheckbox.zip (14,3 KB)
ProjClicadorDeCheckbox.zip (22,5 KB)

Tirei o código que tentava clicar no botão “Imprimir Capa”, e deixei a Janela do Clicador mais informativa:

  • O Fundo dela fica verde quando o Clicador conseguiu clicar na checkbox (ou tentou clicar nela);
  • O Fundo dela fica vermelho se não deu certo, por qualquer coisa não ter sido encontrada;
  • Ela mostra separadamente a área com o número Selecionado pelo Ctrl+F, ou não mostra caso não tenha encontrado;
  • Só mostra a área da checkbox se tiver encontrado o número Selecionado pelo Ctrl+F.
R

Muitíssimo obrigada Douglas, me ajudou demais. Parabéns pelo projeto, eu achei realmente incrível e com certeza vai me ajudar muito no dia a dia, ainda estou realizando testes, mas parece que vai rodar conforme o necessário. :tada::blush::kissing_closed_eyes:

R

O mouse record Pro não ta acompanhando o clicador. :confused: Ele ta clicando errado em alguns momentos, não seleciona o pixel laranja com efetividade , tentei mexer nas configurações mas ainda assim ta rolando esse bug, não sei se é do clicador ou o Mouse Pro. Mas acredito que seja o Mouse Pro, porque ele so erra quando gravo o comando. Vou tentando ajustar e em paralelo pensar em uma extensão para o chome algo que talvez dispense o Mouse Pro e realize o comando sozinho, sei la. Baixei aquele outro programa que mandou do Mouse Premium, mas ele tbm se perde. Caso tenha alguma idéia, compartilha cmg. Desde ja muitíssimo obrigada por tudo!!! A idéia foi fantástica

D

:frowning:

Para descobrir o problema provavelmente você vai precisar conseguir identificar pelo menos um caso em que essa automação falhe, e precisa ser capaz de reproduzir esse caso de falha outras vezes.

Aí é necessário investigar o que está acontecendo. A janela do Clicador te dá informação sobre o que ele conseguiu fazer e o que não conseguiu, toda vez que você clica no botão dele. Por exemplo, se o Mouse Pro realmente clicou no botão do Clicador, então a Janela do Clicador ficará verde ou vermelha, se não ficou, significa que o Mouse Pro não clicou no botão ou o click dele apenas colocou a janela do Clicador em Foco (ou que há um Bug no Clicador, o que é menos provável já que você disse que ele funciona quando operado manualmente).

Coloque para rodar um caso que você sabe que vai falhar, e coloque delays nas ações do Mouse Pro para acompanhar lentamente o que ele está fazendo, o que dá errado, e a partir disso tente descobrir porque deu errado. Talvez seja só a necessidade de haverem delays maiores entre as ações, para aguardar o tempo do Clicador e do Navegador fazerem seus trabalhos após cada comando.

Quando for consertado o problema, você precisará reproduzir esse mesmo caso para ter certeza que o problema realmente foi consertado e que agora funciona nesse caso.

O Clicador? Está clicando no lugar errado ou no momento errado? Está clicando fora da Checkbox? Se sim, verifique se não está havendo rolagem da página durante a ativação do Clicador, se não for isso, é provavel que o recorte do interior da checkbox tenha que ser maior.

Identifique um desses casos onde o Clicador não reconhece o pixel laranja, e experimente usá-lo manualmente nesse caso para ver o que ele está capturando. Ele capturou o número selecionado em laranja por inteiro? Ele mostrou a captura do número em separado? Ele mostrou a área capturada em que espera encontrar a checkbox a ser clicada?

Se ele capturou a Seleção Laranja mas não a reconheceu, é provável que os pixels dela estejam contaminados de outra cor.

No fim, a depuração exige esse trabalho de investigação mesmo, existe muitas possibilidades que podem estar levando às falhas, então precisa investigar.

Sobre passar o trabalho para extensão, vamos ver se está meio fácil, faz o seguinte:

  1. Clique num dos Números que seriam selecionados pelo Ctrl+F com o botão direito, clique em “Inspecionar”.
  2. Na aba “Elements” que abriu você deve ver o Elemento HTML desse Número selecionado, em azul, clique com o botão direito nele e então clique em “Copy > Copy selector”;
  3. Cole aqui como resposta. Deverá ser algo como “#post_85 > div > div.topic-body.clearfix > div.regular.contents.avoid-tab > div > p”.
  4. Faça o mesmo para a checkbox desse mesmo Número.

O que espero encontrar é um ancestral comum entre a Checkbox e o Número.

R

Douglas,

Realmente o Mouse Record seleciona corretamente a Checkbox com a ajuda do clicador, mas ao mesmo tempo ele tira a seleção quando no automático, é como se ele usasse 2 cliques, quando aciono o clicador ele leva o cursor do mouse diretamente na Checkbox e ali mesmo ele tira a seleção da Checkbox, isso no automatico.

D

Que estranho.

Talvez o Clicador esteja dando um click na checkbox e o Mouse Pro se encarrega de dar o outro click, tenta colocar um delay no Mouse Pro logo após ele dar o click no botão da janela do Clicador, e deixe o Mouse Pro mover o cursor para outra posição após esse delay.

O Código do clicador também poderia ser editado facilmente para que ele pare de clicar e apenas mova o cursor para cima da checkbox, deixando o click a cargo do Mouse Pro.

R

Realmente, muito estranho, vou verificar com esse delay. E depois tento alterar o código caso não funcione.
Muito obrigada pela atenção. :kissing_closed_eyes:

D

O que o selector pegou, que você me mandou, parece ser ids; o Número e a Checkbox possuem cada um o seu id, e eles são semelhantes.

Existe um padrão nesses ids, mas não sei se esse padrão se repete para todos os itens da lista, ou se vai se repetir para todas as telas.

Para extensão funcionar, acho que seria assim:

  1. Haveria um TextField adicionado pela extensão na página, que substituiria o do Ctrl+F, do lado dele teria um botão “Imprimir” também adicionado pela extensão;
  2. O Mouse Pro iria inserir o Número no TextField e clicar nesse botão “Imprimir”;
  3. O Número no TextField é enviado para uma função javascript que irá buscar pelo elemento na página que possui esse Número;
    3.1 Essa iteração talvez possa ser feita pelos ids dos labels, no id que você me mandou tinha um “02” que se repete duas vezes, não sei se há um valor diferente para cada linha para que se possa iterar.
    3.2 Através desse id deve ser possível pegar o número para compará-lo com o inserido no TextField, mas como pegá-lo? Para saber isso, vou precisar que você veja que tipo de elemento tem esse id.
  4. A partir do id correto do Numero, devemos conseguir montar o id da checkbox, tendo o id da checkbox deve ser só dar um .checked = true nela.

document.getElementById("checkboxid").checked = true;

Como eu não conheço bem esses mecanismos extensão+javascript+html seria um tanto difícil pra mim fazer isso. Acho que está mais fácil fazer o Clicador funcionar com o Mouse Pro, até porque já está quase funcionado.

Continue com os testes, e se precisar de ajuda com o código do Clicador pode me chamar. Vou estar aguardando os resultados.

Deus te abençoe.

R

Vou estudar melhor esse projeto da extensão e depois tento criar, muito obrigada pela idéia.
Hoje realizei alguns testes com um delay, e a Checkbox permaneceu clicada :pray:, pelo menos não esta mais selecionando e tirando a seleção. Agora o erro esta ocorrendo nos numeros com barra xxxxxx / xxxxxx , a checkbox é clicada fica verde, mas não seleciona.E o engraçado é que se o comando repete ele seleciona corretamente. Vou checar essa captura, altura e largura, se bem que ele me mostra certinho o número capturado, mas vou verificando caso a caso, de qualquer forma me parece que com o delay vai rodar legal. O resto acredito ser somente ajuste de configuração. Muito obrigada por ter me ajudado tanto viu, de coração mesmo! Amém que Deus abençoe você também.

D

Não sei se é o problema, mas imagino que quando o Clicador clica na checkbox, o Navegador não é a Janela em Foco (o Clicador que é), portanto, talvez, o click do Clicador esteja apenas colocando o Navegador em foco.

Outra possibilidade, é que o Clicador não esteja clicando bem certinho no interior da checkbox, acho que isso aconteceria se o recorte da checkbox estiver muito pequeno e sendo detectado numa lateral da checkbox.

O Clicador procura clicar bem no meio da área recortada que deu “match”.

No caso do problema ser a falta de foco no Navegador, dá para lidar com isso de diferentes formas, como fazer o Clicador clicar na Janela do Navegador (para ela ganhar foco) antes de clicar na checkbox, ou mesmo colocar um delay no Clicador para que, antes de ele clicar na Checkbox, o Mouse Pro tenha tempo de clicar na Janela do Navegador para que ela ganhe foco.

Olha o método na classe “Clicador”:

public boolean clicarNaCheckbox() {
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		BufferedImage screenCapture = robo.createScreenCapture(new Rectangle(0, 0, screenSize.width, screenSize.height));
		Rectangle boundsDaCheckboxEncontrada = buscadorDaCheckboxDaLinhaSelecionada.buscarCheckboxDaLinhaSelecionada(
				screenCapture);
		System.out.println(boundsDaCheckboxEncontrada);
		if (boundsDaCheckboxEncontrada != null) {
			int centroDaCheckBox_X = boundsDaCheckboxEncontrada.x + (boundsDaCheckboxEncontrada.width / 2);
			int centroDaCheckBox_Y = boundsDaCheckboxEncontrada.y + (boundsDaCheckboxEncontrada.height / 2);
			clicar(centroDaCheckBox_X, centroDaCheckBox_Y); //Aqui clica na checkbox
			System.out.println("Clicou na Checkbox - x: " + centroDaCheckBox_X + ", y: " + centroDaCheckBox_Y);
			return true;
		}
		return false;
	}

Veja a linha clicar(centroDaCheckBox_X, centroDaCheckBox_Y);, antes dela você poderia colocar um clicar(posXdaJanelaDoNavegador, posYdaJanelaDoNavegador);com as coordenadas de um ponto na Janela do Navegador que o Clicador pode clicar sem causar nenhum problema (como o fundo da página), só para dar foco a Janela do Navegador antes dele clicar na checkbox.

R

Estou mexendo nas configurações, ajustando, mas ele só é asertivo sem a utilização do mouse record, tem momentos em que ele ta selecionando duas checkboxs de uma só vez. Quando ajusto a área xxxxxx / xxxxxx na captura ele se perde na xxxxxx, e as vezes pegando um outro numero xxxxxx, ele executa corretamente, ta meio teimoso, mas tenho fé que ele vai acontecer. :pray:
Vou testar suas alternativas, vou ajustar em casa e levo amanhã, o mais difícil você ja fez, agora tenho que conseguir adpta-ló. Muito obrigada pela ajuda, vou te falando sobre o que vai acontecendo, e contando com sua experiência.Obrigada demais!!

D

Acho que ele só faria uma coisa dessas se ele recebesse dois clicks no botão da janela dele, e se a Área da Checkbox estivesse grande demais para capturar mais de uma checkbox, mesmo que parcialmente.

Isso é bem estranho, como ele pode pegar outro número? ele simplesmente busca pelos pixels laranja do Ctrl+F.

Pelo que você está falando, tenho a impressão que o Clicador está sendo ativado enquanto há pixels laranja selecionando duas linhas de Números diferentes; isso o faria clicar na checkbox errada ou mesmo criar uma área de checkbox grande o suficiente para que duas checkbox sejam marcadas.

Mas esse tipo de problema ficaria bem claro nas capturas que aparecem na janela dele.

Talvez, se o trabalho que o Mouse Record está fazendo for muito simples, podemos adicionar a funcionalidade dele no clicador, dispensando-o.
Se o que ele faz é simplesmente dar uma sequência de clicks em coordenadas específicas, aguardando delays específicos, deve ser fácil adicionar essa funcionalidade ao clicador. A funcionalidade de fazer Ctrl+C e Ctrl+V o robô do Java também consegue fazer.

O robô do Java consegue fazer atalhos de teclado como Ctrl+P também, mas ele não é bom para escrever coisas (nunca consegui fazer ele teclar o ponto de interrogação, e pelo que me lembro, nem o cê-cedilha).

R

1 - Acho que ele só faria uma coisa dessas se ele recebesse dois clicks no botão da janela dele, e se a Área da Checkbox estivesse grande demais para capturar mais de uma checkbox, mesmo que parcialmente.

Acho que o Mouse Pro bagunça ele, realmente aconteceu em alguns casos.

2 - Isso é bem estranho, como ele pode pegar outro número? ele simplesmente busca pelos pixels laranja do Ctrl+F.

Sinceramente não sei te explicar porque entendo que ele deveria selecionar somente o pixel laranja, mas é como se ele movesse o cursor do mouse selecionasse um Checkbox sem pixel laranja e depois seleciona o correto, mas mantem ambos selecionados.

3 - Mas esse tipo de problema ficaria bem claro nas capturas que aparecem na janela dele.
Esse é o que me deixa confusa, porque ele captura exatamente o pixel correto, mas o Mouse Pro o atrapalha, manual o funcionamento é correto.

4 - Talvez, se o trabalho que o Mouse Record está fazendo for muito simples, podemos adicionar a funcionalidade dele no clicador, dispensando-o.
Se o que ele faz é simplesmente dar uma sequência de clicks em coordenadas específicas, aguardando delays específicos, deve ser fácil adicionar essa funcionalidade ao clicador. A funcionalidade de fazer Ctrl+C e Ctrl+V o robô do Java também consegue fazer.

A funcionalidade dele é exatamente isso, só uso comando de Ctrl+C e Ctrl+V, Ctrl P, é uma repetição, faço uma vez, e ele repete. Uso um Excel com as informações, a pagina web, e a extensão que imprime a capa.

5 - O robô do Java consegue fazer atalhos de teclado como Ctrl+P também, mas ele não é bom para escrever coisas (nunca consegui fazer ele teclar o ponto de interrogação, e pelo que me lembro, nem o cê-cedilha).

Nesse processo ele só usa teclas de atalhos mesmo , não tem necessidade de escrever.

D

Implementei a funcionalidade de “seguir um script”, que você poderá definir no arquivo sequencia_de_acoes.txt; nele você coloca instruções e quando clicar no botão da Janela do Clicador ele irá executar essas instruções.

Essas são instruções de teste para você ver o que ele já faz (veja se com essas ações já é suficiente):

//Clica nas coordenadas x=500 e y=200:
CLICAR: 500, 200

//Aguarda 1000 millisegundos, ou seja, 1 segundo:
AGUARDAR: 1000

//Detecta os pixels laranja e tenta clicar na Checkbox certa:
CLICAR_NA_CHECKBOX

//Abaixo faz-se Ctrl+C:
TECLAR: 17, PRESSIONAR //pressiona Ctrl
TECLAR: 67, PRESSIONAR_LIBERAR //pressiona e libera C
TECLAR: 17, LIBERAR //libera Ctrl

Essa instrução teclar recebe o keycode da Tecla desejada como número (17, 67, etc.), para descobrir o keycode de uma tecla, use essa tabela:

https://docs.oracle.com/javase/8/docs/api/constant-values.html#java.awt.event.KeyEvent.CHAR_UNDEFINED

A instrução CLICAR_NA_CHECKBOX não recebe valores, mas atua nas configurações definidas.

Eu esqueci de te falar, mas sempre que alterar as configurações você deve reiniciar o Clicador para que as alterações tenham efeito; o mesmo serve para esse novo arquivo de sequência de ações.

ClicadorDeCheckbox.zip (20,2 KB)

D

Se você está usando o Excel simplesmente para colocar uma pilha de valores, o clicador podia assumir essa tarefa, dispensando o Excel.

Ele poderia pegar a lista de valores de um arquivo txt no HD, ou, poderia ter campos onde você insere os valores.

O Java consegue colocar informações na Área de Transferência, não sendo necessário o Ctrl+C, só o Ctrl+V.

Da forma como a implementação está, acho que até que seria fácil adicionar a funcionalidade de uma instrução como:

AGUARDAR: <caminhoDeImagem>, posX, posY

Essa instrução faria o programa aguardar até a imagem especificada aparecer na Tela na posição especificada, o que seria útil para fazer o programa aguardar até algo acontecer na tela (como o Adobe Reader abrir e aparecer na Tela após o download :slight_smile: )

Atualmente a função Aguardar “trava” o programa, ele não vai responder até o delay terminar.

Teste ele aí, vou estar aguardando.

R

Isso seria ótimo, pelo menos não precisaria me preocupar tanto com o tempo de carregamento, porque internet oscila, então é algo bem mais certo.
Vou desenhar minhas ações, e testar,é realmente muito interessante dessa forma, eu vou fazer sim.

D

As configurações que você precisa editar são essas:

//Configurações para delimitar a Área onde o Número Selecionado pelo Ctrl+F será buscado:
AREA_DA_SELECAO_X: 674 //diminua esse valor, mas deve ser maior ou igual a zero
AREA_DA_SELECAO_Y: 318
AREA_DA_SELECAO_WIDTH: 103 //aumente esse valor
AREA_DA_SELECAO_HEIGHT: 492

AREA_DA_SELECAO_X + AREA_DA_SELECAO_WIDTH deve dar um resultado menor ou igual a 1600 que é a largura da resolução do seu monitor.

Para a captura cobrir toda a largura da Tela, você poderia configurar assim:

//Configurações para delimitar a Área onde o Número Selecionado pelo Ctrl+F será buscado:
AREA_DA_SELECAO_X: 0
AREA_DA_SELECAO_Y: 318
AREA_DA_SELECAO_WIDTH: 1600
AREA_DA_SELECAO_HEIGHT: 492

Mas o ideal é que você ajuste a área capturada para ser o menor possível que funcione em todos os casos, pois isso diminui a chance de erros e também diminui o processamento gasto pelo Clicador (ele sempre terá que percorrer pixel a pixel da área capturada).

Além disso, um área capturada menor é bem mais fácil de ver na Janela do Clicador, o que facilita ver o que ele está capturando.

R

Vou tentar ajustar o minimo possível, estou achando que em alguns momentos os números saem da área capturada, esse caso que te mandei acima é um caso que falha. E quando mexo nessas configurações dai o Mouse Pro quem falha, ele encontra a Checkbox, mas não consegue selecionar. De qualquer forma acredito que é ir tentando ajustar, em um momento vai funcionar redondo.
Muito obrigada pelas informações.

D

Criei uma “versão 2”, que muda a GUI e adiciona a funcionalidade de aguardar por algo aparecer na tela para poder continuar.

O código virou uma bagunça rs, mas o Clicador ficou mais interessante.

ClicadorDeCheckbox2.zip (34,4 KB)

Estou usando o JavaFX para a GUI agora.

A nova instrução suportada está sobrecarregada com a outra AGUARDAR, é só mudar os argumentos:

//Aguarda até a imagem aparecer na Tela dentro da área especificada:
//AGUARDAR: "<caminhoDaImagem>", posX, posY, width, height
AGUARDAR: "src/images/white.png", 300, 500, 50, 20

Os valores posX, posY, width, height delimitam uma área retangular na Tela, o programa fica aguardando até que apareça dentro dessa área uma imagem igual a do caminho passado no primeiro argumento.

Essa área retangular pode ser maior que a imagem buscada.

Quando o Clicador estiver aguardando por algo aparecer na Tela, ele irá mostrar na lateral direita a imagem que está esperando que apareça (que é a imagem do caminhoDaImagem), e mostrará também um retângulo sobre a área da Tela onde ele está buscando essa imagem.

Se o Clicador não conseguir clicar na Checkbox, ele cancela a execução dos comandos após o CLICAR_NA_CHECKBOX, e abre uma janela que mostra as capturas que ele fez, essa janela possui barras de rolagem para dar suporte a capturas de imagens bem grandes, mas ela também é “pannable”, então você clicar no meio dela e arrastar para navegar por ela, o que é bem mais fácil que usar as barras de rolagem.

Ele também é capaz de mostrar as Configurações atuais para a busca pela Checkbox.

Agora as configurações da JANELA ficaram inúteis, mas ainda são lidas, então removê-las deve causar bug.

Ainda não adicionei funcionalidade para inserir nele os números que serão buscados, dispensando o Excel.

Outro ponto, é que o Clicador, em nenhuma versão anterior nem nesta, foi/está preparado para funcionar em um PC com 2 ou mais monitores.

Bem, experimente usá-lo, veja como funciona e o que você acha.

D

Bom, adicionei a funcionalidade que deve dispensar o Excel, veja esse teste pra você ter uma ideia:

Como você pode ver no Gif acima, a ideia é que você digite todos os números que serão buscados pelo Ctrl+F, no exemplo, ao invés de digitar números eu digitei as palavras do título desse artigo.

Aí é só clicar em “Processar Todas as Entradas” para ele começar a executar sequência de Ações em Loop, executando uma vez para cada “Entrada” (uma “Entrada” é uma Palavra, Frase ou Número [como xxxxxxx ou xxxxxx / xxxxxx] que será digitado pelo robô dentro do Campo aberto pelo Ctrl+F).

Cada uma das “Entradas” que você inserir deve estar em sua própria linha, é assim que você deve serpará-las.

Toda vez que uma Entrada é processada ela é apagada da TextArea onde você a digitou. Por isso, no final do gif você pode ver que a TextArea ficou vazia, porque todas as Entradas foram processadas e apagadas dessa TextArea.

O botão “Próxima Entrada” serve para o robô pegar apenas a próxima Entrada (apagando-a da TextArea) e processar a Sequência de Ações somente uma vez, usando essa Entrada no Ctrl+F.

O botão “Processar Sequência” apenas irá processar a Sequência de Ações, uma vez, e ele não apaga nada da TextArea, ou seja, não apaga nenhuma entrada. Ele irá utilizar a “Entrada Atual”, que é a última que foi processada. Também pode ser usado sem nenhuma Entrada, mas não irá digitar nada.

A Nova instrução disponível é esta (sem argumentos):

DIGITAR_ENTRADA_ATUAL

Quando chegar o momento de execução dessa instrução o robô irá digitar (caracter por caracter) a “Entrada Atual” pêga da TextArea.

Nesse exemplo, eu usei essa sequência:

//Aguarda 3000 millisegundos, ou seja, 3 segundos:
AGUARDAR: 3000

//Clica nas coordenadas x=500 e y=200:
CLICAR: 500, 200

//Abaixo faz-se Ctrl+F:
TECLAR: 17, PRESSIONAR
TECLAR: 70, PRESSIONAR_LIBERAR
TECLAR: 17, LIBERAR

AGUARDAR: 500 //Aguarda o TextField do Chrome aparecer após o Ctrl+F

DIGITAR_ENTRADA_ATUAL //escreve dentro do TextField aberto pelo Ctrl+F

Exemplo da utilização do “Processar Próxima Entrada”:

Veja que no final eu usei “Processar Sequência” para repetir a sequência com a última entrada, só não selecionou o texto todo porque o programinha que estou usando para capturar a tela e gerar o Gif parece estar atrapalhando (ele é alwaysOnTop e acho que tira o foco do Navegador).

ClicadorDeCheckbox2.zip (40,1 KB)

D

Talvez não será necessário usar o JNativeHook para você ativar o Clicador por atalho de teclado, se tudo der certo, o botão que você ativou recebe o foco após a execução da sequência, aí, é só você teclar Enter que esse botão é acionado de novo.

R

Nossa já fiquei mega ansiosa e empolgada para testar, rss
Quando penso que não pode melhorar, você surpreende :scream:

Tenho uma duvida e dai não sei se o processo acima vai funcionar, como pensei tudo com a utilização do Mouse Pro, não sei como fica esse ponto.

Quando utilizo o Excel com as informações xxxxxx e xxxxx / xxxxxx, tenho também um código que utilizo pra busca do cliente, e esses números são diferentes para cada entrada xxxxxx ou xxxxxx / xxxxx, então toda vez que acesso o sistema incluo o código e aciono um botão BUSCAR, como essa tela é fixa o Mouse Pro fazia tranquilamente, a partir dai o sistema traz as informações do cliente correspondente ao código onde constam os números xxxxx ou xxxxxx / xxxxx, depois o procedimento é como falamos:

1 - Ctrl+F busca numero xxxxx ou xxxxxx / xxxxx

2 - Pixel detectado e Checkbox selecionada clicar “Imprimir Capa”

3 - Processo se repete

Consigo fazer o processo todo com o robô, ou é algo mais difícil?

D

Depende, o que exatamente o Mouse Pro faz nesse procedimento? Se ele simplesmente dá clicks em pontos específicos, aguarda certos milissegundos, faz atalhos de teclado, então o Clicador já é capaz de fazer isso.

O Clicador está muito flexível agora, ele executa a sequência de instruções que você definir, na ordem que definir. A instrução Aguardar por Imagem também dá muito mais segurança de que vai dar certo do que a Instrução Aguardar por Tempo.

Mas para mim ter uma ideia da sequencia que será necessário criar, e se realmente o Clicador já consegue fazer isso, vou precisar que você detalhe bem esse processo.

Por exemplo, para cada código-do-cliente (vou chamar de cod-cliente) você vai precisar fazer Ctrl+F apenas uma vez ou mais de uma?

Uma dúvida, usar o Mouse Pro com o Clicador ainda continua dando problema?

Eu acho que o Clicador deve conseguir substituir o Mouse Pro, mas se ainda não conseguir, ele já deve estar perto disso :slight_smile:

R

O código ficaria no Excel da seguinte forma:

Linha 1 - código cliente 1 - xxxxx
Linha 2 - código cliente 2 - xxxxx / xxxxx

Acesso ao sistema: A tela do sistema tem a carinha da imagem que tentei desenhar rss

1 - Ctrl+C no código cliente 1 / Ctrl+V no campo Inserir do sistema
2 - Click com o mouse no botão BUSCAR, alguns segundos para receber as informações
3 - Aciono o CTRL+F
4 - Encontra o pixel laranja
5 - Seleciona a Checkbox
4 - Aciona a extensão Imprimir Capa
5 - Click no botão LIMPAR do sistema e reinicia o processo para o código cliente 2

Deu para entender mais ou menos?

Eu ainda não consegui testar a versão 2 com o Mouse Pro, vou ver na segunda e te falo como esta.

image

D

O código cliente é apenas um Número? ou contém outros tipos de caracters como pontos, hífens ou barras?

Pelo que entendi, deve dar para montar uma sequência sim, só que você vai ter que inserir como Entradas o cod-cliente alternando com o numero-buscado pelo Ctrl+F, exemplo de Entradas:

<codigo do cliente 1>
<xxxxxxxx>
<codigo do cliente 2>
<xxxxxxxx / xxxxxxx>
<codigo do cliente 3>
<xxxxxxxx>

Aí a sequência faz (cada um desses passos pode precisar de mais de uma instrução):

  1. clica no Campo para inserir o Codigo do Cliente;
  2. escreve o cod-cliente no campo certo;
  3. clica no botão Buscar;
  4. faz o Ctrl+F;
  5. escreve o numero-buscado;
  6. busca o pixel laranja e clica na checkbox;
  7. clica na extensão “Imprimir Capa”;
  8. Aguarda o Adobe Reader aparecer;
  9. Faz Ctrl+P;
  10. clica no botão para Imprimir;
  11. Fecha o Adobe Reader;
  12. Clica em “Limpar”.

Está correta a sequência? Se for assim, o Clicador já deve conseguir fazer sim.

Se você usar o “Processar Todas as Entradas” ele vai ficar repetindo essa sequência para todos os cod-cliente + numero-buscado, deve dar certo. :smile:

R

Sim, os códigos sao só números, sem barras e sem caracteres.
A sequência é exatamente essa :clap::clap::grin:
Ta demais esse clicador, você é demais Douglas eu já to ansiosa pra testar !!! :scream::tada:

D

Se essa parte em que você insere o código do Cliente fica no Topo da página, então, ao reiniciar o processo pode ser necessário rolar a página para cima, até o topo.

Atualmente o Clicador não tem nenhuma instrução de Scroll, mas você pode usar uma extensão que ao ser clicada rola a página, que seria ativado pelo Clicador:

Eu perguntei se cod-cliente possuía caracters além de números porque o Robot do Java é ruim para escrever coisas, tem muitos caracters que ele não escreve.

No caso da “/” do xxxxx / xxxxx por exemplo, eu criei um tratamento especial no código (já aproveitei e fiz o mesmo para a barra invertida “\”), onde, ao invés dele tentar teclar a barra ele faz Alt+0047, que é uma especie de atalho para a Barra comum (se você fizer esse atalho usando as teclas do teclado numérico verá a barra ser inserida). Vi esta opção aqui:

Antes eu tentei inserir os valores na Área de Transferência diretamente, aí o robô apenas faria Ctrl+V, mas inserir os valores na Área de Transferência não funcionou bem.

Olha os tratamentos especiais:

private Map<Character, Integer[]> caracteresEspeciais = new HashMap<>();
	
	public DigitarEntradaAtual() {
		caracteresEspeciais.put('\\', new Integer[]{KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD9, KeyEvent.VK_NUMPAD2});
		caracteresEspeciais.put('/', new Integer[]{KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD7});
	}

O Código da Classe:

package acoes;

import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;

import main.MainFX;

public class DigitarEntradaAtual extends Acao {

	private Map<Character, Integer[]> caracteresEspeciais = new HashMap<>();
	
	public DigitarEntradaAtual() {
		caracteresEspeciais.put('\\', new Integer[]{KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD9, KeyEvent.VK_NUMPAD2});
		caracteresEspeciais.put('/', new Integer[]{KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD7});
	}
	
	@Override
	public boolean executar(Robot robo) {
		for(char character : MainFX.entradaAtual.toCharArray()){
			
			Integer[] codigo = caracteresEspeciais.get(character);
			
			if (codigo != null)
				processarCaracterEspecial(robo, codigo);
			else
				processarCaracterComum(robo, character);
			
		}
		return true;
	}

	private void processarCaracterEspecial(Robot robo, Integer... codigo) {
		robo.keyPress(KeyEvent.VK_ALT);
		robo.waitForIdle();
		
		for (Integer cod : codigo) {
			robo.keyPress(cod);
			robo.waitForIdle();
			robo.keyRelease(cod);
			robo.waitForIdle();
		}
		
		robo.keyRelease(KeyEvent.VK_ALT);
		robo.waitForIdle();
	}

	private void processarCaracterComum(Robot robo, char character) {
		robo.keyPress(KeyEvent.getExtendedKeyCodeForChar(character));
		robo.waitForIdle();
		robo.keyRelease(KeyEvent.getExtendedKeyCodeForChar(character));
		robo.waitForIdle();
	}

}

Se esse robô fizer coisa errada, pode ser problema dele não estar aguardando fazer uma ação para fazer a próxima, acho que seria uma boa ideia programá-lo com robo.setAutoWaitForIdle(true); e com um pequeno delay entre cada ação, uns 200ms como na última resposta do link do StackOverflow, robo.setAutoDelay(200);. Acabei de adicionar isso aqui no código no projeto, deve evitar problemas:

private static void iniciarConfiguracoes() throws Exception {
	robo = new Robot();
	robo.setAutoWaitForIdle(true);
	robo.setAutoDelay(200);
	carregarConfiguracoesDoArquivo();
}
R

O chrome tem muita extensão que da para aproveitar, eu até desconhecia essas funcionalidades, muito legal.
Obrigada Douglas por essa dedicação no programa, são demais suas ideias e o desenvolvimento de tudo, amanha eu vou testar a versão 2 que me mandou, e se todo esse processo de realizar as ações no clicador for dar muito trabalho não se preocupe viu, já tem me ajudado muito, toda vez que entro aqui é uma surpresa boa, e as ideias ainda mais otimizadas, te agradeço muito mesmo.

D

Lembrei agora de um problema na implementação, eu acho que ele não vai funcionar desse jeito para a sequência, nem precisa testar aí.

O que eu acho que ele vai fazer é pegar uma Entrada, e digitá-la todas as vezes enquanto estiver rodando a mesma sequência, então, ele vai digitar o cod-cliente e depois, na hora de digitar o numero-buscado, ele vai digitar o cod-cliente de novo.

Ele só iria digitar o numero-buscado na próxima execução da sequência, digitando-o no campo do Código do Cliente.

Vou arrumar assim que tiver um tempinho.

R

Tudo bem, obrigada Douglas.
Eu vou fuçando aqui tbm pra ver se tenho alguma idéia. O último arquivo que me enviou funciona mas ele ta errando o pixel laranja as vezes, vou ajustando pra ver se consigo usar com o Mouse Pro, mas a ideia ficou muito bacana.

D

Agora ele é capaz de escrever várias coisas diferentes numa mesma execução da sequência, com isso já é possível criar uma sequência de instruções onde ele irá escrever primeiro o cod-cleinte e mais para frente - ainda na mesma execução da sequência - irá escrever o numero-buscado no campo aberto pelo Ctrl+F.

No gif acima, estou usando ele para executar uma busca no google, usar Ctrl+F para buscar uma palavra na página, e então voltar a página para ficar pronto para a próxima busca.

As linhas vazias são ignoradas, mas você pode usá-las para organizar as Entradas.

A sequência é essa:

//Aguarda 1000 millisegundos, ou seja, 1 segundo:
AGUARDAR: 1000

//Clica no campo de busca do google
CLICAR: 645, 408

AGUARDAR: 500

//A instrução abaixo Avança uma Entrada:
//Na Primeira Execução Avança para a Primeira Entrada; depois para as próximas
PROXIMA_ENTRADA

//Escreve a Entrada no Campo de busca do google
DIGITAR_ENTRADA_ATUAL

//Clica no fundo branco da página do google
CLICAR: 441, 318

//Clica no botão "Pesquisa Google"
CLICAR: 725, 480

AGUARDAR: 3000

//Abaixo faz-se Ctrl+F:
TECLAR: 17, PRESSIONAR
TECLAR: 70, PRESSIONAR_LIBERAR
TECLAR: 17, LIBERAR

//Aguarda o Campo Ctrl+F aparecer
AGUARDAR: 500

//Avança para a Entrada que será escrita no Campo aberto pelo Ctrl+F
PROXIMA_ENTRADA

//Escreve a Entrada no Campo aberto pelo Ctrl+F
DIGITAR_ENTRADA_ATUAL

AGUARDAR: 2000

//Clica em Voltar
CLICAR: 12, 45

Você pode usar o Paint para pegar a posição x e y na tela das coisas que serão clicadas, e também é útil para saber a posição e tamanho que áreas retangulares precisaram ter.

Agora ao clicar nos Botões da GUI do Clicador ele não irá avançar as Entradas automaticamente, ele só avança uma Entrada quando a instrução “PROXIMA_ENTRADA” é executada.

Se a instrução “DIGITAR_ENTRADA_ATUAL” for executada sem que haja uma Entrada para executar, a execução da sequência será interrompida imediatamente, e aparecerá essa mensagem:

image

ClicadorDeCheckbox2.zip (41,0 KB)

Quando ele tenta executar a instrução de detectar o pixel laranja e clicar na checkbox, e falha, ele deve fazer aparecer a Janela que mostra as Capturas feitas. Essa Janela apareceu? Como estão as Capturas dentro dela? Ele capturou o número selecionado com pixels laranja?

Infelizmente não testei muito, e quase não há testes automatizados no código, mas espero que funcione.

Deus te abençoe.

R

Esta demais Douglas, vou testar amanhã, muito mas muito obrigada viu!!! :kissing_heart::pray:
O erro do pixel que comentei foi que ele capturou o pixel no primeiro número somente, como se não tivesse os demais, exemplo :
Entrada: xxxxx / xxxxx
Capturou : x
Dai selecionou dois Checkbox, é como se ele reconhecesse somente o primeiro número, não o conjunto. Não sei se pode ser algo na configuracao, mas isso vou ajustando caso ocorra, mas ja to na fé que não vai ocontecer, rss …você me ajudou demais, e clareou as possibilidades, vou me dedicando para conseguir usar e te perturbo aqui se precisar tbm. Rss
Amém, que Deus te abençoe tbm.

D

A imagem capturada ficou cortada? ou foi o número xxxxx / xxxxx que não ficou completamente selecionado de laranja?

Apareceram dois checkbox na captura? Ou ele realmente chegou a clicar em duas checkbox diferentes marcando-as?

Na Captura, há mais de um numero-buscado selecionado de laranja (como por exemplo um numa linha e outro noutra linha)?

Bem, veja se você consegue reproduzir esse caso de falha, e me envia um recorte de tela das Capturas que ele fez. Acho que isso já seria o suficiente para mim entender o que ocorreu.

Se um caso de falha for reprodutível, então ele precisa ser consertado, porque significa que o Clicador irá falhar quando surgir esse caso ou um caso semelhante.

R

Eu vou testar a última versão que me mandou, se der qualquer erro eu faço o recorte pra você ver.
O numero xxxxx / xxxxx não ficou completamente selecionado na cor laranja.
Não lembro de ter visto dois Checkbox na captura, vou avaliar melhor e te passo com mais detalhes.
Muito obrigada, tenha um bom dia! :kissing_heart:

R

Douglas, :star_struck::star_struck::star_struck::star_struck::star_struck:

Ainda estou tentando ajustar as ações, mas acredito que vai funcionar muito bem, pelos testes que fiz, ele não errou nenhuma vez a Checkbox e esta conseguindo ir até a pagina de Impressão no Adobe Reader, preciso fazer com que ele faça o Ctrl+P na imagem e dai é só repetir o processo.

Tenho uma duvida aqui:
O CaminhoDaImagem seria exatamente o que?
Inseri como caminho,a pasta onde é salvo o download da imagem apos clicar ImprimirCapa, mas deu erro, o que posso estar fazendo de errado?

image

//Aguarda até a imagem aparecer na Tela dentro da área especificada:
AGUARDAR: “<caminho pasta download>”, posX, posY, width, height
AGUARDAR: “src/images/white.png”, 300, 500, 50, 20

Obrigada.

D

Então ao clicar em “Imprimir Capa” é baixada uma imagem? Você tentou fazer o Clicador aguardar esse arquivo de imagem aparecer numa determinada Pasta?

Essa instrução de Aguardar por Imagem não foi feita para “aguardar até arquivos de imagem aparecerem numa determinada Pasta”, ela foi feita para “aguardar que uma determinada coisa apareça na Tela”, o programa fica aguardando até essa coisa aparecer.

  • Mas que “coisa” o programa aguarda que apareça na Tela? Resposta: Isso você define através do CaminhoDaImagem, que deve apontar para um arquivo de imagem (e não uma pasta). Por exemplo, você pode aguardar que o ícone do Adobe Reader apareça em um determinado local da Tela, para fazer isso, recorte esse ícone e salve-o como imagem em algum lugar, depois, faça o CaminhoDaImagem apontar para a imagem salva desse ícone; assim o Clicador saberá o que ele está aguardando que apareça na Tela (está aguardando que apareçam os pixels do ícone do Adobe Reader);
  • Certo, mas o Clicador observará toda a Tela aguardando que esse ícone apareça em qualquer lugar dela? Resposta: o Clicador não precisa ficar observando todos os pixels da Tela em busca do ícone do exemplo acima, você pode definir uma Área Retangular da Tela e o Clicador observará apenas os pixels dentro dela em busca desse ícone. Assim, você delimita onde o ícone deve aparecer para que o Clicador continue a execução. Isso dá muito mais segurança contra erros, porque, se o ícone aparecer fora da área delimitada (o que pode indicar que as coisas estão fora do lugar, talvez pela janela ter sido movida ou a página rolada), o Clicador vai aguardar até ele aparecer dentro da área delimitada.

Eu dei um exemplo com um ícone, mas pode ser qualquer coisa, qualquer recorte da Tela. Pode ser, por exemplo, um recorte de um botão para você ter certeza de que o Clicador só irá clicar numa dada posição se o botão esperado estiver lá, caso contrário, ele aguardará até esse botão aparecer nessa posição.

Para delimitar uma Área Retangular da Tela onde será buscada a imagem do CaminhoDaImagem, basta definir as variáveis posX, posY, width, height.

Essa instrução não tem uma “sintaxe válida”, na verdade, eu coloquei aí só para explicar o que essa instrução Aguardar espera receber, como se fosse os nomes dos parâmetros. Mantenha ela comentada. A NumberFormatException parece ter ocorrido porque você inseriu o caracter “<”, que não é aceito. Aliás, acho que o Clicador também não aceitaria um caminho que contenha vírgula, isso pode confundí-lo.

Essa instrução está correta, e significa que o Clicador irá aguardar que apareça na Tela, dentro da área x=300 y=500 width=50 height=20, uma imagem toda branca (white.png é uma imagem só de pixels brancos).

A instrução Aguardar por Imagem é semelhante a instrução “Wait for pixel color” daquele Mouse Recorder que havia mencionado, só que mais avançada já que ela aguarda por uma imagem inteira (muitos pixels) ao invés de aguardar por um só.

R

Muito obrigada pelo esclarecimento Douglas, e desculpa minha ignorância.
Até a tela do Adobe ta tudo correndo bem, só acho que vou ter que adicionar alguns delay porque em alguns momentos não da o tempo certo do carregamento,quando clico em algum botão.

Veja como esta, preciso da sua ajuda, não estou conseguindo acionar o Ctrl+P
Depois preciso pressionar o botão imprimir acho que consigo e por ultimo fechar o Adobe o que posso estar fazendo errado?

//Aguarda o Campo Ctrl+F aparecer
AGUARDAR: 1000

//Avança para a Entrada que será escrita no Campo aberto pelo Ctrl+F
PROXIMA_ENTRADA

//Escreve a Entrada no Campo aberto pelo Ctrl+F
DIGITAR_ENTRADA_ATUAL

AGUARDAR: 2000

//Clica em Voltar
//CLICAR: 12, 45

//Instruções Comentadas que podem ser usadas:

//Clica nas coordenadas x=500 e y=200:
//CLICAR: 500, 200

//Detecta os pixels laranja e tenta clicar na Checkbox certa:
CLICAR_NA_CHECKBOX

//Clica no icone da impressora
CLICAR: 1520, 50

AGUARDAR: 500

//Clica Imprimir Capa
CLICAR: 1475, 123

AGUARDAR: 500

//Aguarda até a imagem aparecer na Tela dentro da área especificada:
//AGUARDAR: “”, posX, posY, width, height
AGUARDAR: “src/images/white.png”, 300, 500, 50, 20

//Abaixo faz-se Ctrl+P:
TECLAR: 17, PRESSIONAR
TECLAR: 80, PRESSIONAR_LIBERAR
TECLAR: 17, LIBERAR

D

Esse atalho para o Ctrl+P que você fez está correto, testei aqui e funcionou. Testei com essa pequena sequência:

//Delay para eu ter tempo de clicar na Janela do Chrome passando o Foco para ele
AGUARDAR: 2000

//Abaixo faz-se Ctrl+P:
TECLAR: 17, PRESSIONAR
TECLAR: 80, PRESSIONAR_LIBERAR
TECLAR: 17, LIBERAR

//Ao fazer o Ctrl+P acima abriu a tela de impressão do Chrome

Você pode testar essa pequena sequência aí para ver se o Robô aí está fazendo o Ctrl+P certinho. Tenha certeza de que a Janela do Adobe Reader está em Foco quando o Ctrl+P for feito, você pode até programar o Clicador para clicar nessa Janela (para que ela torne-se a Janela em Foco) antes de fazer o Ctrl+P.

Talvez o problema seja essa instrução que está sendo executada antes do Ctrl+P:

AGUARDAR: “src/images/white.png”, 300, 500, 50, 20

Você substituiu a imagem “white.png”? Você redefiniu esses argumentos? Ou os Argumentos atuais resolvem? Eu acho que o que você precisa ai é redefinir os Argumentos dessa instrução, escolhendo um recorte de Tela que faça o Clicador saber que o Adobe Reader já apareceu e que está tudo pronto para fazer o Ctrl+P.

Enquanto o Clicador estiver Aguardando por uma Imagem aparecer na Tela, ele irá mostrar algo assim:

Os labels vermelhos coloquei aqui para explicar o que são esses retângulos de contorno vermelho. O da esquerda é a Área onde a “imagem Buscada” deve aparecer para que o Clicador dê continuidade a sequência. O Retângulo da direita contém a “Imagem Buscada” pelo Clicador, para que você saiba o que ele está esperando que apareça.

Esses retângulos apareceram aí e permaneceram na Tela enquanto você esperava que o Clicador fizesse Ctrl+P? Se sim, significa que o Clicador não fez Ctrl+P porque ele está Aguardando a imagem white.png aparecer no local assinalado.

Você pode até fazer um teste, colocando o fundo branco do Bloco de Notas na área assinalada, ó fundo branco dará match com white.png (se você não substituiu essa imagem) e o Clicador continuará a Sequência (provavelmente fazendo Ctrl+P na Janela em Foco, que deverá ser o Bloco de Nodas nesse exemplo).

R

Valeuuuu Douglas, você é o cara que resolve tudooooooo!!! :clap::clap::grin:
Funcionou com o delay, ainda não executei uma massiva pra ver como ele vai reagir, to adicionando algumas ações ainda, mas ta funcionando muito bem, só preciso testar com mais entradas pra ver se ele vai acompanhar.
Muitíssimo obrigada, se puder me manda o projeto dele por favor. Que Deus te abençoe, muito obrigada mesmo e desculpa a perturbação.
Não precisou sibstituir a imagem “white.png”, os argumentos resolveram. Esta detectando o pixel certinho.

D

ClicadorDeCheckbox2.zip (42,3 KB)
ProjClicadorDeCheckbox.zip (64,8 KB)

Hum, talvez tenha funcionado por coincidência, pode ser que falhe depois. Se falhar, você vai ter que mexer nesses argumentos.

Estou enviando o Projeto e o Clicador que acabei de exportar. Ele tem uma correçãozinha e também configurações sobre a “Imagem Buscada” que aparece durante a execução de “Aguardar por Imagem”, é possível:

  • Escolher se a Imagem Buscada deve aparecer na Tela ou não;
  • Alterar a posição em que essa Imagem Buscada aparece.

Eu notei que a sequência que você está usando possui delays bem grandes, como aguardar 1s para o Campo do Ctrl+F aparecer. Acho que funcionaria se o delay fosse menor. Você pode ir experimentando diminuir esses delays. Mas o melhor mesmo (e mais trabalhoso) é substituir esses delays por instruções “Aguardar por Imagem” especialmente preparadas (com os Argumentos certos), isso diminuiria muito a chance do Clicador cometer erros, e ainda deixaria tudo mais rápido.

Que bom que deu certo, faz a testagem massiva buscando variar as situações dentro do que pode acontecer no fluxo de trabalho do dia-a-dia, assim problemas podem ser descobertos mais rápido.

de nada, Deus te abençoe também; se precisar pode me chamar.

R

eu fiz um check dos argumentos, e testei tbm outras imagens, mas como o fundo é branco, acabou que conhecidiu mesmo, e ta rolando, mas vou testar na massiva pra ver se da erros.

R

Muito obrigada por isso! :kissing_heart:

R

Então eu meio que estendi alguns delays porque ele em alguns momentos estava um comando a frente, dai pulava a ação, mas vou fazer esse processo de instruções “Aguardar por imagem” então, se é mais seguro é bem válido.

R

Sim, vou fazer todos os testes possíveis, estamos em um período de alta demanda e acabo não conseguindo me dedicar muito, mas vou fazer da forma mais efetiva pra ter o mínimo de erro. A parte mais difícil você já fez, agora é comigo. Rs Mais uma vez muito obrigada.

R

Douglas,

Me da uma ajuda, estou fazendo instruções “Aguardar por Imagem”, no paint eu consigo identificar o width, height, como encontro os pontos posX, posY? :thinking::flushed:

D

Quando você move o cursor sobre o Paint, ele mostra a posição X e Y do cursor nessa imagem no canto inferior esquerdo. Quando você clica e arrasta para criar uma seleção retangular ele “trava” a posição X e Y nesse canto inferior esquerdo, é essa posição X e Y que você precisa pegar. Mas, quando você soltar o click finalizando a seleção retangular, ele ira parar de mostrar a posição X e Y dessa área retangular, não mostrando nada quando você colocar o cursor sobre essa área retangular.

image

R

Valeu Douglas, somente para clarear aqui:

1- Posição X e Y eu uso a pagina inteira certo?

2 - Para width, height eu vejo pela imagem cortada ?

3- Para salvar a imagem que precisa aguardar para prosseguir com as ações, o procedimento é aquele mesmo da Checkbox, zoom total na pagina inteira, dai corto uma parte da imagem que o pixel sera identificado?

4- A área onde a imagem é buscada,o retângulo deve estar bem em cima quando ela é encontrada?
Estou fazendo alguns testes mas as ações não estão prosseguindo, não sei se pode ser o recorte da imagem.

D

É relativo a Tela Inteira, o pixel x=0 e y=0 é o 1º pixel que fica no canto superior esquerdo da Tela.

Pode ser, você deve definir como Argumentos um width que seja maior ou igual ao width-da-imagem-recortada, e um height que seja maior ou igual ao height-da-imagem-recortada.

zoom 100% se é com esse zoom que você usará no dia-a-dia. É o mesmo procedimento do recorte da checkbox.

A imagem-buscada deve estar dentro do retângulo vermelho, totalmente dentro dele; esse retângulo vermelho pode ter o mesmo tamanho da imagem ou ser maior que ela, mas não pode ser menor que ela nem em width nem em height.

Fiz alguns testes aqui e funcionou como o esperado. Experimente deixar o retângulo vermelho maior alterando os Argumentos e certifique-se que a imagem recortada sendo buscada está totalmente dentro dele.
Se não der certo, me envie um recorte da Tela mostrando a imagem-buscada e o que está dentro do retângulo vermelho que está esperando a imagem-buscada, no momento que deveria dar match e continuar a execução.

R

Muito obrigada Douglas,vou tentar aqui e te falo. :kissing_heart:
Duvida, sabe se consigo colocar em delay usando o ícone de carregamento da pagina, assim cada sequencia é prosseguída apos o carregamento da pagina,quando tem um X ele trava.
Estou tentando fazer isso, mas sem saber muito da possibilidade.
Caso consiga me manda a sequencia e a telinha de como capturou o ícone dentro do retângulo vermelho por favor.

D

Gostei da sua ideia! Fiz aqui, veja:

reload » reload.png

stop » stop.png

Acima são as imagens que recortei aqui, e essas as ações:

AGUARDAR: "src/images/stop.png", 60, 35, 29, 26
AGUARDAR: "src/images/reload.png", 60, 35, 29, 26

Funcionou corretamente, ele aguarda até o stop aparecer, depois aguarda até o reload aparecer.

Veja que no começo está aberto o google e o Clicador fica aguardando aparecer o stop (o retagulo vermelho ficou cortado na captura :confused: ), depois, enquanto está carregando o GUJ, ele fica esperando o reload aparecer; quando este último aparece significa que o GUJ já carregou por completo, e você pode ver que a execução termina.

Então acaba sendo uma forma bem eficiente e segura de garantir que o carregamento terminou :slight_smile:

ClicadorDeCheckbox2.zip (43,5 KB) » Clicador com essa Sequência e com as imagens necessárias.

R

Muitoo obrigada Douglas, é exatamente isso :heart_eyes:, vou incluir na sequencia e verificar como vai funcionar, amanha faço o teste na empresa e te conto como esta. :star_struck:

R

Douglas,

Deu certo, ta funcionando !!! :clap::tada::grinning:
Hoje fiz alguns testes e não ocorreu nenhum erro , muito obrigada por tudo.

D

De nada, que Deus te abençoe. :smile:

R

Amém que abençoe a todos nós. :pray::blush:

Criado 16 de fevereiro de 2018
Ultima resposta 25 de mar. de 2018
Respostas 120
Participantes 5