Setting Width of Textbox according to maxlenth - c#

I am using winforms application and i want to set that width of textbox which will show characters till max length,in short something like width = maxlength.Any predefined property is there? or we have to calculate it manually?
//I am looking for this type of logic
private void Form1_Load(object sender, EventArgs e)
{
//sample project
textBox2.Width = textBox2.MaxLength;
textBox3.Width = textBox3.MaxLength;
textBox4.Width = textBox4.MaxLength;
}

You have a Unit Mismatch: Width is in Pixels, MaxLength in characters.
So you need to measure the Font using e.g. Graphics.MeasureString.. Works best for fixed Fonts like Consolas.
You can measure the font e.g. like this, using 'x' as a medium width letter:
using (Graphics G = textBox2.CreateGraphics())
textBox2.Width = (int) (textBox2.MaxLength *
G.MeasureString("x", textBox2.Font).Width);
There are other Font measurement methods like TextRenderer.MeasureText you could use; also both methods have options to fine tune the measurement. The default above will include some leeway.
If you use a fixed Font the width will be OK, if you don't you'll need to decide whether you'd rather be on the safe side (use "W" or "M" to measure) or not. "X" is a likely compromise. Or you could adapt dynamically in the e.g. the TextChanged event..

Use the Anchor property to define how a control is automatically resized as its parent control is resized
Anchoring a control to its parent control ensures that the anchored edges remain in the same position relative to the edges of the parent control when the parent control is resized.

Try this:
textbox1.MaxLength = 0//The default value is 0, which indicates no limit;
Refer this msdn link for more info:
msdn link for textbox maxlength

Related

Render numbers for tick on a WPF Slider using TextBox

There have been several earlier questions related to adding number values to the ticks on a WPF Slider (e.g. here and here). All proposed solutions I have found so far are to do with inheriting from the TickBar class and then using DrawText(FormattedText text, Point point) to draw the value. Something like:
protected override void OnRender(DrawingContext dc)
{
foreach(double tick in Ticks)
{
formattedText = new FormattedText(Convert.ToString(tick),
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface("Verdana"), // I don't know why all examples use the Verdana font :P
10, Brushes.Black);
dc.DrawText(formattedText, ComputeTheRightPosition(tick));
}
}
While this is a valid solution, I am finding that it is not generic enough for me, due to the FormattedText. In my application, the Style can change at runtime, so I would prefer a way of putting all the numbers in a TextBlock or something, which can dynamically update its style and font and all.
Is it possible to add text boxes in this way in anSlider or TickBar subclass?
Out of the box solution -
Put a canvas above the slider. When slider value changes, get a ratio of value / (max-min)
Use the same ratio to place the textblock in the canvas using SetLeft or Render Transform.

How to determine the proper maximum value for scrollbar c# .NET (how does windows do it?)

Before I go into my question, let me explain my setup:
First: I have a PictureBox that holds a Bitmap which is generated at runtime. This Bitmap can be different widths but always the same height.
Second: PictureBoxes do not support scrolling, therefore, I have the PictureBox docked in a panel. Initially, I had used the panel's autoscroll feature, but abandoned that after I discovered through this article that PictureBoxes have a size limit. I also learned that it's better to instead have small PictureBoxes and only draw what needs to be seen instead of the whole image.
Third: So I added a HScrollBar, which is fine and dandy, but I can't seem to figure out the math behind how big to make the scroller. I tried setting the maximum of the scrollbar to the length of the bitmap, but as you can see the size of the scroller is much smaller in mine than the one Windows puts in if I use the autoscroll feature.
My question is, what is the math behind the scroller size and how do I emulate that in my custom scrollbar?
Let me know if my question is unclear and I will try my best to make it more understandable. And thanks in advance for your help!
I figured out what was the problem. Perhaps I should have tried a little longer. :)
The answer lies in the LargeChange property. I let the Maximum at the total width of the bitmap and then set the LargeChange to the width of what I wanted to show. (i.e. the width of the PictureBox)
The size of the "scroller" is determined by the ratio of the value of LargeChange to the value of Maximum. For example, if the width to show (LargeChange) is 100 and the total width (Maximum) is 300 then the "scroller" size will be 1/3 of the scrollbar length. (100/300).
I got same problem too and tried to figure it out, I have a panel which contain another panel inside it called panelChild, and the default scrollbar is small, I need lager scrollbar, so I use HScrollBar to do that (display over-top of default scrollbar), I post my solution here, may be it helpful to someone
public Form() {
InitializeComponent();
hScrollBar.Maximum = panelChild.Width;
hScrollBar.LargeChange = panel.Width; // panel which contain panelChild, and this hScrollBar will same as panel scrollbar
hScrollBar.Scroll += HScrollBar_Scroll;
}
private void HScrollBar_Scroll(object sender, ScrollEventArgs e)
{
int diference = e.OldValue - e.NewValue;
foreach (Control c in panel.Controls)
{
c.Location = new Point(c.Location.X + diference, c.Location.Y);
}
}

How to use MeasureString in C# to set table column width?

I have a pretty quick (and I'm hoping basic) question. I'm modifying some C# code for my company's website. The code draws a table for me in fixed columns, the data for which is pulled from a database. The height of the each column of the table is fixed (currently), and I need to change it so if the string is a certain length, and therefore wraps, the second line of text is viewable (instead of hidden by the next row).
From my research, it seems like I can use MeasureString (since I know the font and string) to see if the string is longer/wider than my set table column, and change the height of the row if this is so. However, I'm very new to C# programming (and haven't done much programming overall in years, besides web stuff), so I'm not sure how to get all of this implemented. I have the logic in place, and I know how to change the height, I just need to know how to get an actual number I can use logic against using the MeasureString method (and how to instantiate any variables and functions I might need to use that method).
I believe you need to use this overload for MeasureString(string,font,int):
The width parameter specifies the maximum value of the width component
of the returned SizeF structure (Width). If the width parameter is
less than the actual width of the string, the returned Width component
is truncated to a value representing the maximum number of characters
that will fit within the specified width. To accommodate the entire
string, the returned Height component is adjusted to a value that
allows displaying the string with character wrap.
-- From Above Linked MSDN Page (Emphasis mine)
// Measure string (you'll need to instansiate your own graphics object,
// since you wont have PaintEventArgs)
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont, stringWidth);
int cellHeight = stringSize.Height;
You can either use e.Graphics.MeasureString() or TextRenderer.MeasureText()
Differences and advantages of each of them are describe here:
TextRenderer.MeasureText and Graphics.MeasureString mismatch in size
There you will also find usage examples, which I would skip here to avoid duplication.
MSDN gives an example where you calculate this by registering an event handler to the OnPaint method of your control (in instantiated controls), or by overriding the OnPaint method (in inherited controls), or by overriding the OnPaint method of your form (not best practice since you probably don't want to do this for EVERY form repaint). The OnPaint method will give you access to a graphics object so you can call the MeasureString method.
Consider the following:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
label1.Paint += new PaintEventHandler(label1_Paint);
}
void label1_Paint(object sender, PaintEventArgs e)
{
SizeF size = e.Graphics.MeasureString(label1.Text, label1.Font);
this.label1.Width = (int)size.Width;
this.label1.Height = (int)size.Height;
}
}

FlowLayoutPanel autowrapping doesn't work with autosize

.NET Framework / C# / Windows Forms
I'd like the FlowLayoutPanel to automatically adjust its width or height depending on number of controls inside of it. It also should change the number of columns/rows if there is not enough space (wrap its content). The problem is that if I set autosize then the flowlayoutpanel doesn't wrap controls I insert. Which solution is the best?
Thanks!
Set the FlowLayoutPanel's MaximumSize to the width you want it to wrap at. Set WrapContents = true.
Have you tried using the TableLayoutPanel? It's very useful for placing controls within cells.
There is no such thing like impossible in software development. Impossible just takes longer.
I've investigated the problem. If there is really need for Flow Layout, it can be done with a bit of work. Since FlowLayoutPanel lays out the controls without particularly thinking about the number of rows/columns, but rather on cumulative width/height, you may need to keep track of how many controls you've already added. First of all, set the autosize to false, then hook your own size management logic to the ControlAdded/ControlRemoved events. The idea is to set the width and height of the panel in such a way, that you'll get your desired number of 'columns' there
Dirty proof of concept:
private void flowLayoutPanel1_ControlAdded(object sender, ControlEventArgs e)
{
int count = this.flowLayoutPanel1.Controls.Count;
if (count % 4 == 0)
{
this.flowLayoutPanel1.Height = this.flowLayoutPanel1.Height + 70;
}
}
if the panel has initially width for 4 controls, it will generate row for new ones. ControlRemoved handler should check the same and decrease the panel height, or get all contained controls and place them again. You should think about it, it may not be the kind of thing you want. It depends on the usage scenarios. Will all the controls be of the same size? If not, you'd need more complicated logic.
But really, think about table layout - you can wrap it in a helper class or derive new control from it, where you'd resolve all the control placing logic. FlowLayout makes it easy to add and remove controls, but then the size management code goes in. TableLayout gives you a good mechanism for rows and columns, managing width and height is easier, but you'd need more code to change the placement of all controls if you want to remove one from the form dynamically.
If possible, I suggest you re-size the FlowLayoutPanel so that it makes use of all the width that is available and then anchor it at Top, Left and Right. This should make it grow in height as needed while still wrapping the controls.
I know this is an old thread but if anyone else wonders on here then here's the solution I produced - set autosize to true on the panel and call this extension method from the flow panel's Resize event:
public static void ReOrganise(this FlowLayoutPanel panel)
{
var width = 0;
Control prevChildCtrl = null;
panel.SuspendLayout();
//Clear flow breaks
foreach (Control childCtrl in panel.Controls)
{
panel.SetFlowBreak(childCtrl, false);
}
foreach (Control childCtrl in panel.Controls)
{
width = width + childCtrl.Width;
if(width > panel.Width && prevChildCtrl != null)
{
panel.SetFlowBreak(prevChildCtrl, true);
width = childCtrl.Width;
}
prevChildCtrl = childCtrl;
}
panel.ResumeLayout();
}
Are you adding the controls dynamically basing on the user's actions? I'm afraid you'd need to change the FlowLayout properties on the fly in code, when adding new controls to it, then refreshing the form would do the trick.

C# Printing Inconsistent

I have a form on which I have a number of textboxes. I wish to print the text from these textboxes in the locations they are on the form. It is printing at the moment using the code below. However, the text prints differently on different printers (on some it prints just right, on some too high, etc). It is being printed on a pre-printed form with spaces for the text so it needs to be fairly exact. What am I missing to make it print the same on every printer?
public void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Panel curPanel = this.FormPanel;
Graphics g = (Graphics)e.Graphics;
Pen aPen = new Pen(Brushes.Black, 1);
// Cycle through each control. Determine if it's a checkbox or a textbox and draw the information inside
// in the correct position on the form
int xLocation, yLocation;
for (int j = 0; j < curPanel.Controls.Count; j++)
{
// Check if its a TextBox type by comparing to the type of one of the textboxes
if (curPanel.Controls[j] is TextBox)
{
// Unbox the Textbox
TextBox theText = (TextBox)curPanel.Controls[j];
// Draw the textbox string at the position of the textbox on the form, scaled to the print page
xLocation = theText.Bounds.Left;
yLocation = theText.Bounds.Top;
g.DrawString(theText.Text, theText.Font, Brushes.Black, xLocation, yLocation);
}
}
}
The problem is that you ignoring how the text is aligned inside the control. Default alignment is roughly equal to StringFormat.Alignment = StringAlignment.Center, it can be changed for buttons and check boxes with their TextAlign property. You'll need to use the DrawString() overload that takes a Rectangle and a StringFormat. Note that TextBox is tricky, you might still be off by a few pixels.
Take a look at Control.DrawToBitmap() for a completely different approach.
I'm wondering if maybe the problem is discrepencies in how different printers pull in the paper. The text is off by a maximum of half an inch between printers. I was hoping this wasn't the case because if so I will just have to tailor my application to the client's particular printer (not ideal). Has anyone else run into this situation?
This is most likely a combination of two things:
You need to explicitly set up the page margins/boundaries. Various printers will have default margin and page size settings. Use a PageSetupDialog to help you out. If you want consistent printing, you can make the margins constant, but page size should be the responsibility of the user (and then check to make sure your margins actually fit on the page!).
The text needs to be placed on the page in relation to the page boundaries. I know your comment says that it will be, but it doesn't look like that it is actually implemented in your code. Setting the OriginAtMargins (on your PrintDocument control) to true helps immensely with this.

Categories