你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
Delphi实现简易图形标绘系统
 

    本文介绍了在Delphi环境中实现非矢量图形标绘的简便方法,并给出了程序环境设计与具体代码实现。

关键词  Delphi,非矢量图形,标绘

 

一、前言

相对于语言文字来说,图形能把一定具体共同空间形式及特征的事物形象而概括地表示出来,不仅简化文字叙述,节省时间,而且形象直观,一目了然。在港口码头舰船靠泊、机场飞机驻屯、车场管理等工作中,管理人员需要实时掌握泊位、机位、车位的占用情况,而通过图形标绘能够将舰船、飞机、车辆的停靠情况标注在码头、机场、车场示意图上,让管理人员及时掌握整体情况,进行科学高效管理。

本文介绍了在Delphi环境下实现非矢量图形标绘的简便方法,其实现思路为:根据特定参数动态创建图标控件,并使其支持鼠标拖放操作;在退出系统时,把所有标绘的图标信息(种类、标题、序号和位置)保存至配置文件中,在下一次进入系统时则先读取配置文件,恢复显示上一次退出前所有标绘的图标。

二、窗体设计

程序实验环境如下:

(1)操作系统:Windows XP Professional SP2

(2)开发环境:Delphi 7.0 + Raize Components 3.11控件包。

1.主窗体Form1

Delphi新建一个项目Test,并创建主窗体Form1,其属性Caption设为“简易图形标绘系统”。

在窗体中放置一个ImageList控件,并导入相关的图片,如图1


 

在窗体中放置一个GroupBox控件,其属性Caption设为“军标”,属性Align设为alLeft。在GroupBox1上放置一个ListView控件,属性LargeImages设为ImageList1,属性OwnerDraw设为True,并增加ListView1Item项,Item1的属性Caption设为“常规潜艇”,属性ImageIndex设为0Item2的属性Caption设为“核潜艇”,属性ImageIndex设为1Item3的属性Caption设为“驱逐舰”,属性ImageIndex设为2Item4的属性Caption设为“护卫舰”,属性ImageIndex设为3

在窗体中放置三个BitBtn控件,第一个的属性Caption设为“更换地图”,第二个的属性Caption设为“图标属性”,第三个的属性Caption设为“清除图标”。

在窗体中放置两个RzToolButton控件,第一个的属性Caption设为“种子控件”,属性Name设为RzToolButton_,属性Visible设为False,第二个的属性Visible也设为False

在窗体中放置一个ScrollBox控件,属性Align设为alClient,在其上放置一个Image控件,属性Align设为alClient,并设置Image1Picture属性(导入一幅电子地图图片)。

在窗体中放置一个OpenPictureDialog控件,属性Filter设为“All (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp | JPEG Image File (*.jpg)|*.jpg|JPEG Image File (*.jpeg)|*.jpeg|Bitmaps (*.bmp)|*.bmp”。

主窗体的设计效果如图2所示:


 

2.属性窗体Form2

在项目中创建属性窗体Form2,窗体中放置一个Label、一个Edit和一个BitBtn控件,设计效果如图3所示。


 

三、代码实现

1.公共变量定义

bFirstEnter, bBackground: Boolean;        //是否第一次进入,是否更换电子地图图片

SelfDir, sCaption: string;                 //程序目录, 图标Caption

myIniFile: string;                       //图标配置文件

rwIniFile: TIniFile;                      //读写图标配置文件

iXh, iImageIndex, iCurObject: Integer;      //图标序号, 图标ImageIndex, 当前图标的对象编号

cxVarObject: Array [0..99] of TRzToolButton;//图标新标号

cxSelObject: TRzToolButton;              //种子图标

myControl: TControl;                    //当前图标

XX, YY: Integer;                        //当前图标的新位置

2.图标对象的初始化与存取

procedure TForm1.FormCreate(Sender: TObject);

begin

 

  SelfDir := ExtractFilePath(Paramstr(0)); //当前目录

  myIniFile := SelfDir + 'System.ini';    //配置文件

  bFirstEnter := False;                //登录标志

  bBackground := False;              //更换电子地图图片标志

  iXh := 1;                         //创建的图标标识数

  iCurObject := 0;                   //当前图标的对象编号

  ScrollBox1.DoubleBuffered := True;  //防止拖动控件时图片闪烁

end;

//判读是否为首次进入系统,若为首次登录则读取图标配置文件,调用创建图标的事件,恢复显示上一次退出前所有标绘的图标

procedure TForm1.FormShow(Sender: TObject);

var

  i, iLeft, iTop, icount: Integer;

  sName: string;

  Shift: TShiftState;

begin

  if bFirstEnter then

    Exit;

  if FileExists(myIniFile) then

  begin

    rwIniFile := TIniFile.Create(myIniFile);                         //读取图标配置文件

    icount := rwIniFile.ReadInteger('Control', 'Count', 0);               //图标个数

    for i := 1 to icount do

    begin

      sName := rwIniFile.Readstring(IntToStr(i), 'Name', '');            //图标Name

      if Length(sName) > 0 then

      begin

        cxSelObject := RzToolButton_;                            //图标的父继承控件

        sCaption := rwIniFile.Readstring(IntToStr(i), 'Caption', '');       //图标Caption

        iImageIndex := rwIniFile.ReadInteger(IntToStr(i), 'ImageIndex', 0);//图标ImageIndex'

        iLeft := rwIniFile.ReadInteger(IntToStr(i), 'Left', 0);            //图标Left

        iTop := rwIniFile.ReadInteger(IntToStr(i), 'Top', 0);            //图标Top

        Image1MouseDown(Sender, mbLeft, Shift, iLeft, iTop);        //-调用创建图标事件-

      end

      else

        cxSelObject := nil;

    end;

    rwIniFile.Free;

  end;

  bFirstEnter := True;

end;

//退出系统时,把所有标绘的图标信息(种类、标题、序号和位置)保存至配置文件中

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

var

  i, iPos, iImageIndex: Integer;

  aOwner: TControl;

  sHint, sCaption: string;

begin

  rwIniFile := TIniFile.Create(myIniFile);                         //存取的配置文件名

  rwIniFile.WriteInteger('Control', 'Count', ScrollBox1.ControlCount - 1);//图标个数(Image1除外)

  for i := 0 to ScrollBox1.ControlCount - 1 do                      //该控件内的所有子控件

  begin

    aOwner := ScrollBox1.Controls[i];

    if aOwner is TRzToolButton then                            //符合类型的图标控件

    begin

      sHint := aOwner.Hint;

      iPos := Pos(Chr(1), sHint);

      sCaption := Copy(sHint, 1, iPos - 1);                                      

      iImageIndex :=  StrToInt(Copy(sHint, iPos + 1, Length(sHint) - Length(sCaption) - 1));

      rwIniFile.WriteString(IntToStr(i), 'Name', aOwner.Name);

      rwIniFile.WriteString(IntToStr(i), 'Caption', sCaption);

      rwIniFile.WriteInteger(IntToStr(i), 'ImageIndex', iImageIndex);

      rwIniFile.WriteInteger(IntToStr(i), 'Left', aOwner.Left);

      rwIniFile.WriteInteger(IntToStr(i), 'Top', aOwner.Top);

    end;

  end;

  rwIniFile.Free;

  CanClose := True;

end;

3.拖曳图标的鼠标事件

//设置指定控件处理鼠标事件

procedure TForm1.ControlMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

var

  iPos: Integer;

  sName: string;

begin

  myControl := TControl(Sender);

  SetCaptureControl(myControl);

  XX := X;

  YY := Y; 

  if (myControl is TRzToolButton) then //获得鼠标右键单击时的当前图标标识

  begin

    iPos := Pos('_', myControl.Name);

    sName := Copy(myControl.Name, 1, iPos - 1);

    iCurObject := StrToInt(Copy(myControl.Name, iPos + 1, Length(myControl.Name) - Length(sName) - 1));

  end;

end;

//获得正在处理鼠标事件的控件,并定位到新位置

procedure TForm1.ControlMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);

begin

  myControl := GetCaptureControl;

  if myControl = nil then

    Exit;

  myControl.Left := myControl.Left + X - XX;

  myControl.Top := myControl.Top + Y - YY;

end;

//释放鼠标事件

procedure TForm1.ControlMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

  ReleaseCapture;

end;

//延时事件,用于当前图标的闪烁事件

procedure HaveSigned(MaxWaitTime: Cardinal);

var

  WaitedTime: Cardinal;

begin

  WaitedTime := 0;

  while (WaitedTime < MaxWaitTime) do

  begin

    SleepEx(100, False);

    Inc(WaitedTime, 100);

    Application.ProcessMessages ;

  end;

end;

//当前图标的闪烁事件

procedure TForm1.RzToolButtonWink(Sender: TObject);

begin

  if ((Sender as TRzToolButton).Name <> 'RzToolButton1') then

  begin

    iCurObject := (Sender as TRzToolButton).Tag;

    (Sender as TRzToolButton).Visible := False;

    HaveSigned(200);

    (Sender as TRzToolButton).Visible := True;

    HaveSigned(200);

    (Sender as TRzToolButton).Visible := False;

    HaveSigned(200);

    (Sender as TRzToolButton).Visible := True;

  end;

end; 

4、根据鼠标点击所传递的参数,动态创建图标

//根据鼠标点击ListViewItem项传递创建图表所需的相关参数

procedure TForm1.ListView1Click(Sender: TObject);

begin

  if ListView1.ItemIndex < 0 then

    Exit;

  cxSelObject := RzToolButton_;                             //图标的种子(父亲)控件

  sCaption := ListView1.Items[ListView1.ItemIndex].Caption;      //图标Caption

  iImageIndex := ListView1.Items[ListView1.ItemIndex].ImageIndex;//图标ImageIndex

end; 

//根据参数动态创建图标

procedure TForm1.Image1MouseDown(Sender:TObject; Button:TMouseButton; Shift:TShiftState; X,Y: Integer);

var

  i: Integer;

begin

  if cxSelObject = nil then

    Exit;

  Image1.Cursor := crCross;

  if (iXh > 100) then

  begin

    Application.MessageBox('创建的图标对象已超过100个!', '提示', MB_OK+MB_ICONINFORMATION);

    Exit;

  end;

  if cxSelObject <> RzToolButton1 then

  begin

    //连续序号

    for i := 1 to 99 do

    begin

      if cxVarObject[i] = nil then

      begin

        iXh := i;

        Break;

      end;

    end;

    //创建选择的图标对象

    //设置图标的属性

    cxVarObject[iXh] := TRzToolButton.Create(Application);

    cxVarObject[iXh].Name := cxSelObject.Name + IntToStr(iXh);     //名称

    cxVarObject[iXh].Parent := ScrollBox1;

    cxVarObject[iXh].Left := X;                                 // Left

    cxVarObject[iXh].Top := Y;                                 // Top

    cxVarObject[iXh].Width := cxSelObject.Width;                 //长度Width

    cxVarObject[iXh].Height := cxSelObject.Height;                //高度Height

    cxVarObject[iXh].Layout := blGlyphTop;                      //图标的图片布局

    cxVarObject[iXh].Caption := sCaption;                        //Caption

    cxVarObject[iXh].ShowCaption := True;                      

    cxVarObject[iXh].Images := cxSelObject.Images;                //图标的图片

    cxVarObject[iXh].ImageIndex := iImageIndex;                 

    cxVarObject[iXh].Hint := sCaption + Chr(1) + IntToStr(iImageIndex);//图标的提示信息

    cxVarObject[iXh].ShowHint := False;                         

    cxVarObject[iXh].Cursor := crHandPoint;                       //光标

    cxVarObject[iXh].Visible := True;                             

    cxVarObject[iXh].Tag := iXh;                               

    iCurObject := iXh;                                         //图标序号

设置图标的事件

    cxVarObject[iXh].OnMouseDown := ControlMouseDown;//控件移动的鼠标事件

    cxVarObject[iXh].OnMouseMove := ControlMouseMove ;

    cxVarObject[iXh].OnMouseUp := ControlMouseUp;     

    cxVarObject[iXh].OnClick := RzToolButtonWink;       //闪烁事件

  end;

  cxSelObject := RzToolButton1;                      //转移鼠标焦点

  Image1.SendToBack;

  Image1.Cursor := crDefault;

end;

5.其他事件

//更换底图

procedure TForm1.BitBtn1Click(Sender: TObject);

var

  MyJpegImage: TJpegImage;

  MyBmp: TBitmap;

  sFileName, sFileExt: string;

begin

  if not OpenPictureDialog1.Execute then

    Exit;

  sFileName := OpenPictureDialog1.FileName;

  sFileExt := Copy(sFileName, Length(sFileName) - 2, 3);

  if (sFileExt = 'jpg') or (sFileExt = 'JPG') or (sFileExt = 'peg') or (sFileExt = 'PEG') then//若为JPG图片

  begin

    MyJpegImage := TJpegImage.Create;

    try

      MyJpegImage.LoadFromFile(sFileName);

      Image1.Picture.Graphic := MyJpegImage;

    finally

      MyJpegImage.Free;

    end;

  end

  else if (sFileExt = 'bmp') or (sFileExt = 'BMP') then//若为BMP图片

  begin

    MyBmp := TBitmap.Create;

    try

      MyBmp.LoadFromFile(sFileName);

      Image1.Picture.Graphic := MyBmp;

    finally

      MyBmp.Free;

    end;

  end;

end;

//打开Form2窗体,设置当前图标的名称Caption属性

procedure TForm1.BitBtn2Click(Sender: TObject);

var

  sCaption, sText: string;

  iImageIndex: Integer;

begin

  if (cxVarObject[iCurObject] <> nil) and (cxVarObject[iCurObject] is TRzToolButton) then

  begin

    //读取当前图标属性

    sCaption := cxVarObject[iCurObject].Caption;

    iImageIndex := cxVarObject[iCurObject].ImageIndex;

    //闪烁当前图标

    cxVarObject[iCurObject].Visible := False;

    HaveSigned(150);

    cxVarObject[iCurObject].Visible := True;

    //打开"图标属性设置"窗口

    Form2 := TForm2.Create(nil);

    try

      Form2.Edit1.Text := sCaption;

      if Form2.ShowModal = MrOK then

      begin

        sText := Form2.Edit1.Text;

        if sText <> sCaption then  //比较变化情况

        begin

          cxVarObject[iCurObject].Caption := sText;

          cxVarObject[iCurObject].Hint := sText + Chr(1) + IntToStr(iImageIndex);

        end;

      end;

    finally

      Form2.Free;

    end;

  end;

end;

//删除当前图标

procedure TForm1.BitBtn3Click(Sender: TObject);

begin

  if cxVarObject[iCurObject] <> nil then

  begin

    //闪烁当前图标

    cxVarObject[iCurObject].Visible := False;

    HaveSigned(200);

    cxVarObject[iCurObject].Visible := True;

    //提示删除

    if Application.MessageBox('确定删除当前图标吗?', '提示', MB_YESNO+MB_ICONWARNING) = IDYES then

      if (cxVarObject[iCurObject].Parent = ScrollBox1) then

        FreeAndNil(cxVarObject[iCurObject]);

  end;

end;

四、结语

本文介绍了在Delphi环境下实现非矢量图形标绘的基本方法,主要给出了系统的窗体设计、图标的初始化与配置信息存取、图标创建与拖放、图标属性设置等图形标绘关键事件的代码实现,虽然总体功能还比较简单,但在实际的应用中可以根据需要进行修改与扩展,比如根据用户需求定制图标,对图标方向、大小、颜色等属性的动态调整,图标搜索及将图标信息与数据库数据关联等,应用范围将进一步扩大。

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089