3

私のフォーム階層は次のようなものです。

Form -> TableLayoutOne -> TableLayoutTwo -> Panel -> ListBox

ListBoxのMouseMoveイベントには、次のようなコードがあります。

    Point cursosPosition2 = PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y));
    Control crp = this.GetChildAtPoint(cursosPosition2);
    if (crp != null)
        MessageBox.Show(crp.Name);

MessageBoxには「TableLayoutOne」が表示されますが、「ListBox」が表示されると思います。私のコードのどこが間違っていますか?ありがとう。

4

2 に答える 2

9

このGetChildFromPoint()メソッドはネイティブChildWindowFromPointEx()メソッドを使用し、そのドキュメントには次のように記載されています。

指定された親ウィンドウに属する子ウィンドウのどれに指定されたポイントが含まれているかを判別します。この関数は、非表示、無効、および透過の子ウィンドウを無視できます。検索は、直接の子ウィンドウに制限されます。孫およびより深い子孫は検索されません。

太字のテキストに注意してください。メソッドは必要なものを取得できません。

GetChildFromPoint()理論的には、次のようになるまで、返されたコントロールを呼び出すことができますnull

Control crp = this.GetChildAtPoint(cursosPosition2);
Control lastCrp = crp;

while (crp != null)
{
    lastCrp = crp;
    crp = crp.GetChildAtPoint(cursorPosition2);
}

そして、あなたはそれlastCrpがその位置で最も低い子孫であったことを知っているでしょう。

于 2011-09-22T02:52:19.507 に答える
3

より良いコードは次のように書くことができます:

Public Control FindControlAtScreenPosition(Form form, Point p)
{
    if (!form.Bounds.Contains(p)) return null; //not inside the form
    Control c = form, c1 = null;
    while (c != null)
    {
        c1 = c;
        c = c.GetChildAtPoint(c.PointToClient(p), GetChildAtPointSkip.Invisible | GetChildAtPointSkip.Transparent); //,GetChildAtPointSkip.Invisible
    }
    return c1;
}

使用法は次のとおりです。

Control c = FindControlAtScreenPosition(this, Cursor.Position);
于 2018-09-26T05:54:49.547 に答える