|
|
|
|
I want to create a method that maked the scrollbars of a textbox control visible only if needed.
I tried to use the following method but it doesn't always work, because some times is the control's width much bigger than the Height (I am talking when the WordWrap is set to False):
Code Snippet Private Sub TextBox1_TextChanged(ByVal sender As TextBox, ByVal e As System.EventArgs) _ Handles TextBox1.TextChanged, TextBox1.Resize, TextBox1.FontChanged
Dim fS As Size = TextRenderer.MeasureText(sender.Text, sender.Font) Dim cS As Integer = fS.Height * fS.Width Dim dS As Integer = sender.Size.Height * sender.Size.Width If dS < cS Then sender.ScrollBars = ScrollBars.Both Else sender.ScrollBars = ScrollBars.None End If End Sub
so here is some findings about the text box's control behaviour, maybe it's gonna be useful:
these numbers just bellow (123456) charachterize th number of lines 1 2 3 4 5 6
10 6 22 38 54 70 86 16^ 11 6 24 42 60 78 96 18^ 12 6 26 46 66 86 106 20^ 13 6 28 50 72 94 126 22^ 0 2 4 6 8 10 ^the numbers in this col. are the control's increment per font against line ^this column is the textbox's font's size
the numbers within the table (6,22,38~72,94,126) are the Size.Height of the control, corresponding to font size and line numbers.
also notice that the default Hscrollbar's Height is 57.
well I don't want to waste your time, does any body have any solution?
thanks for your time.
| | | | | | Shimmy Weitzhandler Sunday, April 13, 2008 2:13 AM | Well, this did the trick for me:
VB:
| PublicClassForm1 |
|
| FriendWithEventstbAsNewTextBox |
| PrivateSubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load |
| Withtb |
| .Multiline=True |
| .Dock=DockStyle.Fill |
| .ScrollBars=ScrollBars.Both |
| .WordWrap=False |
| EndWith |
| Controls.Add(tb) |
| EndSub |
|
| PrivateSubtbScroll(ByValsenderAsTextBox,ByValeAsEventArgs)Handlestb.ClientSizeChanged,tb.TextChanged |
| StaticbusyAsBoolean |
| IfbusyThenExitSub |
| busy=True |
|
| Withsender |
| DimtS=TextRenderer.MeasureText(.Text,.Font) |
| DimHsb=.ClientSize.Height<tS.Height+.Font.Size |
| DimVsb=.ClientSize.Width<tS.Width |
|
| IfHsbAndVsbThen |
| .ScrollBars=ScrollBars.Both |
| ElseIfNotHsbAndNotVsbThen |
| .ScrollBars=ScrollBars.None |
| ElseIfHsbAndNotVsbThen |
| .ScrollBars=ScrollBars.Vertical |
| Else |
| .ScrollBars=ScrollBars.Horizontal |
| EndIf |
| EndWith |
| busy=False |
| EndSub |
|
| EndClass |
C#:
| usingSystem; |
| usingSystem.Drawing; |
| usingSystem.Windows.Forms; |
|
| namespaceWindowsFormsApplication1 |
| { |
| publicpartialclassForm1:Form |
| { |
| publicForm1() |
| { |
| InitializeComponent(); |
| TextBoxtb=newTextBox(){Multiline=true,Dock=DockStyle.Fill,ScrollBars=ScrollBars.Both,WordWrap=false}; |
| EventHandlereh=newEventHandler(tb_Changed); |
| tb.TextChanged+=eh; |
| tb.ClientSizeChanged+=eh; |
| Controls.Add(tb); |
| } |
|
| privateboolbusy=false; |
| voidtb_Changed(objectsender,EventArgse) |
| { |
| if(busy)return; |
| busy=true; |
| TextBoxtb=senderasTextBox; |
| SizetS=TextRenderer.MeasureText(tb.Text,tb.Font); |
| boolHsb=tb.ClientSize.Height<tS.Height+Convert.ToInt32(tb.Font.Size); |
| boolVsb=tb.ClientSize.Width<tS.Width; |
|
| if(Hsb&&Vsb) |
| tb.ScrollBars=ScrollBars.Both; |
| elseif(!Hsb&&!Vsb) |
| tb.ScrollBars=ScrollBars.None; |
| elseif(Hsb&&!Vsb) |
| tb.ScrollBars=ScrollBars.Vertical; |
| elseif(!Hsb&&Vsb) |
| tb.ScrollBars=ScrollBars.Horizontal; |
|
| sender=tbasobject; |
| busy=false; |
| } |
| } |
| } |
Enjoy!
- Edited byShimmy Weitzhandler Saturday, February 28, 2009 10:51 PM
- Edited byShimmy Weitzhandler Saturday, February 28, 2009 10:48 PM
-
| | Shimmy Weitzhandler Sunday, April 13, 2008 10:37 AM | Hi,
Here is another solution I wrote which counts the number of displayed lines of text and compute their height.
Then, it is easy to compare this height with the textbox's one.
Code Snippet
/// <summary>
/// Sets or unsets the scrollbars on the lblErrorMessage control upon its size and content
/// </summary>
private void SetErrorMessageScrollbars()
{
// Set or remove the error text box Vertical scrollbar
// according to the text inside:
// Count the number of required displayed lines per line of text in the "Text"
//property:
string[] lines = this.lblErrorMessage.Lines;
int nbDisplayedLines = 0;
Size textSize;
if (lines != null)
{
foreach (string line in lines)
{
textSize = TextRenderer.MeasureText(line, this.lblErrorMessage.Font);
nbDisplayedLines += ( int)(Math.Ceiling((decimal)textSize.Width / this.lblErrorMessage.Width));
}
}
// Search the height of one line:
textSize = TextRenderer.MeasureText("Lp", this.lblErrorMessage.Font);
// CAUTION: DON'T USE PreferedHeight HERE. IT DOESN'T WORK.
// CAUTION 2: PreferredSize works only if not resizing the window!
if (nbDisplayedLines * textSize.Height> this.lblErrorMessage.Size.Height)
{
// There are more text than can be displayed:
this.lblErrorMessage.ScrollBars = ScrollBars.Vertical;
}
else
{
// No much text, so remove the vertical scrollbar:
this.lblErrorMessage.ScrollBars = ScrollBars.None;
}
// Need to add a refresh on the error message text box. Sometimes,
// it doesn't refresh its content:
this.lblErrorMessage.Invalidate();
}
Hope this helps.
| | Haribo007 Wednesday, April 16, 2008 9:52 AM |
yes, but this will not work properly if the propety wrap lines is set to true
and also the previouscode works also for the horizontal scrollbar as well as you can freely resize the control.
anyway thanks for sharing us with your ideas. - Marked As Answer byShimmy Weitzhandler Saturday, February 28, 2009 10:49 PM
-
| | Shimmy Weitzhandler Wednesday, April 16, 2008 11:28 AM | Fortunately somebody else in Microsoft racked his headand created this wonderful function that does the jobthat isTextRenderer.MeasureTextfor us, so we don't need to count lines.
I updated my previous code, please take a look.
Thanks - Marked As Answer byShimmy Weitzhandler Saturday, February 28, 2009 10:50 PM
-
| | Shimmy Weitzhandler Saturday, February 28, 2009 10:12 PM | Hi,
Honestly speaking, I have never tried it out, but you can get some clues over here
http://pinvoke.net/default.aspx/user32/ShowScrollBar.html
HTH, Suprotim Agarwal
| | Suprotim Agarwal Sunday, April 13, 2008 2:22 AM | hello dear suprotim and thanks for your quick response.
what I don't understand is, since when has a PictureBox a Font property????
I am using VB.NET and not VB 6
could you help me doing it pls?
| | Shimmy Weitzhandler Sunday, April 13, 2008 2:52 AM | Well, this did the trick for me:
VB:
| PublicClassForm1 |
|
| FriendWithEventstbAsNewTextBox |
| PrivateSubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load |
| Withtb |
| .Multiline=True |
| .Dock=DockStyle.Fill |
| .ScrollBars=ScrollBars.Both |
| .WordWrap=False |
| EndWith |
| Controls.Add(tb) |
| EndSub |
|
| PrivateSubtbScroll(ByValsenderAsTextBox,ByValeAsEventArgs)Handlestb.ClientSizeChanged,tb.TextChanged |
| StaticbusyAsBoolean |
| IfbusyThenExitSub |
| busy=True |
|
| Withsender |
| DimtS=TextRenderer.MeasureText(.Text,.Font) |
| DimHsb=.ClientSize.Height<tS.Height+.Font.Size |
| DimVsb=.ClientSize.Width<tS.Width |
|
| IfHsbAndVsbThen |
| .ScrollBars=ScrollBars.Both |
| ElseIfNotHsbAndNotVsbThen |
| .ScrollBars=ScrollBars.None |
| ElseIfHsbAndNotVsbThen |
| .ScrollBars=ScrollBars.Vertical |
| Else |
| .ScrollBars=ScrollBars.Horizontal |
| EndIf |
| EndWith |
| busy=False |
| EndSub |
|
| EndClass |
C#:
| usingSystem; |
| usingSystem.Drawing; |
| usingSystem.Windows.Forms; |
|
| namespaceWindowsFormsApplication1 |
| { |
| publicpartialclassForm1:Form |
| { |
| publicForm1() |
| { |
| InitializeComponent(); |
| TextBoxtb=newTextBox(){Multiline=true,Dock=DockStyle.Fill,ScrollBars=ScrollBars.Both,WordWrap=false}; |
| EventHandlereh=newEventHandler(tb_Changed); |
| tb.TextChanged+=eh; |
| tb.ClientSizeChanged+=eh; |
| Controls.Add(tb); |
| } |
|
| privateboolbusy=false; |
| voidtb_Changed(objectsender,EventArgse) |
| { |
| if(busy)return; |
| busy=true; |
| TextBoxtb=senderasTextBox; |
| SizetS=TextRenderer.MeasureText(tb.Text,tb.Font); |
| boolHsb=tb.ClientSize.Height<tS.Height+Convert.ToInt32(tb.Font.Size); |
| boolVsb=tb.ClientSize.Width<tS.Width; |
|
| if(Hsb&&Vsb) |
| tb.ScrollBars=ScrollBars.Both; |
| elseif(!Hsb&&!Vsb) |
| tb.ScrollBars=ScrollBars.None; |
| elseif(Hsb&&!Vsb) |
| tb.ScrollBars=ScrollBars.Vertical; |
| elseif(!Hsb&&Vsb) |
| tb.ScrollBars=ScrollBars.Horizontal; |
|
| sender=tbasobject; |
| busy=false; |
| } |
| } |
| } |
Enjoy!
- Edited byShimmy Weitzhandler Saturday, February 28, 2009 10:51 PM
- Edited byShimmy Weitzhandler Saturday, February 28, 2009 10:48 PM
-
| | Shimmy Weitzhandler Sunday, April 13, 2008 10:37 AM | Hi,
Great. Thanks for sharingthe solutionacross.
HTH, Suprotim Agarwal | | Suprotim Agarwal Sunday, April 13, 2008 12:04 PM | Hi,
Here is another solution I wrote which counts the number of displayed lines of text and compute their height.
Then, it is easy to compare this height with the textbox's one.
Code Snippet
/// <summary>
/// Sets or unsets the scrollbars on the lblErrorMessage control upon its size and content
/// </summary>
private void SetErrorMessageScrollbars()
{
// Set or remove the error text box Vertical scrollbar
// according to the text inside:
// Count the number of required displayed lines per line of text in the "Text"
//property:
string[] lines = this.lblErrorMessage.Lines;
int nbDisplayedLines = 0;
Size textSize;
if (lines != null)
{
foreach (string line in lines)
{
textSize = TextRenderer.MeasureText(line, this.lblErrorMessage.Font);
nbDisplayedLines += ( int)(Math.Ceiling((decimal)textSize.Width / this.lblErrorMessage.Width));
}
}
// Search the height of one line:
textSize = TextRenderer.MeasureText("Lp", this.lblErrorMessage.Font);
// CAUTION: DON'T USE PreferedHeight HERE. IT DOESN'T WORK.
// CAUTION 2: PreferredSize works only if not resizing the window!
if (nbDisplayedLines * textSize.Height> this.lblErrorMessage.Size.Height)
{
// There are more text than can be displayed:
this.lblErrorMessage.ScrollBars = ScrollBars.Vertical;
}
else
{
// No much text, so remove the vertical scrollbar:
this.lblErrorMessage.ScrollBars = ScrollBars.None;
}
// Need to add a refresh on the error message text box. Sometimes,
// it doesn't refresh its content:
this.lblErrorMessage.Invalidate();
}
Hope this helps.
| | Haribo007 Wednesday, April 16, 2008 9:52 AM |
yes, but this will not work properly if the propety wrap lines is set to true
and also the previouscode works also for the horizontal scrollbar as well as you can freely resize the control.
anyway thanks for sharing us with your ideas. - Marked As Answer byShimmy Weitzhandler Saturday, February 28, 2009 10:49 PM
-
| | Shimmy Weitzhandler Wednesday, April 16, 2008 11:28 AM | Hi Shimmy,
can you tell me how your code works when you have a multiline textboxfor whichyou need to display a vertical scrollbar. I've looked at the code and can't see how you can get the height of the text (which would presumably be the height of the font x the number of completely visible lines displayable in the textbox).
Thanks
| | Ross Watson Monday, November 03, 2008 5:05 PM | Fortunately somebody else in Microsoft racked his headand created this wonderful function that does the jobthat isTextRenderer.MeasureTextfor us, so we don't need to count lines.
I updated my previous code, please take a look.
Thanks - Marked As Answer byShimmy Weitzhandler Saturday, February 28, 2009 10:50 PM
-
| | Shimmy Weitzhandler Saturday, February 28, 2009 10:12 PM |
|