Laz*_*zlo 46 .net c# winapi gdi+ aero
我(终于!)找到了一种在玻璃上渲染Windows.Forms控件的方法,它似乎没有任何重大缺点,也没有任何大的实现时间.它受到Coded 的这篇文章的启发,它基本上解释了如何本地覆盖控件绘制以绘制它们.
我使用该方法将控件渲染为位图,并使用GDI +和适当的Alpha通道将其绘制回NativeWindow的绘制区域.实现很简单,但可以完善可用性,但这不是这个问题的重点.然而,结果非常令人满意:

但是,有两个区域需要修复才能真正使用.
SetStyles(this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true)不起作用,但我怀疑我们可以通过一些试验和错误使其工作.某些控件不起作用.我已经能够完成以下工作:
但我不能让这些工作,虽然我不明白为什么不.我有根据的猜测是,实际的NativeWindow句柄我引用了整个控件,而我需要引用它的"输入"(文本)部分,可能是一个孩子.有关如何获取输入窗口句柄的WinAPI专家的任何帮助都是受欢迎的.
但修复双缓冲将是可用性的主要关注点.
这是一个示例用法:
new GlassControlRenderer(textBox1);
Run Code Online (Sandbox Code Playgroud)
这是代码:
public class GlassControlRenderer : NativeWindow
{
private Control Control;
private Bitmap Bitmap;
private Graphics ControlGraphics;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0xF: // WM_PAINT
case 0x85: // WM_NCPAINT
case 0x100: // WM_KEYDOWN
case 0x200: // WM_MOUSEMOVE
case 0x201: // WM_LBUTTONDOWN
this.Control.Invalidate();
base.WndProc(ref m);
this.CustomPaint();
break;
default:
base.WndProc(ref m);
break;
}
}
public GlassControlRenderer(Control control)
{
this.Control = control;
this.Bitmap = new Bitmap(this.Control.Width, this.Control.Height);
this.ControlGraphics = Graphics.FromHwnd(this.Control.Handle);
this.AssignHandle(this.Control.Handle);
}
public void CustomPaint()
{
this.Control.DrawToBitmap(this.Bitmap, new Rectangle(0, 0, this.Control.Width, this.Control.Height));
this.ControlGraphics.DrawImageUnscaled(this.Bitmap, -1, -1); // -1, -1 for content controls (e.g. TextBox, ListBox)
}
}
Run Code Online (Sandbox Code Playgroud)
我真的很高兴解决这个问题,并且一劳永逸地在玻璃上渲染,对于所有.NET控件,没有WPF.
编辑:双缓冲/防闪烁的可能路径:
this.Control.Invalidate()会消除闪烁,但会破坏文本框中的输入.我尝试了WM_SETREDRAW方法和SuspendLayout方法,没有运气:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
public static void SuspendDrawing(Control parent)
{
SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
}
public static void ResumeDrawing(Control parent)
{
SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
parent.Refresh();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0xF: // WM_PAINT
case 0x85: // WM_NCPAINT
case 0x100: // WM_KEYDOWN
case 0x200: // WM_MOUSEMOVE
case 0x201: // WM_LBUTTONDOWN
//this.Control.Parent.SuspendLayout();
//GlassControlRenderer.SuspendDrawing(this.Control);
//this.Control.Invalidate();
base.WndProc(ref m);
this.CustomPaint();
//GlassControlRenderer.ResumeDrawing(this.Control);
//this.Control.Parent.ResumeLayout();
break;
default:
base.WndProc(ref m);
break;
}
}
Run Code Online (Sandbox Code Playgroud)这是一个闪烁少得多的版本,但仍然不完美.
public class GlassControlRenderer : NativeWindow
{
private Control Control;
private Bitmap Bitmap;
private Graphics ControlGraphics;
private object Lock = new object();
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x14: // WM_ERASEBKGND
this.CustomPaint();
break;
case 0x0F: // WM_PAINT
case 0x85: // WM_NCPAINT
case 0x100: // WM_KEYDOWN
case 0x101: // WM_KEYUP
case 0x102: // WM_CHAR
case 0x200: // WM_MOUSEMOVE
case 0x2A1: // WM_MOUSEHOVER
case 0x201: // WM_LBUTTONDOWN
case 0x202: // WM_LBUTTONUP
case 0x285: // WM_IME_SELECT
case 0x300: // WM_CUT
case 0x301: // WM_COPY
case 0x302: // WM_PASTE
case 0x303: // WM_CLEAR
case 0x304: // WM_UNDO
base.WndProc(ref m);
this.CustomPaint();
break;
default:
base.WndProc(ref m);
break;
}
}
private Point Offset { get; set; }
public GlassControlRenderer(Control control, int xOffset, int yOffset)
{
this.Offset = new Point(xOffset, yOffset);
this.Control = control;
this.Bitmap = new Bitmap(this.Control.Width, this.Control.Height);
this.ControlGraphics = Graphics.FromHwnd(this.Control.Handle);
this.AssignHandle(this.Control.Handle);
}
public void CustomPaint()
{
this.Control.DrawToBitmap(this.Bitmap, new Rectangle(0, 0, this.Control.Width, this.Control.Height));
this.ControlGraphics.DrawImageUnscaled(this.Bitmap, this.Offset); // -1, -1 for content controls (e.g. TextBox, ListBox)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3087 次 |
| 最近记录: |