DcadCapture ver.2015.5.3 for DraftSight 2015 / ARES Commander 2015
※ARES は廉価版でも COM API (ActiveX) が使えます。そちらを使ったほうがスマートです。
Bricscad 用のキャプチャーソフトを DraftSight / ARES 用に改造してみました。
キャプチャーした図面イメージをダブルクリックすると、CADの図面が切り替わります。
フォームの大きさは、自由に変更できます。
・コマンドラインに文字列を流し込む方法なので、タイミングが合わない場合があります。
・クリップボードを使用してコマンド履歴を取得しているため、操作後は、クリップボードに文字列が残ります。
・図面の切り替えは、メニューを操作しています。
取得した時の図面数と、「メニュー」 - 「ウィンドウ」の図面数が合わない場合は、「閉じる」、「すべて閉じる」が選択される可能性があります。
※ARES では、「Classic Default」 表示にしておいて下さい。
・高解像度のPCでは、キャプチャー位置が合わないときがあります。DcadCapture.exe のプロパティーから、「高解像度DPI...」にチェックを付けて下さい。
・各所にタイミングをとるためのタイマーを入れているため、取得にかなり時間がかかります。
( 2015/5/3 :若干改善しました。23図面 130sec -> 45sec)
■履歴
2015/04/22
・初版作成
2015/04/28
・シート番号、またはページ番号を取得するを追加
・マウス右クリックのポップアップメニューに「再キャプチャ」を追加
2015/04/28(2回目)
・システム変数の取得を、属性と同様にDXFファイルから取得に変更。若干高速にした。
2015/05/03
・コマンド送信で、[Enter]、[ESC] の送信を追加。
・不要なタイミングタイマーを極力省いた。
■Draftsight 2015
■ARES Commander 2015
■ダウンロード
DcadCapture.zip (2015/05/03 EXE本体のみ)
■ソースコード
unit DcadCaptureUnit; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,{BricscadApp_TLB, BricscadDb_TLB,} Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Grids, ComObj, IniFiles, Vcl.Buttons, Vcl.Menus, ClipBrd ; type TDwgDoc = record Index : integer; Name : string; Comment : string; end; type TForm2 = class(TForm) DrawGrid1: TDrawGrid; Panel1: TPanel; ComboBox1: TComboBox; SpeedButton1: TSpeedButton; PopupMenu1: TPopupMenu; N3: TMenuItem; N1: TMenuItem; N2: TMenuItem; SpeedButton2: TSpeedButton; SpeedButton3: TSpeedButton; N4: TMenuItem; N5: TMenuItem; Edit1: TEdit; SpeedButton4: TSpeedButton; procedure FormDestroy(Sender: TObject); procedure DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure FormResize(Sender: TObject); procedure DrawGrid1DblClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ComboBox1Change(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure N2Click(Sender: TObject); procedure SpeedButton2Click(Sender: TObject); procedure SpeedButton3Click(Sender: TObject); procedure DrawGrid1Click(Sender: TObject); procedure DrawGrid1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure N5Click(Sender: TObject); procedure SpeedButton4Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } // 取得するブロック名と属性名 BlkName, BlkName1, BlkName2, AttName, AttName1, AttName2 : string; AttFlag1, AttFlag2 : boolean; // 連続実行するLISP LspFileName : TFileName; LspCmdName : string; LspCommand : string; MoveX, MoveY : integer; end; var Form2: TForm2; // キャプチャしたビットマップを保持 BmpAry : array of TBitMap; // 図面名とその位置を保持 DwgDocAry : array of TDwgDoc; // ビットマップの大きさ BmpW, BmpH : integer; // タイトル表示の高さ TitleH1, TitleH2 : integer; // シート名、ページ番号を表示する CmtDispFlag : boolean; // キャプチャ時、属性を取得 CmtGetFlag : boolean; BcadActiveFlag : boolean; // メインウィンドウ DcadMainWinHandle : HWND; DcadMDIClientWinHandle : HWND; DcadCommandWinHandle : HWND; DcadInputWinHandle : HWND; DcadOutputWinHandle : HWND; DcadMDIActiveWinHandle : HWND; DcadMDIChildWinHandle : HWND; DCadProcessID : DWORD; //プロセスID implementation {$R *.dfm} uses DcadCaptureCfgUnit; //**************************************** // 最後の指定文字列より後を得る //**************************************** 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; //**************************************** // 最後の指定文字列より後を得る //**************************************** function LastStrAfter(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; //****************************************** // ウィンドウのタイトル(キャプション)を得る //****************************************** 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 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; // ************************************ // 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ウィンドウ取得 // 実際には、Windowsの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; // ************************************ // コマンドラインウィンドウを取得 // ************************************ 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 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 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; // ************************************ // CAD をアクティブに // ************************************ function SetDcadActive:boolean; begin Result := False; GetDCadMainWinHandle; if IsWindow(DcadMainWinHandle) then begin SetForegroundWindow(DcadMainWinHandle); Result := True; end; end; //**************************************** // 画面の指定位置を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; // ******************************* // DwgDocAryをソート // ******************************* procedure SortDwgDocAry; var len, n, m : integer; i, j: integer; DwgDocTmp : TDwgDoc; s, s1 : string; begin n := Length(DwgDocAry); if n > 1 then begin // コメント文字列の最大文字数 len := 0; for i := 0 to n -1 do begin m := DwgDocAry[i].Comment.Length; if len < m then len := m; end; // 文字列比較のため同じ長さにする for i := 0 to n -1 do begin with DwgDocAry[i] do begin m := Comment.Length; if m < len then begin for j := 1 to len - m do begin Comment:= ' ' + Comment; end; end; end; end; // ソート for i := 0 to n - 2 do begin s := DwgDocAry[i].Comment + ':' + DwgDocAry[i].Name; for j := i + 1 to n - 1 do begin s1 := DwgDocAry[j].Comment + ':' + DwgDocAry[j].Name; if s1 < s then begin DwgDocTmp := DwgDocAry[i]; DwgDocAry[i] := DwgDocAry[j]; DwgDocAry[j] := DwgDocTmp; s := s1; end; end; end; end; end; // ************************************ // DrawGrid 同期 // ************************************ procedure TForm2.ComboBox1Change(Sender: TObject); var idx : integer; i : integer; begin with ComboBox1 do begin idx := ItemIndex; if idx >= 0 then i := Integer(Items.Objects[idx]) else i := -1; end; if (i >= 0) and (i < Length(DwgDocAry)) then begin with DrawGrid1 do begin Col := i mod ColCount; Row := i div ColCount; end; end; end; // ************************************ // コンボボックスを同期 // ************************************ procedure TForm2.DrawGrid1Click(Sender: TObject); var i : integer; begin with DrawGrid1 do i := Row * ColCount + col; ComboBox1.ItemIndex := i; end; // ************************************ // 図面切り替え // ************************************ procedure TForm2.DrawGrid1DblClick(Sender: TObject); var i, id, j : integer; begin with DrawGrid1 do begin i := Row * ColCount + col; if (i >= 0) and (i < Length(DwgDocAry)) then begin id := DwgDocAry[i].Index; if GetDCadMainWinHandle = 0 then Exit; 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 id + 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); ComboBox1.ItemIndex := i; //if BcadActiveFlag then // SetForegroundWindow(DcadMainWinHandle); end; end; //if not BcadActiveFlag then // SetForegroundWindow(Handle); end; // ************************** // キャプチャ画像を描画 // ************************** procedure TForm2.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var i, w, h, dx, dy : integer; idx : integer; begin with DrawGrid1 do begin // 現在の表示位置 i := ARow * ColCount + Acol; idx := -1; if (i >= 0) and (i < Length(DwgDocAry)) then idx := DwgDocAry[i].Index; if (idx >= 0) and (idx < Length(BmpAry)) then begin w := BmpAry[idx].Width; h := BmpAry[idx].Height; dx := (DefaultColWidth - w) div 2; if not CmtDispFlag then dy := (DefaultRowHeight - h - TitleH1) div 2 else dy := (DefaultRowHeight - h - TitleH2) div 2; with Canvas do begin if not CmtDispFlag then Draw(Rect.Left + dx, Rect.Top + dy + TitleH1, BmpAry[idx]) else Draw(Rect.Left+dx,Rect.Top+dy + TitleH2, BmpAry[idx]); // 背景を塗りつぶし if (ARow = Row) and (ACol = Col) then Brush.Color := clBlue else Brush.Color := clGray; if not CmtDispFlag then Rectangle(Rect.Left + 1, Rect.Top + 1, Rect.Right - 1, Rect.Top + TitleH1 + 1) else Rectangle(Rect.Left + 1, Rect.Top + 1, Rect.Right - 1, Rect.Top + TitleH2 + 1); Font.Color := clWHITE; // タイトルを描画 TextOut(Rect.Left + 3, Rect.Top + 3, ExtractFileName(DwgDocAry[i].Name)); // コメントを描画 if CmtDispFlag then TextOut(Rect.Left + 3, Rect.Top + 3 + TitleH1 + 1, DwgDocAry[i].Comment); // 標準の設定に戻す Pen.Style := psSolid; Brush.Style := bsClear; Pen.Color := clGray; Pen.Width := 1; Rectangle(Rect); end; end else begin with Canvas do begin Brush.Color := clWhite; FillRect(Rect); end; end; end; end; // ************************************ // マウス座標を保持 // ************************************ procedure TForm2.DrawGrid1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin MoveX := X; MoveY := Y; end; // ************************************ // フォーム生成 // ************************************ procedure TForm2.FormCreate(Sender: TObject); var ini : TIniFile; begin SetLength(BmpAry, 0); SetLength(DwgDocAry, 0); BmpH := 168; BmpW := 240; TitleH1 := 20; TitleH2 := 42; with DrawGrid1 do begin DefaultColWidth := BmpW; DefaultRowHeight := BmpH + 20; Options := Options + [goThumbTracking]; end; BlkName := 'TITLE'; AttName := 'ZSHEET'; BlkName1 := BlkName; AttName1 := AttName; BlkName2 := BlkName; AttName2 := AttName; AttFlag1 := True; AttFlag2 := False; // ダブルクリックで Bricscad をアクティブに BcadActiveFlag := False; // コメント表示 CmtDispFlag := False; // キャプチャ時、コメントを取得 CmtGetFlag := True; LspFileName := ''; LspCmdName := ''; LspCommand := ''; ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); try with Ini do begin Top := ReadInteger('Form', 'Top', Top); Left := ReadInteger('Form', 'Left', Left); Width:= ReadInteger('Form', 'Width', Width); Height := ReadInteger('Form', 'Height', Height); if Left >= Screen.Width then Left := (Screen.Width + Width) div 2; if Top >= Screen.Height then Top := (Screen.Height + Height) div 2; BlkName1 := ReadString('Dcad', 'BlkName1', BlkName1); BlkName2 := ReadString('Dcad', 'BlkName2', BlkName2); AttName1 := ReadString('Dcad', 'AttName1', AttName1); AttName2 := ReadString('Dcad', 'AttName2', AttName2); AttFlag1 := ReadBool('Dcad', 'AttFlag1', AttFlag1); AttFlag2 := ReadBool('Dcad', 'AttFlag2', AttFlag2); BcadActiveFlag := ReadBool('Dcad', 'ActiveFlag', BcadActiveFlag); CmtDispFlag := ReadBool('DcadCapt', 'CmtDispFlag', CmtDispFlag); CmtGetFlag := ReadBool('DcadCapt', 'CmtGetFlag', CmtGetFlag); LspFileName := ReadString('Dcad', 'LispFileName', LspFileName); LspCmdName := ReadString('Dcad', 'LispCmdName', LspCmdName); LspCommand := ReadString('Dcad', 'LispCommand', LspCommand); // メニュー N2.Caption := LspCmdName; SpeedButton2.Caption := LspCmdName; end; finally ini.Free; end; end; // ************************************ // フォーム破棄 // ************************************ procedure TForm2.FormDestroy(Sender: TObject); var i : integer; ini : TIniFile; begin if Length(BmpAry) > 0 then begin for i := 0 to Length(BmpAry) -1 do BmpAry[i].Free; end; ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); try with Ini do begin WriteInteger('Form', 'Top', Top); WriteInteger('Form', 'Left', Left); WriteInteger('Form', 'Width', Width); WriteInteger('Form', 'Height', Height); WriteString('Dcad', 'BlkName1', BlkName1); WriteString('Dcad', 'BlkName2', BlkName2); WriteString('Dcad', 'AttName1', AttName1); WriteString('Dcad', 'AttName2', AttName2); WriteBool('Dcad', 'AttFlag1', AttFlag1); WriteBool('Dcad', 'AttFlag2', AttFlag2); WriteBool('Dcad', 'ActiveFlag', BcadActiveFlag); WriteBool('DcadCapt', 'CmtDispFlag', CmtDispFlag); WriteBool('DcadCapt', 'CmtGetFlag', CmtGetFlag); WriteString('Dcad', 'LispFileName', LspFileName); WriteString('Dcad', 'LispCmdName', LspCmdName); WriteString('Dcad', 'LispCommand', LspCommand); end; finally ini.Free; end; end; // *************************** // フォームリサイズ // *************************** procedure TForm2.FormResize(Sender: TObject); var n, xcnt, ycnt:Integer; begin n := Length(BmpAry); if n > 0 then begin with DrawGrid1 do begin xcnt := (Width - 23) div DefaultColWidth; if xcnt=0 then xcnt:=1; ycnt := n div xcnt; if n mod xcnt > 0 then Inc(ycnt); ColCount := xcnt; RowCount := ycnt; end; end; end; procedure TForm2.N2Click(Sender: TObject); begin end; // ************************************ // 設定フォーム // ************************************ procedure TForm2.N3Click(Sender: TObject); begin Form3 := TForm3.Create(Form2); with Form3 do begin try Edit1.Text := BlkName1; Edit2.Text := AttName1; Edit3.Text := BlkName2; Edit4.Text := AttName2; Edit5.Text := BmpW.ToString; Edit6.Text := BmpH.ToString; Edit7.Text := TitleH1.ToString; Edit8.Text := TitleH2.ToString; CheckBox1.Checked := AttFlag1; CheckBox2.Checked := AttFlag2; CheckBox4.Checked := BcadActiveFlag; CheckBox3.Checked := CmtGetFlag; CheckBox5.Checked := CmtDispFlag; Edit9.Text := LspFileName; Edit10.Text := LspCommand; Edit11.Text := LspCmdName; if ShowModal = mrOk then begin BlkName1 := Edit1.Text; AttName1 := Edit2.Text; BlkName2 := Edit3.Text; AttName2 := Edit4.Text; BmpW := StrToIntDef(Edit5.Text, BmpW); BmpH := StrToIntDef(Edit6.Text, BmpH); TitleH1 := StrToIntDef(Edit7.Text, TitleH1); TitleH2 := StrToIntDef(Edit8.Text, TitleH2); AttFlag1 := CheckBox1.Checked; if AttFlag1 and (BlkName1 <> '') and (AttName1 <> '') then begin BlkName := BlkName1; AttName := AttName1; end; AttFlag2 := CheckBox2.Checked; if AttFlag2 and (BlkName2 <> '') and (AttName2 <> '') then begin BlkName := BlkName2; AttName := AttName2; end; BcadActiveFlag := CheckBox4.Checked; CmtGetFlag := CheckBox3.Checked; CmtDispFlag := CheckBox5.Checked; LspFileName := Edit9.Text; LspCommand := Edit10.Text; LspCmdName := Edit11.Text; // メニュー N2.Caption := LspCmdName; SpeedButton2.Caption := LspCmdName; end; finally Free; end; end; end; // ************************************ // DXFファイルからシステム変数(2D座標)を取得する // ************************************ function ReadDxfVariablePoint2D(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(#3'FILEDIA'#13'0'#13); Sleep(10); SendDcadCommand('DXFOUT'#13 + fname + #13'Vesion'#13'R18'#13'16'#13); 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 TForm2.N5Click(Sender: TObject); var i, idx, j : integer; ACol, ARow :integer; s, s1 : string; n : integer; scrW, scrH : Integer; ARect : TREct; ALeft, ATop : integer; scale : Double; APoint : TPoint; begin with DrawGrid1 do begin // マウス座標をCol,Rowに MouseToCell(MoveX, MoveY, ACol, ARow); Row := ARow; Col := ACol; i := Row * ColCount + Col; if (i >= 0) and (i < Length(DwgDocAry)) then begin idx := DwgDocAry[i].Index; if GetDCadMainWinHandle = 0 then Exit; // MDI のウィンドウを探す GetDcadMDIClientHandle; 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); ComboBox1.ItemIndex := i; Sleep(500); // ウィンドウの位置と大きさを取得 GetWindowRect(DcadMDIClientWinHandle, ARect); // グラフィックウィンドウの左上座標 ALeft := ARect.Left; ATop := ARect.Top; // cad からグラフィック画面のサイズを取得 s := GetDcadVariable('SCREENSIZE'); n := Pos(',', s); scrW := Trunc(StrToFloatDef(Copy(s, 1, n -1), 0)); scrH := Trunc(StrToFloatDef(Copy(s, n + 1 ), 0)); // システム変数取得失敗であれば、終了 if (scrW = 0) or (scrH = 0) then Exit; // 高解像度DPI対策 ALeft := Trunc(ALeft * scrW / (ARect.Right - ARect.Left)); ATop := Trunc(ATop * scrH / (ARect.Bottom - ARect.Top)); // キャプチャするビットマップの大きさに縮小する尺度 if BmpH / BmpW < scrH / scrW then scale := BmpW / scrW else scale := BmpH / scrH; // SetCursorPos(ALeft + 1, ATop + 1); // 図面範囲でズーム s1 := GetDcadVariable('LIMMAX'); s := GetDcadVariable('LIMMIN'); if (s <> '') and (s1 <> '') then begin SendDcadCommand('ZOOM'#13 + s + #13 + s1 + #13); end else begin SendDcadCommand('ZOOM'#13'Fit'#13); end; Sleep(200); SendDcadCommand('ZOOM'#13 + Format('%.3f', [scale]) + 'X'#13); // 描画待ち Sleep(500); if Length(BmpAry) > idx then begin // キャプチャ CaptureToBmp( ALeft + (scrW - BmpW) div 2, ATop + (scrH - BmpH) div 2, BmpAry[idx].Width, BmpAry[idx].Height, BmpAry[idx]); end; // 直前の画面表示に戻す SendDcadCommand('ZOOM'#13'P'#13); // マウスカーソルを戻す APoint.X := MoveX; APoint.Y := MoveY; APoint := ClientToScreen(APoint); SetCursorPos(APoint.X, APoint.Y); Repaint; end; end; end; // *********************************** // 画面キャプチャ // *********************************** procedure TForm2.SpeedButton1Click(Sender: TObject); var limmax, limmin : OleVariant; scrH, scrW : integer; ARect : TRect; ALeft, ATop, AWidth, AHeight : integer; i : integer; scale : double; h, hdwg : HWND; dwgTitle, ext : string; cnt : integer; s, s1 : string; n, j :integer; Tics : Cardinal; sl : TStringList; Title : string; count : integer; begin Tics := GetTickCount; // メインウィンドウのハンドルを取得 if GetDCadMainWinHandle = 0 then Exit; // 最小化されていれば戻す if isIconic(DcadMainWinHandle) then begin OpenIcon(DcadMainWinHandle); Sleep(100); 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; // ウィンドウの位置と大きさを取得 GetWindowRect(DcadMDIClientWinHandle, ARect); // グラフィックウィンドウの左上座標 ALeft := ARect.Left; ATop := ARect.Top; SetCursorPos(ALeft + 1, ATop + 1); AWidth := ARect.Right - ARect.Left; AHeight := ARect.Bottom - ARect.Top; // Draftsight からグラフィック画面のサイズを取得 s := GetDcadVariable('SCREENSIZE'); n := Pos(',', s); scrW := Trunc(StrToFloatDef(Copy(s, 1, n -1), 0)); scrH := Trunc(StrToFloatDef(Copy(s, n + 1), 0)); // 高解像度DPI対策 ALeft := Trunc(ALeft * scrW / AWidth); ATop := Trunc(ATop * scrH / AHeight); // キャプチャするビットマップの大きさに縮小 if BmpH / BmpW < scrH / scrW then scale := BmpW / scrW else scale := BmpH / scrH; // 自フォームを最小に //WindowState := wsMinimized; //Sleep(100); // すでにBitmap が作成されているときは、破棄 if Length(BmpAry) > 0 then begin for i := 0 to Length(BmpAry) -1 do BmpAry[i].Free; end; SetLength(BmpAry, cnt); SetLength(DwgDocAry, cnt); with DrawGrid1 do begin // 適当な大きさを確保 RowCount := cnt div ColCount; if cnt mod ColCount > 0 then RowCount := RowCount + 1; end; SetForegroundWindow(DcadMainWinHandle); sl := TStringList.Create; try Title := ''; // メニューを操作 for i := 0 to cnt - 1 do begin 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; // 配列に格納 with DwgDocAry[i] do begin Index := i; Name := StrAfterStrBefore('[', ']', s); end; if SaveDxfSL(sl) then begin // シート番号、またはページ番号を取得 s := ReadDxfAttRib(sl, BlkName, AttName); DwgDocAry[i].Comment := s; s := ReadDxfVariablePoint2D(sl, 'LIMMAX'); s1 := ReadDxfVariablePoint2D(sl, 'LIMMIN'); SendDcadCommand('ZOOM'#13 + s + #13 + s1 + #13); end else begin SendDcadCommand('ZOOM'#13'F'#13); DwgDocAry[i].Comment := ''; end; SendDcadCommand('ZOOM'#13 + Format('%.3f', [scale]) + 'X'#13); Sleep(200); // キャプチャ用ビットマップを作成 BmpAry[i] := TBitmap.Create; BmpAry[i].PixelFormat := pf32bit; // ビットマップの大きさ BmpAry[i].Width := BmpW; BmpAry[i].Height := BmpH; // キャプチャ CaptureToBmp( ALeft + (scrW - BmpW) div 2, ATop + (scrH - BmpH) div 2, BmpAry[i].Width, BmpAry[i].Height, BmpAry[i]); SendDcadCommand('ZOOM'#13'P'#13); Sleep(200); end; finally sl.Free; end; // シート番号、ページ番号順にソート SortDwgDocAry; with ComboBox1 do begin Items.Clear; Sorted := False; for i := 0 to Length(DwgDocAry) - 1 do Items.AddObject(DwgDocAry[i].Comment +':'+ DwgDocAry[i].Name , TObject(i)); end; FormResize(self); ComboBox1Change(self); // 自フォームを戻す //WindowState := wsNormal; // 自フォームをアクティブに SetForegroundWindow(Handle); ShowMessage('終了しました。'+#13#10 + Format('%.1f',[(GetTickCount - Tics) / 1000]) + '秒'); end; procedure TForm2.SpeedButton2Click(Sender: TObject); begin // コマンド実行 N2Click(self); end; procedure TForm2.SpeedButton3Click(Sender: TObject); begin // 設定 N3Click(self); end; procedure TForm2.SpeedButton4Click(Sender: TObject); var s:string; begin s := GetDcadVariable(Edit1.Text); ShowMessage(s); end; end.