C#でのカスタムコントロール作成は、標準コントロールでは実現できない独自の機能やデザインを実装するために重要です。このガイドでは、カスタムコントロールの基本概念から始め、実際の作成手順、プロパティやメソッドの追加、イベントの実装、描画のカスタマイズ、デザイン時のサポートまで、具体例を交えて詳しく解説します。最終的には、複雑なカスタムコントロールの応用例と演習問題を通じて、理解を深めることを目指します。
カスタムコントロールとは
カスタムコントロールとは、既存の標準コントロールに追加機能を加えたり、全く新しい機能を持つコントロールを作成したりするものです。これにより、標準コントロールでは対応できない特定のニーズに応えることが可能になります。例えば、独自のデザイン要件や特定の動作を持つUIコンポーネントを作成する際に役立ちます。カスタムコントロールを使うことで、アプリケーションのユーザーエクスペリエンスを向上させることができます。
開発環境の準備
カスタムコントロールを作成するには、適切な開発環境を準備することが重要です。ここでは、Visual Studioのセットアップと必要なツールのインストール方法について説明します。
Visual Studioのインストール
まず、Visual Studioの最新バージョンをダウンロードし、インストールします。公式サイトからインストーラを取得し、インストールガイドに従って進めてください。インストール時には、「.NETデスクトップ開発」ワークロードを選択します。
必要なツールとライブラリのインストール
カスタムコントロールの開発には、.NET Frameworkや. NET Coreなどのランタイム環境が必要です。Visual Studioのインストール時にこれらも自動的にインストールされますが、必要に応じて追加インストールすることも可能です。また、NuGetパッケージマネージャを使用して、プロジェクトに必要なライブラリをインストールすることが推奨されます。
プロジェクトの作成
Visual Studioを起動し、新しいプロジェクトを作成します。「新しいプロジェクトの作成」画面で、「Windows フォームアプリケーション(.NET)」や「WPFアプリケーション」など、目的に合ったテンプレートを選択します。プロジェクト名を入力し、保存場所を指定してプロジェクトを作成します。
以上で、カスタムコントロールを作成するための開発環境の準備が整いました。次に、基本的なカスタムコントロールの作成手順について説明します。
基本的なカスタムコントロールの作成
ここでは、簡単なカスタムコントロールを作成する手順を具体例を交えて紹介します。基本的なカスタムコントロールを作成することで、カスタムコントロールの基本概念を理解しやすくなります。
新しいカスタムコントロールクラスの作成
Visual Studioで作成したプロジェクト内に、新しいクラスファイルを追加します。このクラスがカスタムコントロールの基礎となります。例えば、”MyCustomControl.cs”という名前でクラスを作成します。このクラスは、通常のコントロールクラス(例えば、Control
やUserControl
)を継承します。
using System;
using System.Windows.Forms;
public class MyCustomControl : Control
{
// カスタムコントロールの初期化処理
public MyCustomControl()
{
// 初期設定
this.BackColor = System.Drawing.Color.LightBlue;
this.Size = new System.Drawing.Size(100, 50);
}
// 描画処理のオーバーライド
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString("Hello, World!", this.Font, System.Drawing.Brushes.Black, new System.Drawing.Point(10, 10));
}
}
カスタムコントロールのプロジェクトへの追加
作成したカスタムコントロールをプロジェクトに追加します。プロジェクト内のToolbox
にカスタムコントロールをドラッグアンドドロップすることで、デザインビューに表示されるようになります。
カスタムコントロールの配置とテスト
デザイナビューでカスタムコントロールをフォームに配置し、プロジェクトを実行して動作を確認します。カスタムコントロールが正しく表示され、「Hello, World!」のテキストが描画されていることを確認します。
以上が基本的なカスタムコントロールの作成手順です。次に、カスタムコントロールに独自のプロパティとメソッドを追加する方法について説明します。
プロパティとメソッドの追加
カスタムコントロールに独自のプロパティとメソッドを追加することで、コントロールの機能を拡張できます。ここでは、プロパティとメソッドの追加方法について説明します。
独自のプロパティの追加
カスタムコントロールに独自のプロパティを追加するには、プロパティのゲッターとセッターを定義します。例えば、テキストプロパティを追加する場合は以下のようにします。
using System.ComponentModel;
public class MyCustomControl : Control
{
private string customText = "Hello, World!";
[Category("Custom Properties")]
[Description("Custom text displayed by the control")]
public string CustomText
{
get { return customText; }
set
{
customText = value;
this.Invalidate(); // 再描画
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString(customText, this.Font, System.Drawing.Brushes.Black, new System.Drawing.Point(10, 10));
}
}
独自のメソッドの追加
カスタムコントロールにメソッドを追加することで、特定の機能を持たせることができます。例えば、背景色を変更するメソッドを追加する場合は以下のようにします。
public class MyCustomControl : Control
{
// 既存のコード
public void ChangeBackgroundColor(System.Drawing.Color newColor)
{
this.BackColor = newColor;
this.Invalidate(); // 再描画
}
}
プロパティとメソッドの使用例
追加したプロパティやメソッドは、フォーム上で以下のように使用できます。
public class MainForm : Form
{
private MyCustomControl myControl;
public MainForm()
{
myControl = new MyCustomControl();
myControl.Location = new System.Drawing.Point(50, 50);
myControl.CustomText = "Welcome to My Control!";
this.Controls.Add(myControl);
Button changeColorButton = new Button();
changeColorButton.Text = "Change Color";
changeColorButton.Location = new System.Drawing.Point(50, 120);
changeColorButton.Click += ChangeColorButton_Click;
this.Controls.Add(changeColorButton);
}
private void ChangeColorButton_Click(object sender, EventArgs e)
{
myControl.ChangeBackgroundColor(System.Drawing.Color.LightGreen);
}
}
このようにして、カスタムコントロールに独自のプロパティとメソッドを追加することができます。次に、カスタムイベントの実装方法について説明します。
カスタムイベントの実装
カスタムコントロールに独自のイベントを実装することで、コントロールの動作をより柔軟に制御できます。ここでは、カスタムイベントの実装方法とその活用例について説明します。
カスタムイベントの定義
まず、カスタムイベントを定義します。イベントハンドラのデリゲートを定義し、イベントを宣言します。
public class MyCustomControl : Control
{
// 既存のコード
// カスタムイベントのデリゲートを定義
public delegate void CustomEventHandler(object sender, EventArgs e);
// カスタムイベントを宣言
[Category("Custom Events")]
[Description("Occurs when the custom action is performed.")]
public event CustomEventHandler CustomEvent;
protected virtual void OnCustomEvent(EventArgs e)
{
// イベントを発生させる
CustomEvent?.Invoke(this, e);
}
// メソッドやプロパティ内でカスタムイベントを発生させる
public void PerformCustomAction()
{
// カスタムアクションの実行
OnCustomEvent(EventArgs.Empty);
}
}
カスタムイベントの使用例
カスタムイベントを使用するには、フォームや他のコントロールでイベントハンドラを追加します。
public class MainForm : Form
{
private MyCustomControl myControl;
public MainForm()
{
myControl = new MyCustomControl();
myControl.Location = new System.Drawing.Point(50, 50);
myControl.CustomText = "Click to Trigger Event";
this.Controls.Add(myControl);
myControl.CustomEvent += MyControl_CustomEvent;
Button triggerEventButton = new Button();
triggerEventButton.Text = "Trigger Custom Event";
triggerEventButton.Location = new System.Drawing.Point(50, 120);
triggerEventButton.Click += TriggerEventButton_Click;
this.Controls.Add(triggerEventButton);
}
private void MyControl_CustomEvent(object sender, EventArgs e)
{
MessageBox.Show("Custom event triggered!");
}
private void TriggerEventButton_Click(object sender, EventArgs e)
{
myControl.PerformCustomAction();
}
}
カスタムイベントの発生とハンドリング
この例では、MyCustomControl
のPerformCustomAction
メソッドを呼び出すと、CustomEvent
が発生します。MainForm
でこのイベントをハンドリングすることで、カスタムイベントがトリガーされた際に特定の処理を実行できます。例えば、メッセージボックスを表示するなどのアクションを実行できます。
このようにして、カスタムコントロールに独自のイベントを実装し、アプリケーションのニーズに合わせた柔軟な動作を実現することができます。次に、カスタムコントロールの描画のカスタマイズ方法について説明します。
描画のカスタマイズ
カスタムコントロールの見た目を自由に変更するためには、描画処理をカスタマイズすることが必要です。ここでは、カスタム描画の方法について説明します。
OnPaintメソッドのオーバーライド
描画のカスタマイズは、OnPaint
メソッドをオーバーライドすることで行います。これにより、コントロールの描画処理を自由に定義できます。
public class MyCustomControl : Control
{
// 既存のコード
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 背景を描画
e.Graphics.Clear(this.BackColor);
// カスタムテキストを描画
using (var brush = new System.Drawing.SolidBrush(this.ForeColor))
{
e.Graphics.DrawString(this.CustomText, this.Font, brush, new System.Drawing.PointF(10, 10));
}
// カスタム図形を描画(例: 長方形)
using (var pen = new System.Drawing.Pen(System.Drawing.Color.Black, 2))
{
e.Graphics.DrawRectangle(pen, new System.Drawing.Rectangle(5, 5, this.Width - 10, this.Height - 10));
}
}
}
ダブルバッファリングの有効化
描画のちらつきを防ぐために、ダブルバッファリングを有効にすることが重要です。これにより、滑らかな描画が実現できます。
public MyCustomControl()
{
// ダブルバッファリングを有効にする
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
カスタム描画の活用例
以下に、カスタム描画の活用例を示します。この例では、カスタムコントロール上に円を描画します。
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 背景を描画
e.Graphics.Clear(this.BackColor);
// カスタムテキストを描画
using (var brush = new System.Drawing.SolidBrush(this.ForeColor))
{
e.Graphics.DrawString(this.CustomText, this.Font, brush, new System.Drawing.PointF(10, 10));
}
// カスタム図形を描画(例: 円)
using (var pen = new System.Drawing.Pen(System.Drawing.Color.Red, 2))
{
e.Graphics.DrawEllipse(pen, new System.Drawing.Rectangle(20, 20, this.Width - 40, this.Height - 40));
}
}
このように、カスタムコントロールの描画をカスタマイズすることで、独自のデザインや機能を実現することができます。次に、Visual Studioのデザイナでカスタムコントロールを利用するための設定方法について説明します。
デザイン時のサポート
Visual Studioのデザイナでカスタムコントロールを利用するためには、いくつかの設定を行う必要があります。ここでは、デザイン時のサポートを有効にする方法を説明します。
デザイン時の属性設定
カスタムコントロールのプロパティがデザイン時に正しく表示されるようにするためには、属性を設定します。System.ComponentModel
名前空間を使用して、プロパティにカテゴリや説明を付加します。
using System.ComponentModel;
public class MyCustomControl : Control
{
private string customText = "Hello, World!";
[Category("Custom Properties")]
[Description("Custom text displayed by the control")]
public string CustomText
{
get { return customText; }
set
{
customText = value;
this.Invalidate(); // 再描画
}
}
}
デザイン時のサポートクラスの追加
デザイン時のサポートを向上させるために、カスタムデザイナクラスを作成し、コントロールに関連付けます。
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
[Designer(typeof(MyCustomControlDesigner))]
public class MyCustomControl : Control
{
// 既存のコード
}
public class MyCustomControlDesigner : ControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
// デザイン時の動作をカスタマイズ
var myControl = (MyCustomControl)component;
EnableDesignMode(myControl, "CustomText");
}
}
Toolboxへの追加
カスタムコントロールをToolboxに追加することで、デザイナビューで簡単に使用できるようにします。Toolboxに追加するには、プロジェクトをビルドし、Toolboxにドラッグアンドドロップします。
- プロジェクトをビルドします。
- ソリューションエクスプローラーでビルド出力(.dllファイル)を見つけます。
- Visual StudioのToolboxを開きます。
- カスタムコントロールのDLLをToolboxにドラッグアンドドロップします。
デザイン時のカスタム描画
デザイン時に特定の表示を行いたい場合は、DesignMode
プロパティを使用してデザイン時かどうかを判定し、描画をカスタマイズします。
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this.DesignMode)
{
// デザイン時のカスタム描画
e.Graphics.DrawString("Design Mode", this.Font, System.Drawing.Brushes.Gray, new System.Drawing.PointF(10, 10));
}
else
{
// 実行時の描画
e.Graphics.DrawString(customText, this.Font, System.Drawing.Brushes.Black, new System.Drawing.PointF(10, 10));
}
}
このように、デザイン時のサポートを有効にすることで、Visual Studioのデザイナでカスタムコントロールをより便利に使用できるようになります。次に、複雑なカスタムコントロールの応用例について説明します。
応用例:複雑なカスタムコントロールの作成
ここでは、より複雑なカスタムコントロールの作成例を紹介します。具体的には、カスタムカレンダーコントロールを作成し、複数の機能を組み込んでいきます。
カスタムカレンダーコントロールの概要
このカスタムカレンダーコントロールでは、日付の選択やイベントの表示などの機能を実装します。これにより、ユーザーは日付選択や予定の確認を簡単に行えるようになります。
基本構造の定義
まず、カスタムカレンダーコントロールの基本構造を定義します。
using System;
using System.Drawing;
using System.Windows.Forms;
public class CustomCalendar : Control
{
private DateTime currentDate = DateTime.Now;
public CustomCalendar()
{
this.DoubleBuffered = true;
this.Size = new Size(200, 200);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawCalendar(e.Graphics);
}
private void DrawCalendar(Graphics g)
{
// カレンダーの描画ロジック
int cellWidth = this.Width / 7;
int cellHeight = this.Height / 6;
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
int dayOfWeek = (int)firstDayOfMonth.DayOfWeek;
for (int day = 1; day <= DateTime.DaysInMonth(currentDate.Year, currentDate.Month); day++)
{
int x = (dayOfWeek % 7) * cellWidth;
int y = (dayOfWeek / 7) * cellHeight;
g.DrawRectangle(Pens.Black, x, y, cellWidth, cellHeight);
g.DrawString(day.ToString(), this.Font, Brushes.Black, x + 5, y + 5);
dayOfWeek++;
}
}
}
プロパティとメソッドの追加
次に、カスタムカレンダーに必要なプロパティとメソッドを追加します。
public class CustomCalendar : Control
{
private DateTime currentDate = DateTime.Now;
public CustomCalendar()
{
this.DoubleBuffered = true;
this.Size = new Size(200, 200);
}
[Category("Custom Properties")]
[Description("Current date displayed by the calendar")]
public DateTime CurrentDate
{
get { return currentDate; }
set
{
currentDate = value;
this.Invalidate();
}
}
public void NextMonth()
{
currentDate = currentDate.AddMonths(1);
this.Invalidate();
}
public void PreviousMonth()
{
currentDate = currentDate.AddMonths(-1);
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawCalendar(e.Graphics);
}
private void DrawCalendar(Graphics g)
{
// カレンダーの描画ロジック
int cellWidth = this.Width / 7;
int cellHeight = this.Height / 6;
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
int dayOfWeek = (int)firstDayOfMonth.DayOfWeek;
for (int day = 1; day <= DateTime.DaysInMonth(currentDate.Year, currentDate.Month); day++)
{
int x = (dayOfWeek % 7) * cellWidth;
int y = (dayOfWeek / 7) * cellHeight;
g.DrawRectangle(Pens.Black, x, y, cellWidth, cellHeight);
g.DrawString(day.ToString(), this.Font, Brushes.Black, x + 5, y + 5);
dayOfWeek++;
}
}
}
イベントの追加
日付をクリックしたときにイベントを発生させるための処理を追加します。
public class CustomCalendar : Control
{
private DateTime currentDate = DateTime.Now;
public CustomCalendar()
{
this.DoubleBuffered = true;
this.Size = new Size(200, 200);
this.MouseClick += CustomCalendar_MouseClick;
}
[Category("Custom Properties")]
[Description("Current date displayed by the calendar")]
public DateTime CurrentDate
{
get { return currentDate; }
set
{
currentDate = value;
this.Invalidate();
}
}
public void NextMonth()
{
currentDate = currentDate.AddMonths(1);
this.Invalidate();
}
public void PreviousMonth()
{
currentDate = currentDate.AddMonths(-1);
this.Invalidate();
}
public event EventHandler<DateSelectedEventArgs> DateSelected;
protected virtual void OnDateSelected(DateSelectedEventArgs e)
{
DateSelected?.Invoke(this, e);
}
private void CustomCalendar_MouseClick(object sender, MouseEventArgs e)
{
int cellWidth = this.Width / 7;
int cellHeight = this.Height / 6;
int row = e.Y / cellHeight;
int col = e.X / cellWidth;
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
int dayOfWeek = (int)firstDayOfMonth.DayOfWeek;
int day = (row * 7 + col) - dayOfWeek + 1;
if (day > 0 && day <= DateTime.DaysInMonth(currentDate.Year, currentDate.Month))
{
OnDateSelected(new DateSelectedEventArgs(new DateTime(currentDate.Year, currentDate.Month, day)));
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawCalendar(e.Graphics);
}
private void DrawCalendar(Graphics g)
{
// カレンダーの描画ロジック
int cellWidth = this.Width / 7;
int cellHeight = this.Height / 6;
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
int dayOfWeek = (int)firstDayOfMonth.DayOfWeek;
for (int day = 1; day <= DateTime.DaysInMonth(currentDate.Year, currentDate.Month); day++)
{
int x = (dayOfWeek % 7) * cellWidth;
int y = (dayOfWeek / 7) * cellHeight;
g.DrawRectangle(Pens.Black, x, y, cellWidth, cellHeight);
g.DrawString(day.ToString(), this.Font, Brushes.Black, x + 5, y + 5);
dayOfWeek++;
}
}
}
public class DateSelectedEventArgs : EventArgs
{
public DateTime SelectedDate { get; }
public DateSelectedEventArgs(DateTime selectedDate)
{
SelectedDate = selectedDate;
}
}
複雑なカスタムコントロールの使用例
このカスタムカレンダーコントロールをフォームに追加し、動作を確認します。
public class MainForm : Form
{
private CustomCalendar customCalendar;
public MainForm()
{
customCalendar = new CustomCalendar();
customCalendar.Location = new Point(20, 20);
customCalendar.DateSelected += CustomCalendar_DateSelected;
this.Controls.Add(customCalendar);
Button nextMonthButton = new Button();
nextMonthButton.Text = "Next Month";
nextMonthButton.Location = new Point(240, 20);
nextMonthButton.Click += (sender, e) => customCalendar.NextMonth();
this.Controls.Add(nextMonthButton);
Button prevMonthButton = new Button();
prevMonthButton.Text = "Previous Month";
prevMonthButton.Location = new Point(240, 60);
prevMonthButton.Click += (sender, e) => customCalendar.PreviousMonth();
this.Controls.Add(prevMonthButton);
}
private void CustomCalendar_DateSelected(object sender, DateSelectedEventArgs e)
{
MessageBox.Show($"Selected Date: {e.SelectedDate.ToShortDateString()}");
}
}
このようにして、複雑なカスタムコントロールを作成し、様々な機能を組み込むことができます。次に、学んだ内容を確認するための演習問題を提供します。
演習問題
ここでは、カスタムコントロールの作成に関する理解を深めるための演習問題を提供します。以下の問題に取り組むことで、学んだ内容を実践的に応用する力を養います。
演習問題1: 基本的なカスタムコントロールの作成
簡単なカスタムボタンコントロールを作成し、次の機能を追加してください。
- ボタンをクリックすると、背景色がランダムに変わる。
- ボタンにマウスがホバーすると、ボタンのテキストが「Hovered」に変わる。
ヒント
OnClick
メソッドをオーバーライドして背景色を変更。OnMouseEnter
とOnMouseLeave
メソッドをオーバーライドしてテキストを変更。
public class CustomButton : Button
{
private Random rand = new Random();
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
this.BackColor = Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256));
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
this.Text = "Hovered";
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
this.Text = "Custom Button";
}
}
演習問題2: プロパティの追加
独自のプロパティを持つカスタムテキストボックスコントロールを作成し、次の機能を追加してください。
MaxCharacters
プロパティを追加し、入力できる最大文字数を制限する。
ヒント
- プロパティのゲッターとセッターを定義。
OnTextChanged
イベントをオーバーライドして文字数をチェック。
public class CustomTextBox : TextBox
{
private int maxCharacters = 10;
[Category("Custom Properties")]
[Description("Maximum number of characters allowed in the text box.")]
public int MaxCharacters
{
get { return maxCharacters; }
set { maxCharacters = value; }
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (this.Text.Length > maxCharacters)
{
this.Text = this.Text.Substring(0, maxCharacters);
this.SelectionStart = this.Text.Length; // キャレットの位置を維持
}
}
}
演習問題3: カスタムイベントの実装
独自のイベントを持つカスタムチェックボックスコントロールを作成し、次の機能を追加してください。
- チェックボックスがチェックされたときに
CheckedChanged
イベントを発生させる。
ヒント
- カスタムイベントハンドラを定義。
OnCheckedChanged
メソッドをオーバーライドしてイベントを発生。
public class CustomCheckBox : CheckBox
{
public delegate void CheckedChangedEventHandler(object sender, EventArgs e);
[Category("Custom Events")]
[Description("Occurs when the checked state is changed.")]
public event CheckedChangedEventHandler CheckedChanged;
protected virtual void OnCheckedChanged(EventArgs e)
{
CheckedChanged?.Invoke(this, e);
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
OnCheckedChanged(EventArgs.Empty);
}
}
これらの演習問題を通じて、カスタムコントロールの作成に関する知識をさらに深めてください。次に、この記事の内容を総括し、重要ポイントを再確認します。
まとめ
この記事では、C#でのカスタムコントロールの作成方法について、基本から応用まで詳しく解説しました。カスタムコントロールを作成することで、標準コントロールでは実現できない独自の機能やデザインをアプリケーションに追加することが可能です。
- 基本的なカスタムコントロールの作成: カスタムコントロールの基本的な作成手順を学びました。
- プロパティとメソッドの追加: カスタムコントロールに独自のプロパティやメソッドを追加して機能を拡張する方法を理解しました。
- カスタムイベントの実装: 独自のイベントを実装し、コントロールの動作を柔軟に制御する方法を学びました。
- 描画のカスタマイズ:
OnPaint
メソッドをオーバーライドしてカスタム描画を行う方法を説明しました。 - デザイン時のサポート: Visual Studioのデザイナでカスタムコントロールを利用するための設定方法を解説しました。
- 複雑なカスタムコントロールの応用例: より複雑なカスタムコントロールの実例を通じて、実践的な応用方法を学びました。
- 演習問題: 学んだ内容を実践的に確認するための演習問題を提供しました。
これらの内容を通じて、カスタムコントロールの作成に必要な知識と技術を習得できたことと思います。今後のプロジェクトで、ぜひこれらの技術を活用してください。
コメント