JWWファイルの超簡易表示用コンポーネント for Delphi 2007(zipファイル)

[Delphi 2007]
今までの超簡易表示シリーズ?をコンポーネントにしたものがあったので、アップしておきますね。素人が試行錯誤の結果をまとめているものなので、(おられないとは思いますが)CAD処理の基本をこのソースで学ばないで下さい(笑)CAD作成に興味がある方は、AFSoftさんの「CAD作ろ!」をぜひご覧下さい。


AFSoft
http://afsoft.jp/index.html
左側のCADをクリックすると右側に「CAD作ろ!」のリンクが表示されます。




JWWファイルの超簡易表示用コンポーネント for Delphi 2007
「TJwwPanel.zip」をダウンロード

※JwwPanel.pasとJwwDraw.pasの2つのユニットからなります。 ※今回は、ソースが長いのでZIPファイルとしました。


このコンポーネントには、下記のユニットが必要になりますので、事前に用意して下さい。

[1] jww data read & save unit Ver1.40β

Peter's Room
http://be-sp.com/petrm/index.html
softwareのページからダウンロードできます。


[2] Delphi zlib

base2 technologies
http://www.base2ti.com/
現在のバージョンは、1.2.5です。



1.JWWファイルに同梱された画像は、「年月日-時分秒」フォルダ内に解凍します。
2.レイヤーは、レイヤ名を表示するのみです。
3.ブロックツリーも同様に名前を表示するのみで表示を切り替えません。
4.いろいろな部分がとにかく適当です。(^-^)



デザイン時(JWWPanelは、動的に作成します)

Design_2


テスト用コード
 

uses JwwPanel;

procedure TForm1.FormCreate(Sender: TObject);
var
  FileName: String;
begin
  JwwPanel1 := TJwwPanel.Create(Self);
  JwwPanel1.Parent := Self;
  JwwPanel1.Align := alClient;

  FileName := 'c:\jww\Aマンション平面例.jww';
  if FileExists(FileName) then
  begin
    JwwPanel1.FileName := FileName;
    JwwPanel1.BlockListTreeView := TreeView1;
    JwwPanel1.LayerTreeView := TreeView2;
    JwwPanel1.Active := True;
  end;
end;


実行時

Runtime_2



いくつかのファイルを試してみると、ファイルによっては、JwwUnitで、「ファイルの末尾以降を読み込みました」というエラーが表示されました。 私の場合、次のようにすることで読み込めたのですが、JWWファイルが壊れている可能性もあり、実際のところはよくわからないです。とりあえず参考までに載せておきますね。
 
1201-1215行
if JWWHd.JW_DATA_VERSION >= 700 then
begin
    // hiderin
    // Img: Integerとして宣言済み
    BlockRead(F,wd,2);
    if wd > 0 then
    begin
      Img := wd;
      BlockRead(F,wd,2);
      jwwRead_BundleImage(Img);
    end; 
    //次の2行がオリジナルです。
    // BlockRead(F,dw,4);
    // jwwRead_BundleImage(dw);
end;

|

☆JWWファイルの超簡易表示 その5

ブロックデータの回転処理を含めてみました。(倍率処理に関しては線のみ)
まだまだ怪しい部分は多いのですが、一応表示できているようです。 コードは、「JWWファイルの超簡易表示 その4」からの 変更部分のみ載せますね。

Blocktree

Unit1名前空間での訂正内容です。
// 初期設定
procedure TForm1.FormCreate(Sender: TObject);
var
  FileName: String;
  WindowStyles: Integer;
begin
  // TreeViewにCheckBoxを表示させます。
  WindowStyles := GetWindowLong(TreeView1.Handle, GWL_STYLE);
  SetWindowLong(TreeView1.Handle, GWL_STYLE, WindowStyles or TVS_CHECKBOXES);

  JWWBlockList := TJWWBlockList.Create;

  FileName := 'test.jww';
  JwwDataLoadFromFile(FileName);
  SetLayerName(TreeView1);
  MakeBlockTree(TreeView2);   // ブロックツリーの作成  
  JWWDataDraw(PaintBox1);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BlockTreeClear;
  JWWBlockList.Free;
end;

procedure TForm1.BlockTreeClear;
var
  Node: TTreeNode;
begin
  Node := TreeView2.Items.GetFirstNode;
  while Node <> nil do
  begin
    if Assigned(Node.Data) then
      TBlockNodeData(Node.Data).Free;
    Node := Node.GetNext;
  end;
end;


jwwDraw名前空間の追加・変更内容です。
type
  TBlockNodeData = class(TObject)
  private
    x1  : Double;
    y1  : Double;
    kaku: Double;
    bx  : Double;
    by  : Double;
    ID  : Integer;
  public
    constructor Create(AID: Integer; ACDataBlock: CDataBlock);
  end;

implementation

uses
  Commctrl, ShlObj;

const
  TVIS_CHECKED  = $2000;
constructor TBlockNodeData.Create(AID: Integer; ACDataBlock: CDataBlock);
begin
  ID   := AID;
  x1   := ACDataBlock.m_DPKijunTen_x;
  y1   := ACDataBlock.m_DPKijunTen_y;
  kaku := ACDataBlock.m_radKaitenKaku;
  bx   := ACDataBlock.m_dBairitsuX;
  by   := ACDataBlock.m_dBairitsuY;
end;

var
  TV: TTreeView;

// ブロックデータの取得
function GetData(var ID: Integer; var x1, y1, kaku, bx, by: Double): Boolean;
var
  ANode: TTreeNode;
begin
  Result := False;
  x1 := 0;
  y1 := 0;
  kaku := 0;
  bx := 0;
  by := 0;

  // 指定IDを持つノードの検索
  ANode := TV.Items.GetFirstNode;
  repeat
    if Assigned(ANode.Data) and (TBlockNodeData(ANode.Data).ID = ID) then Break;
    ANode := ANode.GetNext;
  until ANode = nil;

  // 見つからなかった場合には終了させます。
  if ANode = nil then
  begin
    ID := -1; // 見つからなかった場合
    Exit;
  end;

  // 指定ノードのブロックデータ取得
  if Assigned(ANode.Data) then
  begin
    x1   := TBlockNodeData(ANode.Data).x1;
    y1   := TBlockNodeData(ANode.Data).y1;
    kaku := TBlockNodeData(ANode.Data).kaku;
    bx   := TBlockNodeData(ANode.Data).bx;
    by   := TBlockNodeData(ANode.Data).by;
  end;

  // 指定ノードの親ノードのID取得
  ANode := ANode.Parent;
  if Assigned(ANode.Data) then
    ID := TBlockNodeData(ANode.Data).ID
  else
    ID := -1; // 見つからなかった場合
  Result := True;
end;


// MakeBlockTree
procedure MakeBlockTree(TreeView: TTreeView);
var
  Node: TTreeNode;
  S: String;

  function GetLable(S: String): String;
  var
    I: Integer;
  begin
    I := AnsiPos('@@',S);
    Result := Copy(S,1,I-1);
  end;

  procedure GetNode(CDB: CDataBlock);
  var
    I,J: Integer;
    S :String;
  begin
    I := CDB.m_n_Number;
    S := GetLable(JWWBlockList.BlockList[I].m_strName);
    Node := TV.Items.AddChildObject(Node, S, TBlockNodeData.Create(I, CDB));
    for J := JWWBlockList.BlockList[I].Count -1 downto 0  do
    begin
      if JWWBlockList.DataType[I,J] = Block then
        GetNode(JWWBlockList.DataBlock[I,J]);
    end;
    Node := Node.Parent;
  end;

var
  I: Integer;
begin
  TV := TreeView;
  TV.Items.BeginUpdate;
  try
    TV.Items.Clear;
    Node := TV.Items.Add(nil,'BlockTree');
    for I:= Low(JWWBlock) to High(JWWBlock) do
    begin
      S := '';
      Node := TV.Items.GetFirstNode;
      GetNode(JWWBlock[I]);
    end;
    // 名前で並べ替えさせます。
    TV.SortType := stText;
    TV.SortType := stNone;
    TV.FullExpand;
  finally
    TV.Items.EndUpdate;
  end;
end;


ブロック図形の描画部分です。 前回のものと入れ替えて下さい。
  // ブロック図形の描画

  // 回転移動
  procedure Revo(x1, y1, xc, yc, a: Double; var x2, y2: Double);
  begin
    x2 := xc + (x1-xc)*Cos(a) - (y1-yc)*Sin(a);
    y2 := yc + (x1-xc)*Sin(a) + (y1-yc)*Cos(a);
  end;

  // 線の変形
  procedure SenModified(ID: Integer; var Sen: CDataSen);
  var
    x1, y1, kaku, bx, by, x2, y2: Double;
  begin
    while True do
    begin
      if not GetData(ID, x1, y1, kaku, bx, by) then Exit;
      Sen.m_start_x := (Sen.m_start_x * bx)+x1;
      Sen.m_start_y := (Sen.m_start_y * by)+y1;
      Sen.m_end_x   := (Sen.m_end_x   * bx)+x1;
      Sen.m_end_y   := (Sen.m_end_y   * by)+y1;
      if Kaku <> 0 then
      begin
        Revo(Sen.m_start_x, Sen.m_start_y, x1, y1, Kaku, x2, y2);
        Sen.m_start_x := x2;
        Sen.m_start_y := y2;
        Revo(Sen.m_end_x, Sen.m_end_y, x1, y1, Kaku, x2, y2);
        Sen.m_end_x := x2;
        Sen.m_end_y := y2;
      end;
      if ID < 0 then Exit;
    end;
  end;

  // 円弧の変形
  procedure EnkoModified(ID: Integer; var Enko: CDataEnko);
  var
    x1, y1, kaku, bx, by, x2, y2: Double;
  begin
    while True do
    begin
      if not GetData(ID, x1, y1, kaku, bx, by) then Exit;
      Enko.m_start_x := (Enko.m_start_x * bx)+x1;
      Enko.m_start_y := (Enko.m_start_y * by)+y1;
      if Kaku <> 0 then
      begin
        Revo(Enko.m_start_x, Enko.m_start_y, x1, y1, Kaku, x2, y2);
        Enko.m_start_x := x2;
        Enko.m_start_y := y2;
        Enko.m_radKatamukiKaku := Enko.m_radKatamukiKaku + kaku;
      end;
      if ID < 0 then Break;
    end;
  end;

  // 文字の変形
  procedure MojiModified(ID: Integer; var Moji: CDataMoji);
  var
    x1, y1, kaku, bx, by, x2, y2: Double;
  begin
    while True do
    begin
      if not GetData(ID, x1, y1, kaku, bx, by) then Exit;
      Moji.m_start_x := (Moji.m_start_x * bx)+x1;
      Moji.m_start_y := (Moji.m_start_y * by)+y1;
      if Kaku <> 0 then
      begin
        Revo(Moji.m_start_x, Moji.m_start_y, x1, y1, Kaku, x2, y2);
        Moji.m_start_x := x2;
        Moji.m_start_y := y2;
        Moji.m_degKakudo := Moji.m_degKakudo + RadToDeg(Kaku);
      end;
      if ID < 0 then Break;
    end;
  end;

  // ソリッド図形の変形
  procedure SolidModified(ID: Integer; var Solid: CDataSolid);
  var
    x1, y1, kaku, bx, by, x2, y2: Double;
  begin
    while True do
    begin
      if not GetData(ID, x1, y1, kaku, bx, by) then Exit;
      Solid.m_start_x := (Solid.m_start_x * bx)+x1;
      Solid.m_start_y := (Solid.m_start_y * by)+y1;
      Solid.m_end_x   := (Solid.m_end_x * bx)+x1;
      Solid.m_end_y   := (Solid.m_end_y * by)+y1;
      Solid.m_DPoint2_x:= (Solid.m_DPoint2_x * bx)+x1;
      Solid.m_DPoint2_y:= (Solid.m_DPoint2_y * by)+y1;
      Solid.m_DPoint3_x:= (Solid.m_DPoint3_x * bx)+x1;
      Solid.m_DPoint3_y:= (Solid.m_DPoint3_y * by)+y1;

      if Kaku <> 0 then
      begin
        Revo(Solid.m_start_x, Solid.m_start_y, x1, y1, Kaku, x2, y2);
        Solid.m_start_x := x2;
        Solid.m_start_y := y2;
        Revo(Solid.m_end_x, Solid.m_end_y, x1, y1, Kaku, x2, y2);
        Solid.m_end_x := x2;
        Solid.m_end_y := y2;
        Revo(Solid.m_DPoint2_x, Solid.m_DPoint2_y, x1, y1, Kaku, x2, y2);
        Solid.m_DPoint2_x := x2;
        Solid.m_DPoint2_y := y2;
        Revo(Solid.m_DPoint3_x, Solid.m_DPoint3_y, x1, y1, Kaku, x2, y2);
        Solid.m_DPoint3_x := x2;
        Solid.m_DPoint3_y := y2;
      end;
      if ID < 0 then Break;
    end;
  end;

  procedure DrawBlock(CDB: CDataBlock);
  var
    I,J: Integer;
    Sen1: CDataSen;
    Enko1: CDataEnko;
    Moji1: CDataMoji;
    Solid1: CDataSolid;
  begin
    I :=  CDB.m_n_Number;

    for J := JWWBlockList.BlockList[I].Count-1  downto 0 do
    begin
      case JWWBlockList.DataType[I,J] of
        Sen: begin
              Sen1 := JWWBlockList.DataSen[I,J];
              SenModified(I, Sen1);
              DrawSen(Sen1);
            end;
        Enko: begin
                Enko1 := JWWBlockList.DataEnko[I,J];
                EnkoModified(I, Enko1);
                DrawEnko(Enko1);
             end;
        //Ten:
        Moji: begin
                Moji1 := JWWBlockList.DataMoji[I,J];
                MojiModified(I, Moji1);
                DrawMoji(Moji1);
             end;
        Solid: begin
                Solid1 := JWWBlockList.DataSolid[I,J];
                SolidModified(I, Solid1);
                DrawSolid(Solid1);
             end;
       Block: begin
                DrawBlock(JWWBlockList.DataBlock[I,J]);
             end;
      end;
    end;
  end;

var
  I: Integer;
begin
  // 画面の消去
  CLS;

  // 用紙枠の描画
  Draw_Paper_Frame;

  // 線の描画
  for I := Low(JWWSen) to High(JWWSen) do
    DrawSen(JWWSen[I]);

  // 円弧の描画
  for I := Low(JWWEnko) to High(JWWEnko) do
    DrawEnko(JWWEnko[I]);

  // 文字の描画
  for I := Low(JWWMoji) to High(JWWMoji) do
    DrawMoji(JWWMoji[I]);

  // ソリッド図形
  for I := Low(JWWSolid) to High(JWWSolid) do
    DrawSolid(JWWSolid[I]);

  // ブロックデータの描画
  for I:= Low(JWWBlock) to High(JWWBlock) do
    DrawBlock(JWWBlock[I]);
end;

|

☆JWWファイルの超簡易表示 その4

ここ数日は、ブロックデータに挑戦していましたが、ブロックデータクラスや回転、 倍率処理・・・どれもややこし過ぎです。ブロックデータクラスの内容がいまいち理解 できていないので、基本的なところで間違っている可能性もありますが、 とりあえず回転、倍率処理を見送り、なんとか表示できるようになりました(^^; そこで前回のソリッド描画と斜め楕円の描画も追加してコードをまとめてみました。

※斜め楕円の描画は、旧FDelphi 16番会議室「玉石混淆みんなで作るSample蔵」 斜め楕円の描画(裏目小僧さん、凛さん)を使わせて頂きました。

Jww4

※ELVがブロック図形となっています。
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, Clipbrd, jwwunit, jwwDraw;

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Panel1: TPanel;
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Commctrl, ShlObj;

// 初期設定
procedure TForm1.FormCreate(Sender: TObject);
var
  FileName: String;
  WindowStyles: Integer;
begin
  // TreeViewにCheckBoxを表示させます。
  WindowStyles := GetWindowLong(TreeView1.Handle, GWL_STYLE);
  SetWindowLong(TreeView1.Handle, GWL_STYLE, WindowStyles or TVS_CHECKBOXES);

  JWWBlockList := TJWWBlockList.Create;

  FileName := 'c:\jww\Aマンション平面例.jww';
  JwwDataLoadFromFile(FileName);
  SetLayerName(TreeView1);
  JWWDataDraw(PaintBox1);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  JWWBlockList.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  JWWDataDraw(PaintBox1);
end;

procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
  if ((MousePos.X > 0) and (MousePos.X < PaintBox1.Width)) and
     ((MousePos.Y > 0) and (MousePos.Y < PaintBox1.Height)) then
  begin
    Handled := True; // TreeView1とPaintBox1を独立してスクロール処理させるために必要
    ZoomUp(PaintBox1.Canvas);
  end;
end;

procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
  if ((MousePos.x > PaintBox1.Left) and (MousePos.x < PaintBox1.Left + PaintBox1.Width)) and
     ((MousePos.y > PaintBox1.Top)  and (MousePos.y < PaintBox1.Top  + PaintBox1.Height))
   then
  begin
    Handled := True; // TreeView1とPaintBox1を独立してスクロール処理させるために必要
    ZoomDown(PaintBox1.Canvas);
  end;
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if not CanDraw then Exit;

  if (ssLeft in Shift) or (ssRight in Shift) then
  begin
    DraggingNow    := True;
    RubberBandShow := False;

    DragStartPoint := Point(X,Y);
    DragEndPoint   := Point(0,0);

    if (ssLeft  in Shift) then DragEndPoint.X := 1;
    if (ssRight in Shift) then DragEndPoint.Y := 1;
  end;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if DraggingNow then
  begin
    if RubberBandShow then
      RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);

    if (ssLeft in Shift) and (ssRight in Shift) then
    begin
      DragEndPoint := Point(X,Y);
      RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);
      RubberBandShow := True;
    end
    else
    begin
      RubberBandShow := False;
      if (ssLeft  in Shift) then DragEndPoint.X := 1;
      if (ssRight in Shift) then DragEndPoint.Y := 1;
    end;
  end
end;

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

  function GetDragModeKind: Integer;
  begin
    if (Abs(DragStartPoint.X - X) <= 5) and (Abs(DragStartPoint.Y - Y) <= 5) then
      Result := 0    // 移動
    else
    begin
      if (DragStartPoint.X <= X) then
        Result := 1  // 拡大
      else
        Result := 2; // 縮小
    end;
  end;

var
  x1, y1, x2, y2: Double;
  cx, cy: Double;
  dx, dy: Double;
  bx, by: Double;
  P1, P2: Double;
begin
  if (not RubberBandShow) and ((DragEndPoint.X = 0) or (DragEndPoint.Y = 0)) then
  begin
    DraggingNow := False;
    Exit;
  end;

  if DraggingNow then
  begin
    DraggingNow := False;

    if RubberBandShow then
      RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);

    DragModeKind := GetDragModeKind;

    x1 := ViewArea.Left   + (DragStartPoint.X / mm_dot);   // ドラッグ開始位置の左上X座標
    y1 := ViewArea.Bottom - (DragStartPoint.Y / mm_dot);   // ドラッグ開始位置の左下Y座標
    x2 := ViewArea.Left   + (X / mm_dot);                  // ドラッグ終了位置の左上X座標
    y2 := ViewArea.Bottom - (Y / mm_dot);                  // ドラッグ終了位置の左下Y座標
    dx := Abs(ViewArea.Right  - ViewArea.Left);            // ビューの幅
    dy := Abs(ViewArea.Bottom - ViewArea.Top );            // ビューの高さ
    bx := Abs(x1 - x2);                                    // 長方形の大きさ X
    by := Abs(y1 - y2);                                    // 長方形の大きさ Y
    cx := (x1 + x2) / 2.0;                                 // 長方形の中央の座標 X
    cy := (y1 + y2) / 2.0;                                 // 長方形の中央の座標 Y

    case (DragModeKind) of
      0: begin
           // 移動
           cx := (ViewArea.Left + ViewArea.Right ) / 2.0;  // 現在のビューの中心座標 X
           cy := (ViewArea.Top  + ViewArea.Bottom) / 2.0;  // 現在のビューの中心座標 Y
           dx := x2 - cx;                                  // 移動量
           dy := y2 - cy;                                  // 移動量
           ViewArea.Left   := ViewArea.Left   + dx;        // 移動計算
           ViewArea.Top    := ViewArea.Top    + dy;        // 移動計算
           ViewArea.Right  := ViewArea.Right  + dx;        // 移動計算
           ViewArea.Bottom := ViewArea.Bottom + dy;        // 移動計算
         end;
      1: begin
           // 拡大
           if (bx < 0.000001) then bx:=0.000001;
           if (by < 0.000001) then by:=0.000001;

           P1 := dx / bx;
           P2 := dy / by;

           if (P1 < P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           ViewArea.Left   := cx - ((ImageSize.Width  / 2.0) / mm_dot);
           ViewArea.Top    := cy - ((ImageSize.Height / 2.0) / mm_dot);
           ViewArea.Right  := cx + ((ImageSize.Width  / 2.0) / mm_dot);
           ViewArea.Bottom := cy + ((ImageSize.Height / 2.0) / mm_dot);
         end;
      2: begin
           // 縮小
           P1 := bx / dx;
           P2 := by / dy;

           if (P1 > P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           ViewArea.Left   := cx - ((ImageSize.Width  / 2.0) / mm_dot);
           ViewArea.Top    := cy - ((ImageSize.Height / 2.0) / mm_dot);
           ViewArea.Right  := cx + ((ImageSize.Width  / 2.0) / mm_dot);
           ViewArea.Bottom := cy + ((ImageSize.Height / 2.0) / mm_dot);
         end;
    end;
    DrawData(PaintBox1.Canvas);
  end
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  DrawData(PaintBox1.Canvas);
end;

// TreeViewのチェックボックス処理
procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  HitTest: TTVHitTestInfo;
  Node: TTreeNode;
  I, J, K: Integer;
begin
  // クリックした位置のノードを取得します。
  Node := TreeView1.GetNodeAt(X, Y);
  if Node = nil then Exit;

  HitTest.pt.x := X;
  HitTest.pt.y := Y;
  TreeView_HitTest(TreeView1.Handle, HitTest);

  if (HitTest.flags = TVHT_ONITEMSTATEICON) then
  begin
    if TreeView_GetCheckState(TreeView1.Handle, Node.ItemId) > 0 then
      K := 1
    else
      K := 0;

    if Node.Level = 0 then
    begin
      I := Node.AbsoluteIndex mod 16;
      JWWHd.GLay[I].m_anGLay := K;
    end
    else
    begin
      I := Node.Parent.AbsoluteIndex mod 16;
      J := Node.Index;
      JWWHd.GLay[I].m_nLay[J].m_aanLay := K;
    end;
    PaintBox1.Invalidate;
  end;
end;

end.
描画のユニットです。
unit jwwDraw;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, jwwunit, Math;

type
  TPointEx = packed record
    X: Double;
    Y: Double;
  end; 

  TRectEx = packed record
    case Integer of
      0: (Left, Top, Right, Bottom: Double);
      1: (TopLeft, BottomRight: TPointEx);
  end;  

  TSize = packed record
    Height: Integer;
    Width: Integer;
  end;

  TSizeEx = packed record
    Height: Double;
    Width: Double;
  end;

var
  OriginPoint: TPoint;                         // 原点
  ImageSize: TSize;                            // 画面ドットサイズ
  PaperSize: TSizeEx;                          // 用紙サイズ
  mm_dot: Double;                              // mm_dot比
  ViewArea: TRectEx;                           // ビューエリア
  DragStartPoint: TPoint;                      // ドラッグ開始点
  DragEndPoint: TPoint;                        // ドラッグ終了点
  DragModeKind : Integer;                      // ドラッグモード 0:移動 1:拡大 2:縮小
  DraggingNow : Boolean;                       // ドラッグ中かどうかのフラグ
  RubberBandShow : Boolean;                    // ラバーバンド表示フラグ
  CanDraw: Boolean;                            // 描画可能かどうかのフラグ
  function PointEx(X, Y: Double): TPointEx;    // PointEx型を作成します。
  procedure JWWDataDraw(APaintBox: TPaintBox);
  procedure DrawData(ACanvas: TCanvas);        // 図面の描画
  procedure SetPaperSize(Size: Integer);       // 用紙サイズの設定
  procedure ZoomUp(ACanvas: TCanvas);          // 拡大
  procedure ZoomDown(ACanvas: TCanvas);        // 縮小
  procedure RubberBand(ACanvas: TCanvas; P1, P2: TPoint); // ラバーバンドの描画
  procedure SetLayerName(ATreeView: TTreeView);    // レイヤー名及び表示/非表示の設定
  procedure JwwDataLoadFromFile(FileName: String);
  
implementation

uses
  Commctrl, ShlObj;

const
  TVIS_CHECKED  = $2000;

procedure JwwDataLoadFromFile(FileName: String);
begin
  DraggingNow := False;
  RubberBandShow := False;
  jwwRead(FileName);
  SetPaperSize(JWWHd.m_nZumen);
  CanDraw := True;
  mm_dot := 0;
end;

function PointEx(X, Y: Double): TPointEx;
begin
  Result.X := X;
  Result.Y := Y;
end;

// ラバーバンド長方形描画
procedure RubberBand(ACanvas: TCanvas; P1, P2: TPoint);
begin
  ACanvas.Pen.Mode := pmXor;
  ACanvas.Pen.Color := clAqua;
  ACanvas.Pen.Width := 0;
  ACanvas.Pen.Style := psSolid;
  ACanvas.Brush.Style := bsClear;
  ACanvas.Rectangle(P1.X, P1.Y, P2.X, P2.Y);
end;

// 用紙サイズの設定
procedure SetPaperSize(Size: Integer);
begin
  case Size of
    0: begin // A0
         PaperSize.Width  :=1189;
         PaperSize.Height := 841;
       end;
    1: begin // A1
         PaperSize.Width  := 841;
         PaperSize.Height := 594;
       end;
    2: begin // A2
         PaperSize.Width  := 594;
         PaperSize.Height := 420;
       end;
    3: begin // A3
         PaperSize.Width  := 420;
         PaperSize.Height := 297;
       end;
    4: begin // A4
         PaperSize.Width  := 297;
         PaperSize.Height := 210;
       end;
  else
    PaperSize.Width  :=1189;
    PaperSize.Height := 841;
  end;
end;

// JWWデータを描画します。
procedure JWWDataDraw(APaintBox: TPaintBox);

  procedure Calc_mm_dot;
  var
    P1, P2: Double;
  begin
    ImageSize.Width  := APaintBox.Width;
    ImageSize.Height := APaintBox.Height;
    P1 := ImageSize.Width  / PaperSize.Width;
    P2 := ImageSize.Height / PaperSize.Height;

    if mm_dot = 0 then
    begin
      if (P1 < P2) then
        mm_dot := P1
      else
        mm_dot := P2;
    end;
  end;

  procedure Calc_ViewArea;
  begin
    ViewArea.Left   := - (ImageSize.Width  / 2.0) / mm_dot;
    ViewArea.Top    := - (ImageSize.Height / 2.0) / mm_dot;
    ViewArea.Right  :=   (ImageSize.Width  / 2.0) / mm_dot;
    ViewArea.Bottom :=   (ImageSize.Height / 2.0) / mm_dot;
  end;

begin
  if not CanDraw then Exit;
  Calc_mm_dot;
  Calc_ViewArea;
  APaintBox.Invalidate;
end;

// CADデータの描画
procedure DrawData(ACanvas: TCanvas);

  // 画面の消去
  procedure CLS;
  begin
    ACanvas.Pen.Mode  := pmCopy;
    ACanvas.Pen.Color := clWhite;
    ACanvas.Pen.Style := psSolid;
    ACanvas.Pen.Width := 1;

    ACanvas.Brush.Color := clWhite;
    ACanvas.Brush.Style := bsSolid;
    ACanvas.Rectangle(0, 0, ImageSize.Width, ImageSize.Height);
  end;

  // 用紙枠の描画
  procedure Draw_Paper_Frame;
  var
    ARect: TRect;
  begin
    // 原点の計算
    OriginPoint.X := Round( (0.0 - ViewArea.Left  ) * mm_dot);
    OriginPoint.Y := Round(-(0.0 - ViewArea.Bottom) * mm_dot);

    // 用紙枠の描画
    ARect.Left   := Round( (-PaperSize.Width / 2 - ViewArea.Left  ) * mm_dot);
    ARect.Top    := Round(-(-PaperSize.Height/ 2 - ViewArea.Bottom) * mm_dot);
    ARect.Right  := Round( ( PaperSize.Width / 2 - ViewArea.Left  ) * mm_dot);
    ARect.Bottom := Round(-( PaperSize.Height/ 2 - ViewArea.Bottom) * mm_dot);
    ACanvas.Pen.Color := clBlue;
    ACanvas.Brush.Style := bsClear;
    ACanvas.Rectangle(ARect);
  end;

  // 座標を変換
  procedure Change_mm_dot_Point(PEx: TPointEx; var P: TPoint);
  begin
    P.x := Round( PEx.x * mm_dot + OriginPoint.X );
    P.y := Round(-PEx.y * mm_dot + OriginPoint.Y );
  end;

  // 線及び円弧の線種・線色の設定
  procedure LineSetting(Root: CData);
  begin
    ACanvas.Pen.Width := 0;
    case Root.m_nPenStyle of
      1: ACanvas.Pen.Style := psSolid;
      2,3,4,9: ACanvas.Pen.Style := psDot;
      5,6,7,8: ACanvas.Pen.Style := psDashDot;
    end;
    case Root.m_nPenColor of
      1: ACanvas.Pen.Color := RGB(0,192,192);
      2: ACanvas.Pen.Color := clBlack;
      3: ACanvas.Pen.Color := RGB(0,192,0);
      4: ACanvas.Pen.Color := RGB(192,192,0);
      5: ACanvas.Pen.Color := RGB(192,0,192);
      6: ACanvas.Pen.Color := RGB(0,0,255);
      7: ACanvas.Pen.Color := RGB(0,128,128);
      8: ACanvas.Pen.Color := RGB(255,0,128);
      9: ACanvas.Pen.Color := RGB(255,128,255);
    end;
  end;

  // フォントの設定
  function FontSetting(ACDataMoji: CDataMoji): Boolean;
  var
    I: Integer;
  begin
    Result := True;
    ACanvas.Font.Name := ACDataMoji.m_strFontName;
    ACanvas.Font.Height := Round(ACDataMoji.m_dSizeY * mm_dot);
    if ACanvas.Font.Height = 0 then
    begin
      Result := False;
      Exit;
    end;
    // フォントのスタイルの設定
    I := ACDataMoji.m_nMojiShu;
    if I >= 30000 then      // ボールド + 斜体文字
    begin
      ACanvas.Font.Style := [fsBold,fsItalic];
      I := I - 30000
    end
    else if I >= 20000 then // ボールド
    begin
      ACanvas.Font.Style := [fsBold];
      I := I -20000
    end
    else if I >= 10000 then // 斜体文字
    begin
      ACanvas.Font.Style := [fsItalic];
      I := I -10000;
    end
    else
      ACanvas.Font.Style := [];

    // フォントの色の設定
    case JWWHd.m_Moji[I].m_anMojiCol of
      1: ACanvas.Font.Color := RGB(0,192,192);
      2: ACanvas.Font.Color := clBlack;
      3: ACanvas.Font.Color := RGB(0,192,0);
      4: ACanvas.Font.Color := RGB(192,192,0);
      5: ACanvas.Font.Color := RGB(192,0,192);
      6: ACanvas.Font.Color := RGB(0,0,255);
      7: ACanvas.Font.Color := RGB(0,128,128);
      8: ACanvas.Font.Color := RGB(255,0,128);
      9: ACanvas.Font.Color := RGB(255,128,255);
     10: ACanvas.Font.Color := clBlack; // 不明
    end;
  end;

  // レイヤーの表示/非表示
  function LayerCheck(Root: CData): Boolean;
  var
    I, J: Integer;
    F1, F2: Boolean;
  begin
    I := Root.m_nGLayer;
    J := Root.m_nLayer;
    F1 := JWWHd.GLay[I].m_anGLay <> 0;
    F2 := JWWHd.GLay[I].m_nLay[J].m_aanLay <> 0;
    Result := F1 and F2;
  end;

  // 補助線かどうか
  function IsSupportLine(Root: CData): Boolean;
  begin
    Result := (Root.m_nPenStyle = 9);
  end;

  // 線の描画
  procedure DrawSen(Sen: CDataSen);
  var
    P1, P2: TPoint;
  begin
    if (not IsSupportLine(Sen.Root)) and LayerCheck(Sen.Root) then
    begin
      Change_mm_dot_Point(PointEx(Sen.m_start_x, Sen.m_start_y), P1);
      Change_mm_dot_Point(PointEx(Sen.m_end_x  , Sen.m_end_y  ), P2); 

      LineSetting(Sen.Root);

      ACanvas.MoveTo(P1.X, P1.Y);
      ACanvas.LineTo(P2.X, P2.Y);
    end;
  end;

  { 旧FDelphi 玉石混淆みんなで作るSample蔵「斜め楕円の描画 」 }
  // 凛さん、裏目小僧さんのコード
  procedure Ellipse2(Center: TPoint; LongRadius, ShortRadius, Angle,
    angleFrom, angleTo: Extended);

    function rot(x,y: Extended; rad: Extended):TPointEx;//rad:radian
    var
      ss, cc: Extended;
    begin
      ss := sin(rad);
      cc := cos(rad);
      Result.x := cc*x-ss*y;
      Result.y := ss*x+cc*y;
    end;

    procedure drawDeclinedEllipsePP(aFrom, aTo: Extended);
    var
      I: Integer;
      bufP: array[0..3] of TPointEx;
      thePoints:array[0..3] of TPoint;
      s,c,xc,yc,fa: Extended;
    begin
      fa := aTo-aFrom;
      s := sin(fa);
      c := cos(fa);
      xc := cos(fa/2);
      yc := sin(fa/2);
      bufP[0].x := 1;
      bufP[0].y := 0;
      bufP[1].x := 1;
      bufP[1].y := -4*c*(1+c-2*xc)/s/3+4*(2*yc-s)/3;
      bufP[2].x := (-4-c+8*xc)/3;
      bufP[2].y :=  4*c*(1+c-2*xc)/s/3+s;
      bufP[3].x := c;
      bufP[3].y := s;

      for I:= 0 to 3 do
      begin
        bufP[I]:=rot(BufP[I].x,bufP[I].y,aFrom);
        bufP[I]:=rot(LongRadius*BufP[I].x,shortRadius*BufP[I].y,angle);
        thePoints[I].x:=round(bufP[I].x + Center.X);
        thePoints[I].y:=round(bufP[I].y + Center.Y);
      end;
      PolyBezier(ACanvas.Handle, thePoints, 4);
    end;

  const
    Err=0.001;
  var
    sep, I: Integer;
    division: Extended;
  begin
    division := PI/3;
    sep := Trunc((AngleTo-AngleFrom)/division);
    for I := 0 to sep-1 do
      drawDeclinedEllipsePP(angleFrom+ I*division, angleFrom+(I+1)*division);
    if (AngleTo-AngleFrom)-(sep*division) > Err then
      drawDeclinedEllipsePP(angleFrom+sep*division, angleTo);
  end;

  // 円弧の描画
  procedure DrawEnko(Enko: CDataEnko; IsSolid: Boolean=False);
  var
    Center: TPointEx;
    x1, y1, Hankei: Double;
    LongRadius, ShortRadius: Double;
    Hajime, Owari, Inclination: Double;
    PEx1, PEx2: TPointEx;
    P1, P2, P3,P4: TPoint;
  begin
    Hajime := Enko.m_radKaishiKaku + Enko.m_radKatamukiKaku;
    Owari :=  Enko.m_radKaishiKaku + Enko.m_radEnkoKaku +
              Enko.m_radKatamukiKaku;

    if (not IsSupportLine(Enko.Root)) and LayerCheck(Enko.Root) then
    begin
      x1 := Enko.m_start_x;
      y1 := Enko.m_start_y;
      Center.X := X1;
      Center.Y := Y1;
      Hankei := Enko.m_dHankei;

      if Enko.m_radKatamukiKaku < 0 then
      begin
        PEx1.X := X1-Hankei * Enko.m_dHenpeiRitsu;
        PEx1.Y := Y1-Hankei;
        PEx2.X := X1+Hankei * Enko.m_dHenpeiRitsu;
        PEx2.Y := Y1+Hankei;
      end
      else
      begin
        PEx1.X := X1-Hankei;
        PEx1.Y := Y1-Hankei*Enko.m_dHenpeiRitsu;
        PEx2.X := X1+Hankei;
        PEx2.Y := Y1+Hankei*Enko.m_dHenpeiRitsu;
      end;

      // 円弧の設定
      LineSetting(Enko.Root);

      // mm→dot変換
      Change_mm_dot_Point(PEx1, P1);
      Change_mm_dot_Point(PEx2, P2);

      // ソリッドかどうか
      if IsSolid then
        ACanvas.Brush.Style := bsSolid
      else
        ACanvas.Brush.Style := bsClear;

      // 円弧の描画
      if Enko.m_bZenEnFlg = 1 then // 円・楕円の場合
      begin
        begin
          if Enko.m_radKatamukiKaku = 0 then
          begin
            // 斜め描画しない
            // 円(楕円)・全円(全楕円)ソリッド
            ACanvas.Ellipse(P1.X,P1.Y,P2.X,P2.Y);
          end
          else
          begin
            // 斜め描画する
            Change_mm_dot_Point(Center, P3);
            if Enko.m_radKatamukiKaku < 0 then
              Inclination := (PI /2) - Enko.m_radKatamukiKaku
            else
              Inclination := - Enko.m_radKatamukiKaku;

            LongRadius := (P2.X-P1.X) div 2;
            ShortRadius := (P2.Y-P1.Y) div 2;
            Hajime := DegToRad(0);
            Owari  := DegToRad(360);
            Ellipse2(P3, LongRadius, ShortRadius, Inclination, Hajime, Owari);
          end;
        end;
      end
      else
      begin
        // 楕円弧の場合
        if Enko.m_dHenpeiRitsu <> 1.0 then
        begin
          Change_mm_dot_Point(Center, P3);
          if Enko.m_radKatamukiKaku < 0 then
            Inclination := (PI /2) - Enko.m_radKatamukiKaku
          else
            Inclination := -Enko.m_radKatamukiKaku;

          LongRadius  := (P2.X-P1.X) div 2;
          ShortRadius := (P2.Y-P1.Y) div 2;

          Hajime := (Inclination+Enko.m_radKatamukiKaku+Enko.m_radKaishiKaku);
          Owari  := (Inclination+Enko.m_radKatamukiKaku+Enko.m_radKaishiKaku +
            Enko.m_radEnkoKaku);

          Ellipse2(P3, LongRadius, ShortRadius, Inclination, Hajime, Owari);
        end
        else
        begin
          // 円弧
          P3.X := Round( ((x1+Hankei*Cos(Hajime)))*MM_dot+OriginPoint.X);
          P3.Y := Round(-((y1+Hankei*Sin(Hajime)))*MM_dot+OriginPoint.Y);
          P4.X := Round( ((x1+Hankei*Cos(Owari )))*MM_dot+OriginPoint.X);
          P4.Y := Round(-((y1+Hankei*Sin(Owari )))*MM_dot+OriginPoint.Y);

          if (P3.X <> P4.X) or (P3.Y <> P4.Y) then
          begin
            if (Enko.m_radEnkoKaku < 0) then
              SetArcDirection(ACanvas.Handle, AD_CLOCKWISE)          // 時計回り
            else
              SetArcDirection(ACanvas.Handle, AD_COUNTERCLOCKWISE);  // 反時計回り

            if Enko.m_bZenEnFlg = 0 then
              ACanvas.Arc(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y)   // 円弧
            else if Enko.m_bZenEnFlg = 2 then
              ACanvas.Chord(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y) // 弓形ソリッド
            else if Enko.m_bZenEnFlg = 3 then
              ACanvas.Pie(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y);  // 扇形ソリッド
          end;
        end;
      end;
    end;
  end;

  // ソリッド図形の描画
  procedure DrawSolid(Solid: CDataSolid);
  var
    poly: array[0..3] of TPoint;
    Enko: CDataEnko;
  begin
    if LayerCheck(Solid.Root) then
    begin
      if Solid.Root.m_nPenStyle > 100 then
      begin
        if Solid.Root.m_nPenStyle = 101 then
        begin
          //円のソリッド
          Enko.Root := Solid.Root;
          Enko.m_start_x := Solid.m_start_x;
          Enko.m_start_y := Solid.m_start_y;
          Enko.m_dHankei := Solid.m_end_x;
          Enko.m_radKaishiKaku := Solid.m_DPoint2_y;
          Enko.m_radEnkoKaku := Solid.m_DPoint3_x;
          Enko.m_radKatamukiKaku := Solid.m_DPoint2_x;
          Enko.m_dHenpeiRitsu := Solid.m_end_y;
          ACanvas.Pen.Color := Solid.m_Color;
          ACanvas.Brush.Color := ACanvas.Pen.Color;
          if Solid.m_DPoint3_y = 100 then
            Enko.m_bZenEnFlg := 1   // 全円ソリッド
          else if Solid.m_DPoint3_y = 5 then
            Enko.m_bZenEnFlg := 2   // 弓形ソリッド ※2は適当
          else if Solid.m_DPoint3_y = 0 then
            Enko.m_bZenEnFlg := 3   // 扇形ソリッド ※3は適当
          else if Solid.m_DPoint3_y = -1 then
            Enko.m_bZenEnFlg := 4   // 外側円弧ソリッド・・・どんな処理?
          else
            Enko.m_bZenEnFlg := 10; // 処理しない  ※10は適当
          if Enko.m_bZenEnFlg < 10 then
            DrawEnko(Enko, True);
        end
        else if Solid.Root.m_nPenStyle = 101 then
        begin
          //円環ソリッド・・・どんな処理?
        end
        else if Solid.Root.m_nPenStyle = 111 then
        begin
          //円周ソリッド・・・どんな処理?
        end;
      end
      else
      begin
        /// 線のソリッド
        // mm→dot変換
        Change_mm_dot_Point(PointEx(Solid.m_start_x  , Solid.m_start_y  ), Poly[0]);
        Change_mm_dot_Point(PointEx(Solid.m_end_x    , Solid.m_end_y    ), Poly[1]);
        Change_mm_dot_Point(PointEx(Solid.m_DPoint2_x, Solid.m_DPoint2_y), Poly[2]);
        Change_mm_dot_Point(PointEx(Solid.m_DPoint3_x, Solid.m_DPoint3_y), Poly[3]);
        ACanvas.Pen.Color := Solid.m_Color;
        ACanvas.Brush.Color := ACanvas.Pen.Color;
        ACanvas.Polygon(poly);
      end;
    end;
  end;

  // 文字の描画
  procedure DrawMoji(Moji: CDataMoji);
  var
    S: String;
    LF: TLogFont;
    P1, P2: TPoint;
  begin
    if LayerCheck(Moji.Root) then
    begin
      S := Moji.m_string;

      // mm→dot変換
      Change_mm_dot_Point(PointEx(Moji.m_start_x, Moji.m_start_y), P1);
      Change_mm_dot_Point(PointEx(Moji.m_end_x  , Moji.m_end_y  ), P2);

      // フォントの設定
      if FontSetting(Moji) then
      begin
        // 文字の描画
        GetObject(ACanvas.Font.Handle, SizeOf(LF), @LF);
        SetTextAlign(ACanvas.Handle,TA_LEFT or TA_BOTTOM);
        LF.lfEscapement := Round(Moji.m_degKakudo*10);
        ACanvas.Font.Handle := CreateFontIndirect(LF);
        ACanvas.TextOut(P1.X, P1.Y, S);
      end;
    end;
  end;

  // ブロック図形の描画---回転や倍率は未対応です。
  // いまいち理解できていないので、間違った処理かも??
  var
    x1, y1: Double;

  procedure DrawBlock(CDB: CDataBlock);
  var
    I,J: Integer;
    Sen1: CDataSen;
    Enko1: CDataEnko;
    Moji1: CDataMoji;
    Solid1: CDataSolid;
  begin
    I := CDB.m_n_Number;
    x1 := CDB.m_DPKijunTen_x+x1;
    y1 := CDB.m_DPKijunTen_y+y1;

    for J := JWWBlockList.BlockList[I].Count-1  downto 0 do
    begin
      case JWWBlockList.DataType[I,J] of
        Sen: begin
               Sen1 := JWWBlockList.DataSen[I,J];
               Sen1.m_start_x := Sen1.m_start_x+x1;
               Sen1.m_start_y := Sen1.m_start_y+y1;
               Sen1.m_end_x   := Sen1.m_end_x  +x1;
               Sen1.m_end_y   := Sen1.m_end_y  +y1;
               DrawSen(Sen1);
             end;
        Enko: begin
               Enko1 := JWWBlockList.DataEnko[I,J];
               Enko1.m_start_x := Enko1.m_start_x+x1;
               Enko1.m_start_y := Enko1.m_start_y+y1;
               DrawEnko(Enko1);
             end;
        Moji: begin
               Moji1 := JWWBlockList.DataMoji[I,J];
               Moji1.m_start_x := Moji1.m_start_x+x1;
               Moji1.m_start_y := Moji1.m_start_y+y1;
               DrawMoji(Moji1);
             end;
        Solid: begin
               Solid1 := JWWBlockList.DataSolid[I,J];
               Solid1.m_start_x := Solid1.m_start_x+x1;
               Solid1.m_start_y := Solid1.m_start_y+y1;
               Solid1.m_end_x := Solid1.m_end_x+x1;
               Solid1.m_end_y := Solid1.m_end_y+y1;
               Solid1.m_DPoint2_x := Solid1.m_DPoint2_x+x1;
               Solid1.m_DPoint2_y := Solid1.m_DPoint2_y+y1;
               Solid1.m_DPoint3_x := Solid1.m_DPoint3_x+x1;
               Solid1.m_DPoint3_y := Solid1.m_DPoint3_y+y1;
               DrawSolid(Solid1);
             end;
        Block: begin
                DrawBlock(JWWBlockList.DataBlock[I,J]);
             end;
      end;
    end;
  end;

var
  I: Integer;
begin
  // 画面の消去
  CLS;

  // 用紙枠の描画
  Draw_Paper_Frame;

  // 線の描画
  for I := Low(JWWSen) to High(JWWSen) do
    DrawSen(JWWSen[I]);

  // 円弧の描画
  for I := Low(JWWEnko) to High(JWWEnko) do
    DrawEnko(JWWEnko[I]);

  // 文字の描画
  for I := Low(JWWMoji) to High(JWWMoji) do
    DrawMoji(JWWMoji[I]);

  // ソリッド図形
  for I := Low(JWWSolid) to High(JWWSolid) do
    DrawSolid(JWWSolid[I]);

  // ブロックデータの描画
   for I:= Low(JWWBlock) to High(JWWBlock) do
   begin
     x1:= 0; y1 := 0;
     DrawBlock(JWWBlock[I]);
   end;
end;

// ビュー中央の座標、ビューの幅、高さを取得
procedure GetViewInfo(var View_CenterPoint: TPointEx;
  var View_Width, View_Height: Double);
begin
  View_CenterPoint.X := (ViewArea.Left + ViewArea.Right) / 2.0;
  View_CenterPoint.Y := (ViewArea.Top + ViewArea.Bottom) / 2.0;
  View_Width    := Abs(ViewArea.Right - ViewArea.Left);
  View_Height   := Abs(ViewArea.Bottom - ViewArea.Top);
end;

// 用紙枠の描画サイズ
procedure GetPaperFrameDrawSize(var ARect: TRect;
  AView_x1, AView_y1, Amm_dot: Double);
begin
  ARect.Left   := Round( (-PaperSize.Width /2.0 - AView_x1) * Amm_dot);
  ARect.Bottom := Round(-(-PaperSize.Height/2.0 - AView_y1) * Amm_dot);
  ARect.Right  := Round( ( PaperSize.Width /2.0 - AView_x1) * Amm_dot);
  ARect.Top    := Round(-( PaperSize.Height/2.0 - AView_y1) * Amm_dot);
end; 

// 拡大
procedure ZoomUp(ACanvas: TCanvas);
var
  View_Width, View_Height: Double;
  View_CenterPoint: TPointEx;

  // 一定以上大きくさせない。
  function LargeCheck: Boolean;
  const
    Max = 80000;
  var
    Check_mm_dot, Check_view_x1, Check_view_y1: Double;
    ARect: TRect;
  begin
    Result := False;

    //2倍に拡大
    Check_mm_dot := mm_dot * 2.0;
    Check_view_x1 := View_CenterPoint.x - (View_Width  / 4.0);
    Check_view_y1 := View_CenterPoint.y + (View_Height / 4.0);

    // 用紙枠の描画サイズ
    GetPaperFrameDrawSize(ARect,Check_view_x1,Check_view_y1,Check_mm_dot);
       
    if (ARect.Right-ARect.Left > Max) or (ARect.Bottom- ARect.Top >Max) then Exit;
    Result := True;
  end;

begin
  // ビュー中央の座標、ビューの幅、高さを取得
  GetViewInfo(View_CenterPoint, View_Width, View_Height);

  // 一定以上拡大させない。
  if not LargeCheck then  Exit;

  //2倍に拡大
  mm_dot := mm_dot * 2.0;

  ViewArea.Left   := View_CenterPoint.X - (View_Width /4.0);
  ViewArea.Top    := View_CenterPoint.Y - (View_Height/4.0);
  ViewArea.Right  := View_CenterPoint.X + (View_Width /4.0);
  ViewArea.Bottom := View_CenterPoint.Y + (View_Height/4.0);

  DrawData(ACanvas);
end;

// 縮小
procedure ZoomDown(ACanvas: TCanvas);
var
  View_Width, View_Height: Double;
  View_CenterPoint: TPointEx;  

  // 一定以上縮小させない。
  function SmallCheck: Boolean;
  const
    Min = 10;
  var
    Check_mm_dot, Check_view_x1, Check_view_y1: Double;
    ARect: TRect;
  begin
    Result := False;
    // 1/2倍に縮小
    Check_mm_dot := mm_dot * 0.5;
    Check_view_x1 := View_CenterPoint.X - View_Width;
    Check_view_y1 := View_CenterPoint.Y + View_Height;

    // 用紙枠の描画サイズ
    GetPaperFrameDrawSize(ARect,Check_view_x1,Check_view_y1,Check_mm_dot);
    if (ARect.Right-ARect.Left < Min) or (ARect.Bottom-ARect.Top <Min) then Exit;
    Result := True;
  end;

begin
  // ビュー中央の座標、ビューの幅、高さを取得
  GetViewInfo(View_CenterPoint, View_Width, View_Height);

  // 一定以上縮小させない。
  if not SmallCheck then  Exit;
  
  // 1/2倍に縮小
  mm_dot := mm_dot * 0.5;
  ViewArea.Left   := View_CenterPoint.X - View_Width;
  ViewArea.Top    := View_CenterPoint.Y - View_Height;
  ViewArea.Right  := View_CenterPoint.X + View_Width;
  ViewArea.Bottom := View_CenterPoint.Y + View_Height;

  DrawData(ACanvas);
end;

// レイヤー名及び表示/非表示の設定
procedure SetLayerName(ATreeView: TTreeView);

  // ノードのチェックボックス設定
  procedure NodeCheckBox(Node: TTreeNode; F: Boolean);
  var
    TvItem: TTVItem;
  begin
    TvItem.hItem := Node.ItemId;
    TvItem.stateMask := TVIS_STATEIMAGEMASK;
    TvItem.mask := TVIF_HANDLE or TVIF_STATE;
    if F then
      TvItem.state := TVIS_CHECKED
    else
      TvItem.state := TVIS_CHECKED shr 1;
    TreeView_SetItem(ATreeView.Handle, TvItem);
  end;

  // 太字設定
  procedure SetBold(Node: TTreeNode);
  var
    TvItem: TTVItem;
  begin
    TvItem.hItem := Node.ItemId;
    TvItem.stateMask := TVIS_BOLD;
    TvItem.mask := TVIF_HANDLE or TVIF_STATE;
    TvItem.state := TVIS_BOLD;
    TreeView_SetItem(ATreeView.Handle, TvItem);
  end;

var
  I, J, K, SNo, ENo: Integer;
  NodeA, NodeB: TTreeNode;
  LayerNo, Scale, LayerName: String;
  F: Boolean;
begin
  ATreeView.Items.BeginUpdate;
  try
    ATreeView.Items.Clear;
    // レイヤーグループの設定
    for I := Low(JWWHd.m_aStrGLayName) to High(JWWHd.m_aStrGLayName) do
    begin
      // レイヤーグループ番号
      LayerNo := '[' + IntToHex(I, 1) +'] ';
      // 縮尺
      if JWWHd.GLay[I].m_adScale < 1 then
        Scale := IntToStr(Round(1 / JWWHd.GLay[I].m_adScale)) + '/1'
      else
        Scale := '1/'+ IntToStr(Trunc(JWWHd.GLay[I].m_adScale));

      // レイヤーグループ名
      LayerName := ' ' + JWWHd.m_aStrGLayName[I];

      // ノードの追加及び表示/非表示の設定
      NodeA := ATreeView.Items.Add(nil, LayerNo + Scale + LayerName);
      F := JWWHd.GLay[I].m_anGLay <> 0;
      NodeCheckBox(NodeA, F);
      SetBold(NodeA);

      // レイヤーの設定
      SNo := I * 16;   // 読み取り開始番号
      ENo := SNo + 15; // 読み取り終了番号
      for J := SNo to ENo do
      begin
        K := J - SNo;
        LayerNo := '[' + IntToHex(K, 1) +'] ';       // レイヤーグループ番号
        LayerName := ' ' + JWWHd.m_aStrLayName[J];   // レイヤー名
        // ノードの追加及び表示/非表示の設定
        NodeB := ATreeView.Items.AddChild(NodeA, LayerNo + LayerName);
        F := JWWHd.GLay[I].m_nLay[K].m_aanLay <> 0;
        NodeCheckBox(NodeB, F);
      end;
    end;
  finally
    ATreeView.Items.EndUpdate;
  end;
end;

end.


Peter's Room
jww data read & save unit Ver1.31β
http://www5b.biglobe.ne.jp/~peter/

AFsoft WebSite
CAD作ろ!
http://afsoft.jp/

|

☆JWWのソリッドデータを描画してみる。

私自身、JWWを使いこなしていないため、よく分からないデータも多いのですが、 下記の処理で描画できているようです。 (申し訳ないのですが、現在、描画処理を別ユニットに分ける作業をしてて、そのユニット内のコードなので 前回のコードに組み込むには少し修正が必要です)

Solid_2


  uses jwwunit;

  // 実数を扱うTPoint
  PPointEx = ^TPointEx;
  TPointEx = packed record
    X: Double;
    Y: Double;
  end;

  // 座標を変換
  procedure Change_mm_dot_Point(PEx: TPointEx; var P: TPoint);
  begin
    P.x := Round( PEx.x * mm_dot + OriginPoint.X );
    P.y := Round(-PEx.y * mm_dot + OriginPoint.Y );
  end;

  // 円弧の描画
  procedure DrawEnko(Enko: CDataEnko; IsSolid: Boolean=False);
  var
    x1, y1, Hankei: Double;
    Hajime, Owari: Double;
    PEx1, PEx2: TPointEx;
    P1, P2, P3,P4: TPoint;
  begin
    if (not IsSupportLine(Enko.Root)) and LayerCheck(Enko.Root) then
    begin
      x1 := Enko.m_start_x;
      y1 := Enko.m_start_y;
      Hankei := Enko.m_dHankei;
      Hajime := Enko.m_radKaishiKaku + Enko.m_radKatamukiKaku;
      Owari :=  Enko.m_radKaishiKaku + Enko.m_radEnkoKaku +
        Enko.m_radKatamukiKaku;
      if Enko.m_radKatamukiKaku < 0 then
      begin
        PEx1.X := X1-Hankei*Enko.m_dHenpeiRitsu;
        PEx1.Y := Y1-Hankei;
        PEx2.X := X1+Hankei*Enko.m_dHenpeiRitsu;
        PEx2.Y := Y1+Hankei;
      end
      else
      begin
        PEx1.X := X1-Hankei;
        PEx1.Y := Y1-Hankei*Enko.m_dHenpeiRitsu;
        PEx2.X := X1+Hankei;
        PEx2.Y := Y1+Hankei*Enko.m_dHenpeiRitsu;
      end;

      // 円弧の設定
      LineSetting(Enko.Root);

      // mm→dot変換
      Change_mm_dot_Point(PEx1, P1);
      Change_mm_dot_Point(PEx2, P2);

      // ソリッドかどうか
      if IsSolid then
        ACanvas.Brush.Style := bsSolid
      else
        ACanvas.Brush.Style := bsClear;

      // 円弧の描画
      if Enko.m_bZenEnFlg = 1 then
      begin
        // 円・全円ソリッド
        ACanvas.Ellipse(P1.X,P1.Y,P2.X,P2.Y);
      end
      else
      begin
        // 円弧
        P3.X := Round( ((x1+Hankei*Cos(Hajime)))*MM_dot+OriginPoint.X);
        P3.Y := Round(-((y1+Hankei*Sin(Hajime)))*MM_dot+OriginPoint.Y);
        P4.X := Round( ((x1+Hankei*Cos(Owari )))*MM_dot+OriginPoint.X);
        P4.Y := Round(-((y1+Hankei*Sin(Owari )))*MM_dot+OriginPoint.Y);

        if (P3.X <> P4.X) or (P3.Y <> P4.Y) then
        begin
          if Enko.m_bZenEnFlg = 0 then
          begin
            // 円弧
            if (Enko.m_radEnkoKaku < 0) then
              ACanvas.Arc(P1.X,P1.Y,P2.X,P2.Y,P4.X,P4.Y,P3.X,P3.Y)
            else
              ACanvas.Arc(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y);
          end
          else if Enko.m_bZenEnFlg = 2 then
          begin
            // 弓形ソリッド
            if (Enko.m_radEnkoKaku < 0) then
              ACanvas.Chord(P1.X,P1.Y,P2.X,P2.Y,P4.X,P4.Y,P3.X,P3.Y)
            else
              ACanvas.Chord(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y);
          end
          else if Enko.m_bZenEnFlg = 3 then
          begin
            // 扇形ソリッド
            if (Enko.m_radEnkoKaku < 0) then
              ACanvas.Pie(P1.X,P1.Y,P2.X,P2.Y,P4.X,P4.Y,P3.X,P3.Y)
            else
              ACanvas.Pie(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y);
          end;
        end;
      end;
    end;
  end;


  // ソリッド図形の描画
  procedure DrawSolid(Solid: CDataSolid);
  var
    poly: array[0..3] of TPoint;
    Enko: CDataEnko;
  begin
    if LayerCheck(Solid.Root) then
    begin
      if Solid.Root.m_nPenStyle > 100 then
      begin
        if Solid.Root.m_nPenStyle = 101 then
        begin
          //円のソリッド
          Enko.Root := Solid.Root;
          Enko.m_start_x := Solid.m_start_x;
          Enko.m_start_y := Solid.m_start_y;
          Enko.m_dHankei := Solid.m_end_x;
          Enko.m_radKaishiKaku := Solid.m_DPoint2_y;
          Enko.m_radEnkoKaku := Solid.m_DPoint3_x;
          Enko.m_radKatamukiKaku := Solid.m_DPoint2_x;
          Enko.m_dHenpeiRitsu := Solid.m_end_y;
          ACanvas.Pen.Color := Solid.m_Color;
          ACanvas.Brush.Color := ACanvas.Pen.Color;
          if Solid.m_DPoint3_y = 100 then
            Enko.m_bZenEnFlg := 1   // 全円ソリッド
          else if Solid.m_DPoint3_y = 5 then
            Enko.m_bZenEnFlg := 2   // 弓形ソリッド ※2は適当
          else if Solid.m_DPoint3_y = 0 then
            Enko.m_bZenEnFlg := 3   // 扇形ソリッド ※3は適当
          else if Solid.m_DPoint3_y = -1 then
            Enko.m_bZenEnFlg := 4   // 外側円弧ソリッド・・・どんな処理?
          else
            Enko.m_bZenEnFlg := 10; // 処理しない  ※10は適当
          if Enko.m_bZenEnFlg < 10 then
            DrawEnko(Enko, True);
        end
        else if Solid.Root.m_nPenStyle = 101 then
        begin
          // 円環ソリッド・・・どんな処理?
        end
        else if Solid.Root.m_nPenStyle = 111 then
        begin
          // 円周ソリッド・・・どんな処理?
        end;
      end
      else
      begin
        // ソリッド
        // mm→dot変換
        Change_mm_dot_Point(PointEx(Solid.m_start_x  , Solid.m_start_y  ), Poly[0]);
        Change_mm_dot_Point(PointEx(Solid.m_end_x    , Solid.m_end_y    ), Poly[1]);
        Change_mm_dot_Point(PointEx(Solid.m_DPoint2_x, Solid.m_DPoint2_y), Poly[2]);
        Change_mm_dot_Point(PointEx(Solid.m_DPoint3_x, Solid.m_DPoint3_y), Poly[3]);
        ACanvas.Pen.Color := Solid.m_Color;
        ACanvas.Brush.Color := ACanvas.Pen.Color;
        ACanvas.Polygon(poly);
      end;
    end;
  end;


  // ソリッド図形
  for I := Low(JWWSolid) to High(JWWSolid) do
    DrawSolid(JWWSolid[I]);

|

☆JWWのクリップボードを読み込んでみる。

HiroCom777さんのVBdeJW !!で公開されているJwwClipControlを参考にして、 JWWのクリップボードのデータを読み込んでみました。

基本的な構造としては、起点の座標+グループ毎の縮尺+各データに なっているようです。

まず、クリップボードからTStreamにデータを取り出します。
uses Clipbrd;

procedure TForm1.Button1Click(Sender: TObject);
var
  Data: THandle;
  DataPtr: Pointer;
  MemStream: TMemoryStream;
  I: Integer;
  FormatID: Integer;
  FormatName: array [0..MAX_PATH] of Char;
  ID: word;
  F: Boolean;
begin
  F := False;
  ID := 0;
  for I := 0 to ClipBoard.FormatCount - 1 do
  begin
    FormatID:= ClipBoard.Formats[I];
    GetClipBoardFormatName(FormatID, FormatName, SizeOf(FormatName));
    if FormatName = 'Jw_win' then
    begin
      F := True;
      ID := FormatID;
      Break;
    end;
  end;

  if not F then Exit;

  ClipBoard.Open;
  Data := ClipBoard.GetAsHandle(ID);
  if Data = 0 then Exit;

  DataPtr := GlobalLock(Data);
  if DataPtr = nil then Exit;

  MemStream := TMemoryStream.Create;
  try
    MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
    MemStream.Position := 0;
    JwwPasteFromClipboard(TStream(MemStream));
    Drawdata;
  finally
    MemStream.Free;
    GlobalUnLock(Data);
    ClipBoard.Close;
  end;
end;

次にTStreamから各データを取得します。この部分については、jwwunitのjwwRead関数を 参考にしています。というかそのままに近いので今回は、線データのみ取得させています。
// クリップボードのデータを取得する。
procedure JwwPasteFromClipboard(Stream: TStream);
var
  I,J,K: Integer;
  dw: DWORD;
  db: Double;
  S: String;
  wd: Word;
  bt: Byte;
  JWWList: TJWWList;
  SenCount: Integer;
  DSen: CDataSen;
  orgX,orgY: Double;
  scale: array[0..15] of Double;
  Size,Cnt: Integer;
  Dummy: array[0..150] of Byte;

  function StringRead(n:Integer): String;
  var
    I: Integer;
    cc: char;
  begin
    Result := '';
    for I:=0 to n-1 do
    begin
      Stream.ReadBuffer(cc,1);
      Result := Result + cc;
    end;
  end;  

begin
  Stream.Position := 0;
  Size := Stream.Size;

  Cnt := High(JWWSen);

  // 基準点
  Stream.ReadBuffer(orgX,SizeOf(Double));
  Stream.ReadBuffer(orgY,SizeOf(Double)); 

  // レイヤグループの縮尺
  for I := 0 to 15 do
    Stream.ReadBuffer(scale[I],SizeOf(Double));

  JWWList := TJWWList.Create;
  try
    Stream.ReadBuffer(wd,SizeOf(wd));
    if wd = $FFFF then
    begin
      Stream.ReadBuffer(dw,SizeOf(dw));
      J := dw;
    end else
      J := wd;

    SetLength(JWWSen,Cnt+J);
    SenCount := Cnt;
    I := 1;

    while Stream.Position <= Size do
    begin
      Stream.ReadBuffer(wd,2);
      case wd of
        $0000: Break;
        $FFFF: begin
                 Stream.ReadBuffer(wd,2);
                 Stream.ReadBuffer(wd,2);
                 S := StringRead(wd);
                 JWWList.AddItem(I,S);
                 J := I;
                 Inc(I);
               end;
        $FF7F: begin
                 Stream.ReadBuffer(dw,4);
                 J := dw and $7FFFFFFF;
               end;
        $7FFF: begin
                 Stream.ReadBuffer(dw,4);
                 J := dw and $7FFFFFFF;
               end;
        else begin
               if (wd and $8000) <> 0 then
                 J := wd and $7FFF else J := 0;
             end;
      end;
      S := JWWList.NoByItem[J].CDataString;
      if S = 'CDataList' then
      begin
        Stream.ReadBuffer(Dummy,28);
        Stream.ReadBuffer(bt,1);
        if bt <> $FF then
          StringRead(bt)
        else
        begin
          Stream.ReadBuffer(wd,2);
          StringRead(wd)
        end;

        Stream.ReadBuffer(wd,2);
        if wd = $FFFF then
          Stream.ReadBuffer(dw,4);
      end;
      if S = 'CDataSen' then
      begin
        Stream.ReadBuffer(dw,4);
        DSen.Root.m_lGroup:=dw;
        Stream.ReadBuffer(bt,1);
        DSen.Root.m_nPenStyle:=bt;
        Stream.ReadBuffer(wd,2);
        DSen.Root.m_nPenColor:=wd;
        Stream.ReadBuffer(wd,2);
        DSen.Root.m_nPenWidth:=wd;
        Stream.ReadBuffer(wd,2);
        DSen.Root.m_nLayer:=wd;
        Stream.ReadBuffer(wd,2);
        DSen.Root.m_nGLayer:=wd;
        Stream.ReadBuffer(wd,2);
        DSen.Root.m_sFlg:=wd;
        Stream.ReadBuffer(db,8);
        DSen.m_start_x := db;
        Stream.ReadBuffer(db,8);
        DSen.m_start_y := db;
        Stream.ReadBuffer(db,8);
        DSen.m_end_x := db;
        Stream.ReadBuffer(db,8);
        DSen.m_end_y := db;
        JWWSen[SenCount] := DSen;
        Inc(SenCount);
      end;
      if S = 'CDataEnko' then
      begin
        Stream.ReadBuffer(Dummy,75);
      end;
      if S = 'CDataTen' then
      begin
        Stream.ReadBuffer(dw,4);
        Stream.ReadBuffer(bt,1);
        Stream.ReadBuffer(Dummy,30);
        if bt = 100 then
          Stream.ReadBuffer(Dummy,20);
      end;
      if S = 'CDataMoji' then
      begin
        Stream.ReadBuffer(Dummy,83);
        Stream.ReadBuffer(bt,1);
        if bt <> $FF then
          StringRead(bt)
        else
        begin
          Stream.ReadBuffer(wd,2);
          StringRead(wd);
        end;
        Stream.ReadBuffer(bt,1);
        if bt <> $FF then
          StringRead(bt)
        else
        begin
          Stream.ReadBuffer(wd,2);
          StringRead(wd);
        end;
      end;
      if S = 'CDataSolid' then
      begin
        Stream.ReadBuffer(dw,4);
        Stream.ReadBuffer(bt,1);
        Stream.ReadBuffer(wd,2);
        Stream.ReadBuffer(Dummy,72);
        if wd = 10 then
          Stream.ReadBuffer(Dummy,4);
      end;
      if S = 'CDataBlock' then
      begin
        Stream.ReadBuffer(Dummy,59);
      end;
      if S = 'CDataSunpou' then
      begin
        Stream.ReadBuffer(Dummy,145);

        Stream.ReadBuffer(bt,1);
        if bt <> $FF then
          Stream.ReadBuffer(Dummy,1)
        else
          Stream.ReadBuffer(Dummy,2);

        Stream.ReadBuffer(bt,1);
        if bt <> $FF then
          Stream.ReadBuffer(Dummy,1)
        else
          Stream.ReadBuffer(Dummy,2);

        Stream.ReadBuffer(wd,2);
        Stream.ReadBuffer(Dummy,94);
        for K := 0 to 3 do
        begin
          Stream.ReadBuffer(dw,4);
          Stream.ReadBuffer(bt,1);
          Stream.ReadBuffer(Dummy,30);
          if bt = 100 then
            Stream.ReadBuffer(Dummy,20);
        end;
      end;
      if S <> '' then Inc(I);
      S:='';
    end;
    SetLength(JWWSen,SenCount);
  finally
    JWWList.Free;
  end;
end;

上記のコードをJWWファイルの超簡易表示 その3で 試して頂くとデータが追加されているのがわかります。ただ、貼り付ける位置の座標やレイヤは元データのままなので、実際に使う場合には その辺りを処理する必要があります。

今回は、メモリ上で処理していますが、クリップボードからTFileStreamでファイルに書き出して、 そこから読み込むというのもいいかも知れませんね。


VBdeJW !!
http://www.h7.dion.ne.jp/~hirocom/VBdeJW/


Peter's Room
jww data read & save unit Ver1.3β
http://www5b.biglobe.ne.jp/~peter/index.html


AFsoft WebSite
CAD作ろ!
http://afsoft.jp/

|

☆JWWファイルの超簡易表示 その3

前回、前々回のTreeViewのチェックボックスとボールド表示を使ってレイヤーの表示/非表示部分を作ってみました。 例によってPeter.さんのjww data read & save unit Ver1.2βとAFsoftさんの「CAD作ろ」のコードを使わせてもらっています。

Jww


unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    TreeView1: TTreeView;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    ox, oy: Integer;                   // 原点
    ImageWidth,ImageHeight: Integer;   // 画面ドットサイズ = PaintBox1のサイズ
    PaperWidth, PaperHeight: Double;   // 用紙サイズ
    mm_dot: Double;                    // mm_dot比
    view_x1, view_y1, view_x2, view_y2: Double;  //ビューエリア
    DragStart_X, DragStart_Y: Integer; // ドラッグ開始点
    DragEnd_X, DragEnd_Y: Integer;     // ドラッグ終了点
    DragModeKind : Integer;            // ドラッグモード 0:移動 1:拡大 2:縮小
    DraggingNow : Boolean;             // ドラッグ中かどうかのフラグ
    RubberBandShow : Boolean;          // ラバーバンド表示フラグ
    procedure Calc_mm_dot;             // mm_dot比の計算
    procedure Calc_ViewArea;           // ビューエリアの計算
    procedure CLS;                     // 画面を消す
    procedure Draw_Paper_Frame;        // 用紙枠の描画
    procedure Drawdata;                // 図面の描画
    procedure RubberBand(x1, y1, x2, y2:Integer); // ラバーバンドの描画
    procedure SetPaperSize(PaperSize: Integer);   // 用紙サイズの設定
    procedure SetLayerName;                       // レイヤー名の設定
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Commctrl, jwwunit;

const
  TVIS_CHECKED  = $2000;

// 初期設定
procedure TForm1.FormCreate(Sender: TObject);
var
  FileName: String;
  WindowStyles: Integer;
begin
  // TreeViewにCheckBoxを表示させます。
  WindowStyles := GetWindowLong(TreeView1.Handle, GWL_STYLE);
  SetWindowLong(TreeView1.Handle, GWL_STYLE, WindowStyles or TVS_CHECKBOXES);

  // 初期化
  DraggingNow := False;
  RubberBandShow := False;

  // ファイルの読み込み
  FileName := 'c:\jww\Aマンション平面例.jww';

  JWWBlockList := TJWWBlockList.Create;

  // JWWファイル読込み
  jwwRead(FileName);

  // 用紙サイズの設定
  SetPaperSize(JWWHd.m_nZumen);

  // mm_dot比の計算
  Calc_mm_dot;

  // ビューエリアの計算
  Calc_ViewArea;

  // レイヤー名及び表示/非表示の設定
  SetLayerName;
end;

// 終了処理
procedure TForm1.FormDestroy(Sender: TObject);
begin
  JWWBlockList.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  // mm_dot比の計算
  Calc_mm_dot;

  // ビューエリアの計算
  Calc_ViewArea;
end;

// 用紙サイズの設定
{
  Paramater 用紙サイズ 
  0-A0
  1-A1
  2-A2
  3-A3
  4-A4
  上記以外は、A0サイズとする。サイズを調べるのが面倒だから(^^;
}
procedure TForm1.SetPaperSize(PaperSize: Integer); // 用紙サイズの設定
begin
  case PaperSize of
    0: begin //A0
         PaperWidth  :=1189;
         PaperHeight := 841;
       end;
    1: begin //A1
         PaperWidth  := 841;
         PaperHeight := 594;
       end;
    2: begin //A2
         PaperWidth  := 594;
         PaperHeight := 420;
       end;
    3: begin //A3
         PaperWidth  := 420;
         PaperHeight := 297;
       end;
    4: begin //A4
         PaperWidth  := 297;
         PaperHeight := 210;
       end;
  else
    PaperWidth  :=1189;
    PaperHeight := 841;
  end;
end;

// mm_dot比の計算
procedure TForm1.Calc_mm_dot;
var
  P1, P2: Double;
begin
  ImageWidth  := PaintBox1.Width;
  ImageHeight := PaintBox1.Height;
  P1 := ImageWidth  / PaperWidth;
  P2 := ImageHeight / PaperHeight;

  if (P1 < P2) then
    mm_dot := P1
  else
    mm_dot := P2;
end;

// ビューエリアの計算
procedure TForm1.Calc_ViewArea;
begin
  view_x1 := - (ImageWidth  / 2.0) / mm_dot;
  view_y1 := - (ImageHeight / 2.0) / mm_dot;
  view_x2 :=   (ImageWidth  / 2.0) / mm_dot;
  view_y2 :=   (ImageHeight / 2.0) / mm_dot;
end;

//画面の消去
procedure TForm1.CLS;
begin
  PaintBox1.Canvas.Pen.Mode  := pmCopy;
  PaintBox1.Canvas.Pen.Color := clWhite;
  PaintBox1.Canvas.Pen.Style := psSolid;
  PaintBox1.Canvas.Pen.Width := 1;

  PaintBox1.Canvas.Brush.Color := clWhite;
  PaintBox1.Canvas.Brush.Style := bsSolid;
  PaintBox1.Canvas.Rectangle(0, 0, ImageWidth, ImageHeight);
end;

//用紙枠の描画
procedure TForm1.Draw_Paper_Frame;
var
  x1, y1, x2, y2: Integer;
begin
  // 原点の計算
  ox := Round( (0.0 - view_x1) * mm_dot);
  oy := Round(-(0.0 - view_y2) * mm_dot);
  
  // 画面の消去
  CLS;

  // 用紙枠の描画
  x1 := Round( (-PaperWidth /2 - view_x1) * mm_dot);
  y1 := Round(-(-PaperHeight/2 - view_y2) * mm_dot);
  x2 := Round( ( PaperWidth /2 - view_x1) * mm_dot);
  y2 := Round(-( PaperHeight/2 - view_y2) * mm_dot);
  PaintBox1.Canvas.Pen.Color := clBlue;
  PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Rectangle(x1, y1, x2, y2);
end;

procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  cx, cy: Double;
  dx, dy: Double;
var
  Pt: TPoint;
begin
  GetCursorPos(Pt);
  Pt := ScreenToClient(Pt);
  if ((Pt.X > 0) and (Pt.X < PaintBox1.Width)) and
     ((Pt.Y > 0) and (Pt.Y < PaintBox1.Height)) then
  begin
    Handled := True;

    //2倍に拡大
    cx := (view_x1 + view_x2) / 2.0;  // ビュー中央のX座標
    cy := (view_y1 + view_y2) / 2.0;  // ビュー中央のY座標
    dx := Abs(view_x2 - view_x1);
    dy := Abs(view_y2 - view_y1);
    mm_dot := mm_dot * 2.0;
    view_x1 := cx - (dx / 4.0);
    view_y1 := cy - (dy / 4.0);
    view_x2 := cx + (dx / 4.0);
    view_y2 := cy + (dy / 4.0);
    Drawdata;
  end;
end;

procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  cx, cy: Double;
  dx, dy: Double;
var
  Pt: TPoint;
begin
  GetCursorPos(Pt);
  Pt := ScreenToClient(Pt);
  if ((Pt.X > 0) and (Pt.X < PaintBox1.Width)) and
     ((Pt.Y > 0) and (Pt.Y < PaintBox1.Height)) then
  begin
    Handled := True;

    // 1/2倍に縮小
    cx := (view_x1 + view_x2) / 2.0;  // ビュー中央のX座標
    cy := (view_y1 + view_y2) / 2.0;  // ビュー中央のY座標
    dx := Abs(view_x2 - view_x1);
    dy := Abs(view_y2 - view_y1);
    mm_dot := mm_dot * 0.5;
    view_x1 := cx - dx;
    view_y1 := cy - dy;
    view_x2 := cx + dx;
    view_y2 := cy + dy;
    Drawdata;
  end;
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if (ssLeft in Shift) or (ssRight in Shift) then
  begin
    DraggingNow := True;
    DragStart_X := X;
    DragStart_Y := Y;
    RubberBandShow := False;
    DragEnd_X := 0;
    DragEnd_Y := 0;

    if (ssLeft  in Shift) then
      DragEnd_X := 1;

    if (ssRight in Shift) then
      DragEnd_Y := 1;
  end;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if (DraggingNow) then
  begin
    if (RubberBandShow) then
      RubberBand(DragStart_X, DragStart_Y, DragEnd_X, DragEnd_Y);

    if (ssLeft in Shift) and (ssRight in Shift) then
    begin
      RubberBand(DragStart_X, DragStart_Y, X, Y);
      RubberBandShow := True;
      DragEnd_X := X;
      DragEnd_Y := Y;
    end;
  end;
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  x1, y1, x2, y2: Double;
  cx, cy: Double;
  dx, dy: Double;
  bx, by: Double;
  P1, P2: Double;
begin
  if (DraggingNow) then
  begin
    // ドラッグ処理の終了
    DraggingNow := False;
    if (RubberBandShow) then
      RubberBand(DragStart_X, DragStart_Y, DragEnd_X, DragEnd_Y);

    if (Abs(DragStart_X - X) <= 5) and (Abs(DragStart_Y - Y) <= 5) then
       DragModeKind := 0     // 移動
    else
    begin
      if (DragStart_X <= X) then
        DragModeKind := 1  // 拡大
      else
        DragModeKind := 2; // 縮小
    end;

    x1 := view_x1 + (DragStart_X / mm_dot);
    y1 := view_y2 - (DragStart_Y / mm_dot);
    x2 := view_x1 + (X / mm_dot);
    y2 := view_y2 - (Y / mm_dot);
    dx := Abs(view_x2 - view_x1);
    dy := Abs(view_y2 - view_y1);
    bx := Abs(x1 - x2);
    by := Abs(y1 - y2);
    cx := (x1 + x2) / 2.0;
    cy := (y1 + y2) / 2.0;

    case (DragModeKind) of
      0: begin    // 移動
           cx := (view_x1 +view_x2) / 2.0;
           cy := (view_y1 +view_y2) / 2.0;
           dx := x2 - cx;
           dy := y2 - cy;
           view_x1 := view_x1 + dx;
           view_y1 := view_y1 + dy;
           view_x2 := view_x2 + dx;
           view_y2 := view_y2 + dy;
         end;
      1: begin    // 拡大
           P1 := dx / bx;
           P2 := dy / by;

           if (P1 < P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           view_x1 := cx - ((ImageWidth  / 2.0) / mm_dot);
           view_y1 := cy - ((ImageHeight / 2.0) / mm_dot);
           view_x2 := cx + ((ImageWidth  / 2.0) / mm_dot);
           view_y2 := cy + ((ImageHeight / 2.0) / mm_dot);
         end;
      2: begin    // 縮小
           P1 := bx / dx;
           P2 := by / dy;

           if (P1 > P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           view_x1 := cx - ((ImageWidth  / 2.0) / mm_dot);
           view_y1 := cy - ((ImageHeight / 2.0) / mm_dot);
           view_x2 := cx + ((ImageWidth  / 2.0) / mm_dot);
           view_y2 := cy + ((ImageHeight / 2.0) / mm_dot);
         end;
    end;
    Drawdata;
  end
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  Drawdata;
end;

// ラバーバンド長方形描画
procedure TForm1.RubberBand(x1, y1, x2, y2:Integer);
begin
  PaintBox1.Canvas.Pen.Mode := pmXor;
  PaintBox1.Canvas.Pen.Color := clAqua;
  PaintBox1.Canvas.Pen.Width := 0;
  PaintBox1.Canvas.Pen.Style := psSolid;
  PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Rectangle(x1,y1,x2,y2);
end;

// CADデータの描画
procedure TForm1.Drawdata;

  // 座標を変換
  procedure Change_mm_dot(x1, x2, y1, y2: Double;
    var ix1, ix2, iy1, iy2: Integer);
  begin
    ix1 := Round( x1 * mm_dot + ox );
    iy1 := Round(-y1 * mm_dot + oy );
    ix2 := Round( x2 * mm_dot + ox );
    iy2 := Round(-y2 * mm_dot + oy );
  end;

  // 線及び円弧の線種・線色の設定
  procedure LineSetting(Root: CData);
  begin
    // ペンの太さ
    PaintBox1.Canvas.Pen.width := 0;
    // ペンのスタイル
    case Root.m_nPenStyle of
      1: PaintBox1.Canvas.Pen.Style := psSolid;
      2,3,4,9: PaintBox1.Canvas.Pen.Style := psDot;
      5,6,7,8: PaintBox1.Canvas.Pen.Style := psDashDot;
    end;
    // ペンの色
    case Root.m_nPenColor of
      1: PaintBox1.Canvas.Pen.Color := RGB(0,192,192);
      2: PaintBox1.Canvas.Pen.Color := clBlack;
      3: PaintBox1.Canvas.Pen.Color := RGB(0,192,0);
      4: PaintBox1.Canvas.Pen.Color := RGB(192,192,0);
      5: PaintBox1.Canvas.Pen.Color := RGB(192,0,192);
      6: PaintBox1.Canvas.Pen.Color := RGB(0,0,255);
      7: PaintBox1.Canvas.Pen.Color := RGB(0,128,128);
      8: PaintBox1.Canvas.Pen.Color := RGB(255,0,128);
      9: PaintBox1.Canvas.Pen.Color := RGB(255,128,255);
    end;
  end;

  // フォントの設定
  procedure FontSetting(ACDataMoji: CDataMoji);
  begin
    // フォント名
    PaintBox1.Canvas.Font.Name := ACDataMoji.m_strFontName;
    // フォントの高さ
    PaintBox1.Canvas.Font.Height := Round(ACDataMoji.m_dSizeY * mm_dot);
    // フォントの色
    case JWWHd.m_Moji[ACDataMoji.m_nMojiShu].m_anMojiCol of
      1: PaintBox1.Canvas.Font.Color := RGB(0,192,192);
      2: PaintBox1.Canvas.Font.Color := clBlack;
      3: PaintBox1.Canvas.Font.Color := RGB(0,192,0);
      4: PaintBox1.Canvas.Font.Color := RGB(192,192,0);
      5: PaintBox1.Canvas.Font.Color := RGB(192,0,192);
      6: PaintBox1.Canvas.Font.Color := RGB(0,0,255);
      7: PaintBox1.Canvas.Font.Color := RGB(0,128,128);
      8: PaintBox1.Canvas.Font.Color := RGB(255,0,128);
      9: PaintBox1.Canvas.Font.Color := RGB(255,128,255);
    end;
  end;

  // レイヤーの表示/非表示
  function LayerCheck(Root: CData): Boolean;
  var
    I, J: Integer;
    F1, F2: Boolean;
  begin
    I := Root.m_nGLayer; // レイヤーグループ
    J := Root.m_nLayer;  // レイヤー
    F1 := JWWHd.GLay[I].m_anGLay <> 0;
    F2 := JWWHd.GLay[I].m_nLay[J].m_aanLay <> 0;
    Result := F1 and F2;
  end;

  // 補助線かどうか
  function IsSupportLine(Root: CData): Boolean;
  begin
    Result := (Root.m_nPenStyle = 9);
  end;

var
  I: Integer;
  x1, x2, y1, y2, Hankei: Double;
  ix1, ix2, iy1, iy2: Integer;
  Moji: String;
  Hajime, Owari: Double;
  wx1,wy1,wx2,wy2 : Double ;
  ax3,ay3,ax4,ay4 : integer ;
  LF: TLogFont;
begin
  // 用紙枠の描画
  Draw_Paper_Frame;

  // 線の描画
  PaintBox1.Canvas.Pen.Color := clBlack;
  for I := Low(JWWSen) to High(JWWSen) do
  begin
    if (not IsSupportLine(JWWSen[I].Root)) and LayerCheck(JWWSen[I].Root) then
    begin
      x1 := JWWSen[I].m_start_x;
      y1 := JWWSen[I].m_start_y;
      x2 := JWWSen[I].m_end_x;
      y2 := JWWSen[I].m_end_y;

      // mm→dot変換
      Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

      // 線の設定
      LineSetting(JWWSen[I].Root);

      //線の描画
      PaintBox1.Canvas.MoveTo(ix1, iy1);
      PaintBox1.Canvas.LineTo(ix2, iy2);
    end;
  end;

  // 円弧の描画
  for I := Low(JWWEnko) to High(JWWEnko) do
  begin
    if (not IsSupportLine(JWWEnko[I].Root)) and LayerCheck(JWWEnko[I].Root) then
    begin
      x1 := JWWEnko[I].m_start_x;
      y1 := JWWEnko[I].m_start_y;
      Hankei := JWWEnko[I].m_dHankei;
      Hajime := JWWEnko[I].m_radKaishiKaku + JWWEnko[I].m_radKatamukiKaku;
      Owari :=  JWWEnko[I].m_radKaishiKaku + JWWEnko[I].m_radEnkoKaku +
        JWWEnko[I].m_radKatamukiKaku;
      if JWWEnko[I].m_radKatamukiKaku < 0 then
      begin
        wx1 := X1-Hankei*JWWEnko[I].m_dHenpeiRitsu;
        wy1 := Y1-Hankei;
        wx2 := X1+Hankei*JWWEnko[I].m_dHenpeiRitsu;
        wy2 := Y1+Hankei;
      end
      else
      begin
        wx1 := X1-Hankei;
        wy1 := Y1-Hankei*JWWEnko[I].m_dHenpeiRitsu;
        wx2 := X1+Hankei;
        wy2 := Y1+Hankei*JWWEnko[I].m_dHenpeiRitsu;
      end;

      // 円弧の設定
      LineSetting(JWWEnko[I].Root);

      // mm→dot変換
      Change_mm_dot(wx1, wx2, wy1, wy2, ix1, ix2, iy1, iy2);

      // 円弧の描画
      if JWWEnko[I].m_bZenEnFlg = 1 then
        PaintBox1.Canvas.Ellipse(ix1, iy1,ix2,iy2)  //円
      else
      begin
        ax3 := Round( ((x1+Hankei*Cos(Hajime)))*MM_dot+ox);
        ay3 := Round(-((y1+Hankei*Sin(Hajime)))*MM_dot+oy);
        ax4 := Round( ((x1+Hankei*Cos(Owari )))*MM_dot+ox);
        ay4 := Round(-((y1+Hankei*Sin(Owari )))*MM_dot+oy);

        if (ax3 <> ax4) or (ay3 <> ay4) then
        begin
          if (JWWEnko[I].m_radEnkoKaku < 0) then
            PaintBox1.Canvas.Arc(ix1,iy1,ix2,iy2,ax4,ay4,ax3,ay3)
          else
            PaintBox1.Canvas.Arc(ix1,iy1,ix2,iy2,ax3,ay3,ax4,ay4);
        end;
      end;
    end;
  end;

  // 文字の描画
  for I := Low(JWWMoji) to High(JWWMoji) do
  begin
    if LayerCheck(JWWMoji[I].Root) then
    begin
      x1 := JWWMoji[I].m_start_x;
      y1 := JWWMoji[I].m_start_y;
      x2 := JWWMoji[I].m_end_x;
      y2 := JWWMoji[I].m_end_y;
      Moji := JWWMoji[I].m_string;

      // mm→dot変換
      Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

      // フォントの設定
      FontSetting(JWWMoji[I]);

      // 文字の描画
      GetObject(PaintBox1.Canvas.Font.Handle, SizeOf(LF), @LF);
      SetTextAlign(PaintBox1.Canvas.Handle,TA_LEFT or TA_BOTTOM);
      LF.lfEscapement := Round(JWWMoji[I].m_degKakudo*10);
      PaintBox1.Canvas.Font.Handle := CreateFontIndirect(LF);
      PaintBox1.Canvas.TextOut(ix1,iy1,moji);
    end;
  end;
end;


// レイヤー名及び表示/非表示の設定
procedure TForm1.SetLayerName;

  // ノードのチェックボックス設定
  procedure NodeCheckBox(Node: TTreeNode; F: Boolean);
  var
    TvItem: TTVItem;
  begin
    TvItem.hItem := Node.ItemId;
    TvItem.stateMask := TVIS_STATEIMAGEMASK;
    TvItem.mask := TVIF_HANDLE or TVIF_STATE;
    TvItem.state := TVIS_CHECKED;
    TreeView_SetItem(TreeView1.Handle, TvItem);
  end;

  // 太字設定
  procedure SetBold(Node: TTreeNode);
  var
    TvItem: TTVItem;
  begin
    TvItem.hItem := Node.ItemId;
    TvItem.stateMask := TVIS_BOLD;
    TvItem.mask := TVIF_HANDLE or TVIF_STATE;
    TvItem.state := TVIS_BOLD;
    TreeView_SetItem(TreeView1.Handle, TvItem);
  end;

var
  I, J, K, SNo, ENo: Integer;
  NodeA, NodeB: TTreeNode;
  LayerNo, Scale, LayerName: String;
  F: Boolean;
begin
  TreeView1.Items.BeginUpdate;
  try
    TreeView1.Items.Clear;
    // レイヤーグループの設定
    for I := Low(JWWHd.m_aStrGLayName) to High(JWWHd.m_aStrGLayName) do
    begin
      // レイヤーグループ番号
      LayerNo := '[' + IntToHex(I, 1) +'] ';
      // 縮尺
      if JWWHd.GLay[I].m_adScale < 1 then
        Scale := IntToStr(Round(1 / JWWHd.GLay[I].m_adScale)) + '/1'
      else
        Scale := '1/'+ IntToStr(Trunc(JWWHd.GLay[I].m_adScale));

      // レイヤーグループ名
      LayerName := ' ' + JWWHd.m_aStrGLayName[I];

      // ノードの追加及び表示/非表示の設定
      NodeA := TreeView1.Items.Add(nil, LayerNo + Scale + LayerName);
      F := JWWHd.GLay[I].m_anGLay <> 0;
      NodeCheckBox(NodeA, F);
      SetBold(NodeA);

      // レイヤーの設定
      SNo := I * 16;   // 読み取り開始番号
      ENo := SNo + 15; // 読み取り終了番号
      for J := SNo to ENo do
      begin
        K := J - SNo;
        LayerNo := '[' + IntToHex(K, 1) +'] ';       // レイヤーグループ番号
        LayerName := ' ' + JWWHd.m_aStrLayName[J];   // レイヤー名
        // ノードの追加及び表示/非表示の設定
        NodeB := TreeView1.Items.AddChild(NodeA, LayerNo + LayerName);
        F := JWWHd.GLay[I].m_nLay[K].m_aanLay <> 0;
        NodeCheckBox(NodeB, F);
      end;
    end;
  finally
    TreeView1.Items.EndUpdate;
  end;
end;

procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  lpht: TTVHitTestInfo;
  Node: TTreeNode;
  I,J, K: Integer;
begin
  // クリックした位置のノードを取得します。
  Node := TreeView1.GetNodeAt(X, Y);
  if Node = nil then Exit;

  // クリックした位置がチェックボックス上からどうかを調べます。
  lpht.pt.x := X;
  lpht.pt.y := Y;
  TreeView_HitTest(TreeView1.Handle, lpht);

  if lpht.flags = TVHT_ONITEMSTATEICON then
  begin
    if TreeView_GetCheckState(TreeView1.Handle, Node.ItemId) > 0 then
      K := 1
    else
      K := 0;

    if Node.Level = 0 then
    begin
      I := Node.AbsoluteIndex mod 16;
      JWWHd.GLay[I].m_anGLay := K;
    end
    else
    begin
      I := Node.Parent.AbsoluteIndex mod 16;
      J := Node.Index;
      JWWHd.GLay[I].m_nLay[J].m_aanLay := K;
    end;
    PaintBox1.Invalidate;
  end;
end;

end.


[20071210NodeCheckBox手続きを訂正]
今、ふと見るとパラメーターFが無視されてました。下記のように訂正します。
  // ノードのチェックボックス設定
  procedure NodeCheckBox(Node: TTreeNode; F: Boolean);
  var
    TvItem: TTVItem;
  begin
    TvItem.hItem := Node.ItemId;
    TvItem.stateMask := TVIS_STATEIMAGEMASK;
    TvItem.mask := TVIF_HANDLE or TVIF_STATE;
    if F then
      TvItem.state := TVIS_CHECKED
    else
      TvItem.state := TVIS_CHECKED shr 1;
    TreeView_SetItem(TreeView1.Handle, TvItem);
  end;
あるいは、パラメーターFを削除して、レイヤーを表示する場合のみ呼び出した方がいいのかも知れませんね。 (チェックボックスを設定した時には、チェックが外れているから)

|

☆JWWファイルの超簡易表示 その2

以前、☆JWWファイルの超簡易表示 という記事で書いたコードのDrawdata手続きを更新しましたので載せておきますね。

Sample


前回は線と文字を適当に表示するだけでしたが、線、円・楕円・円弧、文字をもう少し それっぽく表示するようにしました。(レイヤー、ソリッドやSXFなどは全く考慮していませんけどね。)
procedure TForm1.Drawdata;

  // 座標を変換
  procedure Change_mm_dot(x1, x2, y1, y2: Double;
    var ix1, ix2, iy1, iy2: Integer);
  begin
    ix1 := Round( x1 * mm_dot + ox );
    iy1 := Round(-y1 * mm_dot + oy );
    ix2 := Round( x2 * mm_dot + ox );
    iy2 := Round(-y2 * mm_dot + oy );
  end;

  // 線及び円弧の線種・線色の設定
  procedure LineSetting(Root: CData);
  begin
    // ペンの太さ
    PaintBox1.Canvas.Pen.width := 0;
    // ペンのスタイル
    case Root.m_nPenStyle of
      1: PaintBox1.Canvas.Pen.Style := psSolid;
      2: PaintBox1.Canvas.Pen.Style := psDot;
      3: PaintBox1.Canvas.Pen.Style := psDot;
      4: PaintBox1.Canvas.Pen.Style := psDot;
      5: PaintBox1.Canvas.Pen.Style := psDashDot;
      6: PaintBox1.Canvas.Pen.Style := psDashDot;
      7: PaintBox1.Canvas.Pen.Style := psDashDotDot;
      8: PaintBox1.Canvas.Pen.Style := psDashDotDot;
      9: PaintBox1.Canvas.Pen.Style := psDot;
    end;
    // ペンの色
    case Root.m_nPenColor of
      1: PaintBox1.Canvas.Pen.Color := RGB(0,192,192);
      2: PaintBox1.Canvas.Pen.Color := clBlack;
      3: PaintBox1.Canvas.Pen.Color := RGB(0,192,0);
      4: PaintBox1.Canvas.Pen.Color := RGB(192,192,0);
      5: PaintBox1.Canvas.Pen.Color := RGB(192,0,192);
      6: PaintBox1.Canvas.Pen.Color := RGB(0,0,255);
      7: PaintBox1.Canvas.Pen.Color := RGB(0,128,128);
      8: PaintBox1.Canvas.Pen.Color := RGB(255,0,128);
      9: PaintBox1.Canvas.Pen.Color := RGB(255,128,255);
    end;
  end;

  // フォントの設定
  procedure FontSetting(ACDataMoji: CDataMoji);
  begin
    // フォント名
    PaintBox1.Canvas.Font.Name := ACDataMoji.m_strFontName;
    // フォントの高さ
    PaintBox1.Canvas.Font.Height := Round(ACDataMoji.m_dSizeY* mm_dot);
    // フォントの色
    case JWWHd.m_Moji[ACDataMoji.m_nMojiShu].m_anMojiCol of
      1: PaintBox1.Canvas.Font.Color := RGB(0,192,192);
      2: PaintBox1.Canvas.Font.Color := clBlack;
      3: PaintBox1.Canvas.Font.Color := RGB(0,192,0);
      4: PaintBox1.Canvas.Font.Color := RGB(192,192,0);
      5: PaintBox1.Canvas.Font.Color := RGB(192,0,192);
      6: PaintBox1.Canvas.Font.Color := RGB(0,0,255);
      7: PaintBox1.Canvas.Font.Color := RGB(0,128,128);
      8: PaintBox1.Canvas.Font.Color := RGB(255,0,128);
      9: PaintBox1.Canvas.Font.Color := RGB(255,128,255);
    end;
  end;

var
  I, ax3, ay3, ax4, ay4: Integer;
  x1, x2, y1, y2, Hankei: Double;
  ix1, ix2, iy1, iy2: Integer;
  Moji: String;
  Hajime, Owari: Double;
  wx1,wy1,wx2,wy2: Double;
  LF: TLogFont;
begin
  // 用紙枠の描画
  Draw_Paper_Frame;

  // 線の描画
  PaintBox1.Canvas.Pen.Color := clBlack;
  for I := Low(JWWSen) to High(JWWSen) do
  begin
    x1 := JWWSen[I].m_start_x;
    y1 := JWWSen[I].m_start_y;
    x2 := JWWSen[I].m_end_x;
    y2 := JWWSen[I].m_end_y;

    // mm→dot変換
    Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

    // 線の設定
    LineSetting(JWWSen[I].Root);

    //線の描画
    PaintBox1.Canvas.MoveTo(ix1, iy1);
    PaintBox1.Canvas.LineTo(ix2, iy2);
  end;

  // 円弧の描画
  for I := Low(JWWEnko) to High(JWWEnko) do
  begin
    x1 := JWWEnko[I].m_start_x;
    y1 := JWWEnko[I].m_start_y;
    Hankei := JWWEnko[I].m_dHankei;
    Hajime := JWWEnko[I].m_radKaishiKaku + JWWEnko[I].m_radKatamukiKaku;
    Owari := JWWEnko[I].m_radKaishiKaku + JWWEnko[I].m_radEnkoKaku +
      JWWEnko[I].m_radKatamukiKaku;
    if JWWEnko[I].m_radKatamukiKaku < 0 then
    begin
      wx1 := X1-Hankei*JWWEnko[I].m_dHenpeiRitsu;
      wy1 := Y1-Hankei;
      wx2 := X1+Hankei*JWWEnko[I].m_dHenpeiRitsu;
      wy2 := Y1+Hankei;
    end
    else
    begin
      wx1 := X1-Hankei;
      wy1 := Y1-Hankei*JWWEnko[I].m_dHenpeiRitsu;
      wx2 := X1+Hankei;
      wy2 := Y1+Hankei*JWWEnko[I].m_dHenpeiRitsu;
    end;

    // 円弧の設定
    LineSetting(JWWEnko[I].Root);

    // mm→dot変換
    Change_mm_dot(wx1, wx2, wy1, wy2, ix1, ix2, iy1, iy2);

    // 円弧の描画
    if JWWEnko[I].m_bZenEnFlg = 1 then
      PaintBox1.Canvas.Ellipse(ix1, iy1,ix2,iy2)  //円
    else
    begin
      ax3 := Round( ((x1+Hankei*Cos(Hajime)))*MM_dot+ox);
      ay3 := Round(-((y1+Hankei*Sin(Hajime)))*MM_dot+oy);
      ax4 := Round( ((x1+Hankei*Cos(Owari)))*MM_dot+ox);
      ay4 := Round(-((y1+Hankei*Sin(Owari)))*MM_dot+oy);

      if (ax3 <> ax4) or (ay3 <> ay4) then
      begin
        if (JWWEnko[I].m_radEnkoKaku < 0) then
          PaintBox1.Canvas.Arc(ix1,iy1,ix2,iy2,ax4,ay4,ax3,ay3)
        else
          PaintBox1.Canvas.Arc(ix1,iy1,ix2,iy2,ax3,ay3,ax4,ay4);
      end;
    end;
  end;

  // 文字の描画
  for I := Low(JWWMoji) to High(JWWMoji) do
  begin
    x1 := JWWMoji[I].m_start_x;
    y1 := JWWMoji[I].m_start_y;
    x2 := JWWMoji[I].m_end_x;
    y2 := JWWMoji[I].m_end_y;
    Moji := JWWMoji[I].m_string;

    // mm→dot変換
    Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

    // フォントの設定
    FontSetting(JWWMoji[I]);

    // 文字の描画
    GetObject(PaintBox1.Canvas.Font.Handle, SizeOf(LF), @LF);
    SetTextAlign(PaintBox1.Canvas.Handle,TA_LEFT or TA_BOTTOM);
    LF.lfEscapement := Round(JWWMoji[I].m_degKakudo*10);
    PaintBox1.Canvas.Font.Handle := CreateFontIndirect(LF);
    PaintBox1.Canvas.TextOut(ix1,iy1,moji);
  end;
end;

指定フォルダから検索文字を含むJWWファイル一覧を作成し、 そのファイル名をクリックすると、検索文字を目立つように描画させて、 VE等の内容がきちんと訂正されているかをチェックするのに使っています。

|

☆JWWファイルの超簡易表示

JWWファイルとは、言わずと知れたJW_CAD(JW_WIN)のデータファイルです。
Peter's Roomで公開されているjww data read & save unit Ver1.2βを使って、簡単に線と文字を描画するサンプルです。座標系の処理をしないと描画できないので、AFsoftさんの「CAD作ろ」!のコードを使わせて頂きました。マウスのホイールによる拡大縮小と、右左同時クリックで範囲指定して拡大ができます。
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    ox, oy: Integer;                   // 原点
    ImageWidth,ImageHeight: Integer;   // 画面ドットサイズ=Image1のサイズ
    PaperWidth, PaperHeight: Double;   // 用紙サイズ
    mm_dot: Double;                    // mm_dot比
    view_x1, view_y1, view_x2, view_y2: Double;  //ビューエリア
    DragStart_X, DragStart_Y: Integer; // ドラッグ開始点
    DragEnd_X, DragEnd_Y: Integer;     // ドラッグ終了点
    DragModeKind : Integer;            // ドラッグモード 0:移動 1:拡大 2:縮小
    DraggingNow : Boolean;             // ドラッグ中かどうかのフラグ
    RubberBandShow : Boolean;          // ラバーバンド表示フラグ
    procedure Calc_mm_dot;             // mm_dot比の計算
    procedure Calc_ViewArea;           // ビューエリアの計算
    procedure CLS;                     // 画面を消す
    procedure Draw_Paper_Frame;        // 用紙枠の描画
    procedure Drawdata;                // 図面の描画
    procedure RubberBand(x1, y1, x2, y2:Integer); // ラバーバンドの描画
    procedure SetPaperSize(PaperSize: Integer);   // 用紙サイズの設定
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses jwwunit; // jww data read & save unit Ver1.2β

procedure TForm1.FormCreate(Sender: TObject);
var
  FileName: String;
begin
  // 初期化
  DraggingNow := False;
  RubberBandShow := False;

  // ファイルの読み込み
  FileName := 'c:\jww\Aマンション平面例.jww';

  JWWBlockList := TJWWBlockList.Create;

  // JWWファイル読込み
  jwwRead(FileName);

  // 図面サイズの読み込み
  // A4~A0までしか扱えないようにする。いろいろあると面倒だから(^^;
  if not (JWWHd.m_nZumen in [0,1,2,3,4]) then
  begin
    ShowMessage('A0..A4の用紙サイズしか扱えません。');
    Exit;
  end;

  // 用紙サイズの設定
  SetPaperSize(JWWHd.m_nZumen);

  // mm_dot比の計算
  Calc_mm_dot;

  // ビューエリアの計算
  Calc_ViewArea;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  JWWBlockList.Free;
end;


procedure TForm1.FormResize(Sender: TObject);
begin
  // mm_dot比の計算
  Calc_mm_dot;

  // ビューエリアの計算
  Calc_ViewArea;
end;


// 用紙サイズの設定
{
  Paramater 用紙サイズ 
  0-A0
  1-A1
  2-A2
  3-A3
  4-A4
}
procedure TForm1.SetPaperSize(PaperSize: Integer); // 用紙サイズの設定
begin
  case PaperSize of
    0: begin //A0
         PaperWidth  :=1189;
         PaperHeight := 841;
       end;
    1: begin //A1
         PaperWidth  := 841;
         PaperHeight := 594;
       end;
    2: begin //A2
         PaperWidth  := 594;
         PaperHeight := 420;
       end;
    3: begin //A3
         PaperWidth  := 420;
         PaperHeight := 297;
       end;
    4: begin //A4
         PaperWidth  := 297;
         PaperHeight := 210;
       end;
  end;
end;


// mm_dot比の計算
procedure TForm1.Calc_mm_dot;
var
  P1, P2: Double;
begin
  ImageWidth  := PaintBox1.Width;
  ImageHeight := PaintBox1.Height;
  P1 := ImageWidth  / PaperWidth;
  P2 := ImageHeight / PaperHeight;

  if (P1 < P2) then
    mm_dot := P1
  else
    mm_dot := P2;
end;


// ビューエリアの計算
procedure TForm1.Calc_ViewArea;
begin
  view_x1 := - (ImageWidth  / 2.0) / mm_dot;
  view_y1 := - (ImageHeight / 2.0) / mm_dot;
  view_x2 :=   (ImageWidth  / 2.0) / mm_dot;
  view_y2 :=   (ImageHeight / 2.0) / mm_dot;
end;


//画面の消去
procedure TForm1.CLS;
begin
  PaintBox1.Canvas.Pen.Mode  := pmCopy;
  PaintBox1.Canvas.Pen.Color := clWhite;
  PaintBox1.Canvas.Pen.Style := psSolid;
  PaintBox1.Canvas.Pen.Width := 1;

  PaintBox1.Canvas.Brush.Color := clWhite;
  PaintBox1.Canvas.Brush.Style := bsSolid;
  PaintBox1.Canvas.Rectangle(0, 0, ImageWidth, ImageHeight);
end;


//用紙枠の描画
procedure TForm1.Draw_Paper_Frame;
var
  x1, y1, x2, y2: Integer;
begin
  // 原点の計算
  ox := Round( (0.0 - view_x1) * mm_dot);
  oy := Round(-(0.0 - view_y2) * mm_dot);
  
  // 画面の消去
  CLS;

  // 用紙枠の描画
  x1 := Round( (-PaperWidth /2 - view_x1) * mm_dot);
  y1 := Round(-(-PaperHeight/2 - view_y2) * mm_dot);
  x2 := Round( ( PaperWidth /2 - view_x1) * mm_dot);
  y2 := Round(-( PaperHeight/2 - view_y2) * mm_dot);
  PaintBox1.Canvas.Pen.Color := clBlue;
  PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Rectangle(x1, y1, x2, y2);
end;


procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  cx, cy: Double;
  dx, dy: Double;
begin
  //2倍に拡大
  cx := (view_x1 + view_x2) / 2.0;  // ビュー中央のX座標
  cy := (view_y1 + view_y2) / 2.0;  // ビュー中央のY座標
  dx := Abs(view_x2 - view_x1);
  dy := Abs(view_y2 - view_y1);
  mm_dot := mm_dot * 2.0;
  view_x1 := cx - (dx / 4.0);
  view_y1 := cy - (dy / 4.0);
  view_x2 := cx + (dx / 4.0);
  view_y2 := cy + (dy / 4.0);
  Drawdata;
end;


procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
var
  cx, cy: Double;
  dx, dy: Double;
begin
  // 1/2倍に縮小
  cx := (view_x1 + view_x2) / 2.0;  // ビュー中央のX座標
  cy := (view_y1 + view_y2) / 2.0;  // ビュー中央のY座標
  dx := Abs(view_x2 - view_x1);
  dy := Abs(view_y2 - view_y1);
  mm_dot := mm_dot * 0.5;
  view_x1 := cx - dx;
  view_y1 := cy - dy;
  view_x2 := cx + dx;
  view_y2 := cy + dy;
  Drawdata;
end;


procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if (ssLeft in Shift) or (ssRight in Shift) then
  begin
    DraggingNow := True;
    DragStart_X := X;
    DragStart_Y := Y;
    RubberBandShow := False;
    DragEnd_X := 0;
    DragEnd_Y := 0;

    if (ssLeft  in Shift) then
      DragEnd_X := 1;

    if (ssRight in Shift) then
      DragEnd_Y := 1;
  end;
end;


procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if (DraggingNow) then
  begin
    if (RubberBandShow) then
      RubberBand(DragStart_X, DragStart_Y, DragEnd_X, DragEnd_Y);

    if (ssLeft in Shift) and (ssRight in Shift) then
    begin
      RubberBand(DragStart_X, DragStart_Y, X, Y);
      RubberBandShow := True;
      DragEnd_X := X;
      DragEnd_Y := Y;
    end;
  end;
end;


procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  x1, y1, x2, y2: Double;
  cx, cy: Double;
  dx, dy: Double;
  bx, by: Double;
  P1, P2: Double;
begin
  if (DraggingNow) then
  begin
    // ドラッグ処理の終了
    DraggingNow := False;
    if (RubberBandShow) then
      RubberBand(DragStart_X, DragStart_Y, DragEnd_X, DragEnd_Y);

    if (Abs(DragStart_X - X) <= 5) and (Abs(DragStart_Y - Y) <= 5) then
       DragModeKind := 0     // 移動
    else
      begin
        if (DragStart_X <= X) then
          DragModeKind := 1  // 拡大
        else
          DragModeKind := 2; // 縮小
      end;

    x1 := view_x1 + (DragStart_X / mm_dot);
    y1 := view_y2 - (DragStart_Y / mm_dot);
    x2 := view_x1 + (X / mm_dot);
    y2 := view_y2 - (Y / mm_dot);
    dx := Abs(view_x2 - view_x1);
    dy := Abs(view_y2 - view_y1);
    bx := Abs(x1 - x2);
    by := Abs(y1 - y2);
    cx := (x1 + x2) / 2.0;
    cy := (y1 + y2) / 2.0;

    case (DragModeKind) of
      0: begin    // 移動
           cx := (view_x1 +view_x2) / 2.0;
           cy := (view_y1 +view_y2) / 2.0;
           dx := x2 - cx;
           dy := y2 - cy;
           view_x1 := view_x1 + dx;
           view_y1 := view_y1 + dy;
           view_x2 := view_x2 + dx;
           view_y2 := view_y2 + dy;
         end;
      1: begin    // 拡大
           P1 := dx / bx;
           P2 := dy / by;

           if (P1 < P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           view_x1 := cx - ((ImageWidth  / 2.0) / mm_dot);
           view_y1 := cy - ((ImageHeight / 2.0) / mm_dot);
           view_x2 := cx + ((ImageWidth  / 2.0) / mm_dot);
           view_y2 := cy + ((ImageHeight / 2.0) / mm_dot);
         end;
      2: begin    // 縮小
           P1 := bx / dx;
           P2 := by / dy;

           if (P1 > P2) then
             mm_dot := mm_dot * P1
           else
             mm_dot := mm_dot * P2;

           view_x1 := cx - ((ImageWidth  / 2.0) / mm_dot);
           view_y1 := cy - ((ImageHeight / 2.0) / mm_dot);
           view_x2 := cx + ((ImageWidth  / 2.0) / mm_dot);
           view_y2 := cy + ((ImageHeight / 2.0) / mm_dot);
         end;
    end;
    Drawdata;
  end
end;


procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  Drawdata;
end;


// ラバーバンド長方形描画
procedure TForm1.RubberBand(x1, y1, x2, y2:Integer);
begin
  PaintBox1.Canvas.Pen.Mode := pmXor;
  PaintBox1.Canvas.Pen.Color := clAqua;
  PaintBox1.Canvas.Pen.Width := 0;
  PaintBox1.Canvas.Pen.Style := psSolid;
  PaintBox1.Canvas.Brush.Style := bsClear;
  PaintBox1.Canvas.Rectangle(x1,y1,x2,y2);
end;


// CADデータの描画
procedure TForm1.Drawdata;

  // 座標を変換
  procedure Change_mm_dot(x1, x2, y1, y2: Double;
    var ix1, ix2, iy1, iy2: Integer);
  begin
    ix1 := Round( x1 * mm_dot + ox );
    iy1 := Round(-y1 * mm_dot + oy );
    ix2 := Round( x2 * mm_dot + ox );
    iy2 := Round(-y2 * mm_dot + oy );
  end;

var
  I: Integer;
  x1, x2, y1, y2: Double;
  ix1, ix2, iy1, iy2: Integer;
  Moji: String;
begin
  // 一番肝心な部分ですが、とりあえず線と文字を
  // 単純に描画しています。

  // 用紙枠の描画
  Draw_Paper_Frame;

  PaintBox1.Canvas.Pen.Color := clBlack;
  for I := Low(JWWSen) to High(JWWSen)  do
  begin
    x1 := JWWSen[I].m_start_x;
    y1 := JWWSen[I].m_start_y;
    x2 := JWWSen[I].m_end_x;
    y2 := JWWSen[I].m_end_y;

    // mm→dot変換
    Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

    //線の描画
    PaintBox1.Canvas.Pen.Width := 0;
    PaintBox1.Canvas.MoveTo(ix1, iy1);
    PaintBox1.Canvas.LineTo(ix2, iy2);
  end;

  PaintBox1.Canvas.Font.Size := 6;
  for I := Low(JWWMoji) to High(JWWMoji)  do
  begin
    x1 := JWWMoji[I].m_start_x;
    y1 := JWWMoji[I].m_start_y;
    x2 := JWWMoji[I].m_end_x;
    y2 := JWWMoji[I].m_end_y;
    Moji := JWWMoji[I].m_string;

    // mm→dot変換
    Change_mm_dot(x1, x2, y1, y2, ix1, ix2, iy1, iy2);

    //文字の描画
    PaintBox1.Canvas.TextOut(ix1, iy1, Moji);
  end;
end;

end.


☆Jw_cad

☆AFsoft
CADに必要な数学の解説からCADの具体的な実装まで、豊富なDelphiのサンプルと共に詳しく解説されています。 又、JWW用の便利なソフトをたくさん公開しておられます。

☆Peter's Room
jww data read & save unit Ver1.2β
MicroArtsさんが公開されていたJww読込みユニットをPeter.さんが拡張されたものだそうです。
利用に際しては、ユニットの記載内容をお読み下さい。

[20071109訂正]
for I := Low(JWWMoji) to High(JWWMoji) -1 do
for I := Low(JWWSen) to High(JWWSen) -1 do
上記のところ、High関数を使っているのに-1していましたので、-1を削除しました。

|