question

blinkor12-6317 avatar image
0 Votes"
blinkor12-6317 asked blinkor12-6317 commented

VB.NET Rescale a SVG with a ScaleFactor

I'm trying to rescale a rendered SVG inside a PictureBox loaded from a WebBrowser. I'm trying to resize the drawn SVG inside the PictureBox accordingly with a scale factor (eventually zoomed with a scrollwheel).

I'm using VB.NET Windows Forms.


This code renders a SVG static bitmap from within a WebBrowser.

Imports System.Runtime.InteropServices
    
 Public Class Form1
     <ComImport()>
     <Guid("0000010d-0000-0000-C000-000000000046")>
     <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
     Public Interface IViewObject
         <PreserveSig>
         Function Draw(dwDrawAspect As UInteger, lindex As Integer, pvAspect As IntPtr, ptd As IntPtr, hdcTargetDev As IntPtr, hdcDraw As IntPtr, lprcBounds As Rectangle,
                       lprcWBounds As IntPtr, pfnContinue As IntPtr, dwContinue As Integer) As Integer
         Function GetColorSet(dwDrawAspect As UInteger, lindex As Integer, pvAspect As IntPtr, ptd As IntPtr, hicTargetDev As IntPtr, <Out> ppColorSet As IntPtr) As Integer
         Function Freeze(dwDrawAspect As UInteger, lindex As Integer, pvAspect As IntPtr, <Out> pdwFreeze As UInteger) As Integer
         Function Unfreeze(dwFreeze As UInteger) As Integer
         Function SetAdvise(aspects As UInteger, advf As UInteger, pAdvSink As IntPtr) As Integer
         Function GetAdvise(<Out> pAspects As UInteger, <Out> pAdvf As UInteger, <Out> ppAdvSink As IntPtr) As Integer
     End Interface
    
     Public Enum DVASPECT
         DVASPECT_CONTENT = 1
         DVASPECT_THUMBNAIL = 2
         DVASPECT_ICON = 4
         DVASPECT_DOCPRINT = 8
     End Enum
    
     Friend WithEvents WebBrowser1 As WebBrowser
     Friend WithEvents PictureBox1 As PictureBox
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
         WebBrowser1 = New System.Windows.Forms.WebBrowser()
         PictureBox1 = New System.Windows.Forms.PictureBox()
         WebBrowser1.Location = New System.Drawing.Point(36, 68)
         WebBrowser1.MinimumSize = New System.Drawing.Size(20, 20)
         WebBrowser1.Name = "WebBrowser1"
         WebBrowser1.Size = New System.Drawing.Size(500, 500)
    
         WebBrowser1.ScrollBarsEnabled = False
         WebBrowser1.Url = New Uri(String.Format("E:\Sources\VB_SVG\originalSvg.svg"))
         WebBrowser1.Visible = False
    
         PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
         PictureBox1.Location = New System.Drawing.Point(20, 20)
         PictureBox1.Name = "PictureBox1"
         PictureBox1.Size = New System.Drawing.Size(500, 500)
    
         Controls.Add(PictureBox1)
         Controls.Add(WebBrowser1)
         Name = "Form1"
    
         ClientSize = New System.Drawing.Size(540, 540)
         CenterToScreen()
     End Sub
    
     Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
         ' Arbitrary size to test
Dim scaleFactor As Double = 1.5 'Attempted to multiply scalefactors.
         Dim nWidth = 500 * scaleFactor
         Dim nHeight = 500 * scaleFactor
         Dim bmp = New Bitmap(nWidth, nHeight)
         Dim gr As Graphics = Graphics.FromImage(bmp)
         Dim hDC = gr.GetHdc()
         Dim rc = New Rectangle(0, 0, nWidth, nHeight)
         Dim viewObject = CType(WebBrowser1.Document.DomDocument, IViewObject)
         viewObject.Draw(DVASPECT.DVASPECT_CONTENT, -1, CType(0, IntPtr), CType(0, IntPtr), CType(0, IntPtr), hDC, rc, CType(0, IntPtr), CType(0, IntPtr), 0)
         gr.ReleaseHdc(hDC)
         PictureBox1.Image = bmp
     End Sub
 End Class

I've been attempting to resize the rendered SVG by manipulating the nWidth and nHeight values on the WebBrowser's DocumentCompleted event by multiplying them with 'scale factor' which I want to SVG to be zoomed by (For example, a scale factor of 2 would zoom the SVG 2x) and also changing the sizes of the WebBrowser and the PictureBox1.

This however does not work and just gets somehow just produces random, smaller scales of the SVG for some reason or no SVG at all.

Is there any way I can rescale a SVG with the output result inside a PictureBox and if possible with a ScrollWheel without having to modify the actual width and height in the SVG's source code?

(note: followed up from this question)


dotnet-visual-basic
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

XingyuZhao-MSFT avatar image
0 Votes"
XingyuZhao-MSFT answered blinkor12-6317 commented

Hi @blinkor12-6317 ,
Maybe you can try the following method.
After adding 'Microsoft Internet Controls' to your project:
88937-2.png

You can adjust the display of the picture in PictureBox by scaling the svg in WebBrowser.
Here's the code you can refer to.

     Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
         Dim browser = TryCast(WebBrowser1.ActiveXInstance, SHDocVw.InternetExplorer)
         browser.ExecWB(SHDocVw.OLECMDID.OLECMDID_OPTICAL_ZOOM, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, 200, IntPtr.Zero)
    
         AddHandler WebBrowser1.Document.MouseDown, AddressOf WebBrowser1_MouseDown
     End Sub
     Private Sub WebBrowser1_MouseDown(sender As Object, e As HtmlElementEventArgs)
         Dim nWidth = 500
         Dim nHeight = 500
         Dim bmp = New Bitmap(nWidth, nHeight)
         Dim gr As Graphics = Graphics.FromImage(bmp)
         Dim hDC = gr.GetHdc()
         Dim rc = New Rectangle(0, 0, nWidth, nHeight)
         Dim viewObject = CType(WebBrowser1.Document.DomDocument, IViewObject)
         viewObject.Draw(DVASPECT.DVASPECT_CONTENT, -1, CType(0, IntPtr), CType(0, IntPtr), CType(0, IntPtr), hDC, rc, CType(0, IntPtr), CType(0, IntPtr), 0)
         gr.ReleaseHdc(hDC)
         PictureBox1.Image = bmp
     End Sub

Result of my test:
89311-gif.gif
Hope it could be helpful.
Best Regards,
Xingyu Zhao


If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



2.png (19.9 KiB)
gif.gif (161.3 KiB)
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

This works, but how would I detect automatically when the WebBrowser is zoomed and update it automatically? I know it isnt the 'Zoom' event of the webbrowser that i've tried @XingyuZhao-MSFT

0 Votes 0 ·

Hi @blinkor12-6317 ,
You can consider updating the PictureBox by clicking WebBrowser.

     Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
         ...
    
         AddHandler WebBrowser1.Document.MouseDown, AddressOf WebBrowser1_MouseDown
     End Sub
     Private Sub WebBrowser1_MouseDown(sender As Object, e As HtmlElementEventArgs)
     ...
     End Sub

I have updated my code, and you can take a look.

0 Votes 0 ·

Hi, how would I actually get the zoom factor of the WebBrowser? I’m planning to overlay a JPG on top of it and I want to know by how much I would stretch the JPG so it is sized proportionally with the Webbrowser? (Asking now so I don’t have to post a separate thread). Thanks!

0 Votes 0 ·
Show more comments
XingyuZhao-MSFT avatar image
0 Votes"
XingyuZhao-MSFT answered blinkor12-6317 commented

Hi @blinkor12-6317 ,
Without WebBrowser, you can use svg package to show the svg image on PictureBox.
Here's the code of my test, and you can refer to it.

 Imports Svg
        
     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
         Dim svgDocument = Svg.SvgDocument.Open("...jcss.svg")
         svgDocument.ShapeRendering = SvgShapeRendering.Auto
         Dim bmp As Bitmap = svgDocument.Draw(PictureBox1.Width, PictureBox1.Height)
         PictureBox1.Image = bmp
     End Sub

Result of my test:
90208-gif.gif

Best Regards,
Xingyu Zhao


If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



gif.gif (17.0 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@XingyuZhao-MSFT , your method works perfectly. However, in my code, I'm trying to make a map application that can be zoomed with the MouseWheel. I've written some code so far, it works fine but takes too much memory (up to 1.7 GB). Code in Pastebin. Also, I'm planning to load a SVG from a string in the future and I wouldn't want to save it to a new file every time the user zooms. Is there also a way I can load the SVG from a string instead of a Path? (SVG-NET has sparse documentation).


0 Votes 0 ·