One is for (Moveable) Images or Sprites -> ucPngPicture.ctl - the other is to handle
"4-State-Png-Image"-based Buttons (Normal, Hovered, Pressed, Disabled) -> ucPngButton.ctl.
Here's a ScreenShot, what the combined 4-State-Button-Pngs look like:
The Button-States-PngResources could also be adjusted to work with 5 States (e.g. when
you want to introduce also a "Focused" State - its just about enhancing the Png-Resource
about the new "State-Area" - and adding a few lines of code, which ensure the correct
Offset within the Controls "Refresh-Drawings"-routine.
To incorporate it into your existing Projects, you will have to include the 4 Files:
modPngCache.bas <- only contains a global Definition of PngCache As cPngCacheGDIp
cPngCacheGDIp.cls <- the GDI+ Handling (APIs and conversion into a 32Bit VB-StdPicture-DIB)
ucPngPicture.ctl <- the Png-Image- or Png-Sprite-Control
ucPngButton.ctl <- the (currently) 4-State-Png-Button-Implementation
The Source-Code within the Form is quite small (BTW, also demonstrating the
usage of VBs Usercontrols built-in HitTest-capabilities):
Code:
Option Explicit
Private Sub Form_Initialize() '<- early loading of all Png-Resources under their Keys (before Main-Form_Load)
'here we add true Alpha-Channel-Png-Images to the cache (with 4 Button-States per Image)
PngCache.AddImage "Home", App.Path & "\Res\Home.png"
PngCache.AddImage "Seven", App.Path & "\Res\Seven.png"
'now we cache another Alpha-Png, which will be rendered in a moveable Control
PngCache.AddImage "Tucan", App.Path & "\Res\Tucan.png"
End Sub
Private Sub Form_Load()
'just VBs normal LoadPicture-Function, providing the Forms BackGround-Img from a *.jpg
Set Picture = LoadPicture(App.Path & "\Res\Checker.jpg")
End Sub
Private Sub Form_Resize() 'this adjusts the two Btns, which share the "Seven"-Key at the LeftBottom-Form-Edge
ucPngButton(3).Move 7, ScaleHeight - ucPngButton(3).Height
ucPngButton(4).Move 54, ScaleHeight - ucPngButton(4).Height
End Sub
Private Sub Form_Paint() '<- now that's iportant here for flickerfree rendering
'to receive Form_Paint-Events, the Form needs to remain at the default (AutoRedraw = False)
'then we need to ensure, that each and every Png-Usercontrol we use on this Form, gets refreshed
'...starting with the Z-ordering "Bottom-Up" (the first refr. ucPng-Ctl is "bottom-most", a.s.o.)
ucPngPicture1.Refresh
Dim i As Long 'after the movable Png-Picture-Ctl above, we follow up with our 4 Png-Buttons below
For i = 1 To 4: ucPngButton(i).Refresh: Next
End Sub
Private Sub ucPngButton_Click(Index As Integer)
Caption = "ucPngButton " & Index & " -> " & ucPngButton(Index).Key
End Sub
'just a demonstration of the HitTest-Event (which by default, when not explicitely handled - would
'detect a Hit on the current *rectangular* Ctl-Region) - here we adjust the Hit-Detection with the
'"circle-formula" -> R = Sqr(x^2 + y^2), to the circular region of the round Buttons, so when you move
'the Mouse diagonally across the Button-"edges", it should give a hit only when you cross the circumference
Private Sub ucPngButton_HitTest(Index As Integer, X As Single, Y As Single, HitResult As HitResultConstants)
Const R = 20 '<- we define a Radius of 20 Pixels for our userdefined HitTest
Dim cx: cx = ucPngButton(Index).Width / 2
Dim cy: cy = ucPngButton(Index).Height / 2
HitResult = IIf(Sqr((X - cx) ^ 2 + (Y - cy) ^ 2) < R, vbHitResultHit, vbHitResultOutside)
End Sub
And the appropriate ScreenShot of the small Demo-App:
Have fun with it...
Olaf
Last edited by Schmidt; Feb 28th, 2014 at 06:22 PM.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Originally Posted by Schmidt
To incorporate it into your existing Projects, you will have to include the 4 Files:
modPngCache.bas <- only contains a global Definition of PngCache As cPngCacheGDIp
Wouldn't setting cPngCacheGDIp.cls'
Code:
Attribute VB_PredeclaredId = False
to True achieve the same effect as
Code:
Public PngCache As New cPngCacheGDIP 'let's have it declared here for global usage (we only need one of it for the whole App)
? (thus no more need for a standard module)
I just had to rename your demo project's cPngCacheGDIP class to PngCache in order to maintain compatibility with the existing PngCache references in your code.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Ah - good catch Bonnie.
Didn't thought about the Flag... (which is the same one, you can set in the IDE in an ActiveX-dll project per: [Instancing] Property to [6-GlobalMultiUse]).
In a normal StdExe-Project, the VB-IDE doesn't provide this Flag in its visible Interface - so one would have to resort to manually editing the *.cls-File, to achieve the desired effect.
It runs.
I spent about an hour trying to figure out how to use it.
I am stuck with the following:
I try to use this:
PngCache.AddImage "Spider", App.Path & "\Spider.png"
Set Button1 = New cButton: Button2.InitOn Me, "Spider", 100, 100
The image appears fine but when I hover the mouse over the image, the image disappears.
Could you perhaps provide an example with a standard PNG that only has 1 state?
i.e. what needs to be changed just to put a single PNG on the form ?
Then the other application should run as well IMO, because the cPngCacheGDIp.cls is to 99%
the same as in the other project (there's only some slight changes with an additional
Stretch-Parameter).
So I'd rather find out what went wrong with this Demo here on your XP-machine, because
I think that it's the more intuitive one to use in "normal scenarios".
When you write, that an error happens "here":
Public Property Get Picture(Key As String) As StdPicture
Set Picture = Images(Key)
End Property
In what line exactly - and since you're in a breakpoint then - could you please check,
if there's content at all in the Images-Collection?
e.g. by using:
?Images.Count, "should give 3"
or
?Images("Home") Is Nothing, "should give False"
or
?Images("Seven") Is Nothing, "should give False"
or
?Images("Tucan") Is Nothing, "should give False"
all in the DirectWindow, whilst you are at the breakpoint...
Maybe there's something different on XP - but if the other, earlier Demo works,
then we should be able to make this (easier to use) one work too.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Ah ...
so you're perhaps trying to assign a Png-image to the picture-prop in the Form-Designer?
That's currently not supported on this "lightweight-version" of the control(s).
You will have to assign your Png-Images to the Cache-Instance instead (once - either in Sub Main or in Form-Initialize -
as shown in the Demo, where those images are loaded as resources).
This way you can share the same Cached-Key among several instances of such a Control.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Originally Posted by Schmidt
Ah ...
so you're perhaps trying to assign a Png-image to the picture-prop in the Form-Designer?
That's currently not supported on this "lightweight-version" of the control(s).
You will have to assign your Png-Images to the Cache-Instance instead (once - either in Sub Main or in Form-Initialize -
as shown in the Demo, where those images are loaded as resources).
This way you can share the same Cached-Key among several instances of such a Control.
Olaf
------------------------------
I have not made any changes at all to your code.
Download, unzip, run.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Originally Posted by kembreg
Olaf,
When the X or Y coordinates is too high, the image will not render.
Any ideas?
I don't know which version you currently use - and would like very much,
that you upload a simple version of your own adaptions, which shows the
behaviour you mentioned (in a small zip-file).
That way it would be most painless for all and a solution could be found very fast.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Originally Posted by Schmidt
I don't know which version you currently use - and would like very much,
that you upload a simple version of your own adaptions, which shows the
behaviour you mentioned (in a small zip-file).
That way it would be most painless for all and a solution could be found very fast.
Olaf
Olaf, könntest du mir bitte eine email schicken: kembreg yahoo COMunity
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
My public E-Mail should already be exposed somewhere in my "user-info-page" here.
Though I don't understand, what's so complicated in making a small example in a fresh,
new Std-Exe-project... Even if your "real App" is much larger, you should be able to
reproduce the behaviour you see also in a small Mockup-Demo, which only contains
the source of my uploaded controls ... + the few lines (and a few "unimportant images")
of your own.
Creating something like that - checking if the error is reproducable - then uploading in a zip ...
all that should take up only 10-15 minutes.
I can ensure you, that I invested more time whilst writing this demo for the benefit of all -
why not try a bit, to save some time on my end "in return"...
If it's not the time (or your intellectual property) you're concerned about, but potential
"code-quality issues" - (fearing that others will mock you about it) - that's not happening
here IMO - there's occasional criticism, but that's a normal thing - and needed to get better
with something...
I'd just repost the Zip with my corrections and a few comments - you will see no ridiculing
from my end - but errors need to be pointed out to others - of course also my own ones
(in case it was me, who was responsible for the misbehaviour you encountered).
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Olaf,
I figuret it out.
I was rendering the images in the form "load" event event.
At design time, if the form is not big enough, the methods will not paint the images even through the "windowstate" is set to max.
During the load event, the windowstate is always "normal" regardless of what it is actually set too.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
Originally Posted by kembreg
I figuret it out.
I was rendering the images in the form "load" event event.
At design time, if the form is not big enough, the methods will not paint the images even through the "windowstate" is set to max.
During the load event, the windowstate is always "normal" regardless of what it is actually set too.
Not sure, what version of the Png-Rendering you're using now (the "older one" from the other Link, or this one here),
but if it works for you now, then fine...
For an even better (and easier to code) Png-Rendering-support you could also consider using vbRichClient5
(there's Demos for that here in the CodeBank, but also in the large Cairo-Tutorial on vbRichClient.com.
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
i fixed #4 error with this way :
Code:
in ucPngButton.ctl
Public Sub Refresh()
If Ambient.UserMode Then ScaleMode = vbPixels Else Exit Sub
If Shape1.Visible Then Shape1.Visible = False
If Label1.Visible Then Label1.Visible = False
With Extender
If .Container.AutoRedraw Then .Container.AutoRedraw = False
If .Container.ScaleMode <> vbPixels Then .Container.ScaleMode = vbPixels
If Key = "Key" Then
Exit Sub
End If
.Move .Left, .Top, PngCache.Width(Key), PngCache.Height(Key) \ PngCache.Height(Key) / PngCache.Width(Key)
PngCache.AlphaRenderTo .Container.HDc, Key, .Left, .Top, .Width, .Height, 0, .Height * State
End With
End Sub
in cPngCacheGDIP.cls
Public Property Get Picture(Key As String) As StdPicture
If Key = "Key" Then
Exit Sub
End If
Set Picture = Images(Key)
End Property
Public Property Get Width(Key As String) As Long
If Key = "Key" Then
Exit Sub
End If
Width = Picture(Key).Width / Screen.TwipsPerPixelX * 0.566929133858268
End Property
Public Property Get Height(Key As String) As Long
If Key = "Key" Then
Exit Sub
End If
Height = Picture(Key).Height / Screen.TwipsPerPixelY * 0.566929133858268
End Property
Public Sub AlphaRenderTo(ByVal HDc As Long, Key As String, Optional ByVal X As Long, Optional ByVal Y As Long, _
Optional ByVal dX As Long, Optional ByVal dY As Long, _
Optional ByVal XSrc As Long, Optional ByVal YSrc As Long, _
Optional ByVal Stretch As Boolean, Optional ByVal GlobalAlpha As Double = 1)
If dX = 0 Then dX = Width(Key)
If dY = 0 Then dY = Height(Key)
If Key = "Key" Then
Exit Sub
End If
If Picture(Key).Handle Then OldBM = SelectObject(mhDC, Picture(Key).Handle)
If Stretch Then
GdiAlphaBlend HDc, X, Y, dX, dY, mhDC, XSrc, YSrc, Width(Key), Height(Key), 2 ^ 24 + &HFF0000 * GlobalAlpha
Else
GdiAlphaBlend HDc, X, Y, dX, dY, mhDC, XSrc, YSrc, dX, dY, 2 ^ 24 + &HFF0000 * GlobalAlpha
End If
If OldBM Then SelectObject mhDC, OldBM
End Sub
Re: VB6 lightweight PNG-Controls (4-State-PngButtons and a moveable Png-Image/Sprite)
I have written one of my life's largest VB6 control project, PNG transparent button.I don't know if I did it wrong, because once the control is transparent, it can't be placed on top of other images or webbrowers.
So my idea is to use a non-transparent control, if I place the custom control on a button or a table control, my practice is to copy the elements behind the control as images into my custom control.
If I want to put this custom control above the playing video, it will not be truly transparent.The above content is used translation software, attached to the original Chinese.
我曾经写过一个我人生中最大的vb6 控件工程,png透明按钮。我不知道我是不是做错了,因为一旦控件透明,他就没办法放置在其他图像或者网页控件webbrower上面。
所以我的想法是用非透明的控件,如果我这个自定义控件放置在一个按钮或者表格控件上面,我的做法是先把控件后面的元素以图片方式复制到我的自定义控件里面。
如果要把我这个自定义控件放置在正在播放的视频上面,它就没办法做到真正的透明。以上内容是用翻译软件,附上原来的中文。