Link to home
Start Free TrialLog in
Avatar of dirkil2
dirkil2

asked on

Delphi: How to implement marching ants selection box with graphics32?

Hi there!

I am fairly new to graphics32 and unfortunately documentation about it is very sparse.

On a TImage32 I would like to let the user mark a rectangular area with the mouse as usual by clicking with the left mouse button to mark the start and then dragging the mouse with a pressed left mouse button until the rectangle like he wants it. When the user releases the left mouse button the area he defined should be marked with a rectangle (TPolygon32?) so that the border of the rectangle shows marching ants.

If someone could write me a little sample I would be very happy.

Regards,
Dirk.
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

Something like this ?
unit Unit2;

interface

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

type
  TForm2 = class(TForm)
    img1: TImage;
    procedure img1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure img1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure img1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Déclarations privées }
    _RectStart,_RectStop:TPoint;
    _StartImg:TBitmap;
    _StartSelect:Boolean;
    Procedure DrawRect(P1,P2:TPoint);
  public
    { Déclarations publiques }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

Procedure TForm2.DrawRect(P1,P2:TPoint);
Var
 Temp:integer;
begin
 img1.Picture.BItmap.Assign(_StartImg);
 With img1.Canvas do
  begin
   Pen.Style:=psDashDot;
   Pen.Color:=clYellow;
   Brush.Style:=bsClear;
   if P1.X>P2.X Then
    begin
     Temp:=P1.X;
     P1.X:=P2.X;
     P2.X:=Temp;
    end;
   if P1.Y>P2.Y Then
    begin
     Temp:=P1.Y;
     P1.Y:=P2.Y;
     P2.Y:=Temp;
    end;
   Rectangle(Rect(P1.X,P1.Y,P2.X,P2.Y));
  end;
end;

procedure TForm2.img1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 if Shift=[ssLeft] Then
  begin
   _RectStart.X:=x;
   _RectStart.Y:=y;
   _StartSelect:=True;
   _StartImg:=TBitmap.Create;
   _StartImg.Assign(img1.Picture.Bitmap);
  end;
end;

procedure TForm2.img1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
 if _StartSelect And (Shift=[ssLeft]) Then
  begin
   _RectStop.X:=x;
   _RectStop.Y:=y;
   DrawRect(_RectStart,_RectStop);
  end;
end;

procedure TForm2.img1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 if _StartSelect Then
  begin
   _RectStop.X:=x;
   _RectStop.Y:=y;
   DrawRect(_RectStart,_RectStop);
   _StartSelect:=False;
   _StartImg.Free;
  end;
end;

end.

Open in new window

Avatar of dirkil2
dirkil2

ASKER

Hi epasquier,

thank you for your code but it didn't work for me. You didn't provide the dfm file so I had to experiment a little. I added a TImage and called it img1. I also assigned an image to the Picture property. Furthermore, I attached OnMouseDown, OnMouseUp and OnMouseMove to the callbacks you provided.

What happened is the following: as soon as I click with the left mouse button the image is cleared (looks like the backfround of the window). Even when I unassign the Picture (blank background) I never see a rect.

Maybe I did something wrong. Maybe it makes sense if you can provide the whole project to make sure I have everything as you have it.

Regards,
Dirk.
You did exactly what you had to do not having the DFM files.

are you using TImage or another derived component ?

check what you have in _StartImg after :
_StartImg.Assign(img1.Picture.Bitmap);

that is the background I save on the original click to be able to draw a moving rectangle while selecting the zone.

I will give you the exe later this day so that you can check at least that it is what you want.
ASKER CERTIFIED SOLUTION
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dirkil2

ASKER

Hi epasquier!

Great that you found where the problem was. This is almost what I wanted to have. The only thing left is that the "marching ants" are not marching yet. It is just a rect with a dotted line. I would like to have the line animated. So if the line pattern is 00110011 at the beginning it should be 11001100 half a second later and then half a second later back to the starting pattern and so on. Any idea how I can achieve that?

Regards,
Dirk.
I don't think it's possible with GDI (therefore by Delphi Canvas object), you would have to use GDI+ library to create a custom pattern for your pen
I'm not sure that it would be worth the trouble
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dirkil2

ASKER

@NevTon

Thanks for the great links you provided.

In my initial posting I mentioned that I use the graphics32 library for drawing. In the meantime I checked out a few more of the many sample programs that come with that library and in one of them (Transform demo, switch to projective tab) I found a selection with marching ants. I analysed the code and found to my surprise that the library has that functionality built-in! It's called TRubberband and you can put it on a separate layer which is very easy to use.

Thank you for your contributions - I will split the points between you. I hope you're ok with that.