Control

プロパティ

静的プロパティ
プロパティ 内容
Font DefaultFont コントロールの既定のフォント

その値はユーザーのOSやカルチャの設定に依存し、Windows NT 4.xの日本語版では"MS UI Gothic, 9 point" Remarks - Control.DefaultFont Property (System.Windows.Forms) | Microsoft Learn

MouseButtons MouseButtons マウスボタンの状態
Point MousePosition スクリーン座標でのマウスカーソルの位置

クライアント座標が必要ならば、control.PointToClient(Control.MousePosition)で得られる

Keys ModifierKeys 修飾キー (Shift、Ctrl、Alt) の状態 How to: Determine Which Modifier Key Was Pressed | Microsoft Learn

どのキーも押されていなければKeys.None

     
プロパティ 内容
string Name コントロールの名前
(プログラムの実行時にオブジェクトを評価するためのもの)
string Text コントロールに関連付けられたテキスト

用途は派生クラスによって異なり、たとえばFormではタイトルバーのテキストとして用いられるが、RichTextBoxではコントロール内に表示されるテキストとなる。Remarks - Control.Text Property (System.Windows.Forms) | Microsoft Learn

Object Tag コントロールに関する任意のデータの格納 Control.Tag プロパティ (System.Windows.Forms) | MSDN
bool TabStop trueならば、ユーザーはTabキーでフォーカスを移すことができる
int TabIndex コントロールのタブ オーダー (tab order)
bool IsDisposed trueならば、コントロールは破棄されている
bool Enabled trueならば、ユーザーからの操作に応答する
bool Visible trueならば、コントロールとその子コントロールが表示されている

これにtrueを設定しても、表示されるまではfalseを返す。また親コントロールが表示されていなければtrueを設定しても表示されないが、親コントロールが表示されたときに表示される Remarks - Control.Visible Property (System.Windows.Forms) | Microsoft Learn

親コントロールが表示されていなければ、falseが返される Visible - Control.cs

bool Focused trueならば、コントロールにフォーカスがある
bool ContainsFocus trueならば、コントロールまたはその子コントロールにフォーカスがある
bool Capture trueならば、コントロールはマウスをキャプチャしている
Cursor DefaultCursor 既定のカーソル
Cursor Cursor マウスポインタがコントロール上にあるときに表示されるカーソル
bool UseWaitCursor trueならば、待機カーソルを使用する
Control Parent このコントロールの親コントロール

RadioButtonなど他のコントロールに格納されるコントロールは、FindForm()とは異なる値となる

Control TopLevelControl このコントロールの最上位の親コントロール。典型的には、最も外側のForm。Formが親になっていないならばnull
ControlCollection Controls コントロールに格納されているコントロールのコレクション
Font Font コントロールで使用されるフォント。既定値はDefaultFontプロパティの値
int FontHeight コントロールのフォントの高さ
Point Location 親コントロールの位置を基準とした、左上の位置
int Left 親コントロールの位置を基準とした、左端の位置 (Location.Xと同一)
int Right 親コントロールの位置を基準とした、右端の位置 (Left+Widthと同一)
bool AutoSize 派生クラスで使用される
Padding Margin コントロール間の空間。隣接するコントロールにも設定されていると、大きい方の値が採用される。デザイナでコントロールの位置を合わせるときに表示される、スナップライン (Snap Lines) に作用する
Padding Padding コントロール内の空間。AutoSizeを実装していないコントロールでは無効 Remarks - Control.Padding Property (System.Windows.Forms) | Microsoft Learn
Size Size コントロールのサイズ

このプロパティが返すWidthやHeightに設定しても、コントロールのサイズに作用しない。そのためにはWidthプロパティなどに設定するか、新しく作成したSizeオブジェクトをこのプロパティに設定する

位置とサイズを同時に設定するならば、SetBounds()を用いる

int Width コントロールの幅 (SizeプロパティのWidthと同一)
Size DefaultSize コントロールの既定のサイズ
Size PreferredSize コントロールに適合するサイズ。GetPreferredSize(Size.Empty)の値と同じ PreferredSize - Control.cs
Size MaximumSize GetPreferredSize(Size)で指定できる、上限のサイズ

Sizeで設定可能なサイズ、AnchorやDockで自動設定されるサイズは、これに制限される

Size MinimumSize GetPreferredSize(Size)で指定できる、下限のサイズ
Size DefaultMaximumSize 指定されている、既定の最大サイズ
Size DefaultMinimumSize 指定されている、既定の最小サイズ
Size ClientSize コントロールのクライアント領域のサイズ
Rectangle Bounds コントロールのサイズと位置。サイズは非クライアント要素を含む、位置は親コントロール相対
Rectangle ClientRectangle コントロールのクライアント領域のサイズと位置
AnchorStyles Anchor 親コントロールのどの辺との距離を一定とするか
(AnchorとDockは排他的で、後に設定されたほうが有効となる)

親コントロールが基準であり、隣接するコントロールは無関係

DockStyle Dock 親コントロールのどの辺に接触させるか
(AnchorとDockは排他的で、後に設定されたほうが有効となる)

同じ辺に複数のコントロールを結合させた場合はZオーダー (Z-order) に従い配置され、追加したものが端に、先のものが押し出される

ContextMenu ContextMenu コントロールに結びつけられているContextMenu。.NET 2.0以降ならば、ContextMenuStripを用いる
ContextMenuStrip ContextMenuStrip コントロールに結びつけられているContextMenuStrip
IntPtr Handle コントロールに結びつけられているウィンドウ ハンドル

これはWindows HWNDの値であり、取得時に作成されていないときは強制的に作成される

bool IsHandleCreated trueならば、コントロールに割り当てられたハンドルがある

ハンドルが割り当てられたことは、HandleCreatedで検知できる

bool InvokeRequired trueならば、Invoke()メソッドを呼び出す必要がある
ControlBindingsCollection DataBindings コントロールのデータ バインディング
bool CausesValidation trueならば、フォーカスを受け取ったときに検証が必要ならば、検証を実行する
bool DoubleBuffered trueならば、ダブル バッファリングを有効にしてコントロールを描画する
ImeMode ImeMode コントロールのIMEのモード
ImeMode DefaultImeMode コントロールがサポートする、既定のIMEのモード。派生クラスでオーバーライドすることで、既定のモードを変更できる
     
プロパティ - Control Class (System.Windows.Forms) | Microsoft Learn

アンビエント プロパティ (ambient property)

アンビエント プロパティがあてがわれるプロパティは、値を設定しない限り親コントロールの値が適用されます。AmbientProperties クラス (System.Windows.Forms) | Microsoft Learn

以下のプロパティがこれに該当します。

  • Cursor
  • Font
  • BackColor
  • ForeColor
  • RightToLeft
Remarks - Control Class (System.Windows.Forms) | Microsoft Learn

TabIndex

タブで選択されるコントロールの順番は、Visual Studioのビュー デザイナーから設定すると簡単です。それには対象のコントロールを含むフォームをビュー デザイナーで開き、それにフォーカスがある状態で、メニューの【表示 → タブ オーダー】にチェックを入れます。そして設定するタブの順に、コントロールをクリックします。Changing the Tab Order of Controls | MSDN

Font

親コントロールまたはアンビエント プロパティに有効な値があるならば、DefaultFontより優先されます。Font - Control.cs

コントロールによっては親コントロールのFontを引き継がないため、個別に設定する必要があります。たとえば以下のコントロールが、それに該当します。

これら親コントロールのFontが適用されないコントロールは、Control.OnParentFontChanged()メソッドでFontを適用することで、親のそれと同一にできます。

Controls

コントロール内に複数のコントロールが格納されているとき、それらが重なって表示されるときはZオーダー (z-order) の大きいものが背面になります。そしてこのZオーダーはControlsプロパティに追加した順で大きくなるため、後に追加したコントロールほど後ろに表示されます。

Panel panel0 = new Panel();
Panel panel1 = new Panel();
Panel panel2 = new Panel();

this.Controls.Add(panel0); // 最初に追加
this.Controls.Add(panel1);
this.Controls.Add(panel2);

int index0 = this.Controls.GetChildIndex(panel0); // 0 (最初に追加されたのでインデックスは0で、最前面に表示される)
int index1 = this.Controls.GetChildIndex(panel1); // 1
int index2 = this.Controls.GetChildIndex(panel2); // 2

this.Controls.SetChildIndex(panel2, 0);

int index0a = this.Controls.GetChildIndex(panel0); // 1
int index1a = this.Controls.GetChildIndex(panel1); // 2
int index2a = this.Controls.GetChildIndex(panel2); // 0

Visual Studioのビュー デザイナーで操作するならば、ドキュメント アウトラインでこの順を変更できます。

Zオーダーの予期せぬ変更

Visibleプロパティをfalseからtrueに設定すると、Controls内のコントロールのZオーダーが変更されることがあります。この問題はVisibleを設定するときに、

  • IntPtr dummy = control.Handle;のように取得することで、強制的にウィンドウ ハンドルを作成させる。
  • ControlCollection.SetChildIndex()で、Zオーダーを明示的に設定しなおす。

のいずれかの方法で解決できます。 c# - Z Order Changing When Making Docked Controls Visible - Stack Overflow Remarks - Control.CreateControl Method (System.Windows.Forms) | Microsoft Learn

UseWaitCursor

UIスレッドをブロックする処理はカーソルの変更もブロックするため、別スレッドとしなければこのプロパティへの設定は意味をなしません。またこのプロパティへの設定はマウス関連のイベントが発生するまで適用されないため、即座にカーソルを変更するには、CursorプロパティへCursors.WaitCursorを設定します。Remarks - Control.UseWaitCursor Property (System.Windows.Forms) | Microsoft Learn

同一スレッドでUseWaitCursorを設定しても、表示は更新されません。

this.UseWaitCursor = true;
Task.Delay(1000).Wait(); // ここでスレッドがブロックされるため、変更は適用されない
this.UseWaitCursor = false;

設定後にスレッドを替えれば設定はされますが、マウス関連のイベントが発生するまで表示は変わりません。

this.UseWaitCursor = true;
await Task.Run(() => // 呼び出し元へ処理が戻され、ここで待機カーソルに設定される
{
    Task.Delay(1000).Wait();
    this.UseWaitCursor = false;
}); // ここで待機カーソルの設定が解除される

Cursorプロパティに設定すれば即座に適用されますが、UIスレッド以外からは設定できません。

this.Cursor = Cursors.WaitCursor; // ここで待機カーソルとなる
Task task = new Task(() =>
{
    Task.Delay(1000).Wait();
    //this.Cursor = Cursors.Default; // 「有効ではないスレッド間の操作」としてInvalidOperationExceptionが投げられるため、ここでは変更できない。
});

task.ContinueWith((_task) => // Taskの完了後、呼び出し元のスレッドで実行される
{
    this.Cursor = Cursors.Default; // ここで元のカーソルとなる
}, TaskScheduler.FromCurrentSynchronizationContext());
task.Start();

InvokeRequired

コントロールが作成されたスレッドと呼び出し元のそれが異なるか、コントロールのハンドルが作成されていないときにfalseが返されます。コントロールのハンドルがまだ存在しないときには、それが見つかるまでコントロールの親チェーンをたどって探されます。Control.InvokeRequired プロパティ (System.Windows.Forms) | Microsoft Learn

trueが返されるときは、Invoke()を通してコントロールへアクセスすることが求められます。しかしfalseが返されたとしてもハンドルが作成されていないが故の可能性があるため、IsHandleCreatedがfalseならばそれが作成されるまでInvoke()の呼び出しを待ちます。これを待たないとコントロールへアクセスしているときに、それとは異なるスレッドでハンドルが作成される恐れがあります。Remarks - Control.InvokeRequired Property (System.Windows.Forms) | Microsoft Learn

Form form1 = new Form();
Task.Run(() =>
{
    bool r1 = form1.IsHandleCreated; // false
    bool r2 = form1.InvokeRequired; // false

    form1.Text = "TEST";
});
Form form2 = new Form();
form2.Show();

Task.Run(() =>
{
    bool r1 = form2.IsHandleCreated; // true
    bool r2 = form2.InvokeRequired; // true

    form2.Text = "TEST"; // InvalidOperationException「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール '' がアクセスされました。」
});

DoubleBuffered

描画処理をメモリ バッファに対して行い、画面への描画はそれのコピーの1回だけとすることで、ちらつき (flicker) を抑制できます。内部ではSetStyle()で、OptimizedDoubleBufferが有効にされます。

set {
    if (value != DoubleBuffered) {

        if (value) {
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, value);
        }
        else {
            SetStyle(ControlStyles.OptimizedDoubleBuffer, value);
        }
    }
}
DoubleBuffered - Control.cs

コントロールによってはこれを有効にしても効果はないとされ、エディタで候補として表示されません。 Remarks - ProgressBar.DoubleBuffered Property (System.Windows.Forms) | Microsoft Learn DoubleBuffered - ProgressBar.cs EditorBrowsableState Enum (System.ComponentModel) | Microsoft Learn

参考

プロパティ バインディング … コントロールのプロパティとアプリケーション設定との拘束

メソッド

メソッド 機能
SuspendLayout() コントロールのレイアウト ロジックを一時的に停止させ、パフォーマンスを向上させる
ResumeLayout(Boolean) コントロールのレイアウト ロジックを再開させる。trueを渡すと、保留中のレイアウト要求の適用を強制する。引数を省略するとtrueが渡される ResumeLayout - Control.cs
PerformLayout() コントロールのレイアウト ロジックを、すべての子コントロールに適用するように強制する。引数を渡すとそれでLayoutEventArgs()が作成され、OnLayout()が呼ばれる PerformLayout - control.PerformLayout
Invalidate(Boolean) コントロールの領域を無効にして、ペイント メッセージを送れる。trueを渡すと、子コントロールも無効にする
Update() コントロールの無効化された領域を、再描画させられる
Refresh() コントロールの領域を無効にして、即座に再描画させられる

これはInvalidate(true); Update();と呼ぶのと同等 Refresh() - Control.cs

OnPaint(PaintEventArgs) 描画処理を上書きできる
OnPaintBackground(PaintEventArgs) 背景の消去要求を上書きできる
GetStyle(ControlStyles) 指定のControlStylesフラグの値を取得できる
SetStyle(ControlStyles, Boolean) 指定のControlStylesフラグの値を設定できる
Scale(SizeF) 指定のスケーリングファクター (scaling factor) で、コントロールとすべての子コントロールを拡大縮小する
WndProc(Message) Windowsメッセージを処理できる
PreProcessMessage(Message) メッセージ ループ内のキーボードや入力メッセージがディスパッチされる前に処理できる
CreateHandle() コントロールのハンドルを作成する
ProcessCmdKey(Message, Keys) コマンドキーを処理する。コマンドキーとはアクセラレータやメニューのショートカットで、通常の入力キーよりつねに優先される

これらのキーを処理するため、メッセージの予備処理中に呼ばれる

ProcessDialogKey(Keys) ダイアログキーを処理する。ダイアログキーとは、TabEnterEscや方向キーなど

これらのキーを処理するため、メッセージの予備処理中に呼ばれる

ProcessDialogChar(Char) ダイアログ文字を処理する
Show() コントロールをユーザーに表示する。これはVisibleプロパティをtrueとするのと同じ Show - Control.cs
Focus() コントロールへ入力フォーカスを設定する

なおFocus()は独自のコントロールで使用するものであり、通常はSelect()を用いる。もしそれが子コントロールならばContainerControl.ActiveControlプロパティ、フォームならばActivate()を代わりに用いる。Remarks - Control.Focus Method (System.Windows.Forms) | Microsoft Learn

Select() コントロールをアクティブにできる
SelectNextControl(Control, Boolean, Boolean, Boolean, Boolean) 次のコントロールをアクティブにできる
GetNextControl(Control, Boolean) タブ オーダーで前または後にあるコントロールを得られる

(現在アクティブなコントロールは、ContainerControl.ActiveControlプロパティで得られる)

GetContainerControl() コントロールの親のContainerControlを得られる
PointToClient(Point) 指定位置を、クライアント座標へ変換できる
PointToScreen(Point) 指定位置を、スクリーン座標 (画面座標) へ変換できる
   
メソッド - Control Class (System.Windows.Forms) | Microsoft Learn

SuspendLayout()

コントロールのレイアウト ロジックを、一時的に停止させられます。Control.SuspendLayout メソッド (System.Windows.Forms) | MSDN

これはコントロールに複数のコントロールを追加するときに、その都度レイアウトが調整されるのを抑制するためのものであり、コントロールの内容の更新には無関係です。ただしコントロール上に配置されたMenuStrip、ToolStripやStatusStripのFontプロパティを変更するときにもレイアウトが調整されるため、これを抑制する効果はあります。

呼び出しの回数が内部で加算されており、ResumeLayout()でそれを減算しないと、初回以外は何も処理されません。 SuspendLayout - Control.cs ResumeLayout - Control.cs

レイアウト ロジックが停止しているかどうかは、internalなプロパティであるIsLayoutSuspendedで確認できます。How to determine if SuspendLayout is in effect

停止させたレイアウト ロジックをResumeLayout()で再開させるとき、引数を省略するかtrueを渡すと内部でPerformLayout()が呼ばれます。一方でfalseを渡すとレイアウトの情報が初期化されます。 ResumeLayout - Control.ResumeLayout 「ResumeLayout()」と「ResumeLayout(false) + PerformLayout」の違い - コントロールのレイアウトを一時中断して、パフォーマンスを向上させる - .NET Tips (VB.NET,C#...) The SuperSecretSideEffect of ResumeLayout(false) - jfo's coding - Site Home - MSDN Blogs

Invalidate()

public void Invalidate (bool invalidateChildren);
Invalidate(Boolean) - Control.Invalidate メソッド (System.Windows.Forms) | Microsoft Learn

子コントロールも無効にするにはinvalidateChildrenにtrueを渡します。

引数を省略してInvalidate()とするのは、Invalidate(false)とするのと同等です。Invalidate() - Control.cs

このメソッドを呼び出しても描画は強制されません。即座に描画させたいならば、このメソッドの呼び出し後にUpdate()を呼びます。

UIスレッド以外から呼び出すと、描画されないことがあります。かといってUIスレッド以外からはUpdate()を呼び出せないため、そのような場合はUIスレッドに戻してからInvalidate()を呼びます。

Invoke()

コントロールの基礎となるウィンドウ ハンドルを所有するスレッドで、デリゲートを実行できます。このメソッドを呼ぶべきか不確かならば、InvokeRequiredで確認できます。

public object Invoke(
    Delegate method
)
Invoke(Delegate) - Control.Invoke メソッド (System.Windows.Forms) | Microsoft Learn Invoke - Control.cs

コントロールの基礎となるウィンドウ ハンドルが見つかるまで、コントロールの親チェーンが検索されます。見つからなければ「ウィンドウ ハンドルが作成される前、コントロールで Invoke または BeginInvoke を呼び出せません。」としてInvalidOperationExceptionが投げられます。

戻り値は、methodからの戻り値です。

デリゲートを非同期で実行する、つまりその処理の完了を待たせないならば、代わりにBeginInvoke()で呼び出します。c# - What's the difference between Invoke() and BeginInvoke() - Stack Overflow

コントロールのスレッドが処理待ちでブロックされていると、Invoke()の呼び出しでデッドロックします。

Form form = new Form();
form.Show();

Task.Run(() =>
{
    // ここは、異なるスレッド

    form.Invoke((MethodInvoker)delegate
    {
        // ここは、コントロールの基礎となるウィンドウ ハンドルを所有するスレッド
    });
});

// ここは、コントロールの基礎となるウィンドウ ハンドルを所有するスレッド
// ここの処理を抜けるまで、Invoke()のデリゲートは実行されない

引数を渡したいならば、第2引数以降で渡します。

public object Invoke (
    Delegate method,
    params object[] args
    );
Invoke(Delegate, Object[]) - Control.Invoke メソッド (System.Windows.Forms) | Microsoft Learn
private void Method1() {}
private void Method2(int a, int b) {}
private bool Method3(int a) { return true; }

private void Sample()
{
    object r1 = this.Invoke((Action)Method1);
    object r2 = this.Invoke((Action<int, int>)Method2, 1, 2);
    object r3 = this.Invoke((Func<int, bool>)Method3, 1);
}

BeginInvoke()

public IAsyncResult BeginInvoke(
    Delegate method
)
Control.BeginInvoke メソッド (System.Windows.Forms) | Microsoft Learn BeginInvoke - Control.cs

BeginInvoke()で呼び出したmethodの結果を受け取りたいならば、EndInvoke()でそれが返されるまで待たせます。Control.EndInvoke(IAsyncResult) メソッド (System.Windows.Forms) | Microsoft Learn

Func<int, int> method = (val) =>
{
    // ここはコントロールのスレッド (UIスレッド) で処理される
    return val * 2;
};

IAsyncResult asyncResult = this.BeginInvoke(method, 2); // デリゲートの完了を待たず、処理がすぐに戻る

// ここではコントロールのスレッド と呼び出し側のスレッドが、平行して実行される

object result = this.EndInvoke(asyncResult); // 呼び出したデリゲートの完了を待って、その結果を受け取る

ResetBackColor()

BackColorプロパティを既定値にリセットできます。Control.ResetBackColor メソッド (System.Windows.Forms) | Microsoft Learn

内部的にはBackColorにColor.Emptyを設定することで、親コントロールのBackColorが適用されるようにしています。ResetBackColor - Control.cs

GetStyle()

protected bool GetStyle (System.Windows.Forms.ControlStyles flag);
Control.GetStyle(ControlStyles) メソッド (System.Windows.Forms) | Microsoft Learn
bool r = this.GetStyle(
    ControlStyles.DoubleBuffer |
    ControlStyles.UserPaint |
    ControlStyles.AllPaintingInWmPaint);

この方法では、すべてのスタイルがセットされているときのみtrueが返されます。

SetStyle()

protected void SetStyle (
    System.Windows.Forms.ControlStyles flag,
    bool value // 指定のスタイルを適用するならばtrue
    );
Control.SetStyle(ControlStyles, Boolean) メソッド (System.Windows.Forms) | Microsoft Learn

複数のスタイルは、論理ORで渡すことで一括して設定できます。

this.SetStyle(
    ControlStyles.DoubleBuffer |
    ControlStyles.UserPaint |
    ControlStyles.AllPaintingInWmPaint,
    true);

ControlStyles 列挙型

列挙子 内容
     
OptimizedDoubleBuffer 131072 コントロールはスクリーンへ描画するより、先にバッファへ描画される。これによりちらつき (flicker) を減少できる .net - ControlStyles.DoubleBuffer vs. ControlStyles.OptimizedDoubleBuffer - Stack Overflow
     
ControlStyles 列挙型 (System.Windows.Forms) | Microsoft Learn

SelectNextControl()

次のコントロールをアクティブにできます。

public bool SelectNextControl (
    System.Windows.Forms.Control ctl, // 検索の始点となるコントロール
    bool forward,     // trueならばタブオーダーの前方へ、さもなくば後方へ移動する
    bool tabStopOnly, // trueならば、TabStopプロパティがtrueのコントロールにだけ移動する
    bool nested,      // trueならば、入れ子になったコントロールも含める
    bool wrap         // trueならば、タブオーダーの末尾に達したら最初から検索する
    );
Control.SelectNextControl(Control, Boolean, Boolean, Boolean, Boolean) メソッド (System.Windows.Forms) | Microsoft Learn

特定のコントロールのタブオーダーで次となるコントロールをアクティブにするには、そのコントロールの親からの呼び出しとなるようにcontrol.Parent.SelectNextControl()のようにします。

OnParentVisibleChanged()

OnVisibleChanged()は、Visibleがfalseからtrueまたはその逆に変更された場合にも呼ばれますが、OnParentVisibleChanged()はfalseからtrueの場合にしか呼ばれません。 Control.OnVisibleChanged(EventArgs) Method (System.Windows.Forms) | Microsoft Learn OnParentVisibleChanged - Control.cs OnParentVisibleChanged when parent visible becomes false

親コントロールのVisibleがfalseとなったときは子コントロールのそれもfalseを返しますが、これは親コントロールのVisibleの値を返すだけで、子コントロールの表示状態は変更されていません。Visible - Control.cs

そのため子コントロール側ではOnVisibleChanged()も呼ばれないため、親のVisibleの変更を知りたいならばParent.VisibleChangedのイベントに応じるようにします。

protected override void OnParentChanged(EventArgs e)
{
    base.OnParentChanged(e);

    this.Parent.VisibleChanged += delegate
    {
    };
}

キー処理

キーの押下に応じて、次の順でメソッドが呼ばれます。

aの押下

  1. OnPreviewKeyDown(): A
  2. ProcessCmdKey(): A
  3. ProcessDialogKey(): A
  4. OnKeyDown(): A
  5. ProcessDialogChar(): a
  6. OnKeyPress(): a
  7. OnKeyUp(): A

キーが押され続けた場合、キーが送信されるたびに1~6がこの順で呼び出され、離されたときにOnKeyUp()が一度だけ呼ばれます。

Alt + aの押下

  1. OnPreviewKeyDown(): Menu, Alt
  2. ProcessCmdKey(): Menu, Alt
  3. ProcessDialogKey(): Menu, Alt
  4. OnKeyDown(): Menu, Alt
  1. OnPreviewKeyDown(): A, Alt
  2. ProcessCmdKey(): A, Alt
  3. ProcessDialogKey(): A, Alt
  4. OnKeyDown(): A, Alt
  5. ProcessDialogChar(): a
  1. OnKeyUp: A, Alt
  2. OnKeyUp: Menu

イベント

区分 イベント 発生タイミング
マウス MouseEventHandler MouseDown コントロール上で、マウスボタンが押されたとき
EventHandler Click コントロールが、クリックされたとき (Enterキーなどにより発生することもあるため、マウスによるクリックとは限らない)
MouseEventHandler MouseClick コントロールが、マウスでクリックされたとき
MouseEventHandler MouseDoubleClick コントロールが、マウスでダブルクリックされたとき
MouseEventHandler MouseWheel コントロールにフォーカスがあるときに、マウスホイールが移動したとき
EventHandler MouseEnter コントロール上に、マウスポインタが入ったとき
EventHandler MouseLeave コントロールから、マウスポインタが離れたとき
MouseEventHandler MouseMove コントロール上で、マウスポインタが移動したとき
EventHandler MouseHover コントロール上で、マウスポインタがとどまったとき。1度発生すると、ポインタが離れないと再度発生しない
キー PreviewKeyDownEventHandler PreviewKeyDown フォーカスがあるときに、キーが押されたとき (KeyDownより前に発生する)
KeyEventHandler KeyDown フォーカスがあるときに、キーが押されたとき
KeyPressEventHandler KeyPress フォーカスがあるときに、文字キー、SpaceまたはBackspaceが押されて離されたとき
ハンドル EventHandler HandleCreated コントロールのハンドルが、作成されたとき
EventHandler HandleDestroyed コントロールのハンドルが、破棄されているとき
ドラッグ&ドロップ DragEventHandler DragEnter コントロールの境界内へドラッグされたとき
DragEventHandler DragOver コントロールの境界内でドラッグされたとき
DragEventHandler DragDrop ドラッグ&ドロップ操作が完了したとき
EventHandler DragLeave コントロールの境界外へドラッグされたとき
  PaintEventHandler Paint コントロールが再描画されるとき
  EventHandler TextChanged Textプロパティの値が変更されるとき
  EventHandler Resize コントロールのサイズが変更されるとき
  EventHandler Enter コントロールが入力されたとき
  EventHandler Leave コントロールから入力フォーカスが離れたとき
  EventHandler Move コントロールが移動したとき
  LayoutEventHandler Layout 子コントロールの位置を変更する必要があるとき
イベント - Control Class (System.Windows.Forms) | Microsoft Learn

Click

このイベントではEventArgsしか渡されません。ボタンや位置などのマウスの情報が必要ならば、MouseClickを捕捉します。Remarks - Control.Click Event (System.Windows.Forms) | MSDN

Controlを継承したクラスによって、右クリックやダブルクリックなどへの応答が異なります。Remarks - Control.Click Event (System.Windows.Forms) | MSDN

Clickイベントを発生しないクラス

スタイルにStandardClickが設定されていないコントロールは、このClickイベントを発生させません。このスタイルが設定されているかどうかは、GetStyle()で確認できます。

bool style = GetStyle(ControlStyles.StandardClick);

MouseClick

ハンドラにはMouseEventArgsが渡されます。Control.MouseClick イベント (System.Windows.Forms) | MSDN

コントロール上でマウスがクリックされると、次の順でイベントが発生します。

  1. MouseDown … マウスボタンが押されたとき
  2. Click
  3. MouseClick
  4. MouseUp … マウスボタンが離されたとき
Remarks - Control.MouseClick Event (System.Windows.Forms) | MSDN

続けて2回クリックされたとき、OSによってそれがダブルクリックと認識されると、MouseClickの代わりにMouseDoubleClickが発生します。

MouseEventArgs
プロパティ 内容
MouseButtons Button 押されたマウス ボタン。複数のボタンが同時に押されたときは、最初に離されたボタン

型のMouseButtonsにはFlagsAttribute属性があり、同時に押されることが想定されている。しかしこのイベントは最初に離された1つのボタンしか通知しない

int Clicks マウス ボタンが押されて離された回数
int Delta マウス ホイールの回転回数

(マウス ホイールのノッチ1つが1移動量に相当)

Point Location マウス イベント生成時のマウスのx座標とy座標

(フォームの左上を基準としたピクセル単位)

int X Location.Xと同じ
int Y Location.Yと同じ
プロパティ - MouseEventArgs クラス (System.Windows.Forms) | MSDN

PreviewKeyDown

このイベントはKeyDownイベントの前に発生し、TabEnterEscや方向キーなど、KeyDownイベントを発生させないキーに対して、そのイベントを発生するように指示できます。

private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Tab:
        case Keys.Enter:
            e.IsInputKey = true; // これらのキーで、KeyDownイベントが発生するようになる
            break;
    }
}

private void button1_KeyDown(object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Tab:
            break;

        case Keys.Enter:
            break;
    }
}
PreviewKeyDownEventArgs
プロパティ 内容
bool IsInputKey trueならば、通常の入力キー
     
PreviewKeyDownEventArgs クラス (System.Windows.Forms) | MSDN

KeyDown

押されたキーの情報は、KeyEventArgsで渡されます。Control.KeyDown イベント (System.Windows.Forms) | Microsoft Learn

TabEnterEscや方向キーなどでKeyDownイベントを発生させるには、IsInputKey()かPreviewKeyDownのハンドラで指示します。Remarks - Control.KeyDown Event (System.Windows.Forms) | Microsoft Learn

特定の機能の呼び出しにキーを割り当てるのが目的ならばこのイベントを用いず、その機能のメニュー項目を作成し、それのShortcutKeysプロパティにキーを設定します。なお修飾キーの状態は、静的プロパティであるControl.ModifierKeysから、イベントとは無関係に取得できます。

キーが押され続けたときはキーコードが送信されるたびにこのイベントがくり返し発生し、離されたときにKeyUpが一度だけ発生します。よってKeyDownとKeyUpの呼び出し回数は一致しないことがあります。

ちなみに、キー入力を発生させるにはSendKeys.Send("{ENTER}")のように、SendKeysから送信します。方法: マウス イベントとキーボード イベントをコードでシミュレートする - Windows Forms .NET Framework | Microsoft Learn

GotFocus

これは低水準のイベントであり、Activatedを用いるForm以外ではEnterを用います。一般的にGotFocusやLostFocusは、UICuesを更新するときやカスタム コントロールを作成するときに用います。Remarks - Control.GotFocus Event (System.Windows.Forms) | Microsoft Learn

LostFocus

GotFocus同様に低水準のイベントであり、Deactivateを用いるForm以外ではLeaveを用います。Remarks - Control.LostFocus Event (System.Windows.Forms) | Microsoft Learn

Form内で他のコントロールにフォーカスが移ったときはLeaveとLostFocusが発生しますが、Formがフォーカスを失ったときはLostFocusしか発生しません。これはEnterとGotFocusでも同様であり、アプリケーションで複数のFormを用いるような場合にはGotFocusやLostFocusが必要となるときがあります。

HandleCreated

このイベントは、コントロールのハンドルが作成されたときに発生します。Control.HandleCreated Event (System.Windows.Forms) | Microsoft Learn

そしてハンドルはコントロールが最初に表示されるときに作成されるため、FormのLoadに相当するイベントとして使用できます。c# - What is the Form "On_Load" equivalent for Controls? - Stack Overflow

フォーム上に配置されたコントロールでは、次の順でイベントが発生します。

  1. 親フォーム:HandleCreated
  2. 子コントロール:HandleCreated
  3. 親フォーム:Load

ただし親フォームが表示されたときにコントロールのVisibleがfalseだったときは、これがtrueに設定されたときに発生します。

WndProc()による判定

ハンドルが作成されたことはウィンドウ メッセージが0x0001 (WM_CREATE) であることで判定できるため、WndProc()でもハンドルが作成されたときに処理できます。

HandleDestroyed

このイベントは、コントロールのハンドルが破棄されているときに発生します。 Control.HandleDestroyed Event (System.Windows.Forms) | Microsoft Learn c# - What event signals that a UserControl is being destroyed? - Stack Overflow

フォーム上に配置されたコントロールでは、次の順でイベントが発生します。

  1. 親フォーム:FormClosing
  2. 親フォーム:FormClosed
  3. 親フォーム:Deactivate
  4. 親フォーム:HandleDestroyed
  5. 子コントロール:HandleDestroyed

Paint

Paintイベントのハンドラはコントロールが表示される前に登録しないと、表示されたときに呼び出されません。

Paintイベントが発生しないならば、SetStyle()でUserPaintをtrueに設定します。

this.SetStyle(ControlStyles.UserPaint, true);

コントロールの描画

ControlPaintクラスのメソッドで描画できます。これを視覚スタイルで描画するなら、コントロールごとの***Rendererクラスを用います。

DrawFocusRectangle()

キーボード フォーカスがあることを示す、点線の四角形を描画できます。

視覚スタイルでの描画

視覚スタイルが有効かどうかはApplication.RenderWithVisualStylesで確認でき、有効ならばUIの一貫性を保つために視覚スタイルで描画するようにします。

ComboBoxRendererなどは視覚スタイルが無効なときに呼び出すとInvalidOperationException例外を投げるため、これらのクラスでは視覚スタイルを用いて描画できるかをIsSupportedで確認するようにします。

開発時にはEnableVisualStyles()を呼び出さないことで、一時的に視覚スタイルを無効化できます。

VisualStyleRendererクラス

VisualStyleRenderer クラス (System.Windows.Forms.VisualStyles) | Microsoft Learn

現在の視覚スタイル要素の、指定のカラープロパティ (color properties) の色を取得できます。

public System.Drawing.Color GetColor (System.Windows.Forms.VisualStyles.ColorProperty prop);
VisualStyleRenderer.GetColor(ColorProperty) メソッド (System.Windows.Forms.VisualStyles) | Microsoft Learn
VisualStyleInformationクラス

VisualStyleInformation クラス (System.Windows.Forms.VisualStyles) | Microsoft Learn

描画の禁止

コントロールにBeginUpdate()が実装されているならば、それを呼びます。さもなくばSendMessage()でWM_SETREDRAWを通知します。 コントロールの描画を一時的に停止する - .NET Tips (VB.NET,C#...) WM_SETREDRAW メッセージ (Winuser.h) - Win32 apps | Microsoft Learn

再開後に描画されない部分があるならば、Control.Invalidate(true)として子コントロールまで無効にします。

Resize

まずUpdateBounds()からSizeChangedが呼ばれます。なお、ここで同時にClientSizeChangedも呼ばれます。

protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
...
    bool newSize = this.Width != width || this.Height != height ||
                   this.clientWidth != clientWidth || this.clientHeight != clientHeight;
...
    if (newSize) {
#if DEBUG
        Rectangle originalBounds = this.Bounds;
#endif
        OnSizeChanged(EventArgs.Empty);
        OnClientSizeChanged(EventArgs.Empty);
UpdateBounds - UpdateBounds

そして、そこからResizeが呼ばれます。

protected virtual void OnSizeChanged(EventArgs e) {
    Contract.Requires(e != null);
    OnResize(EventArgs.Empty);

    EventHandler eh = Events[EventSize] as EventHandler;
    if (eh != null) {
        eh(this,e);
    }
}
OnSizeChanged - Control.cs c# - Difference between Resize and SizeChanged events - Stack Overflow
Microsoft Learnから検索