C# .Net 4.5
I have a ListView that is constantly being updated by different threads through this method:
public void UpdateUI_List_SetRow(int rowNum, ListViewItem item)
{
lock (lock_List)
{
try
{
if (this.lstStatus.InvokeRequired)
lstStatus.Invoke(new MethodInvoker(() => lstStatus.Items[rowNum] = item));
else
lstStatus.Items[rowNum] = item;
}
catch (Exception ex)
{
ErrorLogging.Log(ex);
}
}
}
It constantly flickers while being updated. I have tried the DoubleBuffered fix (How to prevent flickering in ListView when updating a single ListViewItem's text?) but it didn't work.
Sorry if this is a duplicate post but I couldn't find any solution other than enabling double buffering.
Subclass ListView to enable double buffering:
namespace System.Windows.Forms
{
public class ListViewEx : ListView
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
}
}
Code provided in accepted answer works, but ruins selection rectangle. The solution below works like a charm. It enables double buffering and retains correct rectangle.
public partial class myListView : ListView
{
public myListView()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
}
How to use it - add this code to your namespace and use myListView instead of conventional ListView.
Related
private void downloader_Succeeded(object sender, EventArgs e)
{
FileDownloader.FileInfo fi = downloader.CurrentFile;
string name = fi.Path;
foreach (ListViewItem lvw in listView1.Items)
{
if (lvw.Text == name)
lvw.ForeColor = Color.Green;
}
label6.Text = countFilesDownloaded++.ToString();
}
Each time when it's coloring the item it's flickering.
I saw some answers but none of them is working.
I saw this answer:
Flickering answer
And this one
Flickering answer
Maybe i didn't use them right. But they didn't work.
Tried to add this to the form1 at the bottom:
protected override CreateParams CreateParams {
get {
var parms = base.CreateParams;
parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN
return parms;
}
}
Then tried to create instance of this each time a item was coloring inside the event.
I had your problem and after doing some research it appears that the ListView control repaints its entire area whenever you modify a single item. The solution is to subclass the ListView and filter out the WM_ERASEBKGND message. This did the trick for me.
For more information see here:
c# flickering Listview on update
public partial class ListViewNF : ListView
{
public ListViewNF()
{
}
public ListViewNF(IContainer container)
{
container.Add(this);
InitializeComponent();
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form's WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
In Win32 API the BS_GROUPBOX just creates a 'button' that is basically painted as a group, it doesn't serve as a container for any other control.
In WinForms, this concept was changed and GroupBox is actually a container.
I'm porting an old Win32 app to WinForms where I generate at run-time dialog forms by parsing a Win32 API dialog definition string. Everything works fine, except these groupBoxes, for which I cannot find an alternative in .NET world.
How would I get a control ala Win32 GroupBox that doesn't take any ownership as the .NET GroupBox?
Thx
After all I solved the problem by creating a Transparent GroupBox in .NET. Here is the code.
public sealed class IGTransparentGroupBox : GroupBox
{
public IGTransparentGroupBox()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Opaque, true);
BackColor = Color.Transparent;
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x20;
return cp;
}
}
protected override void OnBackColorChanged(EventArgs e)
{
Parent?.Invalidate(Bounds, true);
base.OnBackColorChanged(e);
}
protected override void OnParentBackColorChanged(EventArgs e)
{
Invalidate();
base.OnParentBackColorChanged(e);
}
}
I know how to create a fadeIn/Out winform.
The problem is, I don't know how to create a Custom Control which will lose its full transparency when mouse leaves its area and gets transparent when mouse gets back on it.
A Custom Control doesn't have Opacity and TransparentKey properties.
This tutorial explains how to add Opacity property to a User Control.
public UserControl1()
{
InitializeComponent();
// Enables support for transparent back color for inner controls.
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
// This enables transparent backgrounds for the control.
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
// A property to adjust the opacity level.
private int _opacity = 255;
[Description("Set opacity of control. 0 to 255")]
public int Opacity
{
get
{
return this._opacity;
}
set
{
this._opacity = value;
this.Refresh();
}
}
// Override default OnPaintBackground event.
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(this.Opacity, this.BackColor)), this.ClientRectangle);
}
But it doesn't work on my Custom Control or I just don't know how to use it.
By FadeIn/Out, I mean a control which gets transparent when mouse leave it until user points back to it
In my WinForm Application, I am needing to layer some images. However, I'm having trouble getting a transparent control to place the image in. I have done some research and came up with the following class:
public class TransparentPicture : PictureBox
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// do nothing
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
}
This seems to work fine until I close Visual Studios and reopen the Solution. Then my controls all disappear in the designer. They show when I run the program, but I need them to show in designer too where I can continue to design my application.
I know this isn't everything I need to do, because these controls are always causing my program to freeze up for a few seconds and stuff.
So my question is..does anybody know where I can find code for a transparent control, or how to fix the one I've thrown together?
Make the TransparentPicture be a regular PictureBox, until an IsTransparent property is set to true.
Set the property to false on design time, and to true in FormLoad event (which will only happen when you actually run the application).
That way, on design time, they will behave as regular picture boxes, but when you run the application, they will become transparent.
public class TransparentPicture : PictureBox
{
public bool IsTransparent { get; set; }
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
if (this.IsTransparent)
{
cp.ExStyle |= 0x20;
}
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
if (!this.IsTransparent)
{
base.OnPaintBackground(e);
}
}
protected override void OnMove(EventArgs e)
{
if (this.IsTransparent)
{
RecreateHandle();
}
else
{
base.OnMove(e);
}
}
}
Then, on your FormLoad event, you should do:
for (var i = 0; i < this.Controls.Count; i++)
{
var tp = this.Controls[i] as TransparentPicture;
if (tp != null)
{
tp.IsTransparent = true;
}
}
Or if you only have a few:
tp1.IsTransparent = tp2.IsTransparent = tp3.IsTransparent = true;
I am creating some always-on-top toasts as forms and when I open them I'd like them not to take away focus from other forms as they open. How can I do this?
Thanks
protected override bool ShowWithoutActivation
{
get
{
return true;
}
}
Override this property in your form code and it should do the trick for you.
It took me a few minutes using Adam's & Aaron's info above, but I finally got it to work for me. The one thing I had to do was make sure the form's Top Most property is set to false. Here is the code I used...
protected override bool ShowWithoutActivation { get { return true; } }
protected override CreateParams CreateParams
{
get
{
//make sure Top Most property on form is set to false
//otherwise this doesn't work
int WS_EX_TOPMOST = 0x00000008;
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TOPMOST;
return cp;
}
}