Skip to content
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

Merged
merged 6 commits into from Jul 27, 2022

Conversation

0xC0000054
Copy link
Contributor

@0xC0000054 0xC0000054 commented Jul 13, 2022

Fixes #4883

Proposed changes

  • The TreeView will respect the DoubleBuffered property.

Customer Impact

  • Double buffering can be enabled in a derived class without needing to use P/Invoke.

Regression?

  • No

Risk

Probably minimal.

Test methodology

  • Manually tested the change in a winforms app

Test environment(s)

  • 7.0.100-preview.5.22307.18 (x64)
Microsoft Reviewers: Open in CodeFlow

@dreddy-work dreddy-work added the 📭 waiting-author-feedback The team requires more information from the author label Jul 18, 2022
@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Jul 19, 2022
@dreddy-work
Copy link
Member

@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);
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@dreddy-work dreddy-work added the 📭 waiting-author-feedback The team requires more information from the author label Jul 19, 2022
@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Jul 19, 2022
Callers may override the TreeView OnHandleCreated method and set their
own extended styles.
@0xC0000054
Copy link
Contributor Author

can you share gif of how it looks now after the fix?

TreeView

The TreeView on the left uses the code in this PR and sets the DoubleBufferered property to true.
The TreeView on the right overrides the OnHandleCreated method to set the TVS_EX_DOUBLEBUFFER style.

The test project is attached, it is based on the minimal repo posted in the linked issue.
TreeViewFlickering.zip

RussKie
RussKie previously approved these changes Jul 19, 2022
Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@RussKie
Copy link
Member

RussKie commented Jul 19, 2022

/cc: @kirsan31

@RussKie RussKie added the 📭 waiting-author-feedback The team requires more information from the author label Jul 19, 2022
extendedStyles |= TVS_EX.DOUBLEBUFFER;
}

if (extendedStyles != 0)
Copy link
Contributor

@kirsan31 kirsan31 Jul 19, 2022

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...

  1. We need to be able to remove TVS_EX.DOUBLEBUFFER with DoubleBuffered = false; if we set it before with DoubleBuffered = true;
  2. 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 :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Contributor

@kirsan31 kirsan31 Jul 19, 2022

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...

@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label Jul 19, 2022
@kirsan31
Copy link
Contributor

Just in case, so as not to miss, we still have an unresolved issue (possibility to break some users):
#7403 (comment)
#7403 (comment)

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.
@kirsan31
Copy link
Contributor

👍
I think it's all we can do with DoubleBuffered here. Now we will break ppl only in very specific situations 😁

@RussKie
Copy link
Member

RussKie commented Jul 19, 2022

Now we will break ppl only in very specific situations 😁

Can you think what these situations may be?

Comment on lines +2752 to +2753
// 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 👍

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@kirsan31
Copy link
Contributor

Can you think what these situations may be?

Only if some one for any reason will call DoubleBuffered = true; and then DoubleBuffered = false; before HandleCreated.

@RussKie
Copy link
Member

RussKie commented Jul 19, 2022

Only if some one for any reason will call DoubleBuffered = true; and then DoubleBuffered = false; before HandleCreated.

In that case, UpdateTreeViewExtendedStyles would bail in the first return, no?
However, this sequence may result in unexpected behaviour before handle is created:

DoubleBuffered = true;
DoubleBuffered = false;
SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);

@kirsan31
Copy link
Contributor

kirsan31 commented Jul 19, 2022

In that case, UpdateTreeViewExtendedStyles would bail in the first return, no? However, this sequence may result in unexpected behaviour before handle is created:

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 base.OnHandleCreated.

So, if user have this call before base.OnHandleCreated:

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 = true;:

DoubleBuffered = false;

We will break him.

@RussKie RussKie added the ready-to-merge PRs that are ready to merge but worth notifying the internal team. label Jul 20, 2022
@dreddy-work
Copy link
Member

We are taking this and listen the feedback if we break any existing customers.

@dreddy-work dreddy-work merged commit 6379435 into dotnet:main Jul 27, 2022
@ghost ghost added this to the 7.0 RC1 milestone Jul 27, 2022
@RussKie RussKie removed the ready-to-merge PRs that are ready to merge but worth notifying the internal team. label Jul 27, 2022
@dotnet dotnet locked as resolved and limited conversation to collaborators Aug 26, 2022
@0xC0000054 0xC0000054 deleted the TreeView-double-buffer branch September 15, 2022 01:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TreeView flickering
4 participants