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


    根据一副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, 
    20 20 new  Rectangle( 0 0 90 50 ), GraphicsUnit.Pixel);

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

                
    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, 
    15 15 new  Rectangle( 7 140 100 50 ), GraphicsUnit.Pixel);

                g.DrawString(
    " by jinjazz " 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.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( 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);
                }

            }


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

    }

  • 相关阅读:
    博客发在oschina
    博客发在oschina
    C#将dll打包到程序中
    C#将dll打包到程序中
    WPF checkbox文字下掉
    WPF checkbox文字下掉
    手机1520 win8.1升级win10
    CRITICAL **: Couldn't acquire global lock, snapshots will not be consistent: Access denied
    [学习笔记]Dsu On Tree
    手机1520 win8.1升级win10
  • 原文地址:https://www.cnblogs.com/cl1024cl/p/6205000.html
Copyright © 2020-2023  润新知