カスタムドロップダウンボックスを作成していますが、ドロップダウンボックスの外側でマウスがクリックされたときに、それを非表示にするために登録したいと思います。コントロールの外側のクリックを検出することは可能ですか?または、含まれているフォームに何らかのメカニズムを作成し、ドロップダウンボックスが開いているときにマウスクリックを確認する必要がありますか?
ですから、ユーザーがその外側をクリックした場合にのみ閉じたいと最終的に理解しました。その場合、 Leave
event は問題なく機能するはずです...何らかの理由で、カスタムドロップダウンの外にマウスを移動するたびに閉じたいという印象を受けました。 Leave
イベントは、コントロールがフォーカスを失うたびに発生します。ユーザーが他の何かをクリックすると、クリックしたものがフォーカスを獲得するため、確実にフォーカスが失われます。
ドキュメントには、このイベントが必要に応じて制御チェーンを上下にカスケードすることも記載されています。
Enter
イベントとLeave
イベントは階層的であり、適切な制御に到達するまで親チェーンを上下にカスケードします。たとえば、2つのGroupBoxコントロールを持つフォームがあり、各GroupBoxコントロールに1つのTextBoxコントロールがあるとします。キャレットが1つのTextBoxから別のTextBoxに移動されると、TextBoxとGroupBoxに対してLeave
イベントが発生し、他のGroupBoxとTextBoxに対してEnter
イベントが発生します。
UserControlのOnLeave
メソッドをオーバーライドすることが、これを処理するための最良の方法です。
protected override void OnLeave(EventArgs e)
{
// Call the base class
base.OnLeave(e);
// When this control loses the focus, close it
this.Hide();
}
次に、テストの目的で、コマンドのドロップダウンUserControlを表示するフォームを作成しました。
public partial class Form1 : Form
{
private UserControl1 customDropDown;
public Form1()
{
InitializeComponent();
// Create the user control
customDropDown = new UserControl1();
// Add it to the form's Controls collection
Controls.Add(customDropDown);
customDropDown.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
// Display the user control
customDropDown.Show();
customDropDown.BringToFront(); // display in front of other controls
customDropDown.Select(); // make sure it gets the focus
}
}
上記のコードexceptですべてが完全に機能します。ただし、ユーザーがフォームの空白の領域をクリックしても、UserControlは閉じません。うーん、どうして?ええと、フォーム自体はフォーカスを望まないからです。 コントロールのみがフォーカスを取得でき、コントロールをクリックしませんでした。そして、他に何もフォーカスを盗んだことがないため、Leave
イベントが発生することはありませんでした。つまり、UserControlは、それ自体が閉じることになっていることを知りませんでした。
ユーザーがフォームの空白の領域をクリックしたときにUserControlを閉じる必要がある場合は、そのための特別なケース処理が必要です。 クリックだけが気になると言っているので、フォームのClick
イベントを処理して、フォーカスを設定するだけです。別のコントロールに:
protected override void OnClick(EventArgs e)
{
// Call the base class
base.OnClick(e);
// See if our custom drop-down is visible
if (customDropDown.Visible)
{
// Set the focus to a different control on the form,
// which will force the drop-down to close
this.SelectNextControl(customDropDown, true, true, true, true);
}
}
はい、この最後の部分はハックのように感じます。他の人が言及しているように、より良い解決策は、 SetCapture
function を使用して、UserControlのウィンドウ上でマウスをキャプチャするようにWindowsに指示することです。コントロールの Capture
property は、同じことを行うさらに簡単な方法を提供します。
技術的には、制御外で発生するクリックイベントを受信するには、p/invoke SetCapture() である必要があります。
しかし、あなたの場合、@ Martinが示唆するように、 Leave イベントを処理するだけで十分です。
EDIT:SetCapture()
の使用例を探しているときに、 Control.Capture プロパティに出くわしました、私は気づいていませんでした。そのプロパティを使用すると、何もp/invokeする必要がなくなります。これは、私の本では常に良いことです。
したがって、ドロップダウンを表示するときにCapture
をtrue
に設定し、マウスポインタがクリックイベントハンドラのコントロール内にあるかどうかを判断し、そうでない場合は設定する必要があります。 Capture
からfalse
に移動し、ドロップダウンを閉じます。
フォームのMouseDown
イベントを処理するか、フォームのOnMouseDown
メソッドをオーバーライドします。
enter code here
その後:
protected override void OnMouseDown(MouseEventArgs e)
{
if (!theListBox.Bounds.Contains(e.Location))
{
theListBox.Visible = false;
}
}
含むメソッドoldSystem.Drawing.Rectangle
は、点が長方形の中に含まれているかどうかを示すために使用できます。コントロールのBoundsプロパティは、コントロールのエッジによって定義される外側のRectangle
です。 MouseEventArgs
のLocationプロパティは、MouseDown
イベントを受信したコントロールに関連するポイントです。フォーム内のコントロールのBoundsプロパティは、フォームに関連しています。
あなたはおそらく休暇イベントを探しています:
http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.leave.aspx
離脱は、入力フォーカスがコントロールを離れるときに発生します。