|
-
Sep 18th, 2005, 03:29 PM
#1
Thread Starter
Addicted Member
[RESOLVED] UpdateLayeredWindow - help!
I am trying to accomplish an effect similar to programs like Konfabulator and DesktopX which use the UpdateLayeredWindow API to achieve vista-like window layering. I need to create a translucent form with ranging alpha values based on a png image. So basically, I have want to be able to create custom forms which support alpha-blending directly to the desktop. (I am NOT trying to simply change the opacity of a form).
MSDN Library briefly explains in the documentation for the UpdateLayeredWindow API how to do this but I cant get it to work, mostly because my lack of experience with api's. Perhaps someone can make sense of it: http://msdn.microsoft.com/library/de...eredwindow.asp
So here's my question(s):
How do you use pointers (IntPtr) to pass objects to an API
How do you pass objects like the RECT structure to an API, because visual basic doesnt have a RECT structure... it has the rectangle type
Here is my code... The api is encountering errors so it is returning false... Could someone please help me fix this/get it to work?
VB Code:
Public Class Form1
Private Structure BLENDFUNCTION
Public BlendOp As Byte
Public BlendFlags As Byte
Public SourceConstantAlpha As Byte
Public AlphaFormat As Byte
End Structure
'AlphaFormat flags
Private Const AC_SRC_OVER As Long = &H0&
Private Const AC_SRC_ALPHA = &H1
Private Declare Function UpdateLayeredWindow Lib "user32" Alias "UpdateLayeredWindow" (ByVal hwnd As Long, ByVal hdcDst As Long, ByVal pptDst As Object, ByVal psize As Object, ByVal hdcSrc As Long, ByVal pptSrc As Object, ByVal crKey As Long, ByVal pblend As BLENDFUNCTION, ByVal dwFlags As Long) As Long
Private Const ULW_COLORKEY As Long = &H1&
Private Const ULW_ALPHA As Long = &H2&
Private Const ULW_OPAQUE As Long = &H4&
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Opacity = 0.9 'set the opacity to somthing to its a layered window...
End Sub
Dim Graphics As Graphics
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.Clear(Color.Transparent) 'I cant figure out how to create a graphics objet because they have no constructors so I am using the form's graphics object instead...
e.Graphics.DrawImage(My.Resources.alpha, New Point(0, 0)) 'the multi-alpha-channel png image that we want the form to look like
Dim blend As BLENDFUNCTION
blend.AlphaFormat = AC_SRC_OVER
blend.SourceConstantAlpha = 0
blend.BlendFlags = 0
blend.BlendOp = AC_SRC_OVER
If UpdateLayeredWindow(Me.Handle, 0&, 0&, 0&, 0&, e.Graphics.GetHdc(), 0&, blend, ULW_ALPHA) = True Then
MsgBox("it worked")
Else
MsgBox("there was an error") 'it is throwing errors at this point... i havnt gotten it to work yet
End If
End Sub
End Class
-
Sep 18th, 2005, 04:45 PM
#2
Re: UpdateLayeredWindow - help!
here's a link to a C# example on the codeproject >> link <<
it shouldn't be to hard to translate to vb.net
~
if a post is resolved, please mark it as [Resolved]
protected string get_Signature(){return Censored;}
[vbcode][php] please use code tags when posting any code [/php][/vbcode]
-
Sep 18th, 2005, 07:18 PM
#3
Thread Starter
Addicted Member
Re: UpdateLayeredWindow - help!
Ive seen it... I guess I could try translating it...
-
Sep 19th, 2005, 05:53 PM
#4
Thread Starter
Addicted Member
Re: UpdateLayeredWindow - help!
Ok, I have completely converted the C# code to visual basic (im using the beta). I am getting some errors though.
Here is the C# code I am trying to convert:
VB Code:
;
// class that exposes needed win32 gdi functions.
class Win32
{
public enum Bool
{
False= 0,
True
};
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public Int32 x;
public Int32 y;
public Point(Int32 x, Int32 y) { this.x= x; this.y= y; }
}
[StructLayout(LayoutKind.Sequential)]
public struct Size {
public Int32 cx;
public Int32 cy;
public Size(Int32 cx, Int32 cy) { this.cx= cx; this.cy= cy; }
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct ARGB
{
public byte Blue;
public byte Green;
public byte Red;
public byte Alpha;
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
public const Int32 ULW_COLORKEY = 0x00000001;
public const Int32 ULW_ALPHA = 0x00000002;
public const Int32 ULW_OPAQUE = 0x00000004;
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
[DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
[DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", ExactSpelling=true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
public static extern Bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling=true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
public static extern Bool DeleteObject(IntPtr hObject);
}
/// <para>Your PerPixel form should inherit this class</para>
class PerPixelAlphaForm : Form
{
public PerPixelAlphaForm()
{
// This form should not have a border or else Windows will clip it.
FormBorderStyle = FormBorderStyle.None;
}
/// <para>Changes the current bitmap.</para>
public void SetBitmap(Bitmap bitmap)
{
SetBitmap(bitmap, 255);
}
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
public void SetBitmap(Bitmap bitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
// The ideia of this is very simple,
// 1. Create a compatible DC with screen;
// 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
// 3. Call the UpdateLayeredWindow.
IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try {
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
oldBitmap = Win32.SelectObject(memDc, hBitmap);
Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Point pointSource = new Win32.Point(0, 0);
Win32.Point topPos = new Win32.Point(Left, Top);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = opacity;
blend.AlphaFormat = Win32.AC_SRC_ALPHA;
Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
}
finally {
Win32.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero) {
Win32.SelectObject(memDc, oldBitmap);
//Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}
protected override CreateParams CreateParams
{
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
return cp;
}
}
}
Here is my visual basic version which has some errors:
VB Code:
Public Class Win32API
Public Enum Bool
iFalse = 0
iTrue = 1
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure Point
Public x As Int32
Public y As Int32
Public Sub New(ByVal cx As Int32, ByVal cy As Int32)
x = cx
y = cy
End Sub
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure Size
Public cx As Int32
Public cy As Int32
Public Sub New(ByVal x As Int32, ByVal y As Int32)
cx = x
cy = y
End Sub
End Structure
Structure ARGB
Public Blue As Byte
Public Green As Byte
Public Red As Byte
Public Alpha As Byte
End Structure
Public Structure BLENDFUNCTION
Public BlendOp As Byte
Public BlendFlags As Byte
Public SourceConstantAlpha As Byte
Public AlphaFormat As Byte
End Structure
Public Const ULW_COLORKEY As Byte = &H1
Public Const ULW_ALPHA As Byte = &H2
Public Const ULW_OPAQUE As Byte = &H4
Public Const AC_SRC_OVER As Byte = &H0&
Public Const AC_SRC_ALPHA As Byte = &H1
Public Declare Function UpdateLayeredWindow Lib "user32" (ByVal hWnd As Long, ByVal hdcDst As IntPtr, ByVal pptDst As Point, ByVal psize As Size, ByVal hdcSrc As IntPtr, ByVal pptSrc As Point, ByVal crKey As IntPtr, ByVal pblend As BLENDFUNCTION, ByVal dwFlags As IntPtr) As Long
Public Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Public Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
Public Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
End Class
Public Class AlphaForm
Inherits System.Windows.Forms.Form
Private alpha As Integer
Private back As Bitmap
Sub New(ByVal background As Bitmap, ByVal opacity As Double)
If background.PixelFormat = Imaging.PixelFormat.Format32bppArgb Then
back = background
Else
MsgBox("The image provided must be a valid 32bppARGB PNG", MsgBoxStyle.Critical, "DuroBlend - Fatal Error")
Me.Close()
End If
If opacity > 1 Then
opacity = 1
End If
If opacity < 0.01 Then
opacity = 0.01
End If
alpha = opacity * 255
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
End Sub
Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Integer
Declare Function GetWindowDC Lib "user32" Alias "GetWindowDC" (ByVal hwnd As Integer) As Integer
Private Sub AlphaForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' I am using the msgboxes to figure out what line the error occures at when im debugging because you cant run control libraries so i am using it in a seperate project
MsgBox("line1")
Dim screenDc As IntPtr = GetWindowDC(GetDesktopWindow)
MsgBox("line2")
Dim memDc As IntPtr = Win32API.CreateCompatibleDC(screenDc)
MsgBox("line3")
Dim hBitmap As IntPtr = 0
MsgBox("line4")
Dim oldBitmap As IntPtr = 0
MsgBox("line5")
Try
MsgBox("line6")
hBitmap = back.GetHbitmap 'color.transparent
MsgBox("line7")
oldBitmap = Win32API.SelectObject(memDc, hBitmap)
MsgBox("line8")
Dim size As Win32API.Size
MsgBox("line9")
size.cx = back.Width
MsgBox("line10")
size.cy = back.Height
MsgBox("line11")
Dim pointsource As Win32API.Point
MsgBox("line12")
pointsource.x = 0
MsgBox("line13")
pointsource.y = 0
MsgBox("line14")
Dim topPos As Win32API.Point
MsgBox("line15")
topPos.x = Me.Left
MsgBox("line16")
topPos.y = Me.Top
MsgBox("line17")
Dim blend As Win32API.BLENDFUNCTION
MsgBox("line18")
blend.BlendOp = Win32API.AC_SRC_OVER
MsgBox("line19")
blend.BlendFlags = 0
MsgBox("line20")
blend.SourceConstantAlpha = alpha
MsgBox("line21")
blend.AlphaFormat = Win32API.AC_SRC_ALPHA
MsgBox("line22")
Win32API.UpdateLayeredWindow(Me.Handle, screenDc, topPos, size, memDc, pointsource, 0, blend, Win32API.ULW_ALPHA)
MsgBox("line23")
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Any help at all is highly appreciated
-
Sep 19th, 2005, 10:38 PM
#5
Re: UpdateLayeredWindow - help!
If it is any help I have a nice example from PSC that shows how to do proper Alpha blending using a PNG image. It is in VB6 however but shouldn't be hard to convert. I can upload it later when I'm home.
-
Sep 20th, 2005, 04:59 PM
#6
Thread Starter
Addicted Member
Re: UpdateLayeredWindow - help!
ok, I sucessfully converted the code using the c# converter at developer fusion. If anyone wants it, pm me.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|