Link to home
Start Free TrialLog in
Avatar of jlislo
jlislo

asked on

Design a graphic editer program.

I want to create a application to let user create graphic object on a background image. User can do things to the graphic object like programmer can do in design mode (Delphi IDE). For example resize, move, select, bring to front, send to back...etc

User can create TShape, TLabel, TEdit ...  graphic object. Min property editing. Save and load functions.

I like to know the concept behind those functions. If you have sample code to do all and want more points feel free to let me know.

Thanks.

JL
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

hello jlislo,  I do not understand what you want to do. . . in your question -->  "Design a graphic editer program". . . .
but then you say
"User can create TShape, TLabel, TEdit ...  graphic object"

what do you mean? ? For me a TLabel and a TEdit are  NOT in a graphic editer program? Do you want to have shapes and text on your drawing board that are separate objects to be clicked and moved, ,  that may take alot of effort?
Avatar of jlislo
jlislo

ASKER

Yes, you are right. I try to add some graphic shape and text on top of a image. And let user move, resize... those object. For start, when user click on the object I want to display the object with 8 square box (4 on each corner and 4 in the middle of each side).

Any book or document to teach you how to design a graphic editor program?

Do I have to handel the mousedown, mousemove and mouseup for each obj? Or I can create a continer to hold the graphic objs to do those thing?

Thanks.

JL
To do a full graphic editor program would take some one wilth much API graphic experience, a Long Time to do. You may want to learn how to do more basic graphical operations first. And YES you will need to handle ALL mouse and keyboard events on your display. I have some code for a graphic "Object" display and edit on a TPaintBox, if you would like to see the code. . .
Do you have experience with basic graphical operations, like Canvas.Rectangle( ),, Canvas.DrawFocusRect( ), or Canvas.Elispse( ). . .  ? ?
Avatar of jlislo

ASKER

I would love to. If you think 125 point is good enough for you. :-)

my email is jlli@qts.com Thanks.

JL
you did NOT answer my question about knowing something about graphical methods, oh well. . . .  Here is all the code for simple graphic "Object" program, I do not have time to comment and explain in this code, if you do not have much experience, then you may not be able to use this.




unit GrafEdit1;

interface

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

type
  TGraficObj = Record
    PosRect: TRect;
    FillColor, PenColor: TColor;
    PenWidth: Byte;
    Fill: Boolean;
    Layer, ObjType, ShapeIndex: Integer;
    Text: String[255];
    TextFace: String[64];
    TextSize : Integer;
    end;

  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    sbut_Shape: TSpeedButton;
    RadioGroup1: TRadioGroup;
    sbut_Text: TSpeedButton;
    sbut_FreeHand: TSpeedButton;
    CheckBox_Fill: TCheckBox;
    sbut_Select: TSpeedButton;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure sbut_SelectClick(Sender: TObject);
    procedure sbut_ShapeClick(Sender: TObject);
    procedure sbut_TextClick(Sender: TObject);
  private
    { Private declarations }
    PB_Bmp: TBitmap;
    ObjType, SelNum, OffX, OffY{, LastX, LastY}: Integer;
    DrawStart: TPoint;
    DrawRect: TRect;
    Drawing, Moving, Sizing: Boolean;
    Side: Char;
    GrafAry: Array of TGraficObj;
    procedure DrawShape(Index1: Integer);
    procedure PaintText(Index1: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
ObjType := -1;
SelNum := -1;
Drawing := False;
Moving := False;
Sizing := False;
PB_Bmp := TBitmap.Create;
PB_Bmp.Canvas.Brush.Color := $D0FBFF;
PB_Bmp.Width := PaintBox1.Width;
PB_Bmp.Height := PaintBox1.Height;
PB_Bmp.Canvas.TextOut(40,100, 'No Image');
end;

procedure TForm1.PaintText(Index1: Integer);
begin
if GrafAry[Index1].Fill then
  PaintBox1.Canvas.Brush.Color := GrafAry[Index1].FillColor
  else PaintBox1.Canvas.Brush.Style := bsClear;
PaintBox1.Canvas.Font.Name := GrafAry[Index1].TextFace;
PaintBox1.Canvas.Font.Size := GrafAry[Index1].TextSize;

PaintBox1.Canvas.TextOut(GrafAry[Index1].PosRect.Left,GrafAry[Index1].PosRect.Top,GrafAry[Index1].Text);
end;

procedure TForm1.DrawShape(Index1: Integer);
var
AryPnt1: Array[0..2] of TPoint;
begin
if GrafAry[Index1].Fill then
  PaintBox1.Canvas.Brush.Color := GrafAry[Index1].FillColor
  else PaintBox1.Canvas.Brush.Style := bsClear;
PaintBox1.Canvas.Pen.Color := GrafAry[Index1].PenColor;
PaintBox1.Canvas.Pen.Width := GrafAry[Index1].PenWidth;
case GrafAry[Index1].ShapeIndex of
    0: PaintBox1.Canvas.Rectangle(GrafAry[Index1].PosRect);

    1: PaintBox1.Canvas.Ellipse(GrafAry[Index1].PosRect);

    2: begin
       AryPnt1[0].x := GrafAry[Index1].PosRect.Left+((GrafAry[Index1].PosRect.Right - GrafAry[Index1].PosRect.Left) div 2);
       AryPnt1[0].y := GrafAry[Index1].PosRect.Top;
       AryPnt1[1].x := GrafAry[Index1].PosRect.Left;
       AryPnt1[1].y := GrafAry[Index1].PosRect.Bottom;
       AryPnt1[2].x := GrafAry[Index1].PosRect.Right;
       AryPnt1[2].y := GrafAry[Index1].PosRect.Bottom;
       PaintBox1.Canvas.Polygon(AryPnt1);
       end;
    end;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
i: Integer;

begin
PaintBox1.Canvas.Draw(0,0,PB_Bmp);

for i := 0 to High(GrafAry) do
  begin
  if GrafAry[i].ObjType = 0 then
   DrawShape(i);
   if GrafAry[i].ObjType = 1 then
   PaintText(i);
  end;

if SelNum > -1 then
  begin
  PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Pen.Color := clBlack;
  PaintBox1.Canvas.Pen.Width := 4;
  PaintBox1.Canvas.Pen.Mode := pmNot;
  PaintBox1.Canvas.Rectangle(DrawRect);
  PaintBox1.Canvas.Pen.Mode := pmCopy;
  PaintBox1.Canvas.Brush.Style := bsSolid;
  //PaintBox1.Canvas.DrawFocusRect(Rect1{DrawRect});
  end;
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
i: Integer;
Pnt1: TPoint;
begin
if Button = mbLeft then
  begin
  if ObjType = -1 then
    begin
    if PaintBox1.Cursor = crSizeWE then
    begin
    Sizing := True;
    if (X < DrawRect.Left+ 3) and (X > DrawRect.Left -3) then
      Side := 'L'
      else
      Side := 'R';
    Exit;
    end else
    if PaintBox1.Cursor = crSizeNS then
      begin
      Sizing := True;
      if (Y < DrawRect.Top+ 3) and (Y > DrawRect.Top -3) then
        Side := 'T'
        else
        Side := 'B';
      Exit;
      end;

    Drawing := False;
    Pnt1.x := X;
    Pnt1.y := Y;
    for i := High(GrafAry) downTo 0 do
      begin
      if PtInRect(GrafAry[i].PosRect, Pnt1) then
        begin
        Moving := True;
        OffX := GrafAry[i].PosRect.Left - X;
        OffY := GrafAry[i].PosRect.Top - Y;
        DrawStart.x := GrafAry[i].PosRect.Left;
        DrawStart.y := GrafAry[i].PosRect.Top;
        DrawRect := GrafAry[i].PosRect;
        if i <> SelNum then
          begin
          SelNum := i;
          PaintBox1Paint(PaintBox1);
          end;
        Break;
        end;
      end;
    end else
    begin
    DrawStart.x := X;
    DrawStart.y:= Y;
   
    DrawRect.Left := X;
    DrawRect.Top := Y;
    DrawRect.Right := X;
    DrawRect.Bottom := Y;
    if ObjType <> 1 then
    Drawing := True;
    end;
  end;
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
Drawing := False;
if Sizing then
  begin
  GrafAry[SelNum].PosRect := DrawRect;
  PaintBox1Paint(PaintBox1);
  Sizing := False;
  Exit;
  end;

if Moving then
  begin
  if (DrawStart.x <> DrawRect.Left) and (DrawStart.x <> DrawRect.Top) then
    begin
    GrafAry[SelNum].PosRect := DrawRect;
    PaintBox1Paint(PaintBox1);
    end;
  Moving := False;
  Exit;
  end;

if (ObjType <> -1) then
PaintBox1.Canvas.DrawFocusRect(DrawRect);
if ObjType = 0 then
  begin
  SetLength(GrafAry, Length(GrafAry)+1);
  GrafAry[High(GrafAry)].PosRect := DrawRect;
  GrafAry[High(GrafAry)].ObjType := ObjType;
  GrafAry[High(GrafAry)].Fill := CheckBox_Fill.Checked;
  GrafAry[High(GrafAry)].Layer := High(GrafAry);
  GrafAry[High(GrafAry)].FillColor := clRed;
  GrafAry[High(GrafAry)].PenColor := clGreen;
  GrafAry[High(GrafAry)].PenWidth := 1;
  GrafAry[High(GrafAry)].ShapeIndex := RadioGroup1.ItemIndex;
  DrawShape(High(GrafAry));
  end;

if (ObjType = 1) and (Length(Edit1.Text) > 0) then
  begin
  SetLength(GrafAry, Length(GrafAry)+1);
  GrafAry[High(GrafAry)].ObjType := ObjType;
  GrafAry[High(GrafAry)].Fill := CheckBox_Fill.Checked;
  GrafAry[High(GrafAry)].Text := Edit1.Text;
  GrafAry[High(GrafAry)].TextFace := 'Times New Roman';
  GrafAry[High(GrafAry)].TextSize := 24;
  GrafAry[High(GrafAry)].FillColor := clYellow;
  GrafAry[High(GrafAry)].PosRect.Left := X;
  GrafAry[High(GrafAry)].PosRect.Top := Y;
  GrafAry[High(GrafAry)].PosRect.Right := X+60;
  GrafAry[High(GrafAry)].PosRect.Bottom := Y+30;

  if GrafAry[High(GrafAry)].Fill then
  PaintBox1.Canvas.Brush.Color := GrafAry[High(GrafAry)].FillColor
  else PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Font.Name := GrafAry[High(GrafAry)].TextFace;
  PaintBox1.Canvas.Font.Size := GrafAry[High(GrafAry)].TextSize;
  GrafAry[High(GrafAry)].PosRect.Right := GrafAry[High(GrafAry)].PosRect.Left +
                       PaintBox1.Canvas.TextWidth(GrafAry[High(GrafAry)].Text);
  GrafAry[High(GrafAry)].PosRect.Bottom := GrafAry[High(GrafAry)].PosRect.Top +
                      PaintBox1.Canvas.TextHeight(GrafAry[High(GrafAry)].Text);
  PaintBox1.Canvas.TextOut(X,Y,GrafAry[High(GrafAry)].Text);
  end;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
if Sizing then
  begin
  PaintBox1.Canvas.Brush.Style := bsSolid;
  PaintBox1.Canvas.DrawFocusRect(DrawRect);
  if Side = 'T' then
    DrawRect.Top := Y
    else
    if Side = 'L' then
    DrawRect.Left := X
    else
    if Side = 'R' then
    DrawRect.Right := X
    else
    if Side = 'B' then
    DrawRect.Bottom := Y
    else DrawRect.Top := Y;
  PaintBox1.Canvas.DrawFocusRect(DrawRect);
  Exit;
  end;
if (ObjType = -1) and (SelNum > -1) then
  begin
{these boolean tests set the Cursor if over the DrawRect}
  if GrafAry[SelNum].ObjType = 0 then
  if (Y > DrawRect.Top-4) and (Y < DrawRect.Bottom +4) and
     ((X < DrawRect.Left+ 4) and (X > DrawRect.Left -4) or
     (X < DrawRect.Right+ 4) and (X > DrawRect.Right -4)) then
     PaintBox1.Cursor := crSizeWE else

  if (X > DrawRect.Left- 4) and (X < DrawRect.Right +4) and
     ((Y < DrawRect.Top+ 4) and (Y > DrawRect.Top -4) or
     (Y < DrawRect.Bottom+ 4) and (Y > DrawRect.Bottom -4)) then
     PaintBox1.Cursor := crSizeNS else
     PaintBox1.Cursor := crDefault;
  end;

if Drawing then
  if (X <> DrawRect.Right) and (Y <> DrawRect.Bottom) then
    begin
    PaintBox1.Canvas.DrawFocusRect(DrawRect);
    if X >= DrawStart.x then
      begin
      if DrawRect.Left <> DrawStart.x then
        DrawRect.Left := DrawStart.x;
      DrawRect.Right := X
      end else
      begin
      if DrawRect.Right <> DrawStart.x then
      DrawRect.Right := DrawStart.x;
      DrawRect.Left := X;
      end;
    if Y >= DrawStart.y then
      begin
      if DrawRect.Top <> DrawStart.y then
        DrawRect.Top := DrawStart.y;
      DrawRect.Bottom := Y;
      end else
      begin
      if DrawRect.Bottom <> DrawStart.y then
      DrawRect.Bottom := DrawStart.y;
      DrawRect.Top := Y;
      end;
    PaintBox1.Canvas.Brush.Style := bsSolid;
    PaintBox1.Canvas.DrawFocusRect(DrawRect);
    end;

if Moving then
  begin
  PaintBox1.Canvas.Brush.Style := bsSolid;
  PaintBox1.Canvas.DrawFocusRect(DrawRect);
  DrawRect.Right := DrawRect.Right - DrawRect.Left + X + OffX;
  DrawRect.Bottom := DrawRect.Bottom - DrawRect.Top + Y+ OffY;
  DrawRect.Left := X+ OffX;
  DrawRect.Top := Y+ OffY;
  PaintBox1.Canvas.DrawFocusRect(DrawRect);
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
PB_Bmp.Free;
end;

procedure TForm1.sbut_SelectClick(Sender: TObject);
begin
PaintBox1.Cursor := crArrow;
ObjType := -1;
SelNum := -1;
PaintBox1Paint(PaintBox1);
end;

procedure TForm1.sbut_ShapeClick(Sender: TObject);
begin
PaintBox1.Cursor := crDrag;
ObjType := 0;
SelNum := -1;
PaintBox1Paint(PaintBox1);
end;

procedure TForm1.sbut_TextClick(Sender: TObject);
begin
PaintBox1.Cursor := crCross;
ObjType := 1;
SelNum := -1;
PaintBox1Paint(PaintBox1);
end;

end.




- - - - -  - -  - --  - - - - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - -  - - - - -  - --


ask questions if you need some help
Avatar of jlislo

ASKER

I am so sorry I did miss your question. I have a lot experance in graphic programming but not graphic editor type related. That is why I try to focus on editing part. For example to me showing the 8 square box should be an exist function since the design mode already doing it.

Do you mind sending me the dfm that will help a lot.

Thanks.

JL
Avatar of jlislo

ASKER

I am so sorry I did miss your question. I have a lot experance in graphic programming but not graphic editor type related. That is why I try to focus on editing part. For example to me showing the 8 square box should be an exist function since the design mode already doing it.

Do you mind sending me the dfm that will help a lot.

Thanks.

JL
Avatar of jlislo

ASKER

I am so sorry I did miss your question. I have a lot experance in graphic programming but not graphic editor type related. That is why I try to focus on editing part. For example to me showing the 8 square box should be an exist function since the design mode already doing it.

Do you mind sending me the dfm that will help a lot.

Thanks.

JL
Avatar of jlislo

ASKER

I am so sorry I did miss your question. I have a lot experance in graphic programming but not graphic editor type related. That is why I try to focus on editing part. For example to me showing the 8 square box should be an exist function since the design mode already doing it.

Do you mind sending me the dfm that will help a lot.

Thanks.

JL
???????
there are several buttons and an TEdit and one check box, the specs of my form should not matter much at all,  the important aspects of this are the mouse messages for the TPaintBox. .  you should be able to get all of the info you need from the Form Class definitions,  speedbuttons, Edits, check boxes, paint boxes. . . but here it is -


object Form1: TForm1
  Left = 192
  Top = 114
  Width = 883
  Height = 740
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnClose = FormClose
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object PaintBox1: TPaintBox
    Left = 0
    Top = 0
    Width = 489
    Height = 393
    OnMouseDown = PaintBox1MouseDown
    OnMouseMove = PaintBox1MouseMove
    OnMouseUp = PaintBox1MouseUp
    OnPaint = PaintBox1Paint
  end
  object sbut_Shape: TSpeedButton
    Left = 560
    Top = 96
    Width = 57
    Height = 22
    Caption = 'Shape'
    OnClick = sbut_ShapeClick
  end
  object sbut_Text: TSpeedButton
    Left = 568
    Top = 216
    Width = 57
    Height = 22
    Caption = 'Text'
    OnClick = sbut_TextClick
  end
  object sbut_FreeHand: TSpeedButton
    Left = 568
    Top = 328
    Width = 97
    Height = 22
    Caption = 'FreeHand Shape'
  end
  object sbut_Select: TSpeedButton
    Left = 552
    Top = 16
    Width = 65
    Height = 22
    Caption = 'Select'
    OnClick = sbut_SelectClick
  end
  object RadioGroup1: TRadioGroup
    Left = 648
    Top = 88
    Width = 97
    Height = 113
    Caption = 'Shape'
    ItemIndex = 0
    Items.Strings = (
      'Rectangle'
      'Ellipise'
      'Triangle'
      'Pentagram'
      'Hexagram')
    TabOrder = 0
  end
  object CheckBox_Fill: TCheckBox
    Left = 560
    Top = 128
    Width = 73
    Height = 17
    Caption = 'Fill Shape'
    Checked = True
    State = cbChecked
    TabOrder = 1
  end
  object Edit1: TEdit
    Left = 568
    Top = 248
    Width = 201
    Height = 21
    MaxLength = 255
    TabOrder = 2
    Text = 'Text'
  end
end
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America 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 jlislo

ASKER

Thanks, It work great. this will get me start.