I am attempting to overlay two transparent images within a winform, but it keeps rendering the form's background image behind the top transparent image, as opposed to the second image...
My basic set up is I have two panels and in each panel is a picturebox. Each image in the picture boxes have some transparent areas. I've set the BackColor of the panels to color.transparent.
When I make one panel overlay the other I'm seeing the form's backcolor come through as opposed to the underlaying image.
Am I missing a property that I can set?
You only need one picture box. The overlay can be done with graphics.
Imports System.Drawing
Dim OverlayImage As New Bitmap("Some Path", True)
Dim BackImage As New Bitmap("Some Path", True)
g As Graphics = Graphics.FromImage(BackImage)
g.DrawImage(OverlayImage, 0, 0)
pictureBox1.Image = BackImage
If you want to have the timer move the overlayed image, then first, make a variable Dim posX As Integer = 0
then use g.DrawImage(OverlayImage, posX, 0) Now when your timer ticks, increment posX by 10
Here's a complete function to overlay two images (adapted from Blue0500's answer):
''' <summary> Return a new image with one superimposed over the other. </summary>
Function OverlayImgs(ByVal BackgroundImg As System.Drawing.Bitmap, ByVal OverlayImg As System.Drawing.Bitmap, Position As System.Drawing.Point) As System.Drawing.Bitmap
Dim g = System.Drawing.Graphics.FromImage(BackgroundImg)
g.DrawImage(OverlayImg, Position)
Return BackgroundImg
End Function
Usage:
lblTest.Image = OverlayImgs(Img1, Img2, New Point(16, 16))
You don't need a PictureBox for this unless you are using it for the canvas. You can draw all images to a Rectangle structure and move them around. Personally I would create a class object that has a Rectangle, Image and other properties and hold them in a collection. Then you simply draw the class objects by there properties including location. If there images contain transparencies they will overlay for you. This also gives you a method to check for collisions via the Rectangle.IntersectsWith function.
Related
I have a Picturebox which I draw a view to (Gantt View in this case) and it works OK - i.e., the view is drawn and the AutoScroll property allows the image in the PictureBox to be smoothly scrolled.
My problem is, the header of the image (e.g., the date headers in this case) scroll off the top of the display when I scroll down the image.
What I can't work out is how to fix a header to the top. I thought about simply drawing a header into another Picturebox, but then I am not sure how to sync the header with the left-right scrolling of the main PictureBox
Can someone suggest the best approach to handling this, or do I need to revert to doing a direct draw and handle the scrolling myself?
I am using VB with VS 2015.
Many thanks
Phil
Updated - I am now using an off-screen Bitmap, but can someone look at the code below and let me know if there is a faster/better way to do this? It all works, but still learning and so always looking to do things the best way
Public Sub MoveViewPoint(G As Graphics)
' G passed in from controls Paint
G.Clear(Color.WhiteSmoke)
' _Plan is off-screen bitmap of image
' _HeaderHeight is height of the Header area in _Plan
Dim Header_src_rect As New Rectangle(_HScroll.Value, 0, _Plan.Width, _HeaderHeight)
Dim Header_dst_rect As New Rectangle(0, 0, _Plan.Width, _HeaderHeight)
G.DrawImage(_Plan, Header_dst_rect, Header_src_rect, GraphicsUnit.Pixel)
Dim src_rect As New Rectangle(_HScroll.Value, _HeaderHeight + 1 + _VScroll.Value, _Plan.Width, _Plan.Height)
Dim dst_rect As New Rectangle(0, _HeaderHeight + 1, _Plan.Width, _Plan.Height)
G.DrawImage(_Plan, dst_rect, src_rect, GraphicsUnit.Pixel)
_HScroll.LargeChange = G.ClipBounds.Width * 0.9
_VScroll.LargeChange = G.ClipBounds.Height * 0.9
End Sub
I would do all your drawing to an off-screen bitmap using the GDI graphics system. You can draw your headers and the rest of the chart as 2 distinct stages in the same bitmap. You would have to handle the scrolling yourself by watching the MouseMove event and checking the buttons status.
hope i can get some help here.
For a VB app, I try to place one picturebox over GDI+ drawn image (or another picturebox) in visual studio 2008, and the picturebox includes transparent areas which don't come up transparent.
I have looked through many methods but they don't suit my situation:
a background is drawn using GDI, and for my app I need a picturebox stationary upon it. (the stationary image cant be GDI+ drawn too, because the background updates every while, which causes it to disappear. tried to redraw image also but it makes an ugly flickering effect).
when i try to use picturebox as background, and assign it as parent for the overlaying image for transparency effect, the above image doesn't show at all. here is the VB code:
Dim back As PictureBox
Dim silhouetteAs PictureBox
Dim img As Bitmap = New Bitmap(imgPath)
img.MakeTransparent(Color.White)
back = New PictureBox()
silhouette= New PictureBox()
silhouette.Parent = back
silhouette.Size = New Point(width, height)
silhouette.Location = New Point(xpos, ypos)
silhouette.Image = img
silhouette.BackColor = Color.Transparent
back.Parent = MAIN
back.Size = New Point(width, height)
back.Location = New Point(xpos, ypos)
back.BackColor = Color.Blue
where back is the background and silhouette is the on-top image.
can someone please provide an example of how transparency achieved through parenting pictureboxes? or any other solution to this situation?
Never mind, found out what was wrong - when I assigned another picturebox as a parent, I didn't update the location of the overlaying picturebox relatively. the correction would be to
add:
silhouette.location=new point(0,0)
forgot that the coordinates are relative to the parent and not the form anymore.
I have a program where I am attempting to render an image in Direct2D onto a quadrilateral using SlimDX and VB.net.
The program gets an array of 4 points from a server, which are a quadrilateral, where the image should be rendered onto.
The points (For example) are:
points(0) = 20,10 <--Top left, where the geometry starts from
points(1) = 40,10 <-- Top right
points(2) = 40,40 <-- Bottom right
points(3) = 20,40 <-- Bottom left
...A BitmapBrush is constructed when loading and the Bitmap can be rendered fine, but when trying to render onto the quadrilateral, I only get (it seems...) some part the bottom right corner.
For reference: Here is the image I'm trying to draw:
http://i.imgur.com/Dt3iHQ3.png
And here is the code that I'm trying to use (for drawing the image).
R is the point list (see above) and RenderBrush is a BitmapBrush created from a 20x30 version of that image.
Private Sub DrawPoly(R() As PointF, ByRef RenderBrush As SlimDX.Direct2D.BitmapBrush)
'Create the geometry
Dim Path As PathGeometry
Path = New PathGeometry(factoryD2D)
Console.Clear()
'Get a handle to the Geometry
Dim Geometry = Path.Open()
'Set UP Geometry
Geometry.BeginFigure(R(0), FigureBegin.Filled)
Geometry.AddLines(R)
Geometry.EndFigure(FigureEnd.Closed)
Geometry.Close()
'Render
D2DRenderTarget.FillGeometry(Path, RenderBrush)
'and GC
Geometry.Dispose()
Path.Dispose()
End Sub
Thanks in advance for your help!
I figured it out. To get it to draw onto the geometry, you need to set up a transformation matrix like so:
Matrix3x2.Multiply(Matrix3x2.Translation(Point_To_Move_To), Matrix3x2.Rotation(Rotation, Point_To_Rotate_Around))
I am creating program with multileyered picturebox, the image of picturebox is update dynamically from bitmap in memory, and i want to clear the selected part on bitmap to transparent color so i can see image of picturebox behind it.
Here is my code
Dim gBmp As Graphics = Graphics.FromImage(GraphLayer(LayerArray))
Dim TileSrcCrop As New Rectangle(nVal(xTile), nVal(yTile), TileSize, TileSize)
Dim TileDrawSize As New Rectangle(nVal(H), nVal(V), TileSize, TileSize)
gBmp.DrawImage(GraphImage(LayerArray), TileDrawSize, TileSrcCrop, GraphicsUnit.Pixel)
PicMap(LayerArray).Image = GraphLayer(LayerArray)
Thanks
What I'm about to say may only be for Windows icons, but IIRC, the top left pixel must be assigned the color that you want to designate as the color for transparency. You'll usually see MS use Magenta (255, 0, 255). This is called a transparency mask. Then, anywhere you want the color to be transparent, you use the color you placed in the top left pixel.
HTH -- and let me know if it's only for icons, but I think it's for Windows bitmap files, too.
How do I reduce flicker in a vb2005 panel?
Inside the parent panel I have 2 other panels that I'm am using.
The outer most panel contains a background sprite and the two innermost panels are overlays that change to fit the places in the background sprite.
When I change the overlay sprites I would like to reduce the flicker and make it a smooth transition from one sprite to the next.
Here is the code that changes the images in the overlay panels
the overlay panel is not changed if the new value is the same as the old value
Private Sub TrackBar2_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar2.Scroll, TrackBar1.Scroll
If (Panel2.Tag <> TrackBar1.Value) Then
Panel2.Tag = TrackBar1.Value
Panel2.BackgroundImage = tops(TrackBar1.Value) //img array for the top panel
Panel2.Update()
End If
If (Panel3.Tag <> TrackBar2.Value) Then
Panel3.Tag = TrackBar2.Value
If (TrackBar2.Value > 0) Then
Panel3.Location = New Point(182, 210)
Else
Panel3.Location = New Point(182, 209)
End If
Panel3.BackgroundImage = bottoms(TrackBar2.Value)//img array for the bottom panel
Panel3.Update()
End If
You're not going to like this answer. The flicker is caused by the fact that the default .NET panel is not double buffered - so it does all the drawing directly in the visible memory, not a back buffer.
You need to subclass the Panel class and enable double buffering on the new class. This can be done by doing a
SetStyle
call in the constructor with the flags OptimisedDoubleBuffering and DoubleBuffering enabled.
Once you have the new panel class that is double buffered, you can use them in your application instead of the standard Panel.
I told you you wouldn't like the answer ;)
Rein is right, subclassing is the best way. In the meantime though, change that call from Update to Invalidate; that might help a little.