C# AutoScaleMode Font, Bold controls don't scale - c#

I'm developing a small application. I'm trying to use AutoScaleMode = Font and it works like a charm for all my intentions except one, I want some specific controls to have bold text, but then, they don't autoscale when the font size is changed.
Is it possible to change the default font of a control but still AutoScale as the rest of the controls?
Thanks in advance

You are probably using font scaling to do a job it was not intended to do. It was designed to compensate for a different video DPI on the target machine. And yes, you can also use it to rescale your Form by changing the form's Font property. But then you'll run into trouble with controls that don't "inherit" their Parent's font. You have to update their Font property yourself.
Doing this automatically requires iterating the controls inside-out, updating only those that don't inherit their parent's font. This worked well:
public static void ScaleFonts(Control ctl, float multiplier) {
foreach (Control c in ctl.Controls) ScaleFonts(c, multiplier);
if (ctl.Parent == null || ctl.Parent.Font != ctl.Font) {
ctl.Font = new Font(ctl.Font.FontFamily,
ctl.Font.Size * multiplier, ctl.Font.Style);
}
}
Sample usage:
private void Form1_Load(object sender, EventArgs e) {
ScaleFonts(this, 1.25f);
}
A possible failure-mode is triggering layout events while doing this, getting the layout messed up. That's hard to reason through, you may need to call Suspend/ResumeLayout() to fix this.

Related

Setting Width of Textbox according to maxlenth

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

Prevent combobox from resizing on font change

I have a combo box that has a list of font families in it. As you can guess I'm making a toolstrip for editing fonts in a rich text box control. The problem is when I change fonts it's resizing my combobox.
scrolling through different fonts causes the combo box to become "jumpy" and some fonts have a huge height which is causing for some hilarious problems.
Exhibit A:
Exhibit B:
Yeh... I'll show the code that I have so far... by the way the combobox is just bound to the font families collection.
void box_SelectedIndexChanged(object sender, EventArgs e)
{
String text = ((Font)box.SelectedItem).Name;
Font font = (Font)box.SelectedItem;
BeginInvoke(new Action(() => box.Text = text));
BeginInvoke(new Action(() => box.Font = font));
}
Anyone have any ideas, if I can't find a solution I can just stop the font from changing and just display the name in the default font.
Using a ToolStripComboBox is the problem here I think. The .NET 2.0 ToolItem classes have a lot of residual, erm, features that never got addressed. WPF sucked the resources away. The tool strip is obviously not handling the resize very well. Nor does it make the rest of the form move down when it gets bigger which is by design.
The canonical font combobox uses owner draw to display the fonts in the dropdown list in their regular style. Without changing the font of the box itself. You really don't want the toolstrip to resize, that's just not a great UI.
The only way I can think of doing it is by creating a custom combobox control and deriving from said control. This will give you access to the variable ownerdraw which gives us a little more flexibility without having to mess around with the ItemHeight property. Hooking into one of the events, which dictate that the value of the control has changed.
You could then have a function like the following to calculate the new layout size:
using (Font font = new Font(this.Font.FontFamily, (float)this.PreviewFontSize))
{
Size textSize;
textSize = TextRenderer.MeasureText("yY", font);
_itemHeight = textSize.Height + 2;
}
I tried all these approaches with little success sadly. However I didn't realize it until today when I looked at how microsoft office implements it. They actually use the same font in the combo box for the selected item no matter what font is selected. So as much as I want to make it more custom I'm just going to use a uniform font for whatever font is shown in the selected index.

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# Application wide color management

im on to write a large C# Application.
The point is that the colors of the controls should be adjustable by the user of the application.
It would be really nice if there are any solution to override(only for the context of this application) the System.Drawing.SystemColors, so that i do not have to set the value of every single control by hand.
Do anybody know an solution for my problem which is that simple?
Thanks
Look at Application Setting bindings. Not sure how you would do this for all controls, but simply recursing through the control tree should be sufficient.
I think your best approach would be to inherit each control and set its default display properties. This would give you a library of the standard WinForms controls that you could easily customize and re-use. More information here (in VB, I couldn't find examples in C#).
You shouldn't need to override the system defaults but you are able to define your own colours.
Color NastyColour = Color.FromArgb(1, 2, 3);
1 = Red
2 = Green
3 = Blue
Unfortunately it's not possible to modify the Windows colour scheme just for your application.
Winforms makes it possible to change things like the background colour for all controls on a form, but for many areas (such as the bevel colours on buttons, or window title bars), you'll probably need to resort to painting the control yourself.
I wrote the code below to do something like this. I'm not particularly happy with it as it needs specialized handling for any controls that are out of the ordinary, but it did the job. I keep an instance of Painter around, and call Apply every time I create a form, passing the form as the argument. It recurses through all the child controls, altering their appearance
public class Painter
{
Color foreColor;
Color backColor;
Color altBackColor;
Color buttonColor;
Font font;
public Painter(Color foreColor, Color backColor, Color altBackColor, Color buttonColor, Font font)
{
this.foreColor=foreColor;
this.backColor=backColor;
this.altBackColor=altBackColor;
this.buttonColor=buttonColor;
this.font=font;
}
public void Apply(Control c)
{
if(c==null)
return;
c.ForeColor = foreColor;
c.BackColor = (c is Button ) ? buttonColor
: backColor;
if (c is DataGridView)
{
var dgv = (DataGridView) c;
dgv.BackgroundColor = BackColor;
dgv.AlternatingRowsDefaultCellStyle.BackColor = altBackColor;
dgv.ColumnHeadersDefaultCellStyle.BackColor = buttonColor;
}
c.Font = font;
foreach(Control child in c.Controls)
Apply(child);
}
}
Spend $1000 and get a copy of DevExpress. We're writing a large application using their framework, and the skinning ability is great.
I know this doesn't sound like the best answer, but if you're looking for application wide skinning ability, a third-party library may be appropriate.

Strange .NET ListView behaviour

I'm trying to get my head around this behaviour: I have a ListView on a form in LargeIcon View (System.Windows.Forms.View.LargeIcon)
This line is in the constructor:
this.listView1.LargeImageList.ImageSize = new Size(32, 32);
And then this function is called upon a double click:
private void listView1_DoubleClick(object sender, EventArgs e)
{
this.listView1.LargeImageList.ImageSize = new Size(64, 64);
}
When I double click on the listview, the size changes as expected, but the icon I have is taken away, and I just get a big blank space. Even if I set the ImageIndex to use afterwards, it stays blank, and I can't seem to get it displaying again.
I assume I'm doing something wrong (although I guess .NET could be broken). What do I change such that the icon does not disappear?
(I am in .NET 2.0)
I think you are running into this caveat described in MSDN (http://msdn.microsoft.com/en-us/library/system.windows.forms.imagelist.imagesize.aspx):
Because setting the ImageSize property
causes the handle to be recreated, you
should set ImageSize prior to setting
the Images property.
Besides, relying on the system to resize the images from 32x32 to 64x64 would naturally result in low quality images.

Categories