AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CADを考える:アンドゥ/リドゥ(元に戻す/やり直し)
前回は各要素データの削除について記述しました。ここでは、アンドゥ(UNDO;元に戻す)・リドゥ(REDO;やり直し)について考えていきます。
 
アンドゥは、何か作業を行った後、それをしなかった事にする=元に戻す、という処理です。例えば、線を作図した直後にその線を消したり、円を消した直後にその円を復活させたり、というように、操作ミスをしたので元に戻したい、或いは、やってみたけれども今ひとつなので戻したい、等の場合に利用されます。

リドゥは、アンドゥをしたあと、考え直して、やっぱりいいか、と先ほどの作業を再度行う場合に利用されます。ですのでリドゥとアンドゥは対になります。アンドゥをした後に作図・編集等を行うと、リドゥは出来なくなります。

 
作図のアンドゥは削除、削除のアンドゥは作図、となります。それをリドゥすると、削除されたものは作図、作図されたものは削除、となります。

 
線分コマンドでは1回のコマンドで1つの線分要素データを追加しますが、上下に平行線を作図するようなコマンドでは、1回のコマンドで2つの線分要素データを追加する事があります。そのため、アンドゥ最大数と要素数は同じにはなりません。そのため、現在のオペレーション番号とその履歴を管理する変数が別途必要となります。
 
アンドゥを行った後に作図/削除を行うと、その履歴が上書きされ、その分のリドゥが出来なくなります。これが通常のWindowsアプリケーションでの振舞いとなります。

 
アプリケーションによっては、このような一方向アンドゥ・リドゥではなく、分岐を行って、履歴を上書きしないようなシステムというシステムも有り得ます。そうすることによって完全に元に戻すという事が可能になりますが、管理が複雑になると思われます。

 
ここでは、一般的な一方向アンドゥ・リドゥのシステムで作成します。既に作成している「落書きテストプログラム」と似せて作成します。
Unitdata.pas
TOpeHistory = record // 操作履歴
 opt : integer ;   // 操作タイプ
 opn : integer ;   // 操作番号(1-)
 ope : integer ;   // 0:表記要素 +:幾何要素 -:シンボル
 ord : integer ;   // 作図順 xOrdへの番号
end;
 
TDataClass = class
 public
 { Public 宣言 }
 ・・・
 OpeHistory : array of TOpeHistory ; // 操作履歴
 OpeHistoryN, OpeNumber, OpeUndoN : integer ;
 ・・・
実装の前に、レイヤ・色・線種・線幅・文字フォント、については、どうするのか?を考えておく必要があります。現在、これらについては、存在フラグはありませんし、編集機能は、削除+追加ではなく、内容を直接変更するようになっています。これら設定にも、アンドゥ・リドゥを行えるようにしたい、という場合には、存在フラグの追加を行い、編集機能を変更する必要があります。
 
例えば、レイヤ名を一括変更した場合、アンドゥで元に戻す、という事が出来るようにするかどうか、です。もし、対応するのであれば、存在フラグと、レイヤ番号/色番号/線種番号/線幅番号/文字フォント番号を扱う変数を実装し、これらに対応するように、これまでのプログラムを変更しなければなりません。動的配列の添え字+1=番号、だったものを、存在しないデータが含まれ番号がずれますので、番号を探す処理に変更しなければなりません。
 
こういった基本的部分の作業は、なるべく早くにやっておいた方が無難です。後になればなるほど、修正は難しく煩雑になっていきます。
 
という訳で、チャレンジしてみる事にします。まずレイヤから始めます。現在のレイヤは、
Unitdata.pas
TZumenLayer = record   // 図面構造|レイヤ
 name : string ;    // レイヤ名
 Lflag : Integer ;   // 0:非表示 1:表示
 Color : Integer ;   // レイヤ色
 Ltype : Integer ;   // レイヤ線種
 Width : Integer ;   // レイヤ線幅
 Mfont : Integer ;   // レイヤ文字フォント
 cnt : Integer ;    // レイヤ内要素数
 Fcnt : Integer ;    // 複合図形定義内のレイヤ内要素数
end;
となっていますが、これを、
Unitdata.pas
TZumenLayer = record   // 図面構造|レイヤ
 exf : Boolean ;    // 存在フラグ(True:有り False:無し)
 no : integer ;     // レイヤ番号(1-256)
 name : string ;    // レイヤ名
 Lflag : Integer ;   // 0:非表示 1:表示
 Color : Integer ;   // レイヤ色
 Ltype : Integer ;   // レイヤ線種
 Width : Integer ;   // レイヤ線幅
 Mfont : Integer ;   // レイヤ文字フォント
 cnt : Integer ;    // レイヤ内要素数
 Fcnt : Integer ;    // 複合図形定義内のレイヤ内要素数
end;
とします。そして、レイヤに関わる部分、全てを変更します。まずはレイヤの追加を行う AddLayer()関数から。従来は下記のようになっています。
Unitdata.pas
// レイヤ データ項目の追加登録
function TDataClass.AddLayer(s:string;fla,col,ltp,wid,fnt:integer)
 : Boolean;
begin
 Result := False;
 if not(StrCheck(s)) then exit;
 if (LayerNameCheck(0,s) > 0) then exit;
 if (zLayN = LAYER_MAX_NUM) then exit ;
 
 if (fla <> 0) then fla := 1;
 if (col < 1)or(col > zColN) then col := 1;
 if (ltp < 1)or(ltp > zLtpN)or(ltp = 16) then ltp := 1;
 if (wid < 1)or(wid > zWidN) then wid := 1;
 if (fnt < 1)or(fnt > zFntN) then fnt := 1;
 
 Inc(zLayN);
 SetLength(zLay, zLayN);
 with zLay[zLayN-1] do begin
  name := s ;
  Lflag := fla ;
  Color := col ;
  Ltype := ltp ;
  Width := wid ;
  Mfont := fnt ;
  cnt := 0 ;
  Fcnt := 0 ;
 end;
 Result := True ;
end;
最初の最大レイヤ数チェックの部分
 if (zLayN = LAYER_MAX_NUM) then exit ;
は、正しくないという事になります。動的配列の要素数とレイヤ数はイコールではないからです。存在フラグで「存在しない」レイヤの要素が増えているためです。これをチェックするための関数を作成しておきます。
// 現在のレイヤ数を取得する
function TDataClass.GetLayerNum : Integer;
var
 m,r,i : integer ;
begin
 m := 0 ;
 r := 0 ;
 for i:=0 to zLayN-1 do begin
  if not(zLay[i].exf) then continue ;
  if (m < zLay[i].no) then m := zLay[i].no ;
  Inc(r);
 end;
 
 zLayMax := m ;
 Result := r ;
end;
また、レイヤ番号を指定したら、レイヤの動的配列の添え字を取得する関数も合わせて作っておきます。
// レイヤ番号の要素indexを取得する
function TDataClass.GetLayerIdx(n:integer) : Integer;
var
 i : integer ;
begin
 Result := -1 ;
 if (n < 1)or(n > LAYER_MAX_NUM) then exit;
 for i:=0 to zLayN-1 do begin
  if not(zLay[i].exf) then continue ;
  if (n = zLay[i].no) then begin
   Result := i ;
   break ;
  end;
 end;
end;
LayerNameCheck()関数の内容も修正しておきます。
// 指定したレイヤ名のレイヤ番号を取得する
function TDataClass.LayerNameCheck(n:integer;s:string) : Integer;
var
 i,j : integer;
 s1,s2 : AnsiString ;
begin
 Result := 0 ;
 s1 := AnsiString(s) ;
 s1 := MidStr2(s1,1,32,j);
 for i:=0 to zLayN-1 do begin
  if not(zLay[i].exf) then continue ;
  if (zLay[i].no = n) then continue;
  s2 := AnsiString(zLay[i].name) ;
  s2 := MidStr2(s2,1,32,j);
  if (s1 = s2) then begin
   Result := zLay[i].no ;
   break ;
  end;
 end;
end;
AddLayer()関数内では、色・線種・線幅・文字フォントの番号チェックも行われておりますが、これらも、動的配列要素数がそれらの最大番号とはなりませんから修正を行う必要があります。しかし、こういったチェックは各所にあり、そのたびに、動的配列要素内を全検索して最大数を取得してからチェックを行うとなると、検索に時間が掛かりそうな予想が働きます。つまり、CAD操作での作図速度が遅くなる原因の1つになりそうな感じがします。ですので、動的配列要素数の変数とは別に、それぞれの実最大数を保持する変数を用意し、それを参照するように修正します。勿論、実最大数を取得する関数は作成しておきます。
 
それでは AddLayer()関数の修正を行います。
Unitdata.pas
// レイヤ データ項目の追加登録
function TDataClass.AddLayer(s:string;fla,col,ltp,wid,fnt:integer)
 : Boolean;
begin
 Result := False;
 if not(StrCheck(s)) then exit;
 if (LayerNameCheck(0,s) > 0) then exit;
 if (zLayMax = LAYER_MAX_NUM) then exit ;
 
 if (fla <> 0) then fla := 1;
 if (col < 1)or(col > zColMax) then col := 1;
 if (ltp < 1)or(ltp > zLtpMax)or(ltp = 16) then ltp := 1;
 if (wid < 1)or(wid > zWidMax) then wid := 1;
 if (fnt < 1)or(fnt > zFntMax) then fnt := 1;
 
 Inc(zLayMax);
 Inc(zLayN);
 SetLength(zLay, zLayN);
 with zLay[zLayN-1] do begin
  exf := True ;
  no := zLayMax ;
  name := s ;
  Lflag := fla ;
  Color := col ;
  Ltype := ltp ;
  Width := wid ;
  Mfont := fnt ;
  cnt := 0 ;
  Fcnt := 0 ;
 end;
 Result := True ;
end;
 
レイヤ編集の為にはレイヤ削除が必要なので、DelLayer()関数を追加します。
Unitdata.pas
// レイヤ データ項目の削除
//  n : レイヤ番号
// (ret) True:OK False:NG
function TDataClass.DelLayer(n:integer) : Boolean;
var
 i : integer ;
begin
 Result := False ;
 i := GetLayerIdx(n); // 要素index
 if (i > -1) then begin
  zLay[i].exf := False ;
  Result := True ;
 end;
end;
 
これまでレイヤ等の番号は、1,2,3,・・・と順番に+1ずつ追加していましたが、これにより、連続であると想定したレイヤ番号に、欠番が生じることになります。そのため、レイヤ番号指定によりレイヤ追加を行う必要性が出てきますので修正することとします。もし既に存在するレイヤ番号を指定した場合にはエラーを返すものとします。
こうなってくると、レイヤ数≠最大レイヤ番号となってきます。これはレイヤに限らず、色・線種・線幅・文字フォントでも同様です。また、登録時には存在した番号のものも、後で削除された場合にはどうなるのか?という問題も出てきます。ですので、レイヤ・色・線種・線幅・フォントは最大番号を保持するようにして、実際に描画を行う際、もしも存在しない場合には、1番のもので描画するものとします。ですのでレイヤ1・フォント1は初期化時点で必ず存在するものとするようにします。
Unitdata.pas
// レイヤ データ項目の追加登録
function TDataClass.AddLayer(n:integer;s:string;
 fla,col,ltp,wid,fnt,cn1,cn2:integer) : Boolean;
var
 idx : integer ;
begin
 Result := False;
 if (n < 1)or(n > LAYER_MAX_NUM) then exit;
 idx := GetLayerIdx(n);
 if (idx > -1) then exit ;
 if not(StrCheck(s)) then exit;
 if (LayerNameCheck(0,s) > 0) then exit;
 
 if (fla <> 0) then fla := 1;
 if (col < 1)or(col > zColMax) then col := 1;
 if (ltp < 1)or(ltp > zLtpMax)or(ltp = 16) then ltp := 1;
 if (wid < 1)or(wid > zWidMax) then wid := 1;
 if (fnt < 1)or(fnt > zFntMax) then fnt := 1;
 
 try
  Inc(zLayN);
  SetLength(zLay, zLayN);
  with zLay[zLayN-1] do begin
   exf := True ;
   no := n ;
   name := s ;
   Lflag := fla ;
   Color := col ;
   Ltype := ltp ;
   Width := wid ;
   Mfont := fnt ;
   cnt := cn1;
   Fcnt := cn2;
  end;
  Result := True ;
  if (zLayMax < n) then zLayMax := n ;
 except
  Dec(zLayN);
 end;
end;
 
レイヤ編集用の関数 EditLayer()の内容を、直接変更するのではなく、削除+追加で処理するよう修正しておきます。これで、レイヤの分の下準備が出来ました。それでは、レイヤの分のアンドゥ・リドゥの実装を行います。
 
操作履歴を格納する関数を作成します(暫定)。
// 操作履歴を追加します
// tp : 操作タイプ 1:設定追加 2:設定削除
// et : 設定) 1:レイヤ
//   要素) 0:表記要素 +:幾何要素 -:シンボル
// en : 作図順 xOrdへの番号
// OpeNumber ... 操作番号(1-)
function TDataClass.OpAdd(tp,et,en:integer) : Boolean ;
begin
 try
  Inc(OpeHistoryN);
  if ((OpeHistoryN mod 200) = 1) then
   SetLength(OpeHistory, OpeHistoryN+199);
  with OpeHistory[OpeHistoryN-1] do begin
   opt := tp ;
   opn := OpeNumber ;
   ope := et ;
   ord := en ;
  end;
  Result := True ;
 except
  Dec(OpeHistoryN);
  Result := False ;
 end;
 OpeUndoN := OpeHistoryN ;
end;
これをレイヤ追加・レイヤ削除で呼び出すようにします。
// レイヤ データ項目の追加登録
function TDataClass.AddLayer(n:integer;s:string;
 fla,col,ltp,wid,fnt,cn1,cn2:integer) : Boolean;
var
 idx : integer ;
begin
 Result := False;
 if (n < 1)or(n > LAYER_MAX_NUM) then exit;
 idx := GetLayerIdx(n);
 if (idx > -1) then exit ;
 if not(StrCheck(s)) then exit;
 if (LayerNameCheck(0,s) > 0) then exit;
 
 if (fla <> 0) then fla := 1;
 if (col < 1)or(col > zColMax) then col := 1;
 if (ltp < 1)or(ltp > zLtpMax)or(ltp = 16) then ltp := 1;
 if (wid < 1)or(wid > zWidMax) then wid := 1;
 if (fnt < 1)or(fnt > zFntMax) then fnt := 1;
 
 try
  Inc(zLayN);
  SetLength(zLay, zLayN);
  with zLay[zLayN-1] do begin
   exf := True ;
   no := n ;
   name := s ;
   Lflag := fla ;
   Color := col ;
   Ltype := ltp ;
   Width := wid ;
   Mfont := fnt ;
   cnt := cn1;
   Fcnt := cn2;
  end;
  if (OpAdd(1,1,zLayN-1)) then begin
   Result := True ;
   if (zLayMax < n) then zLayMax := n ;
  end
  else
   Dec(zLayN);
 except
  Dec(zLayN);
 end;
end;
 
// レイヤ データ項目の削除
function TDataClass.DelLayer(n:integer) : Boolean;
var
 i : integer ;
begin
 Result := False ;
 i := GetLayerIdx(n); // 要素index
 if (i > -1) then begin
  if (OpAdd(2,1,i)) then begin
   zLay[i].exf := False ;
   if (n = zLayMax) then GetLayerNum; // 最大レイヤ番号更新
   Result := True ;
  end;
 end;
end;
 
レイヤの追加、削除を行う処理の前に、操作履歴番号 OpeNumber の値を+1するようにします。上記で行っていないのは、1回の操作で複数の設定・要素の追加・削除を行えるようにするためです。例えば、
Inc(CData.OpeNumber);
CData.AddLayer(CData.zLayMax+1,'レイヤ名',1,col,ltp,wid,fnt,0,0);
のようにします。こうして、レイヤを追加・削除する毎に、操作履歴変数 OpeHistory、OpeHistoryN の内容が追加されていきます。アンドゥは、この変数内容を見て、存在フラグを反転し、OpeHistoryN値を減らします。リドゥは、OpeHistoryN値を戻し(増やし)この変数内容を見て存在フラグを反転します。下記はまだレイヤのアンドゥ・リドゥのみ対応です。
// アンドゥ可能かどうかのチェック
function TDataClass.CheckOpUndo : Boolean ;
begin
 Result := True ;
 if (OpeNumber = 0) then Result := False ;
end;
 
// リドゥ可能かどうかのチェック
function TDataClass.CheckOpRedo : Boolean ;
begin
 Result := True ;
 if (OpeUndoN = OpeHistoryN) then Result := False ;
end;
 
// アンドゥ・リドゥのサブ
// 存在フラグを反転する=追加→削除、削除→追加の操作を行う
procedure TDataClass.OpUndoRedoSub ;
var
 tp,et,en : integer ;
begin
 with OpeHistory[OpeHistoryN-1] do begin
  tp := opt ;
  et := ope ;
  en := ord ;
 end;
 case(tp)of
  1,2: begin // 設定
   case(et)of
    1: begin // レイヤ
      with zLay[en] do
       exf := not(exf);
     end;
    end;
   end;
  else begin // 要素
  end;
 end
end;
 
// アンドゥ
procedure TDataClass.OpUndo ;
begin
 if not(CheckOpUndo) then exit ;
 while (OpeHistoryN > 0) do begin
  if (OpeHistory[OpeHistoryN-1].opn = OpeNumber) then begin
   OpUndoRedoSub ;
  end
  else
   break ;
  Dec(OpeHistoryN);
 end;
 Dec(OpeNumber);
end;
 
// リドゥ
procedure TDataClass.OpRedo ;
begin
 if not(CheckOpRedo) then exit ;
 Inc(OpeNumber);
 while (OpeHistoryN <= OpeUndoN) do begin
  Inc(OpeHistoryN);
  if (OpeHistory[OpeHistoryN-1].opn = OpeNumber) then begin
   OpUndoRedoSub ;
  end
  else begin
   Dec(OpeHistoryN);
   break ;
  end;
 end;
end;
画面 Form1 上に、[アンドゥ]ボタン、[リドゥ]ボタンを配置し、それぞれ、上記のアンドゥ・リドゥを行うようにします。
 
これでレイヤ設定のアンドゥ・リドゥが出来るようになりました。次に、色・線種・線幅・文字フォントについても同様に行います。以下の関数を追加します。追加・編集・名前チェック用の関数は内容を修正します。
function GetColorNum : Integer;
function GetColorIdx(n:integer) : Integer;
function AddColor(n,r,g,b,cn1,cn2:integer) : Boolean;
function DelColor(n:integer) : Boolean;
function EditColor(n:integer;r,g,b:integer) : Boolean;
function GetLtypeNum : Integer;
function GetLtypeIdx(n:integer) : Integer;
function LtypeNameCheck(n:integer;s:string) : Integer;
function AddLtype(n:integer;s:string;seg:integer;
      pit:array of double;cn1,cn2:integer) : Boolean;
function DelLtype(n:integer) : Boolean;
function EditLtype(n:integer;s:string;seg:integer;
      pit:array of double) : Boolean;
function GetWidthNum : Integer;
function GetWidthIdx(n:integer) : Integer;
function AddWidth(n:integer;w:double;cn1,cn2:integer) : Boolean;
function DelWidth(n:integer) : Boolean;
function EditWidth(n:integer;w:double) : Boolean;
function GetFontNum : Integer;
function GetFontIdx(n:integer) : Integer;
function FontNameCheck(n:integer;s:string) : Integer;
function AddFont(n:integer;s:string;cn1,cn2:integer) : Boolean;
function DelFont(n:integer) : Boolean;
function EditFont(n:integer;s:string) : Boolean;
アンドゥ・リドゥのサブ手続きは下記のようになります。
// アンドゥ・リドゥのサブ
procedure TDataClass.OpUndoRedoSub ;
var
 tp,et,en : integer ;
begin
 with OpeHistory[OpeHistoryN-1] do begin
  tp := opt ;
  et := ope ;
  en := ord ;
 end;
 case(tp)of
  1,2: begin // 設定
   case(et)of
    1: begin // レイヤ
     with zLay[en] do
      exf := not(exf);
    end;
    2: begin // 色
     with zCol[en] do
      exf := not(exf);
    end;
    3: begin // 線種
     with zLtp[en] do
      exf := not(exf);
    end;
    4: begin // 線幅
     with zWid[en] do
      exf := not(exf);
    end;
    5: begin // 文字フォント
     with zFnt[en] do
      exf := not(exf);
    end;
   end;
  end;
  else begin // 要素
  end;
 end
end;
 
これで、各設定(レイヤ・色・線種・線幅・文字フォント)のアンドゥ・リドゥ処理が完了しました。次に、各定義データについて考えます。定義データとしては、複合曲線定義、既定義ハッチング名定義、シンボル図形定義、複合図形定義、があります。このうち、既定義ハッチング名定義の内容は固定ですので除外します。それぞれ、関数 AddCCurveDef()、AddSymbolDef()、AddFZukeiDef()、にて行いますが、ここにアンドゥ用の操作履歴変数への追加を行うよう修正します。現在は定義の削除はありませんが以降で必要になった場合には、設定関連同様の処理を行うようにします。
// 複合曲線定義 データ項目の追加登録
function TDataClass.AddCCurveDef(id,col,ltp,wid,inv:integer) : Boolean;
var
 i : integer ;
begin
 Result := False;
 if (id < 1) then exit ;
 //
 i := CCrvIDCheck(id); // ID番号が使用済かどうかをチェック
 if (i >= 0) then exit ; // ID番号使用済
 //
 if (col < 0) or (col > zColMax) then col := 0 ;
 if (ltp < 0) or (ltp > zLtpMax) then ltp := 0 ;
 if (wid < 0) or (wid > zWidMax) then wid := 0 ;
 if (inv <> 0) then inv := 1 ;
 //
 try
  Inc(cDefN);
  SetLength(cDef, cDefN);
  with cDef[cDefN-1] do begin
   exf := True ;
   ・・・
  end;
  DataClearCCurveMember(cDefN-1);
  if (OpAdd(3,1,cDefN-1)) then begin
   Result := True ;
  end
  else begin
   Dec(cDefN);
   SetLength(cDef, cDefN);
  end;
 except
  Dec(cDefN);
  SetLength(cDef, cDefN);
 end;
end;
 
// アンドゥ・リドゥのサブ
procedure TDataClass.OpUndoRedoSub ;
var
 tp,et,en : integer ;
begin
 with OpeHistory[OpeHistoryN-1] do begin
  tp := opt ;
  et := ope ;
  en := ord ;
 end;
 case(tp)of
  1,2: begin // 設定
   case(et)of
    1: begin // レイヤ
     with zLay[en] do
      exf := not(exf);
    end;
    2: begin // 色
     with zCol[en] do
      exf := not(exf);
    end;
    3: begin // 線種
     with zLtp[en] do
      exf := not(exf);
    end;
    4: begin // 線幅
     with zWid[en] do
      exf := not(exf);
    end;
    5: begin // 文字フォント
     with zFnt[en] do
      exf := not(exf);
    end;
   end;
  end;
  3,4: begin // 定義
   case(et)of
    1: begin // 複合曲線
     with cDef[en] do
      exf := not(exf);
    end;
    2: begin // シンボル図形
     with sDef[en] do
      exf := not(exf);
    end;
    3: begin // 複合図形
     with fDef[en] do
      exf := not(exf);
    end;
   end;
  end;
  else begin // 要素
  end;
 end
end;
 
次に、各要素データについてです。複合図形配置は作図順変数から除外していましたが、アンドゥ・リドゥ処理のため、コード:99として追加するようにします。但し表示についてはこれまで通りとします。
 
// 点マーカ データ項目の追加登録
function TDataClass.AddDataTen(s:string;lay,col,mc:integer;
 px,py,an,sc:double) : Boolean;
var
 m : integer ;
begin
 Result := False;
 if (lay < 1) or (lay > zLayMax) then lay := 1 ;
 if (col < 0) or (col > zColMax) then col := 0 ;
 if (mc < 1) or (mc > 7) then mc := 3 ; // dot
 an := SetAngle(an);
 if (sc < LIMIT8) then sc := 1.0;
 
 if (s = '') then begin
  // 用紙へ追加
  if (AddDataOrder(0,1,dTenN)) then begin
   try
    Inc(dTenN);
    if ((dTenN mod 200) = 1) then SetLength(dTen, dTenN+199);
    with dTen[dTenN-1] do begin
     exf := True ;
     Layer := lay ;
     Color := col ;
     start_x := px ;
     start_y := py ;
     marker_code := mc ;
     rotate_angle:= an ;
     Scale := sc ;
    end;
    OpAdd(5,0,dOrdN-1);
    Result := True ;
    AddLayerCnt(lay,col,-1,-1,-1);
   except
    Dec(dTenN);
    Dec(dOrdN);
   end;
  end;
 end
 else begin
  m := FZukeiNameCheck(0,s);
  if (m > 0) then begin
   with fDef[m-1] do begin
    if (AddDataOrder(m,1,mTenN)) then begin
     try
      Inc(mTenN);
      if ((mTenN mod 200)=1) then SetLength(mTen,mTenN+199);
      with mTen[mTenN-1] do begin
       ・・・
      end;
      OpAdd(5,m,mOrdN-1);
      Result := True ;
      AddLayerFCnt(lay,col,-1,-1,-1);
     except
      Dec(mTenN);
      Dec(mOrdN);
     end;
    end;
   end;
  end
  else if (m < 0) then begin
   with sDef[-m-1] do begin
    if (AddDataOrder(m,1,mTenN)) then begin
     try
      Inc(mTenN);
      if ((mTenN mod 200)=1) then SetLength(mTen,mTenN+199);
      with mTen[mTenN-1] do begin
       ・・・
      end;
      OpAdd(5,m,mOrdN-1);
      Result := True ;
     except
      Dec(mTenN);
      Dec(mOrdN);
     end;
    end;
   end;
  end;
 end;
end;
のような具合です。その他の要素データについても同様に修正します。また、要素データ削除・直前削除を行う関数の修正、アンドゥ・リドゥの実装、を行います。レイヤ・色・線種・線幅・文字フォントの変数の扱いも変更しましたので、UnitDataGraph.pas 内での関連部分も修正します。LayN等のように比較チェックしていたものはLayMax値との比較に変更する事と、レイヤ値をそのままレイヤの配列の要素番号として使わず GetLayerIdxk()関数を利用する事、等です。
 
 
それでは、ここまでのテストプログラムです。実行ファイル、gdiplus.dll、gdipフォルダは入っていません。ソースのみです。
 
CAD装置(1)
CAD装置(2)
メディア
AutoCADの
DIESELマクロ
CSV
DXF
PCES
IGES
STEP
数学とCAD
CAD作ろ!
CADを考える
 ▲PREV
 ▼NEXT
M7
Jw_cad
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015 By AFsoft All Rights Reserved.