New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make the TreeView respect the DoubleBuffered property #7403
Conversation
@0xC0000054 , can you share gif of how it looks now after the fix? |
|
||
TVS_EX extendedStyles = (TVS_EX)User32.SendMessageW(this, (User32.WM)TVM.GETEXTENDEDSTYLE); | ||
|
||
SetExtendedStyle(ref extendedStyles, TVS_EX.DOUBLEBUFFER, DoubleBuffered); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the default extended styles for TreeView here? why do we have to negate when DoubleBuffered
is not enabled? It would default back to current behavior. Did you notice any change in behavior here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default extended styles appeared to be 0 (None) when I was debugging.
But now that I think about it the code is incorrect and would not clear the style anyway, the first SendMessage parameter is a mask.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the GETEXTENDEDSTYLE call and the negation code.
Negating the extended styles would have been a regression for callers that set the values themselves.
Callers may override the TreeView OnHandleCreated method and set their own extended styles.
The TreeView on the left uses the code in this PR and sets the DoubleBufferered property to true. The test project is attached, it is based on the minimal repo posted in the linked issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/cc: @kirsan31 |
extendedStyles |= TVS_EX.DOUBLEBUFFER; | ||
} | ||
|
||
if (extendedStyles != 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to be able to remove TVS_EX.DOUBLEBUFFER
so I think this condition is wrong (redundant).
Ups, I miss a discussion above 🙄
Everything gets a bit complicated...
- We need to be able to remove
TVS_EX.DOUBLEBUFFER
withDoubleBuffered = false;
if we set it before withDoubleBuffered = true;
- We need not to broke users code if they fixed the flickering by themselves...
So I think we need to introduce some flag for it. But it will be a breaking change for some ppl any way :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you missed my update (edit above) on this :(
For example with this realization my workaround from #4883 will stop working...
Just in case, so as not to miss, we still have an unresolved issue (possibility to break some users): |
This stops the TVS_EX.DOUBLEBUFFER style from being removed unless the calling code previously set the DoubleBuffered property to true. Unconditionally removing the TreeView extended styles would break any derived classes that set them using P/Invoke.
👍 |
Can you think what these situations may be? |
// Only set the TVS_EX_DOUBLEBUFFER style if the DoubleBuffered property setter has been executed. | ||
// This stops the style from being removed for any derived classes that set it using P/Invoke. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Only if some one for any reason will call |
In that case, DoubleBuffered = true;
DoubleBuffered = false;
SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER); |
Yes, of course, all this makes sense only if we called SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER); before So, if user have this call before SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER); and this call before handle is created: DoubleBuffered = true; and this call before handle is created and after DoubleBuffered = false; We will break him. |
We are taking this and listen the feedback if we break any existing customers. |
Fixes #4883
Proposed changes
Customer Impact
Regression?
Risk
Probably minimal.
Test methodology
Test environment(s)
Microsoft Reviewers: Open in CodeFlow