我只是在寻找简单问题的答案。这是
我有一个pricturebox,其图片具有透明background
我将图片框backcolor
设置为透明。
之后,图片显示透明bg
。但在我添加此代码之后
ìmg1.Left = windows.forms.cursor.Position.X - me.Left
ìmg1.Top= windows.forms.cursor.Position.Y - me.Top
'code for using img as cursor
图像bg并不像这样透明
我认为透明backcolor
并不是真正透明的。它只会获取表单的backcolor
并将其用作图片的backcolor
而非透明。
有没有解决方案让它完全透明?
答案 0 :(得分:5)
你的假设是对的。
winforms中的透明度并不意味着对象实际上是透明的。相反,它意味着它将显示它的父对象而不是它的背景,包括它的背景,图像和文本,但不包括任何其他控件,因此你的问题。登记/>
由于您最顶部的图片框的父控件不是也不能是其他图片框,因此您最顶部的图片框具有透明背景这一事实无济于事。
不幸的是,使用表单TransparencyKey
属性也无济于事。 (它会使所选颜色透明,但会产生意外(通常是不需要的)结果。
为了实现您的目标,您必须在评论中遵循OneFineDay的建议,并使用Graphics
自行绘制图像。
幸运的是,这很容易做到:
Public Sub DrawImage(Image as Image, Location As Point)
Using(Dim g as Graphics = Me.CreateGraphics())
g.DrawImage(Image, Location)
EndUsing
End Sub
答案 1 :(得分:2)
这blog article启发了此SO answer。这些是通过缩放,文本,内容对齐等进行更强大控制的基础。
以下是缩放版本(在VB中),主要实现真正透明度的外观。核心绘画与original SO post几乎完全相同,只是为了说明绘画中的边界。还保留了一些控制级功能。
'Namespace omitted to reduce indentation
Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Public Class TransPicBox
Inherits PictureBox
Public Enum ImageSizing
None
Stretch
Scale
End Enum
Public Sub New()
' defaults for a new one
MyBase.BackColor = Color.Transparent
MyBase.InitialImage = Nothing
MyBase.ErrorImage = Nothing
MyBase.Image = Nothing
End Sub
Public Overloads Property Image As Image
Get
Return MyBase.Image
End Get
Set(value As Image)
MyBase.Image = value
InvalidateParent()
End Set
End Property
Private imgSizing As ImageSizing = ImageSizing.None
Public Property ImageSizing As ImageSizing
Get
Return imgSizing
End Get
Set(value As ImageSizing)
imgSizing = value
InvalidateParent()
End Set
End Property
' because the child control displays are interdependent
' tell the parent to update when some things change
' Image, Scaling, Border, Text, BackColor etc
Private Sub InvalidateParent()
Invalidate()
If MyBase.Parent IsNot Nothing Then
MyBase.Parent.Invalidate()
End If
End Sub
' since the display depends on ZOrder, provide
' a control method to alter it
Public Sub MoveUpZOrder()
ChangeZOrder(-1)
End Sub
Public Sub MoveDownZOrder()
ChangeZOrder(+1)
End Sub
Private Sub ChangeZOrder(value As Int32)
Dim ndx As Integer = Parent.Controls.GetChildIndex(Me)
If ((ndx + value) >= 0) AndAlso ((ndx + value) < Me.Parent.Controls.Count) Then
Me.Parent.Controls.SetChildIndex(Me, ndx + value)
End If
End Sub
' if you want to remove properties, this is how
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never)>
Public Shadows Property ErrorImage As Image
Protected Overrides Sub OnPaintBackground(pevent As PaintEventArgs)
If MyBase.BackColor = Color.Transparent Then
' magic happens here!
PaintSiblings(pevent)
Else
' do nothing special when the backcolor is not Transparent
MyBase.OnPaintBackground(pevent)
End If
End Sub
' code for painting the image
Protected Overrides Sub OnPaint(pe As PaintEventArgs)
Dim rect As Rectangle
If (MyBase.Image IsNot Nothing) Then
rect = GetImgRect(Bounds)
pe.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
pe.Graphics.CompositingQuality = CompositingQuality.HighQuality
pe.Graphics.SmoothingMode = SmoothingMode.HighQuality
pe.Graphics.DrawImage(Image, rect)
End If
End Sub
Private Sub PaintSiblings(e As PaintEventArgs)
' need to access the parent' controls collection
If (Parent IsNot Nothing) Then
Dim borderSize As Integer = 0
Dim thisLeft As Single = -Left
Dim thisTop As Single = -Top
' fix
Select Case MyBase.BorderStyle
Case BorderStyle.FixedSingle
borderSize = SystemInformation.BorderSize.Width
Case BorderStyle.Fixed3D
borderSize = SystemInformation.Border3DSize.Width
End Select
' Shift ClipBounds to form relative coords
e.Graphics.TranslateTransform(thisLeft, thisTop)
' Get Parent to paint the part behind us:
' we cant know if thats been done or not
Using pea As New PaintEventArgs(e.Graphics, e.ClipRectangle)
InvokePaintBackground(Parent, pea)
InvokePaint(Parent, pea)
End Using
' shift back
e.Graphics.TranslateTransform(-thisLeft, -thisTop)
' starting control index is...well, ours
Dim startAt As Integer = Parent.Controls.GetChildIndex(Me)
Dim ctl As Control
' Controls are in z-Order, so loop
' thru the controls "behind" me
For n As Int32 = Parent.Controls.Count - 1 To startAt + 1 Step -1
ctl = Parent.Controls(n)
' skip if they are invisible, too small or do not overlap me
If (ctl.Visible = False OrElse
ctl.Width = 0 OrElse
ctl.Height = 0 OrElse
Bounds.IntersectsWith(ctl.Bounds) = False) Then
Continue For
Else
Using bmp As New Bitmap(ctl.Width, ctl.Height, e.Graphics)
' draw this sibling to a bitmap
ctl.DrawToBitmap(bmp, New Rectangle(0, 0, ctl.Width, ctl.Height))
' shift the orientation relative to sibling and draw it
thisLeft = ctl.Left - Left
thisTop = ctl.Top - Top
'offset, then draw the image, reset
e.Graphics.TranslateTransform(thisLeft - borderSize,
thisTop - borderSize)
e.Graphics.DrawImageUnscaled(bmp,
New Point(0, 0))
e.Graphics.TranslateTransform(-thisLeft + borderSize,
-thisTop + borderSize)
End Using
End If
Next
Else
' not sure how this could happen
Using br As New SolidBrush(MyBase.BackColor)
e.Graphics.FillRectangle(br, ClientRectangle)
End Using
End If
End Sub
' image scaling is mainly a matter of the size and location
' of the img rect we use in Paint
Private Function GetImgRect(destRect As Rectangle) As Rectangle
Dim pt As New Point(0, 0)
Dim sz As Size
If MyBase.Image IsNot Nothing Then
Select Case Me.ImageSizing
Case ImageSizing.None
sz = Image.Size
Case ImageSizing.Scale
If Width > Height Then
sz = New Size(GetScaledWidth(Height), Height)
Else
sz = New Size(Width, GetScaledHeight(Width))
End If
Case ImageSizing.Stretch
sz = Me.Size
End Select
End If
' ToDo: move the pt if you add an Image ContentAlignment
' (Top, TopLeft, BottomRight...) property
Return New Rectangle(pt, sz)
End Function
Private Function GetScaledWidth(h As Integer) As Integer
Dim scale As Single = CSng(Image.Width / Image.Height)
Return CInt(h * scale)
End Function
Private Function GetScaledHeight(w As Integer) As Integer
Dim scale As Single = CSng(Image.Height / Image.Width)
Return CInt(w * scale)
End Function
End Class
Imports
语句TransPicBox
。您还可以在项目中包含类代码文件并重建以避免DLL依赖项,其中只包含一项内容。结果:
ImageSizing.Scale
大约150%父背景显示通过TL和BR图像以及前面重叠的较大图像。控件将正常显示BMP和JPG,并且当控件的背面颜色为透明时,仍会在空白区域(如果有)后面显示。