Метод GetChildAtPoint возвращает неправильный элемент управления - PullRequest
3 голосов
/ 22 сентября 2011

Моя иерархия форм выглядит примерно так:

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

В событии MouseMove ListBox у меня есть такой код:

    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 ".Где в моем коде я иду не так?Спасибо.

Ответы [ 2 ]

7 голосов
/ 22 сентября 2011

Метод GetChildFromPoint() использует собственный метод ChildWindowFromPointEx(), документация которого гласит:

Определяет, какие из дочерних окон, принадлежащих указанное родительское окно содержит указанную точку. Функция может игнорировать невидимые, отключенные и прозрачные дочерние окна. Поиск ограничено непосредственными дочерними окнами. Внуки и глубже потомки не разыскиваются.

Обратите внимание на жирный текст: метод не может получить то, что вы хотите.

Теоретически вы можете вызывать GetChildFromPoint() для возвращенного элемента управления, пока не получите null:

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

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

И тогда вы узнаете, что lastCrp был самым низким потомком в этой позиции.

1 голос
/ 26 сентября 2018

лучший код можно записать следующим образом:

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);
...