TheSwamp
Code Red => .NET => Topic started by: Jeff H on September 15, 2010, 03:17:12 PM
-
I ran across this post
http://forums.augi.com/showthread.php?t=121671
Here is a quote from the famous Kerry Brown
I know this may sound like a really wild suggestion, but
why don't you ask the original poster at theSwamp ?
and perhaps thank him for posting the code at the same time.
Which was replied with
Boo...
Not to step on toes here but I'm kinda a one forum guy and I asked my original question here. The answers (at this forum) might actually help others (at this forum) instead of some sort of endless link after link into another forum... and then into another. I REALLY DO appreciate the link to the swamp's forum solution and the original poster at that forum, but the personal experience and knowledge of mjohnston.26901 might take me a bit further into my question and solution with his/her personal take on the code and not to mention in the wake of all this... stuff... might help others... here, at this forum, the forum I signed up for and goto the most.
So naturally I had a little free time and simple thing to do so I wrote a VB.NET App and will post it here
If you appoligize to Kerry I will add the code to double click the Picture box and bring all entites from the drawing into the current dwg
or layouts or plotSettings or whatever
Also it was written VS2010 I will convert it VS2008 if you need it.
-
Don't bother converting it. I agree with Kerry wholeheartedly. His suggestion was valid and went straight over their ungrateful heads. Let 'em rot.
Another Useless Group of Individuals.
-
Another Useless Group of Individuals.
:lol:
-
I do not speak English and maybe I'm wrong or not understand the issue.
But if you need to read the preview image without using AutoCAD you can use this:
(Also works with 32-bit images (Yes, thumbnail may be 32-bit), 100% dotNet)
Imports System
Imports System.Drawing
Imports System.IO
Friend NotInheritable Class ThumbnailReader
<System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _
Private Structure tagBITMAPFILEHEADER
Public bfType As UShort
Public bfSize As UInteger
Public bfReserved1 As UShort
Public bfReserved2 As UShort
Public bfOffBits As UInteger
End Structure
Friend Shared Function GetThumbnail(ByVal filename As String) As Bitmap
Using fs As FileStream = File.OpenRead(filename)
Using br As BinaryReader = New BinaryReader(fs)
Dim datLoc As Integer
Dim bytCnt As Byte
' TODO
' Modificar para leer directamente el centinela
fs.Seek(13, SeekOrigin.Begin)
datLoc = br.ReadInt32()
datLoc += 20
fs.Seek(datLoc, SeekOrigin.Begin)
bytCnt = br.ReadByte()
If bytCnt <= 1 Then
Return Nothing
End If
Dim imgHeaderStart As Int32
Dim imgHeaderSize As Int32
Dim imgCode As Byte
For i As Short = 1 To bytCnt
imgCode = br.ReadByte()
imgHeaderStart = br.ReadInt32()
imgHeaderSize = br.ReadInt32()
If imgCode = 2 Then
fs.Seek(imgHeaderStart, SeekOrigin.Begin)
'-----------------------------------------------------
' TODO
' Deberia comprobar si asi es mas rapido, o leer cada bloque uno a uno
Dim bmpHeader(40) As Byte
bmpHeader = br.ReadBytes(40)
Dim biBitCount As UShort = BitConverter.ToUInt16(New Byte() {bmpHeader(14), bmpHeader(15)}, 0)
Dim biSizeImage As UInteger = BitConverter.ToUInt16(New Byte() {bmpHeader(20), bmpHeader(21), bmpHeader(22), bmpHeader(23)}, 0)
'-----------------------------------------------------
fs.Seek(imgHeaderStart, SeekOrigin.Begin)
Dim bytBMPBuff(imgHeaderSize) As Byte
bytBMPBuff = br.ReadBytes(imgHeaderSize)
Dim clrTableSize As UInteger = CUInt(If(biBitCount < 9, 4 * (2 ^ biBitCount), 0))
Dim bfHeader As tagBITMAPFILEHEADER
With bfHeader
.bfType = &H4D42
.bfSize = CUInt(54) + clrTableSize + biSizeImage
.bfOffBits = CUInt(54) + clrTableSize
End With
Using ms As New MemoryStream
Using bw As BinaryWriter = New BinaryWriter(ms)
bw.Write(bfHeader.bfType)
bw.Write(bfHeader.bfSize)
bw.Write(bfHeader.bfReserved1)
bw.Write(bfHeader.bfReserved2)
bw.Write(bfHeader.bfOffBits)
bw.Write(bytBMPBuff)
Dim bm As Bitmap = New Bitmap(ms)
Return bm
End Using
End Using
ElseIf imgCode = 3 Then
Return Nothing
End If
Next
End Using
End Using
Return Nothing
End Function
End Class
-
I love it :evil:
-
I was just trying to help the guy out. AutoCAD .NET is not like C# or C++ or whatever where you can you walk in bookstore and find ten books or a huge amount resources online. You will learn something everywhere which brings me to this.
This is used to fill a ImageList for a ListView Control
Database db = new Database(false, false)
db.ReadDwgFile(filename, FileOpenMode.OpenForReadAndAllShare, false, null);
Bitmap bitmap = db.ThumbnailBitmap;
if (!(DetailsLargeImage.Images.ContainsKey(filename)))
{
DetailsLargeImage.Images.Add(filename, bitmap);
DetailsSmallImage.Images.Add(filename, bitmap);
}
This was to set the picture box Image and if I used FileOpenMode.OpenForReadAndAllShare like above I got an error
Dim fName As String = cboFileNmae.Text
Dim db As Database = New Database(False, False)
db.ReadDwgFile(fName, FileOpenMode.OpenForReadAndReadShare, False, "")
Dim tmbNail As Bitmap = db.ThumbnailBitmap
picBoxThumbnail.Image = tmbNail
I really do not see what the difference would be for setting a PictureBox image and filling a ImageList would be
Somehow a line got left out
-
fro,
I was not having a go at you by any means. It was great you brought up the post on AUGI.
-
jgr,
That's excellent!
-
fro,
I was not having a go at you by any means. It was great you brought up the post on AUGI.
Sorry I did not mean to imply that all
For future reference if I get out line or (I was going to say do something stupid but that is going happen alot) I hope you let me know
-
I really do not see what the difference would be for setting a PictureBox image and filling a ImageList would be
Are you sure?
Imagelist.imageSize is not as bitmap.width, bitmap.heigth
-
For future reference if I get out line or (I was going to say do something stupid but that is going happen alot) I hope you let me know
Join the club, I depend on Glenn and Kerry to keep me in line
-
I really do not see what the difference would be for setting a PictureBox image and filling a ImageList would be
Are you sure?
Imagelist.imageSize is not as bitmap.width, bitmap.heigth
First of all jgr excellent post I added a second picture box to the above app and added the line
picBoxJGR.Image = ThumbnailReader.GetThumbnail(fName)
And worked great I am curious which is faster will test later?
Here I go doing something stupid again making it more complicated than it is I was getting the error at db.ReadDwgFile
Which was before I even assign the bitmap or anything to do with ImageList or PictureBox
-
I'm reminded of my grandfather ..
"You can lead a horse to water but can't give it a map."
-
:oops: Now I understand. (I think)
My code is also based on acThumnailReader (vb6, forever!) + Open Design Specification for .dwg files
(acThumnailReader is based on activedwgpreview (vb6) ... this is based on...this....)
:oops: :oops: :oops: :angel:
Sorry, my code isbased on acBMPPreview (100% vb6). Not on "acThumnailReader"
-
I'm reminded of my grandfather ..
"You can lead a horse to water but can't give it a map."
Yours courteously,
etc...
:-D
-
It has been here the whole time
http://www.theswamp.org/index.php?topic=26621.15
-
It has been here the whole time
http://www.theswamp.org/index.php?topic=26621.15
Does not work with 32-bit images.
-
I think the blockIcon command generates 32x32x8bpp bitmaps, I was able to create them via AcGsDevice/ AcGsView && MFC.
http://www.theswamp.org/index.php?topic=33116.msg401299#msg401299
For .net have a look at Autodesk.AutoCAD.GraphicsSystem.GetSnapshot(Rectangle rectangle); You should be able to render the block and take a snapshot, I think you can do this via OffScreenDevice so you're not capturing off a control like I did
-
I use PreviewIcon with no problem
but this was a reply for CapturePreviewImage which broke in 2011 and the drawing does not have to be active
The behavior has been already reported. The current status for the Change Request is fixed and it should be available in the upcoming AutoCAD update.
As a workaround, The property Layout.Thumbnail should give you the layout/paper space thumbnail bitmap.
Or if you need a thumbnail of the model space you can use the code I provided in my initial reply.
-
DoH! sorry, my mistake, just ignore me :whistle:
-
This one brings up a dialog box though
<DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode)> _
Private Shared Function acedCommand(ByVal type1 As Integer, ByVal command As String, ByVal type2 As Integer, ByVal blockName As String, ByVal [end] As Integer) As Integer
If btr.PreviewIcon Is Nothing Then
acedCommand(5005, "BLOCKICON", 5005, blkName, 5000)
-
Did you figure out in .NET another way for blocks with out having to call BlockIcon
-
Not with .NET, but I assume you can use the classes within Autodesk.AutoCAD.GraphicsSystem to render, view, or get a snapshot of any entity(s) just as you can with the underlying AcGs classes.
-
That NameSpace does not like me every thing I played around with in it has crashed or just leaves a bunch of stuff all over the screen including code from ADN but I am pretty sure it has to do with I have no idea what I doing?
-
The Database.ThumbnailBitmap reads like 200 out of 200 iterating through a folder
This one read 0 out of a 200
[System.Security.SuppressUnmanagedCodeSecurity(), DllImport("acdb18.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acdbGetPreviewBitmap@@YAPEAUtagBITMAPINFO@@PEB_W@Z")]
private static extern IntPtr acdbGetPreviewBitmap([MarshalAs(UnmanagedType.LPWStr)] string sFilename);
System.Drawing.Bitmap GetBitmapFromDwg(string filename)
{
IntPtr bmpInfo = acdbGetPreviewBitmap(filename);
return Autodesk.AutoCAD.Runtime.Marshaler.BitmapInfoToBitmap(bmpInfo);
}
-
I'm a little confused are you trying to get the PreviewBitmap for the drawing or the PreviewIcon(still bitmaps) from the BlockTableRecord?
-
Sorry
There all thrown together
Basically I have no problems getting either a BlockTableRecord's or "drawings or layout's" bitmap's closed or open, but I have not found a stable method for generating one if it does not exist.
-
Simple, use the AcGsVew classes as I mentioned earlier
here is a snippit of a form, just use your block or any other entity
namespace ExecMethod
{
public partial class ViewFrm : Form
{
AcGs.Manager manager = null;
AcGs.Device device = null;
AcGs.Model model = null;
AcGs.View view = null;
public ViewFrm()
{
InitializeComponent();
manager = AcAp.Application.DocumentManager.MdiActiveDocument.GraphicsManager;
device = manager.CreateAutoCADDevice(this.Handle);
device.OnSize(new System.Drawing.Size(300, 300));
model = manager.CreateAutoCADModel();
// you can use your block ref for this
view = manager.CreateAutoCADView(new Line(new Point3d(0, 0, 0), new Point3d(300, 300, 0)));
device.Add(view);
view.ZoomExtents(new Point3d(0, 0, 0), new Point3d(300, 300, 0));
//Bitmap bmp = view.GetSnapshot(new System.Drawing.Size(300, 300)) <<<<<------------------------
}
private void ViewFrm_Paint(object sender, PaintEventArgs e)
{
view.Invalidate();
view.Update();
}
}
}
-
Finally I used that class without crashing
Once again Thank you
AHH!
It just crashed in the background
*EDIT*
After I close the form about 5 to 10 seconds later it crashes
*EDIT*
http://forums.autodesk.com/t5/AutoCAD-2007/Unhandled-Access-Violaton-Writing-0x0014-Exception-at-7788fc47h/td-p/2674073
Is the same error
It might be something with my system
Thanks again for the code
-
Sorry, it was only indented to give you an idea, you probably need to do a bit of disposing
-
It was not your code
There is something wrong with my system
I have contacted ADN about it
And they sent some code to try and it crashed
I need to get back with them on it
Thanks again that will become very useful just not on this computer
-
I get this when I call dispose...
private void ViewFrm_FormClosed(object sender, FormClosedEventArgs e)
{
view.EraseAll();
device.EraseAll();
manager.Dispose();
view.Dispose();
device.Dispose();
line.Dispose();
}
-
I tried manager.Dispose(); and same thing
Writing to Vitural Address error
To show your form are you using either
Application.ShowModelessDialog() or Application.ShowModalDialog();
Also what Command.Flags are you using for the command to open the form
In your command method what
thanks
-
just the default
[CommandMethod("doit")]
static public void test()
{
Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
AcDb.Database database = HostApplicationServices.WorkingDatabase;
try
{
ViewFrm frm = new ViewFrm();
AcAp.Application.ShowModalDialog(frm);
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.Message);
}
}
the C++ stuff works like a charm of course it's a bit harder to code