Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dotNET Platform
wpf
提交
4ab8661a
W
wpf
项目概览
dotNET Platform
/
wpf
12 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
W
wpf
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4ab8661a
编写于
6月 07, 2019
作者:
S
Sam Bent
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
port changes from .NET 4.8
上级
e126953b
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
86 addition
and
45 deletion
+86
-45
src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs
...et.Wpf/src/PresentationFramework/System/Windows/Window.cs
+45
-43
src/Microsoft.DotNet.Wpf/src/WindowsBase/System/ComponentModel/PropertyChangedEventManager.cs
...Base/System/ComponentModel/PropertyChangedEventManager.cs
+41
-2
未找到文件。
src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs
浏览文件 @
4ab8661a
...
...
@@ -399,7 +399,7 @@ public Nullable<bool> ShowDialog()
Debug
.
Assert
(
_threadWindowHandles
==
null
,
"_threadWindowHandles must be null before enumerating the thread windows"
);
// NOTE:
// NOTE:
// _threadWindowHandles is created here. This reference is nulled out in EnableThreadWindows
// when it is called with a true parameter. Please do not null it out anywhere else.
// EnableThreadWindow(true) is called when dialog is going away. Once dialog is closed and
...
...
@@ -423,7 +423,7 @@ public Nullable<bool> ShowDialog()
if
(
hWndCapture
!=
IntPtr
.
Zero
)
{
//
// NOTE:
// NOTE:
// EnableWindow(false) (called from EnableThreadWindows(false)
// sends WM_CANCELMODE to the window, so we don't need
// to send it again. However, if we change our impl
...
...
@@ -455,7 +455,7 @@ public Nullable<bool> ShowDialog()
}
catch
{
// NOTE:
// NOTE:
// See BUG 929740.
// _threadWindowHandles is created before calling ShowDialog and is deleted in
// EnableThreadWindows (when it's called with true).
...
...
@@ -1768,8 +1768,8 @@ public bool ShowActivated
/// this <see cref="Window"/> object is modified
/// </summary>
/// <remarks>
/// This corresponds to <see cref="OnVisualChildrenChanged(DependencyObject, DependencyObject)"/>.
/// The primary consumer of this event is <see cref="System.Windows.Shell.WindowChromeWorker"/>,
/// This corresponds to <see cref="OnVisualChildrenChanged(DependencyObject, DependencyObject)"/>.
/// The primary consumer of this event is <see cref="System.Windows.Shell.WindowChromeWorker"/>,
/// which only needs to be aware of the fact that Visual children have changed, but doesn't
/// need to know which children have changed. Therefore the <see cref="DependencyObject"/>
/// parameters of <see cref="OnVisualChildrenChanged(DependencyObject, DependencyObject)"/> are
...
...
@@ -2423,7 +2423,7 @@ private void InternalDispose()
// detach all events
Utilities
.
SafeDispose
(
ref
_events
);
#endif
// NOTE:
// NOTE:
// This InternalDispose method is called while
// processing WM_DESTROY msg. Once we're done
// processing this msg, HwndWrapper does its processing.
...
...
@@ -2573,15 +2573,15 @@ internal void CreateSourceWindow(bool duringShow)
GetRequestedDimensions
(
ref
requestedLeft
,
ref
requestedTop
,
ref
requestedWidth
,
ref
requestedHeight
);
// Initially, an HWND created in a Per-Monitor Aware process may not
// have a reliable DPI. Instead, it would be associated with the monitor in which the screen point (0,0)
// Initially, an HWND created in a Per-Monitor Aware process may not
// have a reliable DPI. Instead, it would be associated with the monitor in which the screen point (0,0)
// happens to be, but the screen point corresponding to a WPF Window's (requestedLeft, requestedTop) may
// not map into that monitor. Our initial DeviceToLogicalUnits and LogicalToDeviceUnits transforms
// would normally have to rely on the DPI obtained from this HWND, which may lead us to
// an incorrect result when calculating screen points. To avoid this, we use a special heuristic here
// to identify the (screenLeft, screenTop) initially without relying on the HWND, and then
// an incorrect result when calculating screen points. To avoid this, we use a special heuristic here
// to identify the (screenLeft, screenTop) initially without relying on the HWND, and then
// supply it to HwndSourceParameters at the time of HWND creation. This would in turn set up the HWND
// with the correct DPI from the start, and all our transformations would also follow suit.
// with the correct DPI from the start, and all our transformations would also follow suit.
var
topLeftPointHelper
=
new
WindowStartupTopLeftPointHelper
(
new
Point
(
requestedLeft
,
requestedTop
));
using
(
HwndStyleManager
sm
=
HwndStyleManager
.
StartManaging
(
this
,
StyleFromHwnd
,
StyleExFromHwnd
))
...
...
@@ -2598,7 +2598,7 @@ internal void CreateSourceWindow(bool duringShow)
var
screenTopLeft
=
topLeftPointHelper
.
ScreenTopLeft
.
Value
;
param
.
SetPosition
((
int
)
screenTopLeft
.
X
,
(
int
)
screenTopLeft
.
Y
);
}
// HwndSource disposes itself when HwndWrapper process the WM_DESTROY message.
// Window sends WM_CLOSE (which in turn sends WM_DESTROY) to the hwnd when
// Window.Close() is called. Thus, this HwndSource created by window is always
...
...
@@ -2614,7 +2614,7 @@ internal void CreateSourceWindow(bool duringShow)
// the Win32 style bits.
sm
.
Dirty
=
false
;
// NOTE:
// NOTE:
// HwndSource COULD ADD STYLE/STYLEEX BITS TO THE ONES SUPPLIED. TODAY,
// HwndSource ADDS WS_CLIPCHILDREN TO THE STYLE WHICH MAY NOT
// BE REFLECTED IN OUR CACHED STYLE BITS. IF WE WERE
...
...
@@ -2931,7 +2931,7 @@ internal virtual void SetupInitialState(double requestedTop, double requestedLef
///</SecurityNote>
[
SecurityCritical
]
internal
void
SetRootVisual
()
{
{
//FxCop: ConstructorsShouldNotCallBaseClassVirtualMethods::
// System.Windows (presentationframework.dll 2 violation)
//
...
...
@@ -3846,7 +3846,7 @@ private bool CalculateWindowLocation(ref double leftDeviceUnits, ref double topD
case
WindowStartupLocation
.
Manual
:
break
;
case
WindowStartupLocation
.
CenterScreen
:
// NOTE:
// NOTE:
// Which screen to center the
// window on?
//
...
...
@@ -4270,7 +4270,7 @@ private void UpdateIcon()
[
SecurityCritical
]
private
void
SetOwnerHandle
(
IntPtr
ownerHandle
)
{
// Note:
// Note:
// "SetWindowLong failed. Error = 1400" appears in console when setting
// Window.Owner to a Window hasn't been shown (chk build)
//
...
...
@@ -4370,7 +4370,7 @@ private void OnSourceWindowDisposed(object sender, EventArgs e)
IntPtr
retInt
=
IntPtr
.
Zero
;
WindowMessage
message
=
(
WindowMessage
)
msg
;
//
//
// we need to process WM_GETMINMAXINFO before _swh is assigned to
// b/c we want to store the max/min size allowed by win32 for the hwnd
// which is later used in GetWindowMinMax. WmGetMinMaxInfo can handle
...
...
@@ -4769,7 +4769,7 @@ private bool WmSizeChanged(IntPtr wParam)
// WM_GETMINMAXINFO synchronously from CreateWindowEx thus we want
// to explicitly add the null check below, at all other places.
//
// Adding IsCompositionTargetInvalid check here
// Adding IsCompositionTargetInvalid check here
// Add this check here means that we won't fire WindowStateChanged event.
// However, since the hwnd is going away anyways, not firing StateChanged
// should not be a big deal. The other side effect is that Width/Height DPs
...
...
@@ -4855,12 +4855,12 @@ private bool WmSizeChanged(IntPtr wParam)
}
WindowState
=
WindowState
.
Maximized
;
}
// The maximizing size we get from WM_GETMINMAXINFO is only valid for the primary monitor, if the primary monitor
// The maximizing size we get from WM_GETMINMAXINFO is only valid for the primary monitor, if the primary monitor
// happens to be smaller than the secondary monitor, we may end up not maximizing correctly in the secondary monitor.
// Here we are sure that this size value is coming from the OS so it is safe to update our maximizing size.
_windowMaxWidthDeviceUnits
=
Math
.
Max
(
_windowMaxWidthDeviceUnits
,
windowSize
.
X
);
_windowMaxHeightDeviceUnits
=
Math
.
Max
(
_windowMaxHeightDeviceUnits
,
windowSize
.
Y
);
_previousWindowState
=
WindowState
.
Maximized
;
OnStateChanged
(
EventArgs
.
Empty
);
}
...
...
@@ -8255,24 +8255,24 @@ internal bool Dirty
/// <summary>
/// A helper class to convert (Left, Top) <see cref="Point"/> expressed
/// in WPF-space (1/96" units) to Screen units.
/// in WPF-space (1/96" units) to Screen units.
/// </summary>
/// <remarks>
/// Initially, an HWND created in <see cref="Window"/> in a Per-Monitor Aware process may not
/// have a relaible DPI. Instead, it would be associated with the monitor where the screen point (0,0)
/// Initially, an HWND created in <see cref="Window"/> in a Per-Monitor Aware process may not
/// have a relaible DPI. Instead, it would be associated with the monitor where the screen point (0,0)
/// happens to be, but the screen point corresponding to a WPF Window's (requestedLeft, requestedTop) may not map
/// to that monitor. Our initial DeviceToLogicalUnits and LogicalToDeviceUnits transforms
/// would normally have to rely on the DPI obtained from this HWND, which may lead us to
/// an incorrect result when calculating screen points. To avoid this, we use a special heuristic here
/// to identify the (screenLeft, screenTop) initially without relying on the HWND, and then
/// an incorrect result when calculating screen points. To avoid this, we use a special heuristic here
/// to identify the (screenLeft, screenTop) initially without relying on the HWND, and then
/// supply it to HwndSourceParameters at the time of HWND creation. This would in turn set up the HWND
/// with the correct DPI from the start, and all our transformations would also follow suit.
/// with the correct DPI from the start, and all our transformations would also follow suit.
/// </remarks>
private
class
WindowStartupTopLeftPointHelper
{
/// <summary>
/// The (Left, Top) logical point, in WPF coordinate space,
/// that must be translated into Screen space.
/// The (Left, Top) logical point, in WPF coordinate space,
/// that must be translated into Screen space.
/// </summary>
internal
Point
LogicalTopLeft
{
get
;
}
...
...
@@ -8296,9 +8296,9 @@ internal WindowStartupTopLeftPointHelper(Point topLeft)
}
/// <summary>
/// Decides whether this helper should be used.
/// This helper is used when -
/// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and
/// Decides whether this helper should be used.
/// This helper is used when -
/// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and
/// b. The process is PMA (HwndTarget.IsProcessPerMonitorDpiAware)
/// </summary>
/// <remarks>
...
...
@@ -8331,22 +8331,22 @@ private bool IsHelperNeeded
return
HwndTarget
.
IsProcessPerMonitorDpiAware
.
Value
;
}
// WPF supports Per-Monitor scaling, but HwndTarget has not
// yet been initialized with the first HWND, and therefore
// HwndTarget.IsProcessPerMonitorDpiAware is not queryable.
// Let's use the current process' DPI awareness as a proxy.
// WPF supports Per-Monitor scaling, but HwndTarget has not
// yet been initialized with the first HWND, and therefore
// HwndTarget.IsProcessPerMonitorDpiAware is not queryable.
// Let's use the current process' DPI awareness as a proxy.
return
DpiUtil
.
GetProcessDpiAwareness
(
IntPtr
.
Zero
)
==
NativeMethods
.
PROCESS_DPI_AWARENESS
.
PROCESS_PER_MONITOR_DPI_AWARE
;
}
}
/// <summary>
/// Uses EnumDisplayDevices to iterate through each monitor, and looks to see if
/// <see cref="LogicalTopLeft"/> exists within that monitor's rectangle. To do this,
/// it scales that monitors coordinate space by its corresponding DPI scale factor (this
/// Uses EnumDisplayDevices to iterate through each monitor, and looks to see if
/// <see cref="LogicalTopLeft"/> exists within that monitor's rectangle. To do this,
/// it scales that monitors coordinate space by its corresponding DPI scale factor (this
/// happens in <see cref="MonitorEnumProc(IntPtr, IntPtr, ref Runtime.InteropServices.NativeMethods.RECT, IntPtr)"/>)
/// and normalizes it to a 96 DPI space - which is the space in which WPF itself operates - and then sees whether
/// <see cref="LogicalTopLeft"/> lies within that rectangle. If it does, then it updates <see cref="ScreenTopLeft"/>
/// with the corresponding unscaled monitor-space point.
/// with the corresponding unscaled monitor-space point.
/// </summary>
/// <SecurityNote>
/// Critical - Calls into Native methods
...
...
@@ -8355,12 +8355,14 @@ private bool IsHelperNeeded
[
SecuritySafeCritical
]
private
void
IdentifyScreenTopLeft
()
{
var
hdc
=
UnsafeNativeMethods
.
GetDC
(
new
HandleRef
(
null
,
IntPtr
.
Zero
));
var
nullHandle
=
new
HandleRef
(
null
,
IntPtr
.
Zero
);
var
hdc
=
UnsafeNativeMethods
.
GetDC
(
nullHandle
);
UnsafeNativeMethods
.
EnumDisplayMonitors
(
hdc
,
IntPtr
.
Zero
,
MonitorEnumProc
,
IntPtr
.
Zero
);
UnsafeNativeMethods
.
ReleaseDC
(
nullHandle
,
new
HandleRef
(
null
,
hdc
));
}
/// <summary>
...
...
@@ -8371,11 +8373,11 @@ private void IdentifyScreenTopLeft()
/// <param name="hdcMonitor">A handle to the device context</param>
/// <param name="lprcMonitor">
/// A pointer to a RECT structure.
///
///
/// If hdcMonitor is non-NULL, this rectangle is the intersection of the clipping area of the device
/// context identified by hdcMonitor and the display monitor rectangle.The rectangle coordinates are
/// device-context coordinates.
///
///
/// If hdcMonitor is NULL, this rectangle is the display monitor rectangle. The rectangle coordinates
/// are virtual-screen coordinates.
/// </param>
...
...
@@ -8391,7 +8393,7 @@ private void IdentifyScreenTopLeft()
private
bool
MonitorEnumProc
(
IntPtr
hMonitor
,
IntPtr
hdcMonitor
,
ref
NativeMethods
.
RECT
lprcMonitor
,
IntPtr
dwData
)
{
// The call the EnumDisplayMonitors set hdc to null
// This means that hdcMonitor will be null, and
// This means that hdcMonitor will be null, and
// lprcMonitor will represent the RECT of the whole monitor
// skip the checks and trust the API contract that this will
// be so
...
...
src/Microsoft.DotNet.Wpf/src/WindowsBase/System/ComponentModel/PropertyChangedEventManager.cs
浏览文件 @
4ab8661a
...
...
@@ -188,6 +188,16 @@ protected override bool Purge(object source, object data, bool purgeAll)
{
Debug
.
Assert
(
_toRemove
.
Count
==
0
,
"to-remove list should be empty"
);
// If an "in-use" list is changed, we will re-install its clone
// back into the dictionary. Doing this inside the loop
// causes an exception "collection was modified after the enumerator
// was instantiated", so instead just record
// what to do and do the actual work after the loop.
// This is a rare case - it only arises if a PropertyChanged event
// handler calls (indirectly) into the cleanup code - so allocate
// the temporary memory lazily on the stack.
HybridDictionary
toInstall
=
null
;
// enumerate the dictionary using IDE explicitly rather than
// foreach, to avoid allocating temporary DictionaryEntry objects
IDictionaryEnumerator
ide
=
dict
.
GetEnumerator
()
as
IDictionaryEnumerator
;
...
...
@@ -207,11 +217,28 @@ protected override bool Purge(object source, object data, bool purgeAll)
{
ListenerList
list
=
(
ListenerList
)
ide
.
Value
;
if
(
ListenerList
.
PrepareForWriting
(
ref
list
))
dict
[
key
]
=
list
;
bool
inUse
=
ListenerList
.
PrepareForWriting
(
ref
list
);
bool
isChanged
=
false
;
if
(
list
.
Purge
())
{
isChanged
=
true
;
foundDirt
=
true
;
}
// if a cloned list changed, remember the details
// so that the clone can be installed back into the
// dictionary outside the iteration
if
(!
removeList
&&
inUse
&&
isChanged
)
{
if
(
toInstall
==
null
)
{
// lazy allocation
toInstall
=
new
HybridDictionary
();
}
toInstall
[
key
]
=
list
;
}
removeList
=
(
list
.
IsEmpty
);
}
...
...
@@ -234,6 +261,18 @@ protected override bool Purge(object source, object data, bool purgeAll)
_toRemove
.
TrimExcess
();
}
// do the actual re-install of "in-use" lists that changed
if
(
toInstall
!=
null
)
{
IDictionaryEnumerator
installDE
=
toInstall
.
GetEnumerator
()
as
IDictionaryEnumerator
;
while
(
installDE
.
MoveNext
())
{
String
key
=
(
String
)
installDE
.
Key
;
ListenerList
list
=
(
ListenerList
)
installDE
.
Value
;
dict
[
key
]
=
list
;
}
}
#if WeakEventTelemetry
Type
enumeratorType
=
ide
.
GetType
();
if
(
enumeratorType
.
Name
.
IndexOf
(
"NodeEnumerator"
)
>=
0
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录