« ■RAD Studio 2007 ヘルプアップデート 2 | トップページ | ☆JWWのソリッドデータを描画してみる。 »

☆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/

|

« ■RAD Studio 2007 ヘルプアップデート 2 | トップページ | ☆JWWのソリッドデータを描画してみる。 »