C# 窗体样式使用WS_EX_LAYERED后,无法绘制windows控件的解决办法

根据一副 png 图片绘制半透明窗体时,用了 WS_EX_LAYERED 后当前窗体再也不会处理 paint 事件,所以所含的子控件是一辈子也不会画出来的,但是这个控件确实存在,而且可以响应事件 。而此时 windows 画制窗体是使用 UpdateLayeredWindow 这个 api 函数的。

       对于按钮,完全可以自己画两个图片然后盖在 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.IContainer components;

        
public
 Form1()
        
{
            
//

            
// Windows 窗体设计器支持所必需的
            
//
            InitializeComponent();
            FormBorderStyle 
=
 FormBorderStyle.None;

             
        }


        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>

        protected override void Dispose( bool disposing )
        
{
            
if
( disposing )
            
{
                
if (components != null

                
{
                    components.Dispose();
                }

            }

            
base.Dispose( disposing );
        }


        
Windows Form Designer generated code

        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>

        [STAThread]
        
static void
 Main() 
        
{
            
            Application.Run(
new
 Form1());
        }



        Form2 controlFrm 
= new Form2();
        
private void button1_Click(object
 sender, System.EventArgs e)
        
{
            MessageBox.Show(controlFrm,controlFrm.textBox1.Text);
            
        }


        
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;
            }

        }


        
        
private void SetStyle1()
        
{
            Bitmap bm 
= Image.FromFile(@"Green.png"as
 Bitmap;
            Bitmap bm2 
= Image.FromFile(@"btn.png"as
 Bitmap;

            Graphics g 
=
 Graphics.FromImage(bm);
            g.DrawImage(bm2, 
2020new Rectangle(009050
), GraphicsUnit.Pixel);

            g.DrawString(
"by jinjazz"new Font("Ariel"9, FontStyle.Bold), new SolidBrush(Color.Black), new PointF(4050
));

            
this.SetBitmap(bm, 255
);
        }

        
private void SetStyle2()
        
{
            Bitmap bm 
= Image.FromFile(@"Green.png"as
 Bitmap;
            Bitmap bm2 
= Image.FromFile(@"btn.png"as
 Bitmap;

            Graphics g 
=
 Graphics.FromImage(bm);
            g.DrawImage(bm2, 
1515new Rectangle(714010050
), GraphicsUnit.Pixel);

            g.DrawString(
"by jinjazz"new Font("Ariel"9, FontStyle.Bold), new SolidBrush(Color.Black), new PointF(4050
));

            
this.SetBitmap(bm, 255
);
        }


        
        
private void Form1_Load(object sender, System.EventArgs e)
        
{
            
            controlFrm.Show();
            SetStyle1();
           
            
//this.TopMost = true;

            controlFrm.TopMost = true;
        }


        
private void button1_MouseEnter(object sender, EventArgs e)
        
{

            SetStyle2();
        }

        
private void button1_MouseLeave(object sender, EventArgs e)
        
{
            SetStyle1();
        }


        
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(00
);
                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, 0ref
 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);
            }

        }


         
        
private System.Windows.Forms.Button button1;
        
        
private void Form1_MouseDown(object
 sender, System.Windows.Forms.MouseEventArgs e)
        
{
            Win32.ReleaseCapture();
            Win32.SendMessage(
this.Handle.ToInt32(), Win32.WM_SysCommand, Win32.SC_MOVE, 0
);
        }


        
private void Form1_Move(object sender, EventArgs e)
        
{
            controlFrm.Location 
= this
.Location;
        }


        
private void Form1_VisibleChanged(object sender, EventArgs e)
        
{
            controlFrm.Visible 
= this
.Visible;
        }


        
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        
{
            controlFrm.Close();
        }


    }

}

 

显示子控件的Form代码

 

using System;
using
 System.Collections.Generic;
using
 System.ComponentModel;
using
 System.Data;
using
 System.Drawing;
using
 System.Text;
using
 System.Windows.Forms;

namespace
 WindowsApplication7
{
    
public partial class
 Form2 : Form
    
{
        
public
 Form2()
        
{
            InitializeComponent();
        }

        
private System.ComponentModel.IContainer components = null;

        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>

        
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>

        protected override void Dispose(bool disposing)
        
{
            
if (disposing && (components != null
))
            
{
                components.Dispose();
            }

            
base.Dispose(disposing);
        }


        
Windows 窗体设计器生成的代码

        
private System.Windows.Forms.Button button1;
        
internal
 System.Windows.Forms.TextBox textBox1;
        
private void button1_Click(object
 sender, EventArgs e)
        
{
            MessageBox.Show(
this
.textBox1.Text);
            
        }


       
    }

}

 

 调用 API 的代码 

 

using System;
using
 System.Collections.Generic;
using
 System.Text;
using
 System.Runtime.InteropServices;
namespace
 WindowsApplication7
{
    
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);

        [DllImport(
"user32.dll", EntryPoint = "SendMessage"
)]
        
public static extern int SendMessage(int hWnd, int wMsg, int wParam, int
 lParam);
        [DllImport(
"user32.dll", EntryPoint = "ReleaseCapture"
)]

        
public static extern int
 ReleaseCapture();
        
public const int WM_SysCommand = 0x0112
;
        
public const int SC_MOVE = 0xF012
;

        
public const int SC_MAXIMIZE = 61488
;
        
public const int SC_MINIMIZE = 61472
;
    }

}

 

 


 

 

 

 

 

posted @ 2012-01-12 16:30  许明吉博客  阅读(2407)  评论(0编辑  收藏  举报