Listview background drawing problem C# Winform - c#

I have a little problem with a Listview.
I can load it with listview items fine, but when I set the background color it doesn't draw the color all the way to the left side of the row [The listViewItems are loaded with ListViewSubItems to make a grid view, only the first column shows the error]. There is a a narrow strip that doesn't paint. The width of that strip is approximately the same as a row header would be if I had a row header.
If you have a thought on what can be done to make the background draw I'd love to hear it.
Now just to try a new idea, I'm offering a ten vote bounty for the first solution that still has me using this awful construct of a mess of a pseudo grid view. [I love legacy code.]
Edit:
Here is a sample that exhibits the problem.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ListView lv = new ListView();
lv.Dock = System.Windows.Forms.DockStyle.Fill;
lv.FullRowSelect = true;
lv.GridLines = true;
lv.HideSelection = false;
lv.Location = new System.Drawing.Point(0, 0);
lv.TabIndex = 0;
lv.View = System.Windows.Forms.View.Details;
lv.AllowColumnReorder = true;
this.Controls.Add(lv);
lv.MultiSelect = true;
ColumnHeader ch = new ColumnHeader();
ch.Name = "Foo";
ch.Text = "Foo";
ch.Width = 40;
ch.TextAlign = HorizontalAlignment.Left;
lv.Columns.Add(ch);
ColumnHeader ch2 = new ColumnHeader();
ch.Name = "Bar";
ch.Text = "Bar";
ch.Width = 40;
ch.TextAlign = HorizontalAlignment.Left;
lv.Columns.Add(ch2);
lv.BeginUpdate();
for (int i = 0; i < 3; i++)
{
ListViewItem lvi = new ListViewItem("1", "2");
lvi.BackColor = Color.Black;
lvi.ForeColor = Color.White;
lv.Items.Add(lvi);
}
lv.EndUpdate();
}
}

Ah! I see now :}
You want hacky? I present unto you the following:
...
lv.OwnerDraw = true;
lv.DrawItem += new DrawListViewItemEventHandler( lv_DrawItem );
...
void lv_DrawItem( object sender, DrawListViewItemEventArgs e )
{
Rectangle foo = e.Bounds;
foo.Offset( -10, 0 );
e.Graphics.FillRectangle( new SolidBrush( e.Item.BackColor ), foo );
e.DrawDefault = true;
}
For a more inventive - and no less hacky - approach, you could try utilising the background image of the ListView ;)

(Prior to the Edit...)
I've just tried setting the BackColor on a System.Windows.Forms.ListView, and the color is applied across the control just fine (with and without images).
Are you doing any Custom Painting at all?

Ok I'm adding some additional solution notes. If you use the solution above you also need to insert a draw handler for the column headers, otherwise they won't paint. The selected item rectangle also looks funny so you'll want to check for that in the lv_DrawItem function and implement a similar solution. Remeber that highlighting is chosen at the system level and not in you application.

Better ListView (and free Better ListView Express) allows setting background image with various alignment settings (centered, tiled, stretched, fit, snap to border/corner). Alpha transparency is also supported:

Related

Location of panel not correct when using different anchor style

this is for Winforms / C# btw.
So I am making my own ComboBox, just playing around.
The item List is basically a Panel, which is located under or above the ComboBox control, depending on its height and location.
This works as intended, as long as I use AnchorStyle Top / Left for my usercontrol.
As soon as I switch to Top / Right Style, the location of my listpanel breaks. Okay, makes sense, the location point of my usercontrol changes with the different anchorstyle, so how about I adjust my panel to a new location using my usercontrol.LocationChanged event? Doesen't work. Maybe because of the order of the events? Or does the origin of locations change depending on the given AnchorStyles?
Anyway, I am a bit lost. Unfortunately I couldn't find a similar case here, therefore this question.
Here's my DropDownPanel (effectively my "list"):
private Panel DropDownPanel()
{
Panel DropDownPanel = new Panel() {
Width = this.Width,
Height = 200,
BackColor = _skin.TextBoxBackColor,
BorderStyle = BorderStyle.FixedSingle,
ForeColor = _skin.TextBoxForeColor,
Visible = false,
AutoScroll = false
};
DropDownPanel.HorizontalScroll.Enabled = false;
DropDownPanel.HorizontalScroll.Visible = false;
DropDownPanel.HorizontalScroll.Maximum = 0;
DropDownPanel.AutoScroll = true;
DropDownPanel.Leave += DropDownPanel_Leave;
return DropDownPanel;
}
Here's my userControl Load Event:
private void GbComboBox_Load(object sender, EventArgs e)
{
_dropDownPanel = DropDownPanel();
this.Parent.Parent.Controls.Add(_dropDownPanel);
RelocateDropDownPanel();
_dropDownPanel.BringToFront();
ApplyItems(_items);
}
And my calculation for the location:
private void RelocateDropDownPanel()
{
if (_dropDownPanel != null)
{
int initLocY = this.Parent.Location.Y + this.Location.Y + this.Height + _dropDownPanel.Height;
int fullHeight = this.FindForm().Height;
Point p = new Point();
if (initLocY < fullHeight)
{
p = new Point(this.Parent.Location.X + this.Location.X, initLocY - _dropDownPanel.Height);
}
else
{
p = new Point(this.Parent.Location.X + this.Location.X, initLocY - _dropDownPanel.Height - this.Height);
}
_dropDownPanel.Location = p;
}
}
So I figured out a "solution".
I simply inherited the Anchor of my Panel from the Usercontrol it was associated to.
But I wanna mention, that still, this whole thing is kind of a crappy way of dealing with custom combobox desings. As #Jimi stated in his first comment, the correct way of doing this would be to ownerdraw the combobox. I haven't done this because of specific reasons, which didn't let me do this.
A little example on how this could be made:
Change ComboBox Border Color in Windows Forms

PictureBox makes white parts transparent itself

My picturebox acts like it is .PNG file.
It makes white parts transparent.
Even penetrates "Form" and i'm able to see what's behind Form (like my desktop, files).
But it seems normal in Form1.cs [Design].
//card properties and design
this.card.BackColor = System.Drawing.Color.Red;
this.card.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("card.BackgroundImage")));
this.card.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.card.Location = new System.Drawing.Point(47, 92);
this.card.Name = "card";
this.card.Size = new System.Drawing.Size(103, 157);
this.card.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.card.TabIndex = 2;
this.card.TabStop = false;
this.card.Visible = false;
Here is a picture of without running:
Second picture that explains what's my problem:
This looks like a TransparencyKey being set to Color.White. Try clearing that.

How to change window background color in mono (GTK)?

I have a window in gtk which includes a Build() function as follow:
protected virtual void Build()
{
global::Stetic.Gui.Initialize(this);
// Widget Client.Forms.Notification
this.Name = "Client.Forms.Notification";
this.Title = "Notification";
this.TypeHint = Gdk.WindowTypeHint.Normal;
//this.TypeHint = ((global::Gdk.WindowTypeHint)(4));
this.WindowPosition = ((global::Gtk.WindowPosition)(4));
// Container child Client.Forms.Notification.Gtk.Container+ContainerChild
this.vbox1 = new global::Gtk.VBox();
this.vbox1.Name = "vbox1";
this.vbox1.Spacing = 6;
// Container child vbox1.Gtk.Box+BoxChild
this.label1 = new global::Gtk.Label();
this.label1.HeightRequest = 20;
this.label1.Name = "label1";
this.label1.LabelProp = "Notification";
this.vbox1.Add(this.label1);
global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.label1]));
w1.Position = 0;
w1.Expand = false;
w1.Fill = false;
// Container child vbox1.Gtk.Box+BoxChild
this.hbox1 = new global::Gtk.HBox();
this.hbox1.Name = "hbox1";
this.hbox1.Spacing = 6;
// Container child hbox1.Gtk.Box+BoxChild
this.image1 = new global::Gtk.Image();
this.image1.Name = "image1";
this.image1.Pixbuf = global::Gdk.Pixbuf.LoadFromResource("Client.Resources.icon.png");
this.hbox1.Add(this.image1);
global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.image1]));
w2.Position = 0;
w2.Expand = false;
w2.Fill = false;
// Container child hbox1.Gtk.Box+BoxChild
this.label2 = new global::Gtk.Label();
this.label2.Name = "label2";
this.label2.WidthRequest = 260;
this.label2.Wrap = true;
this.label2.LabelProp = "Description";
this.hbox1.Add(this.label2);
global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.label2]));
w3.Position = 1;
w3.Expand = false;
w3.Fill = false;
this.vbox1.Add(this.hbox1);
global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.hbox1]));
w4.Position = 1;
w4.Expand = false;
w4.Fill = false;
this.label1.ModifyBase(Gtk.StateType.Normal, Core.fromColor(System.Drawing.Color.Orange));
this.ModifyBase(Gtk.StateType.Normal, Core.fromColor(System.Drawing.Color.Orange));
this.vbox1.ModifyBase(Gtk.StateType.Normal, Core.fromColor(System.Drawing.Color.Orange));
root = new Gtk.EventBox();
root.Add(this.vbox1);
this.Decorated = false;
this.Add(root);
if ((this.Child != null))
{
this.Child.ShowAll();
}
this.DefaultWidth = 460;
this.DefaultHeight = 220;
}
(source code of this whole window: https://github.com/pidgeonproject/pidgeon/blob/master/Forms/Notification.cs)
As you can see it is calling
this.ModifyBase(Gtk.StateType.Normal, Core.fromColor(System.Drawing.Color.Orange));
which should change the background to orange, however it doesn't.
I tried to insert more similar functions on window elements, but it doesn't work either, does anyone know how to change the background color of the window?
What I want to do is create a small window with no decoration (so just a rectangle) of specific color and some text in it. This window is supposed to be transparent (that works now) and should have a picture and 2 labels with text and disappear on click - all this works now just I can't change the background from gray to some better color. I would be happy for answers that would let me do this using some other way (I can think of creating a small form just with drawing area and paint it with the color and then paint the text as well, but it sounds to me quite complicated for something so simple as I want to do).
NOTE: mono is using GTK 2, and the version of GTK# for .Net is using 2.12.20
Try to use Event Box. Seems to work
For GTK+2 you need to create a gtk resource like so:
char *my_custom_style = "style \"my-style-name\" { bg[NORMAL] = \"#339933\" }\nclass \"GtkWindow\" style \"my-style-name\"";
then load the resource when you start the program, after initialization:
gtk_rc_parse_string (my_custom_style);
Now any GtkWindow will use your custom style for it's background.
The C documentation for Gtk Resource Files
Edit:
If you only want to change one specific window, then you'd change the custom style string to something like
char *my_custom_style="style \"my-style-name\" { bg[NORMAL] = \"#339933\" }\nwidget \"my-custom-window\" style= \"my-style-name\"';
You then set the name of the window you want to change the background with
gtk_widget_set_name (GTK_WIDGET (my_window), "my-custom-window");
Edit 2:
Here's the documentation to the Gtk# Rc parsing function:
http://buttle.shangorilla.com/1.1/handlers/monodoc.ashx?link=M%3aGtk.Rc.Parse(System.String)
The documentation (for the C API) says that gtk_widget_modify_color() is deprecated, and that newly written code should use gtk_widget_override_background_color() instead, so try that.
Overriding themes in GTK+ is notoriously hard though, but the 3.0 API really sounds as if it's supporting what you want to do.
Can't test this myself at the moment, unfortunately.

Can StatusStrip automatically change its height depending on its items' size?

I've got a statusstrip with a number of items. One of them is a ToolStripStatusLabel with Spring = True.
When the text of the label is too long, one can't see it.
Is it possible to make the statusstrip become higher and show whole text in multiline?
This is an interesting problem....I tried a couple of things but no success...basicall the ToolStripStatusLabel is very limited in capability.
I ended up trying a hack that gives the result you want but am not sure even I would recommend this unless of course this is absolutely necessary...
Here's what I have got...
In the properties of your StatusStrip set AutoSize = false, this is to allow the StatusStrip to be resized to accommodate multiple lines. I am assuming statusStrip called ststusStrip1 containing label called toolStripStatusLabel1.
At form Level declare a variable of TextBox type:
TextBox txtDummy = new TextBox();
At Form Load set some of its properties:
txtDummy.Multiline = true;
txtDummy.WordWrap = true;
txtDummy.Font = toolStripStatusLabel1.Font;//Same font as Label
Handle the paint event of the toolStripStatusLabel1
private void toolStripStatusLabel1_Paint(object sender, PaintEventArgs e)
{
String textToPaint = toolStripStatusLabel1.Tag.ToString(); //We take the string to print from Tag
SizeF stringSize = e.Graphics.MeasureString(textToPaint, toolStripStatusLabel1.Font);
if (stringSize.Width > toolStripStatusLabel1.Width)//If the size is large we need to find out how many lines it will take
{
//We use a textBox to find out the number of lines this text should be broken into
txtDummy.Width = toolStripStatusLabel1.Width - 10;
txtDummy.Text = textToPaint;
int linesRequired = txtDummy.GetLineFromCharIndex(textToPaint.Length - 1) + 1;
statusStrip1.Height =((int)stringSize.Height * linesRequired) + 5;
toolStripStatusLabel1.Text = "";
e.Graphics.DrawString(textToPaint, toolStripStatusLabel1.Font, new SolidBrush( toolStripStatusLabel1.ForeColor), new RectangleF( new PointF(0, 0), new SizeF(toolStripStatusLabel1.Width, toolStripStatusLabel1.Height)));
}
else
{
toolStripStatusLabel1.Text = textToPaint;
}
}
IMP: Do not assign the text property of your label instead put it in Tag we would use it from Tag
toolStripStatusLabel1.Tag = "My very long String";

Add vertical scroll bar to panel

I am trying to make a Panel scrollable, but only vertically (so AutoScroll won't work because the child controls go past the left edge and must).
So how is this done?
Try this instead for 'only' scrolling vertical.
(auto scroll needs to be false before it will accept changes)
mypanel.AutoScroll = false;
mypanel.HorizontalScroll.Enabled = false;
mypanel.HorizontalScroll.Visible = false;
mypanel.HorizontalScroll.Maximum = 0;
mypanel.AutoScroll = true;
Assuming you're using winforms, default panel components does not offer you a way to disable the horizontal scrolling components. A workaround of this is to disable the auto scrolling and add a scrollbar yourself:
ScrollBar vScrollBar1 = new VScrollBar();
vScrollBar1.Dock = DockStyle.Right;
vScrollBar1.Scroll += (sender, e) => { panel1.VerticalScroll.Value = vScrollBar1.Value; };
panel1.Controls.Add(vScrollBar1);
Detailed discussion here.
Panel has an AutoScroll property. Just set that property to True and the panel will automatically add a scroll bar when needed.
AutoScroll is really the solution!
You just have to set AutoScrollMargin to 0, 1000 or something like this, then use it to scroll down and add buttons and items there!
Below is the code that implements custom vertical scrollbar. The important detail here is to know when scrollbar is needed by calculating how much space is consumed by the controls that you add to the panel.
panelUserInput.SuspendLayout();
panelUserInput.Controls.Clear();
panelUserInput.AutoScroll = false;
panelUserInput.VerticalScroll.Visible = false;
// here you'd be adding controls
int x = 20, y = 20, height = 0;
for (int inx = 0; inx < numControls; inx++ )
{
// this example uses textbox control
TextBox txt = new TextBox();
txt.Location = new System.Drawing.Point(x, y);
// add whatever details you need for this control
// before adding it to the panel
panelUserInput.Controls.Add(txt);
height = y + txt.Height;
y += 25;
}
if (height > panelUserInput.Height)
{
VScrollBar bar = new VScrollBar();
bar.Dock = DockStyle.Right;
bar.Scroll += (sender, e) => { panelUserInput.VerticalScroll.Value = bar.Value; };
bar.Top = 0;
bar.Left = panelUserInput.Width - bar.Width;
bar.Height = panelUserInput.Height;
bar.Visible = true;
panelUserInput.Controls.Add(bar);
}
panelUserInput.ResumeLayout();
// then update the form
this.PerformLayout();
3 steps:
1- just set AutoScroll property to true
2- in Form load()add the following:
my Panel Vertical Scroll Maximum = 10000
3- after my Panel controls Add(item) add the following:
Invalidate();
Done!
Add to your panel's style code something like this:
<asp:Panel ID="myPanel" runat="Server" CssClass="myPanelCSS" style="overflow-y:auto; overflow-x:hidden"></asp:Panel>

Categories