你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
5.16 用Delphi实现可视化答题卡设计器(下)
 

四、答题卡组件工具条

    这个工具条上的按钮是设计器所需要的答题卡组件,如图2所示。这个工具条的窗体名为frmTool,窗体类型为fsStayOnTop。在点击每一个组件按钮时,系统都会记录所点的是哪个组件。每一个组件按钮是一个TSpeedButton。在TspeedButtontag中保存了当前的组件按钮代表哪一个答题卡组件。所有的组件按钮都执行同一段代码。这段代码如下:
procedure TfrmTool.SpeedButton1Click(Sender: TObject);

var

  widget_id: integer;

begin

  ButtonDown(FunGroup1, Sender);  // 如果某个按钮被按下,将这个按钮设为按下状态

  if drawing_widget <> nil then 

  begin

    drawing_widget.Free;

    drawing_widget := nil

  end;

  widget_id := (Sender as TSpeedButton).Tag;  // 获得当前组件类型

  if widget_id = 0 then   // 设置当前的鼠标指针

    frmMain.Card.Cursor := crDefault

  else

    frmMain.Card.Cursor := crCross;

  case widget_id of   // drawing_widget为全局变量,保存了当前被选中的答题卡组件

    VERTICAL_TBT:  // 选中纵向同步头

    begin

      drawing_widget := TTBT_Vertical.Create(nil) as TWidgetContainer;

    end;

    HORIZONTAL_TBT:  // 选中横向同步头

    begin

      drawing_widget := TTBT_Horizontal.Create(nil) as TWidgetContainer;

    end;

    INFOCOLLECTION:   // 选中信息采集区

    begin

      drawing_widget := TInfoCollection .Create(nil) as TWidgetContainer;

    end;

    QUESTIONREGION:   // 选中答题区

    begin

      drawing_widget := TQuestionRegion .Create(nil) as TWidgetContainer;

    end;

    ZKZREGION:   // 选中准考证

    begin

      drawing_widget := TZKZ .Create(nil) as TWidgetContainer;

    end;

    BORDER:   // 选中边框

    begin

      drawing_widget := TBorder .Create(nil) as TWidgetContainer;

    end;

    BORDEREXTENSION:   // 选中扩展边框

    begin

      drawing_widget := TBorderExtension .Create(nil) as TWidgetContainer;

    end;

    VERTICAL1_TBT:   // 选中只有两个方框的纵向同步头

    begin

      drawing_widget :=  TTBT_Vertical1.Create(nil) as TWidgetContainer;

    end;

    HORIZONTAL1_TBT:  // 选中只有两个方框的横向同步头

    begin

      drawing_widget :=  TTBT_Horizontal1.Create(nil) as TWidgetContainer;

    end;

    VERTICAL_LINE:   // 选中纵向非答题区

    begin

      drawing_widget :=  TVertical_Line.Create(nil) as TWidgetContainer;

    end;

    VERTICAL_SINGLELINE:  // 选中纵向直线

    begin

      drawing_widget :=  TVertical_SingleLine.Create(nil) as TWidgetContainer;

    end;

    HORIZONTAL_SINGLELINE:  // 选中横向直线

    begin

      drawing_widget :=  THorizontal_SingleLine.Create(nil) as TWidgetContainer;

    end;

    HORIZONTAL_LINE:   // 选中横向非答题区

    begin

      drawing_widget :=  THorizontal_Line.Create(nil) as TWidgetContainer;

    end;

  end;

end;

五、主界面

   
在设计中将答题卡画在TPaintBox上。在画完组件,鼠标抬起后。将在MouseUp事件中把drawing_widget所指的组件对象放到TPaintBox上。MouseUp事件的代码如下:

procedure TfrmMain.pbCardMouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

var

  i: integer;

  function Abs_Int(x: integer): integer;   // 取整数的绝对值

  begin

    if x < 0 then

      result := -x

    else

      result := x;

  end;

  function IsSelected(control: TControl): boolean;   // 判断组件是否应被选中

  var

    NewX, NewY, h, w: integer;

  begin

    if X < OldX then  // 鼠标向左侧画

    begin

      NewX := X;

      w := OldX - X;

    end

    else   // 鼠标向右侧画

    begin

      NewX := OldX;

      w := X - OldX;

    end;

    if Y < OldY then  // 鼠标向上侧画

    begin

      NewY := Y;

      h := OldY - Y;

    end

    else  // 鼠标向下侧画

    begin

      NewY := OldY;

      h := Y - OldY;

end;

// 判断鼠标所画的区域是否包含了control所指的组件对象

    if (control.Left + control.Width >= NewX) and (control.Top + control.Height >= NewY) then

    begin

      if (NewX + w > control.Left) and (NewY + h > control.Top) then

      begin

        result := true;

        exit;

      end;

    end;

    result := false;

  end;

 

begin

  drawflag := false;

  pbCard.Repaint;  // 将画布重画

  for i := 0 to Card.ControlCount - 1 do  // 根据鼠标画的区域选择答题卡的所有的组件

  begin

    if Card.Controls[i] is TWidgetContainer then

    begin

      if IsSelected(Card.Controls[i]) then

        (Card.Controls[i] as TWidgetContainer).WidgetStatus := [wsAll];

    end;

  end;

  if drawing_widget <> nil then  // 开始画答题卡组件

  begin

    drawing_widget.Parent := card;  // 将组件放到TPaintBox

    drawing_widget.Width := Abs_Int(X - OldX);  // 设置组件的宽度

    if X < OldX then  // 计算控制是向左侧画,还是向右侧画

      drawing_widget.Left := X

    else

      drawing_widget.Left := OldX;

 

    if Y < OldY then  // 计算控制是向上画,还是向下画

      drawing_widget.Top := Y

    else

      drawing_widget.Top := OldY;

 

    drawing_widget.Height := Abs_Int(Y - OldY);  // 设置组件的高度

    drawing_widget.WidgetStatus := [wsAll];   // 将组件设为被选中状态(显示所有的尺寸块)

 

    current_widget := drawing_widget;

    drawing_widget := nil;

    frmTool.SpeedButton1Click(frmTool.SpeedButton1);

    changed;    // 通知系统当前的答题卡已经被改变

  end;

end;

答题卡设计器不仅可以在TPaintBox上设计答题卡,而且还可以根据所设计的答题卡生成一个bmp图。生成bmp图的代码如下:
procedure TfrmMain.SaveCard(fn: string);

var

  bmp: TBitmap;

  i: integer;

  rect, rect1: TRect;

  wc: TWidgetContainer;

  OldCanvas: TCanvas;

begin

  bmp := TBitmap.Create;  // 建立一个Tbitmap对象

  bmp.Width := card.Width;  // 将这个Tbitmap对象的宽度设为TPaintBox的宽度

  bmp.Height := card.Height;  // 将这个Tbitmap对象的高度设为TPaintBox的高度

  for i := 0 to card.ControlCount - 1 do   // 扫描打题卡中的所有组件,将它们依次画到bmp图上

  begin

    if card.Controls[i] is TWidgetContainer then  // TPaintBox中的控制是TwidgetContainer时进行

    begin

      wc := card.Controls[i] as TWidgetContainer; 

      rect.Left := wc.Left;

      rect.Top := wc.Top;

      rect.Right := wc.Width;

      rect.Bottom := wc.Height;

      rect1.Left := 0;

      rect1.Top := 0;                  

      rect1.Right := wc.Width;

      rect1.Bottom := wc.Height;

      wc.DrawWidgetToCanvas(bmp.Canvas);  // 开始在bmp上画相应的答题卡组件

    end;

  end;

  bmp.SaveToFile(fn);   // 保存bmp

  bmp.Free;

end;


六、总结

在本文中给出了实现答题卡设计器的核心代码。感兴趣的读者可以根据这些源代码来增加程序的功能,从而设计出更为丰富的答题卡设计器来。

  推荐精品文章

·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