为 .NET CheckBox 控件提供正确的视觉主题支持






1.89/5 (6投票s)
2004年12月22日

28584

2
一篇文章,介绍如何在 C# 中为 .NET CheckBox 控件添加正确的视觉主题支持,而无需接管控件的绘制。
引言
本文解决了该问题,并为 CheckBox
控件添加了透明度支持。当 FlatStyle
设置为 FlatStyle.System
时,它使控件以正确的 XP 样式进行绘制。
有一些关于相同主题的文章,例如,为 .NET CheckBox 控件提供真正的透明度支持。但这些文章建议我们接管控件的绘制。我发现了一种避免这种情况的方法,并仅使用 ComboBox
的标准 Windows 过程。
解决方案
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace CustomControls
{
[System.ComponentModel.DesignerCategory("Code")]
public class ThemedCheckBox : CheckBox
{
Bitmap backBufferImage = null;
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (levent.AffectedProperty == "Bounds")
{
backBufferImage = new Bitmap(Width, Height);
}
}
protected override void WndProc(ref Message m)
{
if (FlatStyle != FlatStyle.System)
{
base.WndProc(ref m);
return;
}
switch(m.Msg)
{
case 0xF:
if (backBufferImage == null)
{
backBufferImage = new Bitmap(Width, Height);
}
Graphics bg = Graphics.FromImage(backBufferImage);
IntPtr hdc = bg.GetHdc();
Message bm = Message.Create(Handle, 0xF, hdc, IntPtr.Zero);
base.WndProc(ref bm);
bg.ReleaseHdc(hdc);
bg.Dispose();
PAINTSTRUCT ps = new PAINTSTRUCT();
hdc = m.WParam == IntPtr.Zero ? BeginPaint(Handle, ref ps) : m.WParam;
Graphics fg = Graphics.FromHdc(hdc);
backBufferImage.MakeTransparent(BackColor);
fg.DrawImage(backBufferImage, 0, 0);
fg.Dispose();
if (m.WParam != IntPtr.Zero)
{
EndPaint(Handle, ref ps);
}
break;
case 0x14:
break;
default:
base.WndProc(ref m); break;
}
}
#region API Declares
[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct PAINTSTRUCT
{
public IntPtr hdc;
public bool fErase;
public Rectangle rcPaint;
public bool fRestore;
public bool fIncUpdate;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public byte[] rgbReserved;
}
[DllImport("user32")]
private static extern IntPtr BeginPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint);
[DllImport("user32")]
private static extern bool EndPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint);
#endregion API Declares
}
}