How to subsequently add scaling behaviour in a WinForms application? - c#

I am working on a WinForms application using Visual Studio 2008 (C#). The user interface of the concerning form consists of several SplitContainers.
When I tested the application after setting the Windows font size to 125%, the form didn't look any more as it should. There obviously was a problem with scaling. Therefore I've searched for a solution and found one here. The two following lines did the job for me:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
As explained in the other question (in one of the answers, respectively), they have to be included for every container in the designer file. It works and scaling performs correctly. But on the other hand, I have to manually edit the designer file and that's something one actually shouldn't do. The added lines get lost every time I use the layout designer.
EDIT: Just to clarify: These two properties are not shown in the designer gui.
Now finally, my question is: What can I do? How or where can I add the code for correct scaling without dirty manipulation of the designer file?
I have already tried to simply put these two lines for every container in the constructor after the InitializeComponent() method call, but at this position, they don't have the desired effect.
So, maybe you have an idea how it has to be done.
Thanks in advance,
Alex

I've finally found a way to solve the problem. It isn't really what I intended originally, but it has the same effect.
The concerning two properties don't show in the designer gui, so why not make them appear? Therefore I created a custom control and added some attributes to both scaling properties, so that they appear in the designer.
public class ScalableSplitContainer : SplitContainer
{
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new AutoScaleMode AutoScaleMode
{
get { return base.AutoScaleMode; }
set { base.AutoScaleMode = value; }
}
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new SizeF AutoScaleDimensions
{
get { return base.AutoScaleDimensions; }
set { base.AutoScaleDimensions = value; }
}
}
Using this specialized SplitContainer, scaling behaviour can easily be set in the gui and the code lines are included in the generated designer file.

Related

How do I apply the Settings.settings values at design time?

I have a panel in my Form like this:
and a Panel_BackColor in project's Settings.setting file:
I can change panel back color in the Form constructor:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
panel1.BackColor = UI_Settings.Default.Panel_BackColor;
}
}
All things work at runtime:
But nothing change at Design Time. How can I apply these settings at Design mode too?
I got your question, I try to handle with it when I use MetroFramework. Some changes just shown in runtime because it use another drawing technic with xml or .netframework when you use runtime code. So, I think you can't see changes in design time.
Next time try to explain a little more in details or maybe add some code or images to make us understand better.
In C# you have the property:
//Namespace: System.ComponentModel
//Gets a value that indicates whether the Component is currently in design mode.
//true if the Component is in design mode; otherwise, false.
protected bool DesignMode { get; }
I asked "not edited version" of this question on MSDN forum and got an answer within an hour.
Questions like Convert int to string? is a good questions but mine is not!
I think stackoverflow should keep a watch on it's editors and policy.
The answer:
Select your control in Form Designer (for example a button), go to Properties, (ApplicationSettings),(PropertyBinding), then bind BackColor or other property to Button_BackColor or other settings. Afterward by changing settings in Settings.settings file, all binded controls would be affected.

C# dynamic update of control created in a dll

I created a Control and compiled it into a DLL:
namespace TSControlLibrary
{
public partial class BaseMaskedTextBox : MaskedTextBox
{
public BaseMaskedTextBox()
{
InitializeComponent();
this.BackColor = Color.Pink;
}
}
}
Then I created another Test project and want to use this new MaskedTextBox on it...
Which pretty much works,
1 - I added the reference to the DLL in Test. And kept the default properties. Copy Local = True, Specific Version = False
2 - I added the DLL to the toolbox, which shows the BaseMaskedTextBox.
Now I can add a new masked thingy onto my winform. :-)
BUT!!! But when I want to change the original DLL from Color.Pink to Color.Blue it will allow me to add a new MaskedTextBox on the form in Blue. But the Pink is still Pink.
What I would like to do is change the DLL color, recompile that and the new Test project will have the new color. How can I do this?
VS2012, winforms, heh.
hmm... well, it looks like I figured it out. :-)
I found that the DLL color set works, it updates the color from the default to Green or whatever, but then the Test.Designer.cs runs after that and just resets it to whatever it was when I added it hours ago.
So after a while on my Test form I have 30 different boxes all different colors. Because the designer.cs keeps track of where they go and some other things - like colors and font size and things.
So, I found that LocationChanged event will fire after the designer, but before it shows on the screen. So that was the ticket.
public BaseMaskedTextBoxDate2()
{
this.LocationChanged += new EventHandler(Setup);
}
//*************************************************************************************************
private void Setup(object sender, EventArgs e)
{
MaskedTextBox maskedBox = (MaskedTextBox)sender;
maskedBox.BackColor = Color.Gray; // For testing and also to make sure all fields are handled.
maskedBox.Font = new Font("Microsoft Sans Serif", 10.0f);
maskedBox.ValidatingType = typeof(System.DateTime);
maskedBox.BeepOnError = false;
maskedBox.TypeValidationCompleted += new TypeValidationEventHandler(maskedTextBoxDate_TypeValidationCompleted);
...
}
Now, if I have the DLL version ( above ) open in an instance of VS and make a change, say to the font size, going from 10 to 20, on the other instance of VS that is Test it will update on the Test Design View instantly - and with 20 font it will also be pretty nasty looking... And when compiled it will also be correct - as shown in Design.
Oddly, the only thing that I can't change is the Mask. But I doubt I will ever change that from 00/00/0000 - at least for this project anyway.

ToolStrip with custom ToolStripControlHost makes tab order focus act weird

I'm experiencing some strange behavior. Let me try to explain, I stripped my code down to the bare minimum and I'm still having the problem. So first of all, I'm using VS2013 with .NET 4.0 and I'm on Windows 8.1.
So I have a custom UserControl with a TextBox that's being used through a ToolStripControlHost, if I focus on this textbox and hit TAB, it only cycles through the controls to the LEFT of this textbox. If I have it focused and hit SHIFT+TAB, it cycles through the buttons to the right of it.
So this is an example of my form. The textbox in the middle is a custom control. My code (as simplified as possible) looks like:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripTestControl : ToolStripControlHost
{
public ToolStripTestControl() : this(new TestControl()) { }
public ToolStripTestControl(Control c) : base(c) { }
}
public class TestControl : UserControl
{
private TextBox _textBox = new TextBox();
public TestControl()
{
_textBox.Dock = DockStyle.Fill;
this.Controls.Add(_textBox);
}
protected override Size DefaultMinimumSize { get { return new Size(100, 22); } }
}
Simply creating a new WinForms (.NET4) project and following these steps will allow you to replicate the problem:
Add new class file and paste the code above.
Build
Add a ToolStrip to your form
On the ToolStrip add a Button, my custom control, and another Button (through the designer is how I've been doing it)
Run
Once running...
Focus in the custom control
Hit TAB a few times, it should only focus on controls to the left.
Hit SHIFT+TAB a few times and it will only focus to the right.
Does anyone know what the problem is - or how I can fix this? I've been tearing my hair out all day trying to fix this. I finally stripped my code down and I can't seem to get it to work. I even tried overriding much of the OnEnter/OnGotFocus functionality and doing it myself, but that became a nightmare.
Thanks!
Update1: So a few extra tid-bits.
If I change the custom control to inherit from TextBox instead of UserControl, tabbing/focus works as expected.
If I change it to be a Control instead of a UserControl the tabbing works fine, as well, however the focus never gets inside my inner TextBox - the focus seems to be lost (or presumably on the outer parent control but not being passed down to the inner TextBox).
I do see a MS Connect item added that describes this problem from 2009, but this link only seems to work if I'm NOT logged in to Microsoft Connect. Which means, I can't vote on it or comment... http://connect.microsoft.com/VisualStudio/feedback/details/472592/tab-cycling-through-controls-with-usercontrol-on-toolstrip-doesnt-perform-as-expected
The .NET 2.0 ToolStripItem classes have been a major bug factory. They are window-less controls, but reproducing the exact behavior of a Windows window isn't that easy. There is an enormous amount of code underneath, most of it internal so you can't tinker with it. And with quirks when they don't emulate the behavior of a window perfectly. You could call them "airspace" issues, pretty similar to the kind of problems that WPF has.
The airspace issue here is focus, entirely unambiguous for a true window but it needs to be faked for a ToolStripItem. It is actually the item's parent that has the focus, it needs to be emulated for the item. It is the transition that bytes, ToolStrip expects a window-based control to have a reliable Focus property.
Trouble is, your custom host doesn't. It is the inner control that has the focus. This could arguably be blamed on an omission in the ToolStripControlHost class. Probably. The trouble with emulating a window, there's never enough code :)
Anyhoo, fix your problem by adding this sliver of code to your host:
public override bool Focused {
get { return _textBox.Focused; }
}

Custom control doesn't expose image properties in the Designer

I have made a custom trackbar control, mostly as an exercise. I know i could/should have just inherited what i needed instead of reinventing the wheel, but i have learned a lot during my endeavour.
Now, i have a lot of properties, and all of them shows up in the designer apart from a couple of image properties. This is what i have, modelled on the other working properties (those are ints and Colors and what not, and they all work as expected...), so maybe i should be doing Images in some other way. Bottom line, i don't know what i'm doing :)
EDIT : My custom control is in a Windows Forms solution (VC# 2008 Express), and to clarify, my problem is that some of my control's properties (the Image properties) isn't showing in the properties-tab during design-time.
EDIT 2 : After reading up on DependencyProperty and totally failed to understand that concept (I'm very noob at programmin teh codez or what you gurus call this black voodoo magic??). I have gotten used to letting the IDE fix all my troubles, and i was pleased to see the IDE happily showing my other properties, such as Color BarColor, int Value etc. etc. Why would Image LeftImage be any different, a lot of the standard controls have Image properties and maybe it's naïve of me to think that the IDE can figure all of my mistakes out, but surely the guys at Microsoft did not construct a new editor every time they had to set an image property in their controls. My bet is that they reused something, which i should be able to do as well.
I'm stuck :(
Here's my crappy CoD3Z anyway:
private Image _LeftImage;
/// <summary>
/// Sets the small image appearing to the left of the trackbar
/// </summary>
[Description("The small image appearing to the left of the trackbar"),
Category("Appearance"),
DefaultValue(typeof(Image),"null"),
Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
public Image LeftImage
{
private get { return _LeftImage; }
set
{
if (value.Height != 16 || value.Width != 16)
{
_LeftImage = new Bitmap(value,new Size(16,16));
}
else _LeftImage = value;
Invalidate();
}
}
By the way, what is the difference between DefaultValue and DefaultValueAttribute?
Thanks for any pointers and help!
/Mikael
I have found something here:
http://msdn.microsoft.com/en-us/library/system.drawing.design.imageeditor.aspx
Consider this solved.
For Show the Image in the Designer you need to overrides the OnPaint Method drawing it.
DefaultValue is the same that DefaultValueAttribute. All Attributes in .NET are clases that inherits from System.Attribute, and all those class are something like Name*Attribute* where Attribute is fixed. Then "DefaultValue" is like an Alias.
Your example doesn't show what exactly is your problem but if you create custom control and want to access its properties from designer you should use smth like that:
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(CustomControl),
new FrameworkPropertyMetadata(null, ValueChanged));
hope this helps you

Why does my listview keep drawing in LargeIcon View?

I have a inherited Listview which standard has to be in Tile Mode. When using this control, the DrawItem gives e.bounds which are clearly bounds of largeIcon view ?? When debugging to check the view it is actually set to, it says it's in Tile view ?? Yet e.DrawText draws LargeIcon view ??
......... Edit: .................
This seems only to happen when the control is placed upon another usercontrol?
......... Edit 2: .................
It gets stranger ... When i add buttons next to the list to change the view at runtime, "Tile" is the same as "LargeIcon", and "List" view is the same as "SmallIcons" ??? I've also completely removed the ownerdraw ...
.......... Edit 3: .................
MSDN Documentation:
Tile view
Each item appears as a full-sized icon
with the item label and subitem
information to the right of it. The
subitem information that appears is
specified by the application. This
view is available only on Windows XP
and the Windows Server 2003 family.
On earlier operating systems, this value is ignored and the ListView
control displays in the LargeIcon
view.
Well I am on XP ?!?
...... Edit 4 .....................
Holy mother of strangeness ...
We are now at the point we've completely stripped down EVERYTING ... We have a standard listview on a form, manually filled with 3 values. No Ownerdraw. It is set to Tile.
When we start this form, the list is drawn as LARGEICON.
Now, we start another blank solution, copy this exact same form to the new project, start debug and low and behold .. it is drawn in TILE view ????
... help ...
public class InheritedListView : ListView
{
//Hiding members ... mwuahahahahaha //yeah i was still laughing then
[BrowsableAttribute(false)]
public new View View
{
get { return base.View; }
}
public InheritedListView()
{
base.View = View.Tile;
this.OwnerDraw = true;
base.DrawItem += new DrawListViewItemEventHandler(DualLineGrid_DrawItem);
}
void DualLineGrid_DrawItem(object sender, DrawListViewItemEventArgs e)
{
View v = this.View;
//**when debugging, v is Tile, however e.DrawText() draws in LargeIcon mode,
// e.Bounds also reflects LargeIcon mode ???? **
}
................................
This code behaves differently at different solutions:
private void InitializeComponent()
{
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("fhsdhdsfhsdfhs");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("fdshdsfhdsfhsd");
System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("hdshsdfhsdfhsdfsdfsdf");
this.listView1 = new System.Windows.Forms.ListView();
this.SuspendLayout();
//
// listView1
//
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3});
this.listView1.Location = new System.Drawing.Point(36, 12);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(487, 242);
this.listView1.TabIndex = 2;
this.listView1.TileSize = new System.Drawing.Size(480, 50);
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Tile;
//
// TestControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(595, 712);
this.Controls.Add(this.listView1);
this.Name = "TestControl";
this.Text = "TestControl";
this.ResumeLayout(false);
}
#endregion
OK, we found it. The magic spell is:
Application.EnableVisualStyles();
We skipped this line of code to test our form.
If you don't call this method before you create your form with your listview, TILE view gets drawn as LARGEICON.
Seems totally logical ... :-(
http://blogs.msdn.com/rprabhu/archive/2003/09/28/56540.aspx
Q What does Application.EnableVisualStyles actually do?
Windows XP ships with two versions of the Common Controls Library (comctl32.dll) - versions 5.8 and 6.0. v5.8 renders controls in the "Classic" style that you get on Windows NT/2000 and Windows 9x. v6.0 renders controls using the XP Visual Styles look and feel. Since most Windows Forms controls are based on comctl32, how they are rendered depends on which version of comctl32 is used to do the rendering. By default, v5.8 is used to render the client area of the app and v6.0 is used to render the non-client area. That is why you see the title bar and window borders automatically render "themed", while the controls (like Button, TextBox, ListView, ComboBox and so on) have the classic look by default.
In v1.0 of the Framework, the way to get visual styles in a Windows Forms app was to ship a manifest file with the app, that has information in it to indicate that v6.0 of comctl32 should be used for rendering. While this works fine, many developers felt it cumbersome to author, maintain and deploy manifest files. They felt the need to be able to do this programmatically. Now, the Platform SDK does provide API to do this. Basically, you need to create and activate an Activation Context that has pretty much the same DLL redirection information in it as the manifest file. The Activation Context API can be used to do this in a way suitable to your application.
If you take a look at these API, you will probably notice that they aren't very easy to use. While the advanced developers may like to tinker around with activation contexts, it is probably not something a developer who wants some "quick and dirty" code to get visual styles will do. So the Windows Forms team decided to wrap these API and expose a simple method that developers could call, that would isolate them from these complexities. So, essentially, when you call Application.EnableVisualStyles, we set up an activation context around the application's message loop, so that comctl32 function calls can be properly redirected to comctl32 v6.0. That way, you don't need to include a manifest with your app.

Categories

Resources