-
Notifications
You must be signed in to change notification settings - Fork 991
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
Check for the return value of native SetParent calls in Control class #2262
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2262 +/- ##
===================================================
- Coverage 29.45241% 29.43485% -0.01756%
===================================================
Files 1005 945 -60
Lines 259629 266565 +6936
Branches 36855 37943 +1088
===================================================
+ Hits 76467 78463 +1996
- Misses 178224 182909 +4685
- Partials 4938 5193 +255
|
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.
You must sign CLA before we can accept the submission.
Few stylistic issues
@@ -919,7 +919,10 @@ internal unsafe void InPlaceActivate(Ole32.OLEIVERB verb) | |||
// If it doesn't, that means that the host | |||
// won't reflect messages back to us. | |||
HWNDParent = hwndParent; | |||
User32.SetParent(new HandleRef(_control, _control.Handle), hwndParent); | |||
if (User32.SetParent(new HandleRef(_control, _control.Handle), hwndParent) == IntPtr.Zero) |
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.
@hughbe look like we overlooked an overload public static IntPtr SetParent(IHandle hWndChild, IHandle hWndChildNewParent)
36db571
to
aa97eb0
Compare
The test seems to get stuck on CI pipeline for 57min… Weird. |
aa97eb0
to
0d38114
Compare
@JeremyKuhne could you please review as well? |
@@ -9969,14 +9994,22 @@ internal virtual void RecreateHandleCore() | |||
} | |||
finally | |||
{ | |||
if (parentHandle.Handle != IntPtr.Zero // the parent was not null | |||
&& (FromHandle(parentHandle.Handle) == null || _parent == null) // but wasnt a windows forms window | |||
if (recreationSuccessful |
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.
Since we're dependent on recreationSuccessful
this try ... finally
can move to wrap the block above that I suggested to move. It would look something like this:
// Do the main work of recreating the handle
DestroyHandle();
CreateHandle();
SetState(States.Recreate, false);
try
{
// Inform children that their parent's handle has recreated.
// ...
}
finally
{
// If there is a parent window that isn't a WinForms window we need to reparent manually.
// If the parent was a WinForms Control, CreateControl will have taken care of this.
if (parentHandle.Handle != IntPtr.Zero
// ...
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'm moving re-parenting Win32 window part outside the finally
block, as we should not expect to recover anything / keep anything consistent from ThreadAbortException
in the main thread, and this can reduce 1 level of nesting try
block.
However, I'm keeping the CreateHandle
and DestroyHandle
part inside try
block, as we can still try our best to keep the states (States.Created
, States.Recreate
, Parent
value of the controls in controlSnapshot
) consistent when there is an Exception.
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.
Note that there are no ThreadAbortException
throws in Core. (@RussKie, not sure if you knew this.)
To simplify the code for these flags it would be worth looking at creating ref struct disposables that set and clear specified flags. Pattern dispose and the new syntax for using can help us reduce nesting and cognitive overload on some of our try .. finally
blocks. (And it is efficient when using structs like this as there are no heap allocations.)
0d38114
to
1e94b56
Compare
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.
Looks good!
bf385e4
to
4ac0fed
Compare
…ramework. Without these changes, on PMv2 applications, We might be ending up with wrong Dpiawareness than the requested for windows and some times, might endup failing to parent because of inconsitance DpIcontexts. #2262 addressed for catching the failure but still applications may be still creating wrong DPIawareness windows.
* Seems this changes was missed from Day 1 and a regression from .NET framework. Without these changes, on PMv2 applications, We might be ending up with wrong Dpiawareness than the requested for windows and some times, might endup failing to parent because of inconsitance DpIcontexts. #2262 addressed for catching the failure but still applications may be still creating wrong DPIawareness windows.
This change appears to have caused a regression reported in #6093 |
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262.
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262.
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262.
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262.
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262, which added a check to the method handling recreation of a control handle to verify that the control is created before any child controls can be re-parented on to it. However it was missed that DestroyHandle() method resets the state (i.e. removes Created state), but CreateHandle() method doesn't set the state back.
…orm recreates handle Fixes dotnet#6093 Fix the regression introduced in dotnet#2262, which added a check to the method handling recreation of a control handle to verify that the control is created before any child controls can be re-parented on to it. However it was missed that DestroyHandle() method resets the state (i.e. removes Created state), but CreateHandle() method doesn't set the state back.
Fixes #2163
Proposed changes
RecreateHandleCore
andSetParentHandle
methods.Control.CreateHandle
callsApplication.ParkHandle
, it does not specify the DPI awareness (DPI_AWARENESS_CONTEXT_UNSPECIFIED
), soParkHandle
will choose a parking window forUNSPECIFIED
awareness context. When constructing the parking window forUNSPECIFIED
context, the DPI awareness of current thread will be used (e.g. PerMonitorV2). This will causes the subsequently parked window uses the very same DPI awareness setting, regardless of their owning thread's current DPI awareness at the point of control instance / handle construction.ParkHandle
inCreateHandle
method.Win32Exception
accordingly.Customer Impact
Regression?
Risk
Screenshots
Before
After
Test methodology
Accessibility testing
Test environment(s)
Microsoft Reviewers: Open in CodeFlow