Question

I got following code to load a PNG with alpha channel on to a form and reshape a form to match alpha channel.

Public Function applyAlphaForm(ByVal f As Form, ByVal bitmap As Bitmap, Optional ByVal opacity As Byte = 255) As Boolean
    f.FormBorderStyle = FormBorderStyle.None
    Dim style As Long
    style = Win32.GetWindowLong(f.Handle, Win32.GWL_EXSTYLE)
    If Not (style And Win32.WS_EX_LAYERED = Win32.WS_EX_LAYERED) Then
        style = style Or Win32.WS_EX_LAYERED
        Win32.SetWindowLong(f.Handle, Win32.GWL_EXSTYLE, style)
    End If
    Return SetBitmap(f, bitmap, opacity)
End Function

Public Function SetBitmap(ByVal f As Form, ByVal bitmap As Bitmap, ByVal opacity As Byte) As Boolean
    f.Height = bitmap.Height
    f.Width = bitmap.Width
    If bitmap.PixelFormat <> PixelFormat.Format32bppArgb Then
        f.BackgroundImage = bitmap
        f.TransparencyKey = bitmap.GetPixel(0, 0)
        Return True
    End If

    Dim screenDC As IntPtr = Win32.GetDC(IntPtr.Zero)
    Dim memDC As IntPtr = Win32.CreateCompatibleDC(screenDC)
    Dim hBitmap As IntPtr = IntPtr.Zero
    Dim oldBitmap As IntPtr = IntPtr.Zero

    Try
        hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)) 'grab a GDI handle from this GDI+ bitmap
        oldBitmap = Win32.SelectObject(memDC, hBitmap)

        Dim size As Win32.Size = New Win32.Size(bitmap.Width, bitmap.Height)
        Dim pointSource As Win32.Point = New Win32.Point(0, 0)
        Dim topPos As Win32.Point = New Win32.Point(f.Left, f.Top)
        Dim blend As Win32.BLENDFUNCTION = New Win32.BLENDFUNCTION()
        blend.BlendOp = Win32.AC_SRC_OVER
        blend.BlendFlags = 0
        blend.SourceConstantAlpha = opacity
        blend.AlphaFormat = Win32.AC_SRC_ALPHA

        Win32.UpdateLayeredWindow(f.Handle, screenDC, topPos, size, memDC, pointSource, 0, blend, Win32.ULW_ALPHA)

    Catch ex As Exception
    Finally
        Win32.ReleaseDC(IntPtr.Zero, screenDC)
        If hBitmap <> IntPtr.Zero Then
            Win32.SelectObject(memDC, oldBitmap)
            Win32.DeleteObject(hBitmap)
        End If
        Win32.DeleteDC(memDC)
    End Try
    Return True
End Function

Nice and easy but if I put some control (button, text box ...) on the form, they will disappear. I guest that UpdateLayeredWindow will paint over the form hDC so we can't see anything behind it. So how to draw some form control on the form? I've try to loop through all control and render to png bitmap before calling api but that will be static image.

Was it helpful?

Solution

So I guest I have to create two from, a background form alpha transparent and a foreground form with control on it. The control form will only display the area of control.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top