DcadPlot Ver.2015.5.4 for DraftSight / ARES commander
※ARES は廉価版でも COM API (ActiveX) が使えます。そちらを使ったほうがスマートです。
■概要
DraftSight / ARES で開いている図面を一括で印刷ツールです。
図面の取得、印刷には、結構時間がかかります。
図枠に属性として、シート番号、ページ番号が設定されている場合は、その順で出力できます。
※印刷設定ファイル(PrintStyle)の取得は、システム変数 FONTMAP (フォントマップファイル)のフォルダ名から推定しています。
システム変数 FONTMAP の値が書き変わってしまった場合は、下記を参考に設定しなおして下さい。
DraftSight
"C:\Program Files\Dassault Systemes\DraftSight\Fonts\fonts.fmp"
ARES
"C:\Program Files\Graebert GmbH\ARES Commander 2015\Fonts\fonts.fmp"
(32bit版の時は、Program Files (x86) になります)
※印刷時間は、長めに設定して下さい。印刷中にドキュメントが切り替わると、CADがエラーで継続不能になります。
※印刷待ちに、コマンドラインをキャプチャし、画像の変化による監視を追加しました。「設定」タブにて使えるかどうか確認できます。
コマンドラインが隠れるとうまく動きませんので、注意して下さい。
こちらの環境では、exe のプロパティ「互換」で、「高解像度DPI...」にチェックを付ける必要がありました。
やはり、「バッチ印刷」を使ったほうが、安全で快適なのだと思います。
■履歴
2015/04/26
・初版作成
2015/04/30
・DXFファイルから属性(シート番号、ページ番号)の取得を追加
2015/05/03
・コマンド送信に、[Enter]、[ESC] を追加。取得を若干高速にした。
2015/05/04
・印刷待ちに、キャプチャ画像によるコマンドライン監視を追加。取得を若干高速にした。
・自動保存を一時的にOFFにするを追加した。

■ダウンロード
DcadPlot.zip (2015/05/04 exe本体のみ)
■ソースコード
unit DcadPlotUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, Vcl.CheckLst,Comobj, Vcl.ExtCtrls, Vcl.Grids, IniFiles, System.UITypes,
Vcl.ComCtrls, Vcl.Buttons, ClipBrd, Imm, Printers, Winspool, System.IOUtils, System.Types;
type
DcadPoint = array [0..2] of double;
type
TForm5 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
Button1: TButton;
SpeedButton4: TSpeedButton;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label4: TLabel;
Label5: TLabel;
ComboBox1: TComboBox;
ComboBox2: TComboBox;
Button2: TButton;
Button4: TButton;
Label3: TLabel;
Edit1: TEdit;
StringGrid1: TStringGrid;
ProgressBar1: TProgressBar;
Label6: TLabel;
ComboBox3: TComboBox;
Label8: TLabel;
SpeedButton9: TSpeedButton;
Label17: TLabel;
SpeedButton3: TSpeedButton;
TabSheet2: TTabSheet;
GroupBox2: TGroupBox;
Label7: TLabel;
Edit2: TEdit;
Label9: TLabel;
Label10: TLabel;
Edit3: TEdit;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
Edit4: TEdit;
Label15: TLabel;
GroupBox3: TGroupBox;
Label16: TLabel;
Edit5: TEdit;
Edit6: TEdit;
Label18: TLabel;
Edit7: TEdit;
Edit8: TEdit;
Label19: TLabel;
Label20: TLabel;
SpeedButton5: TSpeedButton;
Image1: TImage;
SpeedButton6: TSpeedButton;
Image2: TImage;
CheckBox1: TCheckBox;
Label21: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure ComboBox2Change(Sender: TObject);
procedure SpeedButton4Click(Sender: TObject);
procedure StringGrid1Click(Sender: TObject);
procedure SpeedButton9Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure PageControl1Change(Sender: TObject);
procedure SpeedButton5Click(Sender: TObject);
procedure SpeedButton6Click(Sender: TObject);
private
{ Private 宣言 }
LastPrinter, LastCtbStb :string;
MbRow, MbCol : integer;
public
{ Public 宣言 }
RunFlag : boolean;
procedure DispCheckedCount;
end;
var
Form5: TForm5;
// メインウィンドウ
DcadMainWinHandle : HWND;
DcadMDIClientWinHandle : HWND;
DcadCommandWinHandle : HWND;
DcadInputWinHandle : HWND;
DcadOutputWinHandle : HWND;
DcadMDIActiveWinHandle : HWND;
DcadMDIChildWinHandle : HWND;
DCadProcessID : DWORD; //プロセスID
SleepDocChg, SleepPrint, SleepSysVar : integer;
// *****************************
// プリンター用紙名を取得
// *****************************
procedure GetPrinterPaperNames(iIndex :integer; sl: TStrings);
implementation
{$R *.dfm}
//****************************************
// 画面の指定位置をBitmapに変換
//****************************************
procedure CaptureToBmp(Lf, Tp, W, H: Integer; bmp: TBitmap);
const
CAPTUREBLT = $40000000;
var
hdcScreen : HDC;
begin
bmp.Width := W;
bmp.Height := H;
hdcScreen := CreateDC('DISPLAY', nil, nil, nil);
try
BitBlt( bmp.Canvas.Handle, 0, 0, W, H, hdcScreen, Lf, Tp, SRCCOPY or CAPTUREBLT);
finally
DeleteDC(hdcScreen);
end;
end;
//****************************************
// 最後の指定文字列より後を得る
//****************************************
function LastSubstringAfter(const ststr, s: string):String;
var
st, stlen : integer;
temp : string;
begin
Result := '';
if Pos(ststr, s) > 0 then begin
temp := s;
stlen := Length(ststr);
while Pos(ststr, temp) > 0 do begin
st := Pos(ststr, temp) + stlen;
temp := Copy(temp, st, Length(temp) - st + 1);
if temp = '' then break;
end;
Result := Trim(temp);
end;
end;
//****************************************
//最初に現れたststrからedstrまでを返す
//****************************************
function StrAfterStrBefore(const ststr, edstr, s:string):String;
var
st, ed:integer;
temp : string;
begin
Result:='';
st:=Pos(ststr,s);
if st > 0 then begin
temp := s;
Delete(temp,1,st + Length(ststr)-1);
ed := Pos(edstr, temp)-1;
if ed >= 0 then
Result := Trim(Copy(temp, 1, ed));
end;
end;
//****************************************
// 実際には、MDIClientではない
//****************************************
function EnumCWinProc_MDIClient(h:HWND;lparam:Integer):Bool;stdcall;
var
Title : array [0..255] of char;
begin
Result:=True;
if GetWindowText(h, Title, 255) <> 0 then begin
if 'CFxWorkspaceImplClassWindow' = Title then begin
DcadMDIClientWinHandle := GetWindow(h, GW_CHILD);
DcadMDIChildWinHandle := GetWindow(DcadMDIClientWinHandle, GW_CHILD);
Result := False;
end;
end;
end;
//****************************************
// 実際には、MDIClientではない
//****************************************
function GetDcadMDIClientHandle:HWND;
begin
EnumChildWindows(DcadMainWinHandle,@EnumCwinProc_MDIClient, 0);
result:=DcadMDIClientWinHandle;
end;
//****************************************
// コマンドウィンドウ
//****************************************
function EnumCWinProc_CommandWinHandle(h: HWND; lparam: Integer):Bool;stdcall;
var
Title : array [0..255] of char;
begin
Result:=True;
if GetWindowText(h, Title, 255) <> 0 then begin
if 'CFxCommandWindowWindow' = Title then begin
DcadCommandWinHandle := h;
Result:=False;
end;
end;
end;
//****************************************
// コマンドウィンドウ Input/OutputWindow
//****************************************
function GetDcadCommandWinHandle:HWND;
begin
EnumChildWindows(DcadMainWinHandle, @EnumCwinProc_CommandWinHandle, 0);
result := DcadCommandWinHandle;
if result <> 0 then begin
DcadOutputWinHandle := GetWindow(DcadCommandWinHandle, GW_CHILD);
DcadInputWinHandle := GetWindow(DcadOutputWinHandle, GW_HWNDNEXT);
end;
end;
//****************************************
// メインウィンドウ
//****************************************
function EnumWindowProcMainWin(h: HWND; lp: LParam): BOOL; stdcall;
var
Title : array [0..255] of char;
ClassName : array [0..255] of char;
begin
Result := true;
GetClassName(h, ClassName, 255);
if 'Qt5QWindowIcon' = ClassName then begin
// タイトルを得る
if GetWindowText(h, Title, 255) <> 0 then begin
if (Pos('DraftSight - [', Title) = 1) or
(Pos('ARES Commander 2015 - [', Title) = 1) then begin
DCadMainWinHandle := h;
GetWindowThreadProcessId(h, @DCadProcessID);
Result := false;
end;
end;
end;
end;
//****************************************
// メインウィンドウのハンドルを得る
//****************************************
function GetDCadMainWinHandle : HWND;
begin
EnumWindows(@EnumWindowProcMainWin, 0);
Result := DCadMainWinHandle;
end;
//****************************************
// 文字列送信
//****************************************
function SendHwndCmdLine(hCmdLine: HWND; const cmd : string):boolean;
var
i : integer;
begin
Result := False;
if hCmdLine <> 0 then begin
// 文字列を送信
for i := 1 to Length(cmd) do begin
if cmd[i] = #13 then begin
SendMessage(hCmdLine,WM_KEYDOWN,VK_RETURN,0);
SendMessage(hCmdLine,WM_KEYUP,VK_RETURN,0);
Sleep(1);
end
else if (cmd[i] = #27) or (cmd[i] = #3) then begin
SendMessage(hCmdLine,WM_KEYDOWN,VK_ESCAPE,0);
SendMessage(hCmdLine,WM_KEYUP,VK_ESCAPE,0);
Sleep(1);
end
else begin
SendMessage(hCmdLine, WM_CHAR, Word(cmd[i]), 0);
if cmd[i] = #20 then Sleep(1);
end;
end;
result := true;
end;
end;
//******************************************
// ウィンドウのタイトル(キャプション)を得る
//******************************************
function GetWindowCaption(h : HWND) : string;
var
Title : array [0..255] of char;
begin
result := '';
if GetWindowText(h, Title, 255) <> 0 then
result := Title;
end;
//****************************************
// コマンド送信
//****************************************
function SendDcadCommand(const cmd: string): boolean;
begin
GetDcadCommandWinHandle;
Result := SendHwndCmdLine(DcadInputWinHandle, cmd);
end;
//****************************************
// システム変数取得
//****************************************
function GetDcadVariable(const SysVar: string): string;
var
s : string;
begin
Result := '';
GetDCadMainWinHandle;
SetForegroundWindow(DcadMainWinHandle);
SendDcadCommand(SysVar + #13#3);
Sleep(10);
SendDcadCommand('COPYHISTORY'#13);
Sleep(200);
s := '';
try
s := ClipBoard.AsText;
s := LastSubstringAfter(': ' + SysVar, s);
Result := '';
if (Pos('=', s) > 0) and (Pos('(', s) > 1) then
Result := Trim(StrAfterStrBefore('=', '(', s));
if (Result = '') and (Pos('(', s) > 0) and (Pos(')', s) > 1) then
Result := Trim(StrAfterStrBefore('(', ')', s));
if (Result = '') and (Pos('デフォルト:', s)>0) then begin
Result := Trim(StrAfterStrBefore('デフォルト:', #13, s));
end;
except
;
end;
end;
//****************************************
// DraftSight / ARES commander をアクティブに
//****************************************
function SetDcadActive: boolean;
begin
Result := False;
if GetDCadMainWinHandle <> 0 then begin
SetForegroundWindow(DcadMainWinHandle);
Result := True;
end;
end;
function WaitForDcadCommandReady(timeout: integer): boolean;
var
cnt : integer;
ARect : TRect;
AHeight,ATop : integer;
Bmp : TBitMap;
co : Integer;
i,j: integer;
pByte :PByteArray;
Flag : Boolean;
msec : integer;
n : integer;
begin
Result := False;
msec := 10;
GetDcadMainWinHandle;
GetDcadCommandWinHandle;
//Form5.Caption := IntToHex(DcadInputWinHandle, 8);
GetWindowRect(DcadInputWinHandle, ARect);
ATop := ARect.Top;
AHeight := ARect.Bottom - ARect.Top;
ATop := ATop+ AHeight -20;
//AWidth := ARect.Right - Arect.Left;
//Form5.Caption := IntToStr(AHeight);
Bmp := TBitmap.Create;
try
Bmp.Width := 100;
Bmp.Height := 20;
Bmp.PixelFormat :=pf24bit;
n := 0;
cnt := 0;
while True do begin
Sleep(msec);
Application.ProcessMessages;
CaptureToBmp(Arect.Left + 18, ATop, Bmp.Width, Bmp.Height, bmp);
Form5.Image1.Picture.Assign(bmp);
pByte := Bmp.ScanLine[0];
co := pByte[0];
Flag := True;
for i := 1 to Bmp.Height - 1 do begin
pByte := Bmp.ScanLine[i];
for j := 0 to Bmp.Width -1 do begin
if co <> pByte[j] then begin
Flag := False;
n := 0;
Break;
end;
end;
end;
if Flag then Inc(n);
if n > 3 then begin
Result := True;
Break;
end;
Inc(cnt);
if cnt * msec > timeout then Break;
end;
finally
Bmp.Free;
end;
end;
//****************************************
// 座標文字列を3D座標に
//****************************************
procedure StrPointToDcadPoint(const StrPoint: string; var pt: DcadPoint);
var
n : integer;
s: string;
begin
s := StrPoint;
n := Pos(',', s);
pt[0] := StrToFloatDef(Copy(s, 1, n - 1), 0);
s := Copy(s, n + 1);
n := Pos(',', s);
if n > 0 then begin
pt[1] := StrToFloatDef(Copy(s, 1, n - 1), 0);
pt[2] := StrToFloatDef(Copy(s, n + 1), 0);
end
else begin
pt[1] := StrToFloatDef(s, 0);
pt[2] := 0;
end;
end;
// ************************************
// DXFファイルからシステム変数(2D座標)を取得する
// ************************************
function ReadDxfVariablePoint2DString(dxfSl: TStrings; const sysName: string):string;
var
idx, i : integer;
code : integer;
s : string;
dxfSys : string;
begin
Result := '';
dxfSys := '$' + Uppercase(sysName);
idx := dxfSL.IndexOf('ENTITIES');
for i := 0 to idx div 2 do begin
code := StrToInt(dxfSl[i *2]);
s := dxfSl[i * 2 + 1];
if (code = 9) and (s = dxfSys) then begin
result := dxfSl[(i + 1) * 2 + 1] + ',' + dxfSl[(i + 2) * 2 + 1];
break;
end;
end;
end;
// ************************************
// DXFファイルから属性を取得する
// ************************************
function ReadDxfAttRib(dxfSl: TStrings; const InsertName: string; const AttRibName: string): string;
var
i : integer;
insFlag, attFlag, hasAtt : boolean;
s : string;
AblkName , AattName, AattString : string;
code, idx : integer;
begin
Result := '';
insFlag := False;
hasAtt := False;
attFlag := False;
// ENTITIESセクションを探す
idx := dxfsl.IndexOf('ENTITIES');
for i := idx div 2 + 1 to dxfsl.Count div 2 - 1 do begin
// DXFコード
code := StrToInt(dxfsl[i * 2]);
// その値
s := dxfsl[i * 2 + 1];
if insFlag then begin
// 属性取得終了
if hasAtt and (code = 0) and (s = 'SEQEND') then begin
insFlag := False;
hasAtt := False;
attFlag := false;
end;
if hasAtt and (AblkName = '') and (code = 2) then
AblkName := s;
if attFlag then begin
// 属性の値を保持
if code = 1 then
AattString := s;
// 属性名
if code = 2 then begin
AattName := s;
// ブロック名、属性名が同じ
if (InsertName = ABlkName) and (AttRibName = AattName) then begin
Result := AattString;
Break;
end;
end;
end;
if hasAtt and (code = 0) and (s = 'ATTRIB') then
attFlag := True;
end;
if (code = 0) and (s = 'INSERT') then begin
insFlag := True;
hasAtt := False;
attFlag := False;
AblkName := '';
end;
// 属性有
if (code = 66) and (Trim(s) = '1') then
hasAtt := True;
// ENTITIES セクション終わり
if (code = 0) and (s = 'ENDSEC') then
Break;
end;
end;
// ************************************
// DXFファイルを作成する
// ************************************
function SaveDxfSl(dxfsl : TStringList):boolean;
var
fname : TFileName;
cnt : integer;
begin
Result := False;
fname := ChangeFileExt(ParamStr(0), '.dxf');
DeleteFile(fname);
cnt := 0;
while True do begin
Sleep(10);
if not FileExists(fname) then begin
Break;
end;
Inc(cnt);
if cnt > 5 then Break;
end;
if SetDcadActive then begin
SendDcadCommand('FILEDIA'#13'0'#13);
Sleep(10);
SendDcadCommand('DXFOUT'#13 + fname +#13'Vesion'#13'R18'#13'16'#13);
Sleep(10);
SendDcadCommand('''FILEDIA'#13'1'#13);
cnt := 0;
// ファイル作成待ち
while True do begin
Sleep(10);
if FileExists(fname) then begin
Sleep(10);
Break;
end;
Inc(cnt);
if cnt > 50 then Break;
end;
if FileExists(fname) then begin
dxfsl.LoadFromFile(fname);
Result := dxfsl.Count > 0;
end;
end;
end;
// *****************************
// 印刷チェック数をカウント
// *****************************
procedure TForm5.DispCheckedCount;
var
i, cnt : integer;
begin
cnt := 0;
with StringGrid1 do begin
for i := 1 to RowCount - 1 do begin
if (Cells[1, i] <> '') and Bool(Objects[1, i]) then Inc(cnt);
end;
end;
// 印刷ボタン
Button2.Enabled := cnt > 0;
Label5.Caption := IntToStr(cnt);
end;
// *****************************
// StringGrid でのキー操作
// *****************************
procedure SgKeyDown(SG: TSTringGrid; var Key: Word; Shift:TShiftState);
var
i, j, k, n : integer;
sl : TStringList;
s, s1 : string;
xflag : boolean;
begin
if Key = VK_DELETE then begin
with SG do begin
if (Selection.Top <> Selection.Bottom) or
(Selection.Left <> Selection.Right) then begin
Key := 0;
for i := Selection.Top to Selection.Bottom do begin
for j := Selection.Left to Selection.Right do begin
Cells[j, i] := '';
end;
end;
end;
end;
end;
if ssCtrl in Shift then begin
if true then begin
xflag := (Key = Ord('X')) or (Key = Ord('x'));
if (Key = Ord('C')) or (Key = Ord('c')) or xflag then begin
Key := 0;
Clipboard.AsText := '';
with SG do begin
for i := Selection.Top to Selection.Bottom do begin
for j := Selection.Left to Selection.Right do begin
Clipboard.AsText := Clipboard.AsText + Cells[j, i];
if j < Selection.Right then Clipboard.AsText := Clipboard.AsText + #9
else Clipboard.AsText := Clipboard.AsText + #13#10;
end;
end;
if xflag then begin
for i := Selection.Top to Selection.Bottom do begin
for j := Selection.Left to Selection.Right do begin
Cells[j, i] := '';
end;
end;
end;
end;
end
else if (Key = Ord('V')) or (Key = Ord('v')) then begin
//with SG do
// if EditorMode then EditorMode := false;
Key := 0;
with SG do begin
sl := TStringList.Create;
try
s := Clipboard.AsText;
while true do begin
k := Pos(#13#10, s);
if k = 0 then break
else begin
sl.Add(Copy(s, 1, k - 1));
Delete(s, 1, k + 1);
end;
end;
for i := 0 to sl.Count-1 do begin
s := SL[i];
j := 0;
while true do begin
k := Pos(#9, s);
if k = 0 then begin
s1 := Copy(s, 1, Length(s));
end
else begin
s1 := Copy(s, 1, k - 1);
Delete(s, 1, k);
end;
Cells[Selection.Left + j,Selection.Top + i] := s1;
n := 1;
while true do begin
if Selection.Bottom < Selection.Top + i + (sl.Count * n) then
break
else begin
Cells[Selection.Left + j, Selection.Top + i + (sl.Count * n)] := s1;
end;
Inc(n);
end;
if k = 0 then break;
Inc(j);
end;
end;
finally
sl.Free;
end;
end;
end;
end;
end;
end;
// *****************************
// StringGrid の Col の値でソート
// *****************************
procedure SgSortByCol2(sg : TStringGrid; col1, col2 :integer; NumFlag:boolean);
var
i, j : integer;
sl, sltemp : TStringList;
s1, s0 : string;
begin
// ソート
sl := TStringList.Create;
try
sltemp := TStringList.Create;
try
with sg do begin
for i := 1 to RowCount -2 do begin
s0 := '';
if col1 >= 0 then s0 := s0 + Cells[col1, i];
if col2 >= 0 then s0 := s0 + Cells[col2, i];
for j := i + 1 to RowCount -1 do begin
s1 := '';
if col1 >= 0 then s1 := s1 + Cells[col1, j];
if col2 >= 0 then s1 := s1 + Cells[col2, j];
if (not NumFlag and (s0 > s1)) or
(NumFlag and (StrToIntDef(s0, 0) > StrToIntDef(s1, 0))) then begin
slTemp.Assign(Rows[i]);
Rows[i] := Rows[j];
Rows[j] := slTemp;
s0 := s1;
end;
end;
end;
end;
finally
slTemp.Free;
end;
finally
sl.Free;
end;
end;
// *****************************
// 取得
// *****************************
procedure TForm5.Button1Click(Sender: TObject);
var
i : integer;
sdir : string;
cnt : integer;
j : integer;
s :string;
arycnt : integer;
dwgname , dwgprefix :string;
limmax, limmin : DcadPoint;
h, hdwg : HWND;
dwgTitle, ext : string;
fnames: TStringDynArray;
fpath, fname : TFileName;
sl : TStringList;
Title : string;
count : integer;
begin
Title := '';
// メニューを操作して図面を切り替えるため、
// 一度図面を切り替えて、そのファイル名を取得して記憶する
// メインウィンドウのハンドルを取得
if GetDCadMainWinHandle = 0 then Exit;
// 最小化されていれば戻す
if isIconic(DcadMainWinHandle) then begin
OpenIcon(DcadMainWinHandle);
// 画面描画待ち
Sleep(SleepDocChg);
end;
// MDI のウィンドウを探す
GetDcadMDIClientHandle;
h := DcadMDIChildWinHandle;
cnt := 0;
// ここでは、ドキュメントの数を数えるだけ
while h <> 0 do begin
hdwg := GetWindow(h, GW_CHILD);
dwgTitle := GetWindowCaption(hdwg);
// ファイル名を取得
ext := Uppercase(ExtRactFileExt(dwgTitle));
// 念のため、拡張子を比較
if (ext = '.DWG') or (ext = '.DWG*') then
Inc(cnt);
// 次のウィンドウを探す
h := GetWindow(h, GW_HWNDNEXT);
end;
if cnt = 0 then Exit;
SendDcadCommand(#3'SAVETIME'#13'0'#13);
sdir := GetDcadVariable('DWGPREFIX');
Edit1.Text := sdir;
arycnt := cnt;
if arycnt > 0 then begin
with Progressbar1 do begin
Max := arycnt;
Position := 0;
end;
with StringGrid1 do begin
RowCount := arycnt + 1;
for i := 1 to RowCount -1 do
for j := 0 to ColCount -1 do
Cells[j, i] := '';
end;
cnt := 0;
sl := TStringList.Create;
try
// メニューを操作
for i := 0 to arycnt - 1 do begin
// CADをアクティブに
SetForegroundWindow(DcadMainWinHandle);
keybd_event(VK_MENU, 0, 0, 0);
keybd_event(Ord('W'), 0, 0, 0);
keybd_event(Ord('W'), 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
for j := 0 to i + 4 do begin
keybd_event(VK_DOWN, 0 ,0 ,0);
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
end;
keybd_event(VK_RETURN, 0, 0, 0);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
count := 0;
while True do begin
Sleep(10);
if Title <> GetWindowCaption(DcadMainWinHandle) then begin
Break;
end;
Inc(count);
if Count > 60 then Break;
end;
// 図面切り替わり待ち
Sleep((count + 2) * 50);
// 編集の図面名を取得
s := GetWindowCaption(DcadMainWinHandle);
Title := s;
dwgname := StrAfterStrBefore('[', ']', s);
dwgprefix := GetDcadVariable('DWGPREFIX');
// 同じフォルダ名の図面のみを取得
if sdir = dwgprefix then begin
with StringGrid1 do begin
Cells[0, cnt + 1] := IntToStr(i + 1);
Cells[1, cnt + 1] := dwgname;
if SaveDxfSL(sl) then begin
// シート番号を取得
s := ReadDxfAttRib(sl, Edit5.Text, Edit6.Text);
Cells[7, cnt + 1] := s;
//ページ番号を取得
s := ReadDxfAttRib(sl, Edit7.Text, Edit8.Text);
Cells[8, cnt + 1] := s;
s := ReadDxfVariablePoint2DString(sl, 'LIMMAX');
Cells[9, cnt + 1] := s;
StrPointToDcadPoint(s, limmax);
s := ReadDxfVariablePoint2DString(sl, 'LIMMIN');
Cells[10, cnt + 1] := s;
StrPointToDcadPoint(s, limmin);
Cells[2, cnt + 1] := Format('%.1f',[limmax[0] - limmin[0]]);
Cells[3, cnt + 1] := Format('%.1f',[limmax[1] - limmin[1]]);
// ScaleA3
Cells[4, cnt + 1] := Format('%.3f',[limmax[0] / 420]);
// ScaleA4
Cells[5, cnt + 1] := Format('%.3f',[limmax[0] / 297]);
Objects[1, cnt + 1] := TObject(True);
end;
end;
with Progressbar1 do Position := Position + 1;
Inc(cnt);
end;
end;
finally
sl.Free;
end;
with StringGrid1 do begin
RowCount := cnt + 1;
Row := 1;
Col := 2;
SetFocus;
end;
label6.Caption := '/' + cnt.ToString;
Progressbar1.Position := 0;
// プリンター名一覧を Windows から取得
ComboBox1.Items.Assign(Printer.Printers);
with ComboBox1 do begin
if LastPrinter <> '' then begin
for i := 0 to Items.Count - 1 do begin
if Items[i] = LastPrinter then begin
ItemIndex := i;
Break;
end;
end;
end
else begin
if Items.Count > 0 then
ItemIndex := 0
else
ItemIndex := - 1;
end;
end;
// 用紙名一覧を Windows から取得
GetPrinterPaperNames(ComboBox1.ItemIndex, ComboBox3.Items);
with ComboBox3 do begin
for i := 0 to Items.Count - 1 do begin
if Pos('A4', Items[i]) > 0 then begin
ItemIndex := i;
break;
end;
end;
end;
Sleep(SleepSysVar);
// PrintStyle をDraftShight / ARES commander のインストールフォルダから取得
// フォントマップファイルの保存先を取得
s := GetDcadVariable('FONTMAP');
fpath := ExtractFilePath(ExtractFileDir(s)) + 'Default Files\Print Styles\';
if DirectoryExists(fpath) then begin
fnames := TDirectory.GetFiles(fpath, '*.?tb', TSearchOption.soTopDirectoryOnly);
with ComboBox2 do begin
Items.Clear;
for fname in fnames do
Items.Add(ExtractFileName(fname));
ItemIndex := Items.IndexOf(LastCtbStb);
if (ItemIndex < 0) and (Items.Count > 0) then
ItemIndex := 0;
end;
end;
end;
SendDcadCommand(#3'SAVETIME'#13'10'#13);
DispCheckedCount;
// シート番号順
SpeedButton3Click(self);
end;
// *****************************
// プリンター用紙名を取得
// *****************************
procedure GetPrinterPaperNames(iIndex :integer; sl: TStrings);
type
//用紙名リスト用.用紙名の文字数の最大は64
TPaperName = array [0..63] of Char;
var
ADevice : array [0..MAX_PATH-1] of Char;
ADriver : array [0..MAX_PATH-1] of Char;
APort : array [0..MAX_PATH-1] of Char;
ADeviceMode : THandle;
Count : Integer;
PaperNames : array of TPaperName;
i : Integer;
begin
sl.Clear;
//選択したプリンタを現在のプリンタとする
Printer.PrinterIndex := iIndex;
//現在のプリンタに関する情報を取り出す
Printer.GetPrinter(ADevice, ADriver, APort, ADeviceMode);
//そのプリンタADeviceのAPortの用紙名の数を取得
Count := Winspool.DeviceCapabilities(ADevice, APort, DC_PAPERNAMES, nil, nil);
//その分だけ用紙名配列の長さと用紙番号の配列の長さを確保
SetLength(PaperNames, Count);
//その配列に用紙名と用紙番号を取得
Winspool.DeviceCapabilities(ADevice, APort, DC_PAPERNAMES, PChar(PaperNames), nil);
//用紙名
for i := 0 to Count - 1 do sl.Add(String(PaperNames[i]));
end;
// *****************************
// 印刷実行
// *****************************
procedure TForm5.Button2Click(Sender: TObject);
var
i, j : integer;
scale : string;
papersize: string;
idx : integer;
devname : string;
sl : TStringList;
fname : TFileName;
begin
fname := ChangeFileExt(ParamStr(0), '.scr');
LastCtbStb := 'monochrome.ctb';
if MessageDlg('選択ファイルを印刷しますか?', mtInformation,mbYesNo,0) = mrYes then begin
// 自動保存をOFF
SendDcadCommand(#3'SAVETIME'#13'0'#13);
with ComboBox1 do begin
if ItemIndex >= 0 then
LastPrinter := Items[ItemIndex]
else
LastPrinter := '';
end;
with ComboBox3 do begin
if ItemIndex >= 0 then
papersize := Items[ItemIndex]
else
papersize := 'A4';
end;
with ComboBox2 do begin
if ItemIndex >= 0 then
LastCtbStb := Items[ItemIndex]
else
LastCtbStb := '';
end;
if (LastPrinter <> '') and (LastCtbStb <> '') then begin
sl := TStringList.Create;
try
devname := LastPrinter;
RunFlag := True;
Button2.Enabled := False;
Button4.Enabled := True;
if True then begin
with StringGrid1 do begin
ProgressBar1.Max := RowCount - 1;
ProgressBar1.Position := 0;
for i := 1 to RowCount - 1 do begin
// A3 -> A4 縮小
if Pos('A4', papersize) > 0 then
scale := '1=' + Format('%.3f',[StrToFloat(Cells[5, i])])
// A3 -> A3
else
// papersize := 'A3';
scale := '1=' + Format('%.3f',[StrToFloat(Cells[4, i])]);
with Progressbar1 do Position := Position + 1;
Application.ProcessMessages;
if RunFlag and Bool(Objects[1, i]) then begin
idx := StrToInt(Cells[0, i]) - 1;
if GetDCadMainWinHandle <> 0 then begin
SetForegroundWindow(DcadMainWinHandle);
// メニュー操作
keybd_event(VK_MENU, 0, 0, 0);
keybd_event(Ord('W'), 0, 0, 0);
keybd_event(Ord('W'), 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
for j := 0 to idx + 4 do begin
keybd_event(VK_DOWN, 0 ,0 ,0);
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
end;
keybd_event(VK_RETURN, 0, 0, 0);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
// 図面切り替わり待ち
Sleep(SleepDocChg);
// スクリプトファイル作成
with sl do begin
Clear;
// コマンドラインプロット
Add('-PLOT');
// 印刷オプションの詳細設定?
Add('Y');
// シート名を指定»
Add('Model');
// プリンタ名を指定»
Add(devname);
Sleep(SleepSysVar);
// ペーパー サイズを指定»
Add(papersize);
// 単位を指定» インチ(I) または ミリメートル(M)
Add('M');
// 方向を指定>>縦(P) または 横(L)
Add('L');
// 上下を逆にして印刷しますか?
Add('Y');
// 印刷範囲を指定»
Add('S');
// 始点コーナーを指定»
Add(Cells[10, i]);
// 反対側のコーナーを指定»
Add(Cells[9, i]);
// 印刷尺度を指定»
Add(scale);
// 印刷 X,Y オフセットを指定»
Add('C');
// 印刷スタイル テーブルを使用?
Add('Y');
// 印刷スタイル名»
Add(LastCtbStb);
// 割り当てられた線幅を使用?
Add('Y');
// オプション指定»
// 表示どおり(D), 隠線(H), レンダリング(R) または ワイヤフレーム(W)
Add('D');
// ファイルに出力?
Add('N');
// 印刷設定をシートに適用?
Add('Y');
// 今すぐ印刷しますか?
Add('Y');
Add('FILEDIA 1');
SaveToFile(fname);
if FileExists(fname) then begin
SendDcadCommand('FILEDIA'#13'0'#13);
Sleep(10);
// スクリプト読込
SendDcadCommand('LOADSCRIPT'#13 + fname + #13);
end;
SetForeGroundWindow(DcadMainWinHandle);
// 印刷終了待ち
if SleepPrint < 5000 then SleepPrint := 5000;
if CheckBox1.Checked then begin
WaitForDcadCommandReady(SleepPrint);
Sleep(100);
end
else
Sleep(SleepPrint);
end;
end;
end;
end;
end;
end;
ProgressBar1.Position := 0;
if RunFlag then
ShowMessage('印刷が終了しました.')
else
ShowMessage('印刷を中止しました.');
Button2.Enabled := True;
Button4.Enabled := False;
finally
sl.Free;
end;
end;
SendDcadCommand(#3'SAVETIME'#13'10'#13);
end;
end;
// *****************************
// 中止ボタン
// *****************************
procedure TForm5.Button4Click(Sender: TObject);
begin
RunFlag := False;
Application.ProcessMessages;
end;
// *****************************
// プリンター変更
// *****************************
procedure TForm5.ComboBox1Change(Sender: TObject);
var
i : integer;
begin
with ComboBox1 do begin
if ItemIndex >= 0 then
LastPrinter := Items[ItemIndex];
end;
GetPrinterPaperNames(ComboBox1.ItemIndex, ComboBox3.Items);
ComboBox3.Sorted := True;
with ComboBox3 do begin
for i := 0 to Items.Count - 1 do begin
if Pos('A4', Items[i]) > 0 then begin
ItemIndex := i;
break;
end;
end;
end;
end;
// *****************************
// 印刷設定変更
// *****************************
procedure TForm5.ComboBox2Change(Sender: TObject);
begin
with ComboBox2 do begin
if ItemIndex >= 0 then
LastCtbStb := Items[ItemIndex];
end;
end;
// *****************************
// フォーム作成
// *****************************
procedure TForm5.FormCreate(Sender: TObject);
var
ini : TIniFile;
begin
PageControl1.ActivePageIndex := 0;
Edit1.Text := '';
//Caption := Application.Title;
with StringGrid1 do begin
RowCount := 2;
ColCount := 11;
ColWidths[0] := 30;
ColWidths[1] := 230;
ColWidths[2] := 50;
ColWidths[3] := 50;
ColWidths[4] := 50;
ColWidths[5] := 50;
ColWidths[6] := 0;
ColWidths[7] := 50;
ColWidths[8] := 50;
ColWidths[9] := -1;
ColWidths[10] := -1;
Cells[0, 0] := 'No.';
Cells[1, 0] := 'ファイル名';
Cells[2, 0] := 'Lim W';
Cells[3, 0] := 'Lim H';
Cells[4, 0] := 'at A3';
Cells[5, 0] := 'at A4';
Cells[6, 0] := 'FilePath';
Cells[7, 0] := 'SHEET';
Cells[8, 0] := 'PAGE';
Cells[9, 0] := 'LimMax';
Cells[10, 0] := 'LimMin';
end;
SleepDocChg := 500;
SleepPrint := 5000;
SleepSysVar := 100;
ini := TIniFile.Create(ChangeFileExt(ParamStr(0), 'ini'));
with ini do begin
try
LastPrinter := ReadString('Plot', 'LastPrinter', '');
LastCtbStb := ReadString('Plot', 'LastCtbStb', '');
with StringGrid1 do
ColWidths[1] := ReadInteger('Form', 'FNameWidth', ColWidths[1] );
SleepDocChg := ReadInteger('Timer', 'SleepDocChg', SleepDocChg);
SleepPrint := ReadInteger('Timer', 'SleepPrint', SleepPrint);
SleepSysVar := ReadInteger('Timer', 'SleepSysVar', SleepSysVar);
Edit5.Text := ReadString('SheetAttRib', 'BlockName', Edit5.Text);
Edit6.Text := ReadString('SheetAttRib', 'AttName', Edit6.Text);
Edit7.Text := ReadString('PageNoAttRib', 'BlockName', Edit7.Text);
Edit8.Text := ReadString('PageNoAttRib', 'AttName', Edit8.Text);
CheckBox1.Checked := ReadBool('CheckBox', 'Uses CmdCapt', CheckBox1.Checked);
finally
Free;
end;
end;
// 待ちタイマー設定
Edit2.Text := SleepDocChg.ToString;
Edit3.Text := SleepPrint.ToString;
Edit4.Text := SleepSysVar.ToString;
end;
// *****************************
// フォーム破棄
// *****************************
procedure TForm5.FormDestroy(Sender: TObject);
var
ini : TIniFile;
begin
ini := TIniFile.Create(ChangeFileExt(ParamStr(0), 'ini'));
with ini do begin
try
WriteString('Plot', 'LastPrinter', LastPrinter);
WriteString('Plot', 'LastCtbStb', LastCtbStb);
WriteInteger('Form', 'FNameWidth', StringGrid1.ColWidths[1] );
WriteInteger('Timer', 'SleepDocChg', SleepDocChg);
WriteInteger('Timer', 'SleepPrint', SleepPrint);
WriteInteger('Timer', 'SleepSysVar', SleepSysVar);
WriteBool('CheckBox', 'Uses CmdCapt', CheckBox1.Checked);
WriteString('SheetAttRib', 'BlockName', Edit5.Text);
WriteString('SheetAttRib', 'AttName', Edit6.Text);
WriteString('PageNoAttRib', 'BlockName', Edit7.Text);
WriteString('PageNoAttRib', 'AttName', Edit8.Text);
finally
Free;
end;
end;
end;
// 待機タイマー設定
procedure TForm5.PageControl1Change(Sender: TObject);
begin
if PageControl1.ActivePageIndex = 0 then begin
SleepDocChg := StrToIntDef(Edit2.Text, SleepDocChg);
SleepPrint := StrToIntDef(Edit3.Text, SleepPrint );
SleepSysVar := StrToIntDef(Edit4.Text, SleepSysVar);
end;
end;
// *****************************
// 印刷チェック「すべてON」
// *****************************
procedure TForm5.SpeedButton1Click(Sender: TObject);
var
i : integer;
begin
with StringGrid1 do begin
for i := 1 to RowCount -1 do
Objects[1, i] := TObject(True);
end;
DispCheckedCount;
end;
// *****************************
// 印刷チェック「すべてOFF」
// *****************************
procedure TForm5.SpeedButton2Click(Sender: TObject);
var
i : integer;
begin
with StringGrid1 do begin
for i := 1 to RowCount - 1 do
Objects[1, i] := TObject(False);
end;
DispCheckedCount;
end;
procedure TForm5.SpeedButton3Click(Sender: TObject);
begin
// シート番号順
SgSortByCol2(StringGrid1, 7, -11, False);
end;
// *****************************
// 印刷「ファイル名順」
// *****************************
procedure TForm5.SpeedButton4Click(Sender: TObject);
begin
// ソート
SgSortByCol2(StringGrid1, 6, 1, False);
end;
procedure TForm5.SpeedButton5Click(Sender: TObject);
begin
// ページ番号順ソート
SgSortByCol2(StringGrid1, 8, -1, True);
end;
procedure TForm5.SpeedButton6Click(Sender: TObject);
var
ARect : TREct;
ATop, AHeight: integer;
Bmp : TBitmap;
begin
GetDcadMainWinHandle;
GetDcadCommandWinHandle;
//Form5.Caption := IntToHex(DcadInputWinHandle, 8);
GetWindowRect(DcadInputWinHandle, ARect);
ATop := ARect.Top;
AHeight := ARect.Bottom - ARect.Top;
ATop := ATop+ AHeight -20;
Bmp := TBitmap.Create;
try
Bmp.Width := 100;
Bmp.Height := 20;
Bmp.PixelFormat :=pf24bit;
CaptureToBmp(Arect.Left, ATop, Bmp.Width, Bmp.Height, bmp);
Image2.Picture.Assign(Bmp);
finally
Bmp.Free;
end;
end;
// *****************************
// 印刷:取得順ソート
// *****************************
procedure TForm5.SpeedButton9Click(Sender: TObject);
begin
SgSortByCol2(StringGrid1, 0, - 1, True);
end;
// *****************************
// 印刷用StringGridクリック
// *****************************
procedure TForm5.StringGrid1Click(Sender: TObject);
var
idx ,j : integer;
begin
with StringGrid1 do begin
if Row > 0 then begin
idx := StrToIntDef(Cells[0, Row], - 1) - 1;
if GetDCadMainWinHandle <> 0 then begin
SetForegroundWindow(DcadMainWinHandle);
// メニュー操作
keybd_event(VK_MENU, 0, 0, 0);
keybd_event(Ord('W'), 0, 0, 0);
keybd_event(Ord('W'), 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
for j := 0 to idx + 4 do begin
keybd_event(VK_DOWN, 0 ,0 ,0);
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
end;
keybd_event(VK_RETURN, 0, 0, 0);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
end;
end;
end;
end;
// *****************************
// 印刷用StringGrid描画
// *****************************
procedure TForm5.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
TempRect : TRect;
BoxRect : TRect;
uState : Cardinal;
sg : TStringGrid;
begin
sg := TStringGrid(Sender);
TempRect := Rect;
if (ARow > (sg.FixedRows - 1)) and (ACol = 1) then begin
// 背景を消す
sg.Canvas.FillRect(Rect);
//チェックボックスのサイズを設定
BoxRect.Left := Rect.Left + 5;
BoxRect.Top := Rect.Top + 3;
BoxRect.Bottom := Rect.Bottom - 3;
BoxRect.Right := BoxRect.Left + (BoxRect.Bottom - BoxRect.Top);
Rect.Right := Rect.Bottom - Rect.Top;
TempRect.Left := TempRect.Left + (BoxRect.Right - BoxRect.Left) + 8;
TempRect.Top := TempRect.Top + 3;
//Objectsプロパティの値に応じてチェック状態を描画
if Bool(sg.Objects[ACol, ARow]) then begin
sg.Canvas.Font.Color := clWindowText;
uState := DFCS_BUTTONCHECK or DFCS_CHECKED;
end else begin
sg.Canvas.Font.Color := clRed;
uState := DFCS_BUTTONCHECK;
end;
DrawText(sg.Canvas.Handle,
PChar(sg.Cells[ACol,ARow]), - 1, TempRect, DT_LEFT or DT_SINGLELINE);
DrawFrameControl(sg.Canvas.Handle, BoxRect, DFC_BUTTON, uState);
end;
end;
// *****************************
// 印刷用StringGrid キー操作
// *****************************
procedure TForm5.StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
AColLeft : Integer;
ARowTop : Integer;
ARowBottom : Integer;
i : Integer;
ABool : Boolean;
sg : TStringGrid;
begin
sg := TStringGrid(Sender);
with sg do begin
if Key = VK_SPACE then begin
//選択中のセルの範囲を調査
AColLeft := Selection.Left;
ARowTop := Selection.Top;
ARowBottom := Selection.Bottom;
//複数行選択に対応
if AColLeft = 1 then begin
for i := ARowTop to ARowBottom do begin
if Cells[AColLeft, i] <> '' then begin
ABool := Bool(Objects[AColLeft, i]);
Objects[AColLeft, i] := TObject(not ABool);
end;
end;
DispCheckedCount;
end;
end;
end;
end;
// *****************************
// 印刷用StringGrid マウス操作
// *****************************
procedure TForm5.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
ACol : Integer;
ARow : Integer;
ABool : Boolean;
sg : TStringGrid;
begin
sg := TStringGrid(Sender);
with sg do begin
if Button = mbLeft then begin
MouseToCell(X, Y, ACol, ARow);
// ダブルクリックのために記憶
MbRow := ARow;
MbCol := ACol;
if (ARow > (FixedRows - 1)) and (ACol = 1) then begin
if Cells[ACol,ARow] <> '' then begin
ABool := Bool(Objects[ACol, ARow]);
Objects[ACol, ARow] := TObject(not ABool);
DispCheckedCount;
end;
end;
end;
end;
end;
end.