Control.PointToScreen gives different results - why?
I have Label controls sitting on a control bar on a form. I want to get the positions of the labels relative to the start of the form so that at runtime I can hide the panel and labels and draw other text in place directly on the form.
Basically what I'm doing is the following calculation: get the absolute screen position of the label with Control.PointToScreen () and convert it back to the relative position with Control.PointToClient () so that:
Dim newloc As Point = Me.PointToClient(ctl.PointToScreen(Point.Empty))
or
Dim newloc As Point = Me.PointToClient(ctl.Parent.PointToScreen(ctl.Location))
I've found that these two methods sometimes give me different results - getting my new point out of the viewport with negative values! - but could not determine why. I would think they should be the same (and they are most of the time).
Reading the docs didn't help the first time, but maybe I missed something ... Anyway, I would appreciate any help before I start pulling out my hair.
Or on the other hand, is there a better way to do this?
Edit: sample results
So here's a real-world example.
Label1 in {X = 4, Y = 6} on Panel1; Label2 at {X = 163, Y = 6} on the same parent, Panel1. Obviously I expect different X-positions, but Y should be identical for both.
When I run the project like
ctl.PointToScreen (Point.Empty)and
ctl.Parent.PointToScreen (ctl.Location)gives me the same screen layout for Label1 at {X = 959, Y = 119} (the absolute values here can vary, of course, depending on the position of the form itself) and therefore the correct position relative to the form when Me.PointToClient is applied (with {X = 5, Y = 32}).
The closest lines do the same calculations for Label2 (remember, same Parent, same Y-value in parent (6)), but the results are completely off: ctl.Parent.PointToScreen () gives me {X = 1114, Y = 63 }. X is almost correct (959-4 + 163 = 1118), but Y is nowhere near 119 I got for Label1. And then ctl.PointToScreen () gives me {X = 166, Y = 29} - translated back to Form-Coordinates (Me.PointToClient) {X = -784, Y = -2}.
These numbers are calculated and printed in the debug window directly one after the other, without moving anything around ... Madness.
Ok, this is getting pretty messy, but I still hope someone has a simple explanation. Thanks!
a source to share
OK, I found a solution.
I happened to call Control.PointToScreen before creating the control: Control.IsHandleCreated = False.
If I make sure the control is created first (Control.CreateControl), both methods work equally well.
The reason I had different results on subsequent calls is that the first call to Control.PointToScreen also causes the control to be created (and therefore its parent and any other controls located on the parent), which means that the second succeeds.
Ok I'm glad I can handle it :-)
a source to share
I think this is a dream. :) Instead of:
ctl.PointToScreen (Point.Empty)
ctl.Parent.PointToScreen (ctl.Location)
try:
ctl.PointToScreen (Point.Empty)
ctl.PointToScreen (ctl.Location) // Note no .Parent!
and you will see the difference in x / y coordinates.
Also, try using Control.TopLevelControl or Control.FindForm () to get the most distant form when doing PointToScreen math.
a source to share