I assumed that the C# margin property had a meaning like in CSS - the spacing around the outside of the control. But Margin values seem to be ignored to matter what values I enter.
Then I read on the SDK:
Setting the Margin property on a
docked control has no effect on the
distance of the control from the the
edges of its container.
Given that I'm placing controls on forms, and perhaps docking them, what does the Margin property get me?
Like Philip Rieck said, the margin property is only respected by container controls that perform layout. Here's an example that makes it fairly clear how the TableLayoutPanel respects the Margin property:
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TableLayoutPanel pnl = new TableLayoutPanel();
pnl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
pnl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
pnl.Dock = DockStyle.Fill;
this.Controls.Add(pnl);
Button btn1 = new Button();
btn1.Text = "No margin";
btn1.Dock = DockStyle.Fill;
Button btn2 = new Button();
btn2.Margin = new Padding(25);
btn2.Text = "Margin";
btn2.Dock = DockStyle.Fill;
pnl.Controls.Add(btn1, 0, 0);
pnl.Controls.Add(btn2, 1, 0);
}
}
}
I believe the only .NET 2.0 built-in controls that respect this property are FlowLayoutPanel and TableLayoutPanel; hopefully third-party components respect it as well. It has basically no effect in other scenarios.
The margin property is used by whatever layout engine your control host (Panel, for example) is using, in whatever way that layout engine sees fit. However, it is best used for spacing just as you assume. Just read the documentation for that specific layout engine.
It can be very handy when using a FlowLayoutPanel or TableLayoutPanel, for example - to either reduce the default padding or space things out a bit. Obviously, if you write a custom layout provider, you can use Margin however you see fit.
Control.Margin property could be also useful at design time if you do not use layout container, but rather place controls manually.
It affects the distance between manually dragged controls at which snaplines appear.
E.g. for default margin value of 3 for text box you would have this snaplines:
And for margin of 10 - these (label has margin of 3 in both cases):
So if you have some strict guidelines for you UI then you just set the margins as you need and drag controls to the snaplines.
Related
In the MS chart, I am displaying tooltip using below code.
ToolTip ToolTip = new ToolTip();
ToolTip .Show(" X value:"+s+"\nLine 1 Y value: =" + ss + "\nLine 2 Y value:=" + ss1, chart, (int)e.Location.X, (int)e.Location.Y);
I am able to set only one foreground color using ToolTip .ForeColor = System.Drawing.Color.Red;.
I am new to C#.
How to assign a different colour and draw text in custom tooltip class or how to use HTML renderer to achieve my requirement?
I could not assign a different colour for a different part of the tooltip text.
How to achieve it?
You can owner-draw the tooltip
Example:
ToolTip ToolTip = new ToolTip();
ToolTip.OwnerDraw = true;
ToolTip.Popup += (ss, ee) => { ee.ToolTipSize = new Size(200, 50); };
ToolTip.Draw += (ss, ee) =>
{
ee.DrawBackground();
ee.DrawBorder();
ee.Graphics.DrawString("Warning", Font, Brushes.Red, 10, 1);
ee.Graphics.DrawString(ee.ToolTipText, Font, Brushes.Black, 1, 22);
};
ToolTip.Show("Demo only", somecontrol..);
This is just a simple example; there are many more parameters to style the tooltip, including drawing stuff, images, brushes of all types, etc..
It is also recommended to use TextRenderer instead of the classic GDI+ DrawString.
Note how I set the Size in the PopUp event!
All sorts of formatting is possible with the text; for multiline text it is recommended to use an overload with bounding rectangle instead of x/y coordinates and maybe also alignment with a StringFormat. Do note though, that is is always tricky to embed formatted parts inside of a text.
Possible, but tedious to get really right, as always with GDI drawing. -
The basic trick is to determine a bounding rectangle first; this can be done with MeasureString.
The short answer would be "natively you simply can't" (Except you count drawing the label yourself as natively). But as always in programming there are creative ways to get the result you want.
The answer in the Question Orel suggested basically makes use of a renderer for HTML Markup to render the styled text inside your application.
If you have a look at the newer version of this library here they actually provide a WinForms ToolTip Control which accepts HTML Markup to render inside it's content area.
To use this renderer they provide a nuget package which makes installation trivial. Simply manage your projects nuget packages and search for HtmlRenderer.WinForms and install the latest version. (Check if it also installs the latest Version of HtmlRenderer.Core because it didn't on my end and I had to update the Core package)
After this rebuild your project to get the new controls in your designer toolbox.
To test the package I dragged a textbox and a HtmlToolTip onto my Form. To set the new toolTip you use it just like a normal WinForms tooltip.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.htmlToolTip1.SetToolTip(this.textBox1, "<h1 style=\"color:red\">Hello</h1><i style=\"color:blue\">World</i>");
}
}
Now you can style your toolTip content with HTML markup and change the foreground colors as you like:
How can I add some extra space between the last item in a listview and the bottom of the control? I don't want to add an empty item to the bottom of the list.
You can't do this directly. Unfortunately the styling options of ListView are rather limited.
Unless you go for owner-drawing it.. Which is powerful and not very hard. But even there I doubt that the Items can have different Heights..
But there is a simple trick you can use:
Remove the LV's borders and place it inside a Panel with appropriate borders. Dock it there to Fill the Panel and give the Panel a Padding of maybe (0;0;0,10) and voila, the will always be a Padding of 10 pixels that looks as if it belongs to the ListView..
Instead of using the Designer, you could put these lines in the Form.Load to make it work on startup:
Panel P = new Panel();
P.BackColor = listView1.BackColor;
P.Location = listView1.Location;
P.Size = listView1.Size;
P.Padding = new System.Windows.Forms.Padding(0,0,0,10);
P.BorderStyle = listView1.BorderStyle;
listView1.BorderStyle = BorderStyle.None;
listView1.Parent = P;
listView1.Dock = DockStyle.Fill;
this.Controls.Add(P);
Today I'm trying to use c# to fit a number of windows controls onto a panel sequentially.
I would like them to dock to the top so that I can then use BringToFront() to stack them up.
HOWEVER I would also like them to be centred. Currently, docking behaviour forces the controls to the left of the screen (however much I resize and change the location property)
I then tried to anchor my controls to the top of the panel instead. This enabled the controls to be centred and also let me resize them but anchoring has no stacking behaviour and each control overwrites the previous one.
I have researched this extensively for hours and have found no answers to this question. Is it possible to use either or both of these properties to stack my controls in the centre of the panel?
My code currently stands as so:
//Docking
userControl.Dock = DockStyle.Top;
userControl.Width = 633;
userControl.Left = (pnlRules.Width - userControl.Width) / 2; //doesn't work
Point location = new Point(((pnlRules.Width - userControl.Width) / 2), 0);
userControl.Location = location; //doesn't work
userControl.BringToFront();
OR
//Anchoring
userControl.Anchor = AnchorStyles.Top;
Point location = new Point(((pnlRules.Width - userControl.Width) / 2), 0);
userControl.Location = location;
userControl.BringToFront(); //doesn't work
My outputs are either stacked controls bound to the left panel edge (docking) or overlapping controls beautifully resized and centred (anchoring)
Thanks :)
Anya
Edit:
This captions my problem quite nicely:
http://www.techrepublic.com/article/manage-winform-controls-using-the-anchor-and-dock-properties/
This explains that using docking, the controls can be stacked next to each other. I would just like the docked, stacked controls to not be bound to the left edge of the panel.
There is no way to use a combination of docking and anchoring. A TableLayoutPanel may have worked here but I was tied to a simple Panel.
The fix was to use padding to force the control to centre:
userControl.Dock = DockStyle.Top;
pnlParent.Padding = new Padding((pnlParent.Width - userControl.Width) / 2, 0, 0, 0);
userControl.BringToFront();
I have a homework, where I need to create a winforms game using C#. I have the following components:
Panel subclass with custom paint event
Panel with default windows UI elements.
I want them to arrange like this:
Because I draw on the center panel manually, I want to set it's Width, and Height fixed, so the Form subclass, what will contain it, would show the whole panel.
I tried setting the size manually in the panel subclass:
Width = someFixedWidth;
Height = someFixedHeight;
Then adding it to the containing Form:
GamePanel panel = new GamePanel(...);
panel.Dock = DockStyle.Center;
this.AutoSize = true;
this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
this.Controlls.Add(panel);
Using this, I thought, that the form will respect the size of the Panel, but it just shrinks the window to so small, that nothing is visible, only the title.
So my question is, how would I be able to set the size of the GamePanel manually, and then dock it in the center of the form, so that the Form will respect the size I set, and doesn't makes it smaller/bigger?
The Dock property is used to define the behavior of the component during resizing Container (Form) The way you did the screen is not centralized but is resized according to the screen changes, the ideal is to use a method to reposition the control and set its size. See this:
SuspendLayout();
Width = someFixedWidth;
Height = someFixedHeight;
panel.Size = new Size(panelWidth, panelHeight);
panel.Location = new Point( ClientSize.Width / 2 - panelWidth / 2, ClientSize.Height / 2 - panelHeight / 2);
panel.Anchor = AnchorStyles.None;
panel.Dock = DockStyle.None;
ResumeLayout();
In my case, I edited minimum height/width of the panel and it worked.
I tried to edit the code which related to design but it was not recommended to rewrite auto-generated code.
Thank you.
I'm using winforms and the DomainUpDown control's height is locked at 20 pixels, which results in "y"'s and other characters with descenders cut off on the bottom.
My initial thought about how to fix the problem was to change the controls height, but I couldn't do so. In the designer I only have controls to drag it's size by width. The property page immediately reverts any change to height I make. Attempts to change the value in code silently fail; no error, no exception, but no change to the value either.
In this sample form the "g" in the DomainUpDown will be cut.
public partial class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DomainUpDown domainUpDown1 = new System.Windows.Forms.DomainUpDown();
public Form1()
{
this.domainUpDown1.Location = new System.Drawing.Point(16, 8);
this.domainUpDown1.Size = new System.Drawing.Size(212, 20);
this.domainUpDown1.Text = "why are descenders like g cut?";
this.ClientSize = new System.Drawing.Size(328, 64);
this.Controls.Add(this.domainUpDown1);
}
}
I see the same fixed height behaviour when using DomainUpDown controls. You can adjust the size of the font that is used, which changes the height of the control to match the text. Perhaps adjusting the size of your text slightly can help with the clipping of the characters with "descenders". I see no clipping using the default 8.25pt font.
EDIT:
After replicating on XP running the classic theme and with Dan's testing, the problem appears to be the thickness of the borders and padding, which cut off the g.
Setting the BorderStyle to either FixedSingle or None fixes the problem.
domainUpDown1.BorderStyle = BorderStyle.FixedSingle;
or
domainUpDown1.BorderStyle = BorderStyle.None;
You will need to see what looks best in your application. Oh, and setting your theme to XP (rather than classic) will work too.