Answered by:
Dwg thumbnail in PictureBox [VB.NET 2010]

Question
-
Hi forum,
I'm creating a project retrieving data from a Access database and I want to show a thumbnail preview of my files in a PictureBox.
I generate the path to the dwg file to show by composing a string.
Based on the given dwg file (read string generated), I want to display a thumbnail image in a picturebox in my form.
I did find several ways to do it on the Net (using Shell API, external ocx files with dedicated controls, loading Autocad dlls, etc) , but I don't seem to get any of them to work. :(
Following the links of some of the solutions proposed on the Net
http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/af1cd802-c357-435b-8e5a-a8fcacd1c9d7/
http://www.vbaccelerator.com/home/net/code/libraries/shell_projects/Thumbnail_Extraction/article.asp
http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/1428326d-7950-42b4-ad94-8e962124043e/
http://www.theswamp.org/index.php?topic=30985.0
I read more carefully these two options:
http://msdn.microsoft.com/en-us/library/8t23aykb%28v=VS.100%29.aspx
http://forums.autodesk.com/t5/NET/Save-preview-to-file/td-p/1351977
I guess the first one is the easier way to accomplish the task, but I don't know if a method similar to the following exists for dwg files to extract the thumbnail.
myBitmap.GetThumbnailImage(40, 40, myCallback, IntPtr.Zero)
I tried to import several dlls in order to try all the solutions above but I'm afraid I'm overcomplicating the task.
I ask for the forum guys to enlighten me on this topic..it's driving me nuts..
thank you in advance for your support
P.
pp _______________ VB Express 2010Tuesday, April 12, 2011 9:52 PM
Answers
-
Hi fredpox,
Welcome to the MSDN Forum.
Here is a test code of retrieve the BMP data from a DWG file for your reference.
Imports System.Collections.Generic Imports System.ComponentModel Imports System.Data Imports System.Drawing Imports System.Text Imports System.Windows.Forms Imports System.IO Partial Public Class Form1 Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load Dim viewDwg As New ViewDWG() PictureBox1.Image = viewDwg.GetDwgImage("d:\s.dwg") End Sub Private Class ViewDWG Private Structure BITMAPFILEHEADER Public bfType As Short Public bfSize As Integer Public bfReserved1 As Short Public bfReserved2 As Short Public bfOffBits As Integer End Structure Public Function GetDwgImage(ByVal FileName As String) As Image If Not (File.Exists(FileName)) Then Throw New FileNotFoundException("the file didn't find") End If 'declare a filestream to read the DWG file Dim DwgF As FileStream 'the position of file description block Dim PosSentinel As Integer 'Binary Reader Dim br As BinaryReader 'the thumbnail farmat Dim TypePreview As Integer 'the thumbnail postion Dim PosBMP As Integer 'the thumbnail size Dim LenBMP As Integer 'the thumbnail depth Dim biBitCount As Short 'BMP file header,because DWG doesn't include the header,we need add it by ourself Dim biH As BITMAPFILEHEADER 'BMP file body in the DWG file Dim BMPInfo As Byte() 'to store the memory stream Dim BMPF As New MemoryStream() 'Binary Writer Dim bmpr As New BinaryWriter(BMPF) Dim myImg As Image = Nothing Try 'DWG file stream DwgF = New FileStream(FileName, FileMode.Open, FileAccess.Read) br = New BinaryReader(DwgF) 'read from the thirteenth byte DwgF.Seek(13, SeekOrigin.Begin) 'read the thumbnail description block position PosSentinel = br.ReadInt32() 'read from the thirty-first byte of the thumbnail description block DwgF.Seek(PosSentinel + 30, SeekOrigin.Begin) 'the thirty-first byte represent the thumbnail picture format, 2 means BMP, 3 means WMF TypePreview = br.ReadByte() If TypePreview = 1 Then ElseIf TypePreview = 2 OrElse TypePreview = 3 Then 'the BMP block postion saved by DWG file PosBMP = br.ReadInt32() 'the BMP block size LenBMP = br.ReadInt32() 'move to the BMP block DwgF.Seek(PosBMP + 14, SeekOrigin.Begin) 'read the btye depth biBitCount = br.ReadInt16() 'read all BMP content DwgF.Seek(PosBMP, SeekOrigin.Begin) 'the BMP with no header BMPInfo = br.ReadBytes(LenBMP) br.Close() DwgF.Close() biH.bfType = 19778 'build the header If biBitCount < 9 Then biH.bfSize = 54 + 4 * CInt(Math.Truncate(Math.Pow(2, biBitCount))) + LenBMP Else biH.bfSize = 54 + LenBMP End If 'reserved byte biH.bfReserved1 = 0 'reserved byte biH.bfReserved2 = 0 'BMP data offset 'write BMP header biH.bfOffBits = 14 + 40 + 1024 'file type bmpr.Write(biH.bfType) 'file size bmpr.Write(biH.bfSize) '0 bmpr.Write(biH.bfReserved1) '0 bmpr.Write(biH.bfReserved2) 'offset bmpr.Write(biH.bfOffBits) 'write BMP file bmpr.Write(BMPInfo) 'move the pointer to the beginning BMPF.Seek(0, SeekOrigin.Begin) 'create the BMP file myImg = Image.FromStream(BMPF) bmpr.Close() BMPF.Close() End If Return myImg Catch ex As Exception Throw New Exception(ex.Message) End Try End Function End Class End Class
I hope this will be helpful.
Best regards,
Mike Feng [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Thursday, April 14, 2011 11:42 AMModerator -
Hi Fredpox,
What do you mean "control the dimensions of the picture I get"? Do you mean "zoom in"? If so, the two links should be helpful to you:
http://social.msdn.microsoft.com/Forums/en-US/vbide/thread/625f8169-4cfb-4b16-a4ba-9030d0a76e39
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/0609b802-b3d4-417e-8a58-4237993589cc
the both is related to zoom in a picture.
As you know, each type of file obey a kind of protocol standard, the standard provide the farmat: which byte means size, which byte means data, and so on. in most cases, the protocol standard isn't open. So the code may do not work with the other type of file.
I hope this will be helpful.
Best regards
Mike Feng [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Friday, April 15, 2011 5:38 AMModerator -
Fred,
For the purpose you want I use also the GetThumbnailImage, it does not what it suggest, but creates simply a new thumbnail from a bitmap.
But first you have to create of course an image from a scratch.
I don't know if you know how to do that as all samples on MSDN show that as a result from the paint event.
The form2 part of the sample on our website shows how it can be done.
http://www.vb-tips.com/dbpages.aspx?Search=clock
And then of course that GetThumbnailImage
(Don't care it is handling a webpage, your part of the code is the same for a windows form)
Success
Cor- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Friday, April 15, 2011 6:16 AM
All replies
-
I have this example that show how to create on a form a thumbnail of another form.
In this example form1 creates a second form (I put a browser on it, but it can be anything). and then creates a thumbnail of this form. the thumbnail is painted on the form1.
In the example, the thumbnail is dynamic, so any change in the second form is reflected in the thumbnail, but if this is not the behaviour you need, you can just move the thumbnail image to a bitmap and it will become a static image.
Hope this can help you ...
just paste the code, the form needs no control
Public Class Form1 Private ThumbID As Integer = 0 Public Sub showThumbNail() If ThumbID <> 0 Then DwmUnregisterThumbnail(ThumbID) ThumbID = 0 End If Dim result As Integer Dim hWnd As IntPtr hWnd = FindWindow(Nothing, "Form2") result = DwmRegisterThumbnail(Me.Handle, hWnd, ThumbID) If result = 0 Then Dim ThumbSize As New PSIZE DwmQueryThumbnailSourceSize(ThumbID, ThumbSize) Dim rect As New Rectangle(10, 10, 300, 300) Dim ThumbPropreties As New DWM_THUMBNAIL_PROPERTIES ThumbPropreties.dwflags = DWM_TNP_RECTDESTINATION Or DWM_TNP_VISIBLE Or DWM_TNP_SOURCECLIENTAREAONLY ThumbPropreties.fSourceClientAreaOnly = True ThumbPropreties.fVisible = True ThumbPropreties.opacity = CByte((255 * 100) / 100) ThumbPropreties.rcDestination = rect result = DwmUpdateThumbnailProperties(ThumbID, ThumbPropreties) Else MsgBox("Cannot Create the Thumbnail") End If End Sub Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing DwmUnregisterThumbnail(ThumbID) End Sub Dim F As New Form2 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.Size = New Size(550, 300) Button1.Location = New Point(445, 20) F.Show() End Sub '===================WIN 32 REGION =============================== 'A value for the rcDestination member has been specified. Const DWM_TNP_RECTDESTINATION As Integer = &H1 'A value for the rcSource member has been specified. Const DWM_TNP_RECTSOURCE As Integer = &H2 'A value for the opacity member has been specified. Const DWM_TNP_OPACITY As Integer = &H4 'A value for the fVisible member has been specified. Const DWM_TNP_VISIBLE As Integer = &H8 'A value for the fSourceClientAreaOnly member has been specified. Const DWM_TNP_SOURCECLIENTAREAONLY As Integer = &H10 Public Structure DWM_THUMBNAIL_PROPERTIES Public dwflags As Integer Public rcDestination As Rectangle Public rcSource As Rectangle Public opacity As Byte Public fVisible As Boolean Public fSourceClientAreaOnly As Boolean End Structure Public Structure PSIZE Public X As Integer Public Y As Integer End Structure Declare Function DwmRegisterThumbnail Lib "Dwmapi.dll" (ByVal hwndDestination As IntPtr, ByVal hwndSource As IntPtr, ByRef phThumbnailId As Integer) As Integer Declare Function DwmUpdateThumbnailProperties Lib "Dwmapi.dll" (ByVal hThumbnailId As Integer, ByVal ptnProperties As DWM_THUMBNAIL_PROPERTIES) As Integer Declare Function DwmUnregisterThumbnail Lib "Dwmapi.dll" (ByVal phThumbnailId As Integer) As Integer Declare Auto Function FindWindow Lib "User32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr Declare Function DwmQueryThumbnailSourceSize Lib "Dwmapi.dll" (ByVal phThumbnailId As Integer, ByRef pSize As PSIZE) As Integer End Class Class Form2 : Inherits Form Public WithEvents Wb As New WebBrowser With {.Parent = Me} Public Sub New() MyBase.New() Me.Text = "Form2" Me.Size = New Size(800, 500) Wb.Dock = DockStyle.Fill Wb.Navigate("http://www.altavista.com") End Sub Private Sub Wb_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles Wb.DocumentCompleted Form1.Focus() Form1.showThumbNail() Me.Location = Form1.Location + Form1.Size End Sub End Class
Wednesday, April 13, 2011 11:06 AM -
Hi fredpox,
Welcome to the MSDN Forum.
Here is a test code of retrieve the BMP data from a DWG file for your reference.
Imports System.Collections.Generic Imports System.ComponentModel Imports System.Data Imports System.Drawing Imports System.Text Imports System.Windows.Forms Imports System.IO Partial Public Class Form1 Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load Dim viewDwg As New ViewDWG() PictureBox1.Image = viewDwg.GetDwgImage("d:\s.dwg") End Sub Private Class ViewDWG Private Structure BITMAPFILEHEADER Public bfType As Short Public bfSize As Integer Public bfReserved1 As Short Public bfReserved2 As Short Public bfOffBits As Integer End Structure Public Function GetDwgImage(ByVal FileName As String) As Image If Not (File.Exists(FileName)) Then Throw New FileNotFoundException("the file didn't find") End If 'declare a filestream to read the DWG file Dim DwgF As FileStream 'the position of file description block Dim PosSentinel As Integer 'Binary Reader Dim br As BinaryReader 'the thumbnail farmat Dim TypePreview As Integer 'the thumbnail postion Dim PosBMP As Integer 'the thumbnail size Dim LenBMP As Integer 'the thumbnail depth Dim biBitCount As Short 'BMP file header,because DWG doesn't include the header,we need add it by ourself Dim biH As BITMAPFILEHEADER 'BMP file body in the DWG file Dim BMPInfo As Byte() 'to store the memory stream Dim BMPF As New MemoryStream() 'Binary Writer Dim bmpr As New BinaryWriter(BMPF) Dim myImg As Image = Nothing Try 'DWG file stream DwgF = New FileStream(FileName, FileMode.Open, FileAccess.Read) br = New BinaryReader(DwgF) 'read from the thirteenth byte DwgF.Seek(13, SeekOrigin.Begin) 'read the thumbnail description block position PosSentinel = br.ReadInt32() 'read from the thirty-first byte of the thumbnail description block DwgF.Seek(PosSentinel + 30, SeekOrigin.Begin) 'the thirty-first byte represent the thumbnail picture format, 2 means BMP, 3 means WMF TypePreview = br.ReadByte() If TypePreview = 1 Then ElseIf TypePreview = 2 OrElse TypePreview = 3 Then 'the BMP block postion saved by DWG file PosBMP = br.ReadInt32() 'the BMP block size LenBMP = br.ReadInt32() 'move to the BMP block DwgF.Seek(PosBMP + 14, SeekOrigin.Begin) 'read the btye depth biBitCount = br.ReadInt16() 'read all BMP content DwgF.Seek(PosBMP, SeekOrigin.Begin) 'the BMP with no header BMPInfo = br.ReadBytes(LenBMP) br.Close() DwgF.Close() biH.bfType = 19778 'build the header If biBitCount < 9 Then biH.bfSize = 54 + 4 * CInt(Math.Truncate(Math.Pow(2, biBitCount))) + LenBMP Else biH.bfSize = 54 + LenBMP End If 'reserved byte biH.bfReserved1 = 0 'reserved byte biH.bfReserved2 = 0 'BMP data offset 'write BMP header biH.bfOffBits = 14 + 40 + 1024 'file type bmpr.Write(biH.bfType) 'file size bmpr.Write(biH.bfSize) '0 bmpr.Write(biH.bfReserved1) '0 bmpr.Write(biH.bfReserved2) 'offset bmpr.Write(biH.bfOffBits) 'write BMP file bmpr.Write(BMPInfo) 'move the pointer to the beginning BMPF.Seek(0, SeekOrigin.Begin) 'create the BMP file myImg = Image.FromStream(BMPF) bmpr.Close() BMPF.Close() End If Return myImg Catch ex As Exception Throw New Exception(ex.Message) End Try End Function End Class End Class
I hope this will be helpful.
Best regards,
Mike Feng [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Thursday, April 14, 2011 11:42 AMModerator -
Dear Crazypenny, dear Mike,
thanks for your welcome, I'm a newbie of VB.NET and I'm learning a lot in this forum, thanks to your helpful and friendly advices.
I tried both of yours suggestions and here I summarize my results.
I thought Crazypenny code was ok until I run it and I got an Access violation exception when executing the Sub showThumbNail(), when assigning the value to result variable.
Just to give you more details about this, I can see the web page is loading correctly, but then everything freezes and I get that message from VB.NET.
I tested Mike's code and it actually works great!
I just wanted to ask you if is there a way to control the dimensions of the picture I get (i.e. can I change the image ratio without set my PB to stretch?) and how is it generated.
My very basic understanding of VB.NET still needs to improved and I'd like to know more about this kind of code you suggested.
I can see you defined a class (ViewDWG), and a function GetDwgImage(), that you use to get the Image file to assign to the PictureBox.
I guess the code executed in the function GetDwgImage() is a stream reading command to get informations from the dwg file to extract the thumbnail data saved therein, but I don't understand how exactly.
I'm a technical designer and I use Autocad at work every day and I would like to improve my understanding on how dwg files are composed.
I know a dwg file is a sort of database, in which every entity is stored with properties, but I can't understand how your code works exactly to get to the proper byte in which the informations are stored and if this is possible for any other binary type of files.
thanks again for your help.
P.
pp _______________ VB Express 2010Thursday, April 14, 2011 9:00 PM -
Hi Fredpox,
What do you mean "control the dimensions of the picture I get"? Do you mean "zoom in"? If so, the two links should be helpful to you:
http://social.msdn.microsoft.com/Forums/en-US/vbide/thread/625f8169-4cfb-4b16-a4ba-9030d0a76e39
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/0609b802-b3d4-417e-8a58-4237993589cc
the both is related to zoom in a picture.
As you know, each type of file obey a kind of protocol standard, the standard provide the farmat: which byte means size, which byte means data, and so on. in most cases, the protocol standard isn't open. So the code may do not work with the other type of file.
I hope this will be helpful.
Best regards
Mike Feng [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Friday, April 15, 2011 5:38 AMModerator -
Fred,
For the purpose you want I use also the GetThumbnailImage, it does not what it suggest, but creates simply a new thumbnail from a bitmap.
But first you have to create of course an image from a scratch.
I don't know if you know how to do that as all samples on MSDN show that as a result from the paint event.
The form2 part of the sample on our website shows how it can be done.
http://www.vb-tips.com/dbpages.aspx?Search=clock
And then of course that GetThumbnailImage
(Don't care it is handling a webpage, your part of the code is the same for a windows form)
Success
Cor- Marked as answer by fredpox Tuesday, April 19, 2011 9:31 PM
Friday, April 15, 2011 6:16 AM -
Dear Cor, dear Mike,
sorry for the delay of this answer.
My question was about the possibility to further zoom in the bitmap retrieved by the dwg file.
I solved with a little 'trick' by creating two buttons which actions are changing the sizemode property of the PictureBox from Zoom to Center.
I'll deepen this topic and I'll further try your hints.
Now I'm quite happy with the results and I'll mark your posts as answers.
The only thing I don't understand is about some generig GDI+ exception error I eventually get as I activate the GetDwgImage function.
It happens that some of the files I have to handle don't display a thumbnail, it also happens in Explorer, but it's quite simple to solve the problem: I just need to open up the drawing and save it. Next time I browse the file I can see the thumbnail in Explorer.
This thing works even for my app, but some files, even if the dwg path is ok and the thumbnail displays correctly in explorer, I get the exception above.In order to make sure the file path was ok, I created some other buttons that trigger the opening of the file itself, the folder and other files contained therein.
I'll try to post the code for your reference as I get back to work.
regards,
P.
pp _______________ VB Express 2010Tuesday, April 19, 2011 9:30 PM -
Hi all,
Could you help me change post 2 code from thumbnail view to normal view please?
regards
toe
edit:
After a lot of searching it seems this will not be possible without a 3rd party component unless there is a way of enlarging a thumbnail.
- Edited by toecutter Tuesday, June 28, 2011 2:50 AM researching
Monday, June 27, 2011 11:40 PM