Bricacad VB.NET 画面キャプチャサンプル BCapt.dll
■概要
Bricscad .NET 本来の機能で、密かにスナップショットを作成しようと、いろいろやってみたのですが、よく分かりませんでした。
結局、他の外部アプリと同じ手法「スクリーンキャプチャ」を使っています。
表示させている画像は1個だけすが、マウススクロールで切り替わります。
(実際には、コンボボックスをアクティブにして、それが切り替わっています。)
フォームは、モードレス表示です。
どこかで、Bitmapの破棄が必要なのだと思います。
シート番号(図枠ブロックの属性)順にソートされて表示されます。
画像をダブルクリックすると、アクティブな図面が切り替わります。
' system Imports System.Text Imports System.Runtime.InteropServices Imports System.IO ' ODA Imports Teigha.Runtime Imports Teigha.DatabaseServices Imports Teigha.Geometry Imports Teigha.GraphicsSystem ' Bricsys Imports Bricscad.ApplicationServices Imports Bricscad.Runtime Imports Bricscad.EditorInput ' alias Imports _AcRx = Teigha.Runtime Imports _AcAp = Bricscad.ApplicationServices Imports _AcDb = Teigha.DatabaseServices Imports _AcGe = Teigha.Geometry Imports _AcEd = Bricscad.EditorInput Imports _AcGi = Teigha.GraphicsInterface Imports _AcClr = Teigha.Colors Imports _AcWnd = Bricscad.Windows Imports Bricscad.PlottingServices Public Class Commands <CommandMethod("BCapt", CommandFlags.Modal)> _ Public Shared Sub CmdBCapt() '' ウィンドウのが存在を確認 Dim hWnd As New IntPtr(0) hWnd = Form1.FindWindow(Nothing, "BCapt") '' ウィンドウが存在しない If hWnd.Equals(IntPtr.Zero) Then Dim frm As Form1 = New Form1 '' モードレス表示 Application.ShowModelessDialog(frm) '' ここでは破棄しない ''frm.Dispose() End If End Sub End Class
' system Imports System.Text Imports System.Runtime.InteropServices Imports System.IO Imports System.Drawing Imports System.Windows.Forms ' ODA Imports Teigha.Runtime Imports Teigha.DatabaseServices Imports Teigha.Geometry Imports Teigha.GraphicsSystem ' Bricsys Imports Bricscad.ApplicationServices Imports Bricscad.Runtime Imports Bricscad.EditorInput ' com Imports BricscadDb Imports BricscadApp ' alias Imports _AcRx = Teigha.Runtime Imports _AcAp = Bricscad.ApplicationServices Imports _AcDb = Teigha.DatabaseServices Imports _AcGe = Teigha.Geometry Imports _AcEd = Bricscad.EditorInput Imports _AcGi = Teigha.GraphicsInterface Imports _AcClr = Teigha.Colors Imports _AcWnd = Bricscad.Windows Imports Bricscad.PlottingServices Public Class Form1 '' データ保持用構造体 Structure DwgDoc Dim DwgName As String Dim DwgPrefix As String Dim DocIndex As Integer Dim DimScale As Double Dim SheetNo As String Dim PageNo As String Dim Bmp As Drawing.Bitmap End Structure '' 動的配列 Public Shared DwgDocs() As DwgDoc Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Left = Screen.PrimaryScreen.WorkingArea.Width - Me.Width Me.Top = Screen.PrimaryScreen.WorkingArea.Height - Me.Height 'If MessageBox.Show("キャプチャを開始しますか?", _ ' "BCapt", _ ' MessageBoxButtons.YesNo, _ ' MessageBoxIcon.Information, _ ' MessageBoxDefaultButton.Button1) = DialogResult.Yes Then ' System.Threading.Thread.Sleep(100) ' Button1.PerformClick() 'End If End Sub <StructLayout(LayoutKind.Sequential)> _ Private Structure RECT Public left As Integer Public top As Integer Public right As Integer Public bottom As Integer End Structure <DllImport("user32.dll")> _ Private Shared Function GetWindowRect(ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer End Function Enum GetWindow_Cmd : uint GW_HWNDFIRST = 0 GW_HWNDLAST = 1 GW_HWNDNEXT = 2 GW_HWNDPREV = 3 GW_OWNER = 4 GW_CHILD = 5 GW_ENABLEDPOPUP = 6 End Enum <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Public Shared Function GetWindow(ByVal hWnd As IntPtr, ByVal uCmd As UInt32) As IntPtr End Function <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Public Shared Function FindWindow( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As IntPtr End Function <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Public Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _ ByVal childAfter As IntPtr, _ ByVal lclassName As String, _ ByVal windowTitle As String) As IntPtr End Function <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Public Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Public Shared Function GetClassName(ByVal hWnd As System.IntPtr, _ ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer End Function Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed '' ここで破棄 Me.Dispose() End Sub '' 図枠ブロックの属性を取得 Public Sub GetAttString(ByRef doc As AcadDocument, ByVal BlkName As String, _ ByVal TagName1 As String, ByVal TagName2 As String, _ ByRef AttString1 As String, ByRef AttString2 As String) Dim Flag1 As Boolean = False Dim Flag2 As Boolean = False Dim mspc As AcadModelSpace = doc.ModelSpace If mspc.Count > 0 Then For j As Integer = 0 To mspc.Count - 1 Dim ent As AcadEntity = mspc.Item(j) If "AcDbBlockReference" = ent.EntityName Then Dim blkref As AcadBlockReference = ent If blkref.HasAttributes Then If BlkName = blkref.Name Then Dim attr As Object = blkref.GetAttributes For k As Integer = LBound(attr, 1) To UBound(attr, 1) Dim att As AcadAttributeReference = attr(k) If TagName1 = att.TagString Then AttString1 = att.TextString Flag1 = True End If If TagName2 = att.TagString Then AttString2 = att.TextString Flag2 = True End If If Flag1 And Flag2 Then Exit For Next End If End If End If If Flag1 And Flag2 Then Exit For Next End If End Sub '' 取得した情報をシート番号順にソート Public Shared Sub SortDwgDocsSheetNo(pageSort As Boolean) Dim temp As DwgDoc Dim s As String Dim s1 As String Dim n As Integer = 0 For i As Integer = 0 To UBound(DwgDocs) If pageSort Then If n < DwgDocs(i).PageNo.Length Then n = DwgDocs(i).PageNo.Length End If Next If UBound(DwgDocs) > 0 Then For i As Integer = 0 To UBound(DwgDocs) - 1 If pageSort Then s = Microsoft.VisualBasic.Right("0000" + DwgDocs(i).PageNo, n) Else s = DwgDocs(i).SheetNo End If For j As Integer = i + 1 To UBound(DwgDocs) If pageSort Then s1 = Microsoft.VisualBasic.Right("0000" + DwgDocs(j).PageNo, n) Else s1 = DwgDocs(j).SheetNo End If If s > s1 Then temp = DwgDocs(i) : DwgDocs(i) = DwgDocs(j) : DwgDocs(j) = temp s = s1 End If Next Next End If End Sub '' キャプチャボタン Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click Const bmpW As Integer = 240 Const bmpH As Integer = 170 ComboBox1.Items.Clear() Dim app As IAcadApplication = _AcAp.Application.AcadApplication Dim appDocs As IAcadDocuments = app.Documents Dim appDoc As IAcadDocument ReDim DwgDocs(appDocs.Count - 1) Dim stIndex As Integer = -1 For i As Integer = 0 To appDocs.Count - 1 If appDocs.Item(i).Active Then stIndex = i Exit For End If Next For i As Integer = 0 To appDocs.Count - 1 appDoc = appDocs.Item(i) appDoc.Activate() With DwgDocs(i) GetAttString(appDoc, "TITLE", "ZSHEET", "ZITEM9", .SheetNo, .PageNo) .DocIndex = i .DwgPrefix = appDoc.GetVariable("DWGPREFIX") .DwgName = appDoc.GetVariable("DWGNAME") End With Dim lmax(1) As Double lmax = appDoc.GetVariable("LIMMAX") Dim lmin(1) As Double lmin = appDoc.GetVariable("LIMMIN") Dim h As Integer = FindWindowEx(app.ActiveDocument.HWND, IntPtr.Zero, "AfxFrameOrView100u", "") If h <> 0 Then Dim rec As RECT GetWindowRect(h, rec) app.ZoomWindow(lmin, lmax) Dim recWidth As Integer = rec.right - rec.left Dim recHeight As Integer = rec.bottom - rec.top Dim scale As Double If bmpH / bmpW < recHeight / recWidth Then scale = bmpW / recWidth Else scale = bmpH / recHeight End If Dim gridMode As Integer = appDoc.GetVariable("GRIDMODE") Dim ucsICon As Integer = appDoc.GetVariable("UCSICON") If gridMode > 0 Then appDoc.SetVariable("GRIDMODE", 0) If ucsICon > 0 Then appDoc.SetVariable("UCSICON", 0) app.ZoomScaled(scale, AcZoomScaleType.acZoomScaledRelative) ''Bitmapの生成 Dim bmp As New Bitmap(bmpW, bmpH) ''Graphicsの作成 Dim gr As Graphics = Graphics.FromImage(bmp) '' グラフィック画面の中心キャプチャする gr.CopyFromScreen( New Point(rec.left + Int((recWidth - bmpW) / 2), rec.top + Int((recHeight - bmpH) / 2)), New Point(0, 0), bmp.Size) '' 破棄 gr.Dispose() DwgDocs(i).Bmp = New Bitmap(bmp) app.ZoomPrevious() If gridMode > 0 Then appDoc.SetVariable("GRIDMODE", gridMode) If ucsICon > 0 Then appDoc.SetVariable("UCSICON", ucsICon) End If Next appDoc = appDocs.Item(stIndex) appDoc.Activate() appDoc = Nothing appDocs = Nothing app = Nothing '' ソート SortDwgDocsSheetNo(False) '' コンボボックスにファイル名を追加 For i As Integer = 0 To UBound(DwgDocs) ComboBox1.Items.Add(DwgDocs(i).SheetNo + ":" + DwgDocs(i).DwgName) Next '' コンボボックスのインデックスを最初の図面にする For i As Integer = 0 To UBound(DwgDocs) If DwgDocs(i).DocIndex = stIndex Then ComboBox1.SelectedIndex = i Exit For End If Next 'System.Threading.Thread.Sleep(100) 'Me.Focus() '' フォーカスをコンボボックスに ComboBox1.Focus() End Sub '' ビットマップとファイル名を更新 Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged Dim idx As Integer = ComboBox1.SelectedIndex If idx >= 0 Then PictureBox1.Image = DwgDocs(idx).Bmp Label1.Text = DwgDocs(idx).DwgName End If End Sub Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click End Sub '' アクティブなドキュメントを切り替え Private Sub PictureBox1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDoubleClick Dim ret As Boolean = False Dim idx As Integer = ComboBox1.SelectedIndex If idx >= 0 Then Dim app As IAcadApplication = _AcAp.Application.AcadApplication Dim appDocs As IAcadDocuments = app.Documents Dim appDoc As IAcadDocument For i As Integer = 0 To appDocs.Count - 1 appDoc = appDocs.Item(i) If (DwgDocs(idx).DwgPrefix = appDoc.GetVariable("DWGPREFIX")) And _ (DwgDocs(idx).DwgName = appDoc.GetVariable("DWGNAME")) Then appDoc.Activate() ret = True Exit For End If Next '' 取得時と同じファイル名が無い If Not ret Then MsgBox("DwgPrefix : " + DwgDocs(idx).DwgPrefix + vbCrLf + _ "DwgNme : " + DwgDocs(idx).DwgName + vbCrLf + "が、見つかりません.", MsgBoxStyle.OkOnly, "BCapt") End If End If End Sub End Class