【C#】Windowsフォーム アプリケーションのグラデーション背景と枠線を表示できるパネルユーザコントロール
久しぶりのWindowsフォーム アプリケーションのユーザコントロールネタです。
WPFだとコントロールに枠線やグラデーションを行うのは容易ですが、Windowsフォーム アプリケーションだと面倒なことこの上ないです。
Panelを継承し、OnPaintをoverrideして自力で背景と枠線を描画してやっと出来るっていう…。
グラデーション背景と枠線を表示できるパネルユーザコントロールの実装コードです。
namespace GradationPanelSample { partial class GradationPanel { /// <summary> /// 必要なデザイナー変数です。 /// </summary> 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); } #region コンポーネント デザイナーで生成されたコード /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> private void InitializeComponent() { components = new System.ComponentModel.Container(); } #endregion } }
using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace GradationPanelSample { /// <summary> /// グラデーションパネルユーザコントロール /// </summary> public partial class GradationPanel : Panel { #region プロパティ /// <summary> /// コントロールの境界線のスタイル /// </summary> /// <remarks>PanelのデフォルトプロパティであるBorderStyleを隠蔽している。</remarks> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールの境界線スタイルを取得または設定します。")] [BrowsableAttribute(false)] public new BorderStyle BorderStyle { get; set; } = BorderStyle.None; /// <summary> /// コントロールの境界線の色 /// </summary> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールの境界線の色を取得または設定します。")] [BrowsableAttribute(true)] public Color BorderColor { get; set; } = Color.Black; /// <summary> /// コントロールの境界線の太さ /// </summary> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールの境界線の太さを取得または設定します。0を設定した場合は枠線は描画されません。")] [BrowsableAttribute(true)] [DefaultValue(0)] public int BorderThickness { get; set; } = 0; /// <summary> /// コントロールのグラデーション開始色 /// </summary> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールのグラデーション開始色を取得または設定します。")] [BrowsableAttribute(true)] public Color StartColor { get; set; } = SystemColors.Control; /// <summary> /// コントロールのグラデーション終了色 /// </summary> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールのグラデーション終了色を取得または設定します。")] [BrowsableAttribute(true)] public Color EndColor { get; set; } = SystemColors.Control; /// <summary> /// コントロールのグラデーションモード /// </summary> [CategoryAttribute("表示")] [DescriptionAttribute("コントロールのグラデーションのモードを取得または設定します。")] [BrowsableAttribute(true)] public LinearGradientMode GradientMode { get; set; } = LinearGradientMode.Vertical; #endregion #region コンストラクタ /// <summary> /// クラスの新しいインスタンスを初期化します。 /// </summary> public GradationPanel() { InitializeComponent(); } #endregion #region protectedメソッド /// <summary> /// 描画処理 /// </summary> /// <param name="pevent">Paintイベント引数</param> protected override void OnPaint(PaintEventArgs pevent) { using (var graphics = pevent.Graphics) { var borderThickness = GetHarfBorderThickness(); var x = borderThickness; var y = borderThickness; var width = 0 < borderThickness ? Width - (borderThickness * 2) : Width; var height = 0 < borderThickness ? Height - (borderThickness * 2) : Height; // 幅と高さが0より小さい場合は、最小値の1を設定する if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } // 算出した幅と高さがコントロールの領域の1/2より大きい場合は、値を設定し直す if ((Width / 2) < borderThickness) { borderThickness = (int)Math.Floor(Width / 2.0F); } if ((Height / 2) < borderThickness) { borderThickness = (int)Math.Floor(Height / 2.0F); } // 背景の描画領域を指定する var rectangle = new Rectangle(x, y, width, height); using (var linearGradientBrush = new LinearGradientBrush(new Rectangle(x, y, width, height), StartColor, EndColor, GradientMode)) { // グラデーションブラシを生成し描画する graphics.FillRectangle(linearGradientBrush, rectangle); } if (0 < BorderThickness) { using (var pen = new Pen(BorderColor, BorderThickness)) { graphics.DrawRectangle(pen, 0 + borderThickness, 0 + borderThickness, width, height); } } } } #endregion #region privateメソッド /// <summary> /// 枠線の太さの1/2の値を取得します。 /// </summary> /// <returns>枠線の太さの1/2の値</returns> private int GetHarfBorderThickness() { return (int)System.Math.Floor((double)(BorderThickness) / 2 + 0.5); } #endregion } }
枠線の太さの最小値と最大値を補正するように記述しています。頭が悪いのでもっと綺麗に書けそうですが、わたしの脳みそではこれで限界です。
Windowsフォーム アプリケーションのユーザコントロールネタにまた戻ってきましたが、そろそろネタが無くなりそう。