Init
This commit is contained in:
111
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs
Normal file
111
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ComGuids.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
internal static partial class IID
|
||||
{
|
||||
/// <summary>IID_IEnumIDList</summary>
|
||||
public const string EnumIdList = "000214F2-0000-0000-C000-000000000046";
|
||||
/// <summary>IID_IEnumObjects</summary>
|
||||
public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e";
|
||||
/// <summary>IID_IHTMLDocument2</summary>
|
||||
public const string HtmlDocument2 = "332C4425-26CB-11D0-B483-00C04FD90119";
|
||||
/// <summary>IID_IModalWindow</summary>
|
||||
public const string ModalWindow = "b4db1657-70d7-485e-8e3e-6fcb5a5c1802";
|
||||
/// <summary>IID_IObjectArray</summary>
|
||||
public const string ObjectArray = "92CA9DCD-5622-4bba-A805-5E9F541BD8C9";
|
||||
/// <summary>IID_IObjectCollection</summary>
|
||||
public const string ObjectCollection = "5632b1a4-e38a-400a-928a-d4cd63230295";
|
||||
/// <summary>IID_IPropertyNotifySink</summary>
|
||||
public const string PropertyNotifySink = "9BFBBC02-EFF1-101A-84ED-00AA00341D07";
|
||||
/// <summary>IID_IPropertyStore</summary>
|
||||
public const string PropertyStore = "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99";
|
||||
/// <summary>IID_IServiceProvider</summary>
|
||||
public const string ServiceProvider = "6d5140c1-7436-11ce-8034-00aa006009fa";
|
||||
/// <summary>IID_IShellFolder</summary>
|
||||
public const string ShellFolder = "000214E6-0000-0000-C000-000000000046";
|
||||
/// <summary>IID_IShellLink</summary>
|
||||
public const string ShellLink = "000214F9-0000-0000-C000-000000000046";
|
||||
/// <summary>IID_IShellItem</summary>
|
||||
public const string ShellItem = "43826d1e-e718-42ee-bc55-a1e261c37bfe";
|
||||
/// <summary>IID_IShellItem2</summary>
|
||||
public const string ShellItem2 = "7e9fb0d3-919f-4307-ab2e-9b1860310c93";
|
||||
/// <summary>IID_IShellItemArray</summary>
|
||||
public const string ShellItemArray = "B63EA76D-1F85-456F-A19C-48159EFA858B";
|
||||
/// <summary>IID_ITaskbarList</summary>
|
||||
public const string TaskbarList = "56FDF342-FD6D-11d0-958A-006097C9A090";
|
||||
/// <summary>IID_ITaskbarList2</summary>
|
||||
public const string TaskbarList2 = "602D4995-B13A-429b-A66E-1935E44F4317";
|
||||
/// <summary>IID_IUnknown</summary>
|
||||
public const string Unknown = "00000000-0000-0000-C000-000000000046";
|
||||
|
||||
#region Win7 IIDs
|
||||
|
||||
/// <summary>IID_IApplicationDestinations</summary>
|
||||
public const string ApplicationDestinations = "12337d35-94c6-48a0-bce7-6a9c69d4d600";
|
||||
/// <summary>IID_IApplicationDocumentLists</summary>
|
||||
public const string ApplicationDocumentLists = "3c594f9f-9f30-47a1-979a-c9e83d3d0a06";
|
||||
/// <summary>IID_ICustomDestinationList</summary>
|
||||
public const string CustomDestinationList = "6332debf-87b5-4670-90c0-5e57b408a49e";
|
||||
/// <summary>IID_IObjectWithAppUserModelID</summary>
|
||||
public const string ObjectWithAppUserModelId = "36db0196-9665-46d1-9ba7-d3709eecf9ed";
|
||||
/// <summary>IID_IObjectWithProgID</summary>
|
||||
public const string ObjectWithProgId = "71e806fb-8dee-46fc-bf8c-7748a8a1ae13";
|
||||
/// <summary>IID_ITaskbarList3</summary>
|
||||
public const string TaskbarList3 = "ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf";
|
||||
/// <summary>IID_ITaskbarList4</summary>
|
||||
public const string TaskbarList4 = "c43dc798-95d1-4bea-9030-bb99e2983a1a";
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal static partial class CLSID
|
||||
{
|
||||
public static T CoCreateInstance<T>(string clsid)
|
||||
{
|
||||
return (T)System.Activator.CreateInstance(System.Type.GetTypeFromCLSID(new System.Guid(clsid)));
|
||||
}
|
||||
|
||||
/// <summary>CLSID_TaskbarList</summary>
|
||||
/// <remarks>IID_ITaskbarList</remarks>
|
||||
public const string TaskbarList = "56FDF344-FD6D-11d0-958A-006097C9A090";
|
||||
/// <summary>CLSID_EnumerableObjectCollection</summary>
|
||||
/// <remarks>IID_IEnumObjects.</remarks>
|
||||
public const string EnumerableObjectCollection = "2d3468c1-36a7-43b6-ac24-d3f02fd9607a";
|
||||
/// <summary>CLSID_ShellLink</summary>
|
||||
/// <remarks>IID_IShellLink</remarks>
|
||||
public const string ShellLink = "00021401-0000-0000-C000-000000000046";
|
||||
|
||||
#region Win7 CLSIDs
|
||||
|
||||
/// <summary>CLSID_DestinationList</summary>
|
||||
/// <remarks>IID_ICustomDestinationList</remarks>
|
||||
public const string DestinationList = "77f10cf0-3db5-4966-b520-b7c54fd35ed6";
|
||||
/// <summary>CLSID_ApplicationDestinations</summary>
|
||||
/// <remarks>IID_IApplicationDestinations</remarks>
|
||||
public const string ApplicationDestinations = "86c14003-4d6b-4ef3-a7b4-0506663b2e68";
|
||||
/// <summary>CLSID_ApplicationDocumentLists</summary>
|
||||
/// <remarks>IID_IApplicationDocumentLists</remarks>
|
||||
public const string ApplicationDocumentLists = "86bec222-30f2-47e0-9f25-60d11cd75c28";
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
389
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs
Normal file
389
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Debug.cs
Normal file
@@ -0,0 +1,389 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
// Conditional to use more aggressive fail-fast behaviors when debugging.
|
||||
#define DEV_DEBUG
|
||||
|
||||
// This file contains general utilities to aid in development.
|
||||
// It is distinct from unit test Assert classes.
|
||||
// Classes here generally shouldn't be exposed publicly since
|
||||
// they're not particular to any library functionality.
|
||||
// Because the classes here are internal, it's likely this file
|
||||
// might be included in multiple assemblies.
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>A static class for verifying assumptions.</summary>
|
||||
internal static class Assert
|
||||
{
|
||||
private static void _Break()
|
||||
{
|
||||
#if DEV_DEBUG
|
||||
Debugger.Break();
|
||||
#else
|
||||
Debug.Assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>A function signature for Assert.Evaluate.</summary>
|
||||
public delegate void EvaluateFunction();
|
||||
|
||||
/// <summary>A function signature for Assert.Implies.</summary>
|
||||
/// <returns>Returns the truth of a predicate.</returns>
|
||||
public delegate bool ImplicationFunction();
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified argument.
|
||||
/// </summary>
|
||||
/// <param name="argument">The function to execute.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Evaluate(EvaluateFunction argument)
|
||||
{
|
||||
IsNotNull(argument);
|
||||
argument();
|
||||
}
|
||||
|
||||
/// <summary>Obsolete: Use Standard.Assert.AreEqual instead of Assert.Equals</summary>
|
||||
/// <typeparam name="T">The generic type to compare for equality.</typeparam>
|
||||
/// <param name="expected">The first generic type data to compare. This is is the expected value.</param>
|
||||
/// <param name="actual">The second generic type data to compare. This is the actual value.</param>
|
||||
[
|
||||
Obsolete("Use Assert.AreEqual instead of Assert.Equals", false),
|
||||
Conditional("DEBUG")
|
||||
]
|
||||
public static void Equals<T>(T expected, T actual)
|
||||
{
|
||||
AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that two generic type data are equal. The assertion fails if they are not.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The generic type to compare for equality.</typeparam>
|
||||
/// <param name="expected">The first generic type data to compare. This is is the expected value.</param>
|
||||
/// <param name="actual">The second generic type data to compare. This is the actual value.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void AreEqual<T>(T expected, T actual)
|
||||
{
|
||||
if (null == expected)
|
||||
{
|
||||
// Two nulls are considered equal, regardless of type semantics.
|
||||
if (null != actual && !actual.Equals(expected))
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
else if (!expected.Equals(actual))
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that two generic type data are not equal. The assertion fails if they are.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The generic type to compare for inequality.</typeparam>
|
||||
/// <param name="notExpected">The first generic type data to compare. This is is the value that's not expected.</param>
|
||||
/// <param name="actual">The second generic type data to compare. This is the actual value.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void AreNotEqual<T>(T notExpected, T actual)
|
||||
{
|
||||
if (null == notExpected)
|
||||
{
|
||||
// Two nulls are considered equal, regardless of type semantics.
|
||||
if (null == actual || actual.Equals(notExpected))
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
else if (notExpected.Equals(actual))
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that if the specified condition is true, then so is the result.
|
||||
/// The assertion fails if the condition is true but the result is false.
|
||||
/// </summary>
|
||||
/// <param name="condition">if set to <c>true</c> [condition].</param>
|
||||
/// <param name="result">
|
||||
/// A second Boolean statement. If the first was true then so must this be.
|
||||
/// If the first statement was false then the value of this is ignored.
|
||||
/// </param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Implies(bool condition, bool result)
|
||||
{
|
||||
if (condition && !result)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lazy evaluation overload. Verifies that if a condition is true, then so is a secondary value.
|
||||
/// </summary>
|
||||
/// <param name="condition">The conditional value.</param>
|
||||
/// <param name="result">A function to be evaluated for truth if the condition argument is true.</param>
|
||||
/// <remarks>
|
||||
/// This overload only evaluates the result if the first condition is true.
|
||||
/// </remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Implies(bool condition, ImplicationFunction result)
|
||||
{
|
||||
if (condition && !result())
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a string has content. I.e. it is not null and it is not empty.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to verify.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNeitherNullNorEmpty(string value)
|
||||
{
|
||||
IsFalse(string.IsNullOrEmpty(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a string has content. I.e. it is not null and it is not purely whitespace.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to verify.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNeitherNullNorWhitespace(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
|
||||
if (value.Trim().Length == 0)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the specified value is not null. The assertion fails if it is.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The generic reference type.</typeparam>
|
||||
/// <param name="value">The value to check for nullness.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNotNull<T>(T value) where T : class
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsDefault<T>(T value) where T : struct
|
||||
{
|
||||
if (!value.Equals(default(T)))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNotDefault<T>(T value) where T : struct
|
||||
{
|
||||
if (value.Equals(default(T)))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified condition is false. The assertion fails if it is true.
|
||||
/// </summary>
|
||||
/// <param name="condition">The expression that should be <c>false</c>.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsFalse(bool condition)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified condition is false. The assertion fails if it is true.
|
||||
/// </summary>
|
||||
/// <param name="condition">The expression that should be <c>false</c>.</param>
|
||||
/// <param name="message">The message to display if the condition is <c>true</c>.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsFalse(bool condition, string message)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified condition is true. The assertion fails if it is not.
|
||||
/// </summary>
|
||||
/// <param name="condition">A condition that is expected to be <c>true</c>.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsTrue(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified condition is true. The assertion fails if it is not.
|
||||
/// </summary>
|
||||
/// <param name="condition">A condition that is expected to be <c>true</c>.</param>
|
||||
/// <param name="message">The message to write in case the condition is <c>false</c>.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsTrue(bool condition, string message)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This line should never be executed. The assertion always fails.
|
||||
/// </summary>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Fail()
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This line should never be executed. The assertion always fails.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to display if this function is executed.</param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Fail(string message)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified object is null. The assertion fails if it is not.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to verify is null.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNull<T>(T item) where T : class
|
||||
{
|
||||
if (null != item)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified value is within the expected range. The assertion fails if it isn't.
|
||||
/// </summary>
|
||||
/// <param name="lowerBoundInclusive">The lower bound inclusive value.</param>
|
||||
/// <param name="value">The value to verify.</param>
|
||||
/// <param name="upperBoundInclusive">The upper bound inclusive value.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void BoundedDoubleInc(double lowerBoundInclusive, double value, double upperBoundInclusive)
|
||||
{
|
||||
if (value < lowerBoundInclusive || value > upperBoundInclusive)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified value is within the expected range. The assertion fails if it isn't.
|
||||
/// </summary>
|
||||
/// <param name="lowerBoundInclusive">The lower bound inclusive value.</param>
|
||||
/// <param name="value">The value to verify.</param>
|
||||
/// <param name="upperBoundExclusive">The upper bound exclusive value.</param>
|
||||
[Conditional("DEBUG")]
|
||||
public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive)
|
||||
{
|
||||
if (value < lowerBoundInclusive || value >= upperBoundExclusive)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the current thread's apartment state is what's expected. The assertion fails if it isn't
|
||||
/// </summary>
|
||||
/// <param name="expectedState">
|
||||
/// The expected apartment state for the current thread.
|
||||
/// </param>
|
||||
/// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsApartmentState(ApartmentState expectedState)
|
||||
{
|
||||
if (Thread.CurrentThread.GetApartmentState() != expectedState)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void NullableIsNotNull<T>(T? value) where T : struct
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void NullableIsNull<T>(T? value) where T : struct
|
||||
{
|
||||
if (null != value)
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void IsNotOnMainThread()
|
||||
{
|
||||
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
|
||||
{
|
||||
_Break();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
148
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs
Normal file
148
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DoubleUtil.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles.
|
||||
/// Note that FP noise is a big problem and using any of these compare
|
||||
/// methods is not a complete solution, but rather the way to reduce
|
||||
/// the probability of repeating unnecessary work.
|
||||
/// </summary>
|
||||
internal static class DoubleUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Epsilon - more or less random, more or less small number.
|
||||
/// </summary>
|
||||
private const double Epsilon = 0.00000153;
|
||||
|
||||
/// <summary>
|
||||
/// AreClose returns whether or not two doubles are "close". That is, whether or
|
||||
/// not they are within epsilon of each other.
|
||||
/// There are plenty of ways for this to return false even for numbers which
|
||||
/// are theoretically identical, so no code calling this should fail to work if this
|
||||
/// returns false.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first double to compare.</param>
|
||||
/// <param name="value2">The second double to compare.</param>
|
||||
/// <returns>The result of the AreClose comparision.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool AreClose(double value1, double value2)
|
||||
{
|
||||
if (value1 == value2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double delta = value1 - value2;
|
||||
return (delta < Epsilon) && (delta > -Epsilon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LessThan returns whether or not the first double is less than the second double.
|
||||
/// That is, whether or not the first is strictly less than *and* not within epsilon of
|
||||
/// the other number.
|
||||
/// There are plenty of ways for this to return false even for numbers which
|
||||
/// are theoretically identical, so no code calling this should fail to work if this
|
||||
/// returns false.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first double to compare.</param>
|
||||
/// <param name="value2">The second double to compare.</param>
|
||||
/// <returns>The result of the LessThan comparision.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool LessThan(double value1, double value2)
|
||||
{
|
||||
return (value1 < value2) && !AreClose(value1, value2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GreaterThan returns whether or not the first double is greater than the second double.
|
||||
/// That is, whether or not the first is strictly greater than *and* not within epsilon of
|
||||
/// the other number.
|
||||
/// There are plenty of ways for this to return false even for numbers which
|
||||
/// are theoretically identical, so no code calling this should fail to work if this
|
||||
/// returns false.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first double to compare.</param>
|
||||
/// <param name="value2">The second double to compare.</param>
|
||||
/// <returns>The result of the GreaterThan comparision.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool GreaterThan(double value1, double value2)
|
||||
{
|
||||
return (value1 > value2) && !AreClose(value1, value2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LessThanOrClose returns whether or not the first double is less than or close to
|
||||
/// the second double. That is, whether or not the first is strictly less than or within
|
||||
/// epsilon of the other number.
|
||||
/// There are plenty of ways for this to return false even for numbers which
|
||||
/// are theoretically identical, so no code calling this should fail to work if this
|
||||
/// returns false.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first double to compare.</param>
|
||||
/// <param name="value2">The second double to compare.</param>
|
||||
/// <returns>The result of the LessThanOrClose comparision.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool LessThanOrClose(double value1, double value2)
|
||||
{
|
||||
return (value1 < value2) || AreClose(value1, value2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GreaterThanOrClose returns whether or not the first double is greater than or close to
|
||||
/// the second double. That is, whether or not the first is strictly greater than or within
|
||||
/// epsilon of the other number.
|
||||
/// There are plenty of ways for this to return false even for numbers which
|
||||
/// are theoretically identical, so no code calling this should fail to work if this
|
||||
/// returns false.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first double to compare.</param>
|
||||
/// <param name="value2">The second double to compare.</param>
|
||||
/// <returns>The result of the GreaterThanOrClose comparision.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool GreaterThanOrClose(double value1, double value2)
|
||||
{
|
||||
return (value1 > value2) || AreClose(value1, value2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a double is a finite number (is not NaN or Infinity).
|
||||
/// </summary>
|
||||
/// <param name='value'>The value to test.</param>
|
||||
/// <returns>Whether or not the value is a finite number.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool IsFinite(double value)
|
||||
{
|
||||
return !double.IsNaN(value) && !double.IsInfinity(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a double a valid size value (is finite and > 0).
|
||||
/// </summary>
|
||||
/// <param name='value'>The value to test.</param>
|
||||
/// <returns>Whether or not the value is a valid size value.</returns>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static bool IsValidSize(double value)
|
||||
{
|
||||
return IsFinite(value) && GreaterThanOrClose(value, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs
Normal file
102
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/DpiHelper.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
internal static class DpiHelper
|
||||
{
|
||||
private static Matrix _transformToDevice;
|
||||
private static Matrix _transformToDip;
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
|
||||
static DpiHelper()
|
||||
{
|
||||
using (SafeDC desktop = SafeDC.GetDesktop())
|
||||
{
|
||||
// Can get these in the static constructor. They shouldn't vary window to window,
|
||||
// and changing the system DPI requires a restart.
|
||||
int pixelsPerInchX = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSX);
|
||||
int pixelsPerInchY = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSY);
|
||||
|
||||
_transformToDip = Matrix.Identity;
|
||||
_transformToDip.Scale(96d / (double)pixelsPerInchX, 96d / (double)pixelsPerInchY);
|
||||
_transformToDevice = Matrix.Identity;
|
||||
_transformToDevice.Scale((double)pixelsPerInchX / 96d, (double)pixelsPerInchY / 96d);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a point in device independent pixels (1/96") to a point in the system coordinates.
|
||||
/// </summary>
|
||||
/// <param name="logicalPoint">A point in the logical coordinate system.</param>
|
||||
/// <returns>Returns the parameter converted to the system's coordinates.</returns>
|
||||
public static Point LogicalPixelsToDevice(Point logicalPoint)
|
||||
{
|
||||
return _transformToDevice.Transform(logicalPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a point in system coordinates to a point in device independent pixels (1/96").
|
||||
/// </summary>
|
||||
/// <param name="logicalPoint">A point in the physical coordinate system.</param>
|
||||
/// <returns>Returns the parameter converted to the device independent coordinate system.</returns>
|
||||
public static Point DevicePixelsToLogical(Point devicePoint)
|
||||
{
|
||||
return _transformToDip.Transform(devicePoint);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static Rect LogicalRectToDevice(Rect logicalRectangle)
|
||||
{
|
||||
Point topLeft = LogicalPixelsToDevice(new Point(logicalRectangle.Left, logicalRectangle.Top));
|
||||
Point bottomRight = LogicalPixelsToDevice(new Point(logicalRectangle.Right, logicalRectangle.Bottom));
|
||||
|
||||
return new Rect(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
public static Rect DeviceRectToLogical(Rect deviceRectangle)
|
||||
{
|
||||
Point topLeft = DevicePixelsToLogical(new Point(deviceRectangle.Left, deviceRectangle.Top));
|
||||
Point bottomRight = DevicePixelsToLogical(new Point(deviceRectangle.Right, deviceRectangle.Bottom));
|
||||
|
||||
return new Rect(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
public static Size LogicalSizeToDevice(Size logicalSize)
|
||||
{
|
||||
Point pt = LogicalPixelsToDevice(new Point(logicalSize.Width, logicalSize.Height));
|
||||
|
||||
return new Size { Width = pt.X, Height = pt.Y };
|
||||
}
|
||||
|
||||
public static Size DeviceSizeToLogical(Size deviceSize)
|
||||
{
|
||||
Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height));
|
||||
|
||||
return new Size(pt.X, pt.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
524
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs
Normal file
524
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/ErrorCodes.cs
Normal file
@@ -0,0 +1,524 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for common Win32 status codes.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct Win32Error
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _value;
|
||||
|
||||
// NOTE: These public static field declarations are automatically
|
||||
// picked up by (HRESULT's) ToString through reflection.
|
||||
|
||||
/// <summary>The operation completed successfully.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_SUCCESS = new Win32Error(0);
|
||||
/// <summary>Incorrect function.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error(1);
|
||||
/// <summary>The system cannot find the file specified.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error(2);
|
||||
/// <summary>The system cannot find the path specified.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error(3);
|
||||
/// <summary>The system cannot open the file.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error(4);
|
||||
/// <summary>Access is denied.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error(5);
|
||||
/// <summary>The handle is invalid.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error(6);
|
||||
/// <summary>Not enough storage is available to complete this operation.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error(14);
|
||||
/// <summary>There are no more files.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error(18);
|
||||
/// <summary>The process cannot access the file because it is being used by another process.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error(32);
|
||||
/// <summary>The parameter is incorrect.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error(87);
|
||||
/// <summary>The data area passed to a system call is too small.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_INSUFFICIENT_BUFFER = new Win32Error(122);
|
||||
/// <summary>Cannot nest calls to LoadModule.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_NESTING_NOT_ALLOWED = new Win32Error(215);
|
||||
/// <summary>Illegal operation attempted on a registry key that has been marked for deletion.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_KEY_DELETED = new Win32Error(1018);
|
||||
/// <summary>Element not found.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_NOT_FOUND = new Win32Error(1168);
|
||||
/// <summary>There was no match for the specified key in the index.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_NO_MATCH = new Win32Error(1169);
|
||||
/// <summary>An invalid device was specified.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_BAD_DEVICE = new Win32Error(1200);
|
||||
/// <summary>The operation was canceled by the user.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_CANCELLED = new Win32Error(1223);
|
||||
/// <summary>The window class was already registered.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_CLASS_ALREADY_EXISTS = new Win32Error(1410);
|
||||
/// <summary>The specified datatype is invalid.</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly Win32Error ERROR_INVALID_DATATYPE = new Win32Error(1804);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Win32 error.
|
||||
/// </summary>
|
||||
/// <param name="i">The integer value of the error.</param>
|
||||
public Win32Error(int i)
|
||||
{
|
||||
_value = i;
|
||||
}
|
||||
|
||||
/// <summary>Performs HRESULT_FROM_WIN32 conversion.</summary>
|
||||
/// <param name="error">The Win32 error being converted to an HRESULT.</param>
|
||||
/// <returns>The equivilent HRESULT value.</returns>
|
||||
public static explicit operator HRESULT(Win32Error error)
|
||||
{
|
||||
// #define __HRESULT_FROM_WIN32(x)
|
||||
// ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
|
||||
if (error._value <= 0)
|
||||
{
|
||||
return new HRESULT((uint)error._value);
|
||||
}
|
||||
return HRESULT.Make(true, Facility.Win32, error._value & 0x0000FFFF);
|
||||
}
|
||||
|
||||
// Method version of the cast operation
|
||||
/// <summary>Performs HRESULT_FROM_WIN32 conversion.</summary>
|
||||
/// <param name="error">The Win32 error being converted to an HRESULT.</param>
|
||||
/// <returns>The equivilent HRESULT value.</returns>
|
||||
public HRESULT ToHRESULT()
|
||||
{
|
||||
return (HRESULT)this;
|
||||
}
|
||||
|
||||
/// <summary>Performs the equivalent of Win32's GetLastError()</summary>
|
||||
/// <returns>A Win32Error instance with the result of the native GetLastError</returns>
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public static Win32Error GetLastError()
|
||||
{
|
||||
return new Win32Error(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ((Win32Error)obj)._value == _value;
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two Win32 error codes for equality.
|
||||
/// </summary>
|
||||
/// <param name="errLeft">The first error code to compare.</param>
|
||||
/// <param name="errRight">The second error code to compare.</param>
|
||||
/// <returns>Whether the two error codes are the same.</returns>
|
||||
public static bool operator ==(Win32Error errLeft, Win32Error errRight)
|
||||
{
|
||||
return errLeft._value == errRight._value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two Win32 error codes for inequality.
|
||||
/// </summary>
|
||||
/// <param name="errLeft">The first error code to compare.</param>
|
||||
/// <param name="errRight">The second error code to compare.</param>
|
||||
/// <returns>Whether the two error codes are not the same.</returns>
|
||||
public static bool operator !=(Win32Error errLeft, Win32Error errRight)
|
||||
{
|
||||
return !(errLeft == errRight);
|
||||
}
|
||||
}
|
||||
|
||||
internal enum Facility
|
||||
{
|
||||
/// <summary>FACILITY_NULL</summary>
|
||||
Null = 0,
|
||||
/// <summary>FACILITY_RPC</summary>
|
||||
Rpc = 1,
|
||||
/// <summary>FACILITY_DISPATCH</summary>
|
||||
Dispatch = 2,
|
||||
/// <summary>FACILITY_STORAGE</summary>
|
||||
Storage = 3,
|
||||
/// <summary>FACILITY_ITF</summary>
|
||||
Itf = 4,
|
||||
/// <summary>FACILITY_WIN32</summary>
|
||||
Win32 = 7,
|
||||
/// <summary>FACILITY_WINDOWS</summary>
|
||||
Windows = 8,
|
||||
/// <summary>FACILITY_CONTROL</summary>
|
||||
Control = 10,
|
||||
/// <summary>MSDN doced facility code for ESE errors.</summary>
|
||||
Ese = 0xE5E,
|
||||
/// <summary>FACILITY_WINCODEC (WIC)</summary>
|
||||
WinCodec = 0x898,
|
||||
}
|
||||
|
||||
/// <summary>Wrapper for HRESULT status codes.</summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct HRESULT
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly uint _value;
|
||||
|
||||
// NOTE: These public static field declarations are automatically
|
||||
// picked up by ToString through reflection.
|
||||
/// <summary>S_OK</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT S_OK = new HRESULT(0x00000000);
|
||||
/// <summary>S_FALSE</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT S_FALSE = new HRESULT(0x00000001);
|
||||
/// <summary>E_PENDING</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_PENDING = new HRESULT(0x8000000A);
|
||||
/// <summary>E_NOTIMPL</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_NOTIMPL = new HRESULT(0x80004001);
|
||||
/// <summary>E_NOINTERFACE</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_NOINTERFACE = new HRESULT(0x80004002);
|
||||
/// <summary>E_POINTER</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_POINTER = new HRESULT(0x80004003);
|
||||
/// <summary>E_ABORT</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_ABORT = new HRESULT(0x80004004);
|
||||
/// <summary>E_FAIL</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_FAIL = new HRESULT(0x80004005);
|
||||
/// <summary>E_UNEXPECTED</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_UNEXPECTED = new HRESULT(0x8000FFFF);
|
||||
/// <summary>STG_E_INVALIDFUNCTION</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT STG_E_INVALIDFUNCTION = new HRESULT(0x80030001);
|
||||
/// <summary>REGDB_E_CLASSNOTREG</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT REGDB_E_CLASSNOTREG = new HRESULT(0x80040154);
|
||||
|
||||
/// <summary>DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists.</summary>
|
||||
/// <remarks>There is no Assoc Handler for the given item registered by the specified application.</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT DESTS_E_NO_MATCHING_ASSOC_HANDLER = new HRESULT(0x80040F03);
|
||||
/// <summary>DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists.</summary>
|
||||
/// <remarks>The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration.</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT DESTS_E_NORECDOCS = new HRESULT(0x80040F04);
|
||||
/// <summary>DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists.</summary>
|
||||
/// <remarks>Not all of the items were successfully cleared</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT DESTS_E_NOTALLCLEARED = new HRESULT(0x80040F05);
|
||||
|
||||
/// <summary>E_ACCESSDENIED</summary>
|
||||
/// <remarks>Win32Error ERROR_ACCESS_DENIED.</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_ACCESSDENIED = new HRESULT(0x80070005);
|
||||
/// <summary>E_OUTOFMEMORY</summary>
|
||||
/// <remarks>Win32Error ERROR_OUTOFMEMORY.</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_OUTOFMEMORY = new HRESULT(0x8007000E);
|
||||
/// <summary>E_INVALIDARG</summary>
|
||||
/// <remarks>Win32Error ERROR_INVALID_PARAMETER.</remarks>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT E_INVALIDARG = new HRESULT(0x80070057);
|
||||
/// <summary>INTSAFE_E_ARITHMETIC_OVERFLOW</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT INTSAFE_E_ARITHMETIC_OVERFLOW = new HRESULT(0x80070216);
|
||||
/// <summary>COR_E_OBJECTDISPOSED</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT COR_E_OBJECTDISPOSED = new HRESULT(0x80131622);
|
||||
/// <summary>WC_E_GREATERTHAN</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT WC_E_GREATERTHAN = new HRESULT(0xC00CEE23);
|
||||
/// <summary>WC_E_SYNTAX</summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||
public static readonly HRESULT WC_E_SYNTAX = new HRESULT(0xC00CEE2D);
|
||||
|
||||
/// <summary>
|
||||
/// Create an HRESULT from an integer value.
|
||||
/// </summary>
|
||||
/// <param name="i"></param>
|
||||
public HRESULT(uint i)
|
||||
{
|
||||
_value = i;
|
||||
}
|
||||
|
||||
public static HRESULT Make(bool severe, Facility facility, int code)
|
||||
{
|
||||
// #define MAKE_HRESULT(sev,fac,code) \
|
||||
// ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
|
||||
|
||||
// Severity has 1 bit reserved.
|
||||
// bitness is enforced by the boolean parameter.
|
||||
|
||||
// Facility has 11 bits reserved (different than SCODES, which have 4 bits reserved)
|
||||
// MSDN documentation incorrectly uses 12 bits for the ESE facility (e5e), so go ahead and let that one slide.
|
||||
// And WIC also ignores it the documented size...
|
||||
Assert.Implies((int)facility != (int)((int)facility & 0x1FF), facility == Facility.Ese || facility == Facility.WinCodec);
|
||||
// Code has 4 bits reserved.
|
||||
Assert.AreEqual(code, code & 0xFFFF);
|
||||
|
||||
return new HRESULT((uint)((severe ? (1 << 31) : 0) | ((int)facility << 16) | code));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieve HRESULT_FACILITY
|
||||
/// </summary>
|
||||
public Facility Facility
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetFacility((int)_value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Facility GetFacility(int errorCode)
|
||||
{
|
||||
// #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
|
||||
return (Facility)((errorCode >> 16) & 0x1fff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieve HRESULT_CODE
|
||||
/// </summary>
|
||||
public int Code
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetCode((int)_value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetCode(int error)
|
||||
{
|
||||
// #define HRESULT_CODE(hr) ((hr) & 0xFFFF)
|
||||
return (int)(error & 0xFFFF);
|
||||
}
|
||||
|
||||
#region Object class override members
|
||||
|
||||
/// <summary>
|
||||
/// Get a string representation of this HRESULT.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
// Use reflection to try to name this HRESULT.
|
||||
// This is expensive, but if someone's ever printing HRESULT strings then
|
||||
// I think it's a fair guess that they're not in a performance critical area
|
||||
// (e.g. printing exception strings).
|
||||
// This is less error prone than trying to keep the list in the function.
|
||||
// To properly add an HRESULT's name to the ToString table, just add the HRESULT
|
||||
// like all the others above.
|
||||
//
|
||||
// CONSIDER: This data is static. It could be cached
|
||||
// after first usage for fast lookup since the keys are unique.
|
||||
//
|
||||
foreach (FieldInfo publicStaticField in typeof(HRESULT).GetFields(BindingFlags.Static | BindingFlags.Public))
|
||||
{
|
||||
if (publicStaticField.FieldType == typeof(HRESULT))
|
||||
{
|
||||
var hr = (HRESULT)publicStaticField.GetValue(null);
|
||||
if (hr == this)
|
||||
{
|
||||
return publicStaticField.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try Win32 error codes also
|
||||
if (Facility == Facility.Win32)
|
||||
{
|
||||
foreach (FieldInfo publicStaticField in typeof(Win32Error).GetFields(BindingFlags.Static | BindingFlags.Public))
|
||||
{
|
||||
if (publicStaticField.FieldType == typeof(Win32Error))
|
||||
{
|
||||
var error = (Win32Error)publicStaticField.GetValue(null);
|
||||
if ((HRESULT)error == this)
|
||||
{
|
||||
return "HRESULT_FROM_WIN32(" + publicStaticField.Name + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no good name for this HRESULT,
|
||||
// return the string as readable hex (0x########) format.
|
||||
return string.Format(CultureInfo.InvariantCulture, "0x{0:X8}", _value);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ((HRESULT)obj)._value == _value;
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static bool operator ==(HRESULT hrLeft, HRESULT hrRight)
|
||||
{
|
||||
return hrLeft._value == hrRight._value;
|
||||
}
|
||||
|
||||
public static bool operator !=(HRESULT hrLeft, HRESULT hrRight)
|
||||
{
|
||||
return !(hrLeft == hrRight);
|
||||
}
|
||||
|
||||
public bool Succeeded
|
||||
{
|
||||
get { return (int)_value >= 0; }
|
||||
}
|
||||
|
||||
public bool Failed
|
||||
{
|
||||
get { return (int)_value < 0; }
|
||||
}
|
||||
|
||||
public void ThrowIfFailed()
|
||||
{
|
||||
ThrowIfFailed(null);
|
||||
}
|
||||
|
||||
[
|
||||
SuppressMessage(
|
||||
"Microsoft.Usage",
|
||||
"CA2201:DoNotRaiseReservedExceptionTypes",
|
||||
Justification="Only recreating Exceptions that were already raised."),
|
||||
SuppressMessage(
|
||||
"Microsoft.Security",
|
||||
"CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")
|
||||
]
|
||||
public void ThrowIfFailed(string message)
|
||||
{
|
||||
if (Failed)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
message = ToString();
|
||||
}
|
||||
#if DEBUG
|
||||
else
|
||||
{
|
||||
message += " (" + ToString() + ")";
|
||||
}
|
||||
#endif
|
||||
// Wow. Reflection in a throw call. Later on this may turn out to have been a bad idea.
|
||||
// If you're throwing an exception I assume it's OK for me to take some time to give it back.
|
||||
// I want to convert the HRESULT to a more appropriate exception type than COMException.
|
||||
// Marshal.ThrowExceptionForHR does this for me, but the general call uses GetErrorInfo
|
||||
// if it's set, and then ignores the HRESULT that I've provided. This makes it so this
|
||||
// call works the first time but you get burned on the second. To avoid this, I use
|
||||
// the overload that explicitly ignores the IErrorInfo.
|
||||
// In addition, the function doesn't allow me to set the Message unless I go through
|
||||
// the process of implementing an IErrorInfo and then use that. There's no stock
|
||||
// implementations of IErrorInfo available and I don't think it's worth the maintenance
|
||||
// overhead of doing it, nor would it have significant value over this approach.
|
||||
Exception e = Marshal.GetExceptionForHR((int)_value, new IntPtr(-1));
|
||||
Assert.IsNotNull(e);
|
||||
// ArgumentNullException doesn't have the right constructor parameters,
|
||||
// (nor does Win32Exception...)
|
||||
// but E_POINTER gets mapped to NullReferenceException,
|
||||
// so I don't think it will ever matter.
|
||||
Assert.IsFalse(e is ArgumentNullException);
|
||||
|
||||
// If we're not getting anything better than a COMException from Marshal,
|
||||
// then at least check the facility and attempt to do better ourselves.
|
||||
if (e.GetType() == typeof(COMException))
|
||||
{
|
||||
switch (Facility)
|
||||
{
|
||||
case Facility.Win32:
|
||||
e = new Win32Exception(Code, message);
|
||||
break;
|
||||
default:
|
||||
e = new COMException(message, (int)_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstructorInfo cons = e.GetType().GetConstructor(new[] { typeof(string) });
|
||||
if (null != cons)
|
||||
{
|
||||
e = cons.Invoke(new object[] { message }) as Exception;
|
||||
Assert.IsNotNull(e);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the result of Win32 GetLastError() into a raised exception.
|
||||
/// </summary>
|
||||
public static void ThrowLastError()
|
||||
{
|
||||
((HRESULT)Win32Error.GetLastError()).ThrowIfFailed();
|
||||
// Only expecting to call this when we're expecting a failed GetLastError()
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
internal sealed class MessageWindow : DispatcherObject, IDisposable
|
||||
{
|
||||
// Alias this to a static so the wrapper doesn't get GC'd
|
||||
private static readonly WndProc s_WndProc = new WndProc(_WndProc);
|
||||
private static readonly Dictionary<IntPtr, MessageWindow> s_windowLookup = new Dictionary<IntPtr, MessageWindow>();
|
||||
|
||||
private WndProc _wndProcCallback;
|
||||
private string _className;
|
||||
private bool _isDisposed;
|
||||
|
||||
public IntPtr Handle { get; private set; }
|
||||
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public MessageWindow(CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback)
|
||||
{
|
||||
// A null callback means just use DefWindowProc.
|
||||
_wndProcCallback = callback;
|
||||
_className = "MessageWindowClass+" + Guid.NewGuid().ToString();
|
||||
|
||||
var wc = new WNDCLASSEX
|
||||
{
|
||||
cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)),
|
||||
style = classStyle,
|
||||
lpfnWndProc = s_WndProc,
|
||||
hInstance = NativeMethods.GetModuleHandle(null),
|
||||
hbrBackground = NativeMethods.GetStockObject(StockObject.NULL_BRUSH),
|
||||
lpszMenuName = "",
|
||||
lpszClassName = _className,
|
||||
};
|
||||
|
||||
NativeMethods.RegisterClassEx(ref wc);
|
||||
|
||||
GCHandle gcHandle = default(GCHandle);
|
||||
try
|
||||
{
|
||||
gcHandle = GCHandle.Alloc(this);
|
||||
IntPtr pinnedThisPtr = (IntPtr)gcHandle;
|
||||
|
||||
Handle = NativeMethods.CreateWindowEx(
|
||||
exStyle,
|
||||
_className,
|
||||
name,
|
||||
style,
|
||||
(int)location.X,
|
||||
(int)location.Y,
|
||||
(int)location.Width,
|
||||
(int)location.Height,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
pinnedThisPtr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
gcHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
~MessageWindow()
|
||||
{
|
||||
_Dispose(false, false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_Dispose(true, false);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// This isn't right if the Dispatcher has already started shutting down.
|
||||
// It will wind up leaking the class ATOM...
|
||||
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")]
|
||||
private void _Dispose(bool disposing, bool isHwndBeingDestroyed)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
// Block against reentrancy.
|
||||
return;
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
|
||||
IntPtr hwnd = Handle;
|
||||
string className = _className;
|
||||
|
||||
if (isHwndBeingDestroyed)
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(IntPtr.Zero, className)));
|
||||
}
|
||||
else if (Handle != IntPtr.Zero)
|
||||
{
|
||||
if (CheckAccess())
|
||||
{
|
||||
_DestroyWindow(hwnd, className);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(hwnd, className)));
|
||||
}
|
||||
}
|
||||
|
||||
s_windowLookup.Remove(hwnd);
|
||||
|
||||
_className = null;
|
||||
Handle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")]
|
||||
private static IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
IntPtr ret = IntPtr.Zero;
|
||||
MessageWindow hwndWrapper = null;
|
||||
|
||||
if (msg == WM.CREATE)
|
||||
{
|
||||
var createStruct = (CREATESTRUCT)Marshal.PtrToStructure(lParam, typeof(CREATESTRUCT));
|
||||
GCHandle gcHandle = GCHandle.FromIntPtr(createStruct.lpCreateParams);
|
||||
hwndWrapper = (MessageWindow)gcHandle.Target;
|
||||
s_windowLookup.Add(hwnd, hwndWrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_windowLookup.TryGetValue(hwnd, out hwndWrapper))
|
||||
{
|
||||
return NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
Assert.IsNotNull(hwndWrapper);
|
||||
|
||||
WndProc callback = hwndWrapper._wndProcCallback;
|
||||
if (callback != null)
|
||||
{
|
||||
ret = callback(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
if (msg == WM.NCDESTROY)
|
||||
{
|
||||
hwndWrapper._Dispose(true, true);
|
||||
GC.SuppressFinalize(hwndWrapper);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static object _DestroyWindow(IntPtr hwnd, string className)
|
||||
{
|
||||
Utility.SafeDestroyWindow(ref hwnd);
|
||||
NativeMethods.UnregisterClass(className, NativeMethods.GetModuleHandle(null));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
3474
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs
Normal file
3474
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/NativeMethods.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,983 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
|
||||
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
|
||||
|
||||
#region Enums and Static Property Classes
|
||||
|
||||
/// <summary>ShellItem attribute flags. SIATTRIBFLAGS_*</summary>
|
||||
internal enum SIATTRIBFLAGS
|
||||
{
|
||||
AND = 0x00000001,
|
||||
OR = 0x00000002,
|
||||
APPCOMPAT = 0x00000003,
|
||||
}
|
||||
|
||||
internal enum APPDOCLISTTYPE
|
||||
{
|
||||
ADLT_RECENT = 0, // The recently used documents list
|
||||
ADLT_FREQUENT, // The frequently used documents list
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags for SetTabProperties. STPF_*
|
||||
/// </summary>
|
||||
/// <remarks>The native enum was called STPFLAG.</remarks>
|
||||
[Flags]
|
||||
internal enum STPF
|
||||
{
|
||||
NONE = 0x00000000,
|
||||
USEAPPTHUMBNAILALWAYS = 0x00000001,
|
||||
USEAPPTHUMBNAILWHENACTIVE = 0x00000002,
|
||||
USEAPPPEEKALWAYS = 0x00000004,
|
||||
USEAPPPEEKWHENACTIVE = 0x00000008,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags for Setting Taskbar Progress state. TBPF_*
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The native enum was called TBPFLAG.
|
||||
/// </remarks>
|
||||
internal enum TBPF
|
||||
{
|
||||
NOPROGRESS = 0x00000000,
|
||||
INDETERMINATE = 0x00000001,
|
||||
NORMAL = 0x00000002,
|
||||
ERROR = 0x00000004,
|
||||
PAUSED = 0x00000008,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THUMBBUTTON mask. THB_*
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum THB : uint
|
||||
{
|
||||
BITMAP = 0x0001,
|
||||
ICON = 0x0002,
|
||||
TOOLTIP = 0x0004,
|
||||
FLAGS = 0x0008,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THUMBBUTTON flags. THBF_*
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum THBF : uint
|
||||
{
|
||||
ENABLED = 0x0000,
|
||||
DISABLED = 0x0001,
|
||||
DISMISSONCLICK = 0x0002,
|
||||
NOBACKGROUND = 0x0004,
|
||||
HIDDEN = 0x0008,
|
||||
// Added post-beta
|
||||
NONINTERACTIVE = 0x0010,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetPropertyStoreFlags. GPS_*.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These are new for Vista, but are used in downlevel components
|
||||
/// </remarks>
|
||||
internal enum GPS
|
||||
{
|
||||
// If no flags are specified (GPS_DEFAULT), a read-only property store is returned that includes properties for the file or item.
|
||||
// In the case that the shell item is a file, the property store contains:
|
||||
// 1. properties about the file from the file system
|
||||
// 2. properties from the file itself provided by the file's property handler, unless that file is offline,
|
||||
// see GPS_OPENSLOWITEM
|
||||
// 3. if requested by the file's property handler and supported by the file system, properties stored in the
|
||||
// alternate property store.
|
||||
//
|
||||
// Non-file shell items should return a similar read-only store
|
||||
//
|
||||
// Specifying other GPS_ flags modifies the store that is returned
|
||||
DEFAULT = 0x00000000,
|
||||
HANDLERPROPERTIESONLY = 0x00000001, // only include properties directly from the file's property handler
|
||||
READWRITE = 0x00000002, // Writable stores will only include handler properties
|
||||
TEMPORARY = 0x00000004, // A read/write store that only holds properties for the lifetime of the IShellItem object
|
||||
FASTPROPERTIESONLY = 0x00000008, // do not include any properties from the file's property handler (because the file's property handler will hit the disk)
|
||||
OPENSLOWITEM = 0x00000010, // include properties from a file's property handler, even if it means retrieving the file from offline storage.
|
||||
DELAYCREATION = 0x00000020, // delay the creation of the file's property handler until those properties are read, written, or enumerated
|
||||
BESTEFFORT = 0x00000040, // For readonly stores, succeed and return all available properties, even if one or more sources of properties fails. Not valid with GPS_READWRITE.
|
||||
NO_OPLOCK = 0x00000080, // some data sources protect the read property store with an oplock, this disables that
|
||||
MASK_VALID = 0x000000FF,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// KNOWNDESTCATEGORY. KDC_*
|
||||
/// </summary>
|
||||
internal enum KDC
|
||||
{
|
||||
FREQUENT = 1,
|
||||
RECENT,
|
||||
}
|
||||
|
||||
// IShellFolder::GetAttributesOf flags
|
||||
[Flags]
|
||||
internal enum SFGAO : uint
|
||||
{
|
||||
/// <summary>Objects can be copied</summary>
|
||||
/// <remarks>DROPEFFECT_COPY</remarks>
|
||||
CANCOPY = 0x1,
|
||||
/// <summary>Objects can be moved</summary>
|
||||
/// <remarks>DROPEFFECT_MOVE</remarks>
|
||||
CANMOVE = 0x2,
|
||||
/// <summary>Objects can be linked</summary>
|
||||
/// <remarks>
|
||||
/// DROPEFFECT_LINK.
|
||||
///
|
||||
/// If this bit is set on an item in the shell folder, a
|
||||
/// 'Create Shortcut' menu item will be added to the File
|
||||
/// menu and context menus for the item. If the user selects
|
||||
/// that command, your IContextMenu::InvokeCommand() will be called
|
||||
/// with 'link'.
|
||||
/// That flag will also be used to determine if 'Create Shortcut'
|
||||
/// should be added when the item in your folder is dragged to another
|
||||
/// folder.
|
||||
/// </remarks>
|
||||
CANLINK = 0x4,
|
||||
/// <summary>supports BindToObject(IID_IStorage)</summary>
|
||||
STORAGE = 0x00000008,
|
||||
/// <summary>Objects can be renamed</summary>
|
||||
CANRENAME = 0x00000010,
|
||||
/// <summary>Objects can be deleted</summary>
|
||||
CANDELETE = 0x00000020,
|
||||
/// <summary>Objects have property sheets</summary>
|
||||
HASPROPSHEET = 0x00000040,
|
||||
|
||||
// unused = 0x00000080,
|
||||
|
||||
/// <summary>Objects are drop target</summary>
|
||||
DROPTARGET = 0x00000100,
|
||||
CAPABILITYMASK = 0x00000177,
|
||||
// unused = 0x00000200,
|
||||
// unused = 0x00000400,
|
||||
// unused = 0x00000800,
|
||||
// unused = 0x00001000,
|
||||
/// <summary>Object is encrypted (use alt color)</summary>
|
||||
ENCRYPTED = 0x00002000,
|
||||
/// <summary>'Slow' object</summary>
|
||||
ISSLOW = 0x00004000,
|
||||
/// <summary>Ghosted icon</summary>
|
||||
GHOSTED = 0x00008000,
|
||||
/// <summary>Shortcut (link)</summary>
|
||||
LINK = 0x00010000,
|
||||
/// <summary>Shared</summary>
|
||||
SHARE = 0x00020000,
|
||||
/// <summary>Read-only</summary>
|
||||
READONLY = 0x00040000,
|
||||
/// <summary> Hidden object</summary>
|
||||
HIDDEN = 0x00080000,
|
||||
DISPLAYATTRMASK = 0x000FC000,
|
||||
/// <summary> May contain children with SFGAO_FILESYSTEM</summary>
|
||||
FILESYSANCESTOR = 0x10000000,
|
||||
/// <summary>Support BindToObject(IID_IShellFolder)</summary>
|
||||
FOLDER = 0x20000000,
|
||||
/// <summary>Is a win32 file system object (file/folder/root)</summary>
|
||||
FILESYSTEM = 0x40000000,
|
||||
/// <summary>May contain children with SFGAO_FOLDER (may be slow)</summary>
|
||||
HASSUBFOLDER = 0x80000000,
|
||||
CONTENTSMASK = 0x80000000,
|
||||
/// <summary>Invalidate cached information (may be slow)</summary>
|
||||
VALIDATE = 0x01000000,
|
||||
/// <summary>Is this removeable media?</summary>
|
||||
REMOVABLE = 0x02000000,
|
||||
/// <summary> Object is compressed (use alt color)</summary>
|
||||
COMPRESSED = 0x04000000,
|
||||
/// <summary>Supports IShellFolder, but only implements CreateViewObject() (non-folder view)</summary>
|
||||
BROWSABLE = 0x08000000,
|
||||
/// <summary>Is a non-enumerated object (should be hidden)</summary>
|
||||
NONENUMERATED = 0x00100000,
|
||||
/// <summary>Should show bold in explorer tree</summary>
|
||||
NEWCONTENT = 0x00200000,
|
||||
/// <summary>Obsolete</summary>
|
||||
CANMONIKER = 0x00400000,
|
||||
/// <summary>Obsolete</summary>
|
||||
HASSTORAGE = 0x00400000,
|
||||
/// <summary>Supports BindToObject(IID_IStream)</summary>
|
||||
STREAM = 0x00400000,
|
||||
/// <summary>May contain children with SFGAO_STORAGE or SFGAO_STREAM</summary>
|
||||
STORAGEANCESTOR = 0x00800000,
|
||||
/// <summary>For determining storage capabilities, ie for open/save semantics</summary>
|
||||
STORAGECAPMASK = 0x70C50008,
|
||||
/// <summary>
|
||||
/// Attributes that are masked out for PKEY_SFGAOFlags because they are considered
|
||||
/// to cause slow calculations or lack context
|
||||
/// (SFGAO_VALIDATE | SFGAO_ISSLOW | SFGAO_HASSUBFOLDER and others)
|
||||
/// </summary>
|
||||
PKEYSFGAOMASK = 0x81044000,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IShellFolder::EnumObjects grfFlags bits. Also called SHCONT
|
||||
/// </summary>
|
||||
internal enum SHCONTF
|
||||
{
|
||||
CHECKING_FOR_CHILDREN = 0x0010, // hint that client is checking if (what) child items the folder contains - not all details (e.g. short file name) are needed
|
||||
FOLDERS = 0x0020, // only want folders enumerated (SFGAO_FOLDER)
|
||||
NONFOLDERS = 0x0040, // include non folders (items without SFGAO_FOLDER)
|
||||
INCLUDEHIDDEN = 0x0080, // show items normally hidden (items with SFGAO_HIDDEN)
|
||||
INIT_ON_FIRST_NEXT = 0x0100, // DEFUNCT - this is always assumed
|
||||
NETPRINTERSRCH = 0x0200, // hint that client is looking for printers
|
||||
SHAREABLE = 0x0400, // hint that client is looking sharable resources (local drives or hidden root shares)
|
||||
STORAGE = 0x0800, // include all items with accessible storage and their ancestors
|
||||
NAVIGATION_ENUM = 0x1000, // mark child folders to indicate that they should provide a "navigation" enumeration by default
|
||||
FASTITEMS = 0x2000, // hint that client is only interested in items that can be enumerated quickly
|
||||
FLATLIST = 0x4000, // enumerate items as flat list even if folder is stacked
|
||||
ENABLE_ASYNC = 0x8000, // inform enumerator that client is listening for change notifications so enumerator does not need to be complete, items can be reported via change notifications
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IShellFolder::GetDisplayNameOf/SetNameOf uFlags. Also called SHGDNF.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For compatibility with SIGDN, these bits must all sit in the LOW word.
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
internal enum SHGDN
|
||||
{
|
||||
SHGDN_NORMAL = 0x0000, // default (display purpose)
|
||||
SHGDN_INFOLDER = 0x0001, // displayed under a folder (relative)
|
||||
SHGDN_FOREDITING = 0x1000, // for in-place editing
|
||||
SHGDN_FORADDRESSBAR = 0x4000, // UI friendly parsing name (remove ugly stuff)
|
||||
SHGDN_FORPARSING = 0x8000, // parsing name for ParseDisplayName()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SHELLITEMCOMPAREHINTF. SICHINT_*.
|
||||
/// </summary>
|
||||
internal enum SICHINT : uint
|
||||
{
|
||||
/// <summary>iOrder based on display in a folder view</summary>
|
||||
DISPLAY = 0x00000000,
|
||||
/// <summary>exact instance compare</summary>
|
||||
ALLFIELDS = 0x80000000,
|
||||
/// <summary>iOrder based on canonical name (better performance)</summary>
|
||||
CANONICAL = 0x10000000,
|
||||
TEST_FILESYSPATH_IF_NOT_EQUAL = 0x20000000,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// ShellItem enum. SIGDN_*.
|
||||
/// </summary>
|
||||
internal enum SIGDN : uint
|
||||
{ // lower word (& with 0xFFFF)
|
||||
NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
||||
PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
||||
DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
||||
PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
||||
DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||
FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
||||
URL = 0x80068000, // SHGDN_FORPARSING
|
||||
PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||
PARENTRELATIVE = 0x80080001, // SHGDN_INFOLDER
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// STR_GPS_*
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When requesting a property store through IShellFolder, you can specify the equivalent of
|
||||
/// GPS_DEFAULT by passing in a null IBindCtx parameter.
|
||||
///
|
||||
/// You can specify the equivalent of GPS_READWRITE by passing a mode of STGM_READWRITE | STGM_EXCLUSIVE
|
||||
/// in the bind context
|
||||
///
|
||||
/// Here are the string versions of GPS_ flags, passed to IShellFolder::BindToObject() via IBindCtx::RegisterObjectParam()
|
||||
/// These flags are valid when requesting an IPropertySetStorage or IPropertyStore handler
|
||||
///
|
||||
/// The meaning of these flags are described above.
|
||||
///
|
||||
/// There is no STR_ equivalent for GPS_TEMPORARY because temporary property stores
|
||||
/// are provided by IShellItem2 only -- not by the underlying IShellFolder.
|
||||
/// </remarks>
|
||||
internal static class STR_GPS
|
||||
{
|
||||
public const string HANDLERPROPERTIESONLY = "GPS_HANDLERPROPERTIESONLY";
|
||||
public const string FASTPROPERTIESONLY = "GPS_FASTPROPERTIESONLY";
|
||||
public const string OPENSLOWITEM = "GPS_OPENSLOWITEM";
|
||||
public const string DELAYCREATION = "GPS_DELAYCREATION";
|
||||
public const string BESTEFFORT = "GPS_BESTEFFORT";
|
||||
public const string NO_OPLOCK = "GPS_NO_OPLOCK";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Structs
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
|
||||
internal struct THUMBBUTTON
|
||||
{
|
||||
/// <summary>
|
||||
/// WPARAM value for a THUMBBUTTON being clicked.
|
||||
/// </summary>
|
||||
public const int THBN_CLICKED = 0x1800;
|
||||
|
||||
public THB dwMask;
|
||||
public uint iId;
|
||||
public uint iBitmap;
|
||||
public IntPtr hIcon;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szTip;
|
||||
public THBF dwFlags;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
internal struct PKEY
|
||||
{
|
||||
/// <summary>fmtid</summary>
|
||||
private readonly Guid _fmtid;
|
||||
/// <summary>pid</summary>
|
||||
private readonly uint _pid;
|
||||
|
||||
public PKEY(Guid fmtid, uint pid)
|
||||
{
|
||||
_fmtid = fmtid;
|
||||
_pid = pid;
|
||||
}
|
||||
|
||||
/// <summary>PKEY_Title</summary>
|
||||
public static readonly PKEY Title = new PKEY(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 2);
|
||||
/// <summary>PKEY_AppUserModel_ID</summary>
|
||||
public static readonly PKEY AppUserModel_ID = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
|
||||
/// <summary>PKEY_AppUserModel_IsDestListSeparator</summary>
|
||||
public static readonly PKEY AppUserModel_IsDestListSeparator = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 6);
|
||||
/// <summary>PKEY_AppUserModel_RelaunchCommand</summary>
|
||||
public static readonly PKEY AppUserModel_RelaunchCommand = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 2);
|
||||
/// <summary>PKEY_AppUserModel_RelaunchDisplayNameResource</summary>
|
||||
public static readonly PKEY AppUserModel_RelaunchDisplayNameResource = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 4);
|
||||
/// <summary>PKEY_AppUserModel_RelaunchIconResource</summary>
|
||||
public static readonly PKEY AppUserModel_RelaunchIconResource = new PKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 3);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Interfaces
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.EnumIdList),
|
||||
]
|
||||
internal interface IEnumIDList
|
||||
{
|
||||
[PreserveSig()]
|
||||
HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
|
||||
[PreserveSig()]
|
||||
HRESULT Skip(uint celt);
|
||||
void Reset();
|
||||
void Clone([Out, MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenum);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.EnumObjects),
|
||||
]
|
||||
internal interface IEnumObjects
|
||||
{
|
||||
//[local]
|
||||
// This signature might not work... Hopefully don't need this interface though.
|
||||
void Next(uint celt, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, IidParameterIndex = 1, SizeParamIndex = 0)] object[] rgelt, [Out] out uint pceltFetched);
|
||||
|
||||
/*
|
||||
[call_as(Next)] HRESULT RemoteNext(
|
||||
[in] ULONG celt,
|
||||
[in] REFIID riid,
|
||||
[out, size_is(celt), length_is(*pceltFetched), iid_is(riid)] void **rgelt,
|
||||
[out] ULONG *pceltFetched);
|
||||
*/
|
||||
|
||||
void Skip(uint celt);
|
||||
|
||||
void Reset();
|
||||
|
||||
IEnumObjects Clone();
|
||||
}
|
||||
|
||||
/// <summary>Unknown Object Array</summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ObjectArray),
|
||||
]
|
||||
internal interface IObjectArray
|
||||
{
|
||||
uint GetCount();
|
||||
[return: MarshalAs(UnmanagedType.IUnknown)]
|
||||
object GetAt([In] uint uiIndex, [In] ref Guid riid);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ObjectArray),
|
||||
]
|
||||
interface IObjectCollection : IObjectArray
|
||||
{
|
||||
#region IObjectArray redeclarations
|
||||
new uint GetCount();
|
||||
[return: MarshalAs(UnmanagedType.IUnknown)]
|
||||
new object GetAt([In] uint uiIndex, [In] ref Guid riid);
|
||||
#endregion
|
||||
|
||||
void AddObject([MarshalAs(UnmanagedType.IUnknown)] object punk);
|
||||
void AddFromArray(IObjectArray poaSource);
|
||||
void RemoveObjectAt(uint uiIndex);
|
||||
void Clear();
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.PropertyStore)
|
||||
]
|
||||
internal interface IPropertyStore
|
||||
{
|
||||
uint GetCount();
|
||||
PKEY GetAt(uint iProp);
|
||||
void GetValue([In] ref PKEY pkey, [In, Out] PROPVARIANT pv);
|
||||
void SetValue([In] ref PKEY pkey, PROPVARIANT pv);
|
||||
void Commit();
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ShellFolder),
|
||||
]
|
||||
internal interface IShellFolder
|
||||
{
|
||||
void ParseDisplayName(
|
||||
[In] IntPtr hwnd,
|
||||
[In] IBindCtx pbc,
|
||||
[In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
|
||||
[In, Out] ref int pchEaten,
|
||||
[Out] out IntPtr ppidl,
|
||||
[In, Out] ref uint pdwAttributes);
|
||||
|
||||
IEnumIDList EnumObjects(
|
||||
[In] IntPtr hwnd,
|
||||
[In] SHCONTF grfFlags);
|
||||
|
||||
// returns an instance of a sub-folder which is specified by the IDList (pidl).
|
||||
// IShellFolder or derived interfaces
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object BindToObject(
|
||||
[In] IntPtr pidl,
|
||||
[In] IBindCtx pbc,
|
||||
[In] ref Guid riid);
|
||||
|
||||
// produces the same result as BindToObject()
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object BindToStorage([In] IntPtr pidl, [In] IBindCtx pbc, [In] ref Guid riid);
|
||||
|
||||
// compares two IDLists and returns the result. The shell
|
||||
// explorer always passes 0 as lParam, which indicates 'sort by name'.
|
||||
// It should return 0 (as CODE of the scode), if two id indicates the
|
||||
// same object; negative value if pidl1 should be placed before pidl2;
|
||||
// positive value if pidl2 should be placed before pidl1.
|
||||
// use the macro ResultFromShort() to extract the result comparison
|
||||
// it deals with the casting and type conversion issues for you
|
||||
[PreserveSig]
|
||||
HRESULT CompareIDs([In] IntPtr lParam, [In] IntPtr pidl1, [In] IntPtr pidl2);
|
||||
|
||||
// creates a view object of the folder itself. The view
|
||||
// object is a difference instance from the shell folder object.
|
||||
// 'hwndOwner' can be used as the owner window of its dialog box or
|
||||
// menu during the lifetime of the view object.
|
||||
// This member function should always create a new
|
||||
// instance which has only one reference count. The explorer may create
|
||||
// more than one instances of view object from one shell folder object
|
||||
// and treat them as separate instances.
|
||||
// returns IShellView derived interface
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object CreateViewObject([In] IntPtr hwndOwner, [In] ref Guid riid);
|
||||
|
||||
// returns the attributes of specified objects in that
|
||||
// folder. 'cidl' and 'apidl' specifies objects. 'apidl' contains only
|
||||
// simple IDLists. The explorer initializes *prgfInOut with a set of
|
||||
// flags to be evaluated. The shell folder may optimize the operation
|
||||
// by not returning unspecified flags.
|
||||
void GetAttributesOf(
|
||||
[In] uint cidl,
|
||||
[In] IntPtr apidl,
|
||||
[In, Out] ref SFGAO rgfInOut);
|
||||
|
||||
// creates a UI object to be used for specified objects.
|
||||
// The shell explorer passes either IID_IDataObject (for transfer operation)
|
||||
// or IID_IContextMenu (for context menu operation) as riid
|
||||
// and many other interfaces
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetUIObjectOf(
|
||||
[In] IntPtr hwndOwner,
|
||||
[In] uint cidl,
|
||||
[In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2)] IntPtr apidl,
|
||||
[In] ref Guid riid,
|
||||
[In, Out] ref uint rgfReserved);
|
||||
|
||||
// returns the display name of the specified object.
|
||||
// If the ID contains the display name (in the locale character set),
|
||||
// it returns the offset to the name. Otherwise, it returns a pointer
|
||||
// to the display name string (UNICODE), which is allocated by the
|
||||
// task allocator, or fills in a buffer.
|
||||
// use the helper APIS StrRetToStr() or StrRetToBuf() to deal with the different
|
||||
// forms of the STRRET structure
|
||||
void GetDisplayNameOf([In] IntPtr pidl, [In] SHGDN uFlags, [Out] out IntPtr pName);
|
||||
|
||||
// sets the display name of the specified object.
|
||||
// If it changes the ID as well, it returns the new ID which is
|
||||
// alocated by the task allocator.
|
||||
void SetNameOf([In] IntPtr hwnd,
|
||||
[In] IntPtr pidl,
|
||||
[In, MarshalAs(UnmanagedType.LPWStr)] string pszName,
|
||||
[In] SHGDN uFlags,
|
||||
[Out] out IntPtr ppidlOut);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shell Namespace helper
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ShellItem),
|
||||
]
|
||||
internal interface IShellItem
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object BindToHandler(IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid);
|
||||
|
||||
IShellItem GetParent();
|
||||
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
string GetDisplayName(SIGDN sigdnName);
|
||||
|
||||
SFGAO GetAttributes(SFGAO sfgaoMask);
|
||||
|
||||
int Compare(IShellItem psi, SICHINT hint);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ShellItemArray),
|
||||
]
|
||||
internal interface IShellItemArray
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object BindToHandler(IBindCtx pbc, [In] ref Guid rbhid, [In] ref Guid riid);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyStore(int flags, [In] ref Guid riid);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyDescriptionList([In] ref PKEY keyType, [In] ref Guid riid);
|
||||
|
||||
uint GetAttributes(SIATTRIBFLAGS dwAttribFlags, uint sfgaoMask);
|
||||
|
||||
uint GetCount();
|
||||
|
||||
IShellItem GetItemAt(uint dwIndex);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object EnumItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shell Namespace helper 2
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ShellItem2),
|
||||
]
|
||||
interface IShellItem2 : IShellItem
|
||||
{
|
||||
#region IShellItem redeclarations
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
new object BindToHandler([In] IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid);
|
||||
new IShellItem GetParent();
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
new string GetDisplayName(SIGDN sigdnName);
|
||||
new SFGAO GetAttributes(SFGAO sfgaoMask);
|
||||
new int Compare(IShellItem psi, SICHINT hint);
|
||||
#endregion
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyStore(
|
||||
GPS flags,
|
||||
[In] ref Guid riid);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyStoreWithCreateObject(
|
||||
GPS flags,
|
||||
[MarshalAs(UnmanagedType.IUnknown)] object punkCreateObject, // factory for low-rights creation of type ICreateObject
|
||||
[In] ref Guid riid);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyStoreForKeys(
|
||||
IntPtr rgKeys,
|
||||
uint cKeys,
|
||||
GPS flags,
|
||||
[In] ref Guid riid);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetPropertyDescriptionList(
|
||||
IntPtr keyType,
|
||||
[In] ref Guid riid);
|
||||
|
||||
// Ensures any cached information in this item is up to date, or returns __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) if the item does not exist.
|
||||
void Update(IBindCtx pbc);
|
||||
|
||||
PROPVARIANT GetProperty(IntPtr key);
|
||||
|
||||
Guid GetCLSID(IntPtr key);
|
||||
|
||||
FILETIME GetFileTime(IntPtr key);
|
||||
|
||||
int GetInt32(IntPtr key);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
string GetString(IntPtr key);
|
||||
|
||||
uint GetUInt32(IntPtr key);
|
||||
|
||||
ulong GetUInt64(IntPtr key);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
void GetBool(IntPtr key);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ShellLink),
|
||||
]
|
||||
internal interface IShellLinkW
|
||||
{
|
||||
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, [In, Out] WIN32_FIND_DATAW pfd, SLGP fFlags);
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
void SetIDList(IntPtr pidl);
|
||||
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
short GetHotKey();
|
||||
void SetHotKey(short wHotKey);
|
||||
uint GetShowCmd();
|
||||
void SetShowCmd(uint iShowCmd);
|
||||
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
|
||||
void Resolve(IntPtr hwnd, uint fFlags);
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.TaskbarList),
|
||||
]
|
||||
internal interface ITaskbarList
|
||||
{
|
||||
/// <summary>
|
||||
/// This function must be called first to validate use of other members.
|
||||
/// </summary>
|
||||
void HrInit();
|
||||
|
||||
/// <summary>
|
||||
/// This function adds a tab for hwnd to the taskbar.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The HWND for which to add the tab.</param>
|
||||
void AddTab(IntPtr hwnd);
|
||||
|
||||
/// <summary>
|
||||
/// This function deletes a tab for hwnd from the taskbar.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The HWND for which the tab is to be deleted.</param>
|
||||
void DeleteTab(IntPtr hwnd);
|
||||
|
||||
/// <summary>
|
||||
/// This function activates the tab associated with hwnd on the taskbar.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The HWND for which the tab is to be actuvated.</param>
|
||||
void ActivateTab(IntPtr hwnd);
|
||||
|
||||
/// <summary>
|
||||
/// This function marks hwnd in the taskbar as the active tab.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The HWND to activate.</param>
|
||||
void SetActiveAlt(IntPtr hwnd);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.TaskbarList2),
|
||||
]
|
||||
internal interface ITaskbarList2 : ITaskbarList
|
||||
{
|
||||
#region ITaskbarList redeclaration
|
||||
new void HrInit();
|
||||
new void AddTab(IntPtr hwnd);
|
||||
new void DeleteTab(IntPtr hwnd);
|
||||
new void ActivateTab(IntPtr hwnd);
|
||||
new void SetActiveAlt(IntPtr hwnd);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Marks a window as full-screen.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle of the window to be marked.</param>
|
||||
/// <param name="fFullscreen">A Boolean value marking the desired full-screen status of the window.</param>
|
||||
/// <remarks>
|
||||
/// Setting the value of fFullscreen to true, the Shell treats this window as a full-screen window, and the taskbar
|
||||
/// is moved to the bottom of the z-order when this window is active. Setting the value of fFullscreen to false
|
||||
/// removes the full-screen marking, but <i>does not</i> cause the Shell to treat the window as though it were
|
||||
/// definitely not full-screen. With a false fFullscreen value, the Shell depends on its automatic detection facility
|
||||
/// to specify how the window should be treated, possibly still flagging the window as full-screen.
|
||||
/// </remarks>
|
||||
void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||
}
|
||||
|
||||
// Used to remove items from the automatic destination lists created when apps or the system call SHAddToRecentDocs to report usage of a document.
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ApplicationDestinations)
|
||||
]
|
||||
internal interface IApplicationDestinations
|
||||
{
|
||||
// Set the App User Model ID for the application removing destinations from its list. If an AppID is not provided
|
||||
// via this method, the system will use a heuristically determined ID. This method must be called before
|
||||
// RemoveDestination or RemoveAllDestinations.
|
||||
void SetAppID([In, MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
|
||||
// Remove an IShellItem or an IShellLink from the automatic destination list
|
||||
void RemoveDestination([MarshalAs(UnmanagedType.IUnknown)] object punk);
|
||||
|
||||
// Clear the frequent and recent destination lists for this application.
|
||||
void RemoveAllDestinations();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows an application to retrieve the most recent and frequent documents opened in that app, as reported via SHAddToRecentDocs
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ApplicationDocumentLists)
|
||||
]
|
||||
internal interface IApplicationDocumentLists
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the App User Model ID for the application retrieving this list. If an AppID is not provided via this method,
|
||||
/// the system will use a heuristically determined ID. This method must be called before GetList.
|
||||
/// </summary>
|
||||
/// <param name="pszAppID">App Id.</param>
|
||||
void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an IEnumObjects or IObjectArray for IShellItems and/or IShellLinks.
|
||||
/// Items may appear in both the frequent and recent lists.
|
||||
/// </summary>
|
||||
/// <param name="?"></param>
|
||||
/// <returns></returns>
|
||||
[return: MarshalAs(UnmanagedType.IUnknown)]
|
||||
object GetList([In] APPDOCLISTTYPE listtype, [In] uint cItemsDesired, [In] ref Guid riid);
|
||||
}
|
||||
|
||||
// Custom Destination List
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.CustomDestinationList)
|
||||
]
|
||||
internal interface ICustomDestinationList
|
||||
{
|
||||
void SetAppID([In, MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
|
||||
// Retrieve IObjectArray of IShellItems or IShellLinks that represent removed destinations
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object BeginList(out uint pcMaxSlots, [In] ref Guid riid);
|
||||
|
||||
// PreserveSig because this will return custom errors when attempting to add unregistered ShellItems.
|
||||
// Can't readily detect that case without just trying to append it.
|
||||
[PreserveSig]
|
||||
HRESULT AppendCategory([MarshalAs(UnmanagedType.LPWStr)] string pszCategory, IObjectArray poa);
|
||||
void AppendKnownCategory(KDC category);
|
||||
[PreserveSig]
|
||||
HRESULT AddUserTasks(IObjectArray poa);
|
||||
void CommitList();
|
||||
|
||||
// Retrieve IObjectCollection of IShellItems
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetRemovedDestinations([In] ref Guid riid);
|
||||
void DeleteList([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
void AbortList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the App User Model ID on objects supporting this value.
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ObjectWithAppUserModelId)
|
||||
]
|
||||
internal interface IObjectWithAppUserModelId
|
||||
{
|
||||
void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
string GetAppID();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the ProgID associated with an object
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.ObjectWithProgId)
|
||||
]
|
||||
internal interface IObjectWithProgId
|
||||
{
|
||||
void SetProgID([MarshalAs(UnmanagedType.LPWStr)] string pszProgID);
|
||||
[return: MarshalAs(UnmanagedType.LPWStr)]
|
||||
string GetProgID();
|
||||
};
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.TaskbarList3),
|
||||
]
|
||||
internal interface ITaskbarList3 : ITaskbarList2
|
||||
{
|
||||
#region ITaskbarList2 redeclaration
|
||||
|
||||
#region ITaskbarList redeclaration
|
||||
new void HrInit();
|
||||
new void AddTab(IntPtr hwnd);
|
||||
new void DeleteTab(IntPtr hwnd);
|
||||
new void ActivateTab(IntPtr hwnd);
|
||||
new void SetActiveAlt(IntPtr hwnd);
|
||||
#endregion
|
||||
|
||||
new void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||
|
||||
#endregion
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetProgressState(IntPtr hwnd, TBPF tbpFlags);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT RegisterTab(IntPtr hwndTab, IntPtr hwndMDI);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT UnregisterTab(IntPtr hwndTab);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT ThumbBarAddButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT ThumbBarSetImageList(IntPtr hwnd, [MarshalAs(UnmanagedType.IUnknown)] object himl);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription);
|
||||
|
||||
[PreserveSig]
|
||||
HRESULT SetThumbnailTooltip(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszTip);
|
||||
|
||||
// Using RefRECT to making passing NULL possible. Removes clipping from the HWND.
|
||||
[PreserveSig]
|
||||
HRESULT SetThumbnailClip(IntPtr hwnd, RefRECT prcClip);
|
||||
}
|
||||
|
||||
[
|
||||
ComImport,
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
|
||||
Guid(IID.TaskbarList3),
|
||||
]
|
||||
internal interface ITaskbarList4 : ITaskbarList3
|
||||
{
|
||||
#region ITaskbarList3 redeclaration
|
||||
|
||||
#region ITaskbarList2 redeclaration
|
||||
|
||||
#region ITaskbarList redeclaration
|
||||
new void HrInit();
|
||||
new void AddTab(IntPtr hwnd);
|
||||
new void DeleteTab(IntPtr hwnd);
|
||||
new void ActivateTab(IntPtr hwnd);
|
||||
new void SetActiveAlt(IntPtr hwnd);
|
||||
#endregion
|
||||
|
||||
new void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||
|
||||
#endregion
|
||||
|
||||
[PreserveSig] new HRESULT SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
|
||||
[PreserveSig] new HRESULT SetProgressState(IntPtr hwnd, TBPF tbpFlags);
|
||||
[PreserveSig] new HRESULT RegisterTab(IntPtr hwndTab, IntPtr hwndMDI);
|
||||
[PreserveSig] new HRESULT UnregisterTab(IntPtr hwndTab);
|
||||
[PreserveSig] new HRESULT SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore);
|
||||
[PreserveSig] new HRESULT SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved);
|
||||
[PreserveSig] new HRESULT ThumbBarAddButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons);
|
||||
[PreserveSig] new HRESULT ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] THUMBBUTTON[] pButtons);
|
||||
[PreserveSig] new HRESULT ThumbBarSetImageList(IntPtr hwnd, [MarshalAs(UnmanagedType.IUnknown)] object himl);
|
||||
[PreserveSig] new HRESULT SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription);
|
||||
[PreserveSig] new HRESULT SetThumbnailTooltip(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszTip);
|
||||
// Using RefRECT to making passing NULL possible. Removes clipping from the HWND.
|
||||
[PreserveSig] new HRESULT SetThumbnailClip(IntPtr hwnd, RefRECT prcClip);
|
||||
|
||||
#endregion
|
||||
|
||||
void SetTabProperties(IntPtr hwndTab, STPF stpFlags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
357
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs
Normal file
357
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/StreamHelper.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
|
||||
// disambiguate with System.Runtime.InteropServices.STATSTG
|
||||
using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;
|
||||
|
||||
// All these methods return void. Does the standard marshaller convert them to HRESULTs?
|
||||
/// <summary>
|
||||
/// Wraps a managed stream instance into an interface pointer consumable by COM.
|
||||
/// </summary>
|
||||
internal sealed class ManagedIStream : IStream, IDisposable
|
||||
{
|
||||
private const int STGTY_STREAM = 2;
|
||||
private const int STGM_READWRITE = 2;
|
||||
private const int LOCK_EXCLUSIVE = 2;
|
||||
|
||||
private Stream _source;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ManagedIStream class with the specified managed Stream object.
|
||||
/// </summary>
|
||||
/// <param name="source">
|
||||
/// The stream that this IStream reference is wrapping.
|
||||
/// </param>
|
||||
public ManagedIStream(Stream source)
|
||||
{
|
||||
Verify.IsNotNull(source, "source");
|
||||
_source = source;
|
||||
}
|
||||
|
||||
private void _Validate()
|
||||
{
|
||||
if (null == _source)
|
||||
{
|
||||
throw new ObjectDisposedException("this");
|
||||
}
|
||||
}
|
||||
|
||||
// Comments are taken from MSDN IStream documentation.
|
||||
#region IStream Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new stream object with its own seek pointer that
|
||||
/// references the same bytes as the original stream.
|
||||
/// </summary>
|
||||
/// <param name="ppstm">
|
||||
/// When this method returns, contains the new stream object. This parameter is passed uninitialized.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::Clone in the MSDN library.
|
||||
/// This class doesn't implement Clone. A COMException is thrown if it is used.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)")]
|
||||
[Obsolete("The method is not implemented", true)]
|
||||
public void Clone(out IStream ppstm)
|
||||
{
|
||||
ppstm = null;
|
||||
HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that any changes made to a stream object that is open in transacted
|
||||
/// mode are reflected in the parent storage.
|
||||
/// </summary>
|
||||
/// <param name="grfCommitFlags">
|
||||
/// A value that controls how the changes for the stream object are committed.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::Commit in the MSDN library.
|
||||
/// </remarks>
|
||||
public void Commit(int grfCommitFlags)
|
||||
{
|
||||
_Validate();
|
||||
_source.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies a specified number of bytes from the current seek pointer in the
|
||||
/// stream to the current seek pointer in another stream.
|
||||
/// </summary>
|
||||
/// <param name="pstm">
|
||||
/// A reference to the destination stream.
|
||||
/// </param>
|
||||
/// <param name="cb">
|
||||
/// The number of bytes to copy from the source stream.
|
||||
/// </param>
|
||||
/// <param name="pcbRead">
|
||||
/// On successful return, contains the actual number of bytes read from the source.
|
||||
/// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written
|
||||
/// to this parameter on success.)
|
||||
/// </param>
|
||||
/// <param name="pcbWritten">
|
||||
/// On successful return, contains the actual number of bytes written to the destination.
|
||||
/// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written
|
||||
/// to this parameter on success.)
|
||||
/// </param>
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
|
||||
{
|
||||
Verify.IsNotNull(pstm, "pstm");
|
||||
|
||||
_Validate();
|
||||
|
||||
// Reasonbly sized buffer, don't try to copy large streams in bulk.
|
||||
var buffer = new byte[4096];
|
||||
long cbWritten = 0;
|
||||
|
||||
while (cbWritten < cb)
|
||||
{
|
||||
int cbRead = _source.Read(buffer, 0, buffer.Length);
|
||||
if (0 == cbRead)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// COM documentation is a bit vague here whether NULL is valid for the third parameter.
|
||||
// Going to assume it is, as most implementations I've seen treat it as optional.
|
||||
// It's possible this will break on some IStream implementations.
|
||||
pstm.Write(buffer, cbRead, IntPtr.Zero);
|
||||
cbWritten += cbRead;
|
||||
}
|
||||
|
||||
if (IntPtr.Zero != pcbRead)
|
||||
{
|
||||
Marshal.WriteInt64(pcbRead, cbWritten);
|
||||
}
|
||||
|
||||
if (IntPtr.Zero != pcbWritten)
|
||||
{
|
||||
Marshal.WriteInt64(pcbWritten, cbWritten);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restricts access to a specified range of bytes in the stream.
|
||||
/// </summary>
|
||||
/// <param name="libOffset">
|
||||
/// The byte offset for the beginning of the range.
|
||||
/// </param>
|
||||
/// <param name="cb">
|
||||
/// The length of the range, in bytes, to restrict.
|
||||
/// </param>
|
||||
/// <param name="dwLockType">
|
||||
/// The requested restrictions on accessing the range.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::LockRegion in the MSDN library.
|
||||
/// This class doesn't implement LockRegion. A COMException is thrown if it is used.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)"), Obsolete("The method is not implemented", true)]
|
||||
public void LockRegion(long libOffset, long cb, int dwLockType)
|
||||
{
|
||||
HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a specified number of bytes from the stream object into memory starting at the current seek pointer.
|
||||
/// </summary>
|
||||
/// <param name="pv">
|
||||
/// When this method returns, contains the data read from the stream. This parameter is passed uninitialized.
|
||||
/// </param>
|
||||
/// <param name="cb">
|
||||
/// The number of bytes to read from the stream object.
|
||||
/// </param>
|
||||
/// <param name="pcbRead">
|
||||
/// A pointer to a ULONG variable that receives the actual number of bytes read from the stream object.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for ISequentialStream::Read in the MSDN library.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public void Read(byte[] pv, int cb, IntPtr pcbRead)
|
||||
{
|
||||
_Validate();
|
||||
|
||||
int cbRead = _source.Read(pv, 0, cb);
|
||||
|
||||
if (IntPtr.Zero != pcbRead)
|
||||
{
|
||||
Marshal.WriteInt32(pcbRead, cbRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Discards all changes that have been made to a transacted stream since the last Commit call.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class doesn't implement Revert. A COMException is thrown if it is used.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)"), Obsolete("The method is not implemented", true)]
|
||||
public void Revert()
|
||||
{
|
||||
HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the seek pointer to a new location relative to the beginning of the
|
||||
/// stream, to the end of the stream, or to the current seek pointer.
|
||||
/// </summary>
|
||||
/// <param name="dlibMove">
|
||||
/// The displacement to add to dwOrigin.
|
||||
/// </param>
|
||||
/// <param name="dwOrigin">
|
||||
/// The origin of the seek. The origin can be the beginning of the file, the current seek pointer, or the end of the file.
|
||||
/// </param>
|
||||
/// <param name="plibNewPosition">
|
||||
/// On successful return, contains the offset of the seek pointer from the beginning of the stream.
|
||||
/// (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written
|
||||
/// to this parameter on success.)
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::Seek in the MSDN library.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
|
||||
{
|
||||
_Validate();
|
||||
|
||||
long position = _source.Seek(dlibMove, (SeekOrigin)dwOrigin);
|
||||
|
||||
if (IntPtr.Zero != plibNewPosition)
|
||||
{
|
||||
Marshal.WriteInt64(plibNewPosition, position);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the size of the stream object.
|
||||
/// </summary>
|
||||
/// <param name="libNewSize">
|
||||
/// The new size of the stream as a number of bytes.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::SetSize in the MSDN library.
|
||||
/// </remarks>
|
||||
public void SetSize(long libNewSize)
|
||||
{
|
||||
_Validate();
|
||||
_source.SetLength(libNewSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the STATSTG structure for this stream.
|
||||
/// </summary>
|
||||
/// <param name="pstatstg">
|
||||
/// When this method returns, contains a STATSTG structure that describes this stream object.
|
||||
/// This parameter is passed uninitialized.
|
||||
/// </param>
|
||||
/// <param name="grfStatFlag">
|
||||
/// Members in the STATSTG structure that this method does not return, thus saving some memory allocation operations.
|
||||
/// </param>
|
||||
public void Stat(out STATSTG pstatstg, int grfStatFlag)
|
||||
{
|
||||
pstatstg = default(STATSTG);
|
||||
_Validate();
|
||||
|
||||
pstatstg.type = STGTY_STREAM;
|
||||
pstatstg.cbSize = _source.Length;
|
||||
pstatstg.grfMode = STGM_READWRITE;
|
||||
pstatstg.grfLocksSupported = LOCK_EXCLUSIVE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the access restriction on a range of bytes previously restricted with the LockRegion method.
|
||||
/// </summary>
|
||||
/// <param name="libOffset">The byte offset for the beginning of the range.
|
||||
/// </param>
|
||||
/// <param name="cb">
|
||||
/// The length, in bytes, of the range to restrict.
|
||||
/// </param>
|
||||
/// <param name="dwLockType">
|
||||
/// The access restrictions previously placed on the range.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// For more information, see the existing documentation for IStream::UnlockRegion in the MSDN library.
|
||||
/// This class doesn't implement UnlockRegion. A COMException is thrown if it is used.
|
||||
/// </remarks>
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Standard.HRESULT.ThrowIfFailed(System.String)")]
|
||||
[Obsolete("The method is not implemented", true)]
|
||||
public void UnlockRegion(long libOffset, long cb, int dwLockType)
|
||||
{
|
||||
HRESULT.STG_E_INVALIDFUNCTION.ThrowIfFailed("The method is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a specified number of bytes into the stream object starting at the current seek pointer.
|
||||
/// </summary>
|
||||
/// <param name="pv">
|
||||
/// The buffer to write this stream to.
|
||||
/// </param>
|
||||
/// <param name="cb">
|
||||
/// The number of bytes to write to the stream.
|
||||
/// </param>
|
||||
/// <param name="pcbWritten">
|
||||
/// On successful return, contains the actual number of bytes written to the stream object.
|
||||
/// If the caller sets this pointer to null, this method does not provide the actual number
|
||||
/// of bytes written.
|
||||
/// </param>
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
|
||||
{
|
||||
_Validate();
|
||||
|
||||
_source.Write(pv, 0, cb);
|
||||
|
||||
if (IntPtr.Zero != pcbWritten)
|
||||
{
|
||||
Marshal.WriteInt32(pcbWritten, cb);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Releases resources controlled by this object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dispose can be called multiple times, but trying to use the object
|
||||
/// after it has been disposed will generally throw ObjectDisposedExceptions.
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
_source = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1062
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs
Normal file
1062
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Utilities.cs
Normal file
File diff suppressed because it is too large
Load Diff
328
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs
Normal file
328
Src/Xceed.Wpf.AvalonDock/Controls/Shell/Standard/Verify.cs
Normal file
@@ -0,0 +1,328 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
// This file contains general utilities to aid in development.
|
||||
// Classes here generally shouldn't be exposed publicly since
|
||||
// they're not particular to any library functionality.
|
||||
// Because the classes here are internal, it's likely this file
|
||||
// might be included in multiple assemblies.
|
||||
namespace Standard
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// A static class for retail validated assertions.
|
||||
/// Instead of breaking into the debugger an exception is thrown.
|
||||
/// </summary>
|
||||
internal static class Verify
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensure that the current thread's apartment state is what's expected.
|
||||
/// </summary>
|
||||
/// <param name="requiredState">
|
||||
/// The required apartment state for the current thread.
|
||||
/// </param>
|
||||
/// <param name="message">
|
||||
/// The message string for the exception to be thrown if the state is invalid.
|
||||
/// </param>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if the calling thread's apartment state is not the same as the requiredState.
|
||||
/// </exception>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsApartmentState(ApartmentState requiredState, string message)
|
||||
{
|
||||
if (Thread.CurrentThread.GetApartmentState() != requiredState)
|
||||
{
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that an argument is neither null nor empty.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to validate.</param>
|
||||
/// <param name="name">The name of the parameter that will be presented if an exception is thrown.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsNeitherNullNorEmpty(string value, string name)
|
||||
{
|
||||
// catch caller errors, mixing up the parameters. Name should never be empty.
|
||||
Assert.IsNeitherNullNorEmpty(name);
|
||||
|
||||
// Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P
|
||||
const string errorMessage = "The parameter can not be either null or empty.";
|
||||
if (null == value)
|
||||
{
|
||||
throw new ArgumentNullException(name, errorMessage);
|
||||
}
|
||||
if ("" == value)
|
||||
{
|
||||
throw new ArgumentException(errorMessage, name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that an argument is neither null nor does it consist only of whitespace.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to validate.</param>
|
||||
/// <param name="name">The name of the parameter that will be presented if an exception is thrown.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsNeitherNullNorWhitespace(string value, string name)
|
||||
{
|
||||
// catch caller errors, mixing up the parameters. Name should never be empty.
|
||||
Assert.IsNeitherNullNorEmpty(name);
|
||||
|
||||
// Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P
|
||||
const string errorMessage = "The parameter can not be either null or empty or consist only of white space characters.";
|
||||
if (null == value)
|
||||
{
|
||||
throw new ArgumentNullException(name, errorMessage);
|
||||
}
|
||||
if ("" == value.Trim())
|
||||
{
|
||||
throw new ArgumentException(errorMessage, name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an argument is not null.</summary>
|
||||
/// <typeparam name="T">Type of the object to validate. Must be a class.</typeparam>
|
||||
/// <param name="obj">The object to validate.</param>
|
||||
/// <param name="name">The name of the parameter that will be presented if an exception is thrown.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsNotDefault<T>(T obj, string name) where T : struct
|
||||
{
|
||||
if (default(T).Equals(obj))
|
||||
{
|
||||
throw new ArgumentException("The parameter must not be the default value.", name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an argument is not null.</summary>
|
||||
/// <typeparam name="T">Type of the object to validate. Must be a class.</typeparam>
|
||||
/// <param name="obj">The object to validate.</param>
|
||||
/// <param name="name">The name of the parameter that will be presented if an exception is thrown.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsNotNull<T>(T obj, string name) where T : class
|
||||
{
|
||||
if (null == obj)
|
||||
{
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an argument is null.</summary>
|
||||
/// <typeparam name="T">Type of the object to validate. Must be a class.</typeparam>
|
||||
/// <param name="obj">The object to validate.</param>
|
||||
/// <param name="name">The name of the parameter that will be presented if an exception is thrown.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsNull<T>(T obj, string name) where T : class
|
||||
{
|
||||
if (null != obj)
|
||||
{
|
||||
throw new ArgumentException("The parameter must be null.", name);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void PropertyIsNotNull<T>(T obj, string name) where T : class
|
||||
{
|
||||
if (null == obj)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The property {0} cannot be null at this time.", name));
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void PropertyIsNull<T>(T obj, string name) where T : class
|
||||
{
|
||||
if (null != obj)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The property {0} must be null at this time.", name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the specified statement is true. Throws an ArgumentException if it's not.
|
||||
/// </summary>
|
||||
/// <param name="statement">The statement to be verified as true.</param>
|
||||
/// <param name="name">Name of the parameter to include in the ArgumentException.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsTrue(bool statement, string name)
|
||||
{
|
||||
if (!statement)
|
||||
{
|
||||
throw new ArgumentException("", name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the specified statement is true. Throws an ArgumentException if it's not.
|
||||
/// </summary>
|
||||
/// <param name="statement">The statement to be verified as true.</param>
|
||||
/// <param name="name">Name of the parameter to include in the ArgumentException.</param>
|
||||
/// <param name="message">The message to include in the ArgumentException.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void IsTrue(bool statement, string name, string message)
|
||||
{
|
||||
if (!statement)
|
||||
{
|
||||
throw new ArgumentException(message, name);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void AreEqual<T>(T expected, T actual, string parameterName, string message)
|
||||
{
|
||||
if (null == expected)
|
||||
{
|
||||
// Two nulls are considered equal, regardless of type semantics.
|
||||
if (null != actual && !actual.Equals(expected))
|
||||
{
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
}
|
||||
else if (!expected.Equals(actual))
|
||||
{
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void AreNotEqual<T>(T notExpected, T actual, string parameterName, string message)
|
||||
{
|
||||
if (null == notExpected)
|
||||
{
|
||||
// Two nulls are considered equal, regardless of type semantics.
|
||||
if (null == actual || actual.Equals(notExpected))
|
||||
{
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
}
|
||||
else if (notExpected.Equals(actual))
|
||||
{
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void UriIsAbsolute(Uri uri, string parameterName)
|
||||
{
|
||||
Verify.IsNotNull(uri, parameterName);
|
||||
if (!uri.IsAbsoluteUri)
|
||||
{
|
||||
throw new ArgumentException("The URI must be absolute.", parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified value is within the expected range. The assertion fails if it isn't.
|
||||
/// </summary>
|
||||
/// <param name="lowerBoundInclusive">The lower bound inclusive value.</param>
|
||||
/// <param name="value">The value to verify.</param>
|
||||
/// <param name="upperBoundExclusive">The upper bound exclusive value.</param>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive, string parameterName)
|
||||
{
|
||||
if (value < lowerBoundInclusive || value >= upperBoundExclusive)
|
||||
{
|
||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The integer value must be bounded with [{0}, {1})", lowerBoundInclusive, upperBoundExclusive), parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void BoundedDoubleInc(double lowerBoundInclusive, double value, double upperBoundInclusive, string message, string parameter)
|
||||
{
|
||||
if (value < lowerBoundInclusive || value > upperBoundInclusive)
|
||||
{
|
||||
throw new ArgumentException(message, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void TypeSupportsInterface(Type type, Type interfaceType, string parameterName)
|
||||
{
|
||||
Assert.IsNeitherNullNorEmpty(parameterName);
|
||||
Verify.IsNotNull(type, "type");
|
||||
Verify.IsNotNull(interfaceType, "interfaceType");
|
||||
|
||||
if (type.GetInterface(interfaceType.Name) == null)
|
||||
{
|
||||
throw new ArgumentException("The type of this parameter does not support a required interface", parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
public static void FileExists(string filePath, string parameterName)
|
||||
{
|
||||
Verify.IsNeitherNullNorEmpty(filePath, parameterName);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "No file exists at \"{0}\"", filePath), parameterName);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
[DebuggerStepThrough]
|
||||
internal static void ImplementsInterface(object parameter, Type interfaceType, string parameterName)
|
||||
{
|
||||
Assert.IsNotNull(parameter);
|
||||
Assert.IsNotNull(interfaceType);
|
||||
Assert.IsTrue(interfaceType.IsInterface);
|
||||
|
||||
bool isImplemented = false;
|
||||
foreach (var ifaceType in parameter.GetType().GetInterfaces())
|
||||
{
|
||||
if (ifaceType == interfaceType)
|
||||
{
|
||||
isImplemented = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isImplemented)
|
||||
{
|
||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The parameter must implement interface {0}.", interfaceType.ToString()), parameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
107
Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs
Normal file
107
Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemCommands.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
namespace Microsoft.Windows.Shell
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using Standard;
|
||||
|
||||
public static class SystemCommands
|
||||
{
|
||||
public static RoutedCommand CloseWindowCommand { get; private set; }
|
||||
public static RoutedCommand MaximizeWindowCommand { get; private set; }
|
||||
public static RoutedCommand MinimizeWindowCommand { get; private set; }
|
||||
public static RoutedCommand RestoreWindowCommand { get; private set; }
|
||||
public static RoutedCommand ShowSystemMenuCommand { get; private set; }
|
||||
|
||||
static SystemCommands()
|
||||
{
|
||||
CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(SystemCommands));
|
||||
MaximizeWindowCommand = new RoutedCommand("MaximizeWindow", typeof(SystemCommands));
|
||||
MinimizeWindowCommand = new RoutedCommand("MinimizeWindow", typeof(SystemCommands));
|
||||
RestoreWindowCommand = new RoutedCommand("RestoreWindow", typeof(SystemCommands));
|
||||
ShowSystemMenuCommand = new RoutedCommand("ShowSystemMenu", typeof(SystemCommands));
|
||||
}
|
||||
|
||||
private static void _PostSystemCommand(Window window, SC command)
|
||||
{
|
||||
IntPtr hwnd = new WindowInteropHelper(window).Handle;
|
||||
if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr((int)command), IntPtr.Zero);
|
||||
}
|
||||
|
||||
public static void CloseWindow(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
_PostSystemCommand(window, SC.CLOSE);
|
||||
}
|
||||
|
||||
public static void MaximizeWindow(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
_PostSystemCommand(window, SC.MAXIMIZE);
|
||||
}
|
||||
|
||||
public static void MinimizeWindow(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
_PostSystemCommand(window, SC.MINIMIZE);
|
||||
}
|
||||
|
||||
public static void RestoreWindow(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
_PostSystemCommand(window, SC.RESTORE);
|
||||
}
|
||||
|
||||
/// <summary>Display the system menu at a specified location.</summary>
|
||||
/// <param name="screenLocation">The location to display the system menu, in logical screen coordinates.</param>
|
||||
public static void ShowSystemMenu(Window window, Point screenLocation)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
ShowSystemMenuPhysicalCoordinates(window, DpiHelper.LogicalPixelsToDevice(screenLocation));
|
||||
}
|
||||
|
||||
internal static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation)
|
||||
{
|
||||
const uint TPM_RETURNCMD = 0x0100;
|
||||
const uint TPM_LEFTBUTTON = 0x0;
|
||||
|
||||
Verify.IsNotNull(window, "window");
|
||||
IntPtr hwnd = new WindowInteropHelper(window).Handle;
|
||||
if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr hmenu = NativeMethods.GetSystemMenu(hwnd, false);
|
||||
|
||||
uint cmd = NativeMethods.TrackPopupMenuEx(hmenu, TPM_LEFTBUTTON | TPM_RETURNCMD, (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero);
|
||||
if (0 != cmd)
|
||||
{
|
||||
NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
573
Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs
Normal file
573
Src/Xceed.Wpf.AvalonDock/Controls/Shell/SystemParameters2.cs
Normal file
@@ -0,0 +1,573 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Microsoft.Windows.Shell
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Standard;
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")]
|
||||
public class SystemParameters2 : INotifyPropertyChanged
|
||||
{
|
||||
private delegate void _SystemMetricUpdate(IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[ThreadStatic]
|
||||
private static SystemParameters2 _threadLocalSingleton;
|
||||
|
||||
private MessageWindow _messageHwnd;
|
||||
|
||||
private bool _isGlassEnabled;
|
||||
private Color _glassColor;
|
||||
private SolidColorBrush _glassColorBrush;
|
||||
private Thickness _windowResizeBorderThickness;
|
||||
private Thickness _windowNonClientFrameThickness;
|
||||
private double _captionHeight;
|
||||
private Size _smallIconSize;
|
||||
private string _uxThemeName;
|
||||
private string _uxThemeColor;
|
||||
private bool _isHighContrast;
|
||||
private CornerRadius _windowCornerRadius;
|
||||
private Rect _captionButtonLocation;
|
||||
|
||||
private readonly Dictionary<WM, List<_SystemMetricUpdate>> _UpdateTable;
|
||||
|
||||
#region Initialization and Update Methods
|
||||
|
||||
// Most properties exposed here have a way of being queried directly
|
||||
// and a way of being notified of updates via a window message.
|
||||
// This region is a grouping of both, for each of the exposed properties.
|
||||
|
||||
private void _InitializeIsGlassEnabled()
|
||||
{
|
||||
IsGlassEnabled = NativeMethods.DwmIsCompositionEnabled();
|
||||
}
|
||||
|
||||
private void _UpdateIsGlassEnabled(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
// Neither the wParam or lParam are used in this case.
|
||||
_InitializeIsGlassEnabled();
|
||||
}
|
||||
|
||||
private void _InitializeGlassColor()
|
||||
{
|
||||
bool isOpaque;
|
||||
uint color;
|
||||
NativeMethods.DwmGetColorizationColor(out color, out isOpaque);
|
||||
color |= isOpaque ? 0xFF000000 : 0;
|
||||
|
||||
WindowGlassColor = Utility.ColorFromArgbDword(color);
|
||||
|
||||
var glassBrush = new SolidColorBrush(WindowGlassColor);
|
||||
glassBrush.Freeze();
|
||||
|
||||
WindowGlassBrush = glassBrush;
|
||||
}
|
||||
|
||||
private void _UpdateGlassColor(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
bool isOpaque = lParam != IntPtr.Zero;
|
||||
uint color = unchecked((uint)(int)wParam.ToInt64());
|
||||
color |= isOpaque ? 0xFF000000 : 0;
|
||||
WindowGlassColor = Utility.ColorFromArgbDword(color);
|
||||
var glassBrush = new SolidColorBrush(WindowGlassColor);
|
||||
glassBrush.Freeze();
|
||||
WindowGlassBrush = glassBrush;
|
||||
}
|
||||
|
||||
private void _InitializeCaptionHeight()
|
||||
{
|
||||
Point ptCaption = new Point(0, NativeMethods.GetSystemMetrics(SM.CYCAPTION));
|
||||
WindowCaptionHeight = DpiHelper.DevicePixelsToLogical(ptCaption).Y;
|
||||
}
|
||||
|
||||
private void _UpdateCaptionHeight(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeCaptionHeight();
|
||||
}
|
||||
|
||||
private void _InitializeWindowResizeBorderThickness()
|
||||
{
|
||||
Size frameSize = new Size(
|
||||
NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME),
|
||||
NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME));
|
||||
Size frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize);
|
||||
WindowResizeBorderThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height, frameSizeInDips.Width, frameSizeInDips.Height);
|
||||
}
|
||||
|
||||
private void _UpdateWindowResizeBorderThickness(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeWindowResizeBorderThickness();
|
||||
}
|
||||
|
||||
private void _InitializeWindowNonClientFrameThickness()
|
||||
{
|
||||
Size frameSize = new Size(
|
||||
NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME),
|
||||
NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME));
|
||||
Size frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize);
|
||||
int captionHeight = NativeMethods.GetSystemMetrics(SM.CYCAPTION);
|
||||
double captionHeightInDips = DpiHelper.DevicePixelsToLogical(new Point(0, captionHeight)).Y;
|
||||
WindowNonClientFrameThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height + captionHeightInDips, frameSizeInDips.Width, frameSizeInDips.Height);
|
||||
}
|
||||
|
||||
private void _UpdateWindowNonClientFrameThickness(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeWindowNonClientFrameThickness();
|
||||
}
|
||||
|
||||
private void _InitializeSmallIconSize()
|
||||
{
|
||||
SmallIconSize = new Size(
|
||||
NativeMethods.GetSystemMetrics(SM.CXSMICON),
|
||||
NativeMethods.GetSystemMetrics(SM.CYSMICON));
|
||||
}
|
||||
|
||||
private void _UpdateSmallIconSize(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeSmallIconSize();
|
||||
}
|
||||
|
||||
private void _LegacyInitializeCaptionButtonLocation()
|
||||
{
|
||||
// This calculation isn't quite right, but it's pretty close.
|
||||
// I expect this is good enough for the scenarios where this is expected to be used.
|
||||
int captionX = NativeMethods.GetSystemMetrics(SM.CXSIZE);
|
||||
int captionY = NativeMethods.GetSystemMetrics(SM.CYSIZE);
|
||||
|
||||
int frameX = NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME) + NativeMethods.GetSystemMetrics(SM.CXEDGE);
|
||||
int frameY = NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME) + NativeMethods.GetSystemMetrics(SM.CYEDGE);
|
||||
|
||||
Rect captionRect = new Rect(0, 0, captionX * 3, captionY);
|
||||
captionRect.Offset(-frameX - captionRect.Width, frameY);
|
||||
|
||||
WindowCaptionButtonsLocation = captionRect;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
private void _InitializeCaptionButtonLocation()
|
||||
{
|
||||
// There is a completely different way to do this on XP.
|
||||
if (!Utility.IsOSVistaOrNewer || !NativeMethods.IsThemeActive())
|
||||
{
|
||||
_LegacyInitializeCaptionButtonLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
var tbix = new TITLEBARINFOEX { cbSize = Marshal.SizeOf(typeof(TITLEBARINFOEX)) };
|
||||
IntPtr lParam = Marshal.AllocHGlobal(tbix.cbSize);
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(tbix, lParam, false);
|
||||
// This might flash a window in the taskbar while being calculated.
|
||||
// WM_GETTITLEBARINFOEX doesn't work correctly unless the window is visible while processing.
|
||||
NativeMethods.ShowWindow(_messageHwnd.Handle, SW.SHOW);
|
||||
NativeMethods.SendMessage(_messageHwnd.Handle, WM.GETTITLEBARINFOEX, IntPtr.Zero, lParam);
|
||||
tbix = (TITLEBARINFOEX)Marshal.PtrToStructure(lParam, typeof(TITLEBARINFOEX));
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.ShowWindow(_messageHwnd.Handle, SW.HIDE);
|
||||
Utility.SafeFreeHGlobal(ref lParam);
|
||||
}
|
||||
|
||||
// TITLEBARINFOEX has information relative to the screen. We need to convert the containing rect
|
||||
// to instead be relative to the top-right corner of the window.
|
||||
RECT rcAllCaptionButtons = RECT.Union(tbix.rgrect_CloseButton, tbix.rgrect_MinimizeButton);
|
||||
// For all known themes, the RECT for the maximize box shouldn't add anything to the union of the minimize and close boxes.
|
||||
Assert.AreEqual(rcAllCaptionButtons, RECT.Union(rcAllCaptionButtons, tbix.rgrect_MaximizeButton));
|
||||
|
||||
RECT rcWindow = NativeMethods.GetWindowRect(_messageHwnd.Handle);
|
||||
|
||||
// Reorient the Top/Right to be relative to the top right edge of the Window.
|
||||
var deviceCaptionLocation = new Rect(
|
||||
rcAllCaptionButtons.Left - rcWindow.Width - rcWindow.Left,
|
||||
rcAllCaptionButtons.Top - rcWindow.Top,
|
||||
rcAllCaptionButtons.Width,
|
||||
rcAllCaptionButtons.Height);
|
||||
|
||||
Rect logicalCaptionLocation = DpiHelper.DeviceRectToLogical(deviceCaptionLocation);
|
||||
|
||||
WindowCaptionButtonsLocation = logicalCaptionLocation;
|
||||
}
|
||||
|
||||
private void _UpdateCaptionButtonLocation(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeCaptionButtonLocation();
|
||||
}
|
||||
|
||||
private void _InitializeHighContrast()
|
||||
{
|
||||
HIGHCONTRAST hc = NativeMethods.SystemParameterInfo_GetHIGHCONTRAST();
|
||||
HighContrast = (hc.dwFlags & HCF.HIGHCONTRASTON) != 0;
|
||||
}
|
||||
|
||||
private void _UpdateHighContrast(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeHighContrast();
|
||||
}
|
||||
|
||||
private void _InitializeThemeInfo()
|
||||
{
|
||||
if (!NativeMethods.IsThemeActive())
|
||||
{
|
||||
UxThemeName = "Classic";
|
||||
UxThemeColor = "";
|
||||
return;
|
||||
}
|
||||
|
||||
string name;
|
||||
string color;
|
||||
string size;
|
||||
NativeMethods.GetCurrentThemeName(out name, out color, out size);
|
||||
|
||||
// Consider whether this is the most useful way to expose this...
|
||||
UxThemeName = System.IO.Path.GetFileNameWithoutExtension(name);
|
||||
UxThemeColor = color;
|
||||
}
|
||||
|
||||
private void _UpdateThemeInfo(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
_InitializeThemeInfo();
|
||||
}
|
||||
|
||||
private void _InitializeWindowCornerRadius()
|
||||
{
|
||||
// The radius of window corners isn't exposed as a true system parameter.
|
||||
// It instead is a logical size that we're approximating based on the current theme.
|
||||
// There aren't any known variations based on theme color.
|
||||
Assert.IsNeitherNullNorEmpty(UxThemeName);
|
||||
|
||||
// These radii are approximate. The way WPF does rounding is different than how
|
||||
// rounded-rectangle HRGNs are created, which is also different than the actual
|
||||
// round corners on themed Windows. For now we're not exposing anything to
|
||||
// mitigate the differences.
|
||||
var cornerRadius = default(CornerRadius);
|
||||
|
||||
// This list is known to be incomplete and very much not future-proof.
|
||||
// On XP there are at least a couple of shipped themes that this won't catch,
|
||||
// "Zune" and "Royale", but WPF doesn't know about these either.
|
||||
// If a new theme was to replace Aero, then this will fall back on "classic" behaviors.
|
||||
// This isn't ideal, but it's not the end of the world. WPF will generally have problems anyways.
|
||||
switch (UxThemeName.ToUpperInvariant())
|
||||
{
|
||||
case "LUNA":
|
||||
cornerRadius = new CornerRadius(6, 6, 0, 0);
|
||||
break;
|
||||
case "AERO":
|
||||
// Aero has two cases. One with glass and one without...
|
||||
if (NativeMethods.DwmIsCompositionEnabled())
|
||||
{
|
||||
cornerRadius = new CornerRadius(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
cornerRadius = new CornerRadius(6, 6, 0, 0);
|
||||
}
|
||||
break;
|
||||
case "CLASSIC":
|
||||
case "ZUNE":
|
||||
case "ROYALE":
|
||||
default:
|
||||
cornerRadius = new CornerRadius(0);
|
||||
break;
|
||||
}
|
||||
|
||||
WindowCornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
private void _UpdateWindowCornerRadius(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
// Neither the wParam or lParam are used in this case.
|
||||
_InitializeWindowCornerRadius();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor. The public way to access this class is through the static Current property.
|
||||
/// </summary>
|
||||
private SystemParameters2()
|
||||
{
|
||||
// This window gets used for calculations about standard caption button locations
|
||||
// so it has WS_OVERLAPPEDWINDOW as a style to give it normal caption buttons.
|
||||
// This window may be shown during calculations of caption bar information, so create it at a location that's likely offscreen.
|
||||
_messageHwnd = new MessageWindow((CS)0, WS.OVERLAPPEDWINDOW | WS.DISABLED, (WS_EX)0, new Rect(-16000, -16000, 100, 100), "", _WndProc);
|
||||
_messageHwnd.Dispatcher.ShutdownStarted += (sender, e) => Utility.SafeDispose(ref _messageHwnd);
|
||||
|
||||
// Fixup the default values of the DPs.
|
||||
_InitializeIsGlassEnabled();
|
||||
_InitializeGlassColor();
|
||||
_InitializeCaptionHeight();
|
||||
_InitializeWindowNonClientFrameThickness();
|
||||
_InitializeWindowResizeBorderThickness();
|
||||
_InitializeCaptionButtonLocation();
|
||||
_InitializeSmallIconSize();
|
||||
_InitializeHighContrast();
|
||||
_InitializeThemeInfo();
|
||||
// WindowCornerRadius isn't exposed by true system parameters, so it requires the theme to be initialized first.
|
||||
_InitializeWindowCornerRadius();
|
||||
|
||||
_UpdateTable = new Dictionary<WM, List<_SystemMetricUpdate>>
|
||||
{
|
||||
{ WM.THEMECHANGED,
|
||||
new List<_SystemMetricUpdate>
|
||||
{
|
||||
_UpdateThemeInfo,
|
||||
_UpdateHighContrast,
|
||||
_UpdateWindowCornerRadius,
|
||||
_UpdateCaptionButtonLocation, } },
|
||||
{ WM.SETTINGCHANGE,
|
||||
new List<_SystemMetricUpdate>
|
||||
{
|
||||
_UpdateCaptionHeight,
|
||||
_UpdateWindowResizeBorderThickness,
|
||||
_UpdateSmallIconSize,
|
||||
_UpdateHighContrast,
|
||||
_UpdateWindowNonClientFrameThickness,
|
||||
_UpdateCaptionButtonLocation, } },
|
||||
{ WM.DWMNCRENDERINGCHANGED, new List<_SystemMetricUpdate> { _UpdateIsGlassEnabled } },
|
||||
{ WM.DWMCOMPOSITIONCHANGED, new List<_SystemMetricUpdate> { _UpdateIsGlassEnabled } },
|
||||
{ WM.DWMCOLORIZATIONCOLORCHANGED, new List<_SystemMetricUpdate> { _UpdateGlassColor } },
|
||||
};
|
||||
}
|
||||
|
||||
public static SystemParameters2 Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_threadLocalSingleton == null)
|
||||
{
|
||||
_threadLocalSingleton = new SystemParameters2();
|
||||
}
|
||||
return _threadLocalSingleton;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
// Don't do this if called within the SystemParameters2 constructor
|
||||
if (_UpdateTable != null)
|
||||
{
|
||||
List<_SystemMetricUpdate> handlers;
|
||||
if (_UpdateTable.TryGetValue(msg, out handlers))
|
||||
{
|
||||
Assert.IsNotNull(handlers);
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
handler(wParam, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
public bool IsGlassEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
// return _isGlassEnabled;
|
||||
// It turns out there may be some lag between someone asking this
|
||||
// and the window getting updated. It's not too expensive, just always do the check.
|
||||
return NativeMethods.DwmIsCompositionEnabled();
|
||||
}
|
||||
private set
|
||||
{
|
||||
if (value != _isGlassEnabled)
|
||||
{
|
||||
_isGlassEnabled = value;
|
||||
_NotifyPropertyChanged("IsGlassEnabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Color WindowGlassColor
|
||||
{
|
||||
get { return _glassColor; }
|
||||
private set
|
||||
{
|
||||
if (value != _glassColor)
|
||||
{
|
||||
_glassColor = value;
|
||||
_NotifyPropertyChanged("WindowGlassColor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SolidColorBrush WindowGlassBrush
|
||||
{
|
||||
get { return _glassColorBrush; }
|
||||
private set
|
||||
{
|
||||
Assert.IsNotNull(value);
|
||||
Assert.IsTrue(value.IsFrozen);
|
||||
if (_glassColorBrush == null || value.Color != _glassColorBrush.Color)
|
||||
{
|
||||
_glassColorBrush = value;
|
||||
_NotifyPropertyChanged("WindowGlassBrush");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Thickness WindowResizeBorderThickness
|
||||
{
|
||||
get { return _windowResizeBorderThickness; }
|
||||
private set
|
||||
{
|
||||
if (value != _windowResizeBorderThickness)
|
||||
{
|
||||
_windowResizeBorderThickness = value;
|
||||
_NotifyPropertyChanged("WindowResizeBorderThickness");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Thickness WindowNonClientFrameThickness
|
||||
{
|
||||
get { return _windowNonClientFrameThickness; }
|
||||
private set
|
||||
{
|
||||
if (value != _windowNonClientFrameThickness)
|
||||
{
|
||||
_windowNonClientFrameThickness = value;
|
||||
_NotifyPropertyChanged("WindowNonClientFrameThickness");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double WindowCaptionHeight
|
||||
{
|
||||
get { return _captionHeight; }
|
||||
private set
|
||||
{
|
||||
if (value != _captionHeight)
|
||||
{
|
||||
_captionHeight = value;
|
||||
_NotifyPropertyChanged("WindowCaptionHeight");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Size SmallIconSize
|
||||
{
|
||||
get { return new Size(_smallIconSize.Width, _smallIconSize.Height); }
|
||||
private set
|
||||
{
|
||||
if (value != _smallIconSize)
|
||||
{
|
||||
_smallIconSize = value;
|
||||
_NotifyPropertyChanged("SmallIconSize");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux")]
|
||||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux")]
|
||||
public string UxThemeName
|
||||
{
|
||||
get { return _uxThemeName; }
|
||||
private set
|
||||
{
|
||||
if (value != _uxThemeName)
|
||||
{
|
||||
_uxThemeName = value;
|
||||
_NotifyPropertyChanged("UxThemeName");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ux")]
|
||||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ux")]
|
||||
public string UxThemeColor
|
||||
{
|
||||
get { return _uxThemeColor; }
|
||||
private set
|
||||
{
|
||||
if (value != _uxThemeColor)
|
||||
{
|
||||
_uxThemeColor = value;
|
||||
_NotifyPropertyChanged("UxThemeColor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HighContrast
|
||||
{
|
||||
get { return _isHighContrast; }
|
||||
private set
|
||||
{
|
||||
if (value != _isHighContrast)
|
||||
{
|
||||
_isHighContrast = value;
|
||||
_NotifyPropertyChanged("HighContrast");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CornerRadius WindowCornerRadius
|
||||
{
|
||||
get { return _windowCornerRadius; }
|
||||
private set
|
||||
{
|
||||
if (value != _windowCornerRadius)
|
||||
{
|
||||
_windowCornerRadius = value;
|
||||
_NotifyPropertyChanged("WindowCornerRadius");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rect WindowCaptionButtonsLocation
|
||||
{
|
||||
get { return _captionButtonLocation; }
|
||||
private set
|
||||
{
|
||||
if (value != _captionButtonLocation)
|
||||
{
|
||||
_captionButtonLocation = value;
|
||||
_NotifyPropertyChanged("WindowCaptionButtonsLocation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged Members
|
||||
|
||||
private void _NotifyPropertyChanged(string propertyName)
|
||||
{
|
||||
Assert.IsNeitherNullNorEmpty(propertyName);
|
||||
var handler = PropertyChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
267
Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs
Normal file
267
Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChrome.cs
Normal file
@@ -0,0 +1,267 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Extended WPF Toolkit
|
||||
|
||||
Copyright (C) 2007-2013 Xceed Software Inc.
|
||||
|
||||
This program is provided to you under the terms of the Microsoft Public
|
||||
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
||||
|
||||
For more features, controls, and fast professional support,
|
||||
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
||||
|
||||
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
||||
|
||||
***********************************************************************************/
|
||||
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
|
||||
namespace Microsoft.Windows.Shell
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using Standard;
|
||||
|
||||
public class WindowChrome : Freezable
|
||||
{
|
||||
private struct _SystemParameterBoundProperty
|
||||
{
|
||||
public string SystemParameterPropertyName { get; set; }
|
||||
public DependencyProperty DependencyProperty { get; set; }
|
||||
}
|
||||
|
||||
// Named property available for fully extending the glass frame.
|
||||
public static Thickness GlassFrameCompleteThickness { get { return new Thickness(-1); } }
|
||||
|
||||
#region Attached Properties
|
||||
|
||||
public static readonly DependencyProperty WindowChromeProperty = DependencyProperty.RegisterAttached(
|
||||
"WindowChrome",
|
||||
typeof(WindowChrome),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(null, _OnChromeChanged));
|
||||
|
||||
private static void _OnChromeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// The different design tools handle drawing outside their custom window objects differently.
|
||||
// Rather than try to support this concept in the design surface let the designer draw its own
|
||||
// chrome anyways.
|
||||
// There's certainly room for improvement here.
|
||||
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var window = (Window)d;
|
||||
var newChrome = (WindowChrome)e.NewValue;
|
||||
|
||||
Assert.IsNotNull(window);
|
||||
|
||||
// Update the ChromeWorker with this new object.
|
||||
|
||||
// If there isn't currently a worker associated with the Window then assign a new one.
|
||||
// There can be a many:1 relationship of to Window to WindowChrome objects, but a 1:1 for a Window and a WindowChromeWorker.
|
||||
WindowChromeWorker chromeWorker = WindowChromeWorker.GetWindowChromeWorker(window);
|
||||
if (chromeWorker == null)
|
||||
{
|
||||
chromeWorker = new WindowChromeWorker();
|
||||
WindowChromeWorker.SetWindowChromeWorker(window, chromeWorker);
|
||||
}
|
||||
|
||||
chromeWorker.SetWindowChrome(newChrome);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static WindowChrome GetWindowChrome(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
return (WindowChrome)window.GetValue(WindowChromeProperty);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static void SetWindowChrome(Window window, WindowChrome chrome)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
window.SetValue(WindowChromeProperty, chrome);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsHitTestVisibleInChromeProperty = DependencyProperty.RegisterAttached(
|
||||
"IsHitTestVisibleInChrome",
|
||||
typeof(bool),
|
||||
typeof(WindowChrome),
|
||||
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static bool GetIsHitTestVisibleInChrome(IInputElement inputElement)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
return (bool)dobj.GetValue(IsHitTestVisibleInChromeProperty);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static void SetIsHitTestVisibleInChrome(IInputElement inputElement, bool hitTestVisible)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
dobj.SetValue(IsHitTestVisibleInChromeProperty, hitTestVisible);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependency Properties
|
||||
|
||||
public static readonly DependencyProperty CaptionHeightProperty = DependencyProperty.Register(
|
||||
"CaptionHeight",
|
||||
typeof(double),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
0d,
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()),
|
||||
value => (double)value >= 0d);
|
||||
|
||||
/// <summary>The extent of the top of the window to treat as the caption.</summary>
|
||||
public double CaptionHeight
|
||||
{
|
||||
get { return (double)GetValue(CaptionHeightProperty); }
|
||||
set { SetValue(CaptionHeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResizeBorderThicknessProperty = DependencyProperty.Register(
|
||||
"ResizeBorderThickness",
|
||||
typeof(Thickness),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(default(Thickness)),
|
||||
(value) => Utility.IsThicknessNonNegative((Thickness)value));
|
||||
|
||||
public Thickness ResizeBorderThickness
|
||||
{
|
||||
get { return (Thickness)GetValue(ResizeBorderThicknessProperty); }
|
||||
set { SetValue(ResizeBorderThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty GlassFrameThicknessProperty = DependencyProperty.Register(
|
||||
"GlassFrameThickness",
|
||||
typeof(Thickness),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
default(Thickness),
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint(),
|
||||
(d, o) => _CoerceGlassFrameThickness((Thickness)o)));
|
||||
|
||||
private static object _CoerceGlassFrameThickness(Thickness thickness)
|
||||
{
|
||||
// If it's explicitly set, but set to a thickness with at least one negative side then
|
||||
// coerce the value to the stock GlassFrameCompleteThickness.
|
||||
if (!Utility.IsThicknessNonNegative(thickness))
|
||||
{
|
||||
return GlassFrameCompleteThickness;
|
||||
}
|
||||
|
||||
return thickness;
|
||||
}
|
||||
public Thickness GlassFrameThickness
|
||||
{
|
||||
get { return (Thickness)GetValue(GlassFrameThicknessProperty); }
|
||||
set { SetValue(GlassFrameThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
|
||||
"CornerRadius",
|
||||
typeof(CornerRadius),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
default(CornerRadius),
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()),
|
||||
(value) => Utility.IsCornerRadiusValid((CornerRadius)value));
|
||||
|
||||
public CornerRadius CornerRadius
|
||||
{
|
||||
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
|
||||
set { SetValue(CornerRadiusProperty, value); }
|
||||
}
|
||||
|
||||
#region ShowSystemMenu
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ShowSystemMenu property. This dependency property
|
||||
/// indicates if the system menu should be shown at right click on the caption.
|
||||
/// </summary>
|
||||
public bool ShowSystemMenu
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new WindowChrome();
|
||||
}
|
||||
|
||||
private static readonly List<_SystemParameterBoundProperty> _BoundProperties = new List<_SystemParameterBoundProperty>
|
||||
{
|
||||
new _SystemParameterBoundProperty { DependencyProperty = CornerRadiusProperty, SystemParameterPropertyName = "WindowCornerRadius" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = CaptionHeightProperty, SystemParameterPropertyName = "WindowCaptionHeight" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = ResizeBorderThicknessProperty, SystemParameterPropertyName = "WindowResizeBorderThickness" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = GlassFrameThicknessProperty, SystemParameterPropertyName = "WindowNonClientFrameThickness" },
|
||||
};
|
||||
|
||||
public WindowChrome()
|
||||
{
|
||||
// Effective default values for some of these properties are set to be bindings
|
||||
// that set them to system defaults.
|
||||
// A more correct way to do this would be to Coerce the value iff the source of the DP was the default value.
|
||||
// Unfortunately with the current property system we can't detect whether the value being applied at the time
|
||||
// of the coersion is the default.
|
||||
foreach (var bp in _BoundProperties)
|
||||
{
|
||||
// This list must be declared after the DP's are assigned.
|
||||
Assert.IsNotNull(bp.DependencyProperty);
|
||||
BindingOperations.SetBinding(
|
||||
this,
|
||||
bp.DependencyProperty,
|
||||
new Binding
|
||||
{
|
||||
Source = SystemParameters2.Current,
|
||||
Path = new PropertyPath(bp.SystemParameterPropertyName),
|
||||
Mode = BindingMode.OneWay,
|
||||
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void _OnPropertyChangedThatRequiresRepaint()
|
||||
{
|
||||
var handler = PropertyChangedThatRequiresRepaint;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
internal event EventHandler PropertyChangedThatRequiresRepaint;
|
||||
}
|
||||
}
|
||||
1227
Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs
Normal file
1227
Src/Xceed.Wpf.AvalonDock/Controls/Shell/WindowChromeWorker.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user