Control.PointToScreen дает разные результаты - почему?
У меня есть некоторые элементы управления Label, расположенные на элементах управления Panel в форме. Я хочу получить положение меток относительно источника формы, чтобы во время выполнения я мог скрыть панель и метки и нарисовать какой-то другой текст на их месте непосредственно в форме.
По сути, я делаю следующий расчет: получить абсолютную позицию на экране надписи с помощью Control.PointToScreen() и преобразовать ее обратно в относительную позицию с помощью Control.PointToClient(), так что либо:
Dim newloc As Point = Me.PointToClient(ctl.PointToScreen(Point.Empty))
или же
Dim newloc As Point = Me.PointToClient(ctl.Parent.PointToScreen(ctl.Location))
Я обнаружил, что эти два метода иногда дают разные результаты - помещая мою новую точку вне видимой области с отрицательными значениями! - но не смог определить почему. Я бы подумал, что они должны быть идентичными (и они, в большинстве случаев).
В первый раз чтение документов не помогло, но, возможно, я что-то пропустил... В любом случае, я был бы благодарен за любую помощь, прежде чем я начну рвать на себе волосы.
Или, с другой стороны, есть ли лучший способ сделать это?
Изменить: пример результатов
Итак, вот реальный пример.
Метка 1 на {X=4,Y=6} на Panel1; Отметьте 2 на {X=163,Y=6} на том же родительском элементе, Panel1. Очевидно, я ожидаю разные X-позиции, но Y должен быть одинаковым для обоих.
Когда я запускаю проект как
ctl.PointToScreen(Point.Empty)а также
ctl.Parent.PointToScreen(ctl.Location)дайте мне то же самое расположение экрана для Label1 в {X=959,Y=119} (абсолютные значения здесь могут варьироваться, конечно, в зависимости от положения самой формы) и, следовательно, правильное расположение относительно формы при Me.PointToClient применяется (при {X=5,Y=32}).
В следующих строках выполняются те же вычисления для Label2 (помните, тот же Parent, то же значение Y в родительском элементе (6)), но результаты полностью отключены: ctl.Parent.PointToScreen() дает мне {X=1114,Y=63}. X почти правильный (959-4+163=1118), но Y далеко не тот 119, который я получил для Label1. И тогда ctl.PointToScreen() дает мне {X=166,Y=29} - переведенный обратно в координаты формы (Me.PointToClient) {X=-784,Y=-2}.
Эти числа рассчитываются и печатаются в окне отладки непосредственно друг за другом, ничего не перемещая... Безумие.
Хорошо, это становится довольно грязным, но я все еще надеюсь, что у кого-то есть простое объяснение. Спасибо!
2 ответа
ОК, я нашел решение.
Я случайно вызвал Control.PointToScreen до того, как был создан элемент управления: Control.IsHandleCreated = False.
Если я гарантирую, что сначала создается элемент управления (Control.CreateControl), оба метода работают одинаково хорошо.
Причина, по которой у меня были разные результаты при последующих вызовах, заключается в том, что первый вызов Control.PointToScreen также вызывает создание элемента управления (и, следовательно, его родительского элемента и любых других элементов управления, расположенных на родительском элементе), что означает, что второй выполняется успешно.
Что ж, я рад, что с этим покончено:-)
Я думаю, что это сон.:) Вместо:
ctl.PointToScreen (Point.Empty)
ctl.Parent.PointToScreen (ctl.Location)
пытаться:
ctl.PointToScreen (Point.Empty)
ctl.PointToScreen (ctl.Location) // Примечание нет. Родитель!
вместо этого, и вы увидите разницу в координатах х / у.
Кроме того, попробуйте использовать Control.TopLevelControl или Control.FindForm(), чтобы получить крайнюю форму при выполнении математики PointToScreen.