Change Item Height of ComboBox - c#

How to set combobox item height? My combobox.size=new size(320,40) and I had set combobox.itemheight=18 but it didn't work. I want my itemheight or text height to be 18, and fixed size for the combobox which is 320x40. I used also drawmode property but nothing is happening.

Try changing Font Size of your combo box

Well, in order to prevent combobox resizing to its default height, you can declare it being manually drawing:
myComboBox.DrawMode = DrawMode.OwnerDrawFixed; // or DrawMode.OwnerDrawVariable;
myComboBox.Height = 18; // <- what ever you want
Then you have to implement DrawItem event:
private void myComboBox_DrawItem(object sender, DrawItemEventArgs e) {
ComboBox box = sender as ComboBox;
if (Object.ReferenceEquals(null, box))
return;
e.DrawBackground();
if (e.Index >= 0) {
Graphics g = e.Graphics;
using (Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
? new SolidBrush(SystemColors.Highlight)
: new SolidBrush(e.BackColor)) {
using (Brush textBrush = new SolidBrush(e.ForeColor)) {
g.FillRectangle(brush, e.Bounds);
g.DrawString(box.Items[e.Index].ToString(),
e.Font,
textBrush,
e.Bounds,
StringFormat.GenericDefault);
}
}
}
e.DrawFocusRectangle();
}
Edit: to have the combobox stretched, but not its dropdown list
myComboBox.DrawMode = DrawMode.OwnerDrawVariable;
myComboBox.Height = 18; // Combobox itself is 18 pixels in height
...
private void myComboBox_MeasureItem(object sender, MeasureItemEventArgs e) {
e.ItemHeight = 17; // while item is 17 pixels high only
}

Related

Highlight ListBox items based on value from class

Is it possible to loop through items in a ListBox and highlight or indicate item unavailability somehow by checking a class for a value?
Basically, got a Game class and within stored info whether Game is Available so I need to check this class when looping through the ListBox Items and somehow indicate on the ListBox if GameAvailable = false.
Got to this point and not sure how to carry on:
private void HighlightUnavailable()
{
foreach(string item in listbox_consoles.Items)
{
foreach (Products.Game game in GameService.AllGames())
{
if (item == game.GameName.ToString())
{
if (game.GameAvailable)
{
}
}
}
}
}
Yes that's possible in such a way as:
Bind the ListBox to the GameService.AllGames() which returns I believe a list or an array of the Game objects.
Set the ListBox.DrawMode to DrawMode.OwnerDrawFixed and handle the ListBox.DrawItem event to draw the items according to their GameAvailable properties.
Assuming the controls names are Form1 and listBox1, add in Form1 constructor:
public Form1()
{
InitializeComponent();
//...
listBox1.DrawMode = DrawMode.OwnerDrawFixed;
listBox1.DrawItem += (s, e) => OnListBoxDrawItem(s, e);
listBox1.DataSource = GameService.AllGames();
}
Say you want to display the available games with green and the rest with red foreground colors.
private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
//Comment if you don't need to show the selected item(s)...
e.DrawBackground();
if (e.Index == -1) return;
var game = listBox1.Items[e.Index] as Game;
var foreColor = game.GameAvailable ? Color.Green : Color.Red;
//Pass the listBox1.BackColor instead of the e.BackColor
//if you don't need to show the selection...
TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
e.Bounds, foreColor, e.BackColor,
TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
... or with different background colors:
private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index == -1) return;
var game = listBox1.Items[e.Index] as Game;
var backColor = e.State.HasFlag(DrawItemState.Selected)
? e.BackColor
: game.GameAvailable
? Color.LightGreen
: listBox1.BackColor;
//Or this if you don't need to show the selection ...
//var backColor = game.GameAvailable
// ? Color.LightGreen
// : listBox1.BackColor;
using (var br = new SolidBrush(backColor))
e.Graphics.FillRectangle(br, e.Bounds);
TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
e.Bounds, Color.Black, backColor,
TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
... or with a couple of yes and no images from your resources:
Bitmap YesImage, NoImage;
public Form1()
{
InitializeComponent();
//...
YesImage = Properties.Resources.YesImage;
NoImage = Properties.Resources.NoImage;
listBox1.DrawMode = DrawMode.OwnerDrawFixed;
listBox1.DrawItem += (s, e) => OnListBoxDrawItem(s, e);
listBox1.DataSource = GameService.AllGames();
this.FormClosed += (s, e) => { YesImage.Dispose(); NoImage.Dispose(); };
}
private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index == -1) return;
var game = listBox1.Items[e.Index] as Game;
var backColor = e.State.HasFlag(DrawItemState.Selected)
? e.BackColor
: listBox1.BackColor;
var bmp = game.GameAvailable ? YesImage : NoImage;
var rectImage = new Rectangle(
3, e.Bounds.Y + ((e.Bounds.Height - bmp.Height) / 2),
bmp.Width, bmp.Height
);
var rectTxt = new Rectangle(
rectImage.Right + 3, e.Bounds.Y,
e.Bounds.Right - rectImage.Right - 3,
e.Bounds.Height
);
using (var br = new SolidBrush(backColor))
e.Graphics.FillRectangle(br, e.Bounds);
e.Graphics.DrawImage(bmp, rectImage);
TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
rectTxt, Color.Black, backColor,
TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}

How to change default selection color of a ListView?

I'm trying to change the default (blue) color of selection bar in ListView.
I'm refusing to use ObjectListView since I'll have to change all the code.
I've searched on this subject and found some answers here:
Change background selection color of ListView?
but that points to ObjectListView.
When I was using ListBox before, this worked to set the selection bar color to my likings:
Set DrawMode to OwnerDrawFixed under Properties
Set DrawItem to ListBox1_DrawItem under Events
private void ListBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) return;
//if the item state is selected them change the back color
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
e = new DrawItemEventArgs(e.Graphics,
e.Font,
e.Bounds,
e.Index,
e.State ^ DrawItemState.Selected,
e.ForeColor,
Color.FromArgb(43, 144, 188));//Choose the color
// Draw the background of the ListBox control for each item.
e.DrawBackground();
// Draw the current item text
e.Graphics.DrawString(lb_result.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds, StringFormat.GenericDefault);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
But I'm now using ListView.
I set OwnerDraw to True
I set DrawItem to ListView1_DrawItem
...and use the code from above.
I expected it to show me a different selection color as stated, but instead I get a few errors:
How would I use this code correctly for a ListView?
Owner-drawing a ListView control is more complicated than a ListBox control: many more details to take care of.
This is an example that considers four View settings of a ListView:
View.Details, View.List, View.Tile and View.SmallIcon.
Only the Text is drawn here (that's why View.LargeIcon is not included), to contain the code to a decent limit.
An example of drawing the Bitmaps included in a ImageList linked to the ListView is here.
Set up the ListView:
Enable your ListView OwnerDraw mode, then subscribe to its DrawItem, DrawSubItem and DrawColumnHeader events as shown in the sample code (mandatory, if you want the ListView to show anything).
The Headers are painted using the default rendering (setting e.DrawDefault = true).
Description of common operations:
The Item Text is drawn using TextRenderer.DrawText: this is the original method used by the ListView to draw its items. It allows to match exactly the default rendering, so we won't notice some mis-alignment of the text.
The DrawItem event is used to draw a custom background in all View modes and will draw the Items' text in all mode except View.Details, where the DrawSubItems event comes into play: we would draw the first Item's text twice, should the DrawItem event perform the same task.
The DrawSubItems event is not called when the View is set to Tile or List.
Details on the code presented here:
A helper method, GetTextAlignment, takes care of setting the Items' alignment, since each Column can have a specific text alignment.
A field, Color listViewSelectionColor, is used to set/change the Color of the select Items. To modify the selection color, set this filed to any value and Invalidate() the ListView: the new Color will be applied immediately.
Sample of the results:
bool lvEditMode = false;
Color listViewSelectionColor = Color.Orange;
protected void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var lView = sender as ListView;
if (lvEditMode || lView.View == View.Details) return;
TextFormatFlags flags = GetTextAlignment(lView, 0);
Color itemColor = e.Item.ForeColor;
if (e.Item.Selected) {
using (var bkBrush = new SolidBrush(listViewSelectionColor)) {
e.Graphics.FillRectangle(bkBrush, e.Bounds);
}
itemColor = e.Item.BackColor;
}
else {
e.DrawBackground();
}
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds, itemColor, flags);
if (lView.View == View.Tile && e.Item.SubItems.Count > 1) {
var subItem = e.Item.SubItems[1];
flags = GetTextAlignment(lView, 1);
TextRenderer.DrawText(e.Graphics, subItem.Text, subItem.Font, e.Bounds, SystemColors.GrayText, flags);
}
}
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var lView = sender as ListView;
TextFormatFlags flags = GetTextAlignment(lView, e.ColumnIndex);
Color itemColor = e.Item.ForeColor;
if (e.Item.Selected && !lvEditMode) {
if (e.ColumnIndex == 0 || lView.FullRowSelect) {
using (var bkgrBrush = new SolidBrush(listViewSelectionColor)) {
e.Graphics.FillRectangle(bkgrBrush, e.Bounds);
}
itemColor = e.Item.BackColor;
}
}
else {
e.DrawBackground();
}
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds, itemColor, flags);
}
protected void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
=> e.DrawDefault = true;
private TextFormatFlags GetTextAlignment(ListView lstView, int colIndex)
{
TextFormatFlags flags = (lstView.View == View.Tile)
? (colIndex == 0) ? TextFormatFlags.Default : TextFormatFlags.Bottom
: TextFormatFlags.VerticalCenter;
if (lstView.View == View.Details) flags |= TextFormatFlags.LeftAndRightPadding;
if (lstView.Columns[colIndex].TextAlign != HorizontalAlignment.Left) {
flags |= (TextFormatFlags)((int)lstView.Columns[colIndex].TextAlign ^ 3);
}
return flags;
}
private void listView1_BeforeLabelEdit(object sender, LabelEditEventArgs e) => lvEditMode = true;
private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e) => lvEditMode = false;

How to change the background color of a ListBox Item when hovering?

How do I change the Background Color of a ListBox Item when I hover over it?
I have overridden the DrawItem Event with this code:
private void DrawListBox(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Graphics g = e.Graphics;
Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
new SolidBrush(Color.FromArgb(52, 146, 204)) : new SolidBrush(e.BackColor);
g.FillRectangle(brush, e.Bounds);
e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font,
new SolidBrush(e.ForeColor), e.Bounds, StringFormat.GenericDefault);
e.DrawFocusRectangle();
}
However, a ListBox does not have a Property which contains the hovered Item. There is also no Event like MouseEnterItem, MouseHoverItem Event, or anything similar on a ListBox to subscribe to.
I did quite a lot of research, but all I found was a similar question on SO, which confused ListBox and ListView: Hightlight Listbox item on mouse over event
As the ListBox does not provide the MouseEnterItem and MouseHoverItem Events, it is necessary to code this functionality yourself, tracking the coordinates of the mouse to determine which item the mouse is over.
The following question is very similar, aimed at showing a tooltip for each item when hovered over. Michael Lang's answer is a very good workaround and should be adaptable for your purposes:
How can I set different Tooltip text for each item in a listbox?
Do you really want a hover? => user moves mouse and then stops over a point for a delay without moving again
If you want immediate feedback then use the MouseMove() event and get the Index of the item you are over with IndexFromPoint(). Store that value at form level so you can determine if it has changed since the last move and then set the background fill color accordingly in your DrawListBox() handler:
private int prevIndex = -1;
private void listBox1_MouseMove(object sender, MouseEventArgs e)
{
int index = listBox1.IndexFromPoint(listBox1.PointToClient(Cursor.Position));
if (index != prevIndex)
{
prevIndex = index;
listBox1.Invalidate();
}
}
private void listBox1_MouseLeave(object sender, EventArgs e)
{
prevIndex = -1;
listBox1.Invalidate();
}
private void DrawListBox(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Graphics g = e.Graphics;
Color c;
if (e.Index == prevIndex )
{
c = Color.Yellow; // whatever the "highlight" color should be
}
else if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
c = Color.FromArgb(52, 146, 204);
}
else
{
c = e.BackColor;
}
using (SolidBrush brsh = new SolidBrush(c))
{
g.FillRectangle(brsh, e.Bounds);
}
using (SolidBrush brsh = new SolidBrush(e.ForeColor))
{
g.DrawString(listBox1.Items[e.Index].ToString(), e.Font,
brsh, e.Bounds, StringFormat.GenericDefault);
}
e.DrawFocusRectangle();
}

combo box - drop down list [duplicate]

This question already has answers here:
Colour Individual Items in a winforms ComboBox?
(4 answers)
Closed 8 years ago.
i was wondering if it is possible to create a combo box (drop down list) and to paint specific cells in the drop down list.
so, if i have five items in the drop down list, the second item and the last item will be painted in blue for example and the others in gray..
is it possible?
System.Windows.Forms.ComboBox comboBox;
comboBox = new System.Windows.Forms.ComboBox();
comboBox.AllowDrop = true;
comboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
comboBox.FormattingEnabled = true;
comboBox.Items.AddRange(excel.getPlanNames());
comboBox.Location = new System.Drawing.Point(x, y);
comboBox.Name = "comboBox1";
comboBox.Size = new System.Drawing.Size(sizeX, sizeY);
comboBox.TabIndex = 0;
group.Controls.Add(comboBox);
thank's for any help..
You can use the DrawItem Event.
First you have to set the DrawMode of the ComboBox to OwnerDrawFixed
Then you set the DrawItem to something like the following:
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
Font font = (sender as ComboBox).Font;
Brush backgroundColor;
Brush textColor;
if (e.Index == 1 || e.Index == 3)
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
backgroundColor = Brushes.Red;
textColor = Brushes.Black;
}
else
{
backgroundColor = Brushes.Green;
textColor = Brushes.Black;
}
}
else
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
backgroundColor = SystemBrushes.Highlight;
textColor = SystemBrushes.HighlightText;
}
else
{
backgroundColor = SystemBrushes.Window;
textColor = SystemBrushes.WindowText;
}
}
e.Graphics.FillRectangle(backgroundColor, e.Bounds);
e.Graphics.DrawString((sender as ComboBox).Items[e.Index].ToString(), font, textColor, e.Bounds);
}
This example will make the default background colour Green with black text, and the highlighted item will have a red background and black text, of the items at indexes 1 and 3.
You could also set the font of individual items using the font variable.

How to change color of selected item in ListBox?

I have a ListBox control with some items and I want to change color of selected item... How can I do it in C# (WinForms)?
Help me please :)
This is how you can set, say Red color, to the selected ASP.NET ListBox items:
<asp:ListBox runat="server" ID="ListBox1">
<asp:ListItem Text="Text1"></asp:ListItem>
<asp:ListItem Text="Text2"></asp:ListItem>
</asp:ListBox>
if(ListBox1.SelectedItem != null)
ListBox1.SelectedItem.Attributes["style"] = "color:red";
A good example of this is available here
I am copying over code from the above example here:
"You can set the color of individual items in a ListBox using C# in your .NET WinForm by writting your own handler for the listbox's DrawItem event.
Set the ListBox's DrawMode property:
Add a standard ListBox to your .NET WinForm then set it's DrawMode property to OwnerDrawFixed which forces the ListBox's DrawItem event to be fired.
Write the handler for the DrawItem event:
private void lstBox_DrawItem(object sender, _
System.Windows.Forms.DrawItemEventArgs e)
{
//
// Draw the background of the ListBox control for each item.
// Create a new Brush and initialize to a Black colored brush
// by default.
//
e.DrawBackground();
Brush myBrush = Brushes.Black;
//
// Determine the color of the brush to draw each item based on
// the index of the item to draw.
//
switch (e.Index)
{
case 0:
myBrush = Brushes.Red;
break;
case 1:
myBrush = Brushes.Orange;
break;
case 2:
myBrush = Brushes.Purple;
break;
}
//
// Draw the current item text based on the current
// Font and the custom brush settings.
//
e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(),
e.Font, myBrush,e.Bounds,StringFormat.GenericDefault);
//
// If the ListBox has focus, draw a focus rectangle
// around the selected item.
//
e.DrawFocusRectangle();
}
In the InitializeComponent section associate your handler to the DrawItem event:
this.lstBox.DrawItem +=
new System.Windows.Forms.DrawItemEventHandler(this.lstBox_DrawItem);
You can try combinations of different brushes and Colors.
using System.Drawing;
using System.Drawing.Drawing2D;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
Rectangle rc = listBox1.GetItemRectangle(listBox1.SelectedIndex);
LinearGradientBrush brush = new LinearGradientBrush(
rc, Color.Transparent, Color.Red, LinearGradientMode.ForwardDiagonal);
Graphics g = Graphics.FromHwnd(listBox1.Handle);
g.FillRectangle(brush, rc);
}
Collating the changes, none of the above answers worked completely for me. Collating what worked for me:
public CustomListBox()
{
this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
this.DrawItem += new System.Windows.Forms.DrawItemEventHandler(custom_DrawItem);
this.MeasureItem += lstMeasureItem;
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
this.Invalidate();
}
private void custom_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) return;
//if the item state is selected then change the back color
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
e = new DrawItemEventArgs(e.Graphics,
e.Font,
e.Bounds,
e.Index,
e.State ^ DrawItemState.Selected,
e.ForeColor,
Color.Gray);//Choose the color
// Draw the background of the ListBox control for each item.
e.DrawBackground();
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(this.tbForeColor);
// Draw the current item text
e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
private void lstMeasureItem(object sender, MeasureItemEventArgs e)
{
// Cast the sender object back to ListBox type.
CustomListBox listBox = (CustomListBox)sender;
e.ItemHeight = listBox.Font.Height;
}

Categories