Recently, I have made some optimizations to the code. After the test, the effect is OK, but I found that the interface will flicker, specifically the TreeView control will flicker, the language is C#, and the IDE is VS2005. After consulting some information and using some basic techniques (such as turning on double buffering), I found that it had no effect.
So I used the PRfiler tool to find out that the bottleneck lies in the EndUpdate operation after updating the interface each time (this is used to reduce the number of interface updates, but it is not ideal here because there are many elements in the control). I guess that every time it is updated, the bottom layer of .Net Each primitive will be updated and redrawn, so the speed will be slow and cause flickering. But if this is the case, using double buffering should have better results. Looking at the code again, I found that the update action might be too frequent, so I reduced the speed and got better, but it still didn't work.
Continue to search online and finally find a solution that is more suitable. It turns out that the underlying redraw will clear the canvas every time and then redraw it all. This is the main cause of flickering. So the message sending function operation is overloaded and this message is disabled. The code is as follows:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // Disable clearing background messages
return;
base.WndProc(ref m);
}
success!
Note: Double buffering is still useful when updates are not very frequent and the control does not contain too many elements. Once there are too many elements, each update will take a long time. Even if double buffering is used, the flickering problem cannot be solved. Personally, I think the ideal method is to disable and clear background messages in the end.
Attachment: Some records of attempts and failures
1) Use setStyle
It is said on the Internet that the setStyle function is used to set the parameters of the control, specifically:
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
The latter of these three option parameters depends on the former and must coexist, otherwise it will be invalid. And this function itself is protected, so you first need to inherit a certain control before using it.
This goal is consistent with the previous correct solution, which also disables clearing the background and turns on double buffering, but requires the user drawing option, and all drawing is done by the user. This requires you to implement all the drawing of the controls yourself, which is quite troublesome. So this method is not completely unfeasible, but it requires extra work and is not recommended. I didn't use it either.
2) Use BeginUpdate and EndUpdate
This pair of operations has a better effect in scenarios where batch operations are required to update controls, such as adding a large number of nodes in batches during initialization. The disadvantage is that it cannot be updated immediately. Therefore, it is not suitable for situations where nodes are frequently updated and want to be reflected in the interface immediately. If you use it and do not disable the clear interface message, the control will appear to be flickering, and it will mainly have a white background, and the content will be almost invisible (depending on the complexity of the video). Because the interface updates are completed at EndUpdate, too many operations cause EndUpdate to be blocked for a long time, and the interface is cleared first and updated later, causing the interface to appear blank for a long time.
3) Use ControlStyles.EnableNotifyMessage option
The effect of this option is also consistent with the correct solution. The usage is:
SetStyle(ControlStyles.EnableNotifyMessage, true);
protected override void onNotifyMessage(Message m)
{
//Write filter message code here
}
However, the actual experiment showed no effect. I don’t know why, and I didn’t investigate it in detail.
-