65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.89/5 (6投票s)

2004年12月22日

viewsIcon

28584

downloadIcon

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
  } 
}
© . All rights reserved.