ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 How to change drawing line of miPutLine

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
AndyColmes Posted - May 23 2014 : 00:16:44
When creating objects of lines, I would like to change the usual black line during drawing. Once the line is drawn, it picks up the color of the ObjPenStyle and ObjPenColor which is fine. It is just the initial drawing that the color is always black which is a problem for grayscale images where the user cannot see what he or she is drawing.

Thanks in advance.
11   L A T E S T    R E P L I E S    (Newest First)
xequte Posted - May 29 2014 : 20:27:48
Wow, Spetric, really enjoyed your video (your accent is way better than mine, and English is my first language ). Those are some awesome effects!

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
spetric Posted - May 29 2014 : 12:46:12
Here you can see those compound objects in action:

http://www.youtube.com/watch?v=1H6-ssIPX-4

Please, ignore my accent in this video, it sound like Will Sasso's impression of Arnold Schwarzenegger.
spetric Posted - May 29 2014 : 12:37:26
In OnMouseMove event, on some objects, I'm checking TShiftState and if Shift key is pressed I'm moving object around (translation). When Alt key is pressed I'm drawing circle/square instead of ellipse/rectangle and when Ctrl key is pressed I'm rotating the object.

This Ctrl "option" comes handy, when you want to rotate rectangle/square:



Now, you can't do it with iekBOX object, but I use the trick: instead of iekBOX I'm using closed iekPOLYLINE with 4 points...and so constructed rectangle can be rotated. The same thing can be done with ellipse, but I did not implemented as it's more complicated...to much points :)
w2m Posted - May 29 2014 : 12:33:44
Thanks for the info Spetric.


William Miller
spetric Posted - May 29 2014 : 12:14:33
Hi Bill,

I'll try to answer your questions:

How did you add the ellipse as shown in you post?

I have extracted only the line drawing and presented it in code.
Here is how it looks when there is some kind of compound object (ellipse, line and text)


// mouse down event
// line with circle around it and text (line angle)
// _hobj, xDown and yDown as in previous post
PaintView->ObjKind[_hobj] = iekLINE;
PaintView->ObjBrushStyle[_hobj] = bsSolid;
PaintView->ObjBrushColor[_hobj] = clBlue;
PaintView->ObjEndShape[_hobj] = iesOUTARROW;
// new objects (circle + text)
_hAdd1 = PaintView->AddNewObject();
PaintView->ObjKind[_hAdd1]    = iekELLIPSE;
PaintView->ObjPenStyle[_hAdd1] = psDot;
PaintView->ObjTop[_hAdd1]  =  yDown;
PaintView->ObjLeft[_hAdd1] =  xDown;
PaintView->ObjWidth[_hAdd1]  = 0;
PaintView->ObjHeight[_hAdd1] = 0;
PaintView->ObjPenWidth[_hAdd1]   = someWidth;
PaintView->ObjPenColor[_hAdd1]   =  someColor;
PaintView->ObjStyle[_hAdd1] = TIEVStyle()<<ievsVisible;
//
_hAdd2 = PaintView->AddNewObject();
PaintView->ObjKind[_hAdd2] = iekTEXT;
PaintView->ObjFontHeight[_hAdd2] = -15;
PaintView->ObjFontName[_hAdd2]   = "Tahoma";
PaintView->ObjText[_hAdd2]       = "";
PaintView->ObjTextAlign[_hAdd2] = iejCenter;
PaintView->ObjPenStyle[_hAdd2]  = psClear;
PaintView->ObjTop[_hAdd2]  =  yDown;
PaintView->ObjLeft[_hAdd2] =  xDown;
PaintView->ObjWidth[_hAdd2]  = 40;
PaintView->ObjHeight[_hAdd2] = 30;


Mouse move:

// mouse move event
// xMove and yMove as in previuso post
double radius, angle;
PaintView->ObjWidth[_hobj]  = xMove - PaintView->ObjLeft[_hobj];
PaintView->ObjHeight[_hobj] = yMove - PaintView->ObjTop[_hobj];
// following function returns angle and radius length
pxaf_GetLineData(&radius, &angle, xDown, _yDown, xMove, yMove);
PaintView->ObjLeft[_hAdd1]  = xDown  - fast_ftol(radius);
PaintView->ObjTop[_hAdd1]   = yDown  - fast_ftol(radius);
PaintView->ObjWidth[_hAdd1] = fast_ftol(radius)*2;
PaintView->ObjHeight[_hAdd1]= fast_ftol(radius)*2;
// angle with decimals -> PaintView->ObjText[_hAdd2]  = FloatToStr(180.0 * angle/M_PI);
// angle as integer (I don't need decimals)
PaintView->ObjText[_hAdd2]  = IntToStr(fast_ftol(180.0 * angle/M_PI));


Note: fast_ftol is small assembly routine that converts double to integer.
I think we don't need this with XE5, however it works faster with BCB6, especially in loop with large ammount of data (pixels).

pxaf_GetLineData is a simple procedure that calculates angle and radius of a line drawn from x1,y1 to x2,y2. If someone need this I can post it.


How did you turn off the drawing by setting ImageEnVect1.MouseInteractVt <> [miObjectSelect])?

Well, I'm actually deleting object (after rendering) in OnMouseUp and use data of an object (angle, radius) to perform some rendering (int this case it's image warping). However, if you want to leave object on ImageEnVect, in OnMouseUp event
simply set ImageEnVect->OnMouseMove = 0;

So, initially, OnMouseMove event is set to 0. In OnMouseDown event set ImageEnVect->OnMOuseMove = MouseMove; and then in OnMouseUp event again set OnMouseMOve to 0.

Obviously, when you want to manipulate vectorial object in usual way (select, move, size) OnMouseDown event must be set to 0 (NULL). To add a new object, again set OnMOuseMoveDown object to method MouseDown.

w2m Posted - May 29 2014 : 10:59:24
To change an object after it is created get the selected object and then set the objects parameters:
procedure TForm1.BrushColor1Change(Sender: TObject);
{ BrushColor1Change. }
const
  BS: array [0 .. 7] of TBrushStyle = (bsSolid, bsClear, bsHorizontal,
    bsVertical, bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross);
var
  i: Integer;
  hobj: Integer;
begin
  BrushStyle1.ItemIndex := 0;
  if BrushTransparency1.Position <> 255 then
    DitheredColor1.Brush.Color := DitherColor(BrushColor1.Selected,
      BrushTransparency1.Position)
  else
    DitheredColor1.Brush.Color := BrushColor1.Selected;
  with ImageEnVect1 do
    for i := 0 to SelObjectsCount - 1 do
    begin
      if i >= 0 then
      begin
        ObjSaveUndo;
        hobj := SelObjects[i];
        ObjBrushColor[hobj] := DitheredColor1.Brush.Color;
        ObjLabelBrushColor[hobj] := DitheredColor1.Brush.Color;
        ObjBrushStyle[hobj] := BS[BrushStyle1.ItemIndex];
        ObjMemoCharsBrushStyle[hobj] := BS[BrushStyle1.ItemIndex];
      end;
      Update;
    end;
  UpdateGUI;
end;

To set the parameters of an object before it is created specify IEV_NEXT_INSERTED_OBJECT then set the objects parameters. In this case the object is created when dragged and dropped from a TButton:
procedure TForm1.ImageEnVect1DragDrop(Sender, Source: TObject; X, Y: Integer);
{ Drop object to mouse position from selected Drag & Drop buttons. }
var
  i: Integer;
  ihObj: Integer;
  iNumberBoxes: Integer;
  iNumberBitmaps: Integer;
begin
  { Accept drops from TButtons with Tags from 1 to 8 }
  if (Source is TButton) and ((Source as TButton).Tag in [1 .. 8]) then
  begin
    AChanging := True;
    PenStyle1.ItemIndex := 0;
    iNumberBoxes := 1;
    iNumberBitmaps := 1;
    { Specify the layer index where the object is located (drawn and referenced) }
    ImageEnVect1.ObjLayer[IEV_NEXT_INSERTED_OBJECT] :=
      ImageEnVect1.LayersCurrent;
    ImageEnVect1.ObjText[IEV_NEXT_INSERTED_OBJECT] := 'Box';
    ImageEnVect1.ObjFontLocked[IEV_NEXT_INSERTED_OBJECT] := False;
    ImageEnVect1.ObjPenWidth[IEV_NEXT_INSERTED_OBJECT] :=
      StrToIntDef(PenWidth1.Text, 1);
    ImageEnVect1.ObjPenStyle[IEV_NEXT_INSERTED_OBJECT] := psSolid;
    ImageEnVect1.ObjPenColor[IEV_NEXT_INSERTED_OBJECT] := PenColor1.Selected;
    ImageEnVect1.ObjBrushStyle[IEV_NEXT_INSERTED_OBJECT] := bsSolid;
    ImageEnVect1.ObjBrushColor[IEV_NEXT_INSERTED_OBJECT] :=
      BrushColor1.Selected;
    { Make sure the object dimensions are less than the bitmap dimensions }
    if ImageEnVect1.Bitmap.Width <= 64 then
    begin
      ImageEnVect1.ObjWidth[IEV_NEXT_INSERTED_OBJECT] :=
        ImageEnVect1.Bitmap.Width div 2;
      ImageEnVect1.ObjHeight[IEV_NEXT_INSERTED_OBJECT] :=
        ImageEnVect1.Bitmap.Height div 2;
    end
    else
    begin
      ImageEnVect1.ObjWidth[IEV_NEXT_INSERTED_OBJECT] := 64;
      ImageEnVect1.ObjHeight[IEV_NEXT_INSERTED_OBJECT] := 64;
    end;
    ihObj := ImageEnVect1.AddNewObject;
    { Count the number of object types }
    for i := 0 to ImageEnVect1.ObjectsCount - 1 do
    begin
      if ImageEnVect1.ObjKind[i] = iekBOX then
        Inc(iNumberBoxes);
      if ImageEnVect1.ObjKind[i] = iekBITMAP then
        Inc(iNumberBitmaps);
    end;
    ImageEnVect1.ObjLayer[ihObj] := ImageEnVect1.LayersCurrent;
    case (Source as TButton).Tag of
      1:
        begin
          ImageEnVect1.MouseInteractVt := [miPutBox];
          ImageEnVect1.ObjKind[ihObj] := iekBOX;
          ImageEnVect1.ObjName[ihObj] :=
            AnsiString('Box ' + IntToStr(iNumberBoxes));
        end;
      2:
        begin
          ImageEnVect1.MouseInteractVt := [miPutBitmap];
          ImageEnVect1.ObjKind[ihObj] := iekBITMAP;
          ImageEnVect1.ObjBitmap[ihObj] := ImageEnView1.IEBitmap;
          ImageEnVect1.ObjName[ihObj] :=
            AnsiString('Bitmap ' + IntToStr(iNumberBitmaps));
          ImageEnVect1.ObjWidth[ihObj] := ImageEnView1.IEBitmap.Width;
          ImageEnVect1.ObjHeight[ihObj] := ImageEnView1.IEBitmap.Height;
          { Do not allow resizing bitmap objects }
          ImageEnVect1.ObjStyle[ihObj] := ImageEnVect1.ObjStyle[ihObj] -
            [ievsSizeable];
        end;
    end;
    ImageEnVect1.ObjLeft[ihObj] := ImageEnVect1.Layers
      [ImageEnVect1.LayersCurrent].ConvXScr2Bmp(X);
    ImageEnVect1.ObjTop[ihObj] := ImageEnVect1.Layers
      [ImageEnVect1.LayersCurrent].ConvYScr2Bmp(Y);
    ImageEnVect1.MouseInteractVt := [miObjectSelect];
    ImageEnVect1.AddSelObject(ihObj);
    ImageEnVect1.UnSelAllObjects;
    UpdateStatusbar;
  end
  else
  begin
    ImageEnVect1.MouseInteractVt := [miObjectSelect];
    ImageEnVect1.UnSelAllObjects;
  end;
  AChanging := False;
end;

procedure TForm1.ImageEnVect1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
{ Accept drop objects from TButtons. }
begin
  Accept := Source is TButton;
end;

William Miller
Adirondack Software & Graphics
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Custom Commercial ImageEn Development
w2m Posted - May 29 2014 : 07:40:24
Spetric,

Very nice.

I converted to pascal, so I'll post the pascal code shortly.
How did you add the ellipse as shown in you post?
How did you turn off the drawing by setting ImageEnVect1.MouseInteractVt <> [miObjectSelect])?

William Miller
Adirondack Software & Graphics
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Custom Commercial ImageEn Development
spetric Posted - May 29 2014 : 06:25:32
Here we go. MouseInteract is empty (no miPutLine).
On ImageEnVect component (PaintView in code) we have OnMouseDown event and OnMouseMove. I use also OnMouseUp event for rendering purposes, but in your case this isn't obligatory.

Here is mousedown event:

// OnMouseDown event
xDown = PaintView->XScr2Bmp(X);
yDown = PaintView->YScr2Bmp(Y);

// _hobj - private variable
_hobj = PaintView->AddNewObject();
PaintView->ObjKind[_hobj] = iekLINE;
PaintView->ObjBrushStyle[_hobj] = bsSolid;
PaintView->ObjBrushColor[_hobj] = clBlue;
PaintView->ObjEndShape[_hobj] = iesOUTARROW;
//you can neglect upper line 
PaintView->ObjTop[_hobj]  =  yDown;
PaintView->ObjLeft[_hobj] =  xDown;
PaintView->ObjWidth[_hobj]  = 0;
PaintView->ObjHeight[_hobj] = 0;
PaintView->ObjPenWidth[_hobj]   = someWidth;
PaintView->ObjPenColor[_hobj]   =  someCOlor;
PaintView->ObjStyle[_hobj] = TIEVStyle()<<ievsVisible;
PaintView->ObjName[_hobj] = "someName";


And here is mousemove event:

// OnMouseMove event
xMove = PaintView->XScr2Bmp(X);
yMove = PaintView->YScr2Bmp(Y);

PaintView->ObjWidth[_hobj]  = xMove - PaintView->ObjLeft[_hobj];
PaintView->ObjHeight[_hobj] = yMove - PaintView->ObjTop[_hobj];


xDown and yDown can be declared as private variables. I use them when performing object movement across the screen (when shift key is pressed - in onmousemove event).

Hope this helps.
spetric Posted - May 28 2014 : 12:31:35
I don't have simple demo, but I can extract code from project where I use such kind of manipulation with vectorial objects.

I'll try to prepare code for tomorrow. However, it's in C++, but you'll get the picture.
AndyColmes Posted - May 28 2014 : 07:12:33
Hi spetric, thank you for your suggestion which seems interesting. Do you have a simple demo project to demonstrate this? I would really appreciate it. Thanks again for helping out.
spetric Posted - May 28 2014 : 01:34:42
Hi Andy.

I haven't find the way to change "temporary" color of line when miPuLine interaction is set.

I don't know if this can help you: sometimes I want to draw multiple objects and "reshape" them on mouse move:




There are actually 3 objects, created in OnMouseDown event:
line with arrow, circle and text (angle in degrees).

In OnMouseMove event I'm simple reshaping those objects according to mouse position.

In the same way, you can create simple line in OnMouseDown event (with desired color) and then change the shape of line in OnMouseMove event.