iconfont-******* vector icon library
In WIN8 system, the webbrowser control shows SVG images with jaggedness, and it is normal with IE11 and the Google browser kernel.
Code:
Private Sub Command2_Click()
WebBrowser1.Navigate "https://iconfont.alicdn.com/s/fedf0846-3e88-48eb-ae98-7e01902c5a97_origin.svg"
End Sub
Sub Test2()
'SvgToPng sample,SvgTOPngByte array()
Dim File1 As String, PngFile As String, PngFile2 As String
Dim Srf As cCairoSurface, Buffer() As Byte
Dim W As Long, H As Long
W = 1600
H = 1600
File1 = App.Path & "\SVGs\dancer.svg"
PngFile = App.Path & "\ToPng.png"
PngFile2 = App.Path & "\ToPng_Arr.png"
Set Srf = Cairo.ImageList.AddImage("", File1, W, H, True) 'render the SVG into a 800x800 InMemSrf with 32bpp, keeping the Aspect-Ratio
Srf.WriteContentToPngFile PngFile 'write the current Srf-content out into a PNG-file
Srf.WriteContentToPngByteArray Buffer
PutToFileBin PngFile2, Buffer
' MsgBox UBound(Buffer) + 1
Me.AutoRedraw = True
Me.Cls
Me.Picture = LoadPicture("001.jpg")
Srf.DrawToDC Me.hDC
Me.Refresh
End Sub
Last edited by xiaoyao; Apr 7th, 2021 at 10:28 AM.
I love the hands-on design approach and paying attention on every small detail like the corner radius of the icons, the typography, the baseline grid, layout grid, the most appropriate colours and keeping all those consistent. It took me some time to do it but finally I was able to complete an example of my step by step process.
The UI kit works best with FF DIN Pro but you could find a version with the free Blogger Sans or update the text styles with any other typeface you prefer. The pack contains Sketch files only. I like Figma but it really takes time. I promise, I'll try to deliver a Figma version... someday soon. All kind of feedback is welcome. Seriously, I mean it. Spending more time on something makes me biased and even blind for some obvious issues, so you could help me improve it and discover some problems.
I'd ask for just one thing. Help me spread the word, please! Thank you!
After installing this component, Webbrowser will automatically call it to display SVG images, but unfortunately the display effect is completely unsatisfactory.
Last edited by xiaoyao; Apr 7th, 2021 at 10:26 AM.
I have no clue, what you mean...
(cairo can be used with several "degrees" of AntiAliasing, but it is normally not set to "CAIRO_ANTIALIAS_NONE" by default).
Please show the complete code you've used - and also provide a download-link to the svg-file you've used in your test.
I have no clue, what you mean...
(cairo can be used with several "degrees" of AntiAliasing, but it is normally not set to "CAIRO_ANTIALIAS_NONE" by default).
Please show the complete code you've used - and also provide a download-link to the svg-file you've used in your test.
Olaf
so I'm providing a GitHub-URL instead (which is an allowed workaround for this forum in the meantime): https://github.com/vbRichClient/CairoTutorial
FROM RC5cairoTutorial\CairoTutorial\16 SVG\SVGs\dancer.svg
Last edited by xiaoyao; Apr 7th, 2021 at 05:58 AM.
It would be convenient if the sawtooth can be eliminated and it is transparent. For example, put the RC6.SVG object into the picturebox control, first set a background image, and then display the SVG object. I can change the background image (screenshot form and the above controls, simulating the transparency effect) at any time, and can get the real occupied width and height of the SVG object. If you can draw to picture1.hdc or draw to the memory dc, it will be more convenient. Equivalent to the image object in gdiplus
I want to convert the SVG object into a PNG or transparent bitmap in the memory according to the required width and height, and then use GDIPLUS or gdi32.dll to draw on the image frame.
Last edited by xiaoyao; Apr 7th, 2021 at 06:09 AM.
It would be convenient if the sawtooth can be eliminated...
There is no sawtooth (the antialiasing works).
Instead the problem is the same as with all your other "micro-benchmarks" and "comparisons"...
Your knowledge is in the most cases not sufficient, to do them properly.
For example - here in this case - the problem is, that you:
- run your VB6-IDE in all likelihood on a high-resolution 4K-display
- without having adjusted the VB6.exe manifest to tell the system, that the Exe-App is dpi-aware
With the effect, that all your GDI-based-outputs (including those of the cairo-surfaces on PictureBox-hDCs) -
in your VB6-IDE-session are done with 96dpi - and then stretched from there to the higher dpi-res of your system (occuring "blurred" and/or "jagged" on your screen).
To do proper tests, you have to:
- switch your system to 100% dpi-zoomfactor
- or make your VB6.exe App dpi-aware (in case you make your screenshots in the IDE-session)
- or make the compiled App dpi-aware (in case you make your screenshots on the compiled running App)
- or avoid screenshots on your running App, and putting out the content from the cairosurface directly into a *.png-file
The last point can for example be achieved by adjusting e.g.:
Code:
Private Sub lstFiles_Click()
Draw ucCanvas1.CC
End Sub
to
Code:
Private Sub lstFiles_Click()
Draw ucCanvas1.CC
ucCanvas1.Srf.WriteContentToPngFile App.Path & "\" & lstFiles.FileName & ".png"
End Sub
Which will ensure the cairo-based output of the ucCanvas-backing-surface directly in a PNG-file.
I've applied the latter suggestion now - and here's the output of that PNG-file for the "clip3.svg"
(as rendered by cairo on the ucCanvas-Backing-Surface). http://vbRichClient.com/Downloads/clip3.svg.png
can it write PNG to mrmory like dim arr() as byte
.
Is it possible to set a picture as a background layer?
If it can be divided into a control. Can be placed with other ordinary controls in the form above more convenient.
Like the Google kernel, we encapsulate it as a control.
WebKitCairo about 10MB SIZE(11 files)
WKE.DLL,EWE.DLL,cef.dll,like these,Generally, there are only 1-2 DLL files
Maybe their principles are similar in nature, that is, some of them combine all the related supporting DLL files and statically compile them into one DLL.
Last edited by xiaoyao; Apr 7th, 2021 at 08:54 AM.
I want to convert the SVG object into a PNG or transparent bitmap in the memory according to the required width and height, and then use GDIPLUS or gdi32.dll to draw on the image frame.
First of all - as soon as you start using the RC6, there is no need anymore for any GDI- or GDIPlus-routines.
(cairo contains "everything GDIPlus offers and more" - and GDI only comes into play, when you want to finally visualize a certain CairoSurface on a given hWnd and its associated hDC)
And as for SVGs - these usually come "without any background-color" -
so, converting them to "transparent PNGs" is given "by default" in the cairo-wrapper...
The following code converts all the *.svg and *.svgz from the SVGs-SubFolder of the Cairo-Tutorial #16 -
into a different Folder ("C:\Temp\ConvertedPngs"), which then contains the transparent *.png converted Svgs in a desired size of currently 800x800:
Code:
Private Sub Form_Load()
SvgFolderToPngFolder "C:\Code\CairoTutorial\16 SVG\SVGs", "C:\Temp\ConvertedPngs"
End Sub
Sub SvgFolderToPngFolder(ByVal SvgPath$, ByVal PngPath$)
New_c.FSO.EnsurePath PngPath 'ensure this target-path on the FileSystem, in case it is not yet there
New_c.FSO.EnsurePathEndSep PngPath 'ensure a trailing "\" on the Path-Variable
With New_c.FSO.GetDirList(SvgPath, dlSortNone, "*.svg;*.svgz") '<- scan the SVG-Path for these file-types
Dim i As Long, Srf As cCairoSurface
For i = 0 To .FilesCount - 1 'iterate over the found files
Set Srf = Cairo.ImageList.AddImage("", .Path & .FileName(i), 800, 800, True) 'render the SVG into a 800x800 InMemSrf with 32bpp, keeping the Aspect-Ratio
Srf.WriteContentToPngFile PngPath & .FileName(i) & ".png" 'write the current Srf-content out into a PNG-file
Next
End With
End Sub
Private Sub lstFiles_Click()
Draw ucCanvas1.CC
ucCanvas1.Srf.WriteContentToPngFile App.Path & "\" & lstFiles.FileName & ".png"
End Sub
Which will ensure the cairo-based output of the ucCanvas-backing-surface directly in a PNG-file.
I've applied the latter suggestion now - and here's the output of that PNG-file for the "clip3.svg"
(as rendered by cairo on the ucCanvas-Backing-Surface). http://vbRichClient.com/Downloads/clip3.svg.png
HTH
Olaf
Thank you very much, the image is indeed not clear due to DPI scaling, now it is completely OK.
My computer is set to 2 times DPI magnification. So there is a background image that uses a screenshot as a transparent control, and the resulting size has doubled. It's the same reason, let me try again
Does the WEBBROWSER control of VB6 also have aliasing? (DPI scaling is prohibited)
By default, the DPI scaling of EXE and computer settings is the same 2 times.
If DPI scaling is disabled, the controls on the window will become very small, and there will be a lot of empty space on the window.
I don't know how you deal with this kind of problem, what is the best way?
exe disables DPI scaling, and the SVG displayed by WEBBROWSER is no longer jagged. This is all perfect (win8 ie11)
Whether the exe is set to disable DPI scaling will not affect RC6's SVG to PNG conversion.
Open the converted PNG (width 800) with photoshop, and the result is that the edges of the image are jagged.
Try right-clicking PHOTOSHOP to disable DPI scaling, but the image is very small.
Change it to a higher output of 1600, which is normal now.
Now the monitor is too big, high-definition, these problems should be paid special attention.
Last edited by xiaoyao; Apr 7th, 2021 at 10:20 AM.
The WebKit-Browser-addon above is BTW "the smallest Browser-Control" (not "Miniblink") -
and it is thought as a "local use only Control, don't go online with it" - for the RC5
(the RC6 has its own, new BrowserControl approach via WebView2, which uses the "rolling runtime-updates" provided by the Operating-system-vendor).
This (in the meantime quite old) WebKit-Browser-control suffers from the same problem, the MiniBlink-Author has...
As soon as you "start optimizing on an existing Code-base, on your own, significantly changed fork", you are basically on your own -
and cannot keep up the pace with the "leading versions" in the public repos anymore after some time...
And as demonstrated e.g. here: https://www.vbforums.com/showthread....vbRichClient5)
... for SVG-support (to be able to render "Icons in any size") - you don't need any of these Browser-Controls...
the SVG-support within the RC-libs should be sufficient (the RC5/RC6 packages are both significantly smaller, compared to a full Browser-Runtime).
There are many functions and very powerful. You can also encapsulate some other functions into independent DLLs, such as WEBSOCKET.DLL, ssl.dll, curl.dll, chromium.dll (miniblink.dll), node.dll, python.dll, lua.dll
I hope there is a website that lists these DLLs and source code together, just like PYTHON (pip.exe), nmp.exe of node.js (Node Package Manager)
ocx control list, com dll (activex) list, standard DLL list (sqlite.dll, etc.)
.net control list, module bas file list, custom control list, class file list (*.cls), various functional window lists (such as login window, change password window), do these tasks well, just like one The purchase of mobile phone parts is the same (diode, mobile phone CPU, camera, charging cable, wireless charger, lithium battery). Of course, it is so powerful that it must be charged.
There are many websites in China for downloading design drawings in PNG, PSD and other formats, and there are many bleach button designs, but most of them are charged, and it is difficult to find free websites.
Recall that 10 years ago, we could buy design material CDs, which contained tens of thousands of pictures.
The WebKit-Browser-addon above is BTW "the smallest Browser-Control" (not "Miniblink") -
and it is thought as a "local use only Control, don't go online with it" - for the RC5
(the RC6 has its own, new BrowserControl approach via WebView2, which uses the "rolling runtime-updates" provided by the Operating-system-vendor).
This (in the meantime quite old) WebKit-Browser-control suffers from the same problem, the MiniBlink-Author has...
Olaf
miniblink is indeed a very good Google Chrome kernel package. It was free at first, but now it is also charged. The free version is relatively old and will not be updated for a long time. If you want to use it well, you must spend money to buy the VIP version. The main problem is that the price is cheaper, and sometimes the cost of learning is also high.
For example, the olf webkit package needs to be decompressed to a fixed directory. Many people may have installed it incorrectly, and need to install the VC2008 runtime library.
Last edited by xiaoyao; Apr 7th, 2021 at 10:21 AM.
The painted picture has a black background. It is not painted transparently on the original canvas. Is there any way to deal with it?
Srf.DrawToDC Me.hDC
Is there a cropping function like PHOTOSHOP that removes the extra blank pixels around the PNG image.
If the height of the image in the SVG is 2 times the width. For example, when outputting a 800*800 PNG file, half of the width is actually blank (transparent).
I wonder if this library itself has the function of obtaining the original SVG aspect ratio? If the real aspect ratio of the picture can be obtained in advance, there will be no excess in the saved PNG
Want to get the width and height of the original image data, the return value is 0?
Code:
Dim OriginalWidth As Long, OriginalHeight As Long
Set Srf = Cairo.ImageList.AddImage("", File1, W, H, True, OriginalWidth, OriginalHeight)
Of pixels are occupied. For example, I can set the output of 400*800 PNG files.
If there is no such method, you can only find the blank pixels around an image by pixel cycle, which will take a lot of time. Then copy the effective picture from the middle
Create another new image object with a matching size, and save it with GDIPLUS.
cCairo is a very powerful function library (class), the source code is VC++, right? I don't know where there is open source, I want to know how it is implemented.
However, he has done a lot of functions in it, converted into JPG, pdf, etc.
It is not easy to learn to use all the functions in the DLL. I don't know where there is SDK manual or CHM help file.
Code:
Sub Test2()
'SvgToPng sample,SvgTOPngByte array()
Dim File1 As String, PngFile As String, PngFile2 As String
Dim Srf As cCairoSurface, Buffer() As Byte
Dim W As Long, H As Long
W = 1600
H = 1600
File1 = App.Path & "\SVGs\dancer.svg"
PngFile = App.Path & "\ToPng.png"
PngFile2 = App.Path & "\ToPng_Arr.png"
Set Srf = Cairo.ImageList.AddImage("", File1, W, H, True) 'render the SVG into a 800x800 InMemSrf with 32bpp, keeping the Aspect-Ratio
Srf.WriteContentToPngFile PngFile 'write the current Srf-content out into a PNG-file
Srf.WriteContentToPngByteArray Buffer
PutToFileBin PngFile2, Buffer
' MsgBox UBound(Buffer) + 1
Me.AutoRedraw = True
Me.Cls
Me.Picture = LoadPicture("001.jpg")
Srf.DrawToDC Me.hDC
Me.Refresh
End Sub
Last edited by xiaoyao; Apr 7th, 2021 at 10:09 AM.
USE WEBBROWSER ALSO CAN show svg,how to save as png?
Code:
WebBrowser1.Navigate App.Path & "\123.svg"
Dim tIv As IViewObject
Dim trc As RECT
trc.Right = 100
trc.Bottom = 100
'USE OLELB.TLB
Set tIv = WebBrowser1.Document
Picture1.Cls
tIv.Draw DVASPECT_CONTENT, 1, ByVal 0, ByVal 0, Picture1.hDC, Picture1.hDC, trc, trc, ByVal 0, ByVal 0
Picture1.Refresh
The screenshot of this code is a white web page background. How to obtain a transparent SVG image and save it as a PNG is probably too difficult, right?
Webbrowser selects the SVG file and right-clicks "Save Picture As" to save it in PNG format. How to use the code to make him save as, it is best not to pop up a window.
Last edited by xiaoyao; Apr 7th, 2021 at 10:44 AM.
The painted picture has a black background.
It is not painted transparently on the original canvas. Is there any way to deal with it?
Srf.DrawToDC Me.hDC
Before you resort to a GDI-call (which is the case with your above Srf.DrawToDC someHDC),
you will have to ensure the BackGround on a given Surface yourself...
So, instead of Me.Cls (which repaints the Form-Background with either its BackColor or the currently assigned Form-Picture),
you can ensure a similar thing on your "Form-covering Surface", by doing (on your CC = Surface.CreateContext) first:
- a "clearing" of the Surface with a solid color: CC.Paint 1, Cairo.CreateSolidPatternLng(SomeBackColor)
- or "clear" the Srf with a BackGround-Bitmap: CC.RenderSurfaceContent "SomeBGImageKeyInCairoImageList"
Or if you want to do it "by the book", you can use the RC6-Form- and -WidgetEngine,
writing your first little Widget-Class:
cwMySVGImg.cls
Code:
Option Explicit
Event DblClick()
Private WithEvents W As cWidgetBase '<- this is required in every cw-Widget-Class (acting similar to 'UserControl' in a VB-UserControl-implementation)
Public SvgBytesOrFileName As Variant 'a Public Property, which takes either a FileName or a ByteArray of the SVG
Private Sub Class_Initialize()
Set W = Cairo.WidgetBase
W.BackColor = -1
W.Moveable = True
End Sub
'the following two Props are always needed in any cw-Widget-implementation
Public Property Get Widget() As cWidgetBase: Set Widget = W: End Property
Public Property Get Widgets() As cWidgets: Set Widgets = W.Widgets: End Property
Private Sub W_DblClick()
RaiseEvent DblClick 'delegate the Widgets DblClick-Event to the outside
End Sub
Private Sub W_Paint(CC As RC6.cCairoContext, ByVal xAbs As Single, ByVal yAbs As Single, ByVal dx_Aligned As Single, ByVal dy_Aligned As Single, UserObj As Object)
If Not IsEmpty(SvgBytesOrFileName) Then
New_c.SVG(SvgBytesOrFileName).RenderFromDOM CC, 0, 0, dx_Aligned, dy_Aligned
End If
End Sub
This Widget is now:
- able to render any SVG-ByteContent "in itself" (after you set its SvgBytesOrFileName-Property, without resorting to temporary PNG-conversions)
- automatically transparent on its WidgetRoot-Parentcontainer
- and also Moveable, because we said so, in Class_Initialize by setting W.Moveable = True
- able to raise a DblClick-Event
A Form-Object which is able to render the above Widget (DPI- and Alpha-aware, as well as User-Zoomable by Ctrl+Mousewheel)...
cfMain.cls
Code:
Option Explicit
Public WithEvents Form As cWidgetForm, WithEvents MySvgImg As cwMySVGImg
Private Sub Class_Initialize()
Set Form = Cairo.WidgetForms.Create(vbSizable, "Use Ctrl+Mousewheel to change Zoom") 'create the Form-instance
Form.WidgetRoot.ImageKey = "BG" 'set the BackGround via the ImageKey we ensured in Sub Main()
ApplyCurrentZoomOn Form.WidgetRoot 'apply the Systems current DPI-Zoomfactor
Set MySvgImg = Form.Widgets.Add(New cwMySVGImg, "MySvgImg", 10, 10, 256, 256)
MySvgImg.SvgBytesOrFileName = New_c.FSO.ReadByteContent("c:\temp\dancer.svg")
End Sub
Private Sub Form_ResizeWithDimensionsDIP(ByVal dx As Single, ByVal dy As Single)
MySvgImg.Widget.Move (dx - MySvgImg.Widget.Width) / 2, (dy - MySvgImg.Widget.Height) / 2
End Sub
Private Sub MySvgImg_DblClick()
MsgBox "DblClick-Event from MySvgImg " & Screen.TwipsPerPixelX
End Sub
Private Sub Form_MouseWheel(ByVal MouseKeys As Long, ByVal Rotation As Long, ByVal Xpos As Single, ByVal Ypos As Single)
If MouseKeys = WebActionCtrlMask Then gUserZoom = gUserZoom + 0.1 * Sgn(Rotation) Else Exit Sub
Form.Locked = True
ApplyCurrentZoomOn Form.WidgetRoot
Form_ResizeWithDimensionsDIP Form.WidgetRoot.Widget.ScaleWidth, Form.WidgetRoot.Widget.ScaleHeight
Form.Locked = False
Form.Caption = "MonitorZoom: " & Form.WidgetRoot.CurrentMonitor.Zoom & ", UserZoom: " & gUserZoom
End Sub
And finally a Startup-Module (with a Sub Main()):
modMain.bas
Code:
Option Explicit
Public fMain As New cfMain, gUserZoom As Single
Sub Main()
Cairo.SetDPIAwareness 'this way we do not need to include a manifest for DPI-awareness
Cairo.ImageList.AddImage "BG", "c:\temp\large.jpg" 'ensure a BackGround-image-resource under the "BG"-ImageKey
fMain.Form.Show
Cairo.WidgetForms.EnterMessageLoop
End Sub
Public Sub ApplyCurrentZoomOn(WidgetRoot As cWidgetRoot)
If gUserZoom = 0 Then gUserZoom = 1
If gUserZoom < 0.7 Then gUserZoom = 0.7 Else If gUserZoom > 2.5 Then gUserZoom = 2.5 'clamp the User-Zoom
WidgetRoot.Zoom = gUserZoom * WidgetRoot.CurrentMonitor.Zoom
End Sub
The above is now a proper WireFrame for your DPI-aware "Alpha-experiments" - and should look like that
(Shot was taken from a compiled Exe without any manifest, on a 4K-display with 250% DPI-Zoom):
i want to use it without cWidgetForm,how to do?
Public WithEvents Form As cWidgetForm。not (Cairo.WidgetForms.Create)
i want put on my usercontrol,or picturebox,maybe it's can't use Srf.DrawToDC ?
my code only show bg picture,can't show svg picture
maybe you can upload a full sample
my bg pic is 576*432,I don't know if this has an impact
Code:
Private Sub W_Paint(CC As RC6.cCairoContext, ByVal xAbs As Single, ByVal yAbs As Single, ByVal dx_Aligned As Single, ByVal dy_Aligned As Single, UserObj As Object)
If Not IsEmpty(SvgBytesOrFileName) Then
'New_c.SVG(SvgBytesOrFileName).RenderFromDOM CC, 0, 0, dx_Aligned, dy_Aligned
New_c.SVG.RenderFromDOM CC, 0, 0, dx_Aligned, dy_Aligned
End If
End Sub
Srf.WriteContentToPngByteArray Buffer()
With this step, it is much more convenient. The main disadvantage is that the actual width and height of the SVG are unknown
(let width = svg.getBoundingClientRect().width). I have to use GDIPLUS memory to load the stream data, remove the surrounding white space, and then zoom and draw to the target control hdc
Displaying an SVG is only the first step. In the end, you want to turn the SVG image into a button background or icon.
There may be 10 or 30 SVG images displayed on a form
Last edited by xiaoyao; Apr 7th, 2021 at 12:43 PM.
Can SVG be deformed as a whole. For example, normal people become short, rectangles become squares. In theory, to turn a rectangle into a triangle is to give it extreme compression on one side。
Like turning a basketball into an oval football.In theory, this distortion will not cause the loss of picture quality.
Gdiplus, the square image becomes a rectangle, the picture may be ugly, not clear.
The main disadvantage is that the actual width and height of the SVG are unknown.
With RC6 (not RC5) the following works:
Code:
With Cairo.ImageList.AddImage("", "c:\temp\dancer.svg")
Debug.Print .Width, .Height
'.WriteContentToPngByteArray SomeByteArray
End With
So, the above "With-construct" decodes the SVG in its original dimensions into an ImageSurface with the same dimensions.
(from which you can directly write to a PNG)...
Or alternatively (the faster method to get the SVG-dimensions, because no rendering is needed onto an ImageSurface):
Code:
With New_c.SVG("c:\temp\dancer.svg")
Dim W, H
.GetSVGDimensions W, H
Debug.Print W, H
End With
As for wrapping a cairo-surface within a normal (hWnd-based) VB6-UserControl...
You can easily do a generic UserControl (which throws an OwnerDraw-Event at you), this way:
Into a Project-Private UserControl:
Code:
Option Explicit
Public Event OwnerDraw(CC As cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
Private Declare Function SetWindowLongW Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLongW Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function UpdateLayeredWindow Lib "user32" (ByVal hWnd As Long, ByVal hdcDst As Long, pptDst As Any, psize As Any, ByVal hdcSrc As Long, pptSrc As Any, ByVal crKey As Long, pblend As Any, ByVal dwFlags As Long) As Long
Public Srf As cCairoSurface, GlobalAlpha As Double
Private Sub UserControl_Initialize()
Const GWL_EXSTYLE = -20, WS_EX_LAYERED = &H80000
SetWindowLongW hWnd, GWL_EXSTYLE, GetWindowLongW(hWnd, GWL_EXSTYLE) Or WS_EX_LAYERED
GlobalAlpha = 1
End Sub
Private Sub UserControl_Resize()
ScaleMode = vbPixels
Set Srf = Cairo.CreateWin32Surface(ScaleWidth, ScaleHeight) 'recreate the backbuf-Srf on resize
Refresh
End Sub
Public Sub Refresh()
RedrawOn Srf.CreateContext
LayerUpdate
End Sub
Private Sub RedrawOn(CC As cCairoContext)
CC.Operator = CAIRO_OPERATOR_CLEAR: CC.Paint 'clear the previous contents
CC.Operator = CAIRO_OPERATOR_OVER 'restore the default-blending-operator
RaiseEvent OwnerDraw(CC, Srf.Width, Srf.Height)
End Sub
Private Function LayerUpdate()
Const ULW_ALPHA = &H2
Dim sz(0 To 1) As Long
sz(0) = Srf.Width: sz(1) = Srf.Height
UpdateLayeredWindow hWnd, hDC, ByVal 0&, sz(0), Srf.GetDC, 0@, 0, CLng(&H10000 * (256 + GlobalAlpha * 255)), ULW_ALPHA
End Function
Usage of such a generic (OwnerDraw-supporting) UC in your normal VB6-Form:
(requires RC6 and the UserControl-Name to be ucAlpha.ctl):
Code:
Option Explicit
Private Sub Form_Load()
ucAlpha1.Refresh '<- calling the Refresh-Method will trigger a new OwnerDraw-Event
End Sub
Private Sub ucAlpha1_OwnerDraw(CC As RC6.cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", "c:\temp\dancer.svg", WPxl, HPxl), 0, 0
End Sub
The above is using UpdateLayeredWindow on Child-hWnds - and therefor runs only on Win8+
(also requiring a properly manifested IDE - or a manifested App).
-----------------------------------------------------------------
If you want to avoid UpdateLayeredWindow, then you could change the approach to "BackGround-copying" this way:
ucAlpha.ctl (even less code, without any API-Declares)
Code:
Option Explicit
Public Event OwnerDraw(CC As cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
Public Srf As cCairoSurface
Private Sub UserControl_Resize()
If Not AutoRedraw Then AutoRedraw = True
ScaleMode = vbPixels
Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight) 'recreate the backbuf-Srf on resize
Refresh
End Sub
Public Sub Refresh()
RedrawOn Srf.CreateContext
End Sub
Private Sub RedrawOn(CC As cCairoContext)
On Error Resume Next
Dim ParentSrf As cCairoSurface: Set ParentSrf = Parent.Srf
On Error GoTo 0
If ParentSrf Is Nothing Then
CC.Paint 1, Cairo.CreateSolidPatternLng(Parent.BackColor)
Else
CC.RenderSurfaceContent ParentSrf, -ScaleX(Extender.Left, Parent.ScaleMode, vbPixels), _
-ScaleY(Extender.Top, Parent.ScaleMode, vbPixels)
End If
RaiseEvent OwnerDraw(CC, Srf.Width, Srf.Height)
Srf.DrawToDC hDC
UserControl.Refresh
End Sub
Form-Code:
Code:
Option Explicit
Public Srf As cCairoSurface '<- the Parent of the ucAlpha-Ctl needs a Public Property like this
Private Sub Form_Load()
Set Srf = Cairo.ImageList.AddImage("", "c:\temp\large.jpg") 'load a BG-image into the Public Property
Set Picture = Srf.Picture 'reflect this Property-content also in the Form-Picture
ucAlpha1.Refresh
End Sub
Private Sub ucAlpha1_OwnerDraw(CC As RC6.cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", "c:\temp\dancer.svg", WPxl, HPxl), 0, 0
End Sub
The size obtained is 400,700, and there are still a lot of blanks around. After using PHOTOSHOP to remove the surrounding transparent or blank pixels, it is 400*688
Code:
With Cairo.ImageList.AddImage("", "c:\temp\dancer.svg")
Debug.Print .Width, .Height
'.WriteContentToPngByteArray SomeByteArray
End With
it's show a jpg file,and show svg on it,very good
【The above is using UpdateLayeredWindow on Child-hWnds - and therefor runs only on Win8+】
Private Sub Form_Load()
Me.Picture = LoadPicture("1.jpg")
ocx11.Refresh '<- calling the Refresh-Method will trigger a new OwnerDraw-Event
End Sub
Private Sub ocx11_OwnerDraw(CC As RC6.cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", App.Path & "\SVGs\filter-special.svg", WPxl, HPxl), 0, 0
End Sub
Last edited by xiaoyao; Apr 7th, 2021 at 09:44 PM.
Option Explicit
'Public Event OwnerDraw(CC As cCairoContext, ByVal WPxl As Long, ByVal HPxl As Long)
Public Srf As cCairoSurface
Public Srf2 As cCairoSurface '<- the Parent of the ucAlpha-Ctl needs a Public Property like this
Dim SvgFile As String, BgFile As String
Private Sub UserControl_Resize()
If Not AutoRedraw Then AutoRedraw = True
ScaleMode = vbPixels
Set Srf = Cairo.CreateSurface(ScaleWidth, ScaleHeight) 'recreate the backbuf-Srf on resize
RefreshImg
End Sub
Public Sub RefreshImg()
If SvgFile <> "" Then RedrawOn Srf.CreateContext
End Sub
Public Sub ShowSvg(SvgFileA As String)
SvgFile = SvgFileA
RedrawOn Srf.CreateContext
End Sub
Private Sub RedrawOn(CC As cCairoContext)
On Error Resume Next
Dim ParentSrf As cCairoSurface: Set ParentSrf = Parent.Srf
On Error GoTo 0
If ParentSrf Is Nothing Then
CC.Paint 1, Cairo.CreateSolidPatternLng(Parent.BackColor)
Else
CC.RenderSurfaceContent ParentSrf, -ScaleX(Extender.Left, Parent.ScaleMode, vbPixels), _
-ScaleY(Extender.Top, Parent.ScaleMode, vbPixels)
End If
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", SvgFile, Srf.Width, Srf.Height), 0, 0
Srf.DrawToDC hDC
UserControl.Refresh
End Sub
Public Sub ShowBgAndSvg(BgFileA As String, SvgFileA As String)
BgFile = BgFileA
SvgFile = SvgFileA
RedrawOn2 Srf.CreateContext
End Sub
Private Sub RedrawOn2(CC As cCairoContext)
On Error Resume Next
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", BgFile, Srf.Width, Srf.Height), 0, 0
CC.RenderSurfaceContent Cairo.ImageList.AddImage("", SvgFile, Srf.Width, Srf.Height), 0, 0
Srf.DrawToDC hDC
UserControl.Refresh
End Sub
In this way, you can set the background of the control and the background of the form at will
FORM1.FRM
Code:
Public Srf As cCairoSurface '<- the Parent of the ucAlpha-Ctl needs a Public Property like this
Dim BackgroundPicture As String
Private Sub Form_Load()
BackgroundPicture = APP.PATH & "\BG1.jpg"
End Sub
Private Sub Command1_Click()
SvgOcx1.ShowBgAndSvg BackgroundPicture, App.Path & "\SVGs\dancer.svg"
End Sub
Private Sub Command2_Click()
Set Srf = Cairo.ImageList.AddImage("", BackgroundPicture) 'load a BG-image into the Public Property
Set Picture = Srf.Picture 'reflect this Property-content also in the Form-Picture
SvgOcx1.ShowSvg App.Path & "\SVGs\dancer.svg"
End Sub
IF I ONLY WANT LOAD BackgroundPicture once in usercontrol,how to do?
svgfile will change
CC.RenderSurfaceContent Cairo.ImageList.AddImage("SVG", SvgFile, Srf.Width / 2, Srf.Height), 0, 0
If you change the picture multiple times, will it cause a lot of waste of memory? Is there any way to keep the background image unchanged, and then change the image above each time?
The second use scenario, if I load a background image first, and then load 3 photos to simulate the 3 states of the button press, how to deal with it (the size of the 3 pictures may be different)
That is, the background image is unchanged, 3 images are pre-loaded, any one of them as needed
Code:
Private Sub RedrawOn2(CC As cCairoContext)
On Error Resume Next
Static BGOK As Boolean
If Not BGOK Then
BGOK = True
CC.RenderSurfaceContent Cairo.ImageList.AddImage("BG", BgFile, Srf.Width, Srf.Height), 0, 0
End If
Cairo.ImageList.Remove "SVG"
CC.RenderSurfaceContent Cairo.ImageList.AddImage("SVG", SvgFile, Srf.Width / 2, Srf.Height), 0, 0
Srf.DrawToDC Hdc
UserControl.Refresh
End Sub
Last edited by xiaoyao; Apr 7th, 2021 at 10:07 PM.
The third question: I am developing a transparent button control (copy the image of multiple controls in the background area + button picture)
If I move the custom control, I need to redraw a new background image, and use GDIPLUS to continuously take bitbit screenshots from the form (or the corresponding form area of the screen) to a fixed common variable memory DC object.
Cairo.ImageList.AddImage("BG", from byte or File), so I need to convert the bitmap data of the memory DC into BMP bytes, and then transmit Cairo.ImageList.AddImage("bg",buffer() as byte)
Is there a way to add a method bound to the memory DC in Cairo?
Perhaps the easiest way is to convert the SVG to a transparent PNG format, then draw the background image, and then draw the PNG image according to the size of the control.
Without using WS_EX_LAYERED, it is troublesome to use the simulation method to form a transparent effect. You need to hide the custom control first, then take a screenshot of this area of the form as the background image of the control, and then display the control.
It will flicker during operation, is there any way to deal with it?
IF I ONLY WANT LOAD BackgroundPicture once in usercontrol,how to do?
That depends on, whether your BG-Picture is UC-specific (exists once for your UC) -
or if you mean "an inherited Parent-Background".
Generally spoken - any Image you use, is a resource.
And the App-global image-resource-storage is the Cairo.ImageList-CollectionObject.
Normally the filling of this ImageList-Collection is done at App-Startup once:
- Cairo.ImageList.AddImage "SomeBGImgKey1", SomeBGImgKey1FileNameOrByteArray
- Cairo.ImageList.AddImage "SomeBGImgKey2", SomeBGImgKey2FileNameOrByteArray
- Cairo.ImageList.AddImage "SVGButtonFacePressed", SVGButtonFacePressedFileNameOrByteArray2
- Cairo.ImageList.AddImage "SVGButtonFaceReleased", SVGButtonFaceReleasedFileNameOrByteArray2
Later on, in your Controls, you only need to define Public StringKey-Variables to refer to such loaded resource-ImageKeys:
Public BGKey1$, BGKey2$, SVGPressed$, SvgReleased$
The rendering can then be done by CC.RenderSurfaceContent (which is basically an Alpha-capable version of PaintPicture) -
which in its first parameter, will accept either a cCairoSurface-Object or a StringKey into the Cairo.ImageList:
- CC.RenderSurfaceContent BGKey1$, xOffs, yOffs, DesiredWidth, DesiredHeight
- CC.RenderSurfaceContent IIF(BtnPressed, SVGPressed$, SvgReleased$) , xOffs, yOffs, DesiredWidth, DesiredHeight
when cls,Flickering problem occurred during image switching,maybe by picture1.cls?
Copy the background image to the memory DC, using double slow charge, every time you draw 2 pictures, you don’t need to clean up the image. The background image is complete, the second image superimposed above often changes, and the size may be smaller than the background area.
Create a memory DC object, first draw the background area, and then draw image 2 or image 3 on it. Then copy and draw the mixed result to the real target image dc
Last edited by xiaoyao; Apr 8th, 2021 at 03:14 AM.
Is there a way to add a method bound to the memory DC in Cairo?
I don't know what you mean exactly.
A cCairoSurface-Object (of type Image), is comparable to a DIBSection in 32BitPerPixel (without using any GDI-Handles).
And if you want to paint something on such a SurfaceObject -
you can derive a (cairo-)Drawing-Context at any time via Set CC = SrfObj.CreateContext.
In case you current problem is, that you have alread "stored" some Image in a
normal Form-Picture (or a PictureBox.Picture) - it is quite easy to avoid that -
by not storing ImageResources in such "old, GDI-reliant" ImageContainer-Objects.
Instead you should (at App-Startup) load all your ImageResources into memory as cCairoSurface-Objects
(and the Collection-like Container-Object which can do that best, is the Cairo.ImageList).
Originally Posted by xiaoyao
Without using WS_EX_LAYERED, it is troublesome to use the simulation method to form a transparent effect.
This "parent-background-copying" approach is horrible - and not recommended for "anything serious".
In the last part of my post #28, I've only shown how to do it, to give you an impression how to use
cCairoSurfaces in such a "BitBlit"-like scenario for learning-purposes.
If you want to do it "more professionally" - then:
- either use the WS_EX_LAYERED approach for UserControl-Child-hWnds
- or go "all the way", and use the Widget-based approach in post #25 (with full nested Alpha-, DPI-awareness and MouseWheel-Zoom-support).
Because I'm just treating it as a custom control. The previous example is inside the form to get a background image. Custom control to copy the corresponding area.
But my form has other controls, so what I need is a screenshot of the whole form or part of the screen.cairo Can I take a screenshot?
The custom control position has been moved, first hidden, re-intercept the entire form or the corresponding area of the entire screen, imitate the effect of transparency. And then display one or more of the images above.