How do I set the height of a ComboBox? - c#

I have a ComboBox on a form, and its default height is 21. How do I change it?

ComboBox auto-sizes to fit the font. Turning that off is not an option. If you want it bigger then give it a bigger font.

Set the DrawMode to OwnerDrawVariable. However customization of the ComboBox leads to other issues. See this link for a tutorial on how to do this completely:
http://www.csharphelp.com/2006/09/listbox-control-in-c/
OwnerDrawVariable sample code here:
https://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.drawitem%28v=vs.110%29.aspx
Once that's done, you need to set the ItemHeight property of the combobox to set the effective height of the combobox.

Just as another option, if you'd like to increase the height of the ComboBox without increasing the font size or having to worry about drawing everything yourself, you can use a simple Win32 API call to increase the height like this:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Win32ComboBoxHeightExample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
private const Int32 CB_SETITEMHEIGHT = 0x153;
private void SetComboBoxHeight(IntPtr comboBoxHandle, Int32 comboBoxDesiredHeight)
{
SendMessage(comboBoxHandle, CB_SETITEMHEIGHT, -1, comboBoxDesiredHeight);
}
private void button1_Click(object sender, EventArgs e)
{
SetComboBoxHeight(comboBox1.Handle, 150);
comboBox1.Refresh();
}
}
}
Result:

To do this, you need to set the DrawMode to OwnerDrawVariable or OwnerDrawFixed and manually draw your items. This can be done with a pretty simple class.
This example will allow you to use the ItemHeight property of the ComboBox regardless of font size. I threw in an bonus property TextAlign which will also allow you to center the items.
One thing worth mentioning is, you must set DropDownStyle to DropDownList for the selected item to respect our customizations.
// The standard combo box height is determined by the font. This means, if you want a large text box, you must use a large font.
// In our class, ItemHeight will now determine the height of the combobox with no respect to the combobox font.
// TextAlign can be used to align the text in the ComboBox
class UKComboBox : ComboBox
{
private StringAlignment _textAlign = StringAlignment.Center;
[Description("String Alignment")]
[Category("CustomFonts")]
[DefaultValue(typeof(StringAlignment))]
public StringAlignment TextAlign
{
get { return _textAlign; }
set
{
_textAlign = value;
}
}
private int _textYOffset = 0;
[Description("When using a non-centered TextAlign, you may want to use TextYOffset to manually center the Item text.")]
[Category("CustomFonts")]
[DefaultValue(typeof(int))]
public int TextYOffset
{
get { return _textYOffset; }
set
{
_textYOffset = value;
}
}
public UKComboBox()
{
// Set OwnerDrawVariable to indicate we will manually draw all elements.
this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
// DropDownList style required for selected item to respect our DrawItem customizations.
this.DropDownStyle = ComboBoxStyle.DropDownList;
// Hook into our DrawItem & MeasureItem events
this.DrawItem +=
new DrawItemEventHandler(ComboBox_DrawItem);
this.MeasureItem +=
new MeasureItemEventHandler(ComboBox_MeasureItem);
}
// Allow Combo Box to center aligned and manually draw our items
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
{
// Draw the background
e.DrawBackground();
// Draw the items
if (e.Index >= 0)
{
// Set the string format to our desired format (Center, Near, Far)
StringFormat sf = new StringFormat();
sf.LineAlignment = _textAlign;
sf.Alignment = _textAlign;
// Set the brush the same as our ForeColour
Brush brush = new SolidBrush(this.ForeColor);
// If this item is selected, draw the highlight
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
brush = SystemBrushes.HighlightText;
// Draw our string including our offset.
e.Graphics.DrawString(this.Items[e.Index].ToString(), this.Font, brush,
new RectangleF(e.Bounds.X, e.Bounds.Y + _textYOffset, e.Bounds.Width, e.Bounds.Height), sf);
}
}
// If you set the Draw property to DrawMode.OwnerDrawVariable,
// you must handle the MeasureItem event. This event handler
// will set the height and width of each item before it is drawn.
private void ComboBox_MeasureItem(object sender,System.Windows.Forms.MeasureItemEventArgs e)
{
// Custom heights per item index can be done here.
}
}
Now we have full control over our font and height of the ComboBox separately. We no longer need to make a large font to size our ComboBox.

If you are wanting to adjust to the number of items in the ComboBox you can change the value of the DropDownHeight as follows, given a List of items. I'm using 24 here as a "per item amount"; this is by no means fixed.
comboBox1.DropDownHeight = SomeList.Count * 24;

ComboBox has a property 'DropDownHeight' which can be changed either via the properties window of the combobox or programmatically. i.e.
public partial class EventTestForm : Form
{
public EventTestForm()
{
InitializeComponent();
cmbOwners.DropDownHeight = 100;
}

In code, a.Height should work. In the designer, go into the properties and look in Size->Height.
Alternatively, you can change the Font Size and the combo box will grow bigger to accomodate it, but I don't think that's what you want.

Related

ListBox draw size does not change with change to larger font size

When I increase the font size in my ListBox, the larger text strings get vertically clipped because the item draw rectangle size (spacing) does not increase with the font size. Each lower line of text overlays the previous line of text so that only the tops of letters show in larger font sizes.
Everything works fine with DrawMode.OwnerDrawFixed if I don't change the font sizes. Smaller-than-normal fonts display properly. It's only the larger fonts that get clipped. I changed to DrawMode.OwnerDrawVariable and added a MeasureItem event handler to measure the larger font size explicitly, but that did not work either.
What am I missing? Thank you.
UPDATE: I provided working code below based on #Jimi's examples in the links he provided in his comments. I was missing the idea that the MeasureItem event runs only once (or when necessary) and not for each drawn item. Thus, you must manually trigger a new MeasureItem event when you change the font size in the ListBox. The trick to generating the event is to flip the DrawMode.OwnerDrawVariable to Normal and back.
listBox1.DrawMode = DrawMode.OwnerDrawVariable;
listBox1.DrawItem += DrawItemHandler;
listBox1.MeasureItem += MeasureItemHandler;
private void MeasureItemHandler(object sender, MeasureItemEventArgs e) {
// must measure the height to allow for user font size changes
var listBox = (ListBox) sender;
e.ItemHeight = listBox.Font.Height;
}
public void DrawItemHandler(object sender, DrawItemEventArgs e) {
// prepare text and colors for drawing here
//
using (var bgbrush = new SolidBrush(bgcolor)) {
using (var fgbrush = new SolidBrush(fgcolor)) {
e.Graphics.FillRectangle(bgbrush, e.Bounds);
e.Graphics.DrawString(logEntry.EntryText, e.Font, fgbrush, e.Bounds);
}
}
e.DrawFocusRectangle();
}
private void fontUpToolStripMenuItem_Click(object sender, EventArgs e) {
// To increase size alone, use the original font family
var size = listBox1.Font.Size;
if (size < 32) {
// set the new font size, register it with the list box, and then
// flip the draw mode back and forth to trigger a MeasureItem event.
// The measure event will recalculate the bounds for all items in the box.
listBox1.Font = new Font(listBox1.Font.FontFamily, size + 1);
listBox1.Height = listBox1.Font.Height;
listBox1.DrawMode = DrawMode.Normal;
listBox1.DrawMode = DrawMode.OwnerDrawVariable;
listBox1.Invalidate();
}
}

How to make group box text alignment center in win forms?

I am using a group box and there are several controls inside this.
My requirement is to set the group box title to the middle of the group box instead of Left.
How?
you can extend the group box class like this.
public class CustomGrpBox : GroupBox
{
private string _Text = "";
public CustomGrpBox()
{
//set the base text to empty
//base class will draw empty string
//in such way we see only text what we draw
base.Text = "";
}
//create a new property a
[Browsable(true)]
[Category("Appearance")]
[DefaultValue("GroupBoxText")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new string Text
{
get
{
return _Text;
}
set
{
_Text = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
//first let the base class to draw the control
base.OnPaint(e);
//create a brush with fore color
SolidBrush colorBrush = new SolidBrush(this.ForeColor);
//create a brush with back color
var backColor = new SolidBrush(this.BackColor);
//measure the text size
var size = TextRenderer.MeasureText(this.Text, this.Font);
// evaluate the postiong of text from left;
int left = (this.Width - size.Width) / 2;
//draw a fill rectangle in order to remove the border
e.Graphics.FillRectangle(backColor, new Rectangle(left, 0, size.Width, size.Height));
//draw the text Now
e.Graphics.DrawString(this.Text, this.Font, colorBrush, new PointF(left, 0));
}
}
add the above class into your project and use "CustomGrpBox" instead of "GroupBox" which will be created after build in your tool box.
and you can set the text any time like this.
private void Form2_Load(object sender, EventArgs e)
{
customGrpBox1.Text = "Hello World";
}
it will look like this in design time visual studio
Unfortunately, you may set the title on the right by using the RightToLeft property, but there is no property to set it in the middle.
What you can do is to set an empty Text in your GroupBox, create a Label with the title and put that label above the GroupBox (with the same parent).
You may do it dynamically at form initialization by calling following procedure:
private void CenterGroupBoxTitle(GroupBox groupbox)
{
Label label = new Label() ;
label.Text = groupbox.Text ;
groupbox.Text = "" ;
label.Left = groupbox.Left+(groupbox.Width-label.Width)/2 ;
label.Top = groupbox.Top + 2 ; // 2 is an example : adjust the constant
label.Parent = groupbox.Parent ;
label.BringToFront() ;
}
Try to create a custom control using Panel as container and draw border around this, you can then have full control of the title's alignment.
If you would like a simple approach, you can leave the groupbox's title as empty text, and then place a label at the center position of the groupbox. You can also define this as user-control so you wouldn't need to do this repeatedly.
Not an eloquent solution, but if you have a simple GroupBox, that stays the( same size, you can just pad the beginning, and the end with spaces.
example : GroupBox.Text = " This is the groupbox text ";
The amount of padding of space's will depend on the length of the box.
Of course you'll lose some of the GroupBox's beginning and end lines on top, and if that's important, then Answer 3 seems like a good solution.

change height of combobox in winform application

I'm developing an application for kind of touch screen device. In order be user friendly, I need to change size of combobox.
I've checked many thing including DrawItemEventHandler and MeasureItemEventHandler, but it didn't work as I want.
Basically I would like to change height of combobox without touching font size. When I change font size of combobox, it looks like left side of the image.
How can I set my combobox which will look like right side of the image?
By the way, don't know if it's effect solution, I am not using array string. I'm binding data like.
combobox.DisplayMember = "Name";
combobox.ValueMember = "ID";
combobox.DataSource = new BindingSource { DataSource = datalist };
Thanks in advance.
With TaW solution, I managed to set items as I want. The only thing I couldn't set text in middle when combobox items not droped down. How can I set this text position to the centre?
You can set the ItemHeight property and then draw the items yourself in the DrawItem event.
Not terribly hard, search for 'ownerdraw' & 'combobox'. There is one example on Code Project
Here is a minimal version, pulled from the above link:
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) return;
Font f = comboBox1.Font;
int yOffset = 10;
if ((e.State & DrawItemState.Focus) == 0)
{
e.Graphics.FillRectangle(Brushes.White, e.Bounds);
e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), f, Brushes.Black,
new Point(e.Bounds.X, e.Bounds.Y + yOffset));
}
else
{
e.Graphics.FillRectangle(Brushes.Blue, e.Bounds);
e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), f, Brushes.White,
new Point(e.Bounds.X, e.Bounds.Y + yOffset));
}
}
You also have to set the DropDownStyle to DropDownList to get the highlighting to work and you need to set the DrawMode to OwnerDrawFixed. (Or to OwnerDrawVariable, if you want to have different heights for some itmes..)

OwnerDraw DrawItem event on my combobox also changes the Text property value

My question is basically, does implementing DrawItem for my ComboBox in WinForms, change my Text property, why and I can I stop it?
Because my OwnerDraw event works perfectly except the Text property "also" gets set to the same logic as all the items in Items[] (ie implemented in DrawItem event below)
For context, I show URL's in the list, but some are so long I basically chop them and put the text "..." at the end - to make it more readable. I have DataSource set so that it renders one property of my class "DisplayUrl" but uses another "Url" for the actual value. (MyUrl below)
At the end of some code, I explicitly set cmbUrl.Text = "THE FULL TEXT"
But somehow the DrawItem event is also effecting the "Text" property because even after running this code, once the DrawItem event is finished my Text property is set to the same as Item[0]. ie With the text chopped off - as in "THE FULL T..."
void cmbUrl_DrawItem(object sender, DrawItemEventArgs e)
{
var text = ((MyUrl)((ComboBox)sender).Items[e.Index]).DisplayUrl;
var brush = text.Contains("bla) ? Brushes.DarkGreen : Brushes.Black;
// Fill in the background
e.Graphics.FillRectangle(new SolidBrush(e.BackColor), e.Bounds);
if (e.Index < 0) return;
// Work out where every thing goes
int nX = e.Bounds.Left;
int nY = e.Bounds.Top;
const int nMarg = 2;
int nH = e.Bounds.Height - (2 * nMarg);
// Draw the Colour Gymph
var penFore = new Pen(e.ForeColor);
var rectGymph = new Rectangle(nX + nMarg, nY + nMarg, nH, nH);
e.Graphics.FillRectangle(brush, rectGymph);
e.Graphics.DrawRectangle(penFore, rectGymph);
var fullWidth = nX + nH + (2 * nMarg);
e.Graphics.DrawString(text, e.Font, brush, fullWidth, e.Bounds.Top);
}
I think you want to show your the full Text in your combobox and just want to show the short text in Items drop-down list, so the solution may be this:
private void cmbUrl_DropDown(object sender, EventArgs e){
cmbUrl.DisplayMember = "DisplayUrl";
}
private void cmbUrl_DropDownClosed(object sender, EventArgs e){
cmbUrl.DisplayMember = "Url";
}

Temperature TextBox In C#

I need some code to convert standard C# TextBox to temperature TextBox which means adding "°C" to end of the text in the textbox with another color than the default color.
To get the degree symbol you can use character code 176 e.g.
Char degree = (Char)176
You can then append this to your textbox content or I would just add a label to the right of the textbox with the degree symbol if you want to control the forecolor easily.
TextBox is a plain text editor. To get different colours you would have to muck around with a rich text box. Why not put the "°C" in a label positioned to the right of the text box? That would also make your parsing and rendering code much easier.
You could probably create your own control which inherits from TextBox and then override Text property to automaticaly add °C though other color inside the same TextBox could be problem.
Why you want to have °C in TextBox ?
Can't it just be label right after TextBox ?
You can set static text and color to what you want.
The other solutions proposed here are probably sufficient for your application; however, if you had the need to implement this with re-usability in mind, here is a custom control solution which you may extend to better suit your application:
public class TemperatureTextBox : ContainerControl
{
private const int BORDER_SIZE = 1;
// Exposes text property of text box,
// expose other text box properties as needed:
public override string Text
{
get { return textBox.Text; }
set { textBox.Text = value; }
}
private TextBox textBox = new TextBox()
{
Text = string.Empty,
BorderStyle = BorderStyle.None,
Dock = DockStyle.Fill
};
private Label label = new Label()
{
Text = "°C",
TextAlign = ContentAlignment.MiddleCenter,
Size = new Size()
{
Width = 32
},
BackColor = SystemColors.Window,
Dock = DockStyle.Right
};
public TemperatureTextBox()
{
this.BackColor = SystemColors.Window;
this.Padding = new Padding(BORDER_SIZE);
this.Controls.Add(label);
this.Controls.Add(textBox);
this.PerformLayout();
}
// Constrain control size to textbox height plus top and bottom border:
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Height = (textBox.Height + (BORDER_SIZE * 2));
}
// Render a border around the control:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(
SystemPens.ControlDarkDark,
new Rectangle()
{
Width = (this.Width - BORDER_SIZE),
Height = (this.Height - BORDER_SIZE)
});
}
}
Simply create a new class and drop this code in and rebuild you solution. It will create a new TemperatureTextBox control in the toolbox which can be dropped onto a new form and visually designed.
This example exposes the Text property of the underlying text box by overriding the custom control's text property. You may want to expose other properties, and events depending on what your application needs to accomplish.

Categories

Resources