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

来源:互联网 发布:博客系统ag是什么源码 编辑:程序博客网 时间:2024/06/05 14:41

根据一副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.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;
    }

}

原创粉丝点击