TImage - Colocar ponto colorido no clique do mouse

Delphi

20/11/2007

Pessoal...

Tenho um componente TImage aonde eu vou clicar com o mouse sobre a imagem que se abrir (isso em vários pontos da imagem) e eu gostaria que a cada clique do mouse fosse colocado um ponto vermelho (pode ser qualquer cor).

Eu tentei assim:

Image.Picture.Bitmap.Canvas.Pen.Width := 1000;
Image.Picture.Bitmap.Canvas.Pixels[Pt.X,Pt.Y] := clRed;


Mas também não aconteceu nada.

Como eu faço isso?

Agradeço a ajuda de todos.


Marcos.gandin

Marcos.gandin

Curtidas 0

Respostas

Vitor Alcantara

Vitor Alcantara

20/11/2007

Coloque no evento MouseMove da imagem.

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if ssLeft in Shift then
  begin
    Image1.Picture.Bitmap.Canvas.Pen.Width := 10000;
    Image1.Picture.Bitmap.Canvas.Pixels[X ,Y ] := clRed;
  end;
end;


Eu acho que do jeito que estava você pegava o valor do ponteiro em relação ao form e não em relação a imagem.


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

Nos testes em que fiz aqui me parece que a linha ´[b:b7ce98774b]Image1.Picture.Bitmap.Canvas.Pen.Width := 10000[/b:b7ce98774b]´ não faz diferença alguma.


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Vitor

A linha [b:90c3782495]´Image1.Picture.Bitmap.Canvas.Pen.Width := 10000´[/b:90c3782495] era somente para aumentar o tamanho da caneta, mas eu também acho que não faz nenhuma diferença.

Obrigado por ajudar...vou testar e depois aviso o resultado.

Flw


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Vitor...

Testei aqui e não aconteceu nada.
Pra você funcionou?


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

A única coisa que aconteceu foi eu deixar clicado o botão esquerdo do mouse e ir arrastando ele sobre a figura, aí foi pintando de vermelho, mas mesmo assim, não foi na posição que o ponteiro do mouse estava.

O que eu preciso é somente dar um clique na figura e deixar marcado um ponto, e esse ponto deveria ser bem visivel.


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

Tenta isso no evento MouseDown;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then
  begin
      Image1.Picture.Bitmap.Canvas.Brush.Color := clred;
      Image1.Picture.Bitmap.Canvas.Brush.Style := bsSolid;
      Image1.Picture.Bitmap.Canvas.Ellipse(x,y,x+10,y+10);
  end;
end;


Dessa forma ele cria um circulo onde você clicou na imagem.


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

So complementando a idéia esse exemplo pode se aplicar perfeitamente para se desenhar na imagem (como um Primo pobre (bem pobre mesmo) do Paint por exemplo).
No evento MouseMove:

  if ssLeft in Shift then
  begin
     Image1.Picture.Bitmap.Canvas.Brush.Color := clBlack;
      Image1.Picture.Bitmap.Canvas.Brush.Style := bsSolid;
      Image1.Picture.Bitmap.Canvas.Pen.Style := psClear;      
      Image1.Picture.Bitmap.Canvas.Ellipse (x,y,x+10,y+10);
  end;

Enquanto estiver com o mouse precionado ele vai pintando a imagem.


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

Quanto aos pontos não estarem na posição que você indicou, talvez seja por que sua tImagem esteja com a propriedade [b:49af5e7f7e]Strench[/b:49af5e7f7e] setada para [b:49af5e7f7e]true[/b:49af5e7f7e].


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Vitor...

Agora os pontos ficaram maiores, mas a posição continua não sendo a mesma do ponteiro do mouse.

Verifiquei a propriedade Stretch ela está false.


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Tentei fazer assim:

procedure TfrmImagem.ImageMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  pt: TPoint;
begin
  GetCursorPos(pt);
  pt := Image.ScreenToClient(pt); 

  if Button = mbLeft then
  begin
    Image.Picture.Bitmap.Canvas.Brush.Color := clBlue;
    Image.Picture.Bitmap.Canvas.Brush.Style := bsSolid;
    Image.Picture.Bitmap.Canvas.Ellipse(pt.X,pt.Y,pt.X+5,pt.Y+5);
  end;
end;


Mas os pontos ainda não estão nos lugares corretos...


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

Estranho isso, testei do jeito que você postou por último e do outro jeito e ficou certo, a bolinha que cria sai exatamente na ponto da setinha do mouse, etedendo que ele começa dali da ponta do mouse caso você queira colocar a ponta do mouse exatamente no centro da bolinha dai você teria que diminuir o tamanho pra esquerda (x - tamanho pro lado) e do tamanho pra cima (y - tamanho pra cima), nos parametros left e top.

ex:

Image1.Picture.Bitmap.Canvas.Ellipse(pt.X - 2,pt.Y-2,pt.X+2,pt.Y+2);

No mais não sei o que pode estar errado.


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Você pode me dizer exatamente o que está utilizando pra testar?
Ou seja, você criou um form novo, colocou um componente TImage, você carrega uma imagem no componente utilizando um TOpenPictureDialog, e coloca o código que eu postei aí no evento OnMouseDown do componente TImagem ???

É isso?


GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Você poderia me enviar esse projeto que você fez pra que eu dê uma olhada, por favor?

Poderia me enviar para o e-mail:
marcos.gandin@hotmail.com

Flw


GOSTEI 0
Vitor Alcantara

Vitor Alcantara

20/11/2007

Olha ai o dfm

object Form1: TForm1
  Left = 0
  Top = 0
  AutoSize = True
  Caption = ´Form1´
  ClientHeight = 511
  ClientWidth = 708
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = ´Tahoma´
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Image1: TImage
    Left = 0
    Top = 0
    Width = 708
    Height = 511
    AutoSize = True
    OnMouseDown = Image1MouseDown
  end
  object Button1: TButton
    Left = 208
    Top = 32
    Width = 75
    Height = 25
    Caption = ´Button1´
    TabOrder = 0
    OnClick = Button1Click
  end
  object OpenPictureDialog1: TOpenPictureDialog
    Left = 344
    Top = 256
  end
end


Olha ai o Pas

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, jpeg, ExtDlgs, StdCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenPictureDialog1.Execute then
  Begin
    Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName );
  End;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin 
  
  if Button = mbLeft then
  begin
    Image1.Picture.Bitmap.Canvas.Brush.Color := clBlue;
    Image1.Picture.Bitmap.Canvas.Brush.Style := bsSolid;
    Image1.Picture.Bitmap.Canvas.Ellipse(X-2,Y-2,X+2,Y+2); 
  end;
end;

end.



GOSTEI 0
Marcos.gandin

Marcos.gandin

20/11/2007

Vitor...

Consegui acertar o meu projeto.
O que eu estava fazendo de errado não tinha nada a ver com o código, mas sim com a propriedade [b:d5780290c6]Center[/b:d5780290c6] que eu tinha setado como [b:d5780290c6]True[/b:d5780290c6] para que a imagem que fosse aberta, sempre se posicionasse no centro do componente.

Não sei se isso teria concerto...mas por hora está funcionando.

Valeu pela ajuda.
Obrigado mesmo.

Abraço...


GOSTEI 0
Micheus

Micheus

20/11/2007

[quote:fd2a771bf4=´Vitor Araujo Alcantara´]Coloque no evento MouseMove da imagem.

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if ssLeft in Shift then
  begin
    Image1.Picture.Bitmap.Canvas.Pen.Width := 10000;
    Image1.Picture.Bitmap.Canvas.Pixels[X ,Y ] := clRed;
  end;
end;


Eu acho que do jeito que estava você pegava o valor do ponteiro em relação ao form e não em relação a imagem.[/quote:fd2a771bf4]

A linha [b:fd2a771bf4]´Image1.Picture.Bitmap.Canvas.Pen.Width := 10000´[/b:fd2a771bf4] era somente para aumentar o tamanho da caneta, mas eu também acho que não faz nenhuma diferença.

[b:fd2a771bf4]marcos.gandin[/b:fd2a771bf4], o fato de Width=10000 não estar fazendo qualquer diferença neste código, deve-se a o fato de que vc não está utilizando a caneta para desenhar o ponto. Voce está, na verdade apenas mudando sua espessura, mas manipula o pixels, ou seja, apenas 1 ponto!


O que eu estava fazendo de errado não tinha nada a ver com o código, mas sim com a propriedade [b:fd2a771bf4]Center[/b:fd2a771bf4] que eu tinha setado como [b:fd2a771bf4]True[/b:fd2a771bf4] para que a imagem que fosse aberta, sempre se posicionasse no centro do componente. Não sei se isso teria concerto...mas por hora está funcionando.
A questão de vc ter habilitado a propriedade [i:fd2a771bf4]Center[/i:fd2a771bf4], tem como contornar facilmente. Mas eu acho que seria também interessante, vc realmente utilizar a caneta ao invés do método alternativo, com Ellipse. Veja o exemplo que vou colocar abaixo.

[b:fd2a771bf4]1[/b:fd2a771bf4]) Supondo que a propriedade Center estará setada antes do uso, inicialmente, vc deve calcular o offset (deslocamento) da imagem dentro do TImage ao carregar o bitmap para o TImage, já que este cálculo só precisaria ser realizado neste momento.
Também aproveita para definir espessura de caneta e cor da mesma (apesar que isto pode ser feito a qualquer momento).
Como eu não tenho um procedimento para carga da imagem, eu adicionei uma em design-time e no evento OnShow do form fiz as inicializações:
procedure TForm1.FormShow(Sender: TObject);
begin
  if Image2.Center then
  begin
    XOffSet := (Image2.Width -Image2.Picture.Width) div 2;
    YOffset := (Image2.Height -Image2.Picture.Height) div 2;
  end else
  begin
    XOffSet := 0;
    YOffset := 0;
  end;
  Image2.Picture.Bitmap.Canvas.Pen.Width := 10;
  Image2.Picture.Bitmap.Canvas.Pen.Color := clRed;
end;
Observações: As variáveis XOffiset e YOffset foram declaras na cláusula privare do Form1

[b:fd2a771bf4]2[/b:fd2a771bf4]) no evento OnMouseDown do TImage, vc pode utilizar a propriedade Tag para sinalizar quando o componente estará ou não no modo edição. Neste momento, também posicionamos a caneta:
procedure TForm1.Image2MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 // botão mouse pressionado - vamos pintar...
 // aqui vc pode testar ainda qual o botão pressionado, para habilitar conforme o caso
  Image2.Tag := 1;
 // Posiconamos a caneta onde clicamos
  Image2.Picture.Bitmap.Canvas.MoveTo(X -XOffSet, Y -YOffSet);
end;


[b:fd2a771bf4]3[/b:fd2a771bf4]) Ao mover o mouse (evento OnMouseMove), vc verifica se a imagem está no modo edição, caso esteja vc chama o método LineTo que fará uso da caneta para desenhar na imagem a partir da última posição da caneta, neste caso aquela que deixamos ao chamar MoveTo anteriormente.
procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if Image2.Tag = 1 then  // se vamos pintar...
    Image2.Picture.Bitmap.Canvas.LineTo(X -XOffSet, Y -YOffSet);
end;


[b:fd2a771bf4]4[/b:fd2a771bf4]) Ao ser liverado o botão do mouse (evento OnMouseUp), vc verifica se estava no modo edição e, caso esteja, verifica ainda se por acaso o mouse foi apenas pressionado e solto, caracterizando apenas um clique com a intensão de marcar 1 ponto apenas. Caso isto ocorra, forçamos o desenho do ponto.
Este procedimento deve-se ao fato de que não havendo movimento do mouse, não há o evento OnMouseMove e então, ao tentar marcar um ponto não conseguiriamos sem este artifícil.
procedure TForm1.Image2MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 // caso seja apenas clicado e solto o botão, sem o arrasto, então
 // forçamos o desenho de um ponto, chamando moveto na mesma posição
  if Image2.Tag = 1 then  // se estavamos pintando...
  with Image2.Picture.Bitmap.Canvas do
   if ((X -XOffSet) = PenPos.x) and ((Y -YOffSet) = PenPos.Y) then
     LineTo(X -XOffSet, Y -YOffSet);
  Image2.Tag := 0;
end;


Teste ai, qualquer coisa...

Abraços


GOSTEI 0
Jeferson Machia

Jeferson Machia

20/11/2007

Olá amigo. Sei que já é antigo e desculpe por reabrir, mas estou com algumas dúvidas e acredito que ficaria mais completo se conseguir responder. É o seguinte, como eu faria para apagar a bola que marquei, tipo e se eu marcar umas cinco, mas ai quero retirar uma e deixar apenas 4 bolas na imagem. Como eu poderia fazer isso? Seria subtrair o ponto de x e y ? Para gravar essas posições em um banco de dados seria somente gravar o x e y e depois carregar quando eu chamar o cliente no banco de dados os valores de x e y vem? Outra duvida seria, se x e y guarda todos os valores do pixel, se eu tiver cinco bolas, ele guardo a posição destas 5 somente em um x e y ? Obrigado se puder ajudar. abraço e parabéns.
GOSTEI 0
POSTAR