trouble calculating control location when using scroll bars

A

Angelo

VS Version: 2008
..Net Version: 3.5 sp1

Hello,

I have just started using scroll bars in a user control (called
DisplayCtrl) and it seems that the Location property for any .Net
Control (e.g TextBox) that I place in my DisplayCtrl references the
upper-left corner for the encapsulating dialog, but *not* the
DisplayCtrl that it was placed in. So, to calculate the TextBox
Location inside the DisplayCtrl, I must add the Location with the
corresponding scroll positions of the DisplayCtrl.

Is it possible to get the TextBox Location in terms of the upper-left
of my DisplayCtrl if I only have a reference to the TextBox (and not
the DisplayCtrl)?


I hope I am begin clear enough on what is going on and what I am
looking to do.
If more details are needed, I would be happy to share.

Thanks
AJ
 
B

Ben Voigt [C++ MVP]

Angelo said:
VS Version: 2008
.Net Version: 3.5 sp1

Hello,

I have just started using scroll bars in a user control (called
DisplayCtrl) and it seems that the Location property for any .Net
Control (e.g TextBox) that I place in my DisplayCtrl references the
upper-left corner for the encapsulating dialog, but *not* the
DisplayCtrl that it was placed in. So, to calculate the TextBox
Location inside the DisplayCtrl, I must add the Location with the
corresponding scroll positions of the DisplayCtrl.

Is it possible to get the TextBox Location in terms of the upper-left
of my DisplayCtrl if I only have a reference to the TextBox (and not
the DisplayCtrl)?


I hope I am begin clear enough on what is going on and what I am
looking to do.
If more details are needed, I would be happy to share.

what is the Parent of the TextBox?

Did you add the TextBox in the designer of the UserControl, or in the
designer of a Form containing an instance of the UserControl?
 
A

Angelo

The TextBox gets placed into the Controls Collection of the
UserControl. This is done at runtime (not in the designer).


Do I need to manually set the parent for the TextBox? Currently, I am
not.

AJ
 
B

Ben Voigt [C++ MVP]

Angelo said:
The TextBox gets placed into the Controls Collection of the
UserControl. This is done at runtime (not in the designer).

Ok, the designer just generates that same sort of code. But with the
designer, it'd be easy to place it "over" the UserControl instead of
contained within.
Do I need to manually set the parent for the TextBox? Currently, I am
not.

You don't need to manually set the Parent, I just was suggesting that you
check the actual value in the debugger to make sure that it actually it the
UserControl you think it is.

Did you write this UserControl? Are there any shenanigans with the Controls
property (i.e. is it inherited from UserControl or some custom property
implementation)? If you're not the author, you may need to use .NET
Reflector (now distributed by Red Gate) to see, but checking the Parent
property ought to show you whether there's a problem you need to look deeper
into.
 
A

Angelo

I wrote the DispalyControl, and the only thing that I did slightly
different was I inherit from a Viewbase class which inherits from
UserControl. The Viewbase class adds a few properties but does
nothing to the internals of the DisplayControl. I do not believe this
is the problem.

Let me go over the process in a little bit more detail:

-When the application is executing, the user selects to add a textbox
from a contextmenu inside the DisplayControl.
-Next, the user selects the font / size of the control.
-When finished, the DisplayControl adds the textbox into it's control
list.

I must point out that when the DisplayControl area becomes larger than
the dialog containing it, scrollbars appear in the corners of the
DisplayControl, and the controls contained inside the DisplayControl
scroll correctly. However, when I look at the location of the
controls, they show the location with respect to the upper-left corner
of the DisplayControl, but it does not take the scroll-bars into
account.

example: I have a TextBox which contains Location of 100,100 and the
AutoScrollPosition is 100, 100. To calculate the actual TextBox
Location, I need to add the AutoScrollPosition to the TextBox
Location. My question being: is this working as intended or is this a
bug somewhere in my code?


Thanks for your help
AJ
 
B

Ben Voigt [C++ MVP]

Angelo said:
I wrote the DispalyControl, and the only thing that I did slightly
different was I inherit from a Viewbase class which inherits from
UserControl. The Viewbase class adds a few properties but does
nothing to the internals of the DisplayControl. I do not believe this
is the problem.

Let me go over the process in a little bit more detail:

-When the application is executing, the user selects to add a textbox
from a contextmenu inside the DisplayControl.
-Next, the user selects the font / size of the control.
-When finished, the DisplayControl adds the textbox into it's control
list.

I must point out that when the DisplayControl area becomes larger than
the dialog containing it, scrollbars appear in the corners of the
DisplayControl, and the controls contained inside the DisplayControl
scroll correctly. However, when I look at the location of the
controls, they show the location with respect to the upper-left corner
of the DisplayControl, but it does not take the scroll-bars into
account.

example: I have a TextBox which contains Location of 100,100 and the
AutoScrollPosition is 100, 100. To calculate the actual TextBox
Location, I need to add the AutoScrollPosition to the TextBox
Location. My question being: is this working as intended or is this a
bug somewhere in my code?

I dunno, haven't used auto-scrolling all that much. But I may have a way to
fix it. May I suggest an intermediate Panel? Then the Panel will move
inside the DisplayControl, and the child controls will never move relative
to the Panel.
 
A

Angelo

I don't quite understand what you mean by intermediate Panel. Could
you elaborate?

Thanks
AJ
 
A

Angelo

I don't quite understand what you mean by intermediate Panel. Could
you elaborate?

Thanks
AJ
 
B

Ben Voigt [C++ MVP]

Put a Panel in the ScrollableContainer.

Add your TextBox to the Panel.Control collection. Then the Panel itself
will move back and forth as you scroll, but the TextBox will never move
relative to the Panel, so the Location property will be correct.
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
It would be helpful if you could be more explicit about what you're
seeing. In your original post, you write "it seems that the Location
property for any .Net Control (e.g TextBox) that I place in my DisplayCtrl
references the upper-left corner for the encapsulating dialog, but *not*
the DisplayCtrl that it was placed in". In the above post, you write
"they show the location with respect to the upper-left corner of the
DisplayControl" (where I assume by "upper-left corner", you mean the
visible upper-left corner, not the virtual upper-left corner).

In fact, the Location property for each control should be relative to the
origin of the container containing the control. If this isn't what you're
seeing, we need to resolve that discrepancy first.

Now, the origin of the container is affected by scroll position. So you
will indeed see different values for the Location property depending on
the scroll bar position, and this is by design (not a great design IMHO,
but that's the way .NET Forms works).

One approach is to adjust the Location values according to the scroll bar
positions. Another is the suggestion Ben offered. Note that if you do
that, the result is subtly different from simply adjusting according to
the scroll bar positions.

In particular, the natural idea would be to make a Panel the same width as
the UserControl. But if and when the vertical scroll bar appears, this
obscures part of the Panel, causing the horizontal scroll bar to appear as
well. On the other hand, if you make the Panel the width of the
UserControl minus the width needed for the scroll bar (or narrower), then
contents of the Panel could be clipped unless you have the Panel's
AutoSize property set to "true".

This (setting AutoSize to "true") is the most convenient way to use the
Panel anyway, so IMHO is a nice way to solve the issue. Just set the
Panel to the minimum size required, and let it expand as items are added
to it. As the Panel expands, the UserControl containing it will show
scroll bars as appropriate, but the items within the Panel will still have
their locations unchanged, because they are relative to the Panel, not the
UserControl.

In particular, the Panel's Location will be -DisplayCtrl.AutoScrollPosition,
the Panel never has scrollbars, so it's AutoScrollPosition = (0,0) always,
and the Location of each child Control is as expected.
 
A

Angelo

It would be helpful if you could be more explicit about what you're  
seeing.  In your original post, you write "it seems that the Location  
property for any .Net Control (e.g TextBox) that I place in my DisplayCtrl  
references the upper-left corner for the encapsulating dialog, but *not*  
the DisplayCtrl that it was placed in".  In the above post, you write  
"they show the location with respect to the upper-left corner of the  
DisplayControl" (where I assume by "upper-left corner", you mean the  
visible upper-left corner, not the virtual upper-left corner).

In fact, the Location property for each control should be relative to the
origin of the container containing the control. If this isn't what you're
seeing, we need to resolve that discrepancy first.



I spoke incorrectly the first time: a .Net Control references the
upper-left corner of the DisplayCtrl.


Now, the origin of the container is affected by scroll position.  So you  
will indeed see different values for the Location property depending on  
the scroll bar position, and this is by design (not a great design IMHO,  
but that's the way .NET Forms works).


This makes sense and I wanted to verify it was working as intended. I
initially noticed this when I added code to save the control positions
on disk. The location would change depending on the scroll bar
position.


One approach is to adjust the Location values according to the scroll bar 
positions.  Another is the suggestion Ben offered. Note that if you do  
that, the result is subtly different from simply adjusting according to  
the scroll bar positions.

In particular, the natural idea would be to make a Panel the same width as  
the UserControl.  But if and when the vertical scroll bar appears, this 
obscures part of the Panel, causing the horizontal scroll bar to appear as  
well.  On the other hand, if you make the Panel the width of the  
UserControl minus the width needed for the scroll bar (or narrower), then 
contents of the Panel could be clipped unless you have the Panel's  
AutoSize property set to "true".

This (setting AutoSize to "true") is the most convenient way to use the  
Panel anyway, so IMHO is a nice way to solve the issue.  Just set the  
Panel to the minimum size required, and let it expand as items are added  
to it.  As the Panel expands, the UserControl containing it will show  
scroll bars as appropriate, but the items within the Panel will still have  
their locations unchanged, because they are relative to the Panel, not the  
UserControl.

If between Ben's advice and the above, you still are unable to get things 
to work the way you want, you should post a concise-but-complete code  
example that reliably demonstrates what you've got, along with a  
description of how to use the program, what the program does, and why  
that's different from what you want.

Pete


I am looking to get the Control's Location without having to adjust it
with respect to scroll bar position, so I believe Ben's solution will
work well. I think I have enough information to implement and will
start doing so. If I have any problems, I will let you know.


Thanks a lot for your help
AJ
 
A

Angelo

It would be helpful if you could be more explicit about what you're  
seeing.  In your original post, you write "it seems that the Location  
property for any .Net Control (e.g TextBox) that I place in my DisplayCtrl  
references the upper-left corner for the encapsulating dialog, but *not*  
the DisplayCtrl that it was placed in".  In the above post, you write  
"they show the location with respect to the upper-left corner of the  
DisplayControl" (where I assume by "upper-left corner", you mean the  
visible upper-left corner, not the virtual upper-left corner).

In fact, the Location property for each control should be relative to the
origin of the container containing the control. If this isn't what you're
seeing, we need to resolve that discrepancy first.



I spoke incorrectly the first time: a .Net Control references the
upper-left corner of the DisplayCtrl.


Now, the origin of the container is affected by scroll position.  So you  
will indeed see different values for the Location property depending on  
the scroll bar position, and this is by design (not a great design IMHO,  
but that's the way .NET Forms works).


This makes sense and I wanted to verify it was working as intended. I
initially noticed this when I added code to save the control positions
on disk. The location would change depending on the scroll bar
position.


One approach is to adjust the Location values according to the scroll bar 
positions.  Another is the suggestion Ben offered. Note that if you do  
that, the result is subtly different from simply adjusting according to  
the scroll bar positions.

In particular, the natural idea would be to make a Panel the same width as  
the UserControl.  But if and when the vertical scroll bar appears, this 
obscures part of the Panel, causing the horizontal scroll bar to appear as  
well.  On the other hand, if you make the Panel the width of the  
UserControl minus the width needed for the scroll bar (or narrower), then 
contents of the Panel could be clipped unless you have the Panel's  
AutoSize property set to "true".

This (setting AutoSize to "true") is the most convenient way to use the  
Panel anyway, so IMHO is a nice way to solve the issue.  Just set the  
Panel to the minimum size required, and let it expand as items are added  
to it.  As the Panel expands, the UserControl containing it will show  
scroll bars as appropriate, but the items within the Panel will still have  
their locations unchanged, because they are relative to the Panel, not the  
UserControl.

If between Ben's advice and the above, you still are unable to get things 
to work the way you want, you should post a concise-but-complete code  
example that reliably demonstrates what you've got, along with a  
description of how to use the program, what the program does, and why  
that's different from what you want.

Pete


I am looking to get the Control's Location without having to adjust it
with respect to scroll bar position, so I believe Ben's solution will
work well. I think I have enough information to implement and will
start doing so. If I have any problems, I will let you know.


Thanks a lot for your help
AJ
 
A

Angelo

It would be helpful if you could be more explicit about what you're  
seeing.  In your original post, you write "it seems that the Location  
property for any .Net Control (e.g TextBox) that I place in my DisplayCtrl  
references the upper-left corner for the encapsulating dialog, but *not*  
the DisplayCtrl that it was placed in".  In the above post, you write  
"they show the location with respect to the upper-left corner of the  
DisplayControl" (where I assume by "upper-left corner", you mean the  
visible upper-left corner, not the virtual upper-left corner).

In fact, the Location property for each control should be relative to the
origin of the container containing the control. If this isn't what you're
seeing, we need to resolve that discrepancy first.



I spoke incorrectly the first time: a .Net Control references the
upper-left corner of the DisplayCtrl.


Now, the origin of the container is affected by scroll position.  So you  
will indeed see different values for the Location property depending on  
the scroll bar position, and this is by design (not a great design IMHO,  
but that's the way .NET Forms works).


This makes sense and I wanted to verify it was working as intended. I
initially noticed this when I added code to save the control positions
on disk. The location would change depending on the scroll bar
position.


One approach is to adjust the Location values according to the scroll bar 
positions.  Another is the suggestion Ben offered. Note that if you do  
that, the result is subtly different from simply adjusting according to  
the scroll bar positions.

In particular, the natural idea would be to make a Panel the same width as  
the UserControl.  But if and when the vertical scroll bar appears, this 
obscures part of the Panel, causing the horizontal scroll bar to appear as  
well.  On the other hand, if you make the Panel the width of the  
UserControl minus the width needed for the scroll bar (or narrower), then 
contents of the Panel could be clipped unless you have the Panel's  
AutoSize property set to "true".

This (setting AutoSize to "true") is the most convenient way to use the  
Panel anyway, so IMHO is a nice way to solve the issue.  Just set the  
Panel to the minimum size required, and let it expand as items are added  
to it.  As the Panel expands, the UserControl containing it will show  
scroll bars as appropriate, but the items within the Panel will still have  
their locations unchanged, because they are relative to the Panel, not the  
UserControl.

If between Ben's advice and the above, you still are unable to get things 
to work the way you want, you should post a concise-but-complete code  
example that reliably demonstrates what you've got, along with a  
description of how to use the program, what the program does, and why  
that's different from what you want.

Pete


I am looking to get the Control's Location without having to adjust it
with respect to scroll bar position, so I believe Ben's solution will
work well. I think I have enough information to implement and will
start doing so. If I have any problems, I will let you know.


Thanks a lot for your help
AJ
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top