overriding CreateParams in a custom ListView has no effect? - c#

I know that there are available Properties for ListView to change the common styles but I just want to test this. That is for example the View = View.LargeIcon applies the style LVS_ICON = 0 to the ListView or GridLines = true applies the style LVS_EX_GRIDLINES = 1 to the ListView. I would like to test with CreateParams. I think using GetWindowLong and SetWindowLong Win32 functions would be OK, but for convenience, as far as I know, CreateParams can change the style of a control. But this time with a ListView, I can't make it work, it has no effect at all, I wonder if ListView is a special case?. Here is my code:
public class CustomListView : ListView {
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.Style |= 3; //Apply LVS_LIST (View as List)
return cp;
}
}
}
Only LVS_EX_GRIDLINES = 1 makes some effect but the effect is not Grid lines are drawn on the ListView but the Border becomes thicker and looks like 3D-border. That's strange, most of other applies have not effect at all.
Could you explain it or at least give me some example which works? Again please don't give me any solution or code which uses GetWindowLong and SetWindowLong, just use CreateParams.
Thanks!

If it helps to explain how this works, this is handled internally by the ListView.UpdateExtendedStyles function, which gets called when one of the properties relating to an extended style is set.
Quoting from the relevant section on MSDN
Reflector disassembles the function as follows
protected void UpdateExtendedStyles()
{
if (base.IsHandleCreated)
{
int lparam = 0;
int wparam = 0x10cfd;
switch (this.activation)
{
case ItemActivation.OneClick:
lparam |= 0x40;
break;
case ItemActivation.TwoClick:
lparam |= 0x80;
break;
}
if (this.AllowColumnReorder)
{
lparam |= 0x10;
}
if (this.CheckBoxes)
{
lparam |= 4;
}
if (this.DoubleBuffered)
{
lparam |= 0x10000;
}
if (this.FullRowSelect)
{
lparam |= 0x20;
}
if (this.GridLines)
{
lparam |= 1;
}
if (this.HoverSelection)
{
lparam |= 8;
}
if (this.HotTracking)
{
lparam |= 0x800;
}
if (this.ShowItemToolTips)
{
lparam |= 0x400;
}
base.SendMessage(0x1036, wparam, lparam);
base.Invalidate();
}
}
EDIT
The reason you can't use CreateParams is because it's not relevant for a ListView see MSDN here - excerpt copied below

Related

Selecting item in PropertyGrid causes UI flicker

I have designed a WinForms app with a several (nested) TableLayoutPanel containing background images and colors indicating status of hardware components. I added a PropertyGrid to display content of a specific object using the ComponentModel.
Example:
public class MyObject
{
public float Voltage;
[Category("Operation Voltage")]
[Description("Voltage applied")]
[DisplayName("Voltage")]
public float Vop { get => Voltage; }
}
I add the object to a PropertyGrid (the example is nonsense - only for illustration)
MyObject m = new MyObject();
m.Voltage = 1.234;
propertyGrid1.SelectedObject = m;
All works fine so far until I actively select the value in the PropertyGrid the actual value, selecting the category header has no side effect). If I do so, most TableLayoutPanel in my app start to flicker.
The problem is caused by (which I need for other purposes) this method described here:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
Following this article here which describes the issue in my opinion I am supposed to release the "device context". Can anyone point out how to do that in case of a PropertyGrid?

how to remove dropshadow in form?

How to remove dropshadow effect which is enabled by CS_DropShadow because, shadow is always showing,
below is my code,
protected override CreateParams CreateParams
{
get
{
CreateParams value = base.CreateParams;
value.ExStyle |= WindowMessages.WS_EX_TOPMOST;
if (this.ShowShadow)
value.ClassStyle |= WindowMessages.CS_DROPSHADOW;
else
value.ClassStyle &= ~WindowMessages.CS_DROPSHADOW;
return value;
}
}
Help me resolve this.

Flickering with transparent panel

I've created a simple program and now i'm in the stages of doing my designing. I've got a multiple Panels which i make visible / invisible to switch between "tabs" (EG. 1 panel for the login screen and 1 panel for the create account screen). Now i've made these panels invisible because i want them just as containers to be able to quickly move around controls and create buttons in.
My problem is that i've set my forms background image to a image i made in photoshop and whenever i switch between panels it flickers, whenever i just use a system color (white,black) this doesn't happen.
Is there any way for me to remove the flickering?
i've tried :
Setting double buffer to true
protected overrideing OnPaint, CreateBackground, and Createparam
my code is extremely basic :
private void btnNewAcc_Click(object sender, EventArgs e)
{
PanelNewAccount.Visible = true;
PanelLogin.Visible = false;
}
Try to setting the form property DoubleBuffered to true, in winforms the flickering usually happens because the GDI+ is trying to draw the control(s) a lot of times so DoubleBuffering you graphics should help in such cases
form.DoubleBuffered = true;
Thanks to Patrick i've solved my problem,
instead of using panels i'm using a TabControl and i assigned the same background to each tab.
Just as easy to add dynamic buttons as well.
Same features as panels but without the flickering.
#region .. Double Buffered function ..
public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
}
#endregion
#region .. code for Flucuring ..
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
#endregion
Even though i am late but if somebody else is also suffering from the same problem then this code fixed the flickering for me even though i dont know how it works.
I found it here.
Add the above code snippet in your program and in the contructor of your app add this line:
SetDoubleBuffered(YourPanelName);
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
code copy from codeproject solved my problem.

Password char for RichTextBox

I am using transparent custom control based on RichTextBox. Is there are any way to have password char support like in regular TextBox control.
It is simple to do, RTB actually implements support for password entry. It just isn't exposed in the .NET wrapper. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
class RichPassword : RichTextBox {
protected override CreateParams CreateParams {
get {
// Turn on ES_PASSWORD
var cp = base.CreateParams;
cp.Style |= 0x20;
return cp;
}
}
}
Yes there is a way. You would have to intercept key presses before they are drawn (look for PreviewKeyDown or similar events) and change them to asterisks(*). But you also need to implement logic to manage the real chars string.
Note I am in agreement with the Cody Gray comment.
string Value= "";
int richTextlent = 1;
private void richTextBox2_TextChanged(object sender, EventArgs e)
{
if(richTextBox2.Text.Length == richTextlent)
{
Value += richTextBox2.Text[0].ToString();
richTextBox2.Text = richTextBox2.Text.Remove(0, 1);
richTextBox2.Text += "*";
}
else
{
Value = "";
richTextBox2.Text = "";
}
richTextlent = richTextBox2.Text.Length + 1;
}
This has worked for me and solved the purpose.
Public Class RichPassword
Inherits RichTextBox
Private Const ES_PASSWORD = 32
Protected Overrides ReadOnly Property CreateParams As CreateParams
Get
Dim CP = MyBase.CreateParams
CP.Style = CP.Style Or 32
Return CP
End Get
End Property
End Class

How to double buffer .NET controls on a form?

How can I set the protected DoubleBuffered property of the controls on a form that are suffering from flicker?
Here's a more generic version of Dummy's solution.
We can use reflection to get at the protected DoubleBuffered property, and then it can be set to true.
Note: You should pay your developer taxes and not use double-buffering if the user is running in a terminal services session (e.g. Remote Desktop) This helper method will not turn on double buffering if the person is running in remote desktop.
public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
//Taxes: Remote Desktop Connection and painting
//http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
}
Check this thread
Repeating the core of that answer, you can turn on the WS_EX_COMPOSITED style flag on the window to get both the form and all of its controls double-buffered. The style flag is available since XP. It doesn't make painting faster but the entire window is drawn in an off-screen buffer and blitted to the screen in one whack. Making it look instant to the user's eyes without visible painting artifacts. It is not entirely trouble-free, some visual styles renderers can glitch on it, particularly TabControl when its has too many tabs. YMMV.
Paste this code into your form class:
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
The big difference between this technique and Winform's double-buffering support is that Winform's version only works on one control at at time. You will still see each individual control paint itself. Which can look like a flicker effect as well, particularly if the unpainted control rectangle contrasts badly with the window's background.
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null);
Ian has some more information about using this on a terminal server.
public void EnableDoubleBuffering()
{
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
One way is to extend the specific control you want to double buffer and set the DoubleBuffered property inside the control's ctor.
For instance:
class Foo : Panel
{
public Foo() { DoubleBuffered = true; }
}
nobugz gets the credit for the method in his link, I'm just reposting. Add this override to the Form:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
This worked best for me, on Windows 7 I was getting large black blocks appearing when I resize a control heavy form. The control now bounce instead! But it's better.
Extension method to turn double buffering on or off for controls
public static class ControlExtentions
{
/// <summary>
/// Turn on or off control double buffering (Dirty hack!)
/// </summary>
/// <param name="control">Control to operate</param>
/// <param name="setting">true to turn on double buffering</param>
public static void MakeDoubleBuffered(this Control control, bool setting)
{
Type controlType = control.GetType();
PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(control, setting, null);
}
}
Usage (for example how to make DataGridView DoubleBuffered):
DataGridView _grid = new DataGridView();
// ...
_grid.MakeDoubleBuffered(true);
Before you try double buffering, see if SuspendLayout()/ResumeLayout() solve your problem.
This caused me a lot of grief for two days with a third party control until I tracked it down.
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
I recently had a lot of holes (droppings) when re-sizing / redrawing a control containing several other controls.
I tried WS_EX_COMPOSITED and WM_SETREDRAW but nothing worked until I used this:
private void myPanel_SizeChanged(object sender, EventArgs e)
{
Application.DoEvents();
}
Just wanted to pass it on.
vb.net version of this fine solution....:
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
Return cp
End Get
End Property
You can also inherit the controls into your own classes, and set the property in there. This method is also nice if you tend to be doing a lot of set up that is the same on all of the controls.
I have found that simply setting the DoubleBuffered setting on the form automatically sets all the properties listed here.
FWIW
building on the work of those who've come before me:
Dummy's Solution, Ian Boyd's Solution, Amo's Solution
here is a version that sets double buffering via SetStyle in PowerShell using reflection
function Set-DoubleBuffered{
<#
.SYNOPSIS
Turns on double buffering for a [System.Windows.Forms.Control] object
.DESCRIPTION
Uses the Non-Public method 'SetStyle' on the control to set the three
style flags recomend for double buffering:
UserPaint
AllPaintingInWmPaint
DoubleBuffer
.INPUTS
[System.Windows.Forms.Control]
.OUTPUTS
None
.COMPONENT
System.Windows.Forms.Control
.FUNCTIONALITY
Set Flag, DoubleBuffering, Graphics
.ROLE
WinForms Developer
.NOTES
Throws an exception when trying to double buffer a control on a terminal
server session becuase doing so will cause lots of data to be sent across
the line
.EXAMPLE
#A simple WinForm that uses double buffering to reduce flicker
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Pen = [System.Drawing.Pen]::new([System.Drawing.Color]::FromArgb(0xff000000),3)
$Form = New-Object System.Windows.Forms.Form
Set-DoubleBuffered $Form
$Form.Add_Paint({
param(
[object]$sender,
[System.Windows.Forms.PaintEventArgs]$e
)
[System.Windows.Forms.Form]$f = $sender
$g = $e.Graphics
$g.SmoothingMode = 'AntiAlias'
$g.DrawLine($Pen,0,0,$f.Width/2,$f.Height/2)
})
$Form.ShowDialog()
.LINK
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.setstyle?view=net-5.0
.LINK
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.controlstyles?view=net-5.0
#>
param(
[parameter(mandatory=$true,ValueFromPipeline=$true)]
[ValidateScript({$_ -is [System.Windows.Forms.Control]})]
#The WinForms control to set to double buffered
$Control,
[switch]
#Override double buffering on a terminal server session(not recomended)
$Force
)
begin{try{
if([System.Windows.Forms.SystemInformation]::TerminalServerSession -and !$Force){
throw 'Double buffering not set on terminal server session.'
}
$SetStyle = ([System.Windows.Forms.Control]).GetMethod('SetStyle',
[System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance
)
$UpdateStyles = ([System.Windows.Forms.Control]).GetMethod('UpdateStyles',
[System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance
)
}catch {$PSCmdlet.ThrowTerminatingError($PSItem)}
}process{try{
$SetStyle.Invoke($Control,#(
([System.Windows.Forms.ControlStyles]::UserPaint -bor
[System.Windows.Forms.ControlStyles]::AllPaintingInWmPaint -bor
[System.Windows.Forms.ControlStyles]::DoubleBuffer
),
$true
))
$UpdateStyles.Invoke($Control,#())
}catch {$PSCmdlet.ThrowTerminatingError($PSItem)}}
}

Categories