根据一副png图片绘制半透明窗体时,用了WS_EX_LAYERED后当前窗体再也不会处理paint事件,所以所含的子控件是一辈子也不会画出来的,但是这个控件确实存在,而且可以响应事件 。而此时windows画制窗体是使用UpdateLayeredWindow这个api函数的。
其实这个问题,3年前就在csdn网友miky的"笨笨钟"发布后就讨论过了,后来出了一个叫桌面天气秀 的东东也采用类似的技术。那时候我有幸拿到了miky的delphi下实现gdi+半透明窗体的一段代码,因为无法画出button等控件和 几位高人讨论过,这里是当时的讨论情况
http://borland.mblogger.cn/jinjazz/posts/21093.aspx
最终并没有很好的解决办法,而是通过大概如下的方法解决的
————————————————————————————————————
对于按钮,完全可以自己画两个图片然后盖在button上面,通过处理button的enter和leave消息来切换者两个图片来表达按钮状态
对于输入框..这个可以用一个让任何人看了都生气地办法,那就是....两个窗体 ,的确别人就是这么做的
可以用一个空心窗体只显示该显示的控件,然后盖在你的半透明窗体上面,并处理半透明窗体的move事件,让另外一个窗体同步移动或者做其它事情
效果如下:
以下是一些C#代码,Delphi的就不贴了
主Form的代码
using
System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace WindowsApplication7
{
public class Form1:System.Windows.Forms.Form
{
private System.ComponentModel.IContainercomponents;
public Form1()
{
//
// Windows窗体设计器支持所必需的
//
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
}
///
/// 清理所有正在使用的资源。
///
protected override void Dispose( bool disposing)
{
if (disposing)
{
if (components != null )
{
components.Dispose();
}
}
base .Dispose(disposing);
}
WindowsFormDesignergeneratedcode
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main()
{
Application.Run( new Form1());
}
Form2controlFrm = new Form2();
private void button1_Click( object sender,System.EventArgse)
{
MessageBox.Show(controlFrm,controlFrm.textBox1.Text);
}
protected override CreateParamsCreateParams
{
get
{
CreateParamscp = base .CreateParams;
cp.ExStyle |= 0x00080000 ; // ThisformhastohavetheWS_EX_LAYEREDextendedstyle
return cp;
}
}
private void SetStyle1()
{
Bitmapbm = Image.FromFile( @" Green.png " ) as Bitmap;
Bitmapbm2 = Image.FromFile( @" btn.png " ) as Bitmap;
Graphicsg = Graphics.FromImage(bm);
g.DrawImage(bm2, 20 , 20 , new Rectangle( 0 , 0 , 90 , 50 ),GraphicsUnit.Pixel);
g.DrawString( " byjinjazz " , new Font( " Ariel " , 9 ,FontStyle.Bold), new SolidBrush(Color.Black), new PointF( 40 , 50 ));
this .SetBitmap(bm, 255 );
}
private void SetStyle2()
{
Bitmapbm = Image.FromFile( @" Green.png " ) as Bitmap;
Bitmapbm2 = Image.FromFile( @" btn.png " ) as Bitmap;
Graphicsg = Graphics.FromImage(bm);
g.DrawImage(bm2, 15 , 15 , new Rectangle( 7 , 140 , 100 , 50 ),GraphicsUnit.Pixel);
g.DrawString( " byjinjazz " , new Font( " Ariel " , 9 ,FontStyle.Bold), new SolidBrush(Color.Black), new PointF( 40 , 50 ));
this .SetBitmap(bm, 255 );
}
private void Form1_Load( object sender,System.EventArgse)
{
controlFrm.Show();
SetStyle1();
// this.TopMost=true;
controlFrm.TopMost = true ;
}
private void button1_MouseEnter( object sender,EventArgse)
{
SetStyle2();
}
private void button1_MouseLeave( object sender,EventArgse)
{
SetStyle1();
}
public void SetBitmap(Bitmapbitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException( " Thebitmapmustbe32pppwithalpha-channel. " );
// Theideiaofthisisverysimple,
// 1.CreateacompatibleDCwithscreen;
// 2.Selectthebitmapwith32bppwithalpha-channelinthecompatibleDC;
// 3.CalltheUpdateLayeredWindow.
IntPtrscreenDc = Win32.GetDC(IntPtr.Zero);
IntPtrmemDc = Win32.CreateCompatibleDC(screenDc);
IntPtrhBitmap = IntPtr.Zero;
IntPtroldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb( 0 )); // grabaGDIhandlefromthisGDI+bitmap
oldBitmap = Win32.SelectObject(memDc,hBitmap);
Win32.Sizesize = new Win32.Size(bitmap.Width,bitmap.Height);
Win32.PointpointSource = new Win32.Point( 0 , 0 );
Win32.PointtopPos = new Win32.Point(Left,Top);
Win32.BLENDFUNCTIONblend = 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); // ThedocumentationsaysthatwehavetousetheWindows.DeleteObject...butsincethereisnosuchmethodIusethenormalDeleteObjectfromWin32GDIandit'sworkingfinewithoutanyresourceleak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}
private System.Windows.Forms.Buttonbutton1;
private void Form1_MouseDown( object sender,System.Windows.Forms.MouseEventArgse)
{
Win32.ReleaseCapture();
Win32.SendMessage( this .Handle.ToInt32(),Win32.WM_SysCommand,Win32.SC_MOVE, 0 );
}
ht
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace WindowsApplication7
{
public class Form1:System.Windows.Forms.Form
{
private System.ComponentModel.IContainercomponents;
public Form1()
{
//
// Windows窗体设计器支持所必需的
//
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
}
///
/// 清理所有正在使用的资源。
///
protected override void Dispose( bool disposing)
{
if (disposing)
{
if (components != null )
{
components.Dispose();
}
}
base .Dispose(disposing);
}
WindowsFormDesignergeneratedcode
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main()
{
Application.Run( new Form1());
}
Form2controlFrm = new Form2();
private void button1_Click( object sender,System.EventArgse)
{
MessageBox.Show(controlFrm,controlFrm.textBox1.Text);
}
protected override CreateParamsCreateParams
{
get
{
CreateParamscp = base .CreateParams;
cp.ExStyle |= 0x00080000 ; // ThisformhastohavetheWS_EX_LAYEREDextendedstyle
return cp;
}
}
private void SetStyle1()
{
Bitmapbm = Image.FromFile( @" Green.png " ) as Bitmap;
Bitmapbm2 = Image.FromFile( @" btn.png " ) as Bitmap;
Graphicsg = Graphics.FromImage(bm);
g.DrawImage(bm2, 20 , 20 , new Rectangle( 0 , 0 , 90 , 50 ),GraphicsUnit.Pixel);
g.DrawString( " byjinjazz " , new Font( " Ariel " , 9 ,FontStyle.Bold), new SolidBrush(Color.Black), new PointF( 40 , 50 ));
this .SetBitmap(bm, 255 );
}
private void SetStyle2()
{
Bitmapbm = Image.FromFile( @" Green.png " ) as Bitmap;
Bitmapbm2 = Image.FromFile( @" btn.png " ) as Bitmap;
Graphicsg = Graphics.FromImage(bm);
g.DrawImage(bm2, 15 , 15 , new Rectangle( 7 , 140 , 100 , 50 ),GraphicsUnit.Pixel);
g.DrawString( " byjinjazz " , new Font( " Ariel " , 9 ,FontStyle.Bold), new SolidBrush(Color.Black), new PointF( 40 , 50 ));
this .SetBitmap(bm, 255 );
}
private void Form1_Load( object sender,System.EventArgse)
{
controlFrm.Show();
SetStyle1();
// this.TopMost=true;
controlFrm.TopMost = true ;
}
private void button1_MouseEnter( object sender,EventArgse)
{
SetStyle2();
}
private void button1_MouseLeave( object sender,EventArgse)
{
SetStyle1();
}
public void SetBitmap(Bitmapbitmap, byte opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException( " Thebitmapmustbe32pppwithalpha-channel. " );
// Theideiaofthisisverysimple,
// 1.CreateacompatibleDCwithscreen;
// 2.Selectthebitmapwith32bppwithalpha-channelinthecompatibleDC;
// 3.CalltheUpdateLayeredWindow.
IntPtrscreenDc = Win32.GetDC(IntPtr.Zero);
IntPtrmemDc = Win32.CreateCompatibleDC(screenDc);
IntPtrhBitmap = IntPtr.Zero;
IntPtroldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb( 0 )); // grabaGDIhandlefromthisGDI+bitmap
oldBitmap = Win32.SelectObject(memDc,hBitmap);
Win32.Sizesize = new Win32.Size(bitmap.Width,bitmap.Height);
Win32.PointpointSource = new Win32.Point( 0 , 0 );
Win32.PointtopPos = new Win32.Point(Left,Top);
Win32.BLENDFUNCTIONblend = 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); // ThedocumentationsaysthatwehavetousetheWindows.DeleteObject...butsincethereisnosuchmethodIusethenormalDeleteObjectfromWin32GDIandit'sworkingfinewithoutanyresourceleak.
Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}
private System.Windows.Forms.Buttonbutton1;
private void Form1_MouseDown( object sender,System.Windows.Forms.MouseEventArgse)
{
Win32.ReleaseCapture();
Win32.SendMessage( this .Handle.ToInt32(),Win32.WM_SysCommand,Win32.SC_MOVE, 0 );
}
ht