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.

Другие вопросы по тегам