Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Nullable, ReadOnly, Changable ForeColor, Changable BackColor DateTimePicker
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Metroit.Windows.Forms
{
/// <summary>
/// ユーザーが日時を選択し、書式を指定して日時を表示できる Windows コントロールを表します。
/// </summary>
public class MetDateTimePicker : DateTimePicker, ISupportInitialize
{
/// <summary>
/// MetDateTimePicker の新しいインスタンスを初期化します。
/// </summary>
public MetDateTimePicker()
: base()
{
// デザイン時は制御しない
if (MetDateTimePicker.DesignMode)
{
return;
}
this.KeyDown += MetDateTimePicker_KeyDown;
this.ValueChanged += MetDateTimePicker_ValueChanged;
this.Enter += MetDateTimePicker_Enter;
this.Leave += MetDateTimePicker_Leave;
}
#region イベント
private bool isInputting = false;
private bool isNull = false;
/// <summary>
/// Backspace, Deleteキー押下でnull表示にする。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MetDateTimePicker_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Delete || e.KeyData == Keys.Back)
{
//Backspace, Deleteキーが押されたらnull表示
this.isInputting = false;
this.switchFormat(null);
// 強制的に値変更イベントを走行
this.OnValueChanged(EventArgs.Empty);
}
else
{
bool isPrevNull = false;
if (this.isNull)
{
isPrevNull = true;
}
this.isInputting = true;
this.switchFormat(DateTime.Now); // 一時的に現在時刻を設定。後の走行で入力値に反映される。
// 値変更前がnullだった時は値変更イベントを走行
if (isPrevNull)
{
this.OnValueChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// null時、カレンダーから選択された場合に値の表示を行う。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MetDateTimePicker_ValueChanged(object sender, EventArgs e)
{
this.switchFormat(this.Value);
}
/// <summary>
/// フォーカスを得た時、色の変更とテキストの反転を行う。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MetDateTimePicker_Enter(object sender, EventArgs e)
{
// フォーカス取得時の色に変更
this.changeFocusColor();
}
/// <summary>
/// フォーカスを失った時、色の変更を行う。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MetDateTimePicker_Leave(object sender, EventArgs e)
{
this.changeBaseColor();
}
/// <summary>
/// 入力日時の状態に応じてフォーマットの変更を行う。
/// </summary>
/// <param name="datetime">入力日時</param>
private void switchFormat(DateTime? datetime)
{
if (datetime == null)
{
this.isNull = true;
this.Format = DateTimePickerFormat.Custom;
this.CustomFormat = " ";
}
else
{
this.isNull = false;
this.Format = this.format;
this.CustomFormat = this.customFormat;
}
}
#endregion
#region プロパティ
private bool isValueChanged = false;
private DateTimePickerFormat format = DateTimePickerFormat.Long;
private string customFormat = "";
private bool visible = true;
/// <summary>
/// コントロールに代入された日付/時刻値を取得または設定します。
/// </summary>
public new DateTime? Value
{
get
{
if (this.isNull)
{
return null;
}
return base.Value;
}
set
{
this.isValueChanged = true;
// nullの設定時
if (value == null)
{
this.isInputting = false;
this.switchFormat(null);
if (MetDateTimePicker.DesignMode)
{
return;
}
this.OnValueChanged(EventArgs.Empty);
return;
}
// キーによる入力時
if (this.isInputting)
{
base.Value = (DateTime)this.Value;
this.isInputting = false;
return;
}
// nullからの復帰時
if (this.isNull)
{
this.isNull = false;
this.Format = this.format;
this.CustomFormat = this.customFormat;
}
// nullからの復帰時・カレンダーからの設定時
base.Value = (DateTime)value;
}
}
/// <summary>
/// Value が既定値から変更されたかどうかを返却する。
/// </summary>
/// <returns>true:変更された, false:変更されていない</returns>
internal bool ShouldSerializeValue() => this.isValueChanged;
/// <summary>
/// Value のリセット操作を行う。
/// </summary>
internal void ResetValue()
{
this.Value = DateTime.Now;
this.Checked = false;
this.isValueChanged = false;
}
/// <summary>
/// このコントロールに関連付けられているテキストを取得または設定します。
/// </summary>
public override string Text
{
get
{
if (this.isNull)
{
return "";
}
return base.Text;
}
set => base.Text = value;
}
/// <summary>
/// コントロールに表示される日時の書式を取得または設定します。
/// </summary>
[DefaultValue(DateTimePickerFormat.Long)]
public new DateTimePickerFormat Format
{
get => this.format;
set
{
if (!this.isNull)
{
this.format = value;
}
base.Format = value;
if (!this.controlCreated)
{
return;
}
if (this.ReadOnly)
{
this.switchTextBox();
}
if (this.ReadOnlyLabel)
{
this.switchLabel();
}
}
}
/// <summary>
/// 日付/時刻のカスタム書式指定文字列を取得または設定します。
/// </summary>
[DefaultValue("")]
public new string CustomFormat
{
get => this.customFormat;
set
{
if (!this.isNull)
{
this.customFormat = value;
}
base.CustomFormat = value;
if (!this.controlCreated)
{
return;
}
if (this.Format == DateTimePickerFormat.Custom && this.ReadOnly)
{
this.switchTextBox();
}
if (this.Format == DateTimePickerFormat.Custom && this.ReadOnlyLabel)
{
this.switchLabel();
}
}
}
/// <summary>
/// コントロールとそのすべての子コントロールが表示されているかどうかを示す値を取得または設定します。
/// </summary>
[Browsable(true)]
[DefaultValue(true)]
public new bool Visible
{
get => this.visible;
set
{
this.visible = value;
if (MetDateTimePicker.DesignMode)
{
return;
}
if (!this.ReadOnly && !this.ReadOnlyLabel)
{
base.Visible = value;
return;
}
if (!this.controlCreated)
{
return;
}
if (this.ReadOnly)
{
this.switchTextBox();
}
if (this.ReadOnlyLabel)
{
this.switchLabel();
}
}
}
/// <summary>
/// DateTimePicker コントロールの背景色を示す値を取得または設定します。
/// </summary>
[Browsable(false)]
public override Color BackColor { get => base.BackColor; set => base.BackColor = value; }
/// <summary>
/// DateTimePicker コントロールの文字色を示す値を取得または設定します。
/// </summary>
[Browsable(false)]
public override Color ForeColor { get => base.ForeColor; set => base.ForeColor = value; }
#endregion
#region 追加プロパティ
private TextBox textBox = null;
private bool readOnlyText = false;
private Label label = null;
private bool readOnlyLabel = false;
private Color defaultBaseBackColor => this.ReadOnly ? SystemColors.Control : SystemColors.Window; // BaseBackColor の既定値
private Color? baseBackColor = null;
private Color defaultFocusBackColor => this.ReadOnly ? SystemColors.Control : SystemColors.Window; // FocusBackColor の既定値
private Color? focusBackColor = null;
private Color defaultBaseForeColor => SystemColors.WindowText; // BaseForeColor の既定値
private Color? baseForeColor = null;
private Color defaultFocusForeColor => SystemColors.WindowText; // FocusForeColor の既定値
private Color? focusForeColor = null;
/// <summary>
/// TextBox による代替表示を行っているかどうかを取得します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 動作")]
[DefaultValue(false)]
[Description("コントロールをテキストボックスで置き換えます。")]
public bool ReadOnly
{
get
{
return this.readOnlyText;
}
set
{
// ラベルで代替中は動作しない
if (this.ReadOnlyLabel)
{
this.ReadOnlyLabel = false;
}
this.readOnlyText = value;
if (MetDateTimePicker.DesignMode)
{
// 背景色・文字色の変更
this.ChangeDisplayColor();
return;
}
if (!this.controlCreated)
{
return;
}
this.switchTextBox();
}
}
/// <summary>
/// 表示状態に応じて、Visible、ラベル代替を切り替える。
/// </summary>
private void switchTextBox()
{
// 非表示
if (!this.Visible)
{
// テキスト代替なしの場合は通常のVisible
if (!this.ReadOnly)
{
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// テキストを一旦削除する
if (this.textBox != null)
{
this.textBox.Parent.Controls.Remove(this.textBox);
this.textBox.Dispose();
this.textBox = null;
}
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// 表示でテキスト代替なしの場合はラベルを消す
if (!this.ReadOnly)
{
if (this.textBox != null)
{
this.textBox.Parent.Controls.Remove(this.textBox);
this.textBox.Dispose();
this.textBox = null;
}
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// ReadOnly=trueで既にテキストが存在する場合、一旦テキストを削除する
if (this.textBox != null)
{
this.textBox.Parent.Controls.Remove(this.textBox);
this.textBox.Dispose();
this.textBox = null;
}
// 表示でラベル代替あり
this.textBox = new TextBox();
this.textBox.ReadOnly = true;
this.textBox.Text = this.Text;
this.textBox.Size = this.Size;
this.textBox.Location = this.Location;
this.textBox.Margin = this.Margin;
this.textBox.MaximumSize = this.MaximumSize;
this.textBox.MinimumSize = this.MinimumSize;
this.textBox.Padding = this.DefaultPadding;
this.textBox.Visible = this.Visible;
this.textBox.Enabled = this.Enabled;
this.textBox.Dock = this.Dock;
this.textBox.Font = this.Font;
this.textBox.Anchor = this.Anchor;
this.textBox.RightToLeft = this.RightToLeft;
this.textBox.BorderStyle = BorderStyle.Fixed3D;
this.textBox.Cursor = this.Cursor;
this.textBox.TextAlign = HorizontalAlignment.Left;
this.textBox.TabIndex = this.TabIndex;
this.textBox.TabStop = this.TabStop;
this.ChangeDisplayColor();
this.textBox.Enter += MetDateTimePicker_Enter;
this.textBox.Leave += MetDateTimePicker_Leave;
base.Visible = false;
if (this.Parent.GetType() == typeof(TableLayoutPanel))
{
var tlp = (TableLayoutPanel)this.Parent;
var position = tlp.GetPositionFromControl(this);
tlp.Controls.Add(this.textBox, position.Column, position.Row);
}
else if (this.Parent.GetType() == typeof(FlowLayoutPanel))
{
var flp = (FlowLayoutPanel)this.Parent;
flp.Controls.Add(this.textBox);
flp.Controls.SetChildIndex(this.textBox, flp.Controls.IndexOf(this));
}
else
{
this.Parent.Controls.Add(this.textBox);
}
}
/// <summary>
/// Label による代替表示を行っているかどうかを取得します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 動作")]
[DefaultValue(false)]
[Description("コントロールをラベルで置き換えます。")]
public bool ReadOnlyLabel
{
get
{
return this.readOnlyLabel;
}
set
{
// テキストで代替中は動作しない
if (this.ReadOnly)
{
this.ReadOnly = false;
}
this.readOnlyLabel = value;
if (MetDateTimePicker.DesignMode)
{
// 背景色・文字色の変更
this.ChangeDisplayColor();
return;
}
if (!this.controlCreated)
{
return;
}
this.switchLabel();
}
}
/// <summary>
/// 表示状態に応じて、Visible、ラベル代替を切り替える。
/// </summary>
private void switchLabel()
{
// 非表示
if (!this.Visible)
{
// ラベル代替なしの場合は通常のVisible
if (!this.ReadOnlyLabel)
{
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// ラベルを一旦削除する
if (this.label != null)
{
this.label.Parent.Controls.Remove(this.label);
this.label.Dispose();
this.label = null;
}
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// 表示でラベル代替なしの場合はラベルを消す
if (!this.ReadOnlyLabel)
{
if (this.label != null)
{
this.label.Parent.Controls.Remove(this.label);
this.label.Dispose();
this.label = null;
}
this.ChangeDisplayColor();
base.Visible = this.Visible;
return;
}
// ReadOnlyLabel=trueで既にラベルが存在する場合、一旦ラベルを削除する
if (this.label != null)
{
this.label.Parent.Controls.Remove(this.label);
this.label.Dispose();
this.label = null;
}
// 表示でラベル代替あり
this.label = new Label();
this.label.Text = this.Text;
this.label.Size = this.Size;
this.label.Location = this.Location;
this.label.Margin = this.Margin;
this.label.MaximumSize = this.MaximumSize;
this.label.MinimumSize = this.MinimumSize;
this.label.Padding = this.DefaultPadding;
this.label.Visible = this.Visible;
this.label.Enabled = this.Enabled;
this.label.Dock = this.Dock;
this.label.Font = this.Font;
this.label.Anchor = this.Anchor;
this.label.RightToLeft = this.RightToLeft;
this.label.BorderStyle = BorderStyle.Fixed3D;
this.label.Cursor = this.Cursor;
this.label.TextAlign = ContentAlignment.MiddleLeft;
this.ChangeDisplayColor();
base.Visible = false;
if (this.Parent.GetType() == typeof(TableLayoutPanel))
{
var tlp = (TableLayoutPanel)this.Parent;
var position = tlp.GetPositionFromControl(this);
tlp.Controls.Add(this.label, position.Column, position.Row);
}
else if (this.Parent.GetType() == typeof(FlowLayoutPanel))
{
var flp = (FlowLayoutPanel)this.Parent;
flp.Controls.Add(this.label);
flp.Controls.SetChildIndex(this.label, flp.Controls.IndexOf(this));
}
else
{
this.Parent.Controls.Add(this.label);
}
}
/// <summary>
/// コントロールの背景色を取得または設定します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 表示")]
[Description("コントロールの背景色を取得または設定します。")]
public Color BaseBackColor
{
get
{
this.Refresh();
return this.baseBackColor ?? this.defaultBaseBackColor;
}
set
{
this.baseBackColor = value;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
}
/// <summary>
/// BaseBackColor が既定値から変更されたかどうかを返却する。
/// </summary>
/// <returns>true:変更された, false:変更されていない</returns>
internal bool ShouldSerializeBaseBackColor() => this.baseBackColor != null && this.baseBackColor != this.defaultBaseBackColor;
/// <summary>
/// BaseBackColor のリセット操作を行う。
/// </summary>
internal void ResetBaseBackColor()
{
this.baseBackColor = null;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
/// <summary>
/// フォーカス時のコントロールの背景色を取得または設定します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 表示")]
[Description("フォーカス時のコントロールの背景色を取得または設定します。")]
public Color FocusBackColor
{
get
{
this.Refresh();
return this.focusBackColor ?? this.defaultFocusBackColor;
}
set
{
this.focusBackColor = value;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
}
/// <summary>
/// FocusBackColor が既定値から変更されたかどうかを返却する。
/// </summary>
/// <returns>true:変更された, false:変更されていない</returns>
internal bool ShouldSerializeFocusBackColor() => this.focusBackColor != null && this.focusBackColor != this.defaultFocusBackColor;
/// <summary>
/// FocusBackColor のリセット操作を行う。
/// </summary>
internal void ResetFocusBackColor()
{
this.focusBackColor = null;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
/// <summary>
/// コントロールの文字色を取得または設定します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 表示")]
[Description("コントロールの文字色を取得または設定します。")]
public Color BaseForeColor
{
get
{
this.Refresh();
return this.baseForeColor ?? this.defaultBaseForeColor;
}
set
{
this.baseForeColor = value;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
}
/// <summary>
/// BaseBackColor が既定値から変更されたかどうかを返却する。
/// </summary>
/// <returns>true:変更された, false:変更されていない</returns>
internal bool ShouldSerializeBaseForeColor() => this.baseForeColor != null && this.baseForeColor != this.defaultBaseForeColor;
/// <summary>
/// BaseBackColor のリセット操作を行う。
/// </summary>
internal void ResetBaseForeColor()
{
this.baseForeColor = null;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
/// <summary>
/// フォーカス時のコントロールの文字色を取得または設定します。
/// </summary>
[Browsable(true)]
[Category("Metroit拡張 表示")]
[Description("フォーカス時のコントロールの文字色を取得または設定します。")]
public Color FocusForeColor
{
get
{
this.Refresh();
return this.focusForeColor ?? this.defaultFocusForeColor;
}
set
{
this.focusForeColor = value;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
}
/// <summary>
/// FocusBackColor が既定値から変更されたかどうかを返却する。
/// </summary>
/// <returns>true:変更された, false:変更されていない</returns>
internal bool ShouldSerializeFocusForeColor() => this.focusForeColor != null && this.focusForeColor != this.defaultFocusForeColor;
/// <summary>
/// FocusBackColor のリセット操作を行う。
/// </summary>
internal void ResetFocusForeColor()
{
this.focusForeColor = null;
// 背景色・文字色の変更
this.ChangeDisplayColor();
}
/// <summary>
/// コントロールのアクティブ状態に応じた表示色に変更する。
/// </summary>
protected virtual void ChangeDisplayColor()
{
// アクティブの時にアクティブ色に変更
var form = this.FindForm();
if (form != null && form.ActiveControl == this)
{
this.changeFocusColor();
}
else
{
this.changeBaseColor();
}
}
/// <summary>
/// 表示色をフォーカス色に変更する。
/// </summary>
private void changeFocusColor()
{
if (this.focusBackColor == null)
{
base.BackColor = this.defaultFocusBackColor;
}
else
{
base.BackColor = this.FocusBackColor;
}
if (this.focusForeColor == null)
{
base.ForeColor = this.defaultFocusForeColor;
}
else
{
base.ForeColor = this.FocusForeColor;
}
// テキストの代替表示を行っている場合はテキストの表示色も変更
if (this.controlCreated && this.ReadOnly)
{
this.textBox.BackColor = this.FocusBackColor;
this.textBox.ForeColor = this.FocusForeColor;
}
}
/// <summary>
/// 表示色を非フォーカス色に変更する。
/// </summary>
private void changeBaseColor()
{
if (this.baseBackColor == null)
{
base.BackColor = this.defaultBaseBackColor;
}
else
{
base.BackColor = this.BaseBackColor;
}
if (this.baseForeColor == null)
{
base.ForeColor = this.defaultFocusForeColor;
}
else
{
base.ForeColor = this.BaseForeColor;
}
// テキスト・ラベルの代替表示を行っている場合はテキスト・ラベルの表示色も変更
if (this.controlCreated && this.ReadOnly)
{
this.textBox.BackColor = this.BaseBackColor;
this.textBox.ForeColor = this.BaseForeColor;
}
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.BackColor = this.BaseBackColor;
this.label.ForeColor = this.BaseForeColor;
}
}
#endregion
#region メソッド
private bool controlCreated = false;
[StructLayout(LayoutKind.Sequential)]
private struct NMHDR
{
public IntPtr HwndFrom;
public int IdFrom;
public int Code;
}
/// <summary>
/// InitializeComponent()でコントロールの生成が完了していないことを通知します。
/// </summary>
public void BeginInit()
{
this.controlCreated = false;
}
/// <summary>
/// 実装はありません。
/// </summary>
public void EndInit() { }
/// <summary>
/// コントロールの生成が完了したことを通知し、ReadOnly, ReadOnlyLabelの制御を行います。
/// </summary>
protected override void OnCreateControl()
{
base.OnCreateControl();
if (MetDateTimePicker.DesignMode)
{
return;
}
this.controlCreated = true;
if (this.ReadOnly)
{
this.switchTextBox();
}
if (this.ReadOnlyLabel)
{
this.switchLabel();
}
}
/// <summary>
/// コントロールの配置元が変更時、ラベル・テキスト代替表示をしていたらラベル・テキストの配置元も変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnParentChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Parent = this.Parent;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Parent = this.Parent;
}
base.OnParentChanged(e);
}
/// <summary>
/// コントロールの表示位置が変更時、ラベル・テキスト代替表示をしていたらラベル・テキストの表示位置も変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnLocationChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Location = this.Location;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Location = this.Location;
}
base.OnLocationChanged(e);
}
/// <summary>
/// コントロールのサイズが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのサイズも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Size = this.Size;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Size = this.Size;
}
base.OnSizeChanged(e);
}
/// <summary>
/// コントロールのサイズが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのサイズも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Size = this.Size;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Size = this.Size;
}
base.OnResize(e);
}
/// <summary>
/// コントロールのドッキングが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのドッキングも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnDockChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Dock = this.Dock;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Dock = this.Dock;
}
base.OnDockChanged(e);
}
/// <summary>
/// コントロールの文字入力方向が変更時、ラベル・テキスト代替表示をしていたらラベル・テキストの文字入力方向も変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnRightToLeftChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.RightToLeft = this.RightToLeft;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.RightToLeft = this.RightToLeft;
}
base.OnRightToLeftChanged(e);
}
/// <summary>
/// コントロールのフォントが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのフォントも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnFontChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Font = this.Font;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Font = this.Font;
}
base.OnFontChanged(e);
}
/// <summary>
/// コントロールのマージンが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのマージンも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnMarginChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Margin = this.Margin;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Margin = this.Margin;
}
base.OnMarginChanged(e);
}
/// <summary>
/// コントロールのカーソルが変更時、ラベル・テキスト代替表示をしていたらラベル・テキストのカーソルも変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnCursorChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnlyLabel)
{
this.label.Cursor = this.Cursor;
}
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Cursor = this.Cursor;
}
base.OnCursorChanged(e);
}
/// <summary>
/// コントロールの活性状態が変更時、テキスト代替表示をしていたらテキストの活性状態も変更します。
/// </summary>
/// <param name="e"></param>
protected override void OnEnabledChanged(EventArgs e)
{
if (this.controlCreated && this.ReadOnly)
{
this.textBox.Enabled = this.Enabled;
}
base.OnEnabledChanged(e);
}
/// <summary>
/// 入力状態に応じてフラグのリセットを行い、背景色の変更を行います。
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
// 手入力・カレンダーによって日付が確定された時、入力中フラグを取り消す
if (m.Msg == 0x204e)
{
var lparam = (NMHDR)m.GetLParam(typeof(NMHDR));
if (lparam.Code == -759)
{
this.isInputting = false;
}
}
// カレンダーから値を選択後・入力エリア反映前に、nullフラグを取り消す
if (m.Msg == 0x004e) // WM_NOTIFY
{
NMHDR nm = (NMHDR)m.GetLParam(typeof(NMHDR));
if (nm.Code == -749)
{
this.isNull = false;
}
}
base.WndProc(ref m);
// 背景色を描画する
this.redrawBackColor(ref m);
}
/// <summary>
/// 背景色の描画し直します。
/// </summary>
private void redrawBackColor(ref Message m)
{
if (m.Msg == 0x000f) // WM_PAINT
{
// Bitmapを自分の上に描画して背景色を設定する
var bsz = SystemInformation.Border3DSize;
using (var g = this.CreateGraphics())
using (var bmp = this.getControlImage())
{
g.DrawImage(bmp, -bsz.Width + 2, -bsz.Height + 2);
}
}
}
/// <summary>
/// 背景色描画用のBitmapオブジェクトを取得する。
/// </summary>
/// <returns></returns>
private Bitmap getControlImage()
{
// 自分自身の画像をBitmapにコピー
var bmp = new Bitmap(this.Width, this.Height);
this.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));
// Bitmapの背景色をMe.BackColorに変更する
using (var g = Graphics.FromImage(bmp))
{
System.Drawing.Imaging.ColorMap[] cm = { new System.Drawing.Imaging.ColorMap(), new System.Drawing.Imaging.ColorMap() };
// 背景色のマッピング
cm[0].OldColor = SystemColors.Window;
cm[0].NewColor = this.BackColor;
// 文字色のマッピング
cm[1].OldColor = SystemColors.WindowText;
cm[1].NewColor = this.ForeColor;
var ia = new System.Drawing.Imaging.ImageAttributes();
ia.SetRemapTable(cm);
var r = new Rectangle(0, 0, bmp.Width, bmp.Height);
g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),
0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
}
return bmp;
}
#endregion
/// <summary>
/// <para>Component が現在デザイン モードかどうかを示す値を取得します。</para>
/// <para>System.Windows.Forms.Control.DesignMode プロパティで制御されない継承コンポーネントの状態まで把握します。</para>
/// </summary>
/// <returns>true:デザインモード、false:実行中</returns>
private new static bool DesignMode
{
get
{
if (System.ComponentModel.LicenseManager.UsageMode
== System.ComponentModel.LicenseUsageMode.Designtime)
{
return true;
}
var processName = Process.GetCurrentProcess().ProcessName.ToUpper();
if (processName == "DEVENV" || processName == "VCSEXPRESS")
{
return true;
}
if (AppDomain.CurrentDomain.FriendlyName == "DefaultDomain")
{
return true;
}
return false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment