├── .gitignore
├── Microsoft.Windows.Shell.sln
├── Microsoft.Windows.Shell
├── JumpItem.cs
├── JumpList.cs
├── JumpPath.cs
├── JumpTask.cs
├── Microsoft.Windows.Shell.v35.csproj
├── Microsoft.Windows.Shell.v4.csproj
├── Properties
│ └── AssemblyInfo.cs
├── SystemCommands.cs
├── SystemParameters2.cs
├── TaskbarItemInfo.cs
├── ThumbButtonInfo.cs
├── ThumbButtonInfoCollection.cs
├── WindowChrome.cs
├── WindowChromeWorker.cs
└── standard.net
│ ├── Csv.cs
│ ├── Debug.cs
│ ├── DoubleUtil.cs
│ ├── Enumerable2.cs
│ ├── MergeableCollection.cs
│ ├── NotifyingList.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── README.md
│ ├── SmallString.cs
│ ├── SmallUri.cs
│ ├── Standard.Native.csproj
│ ├── Standard.Wpf.csproj
│ ├── Standard.csproj
│ ├── Standard.sln
│ ├── Utilities.cs
│ ├── Verify.cs
│ ├── Windows
│ ├── ComGuids.cs
│ ├── ErrorCodes.cs
│ ├── FileWalker.cs
│ ├── NativeMethods.cs
│ ├── ShellProvider.cs
│ ├── StreamHelper.cs
│ ├── Utilities.Windows.cs
│ └── WicProvider.cs
│ └── Wpf
│ ├── CornerRadiusAnimation.cs
│ ├── CornerRadiusAnimationBase.cs
│ ├── DpiHelper.cs
│ ├── GlassHelper.cs
│ ├── MessageWindow.cs
│ ├── MshtmlProvider.cs
│ ├── SingleInstance.cs
│ ├── SplashScreen.cs
│ ├── Utilities.Wpf.cs
│ └── WindowExtensions.cs
├── README.md
├── TaskbarSample
├── App.xaml
├── App.xaml.cs
├── Images
│ ├── CircleGreen.png
│ ├── CircleRed.png
│ ├── CircleYellow.png
│ ├── Copy.png
│ ├── Cut.png
│ └── Paste.png
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ └── AssemblyInfo.cs
├── TaskbarSample.csproj
├── app.config
└── app.ico
├── WindowChromeSample
├── App.xaml
├── CaptionButtonRectToMarginConverter.cs
├── Properties
│ └── AssemblyInfo.cs
├── SelectableChromeWindow.xaml
├── SelectableChromeWindow.xaml.cs
├── WindowChromeSample.csproj
├── app.config
└── app.ico
└── license.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
110 | .DS_Store
111 |
112 | *.swp
113 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaskbarSample", "TaskbarSample\TaskbarSample.csproj", "{F7D0B052-2123-4DFD-B844-C545A1082514}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowChromeSample", "WindowChromeSample\WindowChromeSample.csproj", "{7E654166-1387-43D9-956C-6B473C514545}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Windows.Shell.v4", "Microsoft.Windows.Shell\Microsoft.Windows.Shell.v4.csproj", "{55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Windows.Shell.v35", "Microsoft.Windows.Shell\Microsoft.Windows.Shell.v35.csproj", "{8F016757-F022-4338-9989-9CEE39BFC087}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {F7D0B052-2123-4DFD-B844-C545A1082514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {F7D0B052-2123-4DFD-B844-C545A1082514}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {7E654166-1387-43D9-956C-6B473C514545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {7E654166-1387-43D9-956C-6B473C514545}.Release|Any CPU.ActiveCfg = Release|Any CPU
22 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {8F016757-F022-4338-9989-9CEE39BFC087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {8F016757-F022-4338-9989-9CEE39BFC087}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {8F016757-F022-4338-9989-9CEE39BFC087}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {8F016757-F022-4338-9989-9CEE39BFC087}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/JumpItem.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | namespace Microsoft.Windows.Shell
6 | {
7 | public abstract class JumpItem
8 | {
9 | // This class is just provided to strongly type the JumpList's contents.
10 | // It's not externally extendable.
11 | internal JumpItem()
12 | {
13 | }
14 |
15 | public string CustomCategory { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/JumpPath.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | namespace Microsoft.Windows.Shell
6 | {
7 | public class JumpPath : JumpItem
8 | {
9 | public JumpPath()
10 | {}
11 |
12 | public string Path { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/JumpTask.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | namespace Microsoft.Windows.Shell
6 | {
7 | public class JumpTask : JumpItem
8 | {
9 | public JumpTask()
10 | {}
11 |
12 | public string Title { get; set; }
13 |
14 | public string Description { get; set; }
15 |
16 | public string ApplicationPath { get; set; }
17 |
18 | public string Arguments { get; set; }
19 |
20 | public string WorkingDirectory { get; set; }
21 |
22 | public string IconResourcePath { get; set; }
23 |
24 | public int IconResourceIndex { get; set; }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/Microsoft.Windows.Shell.v35.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {8F016757-F022-4338-9989-9CEE39BFC087}
9 | Library
10 | Properties
11 | Microsoft.Windows.Shell
12 | Microsoft.Windows.Shell
13 | v3.5
14 | 512
15 | false
16 | true
17 | Disk
18 | false
19 | Client
20 |
21 |
22 | true
23 | full
24 | false
25 | bin35\Debug\
26 | TRACE;DEBUG;CODE_ANALYSIS
27 | prompt
28 | 4
29 | true
30 | AllRules.ruleset
31 |
32 |
33 | pdbonly
34 | true
35 | bin35\Release\
36 | TRACE
37 | prompt
38 | 4
39 | true
40 | AllRules.ruleset
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/Microsoft.Windows.Shell.v4.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB}
9 | Library
10 | Properties
11 | Microsoft.Windows.Shell
12 | Microsoft.Windows.Shell
13 | v4.0
14 | 512
15 | false
16 | true
17 | Disk
18 | false
19 | Client
20 |
21 |
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | TRACE;DEBUG;CODE_ANALYSIS
27 | prompt
28 | 4
29 | true
30 | AllRules.ruleset
31 |
32 |
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE
37 | prompt
38 | 4
39 | true
40 | AllRules.ruleset
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | using System;
6 | using System.Diagnostics.CodeAnalysis;
7 | using System.Reflection;
8 | using System.Runtime.InteropServices;
9 | using System.Windows.Markup;
10 |
11 | [assembly: AssemblyTitle("Microsoft.Windows.Shell")]
12 | [assembly: AssemblyDescription("Windows 7 shell integration library for WPF")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("Microsoft")]
15 | [assembly: AssemblyProduct("Microsoft.Windows.Shell")]
16 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | [assembly: ComVisible(false)]
21 | [assembly: Guid("573618e1-4f3f-4395-a3bf-ffebfb342917")]
22 | [assembly: CLSCompliant(true)]
23 |
24 | [assembly: AssemblyVersion("3.0.1.0")]
25 | [assembly: AssemblyFileVersion("3.0.1.0")]
26 |
27 | [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell", "Microsoft.Windows.Shell")]
28 |
29 | // Code analysis suppressions:
30 | [assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Standard", Justification="Internal-only namespace")]
31 | [assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification="Assembly has strong name when published")]
32 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/SystemCommands.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Microsoft.Windows.Shell
3 | {
4 | using System;
5 | using System.Windows;
6 | using System.Windows.Input;
7 | using System.Windows.Interop;
8 | using Standard;
9 |
10 | public static class SystemCommands
11 | {
12 | public static RoutedCommand CloseWindowCommand { get; private set; }
13 | public static RoutedCommand MaximizeWindowCommand { get; private set; }
14 | public static RoutedCommand MinimizeWindowCommand { get; private set; }
15 | public static RoutedCommand RestoreWindowCommand { get; private set; }
16 | public static RoutedCommand ShowSystemMenuCommand { get; private set; }
17 |
18 | static SystemCommands()
19 | {
20 | CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(SystemCommands));
21 | MaximizeWindowCommand = new RoutedCommand("MaximizeWindow", typeof(SystemCommands));
22 | MinimizeWindowCommand = new RoutedCommand("MinimizeWindow", typeof(SystemCommands));
23 | RestoreWindowCommand = new RoutedCommand("RestoreWindow", typeof(SystemCommands));
24 | ShowSystemMenuCommand = new RoutedCommand("ShowSystemMenu", typeof(SystemCommands));
25 | }
26 |
27 | private static void _PostSystemCommand(Window window, SC command)
28 | {
29 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
30 | if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
31 | {
32 | return;
33 | }
34 |
35 | NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr((int)command), IntPtr.Zero);
36 | }
37 |
38 | public static void CloseWindow(Window window)
39 | {
40 | Verify.IsNotNull(window, "window");
41 | _PostSystemCommand(window, SC.CLOSE);
42 | }
43 |
44 | public static void MaximizeWindow(Window window)
45 | {
46 | Verify.IsNotNull(window, "window");
47 | _PostSystemCommand(window, SC.MAXIMIZE);
48 | }
49 |
50 | public static void MinimizeWindow(Window window)
51 | {
52 | Verify.IsNotNull(window, "window");
53 | _PostSystemCommand(window, SC.MINIMIZE);
54 | }
55 |
56 | public static void RestoreWindow(Window window)
57 | {
58 | Verify.IsNotNull(window, "window");
59 | _PostSystemCommand(window, SC.RESTORE);
60 | }
61 |
62 | /// Display the system menu at a specified location.
63 | /// The location to display the system menu, in logical screen coordinates.
64 | public static void ShowSystemMenu(Window window, Point screenLocation)
65 | {
66 | Verify.IsNotNull(window, "window");
67 | ShowSystemMenuPhysicalCoordinates(window, DpiHelper.LogicalPixelsToDevice(screenLocation));
68 | }
69 |
70 | internal static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation)
71 | {
72 | const uint TPM_RETURNCMD = 0x0100;
73 | const uint TPM_LEFTBUTTON = 0x0;
74 |
75 | Verify.IsNotNull(window, "window");
76 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
77 | if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
78 | {
79 | return;
80 | }
81 |
82 | IntPtr hmenu = NativeMethods.GetSystemMenu(hwnd, false);
83 |
84 | uint cmd = NativeMethods.TrackPopupMenuEx(hmenu, TPM_LEFTBUTTON | TPM_RETURNCMD, (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero);
85 | if (0 != cmd)
86 | {
87 | NativeMethods.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero);
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/ThumbButtonInfo.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | namespace Microsoft.Windows.Shell
6 | {
7 | using System;
8 | using System.Diagnostics;
9 | using System.Windows;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.ComponentModel;
13 | using Standard;
14 |
15 | // This class doesn't lend itself to designer support, but still decorating the DefaultEvent.
16 | [DefaultEvent("Click")]
17 | public sealed class ThumbButtonInfo : Freezable, ICommandSource
18 | {
19 | // The CommandManager keeps weak references on delegates
20 | // hooked for CanExecuteChanged. We need to explicitly keep a
21 | // strong reference, because just adding an instance method causes
22 | // the auto-generated handler to be GC'd.
23 | private EventHandler _commandEvent;
24 |
25 | protected override Freezable CreateInstanceCore()
26 | {
27 | return new ThumbButtonInfo();
28 | }
29 |
30 | #region Dependency Properties and support methods
31 |
32 | public static readonly DependencyProperty VisibilityProperty = DependencyProperty.Register(
33 | "Visibility",
34 | typeof(Visibility),
35 | typeof(ThumbButtonInfo),
36 | new PropertyMetadata(Visibility.Visible));
37 |
38 | ///
39 | /// Gets or sets the whether this should be visible in the UI.
40 | ///
41 | public Visibility Visibility
42 | {
43 | get { return (Visibility)GetValue(VisibilityProperty); }
44 | set { SetValue(VisibilityProperty, value); }
45 | }
46 |
47 | public static readonly DependencyProperty DismissWhenClickedProperty = DependencyProperty.Register(
48 | "DismissWhenClicked",
49 | typeof(bool),
50 | typeof(ThumbButtonInfo),
51 | new PropertyMetadata(false));
52 |
53 | ///
54 | /// Gets or sets the DismissWhenClicked property. This dependency property
55 | /// indicates whether the thumbnail window should disappear as a result
56 | /// of the user clicking this button.
57 | ///
58 | public bool DismissWhenClicked
59 | {
60 | get { return (bool)GetValue(DismissWhenClickedProperty); }
61 | set { SetValue(DismissWhenClickedProperty, value); }
62 | }
63 |
64 | public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
65 | "ImageSource",
66 | typeof(ImageSource),
67 | typeof(ThumbButtonInfo),
68 | new PropertyMetadata(null));
69 |
70 | ///
71 | /// Gets or sets the ImageSource property. This dependency property
72 | /// indicates the ImageSource to use for this button's display.
73 | ///
74 | public ImageSource ImageSource
75 | {
76 | get { return (ImageSource)GetValue(ImageSourceProperty); }
77 | set { SetValue(ImageSourceProperty, value); }
78 | }
79 |
80 | public static readonly DependencyProperty IsBackgroundVisibleProperty = DependencyProperty.Register(
81 | "IsBackgroundVisible",
82 | typeof(bool),
83 | typeof(ThumbButtonInfo),
84 | new PropertyMetadata(true));
85 |
86 | ///
87 | /// Gets or sets the IsBackgroundVisible property. This dependency property
88 | /// indicates whether the default background should be shown.
89 | ///
90 | public bool IsBackgroundVisible
91 | {
92 | get { return (bool)GetValue(IsBackgroundVisibleProperty); }
93 | set { SetValue(IsBackgroundVisibleProperty, value); }
94 | }
95 |
96 | public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
97 | "Description",
98 | typeof(string),
99 | typeof(ThumbButtonInfo),
100 | new PropertyMetadata(
101 | string.Empty,
102 | null,
103 | _CoerceDescription));
104 |
105 | ///
106 | /// Gets or sets the Description property. This dependency property
107 | /// indicates the text to display in the tooltip for this button.
108 | ///
109 | public string Description
110 | {
111 | get { return (string)GetValue(DescriptionProperty); }
112 | set { SetValue(DescriptionProperty, value); }
113 | }
114 |
115 | // The THUMBBUTTON struct has a hard-coded length for this field of 260.
116 | private static object _CoerceDescription(DependencyObject d, object value)
117 | {
118 | var text = (string)value;
119 |
120 | if (text != null && text.Length >= 260)
121 | {
122 | // Account for the NULL in native LPWSTRs
123 | text = text.Substring(0, 259);
124 | }
125 |
126 | return text;
127 | }
128 |
129 | public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(
130 | "IsEnabled",
131 | typeof(bool),
132 | typeof(ThumbButtonInfo),
133 | new PropertyMetadata(
134 | true,
135 | null,
136 | (d, e) => ((ThumbButtonInfo)d)._CoerceIsEnabledValue(e)));
137 |
138 | private object _CoerceIsEnabledValue(object value)
139 | {
140 | var enabled = (bool)value;
141 | return enabled && _CanExecute;
142 | }
143 |
144 | ///
145 | /// Gets or sets the IsEnabled property.
146 | ///
147 | ///
148 | /// This dependency property
149 | /// indicates whether the button is receptive to user interaction and
150 | /// should appear as such. The button will not raise click events from
151 | /// the user when this property is false.
152 | /// See also IsInteractive.
153 | ///
154 | public bool IsEnabled
155 | {
156 | get { return (bool)GetValue(IsEnabledProperty); }
157 | set { SetValue(IsEnabledProperty, value); }
158 | }
159 |
160 | public static readonly DependencyProperty IsInteractiveProperty = DependencyProperty.Register(
161 | "IsInteractive",
162 | typeof(bool),
163 | typeof(ThumbButtonInfo),
164 | new PropertyMetadata(true));
165 |
166 | ///
167 | /// Gets or sets the IsInteractive property.
168 | ///
169 | ///
170 | /// This dependency property allows an enabled button, as determined
171 | /// by the IsEnabled property, to not raise click events. Buttons that
172 | /// have IsInteractive=false can be used to indicate status.
173 | /// IsEnabled=false takes precedence over IsInteractive=false.
174 | ///
175 | public bool IsInteractive
176 | {
177 | get { return (bool)GetValue(IsInteractiveProperty); }
178 | set { SetValue(IsInteractiveProperty, value); }
179 | }
180 |
181 | public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
182 | "Command",
183 | typeof(ICommand),
184 | typeof(ThumbButtonInfo),
185 | new PropertyMetadata(
186 | null,
187 | (d, e) => ((ThumbButtonInfo)d)._OnCommandChanged(e)));
188 |
189 | private void _OnCommandChanged(DependencyPropertyChangedEventArgs e)
190 | {
191 | var oldCommand = (ICommand)e.OldValue;
192 | var newCommand = (ICommand)e.NewValue;
193 |
194 | if (oldCommand == newCommand)
195 | {
196 | return;
197 | }
198 |
199 | if (oldCommand != null)
200 | {
201 | _UnhookCommand(oldCommand);
202 | }
203 | if (newCommand != null)
204 | {
205 | _HookCommand(newCommand);
206 | }
207 | }
208 |
209 | ///
210 | /// CommandParameter Dependency Property
211 | ///
212 | public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
213 | "CommandParameter",
214 | typeof(object),
215 | typeof(ThumbButtonInfo),
216 | new PropertyMetadata(
217 | null,
218 | (d, e) => ((ThumbButtonInfo)d)._UpdateCanExecute()));
219 |
220 | // .Net property deferred to ICommandSource region.
221 |
222 | ///
223 | /// CommandTarget Dependency Property
224 | ///
225 | public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register(
226 | "CommandTarget",
227 | typeof(IInputElement),
228 | typeof(ThumbButtonInfo),
229 | new PropertyMetadata(
230 | null,
231 | (d, e) => ((ThumbButtonInfo)d)._UpdateCanExecute()));
232 |
233 | // .Net property deferred to ICommandSource region.
234 |
235 | private static readonly DependencyProperty _CanExecuteProperty = DependencyProperty.Register(
236 | "_CanExecute",
237 | typeof(bool),
238 | typeof(ThumbButtonInfo),
239 | new PropertyMetadata(
240 | true,
241 | (d, e) => d.CoerceValue(IsEnabledProperty)));
242 |
243 | private bool _CanExecute
244 | {
245 | get { return (bool)GetValue(_CanExecuteProperty); }
246 | set { SetValue(_CanExecuteProperty, value); }
247 | }
248 |
249 | #endregion
250 |
251 | public event EventHandler Click;
252 |
253 | internal void InvokeClick()
254 | {
255 | EventHandler local = Click;
256 | if (local != null)
257 | {
258 | local(this, EventArgs.Empty);
259 | }
260 |
261 | _InvokeCommand();
262 | }
263 |
264 | private void _InvokeCommand()
265 | {
266 | ICommand command = Command;
267 | if (command != null)
268 | {
269 | object parameter = CommandParameter;
270 | IInputElement target = CommandTarget;
271 |
272 | RoutedCommand routedCommand = command as RoutedCommand;
273 | if (routedCommand != null)
274 | {
275 | if (routedCommand.CanExecute(parameter, target))
276 | {
277 | routedCommand.Execute(parameter, target);
278 | }
279 | }
280 | else if (command.CanExecute(parameter))
281 | {
282 | command.Execute(parameter);
283 | }
284 | }
285 | }
286 |
287 | private void _UnhookCommand(ICommand command)
288 | {
289 | Assert.IsNotNull(command);
290 | command.CanExecuteChanged -= _commandEvent;
291 | _commandEvent = null;
292 | _UpdateCanExecute();
293 | }
294 |
295 | private void _HookCommand(ICommand command)
296 | {
297 | _commandEvent = (sender, e) => _UpdateCanExecute();
298 | command.CanExecuteChanged += _commandEvent;
299 | _UpdateCanExecute();
300 | }
301 |
302 | private void _UpdateCanExecute()
303 | {
304 | if (Command != null)
305 | {
306 | object parameter = CommandParameter;
307 | IInputElement target = CommandTarget;
308 |
309 | RoutedCommand routed = Command as RoutedCommand;
310 | if (routed != null)
311 | {
312 | _CanExecute = routed.CanExecute(parameter, target);
313 | }
314 | else
315 | {
316 | _CanExecute = Command.CanExecute(parameter);
317 | }
318 | }
319 | else
320 | {
321 | _CanExecute = true;
322 | }
323 | }
324 |
325 | #region ICommandSource Members
326 |
327 | public ICommand Command
328 | {
329 | get { return (ICommand)GetValue(CommandProperty); }
330 | set { SetValue(CommandProperty, value); }
331 | }
332 |
333 | public object CommandParameter
334 | {
335 | get { return (object)GetValue(CommandParameterProperty); }
336 | set { SetValue(CommandParameterProperty, value); }
337 | }
338 |
339 | public IInputElement CommandTarget
340 | {
341 | get { return (IInputElement)GetValue(CommandTargetProperty); }
342 | set { SetValue(CommandTargetProperty, value); }
343 | }
344 |
345 | #endregion
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/ThumbButtonInfoCollection.cs:
--------------------------------------------------------------------------------
1 | /**************************************************************************\
2 | Copyright Microsoft Corporation. All Rights Reserved.
3 | \**************************************************************************/
4 |
5 | namespace Microsoft.Windows.Shell
6 | {
7 | using System.Windows;
8 |
9 | public class ThumbButtonInfoCollection : FreezableCollection
10 | {
11 | protected override Freezable CreateInstanceCore()
12 | {
13 | return new ThumbButtonInfoCollection();
14 | }
15 |
16 | ///
17 | /// A frozen empty ThumbButtonInfoCollection.
18 | ///
19 | internal static ThumbButtonInfoCollection Empty
20 | {
21 | get
22 | {
23 | if (s_empty == null)
24 | {
25 | var collection = new ThumbButtonInfoCollection();
26 | collection.Freeze();
27 | s_empty = collection;
28 | }
29 |
30 | return s_empty;
31 | }
32 | }
33 |
34 | private static ThumbButtonInfoCollection s_empty;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Csv.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics.CodeAnalysis;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | internal static class Csv
11 | {
12 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
13 | public static string Escape(string str)
14 | {
15 | if (string.IsNullOrEmpty(str))
16 | {
17 | return "";
18 | }
19 |
20 | if (str.Contains("\""))
21 | {
22 | str = str.Replace("\"", "\"\"");
23 | }
24 |
25 | if (str.IndexOfAny(new char[] { ',', '"', '\n' }) > -1)
26 | {
27 | str = '\"' + str + '\"';
28 | }
29 |
30 | return str;
31 | }
32 |
33 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
34 | public static string MakeLine(string[] data)
35 | {
36 | var sb = new StringBuilder();
37 | foreach (var cell in data)
38 | {
39 | sb.Append(Escape(cell));
40 | sb.Append(',');
41 | }
42 |
43 | return sb.ToString(0, sb.Length - 1);
44 | }
45 |
46 | // Read a logical line from the stream. It may contain embedded newlines if it was CSV-style escaped.
47 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
48 | private static string _ReadLine(StreamReader reader)
49 | {
50 | int i = 0;
51 | bool inEscape = false;
52 | bool lastChance = false;
53 |
54 | var sb = new StringBuilder(reader.ReadLine());
55 |
56 | while (true)
57 | {
58 | for (; i < sb.Length; ++i)
59 | {
60 | if (sb[i] == '\"')
61 | {
62 | inEscape = !inEscape;
63 | }
64 | }
65 | if (!inEscape)
66 | {
67 | return sb.ToString();
68 | }
69 | sb.Append("\n");
70 | if (lastChance)
71 | {
72 | throw new ArgumentException("Invalid CSV data.");
73 | }
74 | sb.Append(reader.ReadLine());
75 | lastChance = reader.EndOfStream;
76 | }
77 | }
78 |
79 | private static readonly string bellString = Encoding.ASCII.GetString(new byte[] { 7 });
80 |
81 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
82 | private static List _ParseLine(string row)
83 | {
84 | if (!row.Contains('\"'))
85 | {
86 | return new List(row.Split(','));
87 | }
88 |
89 | // Make it simpler to not have to look for escaped quotes.
90 | row = row.Replace("\"\"", bellString);
91 |
92 | var ret = new List();
93 | int startIndex = 0;
94 | for (int i = 0; i < row.Length; ++i)
95 | {
96 | if (row[i] == '\"')
97 | {
98 | // Skip the opening quote
99 | startIndex = i + 1;
100 | while (row[++i] != '\"')
101 | { }
102 |
103 | // Remove the trailing quote, and replace back any embedded quotes.
104 | ret.Add(row.Substring(startIndex, i - startIndex).Replace((char)7, '\"'));
105 |
106 | ++i;
107 | if (i < row.Length && row[i] != ',')
108 | {
109 | throw new ArgumentException("Malformed data.");
110 | }
111 | startIndex = i + 1;
112 | }
113 | else
114 | {
115 | if (i >= row.Length - 1 || row[i] == ',')
116 | {
117 | ret.Add("");
118 | startIndex = i + 1;
119 | continue;
120 | }
121 |
122 | while (i < row.Length-1 && row[++i] != ',')
123 | { }
124 |
125 | ret.Add(row.Substring(startIndex, i - startIndex));
126 |
127 | if (i < row.Length-1 && row[i] != ',')
128 | {
129 | throw new ArgumentException("Malformed data.");
130 | }
131 | startIndex = i + 1;
132 | }
133 | }
134 |
135 | if (row.EndsWith(",", StringComparison.Ordinal))
136 | {
137 | ret.Add("");
138 | }
139 |
140 | return ret;
141 | }
142 |
143 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
144 | public static List> ReadDocument(StreamReader reader)
145 | {
146 | List headers = _ParseLine(_ReadLine(reader));
147 | var ret = new List>();
148 |
149 | while (!reader.EndOfStream)
150 | {
151 | var rowData = new Dictionary();
152 | List cells = _ParseLine(_ReadLine(reader));
153 | if (cells.Count != headers.Count)
154 | {
155 | throw new ArgumentException("Bad CSV file.");
156 | }
157 |
158 | for (int i = 0; i < headers.Count; ++i)
159 | {
160 | rowData.Add(headers[i], cells[i]);
161 | }
162 | ret.Add(rowData);
163 | }
164 |
165 | return ret;
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/DoubleUtil.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Standard
3 | {
4 | using System;
5 | using System.Diagnostics.CodeAnalysis;
6 |
7 | ///
8 | /// DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles.
9 | /// Note that FP noise is a big problem and using any of these compare
10 | /// methods is not a complete solution, but rather the way to reduce
11 | /// the probability of repeating unnecessary work.
12 | ///
13 | internal static class DoubleUtilities
14 | {
15 | ///
16 | /// Epsilon - more or less random, more or less small number.
17 | ///
18 | private const double Epsilon = 0.00000153;
19 |
20 | ///
21 | /// AreClose returns whether or not two doubles are "close". That is, whether or
22 | /// not they are within epsilon of each other.
23 | /// There are plenty of ways for this to return false even for numbers which
24 | /// are theoretically identical, so no code calling this should fail to work if this
25 | /// returns false.
26 | ///
27 | /// The first double to compare.
28 | /// The second double to compare.
29 | /// The result of the AreClose comparision.
30 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
31 | public static bool AreClose(double value1, double value2)
32 | {
33 | if (value1 == value2)
34 | {
35 | return true;
36 | }
37 |
38 | double delta = value1 - value2;
39 | return (delta < Epsilon) && (delta > -Epsilon);
40 | }
41 |
42 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
43 | public static bool IsCloseTo(this double value1, double value2)
44 | {
45 | return AreClose(value1, value2);
46 | }
47 |
48 | ///
49 | /// LessThan returns whether or not the first double is less than the second double.
50 | /// That is, whether or not the first is strictly less than *and* not within epsilon of
51 | /// the other number.
52 | /// There are plenty of ways for this to return false even for numbers which
53 | /// are theoretically identical, so no code calling this should fail to work if this
54 | /// returns false.
55 | ///
56 | /// The first double to compare.
57 | /// The second double to compare.
58 | /// The result of the LessThan comparision.
59 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
60 | public static bool IsStrictlyLessThan(this double value1, double value2)
61 | {
62 | return (value1 < value2) && !AreClose(value1, value2);
63 | }
64 |
65 | ///
66 | /// GreaterThan returns whether or not the first double is greater than the second double.
67 | /// That is, whether or not the first is strictly greater than *and* not within epsilon of
68 | /// the other number.
69 | /// There are plenty of ways for this to return false even for numbers which
70 | /// are theoretically identical, so no code calling this should fail to work if this
71 | /// returns false.
72 | ///
73 | /// The first double to compare.
74 | /// The second double to compare.
75 | /// The result of the GreaterThan comparision.
76 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
77 | public static bool IsStrictlyGreaterThan(this double value1, double value2)
78 | {
79 | return (value1 > value2) && !AreClose(value1, value2);
80 | }
81 |
82 | ///
83 | /// LessThanOrClose returns whether or not the first double is less than or close to
84 | /// the second double. That is, whether or not the first is strictly less than or within
85 | /// epsilon of the other number.
86 | /// There are plenty of ways for this to return false even for numbers which
87 | /// are theoretically identical, so no code calling this should fail to work if this
88 | /// returns false.
89 | ///
90 | /// The first double to compare.
91 | /// The second double to compare.
92 | /// The result of the LessThanOrClose comparision.
93 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
94 | public static bool IsLessThanOrCloseTo(this double value1, double value2)
95 | {
96 | return (value1 < value2) || AreClose(value1, value2);
97 | }
98 |
99 | ///
100 | /// GreaterThanOrClose returns whether or not the first double is greater than or close to
101 | /// the second double. That is, whether or not the first is strictly greater than or within
102 | /// epsilon of the other number.
103 | /// There are plenty of ways for this to return false even for numbers which
104 | /// are theoretically identical, so no code calling this should fail to work if this
105 | /// returns false.
106 | ///
107 | /// The first double to compare.
108 | /// The second double to compare.
109 | /// The result of the GreaterThanOrClose comparision.
110 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
111 | public static bool IsGreaterThanOrCloseTo(this double value1, double value2)
112 | {
113 | return (value1 > value2) || AreClose(value1, value2);
114 | }
115 |
116 | ///
117 | /// Test to see if a double is a finite number (is not NaN or Infinity).
118 | ///
119 | /// The value to test.
120 | /// Whether or not the value is a finite number.
121 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
122 | public static bool IsFinite(this double value)
123 | {
124 | return !double.IsNaN(value) && !double.IsInfinity(value);
125 | }
126 |
127 | ///
128 | /// Test to see if a double a valid size value (is finite and > 0).
129 | ///
130 | /// The value to test.
131 | /// Whether or not the value is a valid size value.
132 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
133 | public static bool IsValidSize(this double value)
134 | {
135 | return IsFinite(value) && value.IsGreaterThanOrCloseTo(0);
136 | }
137 |
138 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
139 | public static bool IsFiniteAndNonNegative(this double d)
140 | {
141 | if (double.IsNaN(d) || double.IsInfinity(d) || d < 0)
142 | {
143 | return false;
144 | }
145 |
146 | return true;
147 | }
148 |
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Enumerable2.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Standard
3 | {
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | ///
9 | /// Further LINQ extensions
10 | ///
11 | internal static class Enumerable2
12 | {
13 | // Unnecessary in .Net 4.
14 | //public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func func)
15 | //{
16 | // Verify.IsNotNull(first, "first");
17 | // Verify.IsNotNull(second, "second");
18 |
19 | // return _Zip(first, second, func);
20 | //}
21 |
22 | //private static IEnumerable _Zip(this IEnumerable first, IEnumerable second, Func func)
23 | //{
24 | // IEnumerator ie1 = first.GetEnumerator();
25 | // IEnumerator ie2 = second.GetEnumerator();
26 | // while (ie1.MoveNext() && ie2.MoveNext())
27 | // {
28 | // yield return func(ie1.Current, ie2.Current);
29 | // }
30 | //}
31 |
32 | /// Partition a collection into two, based on whether the items match a predicate.
33 | /// The type of the enumeration.
34 | /// The original collection to split.
35 | /// The condition to use for the split.
36 | /// A collection of all items in the original collection that do not satisfy the condition.
37 | /// A collection of all items in the original collection that satisfy the condition.
38 | /// Unlike most extension methods of this nature, this does not perform the operation lazily.
39 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
40 | public static IEnumerable SplitWhere(this IEnumerable collection, Predicate condition, out IEnumerable rest)
41 | {
42 | Verify.IsNotNull(collection, "collection");
43 | Verify.IsNotNull(condition, "condition");
44 |
45 | var passList = new List();
46 | var failList = new List();
47 |
48 | foreach (T t in collection)
49 | {
50 | if (condition(t))
51 | {
52 | passList.Add(t);
53 | }
54 | else
55 | {
56 | failList.Add(t);
57 | }
58 | }
59 |
60 | rest = failList;
61 | return passList;
62 | }
63 |
64 | ///
65 | /// Limit an enumeration to be constrained to a subset after a given index.
66 | ///
67 | /// The type of items being enumerated.
68 | /// The collection to be enumerated.
69 | /// The index (inclusive) of the first item to be returned.
70 | ///
71 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
72 | public static IEnumerable Sublist(this IEnumerable enumerable, int startIndex)
73 | {
74 | return Sublist(enumerable, startIndex, null);
75 | }
76 |
77 | ///
78 | /// Limit an enumeration to be within a set of indices.
79 | ///
80 | /// The type of items being enumerated.
81 | /// The collection to be enumerated.
82 | /// The index (inclusive) of the first item to be returned.
83 | ///
84 | /// The index (exclusive) of the last item to be returned.
85 | /// If this is null then the full collection after startIndex is returned.
86 | /// If this is greater than the count of the collection after startIndex, then the full collection after startIndex is returned.
87 | ///
88 | ///
89 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
90 | public static IEnumerable Sublist(this IEnumerable enumerable, int startIndex, int? endIndex)
91 | {
92 | Verify.IsNotNull(enumerable, "enumerable");
93 | Verify.BoundedInteger(0, startIndex, int.MaxValue, "startIndex");
94 | if (endIndex != null)
95 | {
96 | Verify.BoundedInteger(startIndex, endIndex.Value, int.MaxValue, "endIndex");
97 | }
98 |
99 | // If this supports indexing then just use that.
100 | var list = enumerable as IList;
101 | if (list != null)
102 | {
103 | return _SublistList(list, startIndex, endIndex);
104 | }
105 |
106 | return _SublistEnum(enumerable, startIndex, endIndex);
107 | }
108 |
109 | private static IEnumerable _SublistEnum(this IEnumerable enumerable, int startIndex, int? endIndex)
110 | {
111 | int currentIndex = 0;
112 | IEnumerator enumerator = enumerable.GetEnumerator();
113 | while (currentIndex < startIndex && enumerator.MoveNext())
114 | {
115 | ++currentIndex;
116 | }
117 |
118 | int trueEndIndex = endIndex ?? int.MaxValue;
119 |
120 | while (currentIndex < trueEndIndex && enumerator.MoveNext())
121 | {
122 | yield return enumerator.Current;
123 | ++currentIndex;
124 | }
125 | }
126 |
127 | private static IEnumerable _SublistList(this IList list, int startIndex, int? endIndex)
128 | {
129 | int trueEndIndex = Math.Min(list.Count, endIndex ?? int.MaxValue);
130 | for (int i = startIndex; i < trueEndIndex; ++i)
131 | {
132 | yield return list[i];
133 | }
134 | }
135 |
136 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
137 | public static bool AreSorted(this IEnumerable enumerable)
138 | {
139 | return _AreSorted(enumerable, null);
140 | }
141 |
142 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
143 | public static bool AreSorted(this IEnumerable enumerable, Comparison comparison)
144 | {
145 | Verify.IsNotNull(enumerable, "enumerable");
146 | if (comparison == null)
147 | {
148 | if (typeof(T).GetInterface(typeof(IComparable).Name) == null)
149 | {
150 | // Not comparable for a sort.
151 | return true;
152 | }
153 |
154 | comparison = delegate(T left, T right)
155 | {
156 | if (left == null)
157 | {
158 | if (right == null)
159 | {
160 | return 0;
161 | }
162 | return -((IComparable)right).CompareTo(left);
163 | }
164 | return ((IComparable)left).CompareTo(right);
165 | };
166 | }
167 |
168 | return _AreSorted(enumerable, comparison);
169 | }
170 |
171 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
172 | private static bool _AreSorted(IEnumerable enumerable, Comparison comparison)
173 | {
174 | var enumerator = enumerable.GetEnumerator();
175 | if (!enumerator.MoveNext())
176 | {
177 | return true;
178 | }
179 |
180 | T last = enumerator.Current;
181 | while (enumerator.MoveNext())
182 | {
183 | if (comparison(last, enumerator.Current) > 0)
184 | {
185 | return false;
186 | }
187 | last = enumerator.Current;
188 | }
189 |
190 | return true;
191 | }
192 |
193 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
194 | public static void AddRange(this ICollection collection, params T[] items)
195 | {
196 | Verify.IsNotNull(collection, "collection");
197 | _AddRange(collection, items);
198 | }
199 |
200 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
201 | public static void AddRange(this ICollection collection, IEnumerable items)
202 | {
203 | Verify.IsNotNull(collection, "collection");
204 | _AddRange(collection, items);
205 | }
206 |
207 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
208 | private static void _AddRange(ICollection collection, IEnumerable items)
209 | {
210 | if (items == null)
211 | {
212 | return;
213 | }
214 |
215 | foreach (var item in items)
216 | {
217 | collection.Add(item);
218 | }
219 | }
220 |
221 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
222 | public static IEnumerable Reverse(this IList list)
223 | {
224 | Verify.IsNotNull(list, "list");
225 | return _Reverse(list);
226 | }
227 |
228 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
229 | private static IEnumerable _Reverse(IList list)
230 | {
231 | for (int i = list.Count - 1; i >= 0; --i)
232 | {
233 | yield return list[i];
234 | }
235 | }
236 |
237 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
238 | public static IList Shuffle(this IList list)
239 | {
240 | var r = new Random();
241 | return Shuffle(list, () => r.Next(list.Count));
242 | }
243 |
244 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
245 | public static IList Shuffle(this IList list, Func numberGenerator)
246 | {
247 | Verify.IsNotNull(list, "list");
248 | Verify.IsNotNull(numberGenerator, "numberGenerator");
249 |
250 | var swapIndices = new int[list.Count];
251 | for (int i = 0; i < list.Count; ++i)
252 | {
253 | int j = numberGenerator();
254 | if (j < 0 || j >= list.Count)
255 | {
256 | throw new ArgumentException("The number generator function generated a number outside the valid range.");
257 | }
258 | swapIndices[i] = j;
259 | }
260 | return _Shuffle(list, swapIndices);
261 | }
262 |
263 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
264 | private static IList _Shuffle(IList list, int[] swapIndices)
265 | {
266 | Assert.AreEqual(list.Count, swapIndices.Length);
267 | for (int i = swapIndices.Length; i > 1; --i)
268 | {
269 | int k = swapIndices[i-1];
270 | T temp = list[k];
271 | list[k] = list[i-1];
272 | list[i-1] = temp;
273 | }
274 |
275 | return list;
276 | }
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/NotifyingList.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Standard
3 | {
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.Collections.ObjectModel;
7 | using System.Collections.Specialized;
8 | using System.ComponentModel;
9 | using System.Diagnostics.CodeAnalysis;
10 |
11 | [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
12 | internal class NotifyingList : IList, INotifyCollectionChanged where T : INotifyPropertyChanged
13 | {
14 | private readonly ObservableCollection _list;
15 |
16 | public event PropertyChangedEventHandler ItemPropertyChanged;
17 |
18 | private void _SafeAddPropertyListener(T item)
19 | {
20 | if (item != null)
21 | {
22 | item.PropertyChanged += _OnItemPropertyChanged;
23 | }
24 | }
25 |
26 | private void _SafeRemovePropertyListener(T item)
27 | {
28 | if (item != null)
29 | {
30 | item.PropertyChanged -= _OnItemPropertyChanged;
31 | }
32 | }
33 |
34 | public NotifyingList()
35 | {
36 | _list = new ObservableCollection();
37 | }
38 |
39 | public NotifyingList(IEnumerable collection)
40 | {
41 | _list = new ObservableCollection(collection);
42 | foreach (T item in collection)
43 | {
44 | _SafeAddPropertyListener(item);
45 | }
46 | }
47 |
48 | private void _OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
49 | {
50 | var handler = ItemPropertyChanged;
51 | if (handler != null)
52 | {
53 | handler(sender, e);
54 | }
55 | }
56 |
57 | #region IList Members
58 |
59 | public int IndexOf(T item)
60 | {
61 | return _list.IndexOf(item);
62 | }
63 |
64 | public void Insert(int index, T item)
65 | {
66 | _list.Insert(index, item);
67 | _SafeAddPropertyListener(item);
68 | }
69 |
70 | public void RemoveAt(int index)
71 | {
72 | T item = _list[index];
73 | _list.RemoveAt(index);
74 | _SafeRemovePropertyListener(item);
75 | }
76 |
77 | public T this[int index]
78 | {
79 | get { return _list[index]; }
80 | set { _list[index] = value; }
81 | }
82 |
83 | #endregion
84 |
85 | #region ICollection Members
86 |
87 | public void Add(T item)
88 | {
89 | _list.Add(item);
90 | _SafeAddPropertyListener(item);
91 | }
92 |
93 | public void Clear()
94 | {
95 | T[] items = new T[_list.Count];
96 | _list.CopyTo(items, 0);
97 | _list.Clear();
98 | foreach (T item in items)
99 | {
100 | _SafeRemovePropertyListener(item);
101 | }
102 | }
103 |
104 | public bool Contains(T item)
105 | {
106 | return _list.Contains(item);
107 | }
108 |
109 | public void CopyTo(T[] array, int arrayIndex)
110 | {
111 | _list.CopyTo(array, arrayIndex);
112 | }
113 |
114 | public int Count { get { return _list.Count; } }
115 |
116 | public bool IsReadOnly { get { return false; } }
117 |
118 | public bool Remove(T item)
119 | {
120 | // Don't call through _list.Remove().
121 | // If equality has been overloaded then we may try removing the handler
122 | // from a different object and we'll leak it.
123 | // Ensure reference equality.
124 | int index = _list.IndexOf(item);
125 | if (index == -1)
126 | {
127 | return false;
128 | }
129 |
130 | RemoveAt(index);
131 | return true;
132 | }
133 |
134 | #endregion
135 |
136 | #region IEnumerable Members
137 |
138 | public IEnumerator GetEnumerator()
139 | {
140 | return _list.GetEnumerator();
141 | }
142 |
143 | #endregion
144 |
145 | #region IEnumerable Members
146 |
147 | IEnumerator IEnumerable.GetEnumerator()
148 | {
149 | return _list.GetEnumerator();
150 | }
151 |
152 | #endregion
153 |
154 | #region INotifyCollectionChanged Members
155 |
156 | private event NotifyCollectionChangedEventHandler _sourceCollectionChanged;
157 |
158 | public event NotifyCollectionChangedEventHandler CollectionChanged
159 | {
160 | add
161 | {
162 | if (_sourceCollectionChanged == null)
163 | {
164 | _list.CollectionChanged += _OnSourceCollectionChanged;
165 | }
166 | _sourceCollectionChanged += value;
167 | }
168 | remove
169 | {
170 | _sourceCollectionChanged -= value;
171 | if (_sourceCollectionChanged == null)
172 | {
173 | _list.CollectionChanged -= _OnSourceCollectionChanged;
174 | }
175 | }
176 | }
177 |
178 | private void _OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
179 | {
180 | var handler = _sourceCollectionChanged;
181 | if (handler != null)
182 | {
183 | handler(this, e);
184 | }
185 | }
186 |
187 | #endregion
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("Standard")]
6 | [assembly: AssemblyDescription("")]
7 | [assembly: AssemblyConfiguration("")]
8 | [assembly: AssemblyCompany("")]
9 | [assembly: AssemblyProduct("Standard")]
10 | [assembly: AssemblyCopyright("Copyright © Joe Castro 2013")]
11 | [assembly: AssemblyTrademark("")]
12 | [assembly: AssemblyCulture("")]
13 |
14 | [assembly: ComVisible(false)]
15 | [assembly: Guid("559D8E94-8DB7-4891-941E-95122BAFC2B4")]
16 |
17 | [assembly: AssemblyVersion("0.1.0.0")]
18 | [assembly: AssemblyFileVersion("0.1.0.0")]
19 |
20 | // Never intended to ship as a real assembly. These files should be linked into the containing projects.
21 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
22 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/README.md:
--------------------------------------------------------------------------------
1 | standard.net
2 | ============
3 |
4 | Common utility functions I tend to carry from one C# project to the next.
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/SmallString.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Standard
3 | {
4 | using System;
5 | using System.Diagnostics.CodeAnalysis;
6 | using System.Globalization;
7 |
8 | [System.Diagnostics.DebuggerDisplay("SmallString: { GetString() }")]
9 | internal struct SmallString : IEquatable, IComparable
10 | {
11 | [Flags]
12 | private enum _SmallFlags : byte
13 | {
14 | None = 0,
15 | IsInt64 = 1,
16 | HasHashCode = 2,
17 | Reserved = 4,
18 | }
19 |
20 | private static readonly System.Text.UTF8Encoding s_Encoder = new System.Text.UTF8Encoding(false /* do not emit BOM */, true /* throw on error */);
21 | private readonly byte[] _encodedBytes;
22 | private _SmallFlags _flags;
23 | private int _cachedHashCode;
24 |
25 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
26 | public SmallString(string value, bool precacheHashCode = false)
27 | {
28 | _flags = _SmallFlags.None;
29 | _cachedHashCode = 0;
30 |
31 | if (!string.IsNullOrEmpty(value))
32 | {
33 | if (precacheHashCode)
34 | {
35 | _flags |= _SmallFlags.HasHashCode;
36 | _cachedHashCode = value.GetHashCode();
37 | }
38 |
39 | long numValue;
40 | if (long.TryParse(value, System.Globalization.NumberStyles.None, null, out numValue))
41 | {
42 | _flags |= _SmallFlags.IsInt64;
43 | _encodedBytes = BitConverter.GetBytes(numValue);
44 |
45 | // It's possible that this doesn't round trip with full fidelity.
46 | // If this assert ever gets hit, consider adding an overload that opts
47 | // out of this optimization.
48 | // (Note that the parameters are not evaluated on retail builds)
49 | Assert.AreEqual(this.GetString(), value);
50 |
51 | return;
52 | }
53 |
54 | _encodedBytes = s_Encoder.GetBytes(value);
55 | Assert.IsNotNull(_encodedBytes);
56 | }
57 | else
58 | {
59 | _encodedBytes = null;
60 | }
61 | }
62 |
63 | private bool _IsInt64
64 | {
65 | get { return (_flags & _SmallFlags.IsInt64) == _SmallFlags.IsInt64; }
66 | }
67 |
68 | private bool _HasCachedHashCode
69 | {
70 | get { return (_flags & _SmallFlags.HasHashCode) == _SmallFlags.HasHashCode; }
71 | }
72 |
73 | #region Object Overrides
74 |
75 | [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "GetString")]
76 | public override string ToString()
77 | {
78 | Assert.Fail();
79 | throw new NotSupportedException("This exception exists to prevent accidental performance penalties. Call GetString() instead.");
80 | }
81 |
82 | public override int GetHashCode()
83 | {
84 | if (_encodedBytes == null)
85 | {
86 | return 0;
87 | }
88 |
89 | if (!_HasCachedHashCode)
90 | {
91 | // Intentionally hashes similarly to the expanded strings.
92 | _cachedHashCode = GetString().GetHashCode();
93 | _flags |= _SmallFlags.HasHashCode;
94 | }
95 |
96 | return _cachedHashCode;
97 | }
98 |
99 | public override bool Equals(object obj)
100 | {
101 | try
102 | {
103 | return Equals((SmallString)obj);
104 | }
105 | catch (InvalidCastException)
106 | {
107 | return false;
108 | }
109 | }
110 |
111 | #endregion
112 |
113 | #region IEquatable Members
114 |
115 | public bool Equals(SmallString other)
116 | {
117 | if (_encodedBytes == null)
118 | {
119 | return other._encodedBytes == null;
120 | }
121 |
122 | if (other._encodedBytes == null)
123 | {
124 | return false;
125 | }
126 |
127 | if (_encodedBytes.Length != other._encodedBytes.Length)
128 | {
129 | return false;
130 | }
131 |
132 | // If only one is a number, then they're not equal.
133 | if (((_flags ^ other._flags) & _SmallFlags.IsInt64) == _SmallFlags.IsInt64)
134 | {
135 | return false;
136 | }
137 |
138 | if (_HasCachedHashCode && other._HasCachedHashCode)
139 | {
140 | if (_cachedHashCode != other._cachedHashCode)
141 | {
142 | return false;
143 | }
144 | }
145 |
146 | if (_IsInt64)
147 | {
148 | return BitConverter.ToInt64(_encodedBytes, 0) == BitConverter.ToInt64(other._encodedBytes, 0);
149 | }
150 |
151 | // Note that this is doing a literal binary comparison of the two strings.
152 | // It's possible for two real strings to compare equally even though they
153 | // can be encoded in different ways with UTF8.
154 | return Utility.MemCmp(_encodedBytes, other._encodedBytes, _encodedBytes.Length);
155 | }
156 |
157 | #endregion
158 |
159 | public string GetString()
160 | {
161 | if (_encodedBytes == null)
162 | {
163 | return "";
164 | }
165 |
166 | if (_IsInt64)
167 | {
168 | return BitConverter.ToInt64(_encodedBytes, 0).ToString(CultureInfo.InvariantCulture);
169 | }
170 |
171 | return s_Encoder.GetString(_encodedBytes);
172 | }
173 |
174 | public static bool operator==(SmallString left, SmallString right)
175 | {
176 | return left.Equals(right);
177 | }
178 |
179 | public static bool operator!=(SmallString left, SmallString right)
180 | {
181 | return !left.Equals(right);
182 | }
183 |
184 | #region IComparable Members
185 |
186 | public int CompareTo(SmallString other)
187 | {
188 | // If either of the strings contains multibyte characters
189 | // then we can't do a strictly bitwise comparison.
190 | // We can look for a signaled high-bit in the byte to detect this.
191 | // Opportunistically, we're going to assume that the strings are
192 | // ASCII compatible until we find out they aren't.
193 |
194 | if (_encodedBytes == null)
195 | {
196 | if (other._encodedBytes == null)
197 | {
198 | return 0;
199 | }
200 | Assert.AreNotEqual(0, other._encodedBytes.Length);
201 | return -1;
202 | }
203 | else if (other._encodedBytes == null)
204 | {
205 | Assert.AreNotEqual(0, _encodedBytes.Length);
206 | return 1;
207 | }
208 |
209 | bool? isThisStringShorter = null;
210 | int cb = _encodedBytes.Length;
211 | int cbDiffernce = other._encodedBytes.Length - cb;
212 |
213 | if (cbDiffernce < 0)
214 | {
215 | isThisStringShorter = false;
216 | cb = other._encodedBytes.Length;
217 | }
218 | else if (cbDiffernce > 0)
219 | {
220 | isThisStringShorter = true;
221 | }
222 |
223 | for (int i = 0; i < cb; ++i)
224 | {
225 | bool isEitherHighBitSet = ((_encodedBytes[i] | other._encodedBytes[i]) & 0x80) != 0;
226 | // If the byte array contains multibyte characters
227 | // we need to do a real string comparison.
228 | if (isEitherHighBitSet)
229 | {
230 | string left = this.GetString();
231 | string right = other.GetString();
232 |
233 | return string.Compare(left, right, StringComparison.Ordinal);
234 | }
235 |
236 | if (_encodedBytes[i] != other._encodedBytes[i])
237 | {
238 | return _encodedBytes[i] - other._encodedBytes[i];
239 | }
240 | }
241 |
242 | if (isThisStringShorter == null)
243 | {
244 | return 0;
245 | }
246 |
247 | if (isThisStringShorter == false)
248 | {
249 | return -1;
250 | }
251 |
252 | return 1;
253 | }
254 |
255 | #endregion
256 | }
257 | }
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/SmallUri.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Standard
3 | {
4 | using System;
5 | using System.Diagnostics;
6 | using System.Diagnostics.CodeAnalysis;
7 | using System.Text;
8 |
9 | [DebuggerDisplay("SmallUri: { GetUri() }")]
10 | internal struct SmallUri : IEquatable
11 | {
12 | private static readonly UTF8Encoding s_Encoder = new UTF8Encoding(false /* do not emit BOM */, true /* throw on error */);
13 | private readonly byte[] _utf8String;
14 | private readonly bool _isHttp;
15 |
16 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
17 | public SmallUri(Uri value)
18 | {
19 | _isHttp = false;
20 | _utf8String = null;
21 |
22 | if (value == null)
23 | {
24 | return;
25 | }
26 |
27 | if (!value.IsAbsoluteUri)
28 | {
29 | throw new ArgumentException("The parameter is not a valid absolute uri", "value");
30 | }
31 |
32 | string strValue = value.OriginalString;
33 | if (strValue.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
34 | {
35 | _isHttp = true;
36 | strValue = strValue.Substring(7);
37 | }
38 |
39 | _utf8String = s_Encoder.GetBytes(strValue);
40 | Assert.IsNotNull(_utf8String);
41 | }
42 |
43 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
44 | public SmallUri(string value)
45 | {
46 | _isHttp = false;
47 | _utf8String = null;
48 |
49 | if (string.IsNullOrEmpty(value))
50 | {
51 | return;
52 | }
53 |
54 | if (!Uri.IsWellFormedUriString(value, UriKind.Absolute))
55 | {
56 | throw new ArgumentException("The parameter is not a valid uri", "value");
57 | }
58 |
59 | if (value.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
60 | {
61 | _isHttp = true;
62 | value = value.Substring(7);
63 | }
64 |
65 | _utf8String = s_Encoder.GetBytes(value);
66 | Assert.IsNotNull(_utf8String);
67 | }
68 |
69 | #region Object Overrides
70 |
71 | [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "GetString")]
72 | public override string ToString()
73 | {
74 | Assert.Fail();
75 | throw new NotSupportedException("This exception exists to prevent accidental performance penalties. Call GetString() instead.");
76 | }
77 |
78 | public override int GetHashCode()
79 | {
80 | // Intentionally hashes similarly to the expanded strings.
81 | return GetString().GetHashCode();
82 | }
83 |
84 | public override bool Equals(object obj)
85 | {
86 | try
87 | {
88 | return Equals((SmallUri)obj);
89 | }
90 | catch (InvalidCastException)
91 | {
92 | return false;
93 | }
94 | }
95 |
96 | #endregion
97 |
98 | #region IEquatable Members
99 |
100 | public bool Equals(SmallUri other)
101 | {
102 | if (_utf8String == null)
103 | {
104 | return other._utf8String == null;
105 | }
106 |
107 | if (other._utf8String == null)
108 | {
109 | return false;
110 | }
111 |
112 | if (_isHttp != other._isHttp)
113 | {
114 | return false;
115 | }
116 |
117 | if (_utf8String.Length != other._utf8String.Length)
118 | {
119 | return false;
120 | }
121 |
122 | return Utility.MemCmp(_utf8String, other._utf8String, _utf8String.Length);
123 | }
124 |
125 | #endregion
126 |
127 | public string GetString()
128 | {
129 | if (_utf8String == null)
130 | {
131 | return "";
132 | }
133 | return GetUri().ToString();
134 | }
135 |
136 | public Uri GetUri()
137 | {
138 | if (_utf8String == null)
139 | {
140 | return null;
141 | }
142 | return new Uri((_isHttp ? "http://" : "") + s_Encoder.GetString(_utf8String), UriKind.Absolute);
143 | }
144 |
145 | public static bool operator ==(SmallUri left, SmallUri right)
146 | {
147 | return left.Equals(right);
148 | }
149 |
150 | public static bool operator !=(SmallUri left, SmallUri right)
151 | {
152 | return !left.Equals(right);
153 | }
154 | }
155 | }
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Standard.Native.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {48634441-DEDA-4D0D-8D35-14E61A29A363}
8 | Library
9 | Properties
10 | Standard.Native
11 | Standard.Native
12 | v4.0
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | true
24 | AllRules.ruleset
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
66 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Standard.Wpf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {89835A37-CA82-4036-A9E3-FC3456290F65}
8 | Library
9 | Properties
10 | Standard.Wpf
11 | Standard.Wpf
12 | v4.0
13 | 512
14 | Client
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | true
25 | AllRules.ruleset
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Standard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}
9 | Library
10 | Properties
11 | Standard
12 | Standard
13 | v4.0
14 | Client
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | AllRules.ruleset
25 | true
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 | AllRules.ruleset
35 |
36 |
37 | true
38 | bin\x86\Debug\
39 | DEBUG;TRACE
40 | full
41 | x86
42 | true
43 | GlobalSuppressions.cs
44 | prompt
45 | true
46 | AllRules.ruleset
47 |
48 |
49 | bin\x86\Release\
50 | TRACE
51 | true
52 | pdbonly
53 | x86
54 | true
55 | GlobalSuppressions.cs
56 | prompt
57 | AllRules.ruleset
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Standard.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standard.Wpf", "Standard.Wpf.csproj", "{89835A37-CA82-4036-A9E3-FC3456290F65}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standard", "Standard.csproj", "{A1326555-AD64-4A93-A95C-B68ABD5672D4}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standard.Native", "Standard.Native.csproj", "{48634441-DEDA-4D0D-8D35-14E61A29A363}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x86 = Debug|x86
14 | Release|Any CPU = Release|Any CPU
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Debug|x86.ActiveCfg = Debug|Any CPU
21 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Release|Any CPU.ActiveCfg = Release|Any CPU
22 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Release|Any CPU.Build.0 = Release|Any CPU
23 | {89835A37-CA82-4036-A9E3-FC3456290F65}.Release|x86.ActiveCfg = Release|Any CPU
24 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Debug|x86.ActiveCfg = Debug|x86
27 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Debug|x86.Build.0 = Debug|x86
28 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Release|x86.ActiveCfg = Release|x86
31 | {A1326555-AD64-4A93-A95C-B68ABD5672D4}.Release|x86.Build.0 = Release|x86
32 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Debug|x86.ActiveCfg = Debug|Any CPU
35 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Release|Any CPU.Build.0 = Release|Any CPU
37 | {48634441-DEDA-4D0D-8D35-14E61A29A363}.Release|x86.ActiveCfg = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | EndGlobal
43 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Windows/ComGuids.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System.Diagnostics.CodeAnalysis;
4 |
5 | internal static partial class IID
6 | {
7 | /// IID_IApplicationAssociationRegistration
8 | public const string ApplicationAssociationRegistration = "4e530b0a-e611-4c77-a3ac-9031d022281b";
9 | /// IID_IConnectionPoint
10 | public const string ConnectionPoint = "B196B286-BAB4-101A-B69C-00AA00341D07";
11 | /// IID_IConnectionPointContainer
12 | public const string ConnectionPointContainer = "B196B284-BAB4-101A-B69C-00AA00341D07";
13 | public const string DragSourceHelper = "DE5BF786-477A-11D2-839D-00C04FD918D0";
14 | public const string DragSourceHelper2 = "83E07D0D-0C5F-4163-BF1A-60B274051E40";
15 | public const string DropTargetHelper = "4657278B-411B-11D2-839A-00C04FD918D0";
16 | /// IID_IEnumConnectionPoints
17 | public const string EnumConnectionPoints = "B196B285-BAB4-101A-B69C-00AA00341D07";
18 | /// IID_IEnumConnections
19 | public const string EnumConnections = "B196B287-BAB4-101A-B69C-00AA00341D07";
20 | /// IID_IEnumIDList
21 | public const string EnumIdList = "000214F2-0000-0000-C000-000000000046";
22 | /// IID_IEnumObjects
23 | public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e";
24 | /// IID_IFileDialog
25 | public const string FileDialog = "42f85136-db7e-439c-85f1-e4075d135fc8";
26 | /// IID_IFileDialogEvents
27 | public const string FileDialogEvents = "973510DB-7D7F-452B-8975-74A85828D354";
28 | /// IID_IFileOpenDialog
29 | public const string FileOpenDialog = "d57c7288-d4ad-4768-be02-9d969532d960";
30 | /// IID_IFileSaveDialog
31 | public const string FileSaveDialog = "84bccd23-5fde-4cdb-aea4-af64b83d78ab";
32 | /// IID_IHTMLDocument
33 | public const string HtmlDocument = "626FC520-A41E-11CF-A731-00A0C9082637";
34 | /// IID_IHTMLDocument2
35 | public const string HtmlDocument2 = "332C4425-26CB-11D0-B483-00C04FD90119";
36 | /// IID_IModalWindow
37 | public const string ModalWindow = "b4db1657-70d7-485e-8e3e-6fcb5a5c1802";
38 | /// IID_IObjectArray
39 | public const string ObjectArray = "92CA9DCD-5622-4bba-A805-5E9F541BD8C9";
40 | /// IID_IObjectCollection
41 | public const string ObjectCollection = "5632b1a4-e38a-400a-928a-d4cd63230295";
42 | /// IID_IPropertyNotifySink
43 | public const string PropertyNotifySink = "9BFBBC02-EFF1-101A-84ED-00AA00341D07";
44 | /// IID_IPropertyStore
45 | public const string PropertyStore = "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99";
46 | /// IID_IServiceProvider
47 | public const string ServiceProvider = "6d5140c1-7436-11ce-8034-00aa006009fa";
48 | /// IID_IShellFolder
49 | public const string ShellFolder = "000214E6-0000-0000-C000-000000000046";
50 | /// IID_IShellLink
51 | public const string ShellLink = "000214F9-0000-0000-C000-000000000046";
52 | /// IID_IShellItem
53 | public const string ShellItem = "43826d1e-e718-42ee-bc55-a1e261c37bfe";
54 | /// IID_IShellItem2
55 | public const string ShellItem2 = "7e9fb0d3-919f-4307-ab2e-9b1860310c93";
56 | /// IID_IShellItemArray
57 | public const string ShellItemArray = "B63EA76D-1F85-456F-A19C-48159EFA858B";
58 | /// IID_ITaskbarList
59 | public const string TaskbarList = "56FDF342-FD6D-11d0-958A-006097C9A090";
60 | /// IID_ITaskbarList2
61 | public const string TaskbarList2 = "602D4995-B13A-429b-A66E-1935E44F4317";
62 | /// IID_IUnknown
63 | public const string Unknown = "00000000-0000-0000-C000-000000000046";
64 | /// IID_IWebBrowser2
65 | public const string WebBrowser2 = "D30C1661-CDAF-11D0-8A3E-00C04FC9E26E";
66 | /// DIID_DWebBrowserEvents
67 | public const string WebBrowserEvents = "EAB22AC2-30C1-11CF-A7EB-0000C05BAE0B";
68 | /// IID_DWebBrowserEvents2
69 | public const string WebBrowserEvents2 = "34A715A0-6587-11D0-924A-0020AFC7AC4D";
70 | /// IID_IWICBitmapDecoder
71 | public const string WICBitmapDecoder = "9EDDE9E7-8DEE-47ea-99DF-E6FAF2ED44BF";
72 | /// IID_IWICBitmapFlipRotator
73 | public const string WICBitmapFlipRotator = "5009834F-2D6A-41ce-9E1B-17C5AFF7A782";
74 | /// IID_IWICBitmapFrameDecode
75 | public const string WICBitmapFrameDecode = "3B16811B-6A43-4ec9-A813-3D930C13B940";
76 | /// IID_IWICBitmap
77 | public const string WICBitmap = "00000121-a8f2-4877-ba0a-fd2b6645fb94";
78 | /// IID_IWICBitmapSource
79 | public const string WICBitmapSource = "00000120-a8f2-4877-ba0a-fd2b6645fb94";
80 | /// IID_IWICFormatConverter
81 | public const string WICFormatConverter = "00000301-a8f2-4877-ba0a-fd2b6645fb94";
82 | /// IID_IWICImagingFactory
83 | public const string WICImagingFactory = "ec5ec8a9-c395-4314-9c77-54d7a935ff70";
84 | /// IID_IWICStream
85 | public const string WICStream = "135FF860-22B7-4ddf-B0F6-218F4F299A43";
86 |
87 | #region Win7 IIDs
88 |
89 | /// IID_IApplicationDestinations
90 | public const string ApplicationDestinations = "12337d35-94c6-48a0-bce7-6a9c69d4d600";
91 | /// IID_IApplicationDocumentLists
92 | public const string ApplicationDocumentLists = "3c594f9f-9f30-47a1-979a-c9e83d3d0a06";
93 | /// IID_ICustomDestinationList
94 | public const string CustomDestinationList = "6332debf-87b5-4670-90c0-5e57b408a49e";
95 | /// IID_IObjectWithAppUserModelID
96 | public const string ObjectWithAppUserModelId = "36db0196-9665-46d1-9ba7-d3709eecf9ed";
97 | /// IID_IObjectWithProgID
98 | public const string ObjectWithProgId = "71e806fb-8dee-46fc-bf8c-7748a8a1ae13";
99 | /// IID_ITaskbarList3
100 | public const string TaskbarList3 = "ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf";
101 | /// IID_ITaskbarList4
102 | public const string TaskbarList4 = "c43dc798-95d1-4bea-9030-bb99e2983a1a";
103 |
104 | #endregion
105 | }
106 |
107 | internal static partial class SID
108 | {
109 | /// SID_SWebBrowserApp
110 | public const string SWebBrowserApp = "0002DF05-0000-0000-C000-000000000046";
111 | }
112 |
113 | internal static partial class CLSID
114 | {
115 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
116 | public static T CoCreateInstance(string clsid)
117 | {
118 | return (T)System.Activator.CreateInstance(System.Type.GetTypeFromCLSID(new System.Guid(clsid)));
119 | }
120 |
121 | /// CLSID_ApplicationAssociationRegistration
122 | /// IID_IApplicationAssociationRegistration
123 | public const string ApplicationAssociationRegistration = "591209c7-767b-42b2-9fba-44ee4615f2c7";
124 | /// CLSID_DragDropHelper
125 | public const string DragDropHelper = "4657278A-411B-11d2-839A-00C04FD918D0";
126 | /// CLSID_FileOpenDialog
127 | /// IID_IFileOpenDialog
128 | public const string FileOpenDialog = "DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7";
129 | /// CLSID_FileSaveDialog
130 | /// IID_IFileSaveDialog
131 | public const string FileSaveDialog = "C0B4E2F3-BA21-4773-8DBA-335EC946EB8B";
132 | /// CLSID_TaskbarList
133 | /// IID_ITaskbarList
134 | public const string TaskbarList = "56FDF344-FD6D-11d0-958A-006097C9A090";
135 | /// CLSID_EnumerableObjectCollection
136 | /// IID_IEnumObjects.
137 | public const string EnumerableObjectCollection = "2d3468c1-36a7-43b6-ac24-d3f02fd9607a";
138 | /// CLSID_ShellLink
139 | /// IID_IShellLink
140 | public const string ShellLink = "00021401-0000-0000-C000-000000000046";
141 |
142 | /// CLSID_WICImagingFactory
143 | public const string WICImagingFactory = "cacaf262-9370-4615-a13b-9f5539da4c0a";
144 |
145 | #region Win7 CLSIDs
146 |
147 | /// CLSID_DestinationList
148 | /// IID_ICustomDestinationList
149 | public const string DestinationList = "77f10cf0-3db5-4966-b520-b7c54fd35ed6";
150 | /// CLSID_ApplicationDestinations
151 | /// IID_IApplicationDestinations
152 | public const string ApplicationDestinations = "86c14003-4d6b-4ef3-a7b4-0506663b2e68";
153 | /// CLSID_ApplicationDocumentLists
154 | /// IID_IApplicationDocumentLists
155 | public const string ApplicationDocumentLists = "86bec222-30f2-47e0-9f25-60d11cd75c28";
156 |
157 | #endregion
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Windows/FileWalker.cs:
--------------------------------------------------------------------------------
1 | // Cribbed heavily from MSDN magazine's .Net Matters (12/2005) by Stephen Toub.
2 | // http://msdn.microsoft.com/msdnmag/issues/05/12/NETMatters/
3 | // This started off an excellent implementation, I'd rather not unnecessarily rewrite it.
4 | // Some small stylistic changes were made to make it more consistent with the rest of the code
5 | // and also changed the recurse criteria.
6 |
7 | namespace Standard
8 | {
9 | using System.Collections.Generic;
10 | using System.Diagnostics.CodeAnalysis;
11 | using System.IO;
12 | using System.Security.Permissions;
13 |
14 | internal class FileWalker
15 | {
16 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
17 | public static IEnumerable GetFiles(DirectoryInfo startDirectory, string pattern, bool recurse)
18 | {
19 | // We suppressed this demand for each p/invoke call, so demand it upfront once
20 | new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
21 |
22 | // Validate parameters
23 | Verify.IsNotNull(startDirectory, "startDirectory");
24 | Verify.IsNeitherNullNorEmpty(pattern, "pattern");
25 |
26 | // Setup
27 | var findData = new WIN32_FIND_DATAW();
28 | var directories = new Stack();
29 | directories.Push(startDirectory);
30 |
31 | // Process each directory. Only push new directories if we're recursing.
32 | ErrorModes origErrorMode = NativeMethods.SetErrorMode(ErrorModes.FailCriticalErrors);
33 | try
34 | {
35 | while (directories.Count > 0)
36 | {
37 | // Get the name of the next directory and the corresponding search pattern
38 | DirectoryInfo dir = directories.Pop();
39 | string dirPath = dir.FullName.Trim();
40 | if (dirPath.Length == 0)
41 | {
42 | continue;
43 | }
44 | char lastChar = dirPath[dirPath.Length - 1];
45 | if (lastChar != Path.DirectorySeparatorChar && lastChar != Path.AltDirectorySeparatorChar)
46 | {
47 | dirPath += Path.DirectorySeparatorChar;
48 | }
49 |
50 | // Process all files in that directory
51 | using (SafeFindHandle handle = NativeMethods.FindFirstFileW(dirPath + pattern, findData))
52 | {
53 | Win32Error error;
54 | if (handle.IsInvalid)
55 | {
56 | error = Win32Error.GetLastError();
57 | if (error == Win32Error.ERROR_ACCESS_DENIED || error == Win32Error.ERROR_FILE_NOT_FOUND)
58 | {
59 | continue;
60 | }
61 | Assert.AreNotEqual(Win32Error.ERROR_SUCCESS, error);
62 | ((HRESULT)error).ThrowIfFailed();
63 | }
64 |
65 | do
66 | {
67 | if (!Utility.IsFlagSet((int)findData.dwFileAttributes, (int)FileAttributes.Directory))
68 | {
69 | yield return new FileInfo(dirPath + findData.cFileName);
70 | }
71 | }
72 | while (NativeMethods.FindNextFileW(handle, findData));
73 | error = Win32Error.GetLastError();
74 | if (error != Win32Error.ERROR_NO_MORE_FILES)
75 | {
76 | ((HRESULT)error).ThrowIfFailed();
77 | }
78 | }
79 |
80 | // Push subdirectories onto the stack if we are recursing.
81 | if (recurse)
82 | {
83 | // In a volatile system we can't count on all the file information staying valid.
84 | // Catch reasonable exceptions and move on.
85 | try
86 | {
87 | foreach (DirectoryInfo childDir in dir.GetDirectories())
88 | {
89 | try
90 | {
91 | FileAttributes attrib = File.GetAttributes(childDir.FullName);
92 | // If it's not a hidden, system folder, nor a reparse point
93 | if (!Utility.IsFlagSet((int)attrib, (int)(FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReparsePoint)))
94 | {
95 | directories.Push(childDir);
96 | }
97 | }
98 | catch (FileNotFoundException)
99 | {
100 | // Shouldn't see this.
101 | Assert.Fail();
102 | }
103 | catch (DirectoryNotFoundException) { }
104 | }
105 | }
106 | catch (DirectoryNotFoundException) { }
107 | }
108 | }
109 | }
110 | finally
111 | {
112 | NativeMethods.SetErrorMode(origErrorMode);
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Windows/Utilities.Windows.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Runtime.InteropServices;
6 |
7 | internal static partial class Utility
8 | {
9 | private static readonly Version _osVersion = Environment.OSVersion.Version;
10 |
11 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
12 | public static void SafeDestroyIcon(ref IntPtr hicon)
13 | {
14 | IntPtr p = hicon;
15 | hicon = IntPtr.Zero;
16 | if (IntPtr.Zero != p)
17 | {
18 | NativeMethods.DestroyIcon(p);
19 | }
20 | }
21 |
22 | /// GDI's DeleteObject
23 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
24 | public static void SafeDeleteObject(ref IntPtr gdiObject)
25 | {
26 | IntPtr p = gdiObject;
27 | gdiObject = IntPtr.Zero;
28 | if (IntPtr.Zero != p)
29 | {
30 | NativeMethods.DeleteObject(p);
31 | }
32 | }
33 |
34 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
35 | public static void SafeDestroyWindow(ref IntPtr hwnd)
36 | {
37 | IntPtr p = hwnd;
38 | hwnd = IntPtr.Zero;
39 | if (NativeMethods.IsWindow(p))
40 | {
41 | NativeMethods.DestroyWindow(p);
42 | }
43 | }
44 |
45 | /// GDI+'s DisposeImage
46 | ///
47 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
48 | public static void SafeDisposeImage(ref IntPtr gdipImage)
49 | {
50 | IntPtr p = gdipImage;
51 | gdipImage = IntPtr.Zero;
52 | if (IntPtr.Zero != p)
53 | {
54 | NativeMethods.GdipDisposeImage(p);
55 | }
56 | }
57 |
58 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
59 | [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
60 | public static void SafeCoTaskMemFree(ref IntPtr ptr)
61 | {
62 | IntPtr p = ptr;
63 | ptr = IntPtr.Zero;
64 | if (IntPtr.Zero != p)
65 | {
66 | Marshal.FreeCoTaskMem(p);
67 | }
68 | }
69 |
70 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
71 | [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
72 | public static void SafeFreeHGlobal(ref IntPtr hglobal)
73 | {
74 | IntPtr p = hglobal;
75 | hglobal = IntPtr.Zero;
76 | if (IntPtr.Zero != p)
77 | {
78 | Marshal.FreeHGlobal(p);
79 | }
80 | }
81 |
82 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
83 | [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
84 | public static void SafeRelease(ref T comObject) where T : class
85 | {
86 | T t = comObject;
87 | comObject = default(T);
88 | if (null != t)
89 | {
90 | Assert.IsTrue(Marshal.IsComObject(t));
91 | Marshal.ReleaseComObject(t);
92 | }
93 | }
94 |
95 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
96 | public static bool IsOSVistaOrNewer
97 | {
98 | get { return _osVersion >= new Version(6, 0); }
99 | }
100 |
101 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
102 | public static bool IsOSWindows7OrNewer
103 | {
104 | get { return _osVersion >= new Version(6, 1); }
105 | }
106 |
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Wpf/CornerRadiusAnimationBase.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Windows;
5 | using System.Windows.Media.Animation;
6 |
7 | internal abstract class CornerRadiusAnimationBase : AnimationTimeline
8 | {
9 | #region Constructors
10 |
11 | ///
12 | /// Creates a new CornerRadiusAnimationBase.
13 | ///
14 | protected CornerRadiusAnimationBase()
15 | : base()
16 | {
17 | }
18 |
19 | #endregion
20 |
21 | #region Freezable
22 |
23 | ///
24 | /// Creates a copy of this CornerRadiusAnimationBase
25 | ///
26 | /// The copy
27 | public new CornerRadiusAnimationBase Clone()
28 | {
29 | return (CornerRadiusAnimationBase)base.Clone();
30 | }
31 |
32 | #endregion
33 |
34 | #region IAnimation
35 |
36 | ///
37 | /// Calculates the value this animation believes should be the current value for the property.
38 | ///
39 | ///
40 | /// This value is the suggested origin value provided to the animation
41 | /// to be used if the animation does not have its own concept of a
42 | /// start value. If this animation is the first in a composition chain
43 | /// this value will be the snapshot value if one is available or the
44 | /// base property value if it is not; otherise this value will be the
45 | /// value returned by the previous animation in the chain with an
46 | /// animationClock that is not Stopped.
47 | ///
48 | ///
49 | /// This value is the suggested destination value provided to the animation
50 | /// to be used if the animation does not have its own concept of an
51 | /// end value. This value will be the base value if the animation is
52 | /// in the first composition layer of animations on a property;
53 | /// otherwise this value will be the output value from the previous
54 | /// composition layer of animations for the property.
55 | ///
56 | ///
57 | /// This is the animationClock which can generate the CurrentTime or
58 | /// CurrentProgress value to be used by the animation to generate its
59 | /// output value.
60 | ///
61 | ///
62 | /// The value this animation believes should be the current value for the property.
63 | ///
64 | public override sealed object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
65 | {
66 | // Verify that object arguments are non-null since we are a value type
67 | if (defaultOriginValue == null)
68 | {
69 | throw new ArgumentNullException("defaultOriginValue");
70 | }
71 | if (defaultDestinationValue == null)
72 | {
73 | throw new ArgumentNullException("defaultDestinationValue");
74 | }
75 | return GetCurrentValue((CornerRadius)defaultOriginValue, (CornerRadius)defaultDestinationValue, animationClock);
76 | }
77 |
78 | ///
79 | /// Returns the type of the target property
80 | ///
81 | public override sealed Type TargetPropertyType
82 | {
83 | get
84 | {
85 | ReadPreamble();
86 |
87 | return typeof(CornerRadius);
88 | }
89 | }
90 |
91 | #endregion
92 |
93 | #region Methods
94 |
95 |
96 | ///
97 | /// Calculates the value this animation believes should be the current value for the property.
98 | ///
99 | ///
100 | /// This value is the suggested origin value provided to the animation
101 | /// to be used if the animation does not have its own concept of a
102 | /// start value. If this animation is the first in a composition chain
103 | /// this value will be the snapshot value if one is available or the
104 | /// base property value if it is not; otherise this value will be the
105 | /// value returned by the previous animation in the chain with an
106 | /// animationClock that is not Stopped.
107 | ///
108 | ///
109 | /// This value is the suggested destination value provided to the animation
110 | /// to be used if the animation does not have its own concept of an
111 | /// end value. This value will be the base value if the animation is
112 | /// in the first composition layer of animations on a property;
113 | /// otherwise this value will be the output value from the previous
114 | /// composition layer of animations for the property.
115 | ///
116 | ///
117 | /// This is the animationClock which can generate the CurrentTime or
118 | /// CurrentProgress value to be used by the animation to generate its
119 | /// output value.
120 | ///
121 | ///
122 | /// The value this animation believes should be the current value for the property.
123 | ///
124 | public CornerRadius GetCurrentValue(CornerRadius defaultOriginValue, CornerRadius defaultDestinationValue, AnimationClock animationClock)
125 | {
126 | ReadPreamble();
127 |
128 | if (animationClock == null)
129 | {
130 | throw new ArgumentNullException("animationClock");
131 | }
132 |
133 | // We check for null above but presharp doesn't notice so we suppress the
134 | // warning here.
135 |
136 | //#pragma warning suppress 6506
137 | if (animationClock.CurrentState == ClockState.Stopped)
138 | {
139 | return defaultDestinationValue;
140 | }
141 |
142 | /*
143 | if (!AnimatedTypeHelpers.IsValidAnimationValueCornerRadius(defaultDestinationValue))
144 | {
145 | throw new ArgumentException(
146 | SR.Get(
147 | SRID.Animation_InvalidBaseValue,
148 | defaultDestinationValue,
149 | defaultDestinationValue.GetType(),
150 | GetType()),
151 | "defaultDestinationValue");
152 | }
153 | */
154 |
155 | return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock);
156 | }
157 |
158 |
159 | ///
160 | /// Calculates the value this animation believes should be the current value for the property.
161 | ///
162 | ///
163 | /// This value is the suggested origin value provided to the animation
164 | /// to be used if the animation does not have its own concept of a
165 | /// start value. If this animation is the first in a composition chain
166 | /// this value will be the snapshot value if one is available or the
167 | /// base property value if it is not; otherise this value will be the
168 | /// value returned by the previous animation in the chain with an
169 | /// animationClock that is not Stopped.
170 | ///
171 | ///
172 | /// This value is the suggested destination value provided to the animation
173 | /// to be used if the animation does not have its own concept of an
174 | /// end value. This value will be the base value if the animation is
175 | /// in the first composition layer of animations on a property;
176 | /// otherwise this value will be the output value from the previous
177 | /// composition layer of animations for the property.
178 | ///
179 | ///
180 | /// This is the animationClock which can generate the CurrentTime or
181 | /// CurrentProgress value to be used by the animation to generate its
182 | /// output value.
183 | ///
184 | ///
185 | /// The value this animation believes should be the current value for the property.
186 | ///
187 | protected abstract CornerRadius GetCurrentValueCore(CornerRadius defaultOriginValue, CornerRadius defaultDestinationValue, AnimationClock animationClock);
188 |
189 | #endregion
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Wpf/DpiHelper.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Windows;
6 | using System.Windows.Media;
7 |
8 | internal static class DpiHelper
9 | {
10 | private static Matrix _transformToDevice;
11 | private static Matrix _transformToDip;
12 |
13 | [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
14 | static DpiHelper()
15 | {
16 | using (SafeDC desktop = SafeDC.GetDesktop())
17 | {
18 | // Can get these in the static constructor. They shouldn't vary window to window,
19 | // and changing the system DPI requires a restart.
20 | int pixelsPerInchX = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSX);
21 | int pixelsPerInchY = NativeMethods.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSY);
22 |
23 | _transformToDip = Matrix.Identity;
24 | _transformToDip.Scale(96d / (double)pixelsPerInchX, 96d / (double)pixelsPerInchY);
25 | _transformToDevice = Matrix.Identity;
26 | _transformToDevice.Scale((double)pixelsPerInchX / 96d, (double)pixelsPerInchY / 96d);
27 | }
28 | }
29 |
30 | ///
31 | /// Convert a point in device independent pixels (1/96") to a point in the system coordinates.
32 | ///
33 | /// A point in the logical coordinate system.
34 | /// Returns the parameter converted to the system's coordinates.
35 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
36 | public static Point LogicalPixelsToDevice(Point logicalPoint)
37 | {
38 | return _transformToDevice.Transform(logicalPoint);
39 | }
40 |
41 | ///
42 | /// Convert a point in system coordinates to a point in device independent pixels (1/96").
43 | ///
44 | /// A point in the physical coordinate system.
45 | /// Returns the parameter converted to the device independent coordinate system.
46 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
47 | public static Point DevicePixelsToLogical(Point devicePoint)
48 | {
49 | return _transformToDip.Transform(devicePoint);
50 | }
51 |
52 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
53 | public static Rect LogicalRectToDevice(Rect logicalRectangle)
54 | {
55 | Point topLeft = LogicalPixelsToDevice(new Point(logicalRectangle.Left, logicalRectangle.Top));
56 | Point bottomRight = LogicalPixelsToDevice(new Point(logicalRectangle.Right, logicalRectangle.Bottom));
57 |
58 | return new Rect(topLeft, bottomRight);
59 | }
60 |
61 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
62 | public static Rect DeviceRectToLogical(Rect deviceRectangle)
63 | {
64 | Point topLeft = DevicePixelsToLogical(new Point(deviceRectangle.Left, deviceRectangle.Top));
65 | Point bottomRight = DevicePixelsToLogical(new Point(deviceRectangle.Right, deviceRectangle.Bottom));
66 |
67 | return new Rect(topLeft, bottomRight);
68 | }
69 |
70 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
71 | public static Size LogicalSizeToDevice(Size logicalSize)
72 | {
73 | Point pt = LogicalPixelsToDevice(new Point(logicalSize.Width, logicalSize.Height));
74 |
75 | return new Size { Width = pt.X, Height = pt.Y };
76 | }
77 |
78 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
79 | public static Size DeviceSizeToLogical(Size deviceSize)
80 | {
81 | Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height));
82 |
83 | return new Size(pt.X, pt.Y);
84 | }
85 |
86 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
87 | public static Thickness LogicalThicknessToDevice(Thickness logicalThickness)
88 | {
89 | Point topLeft = LogicalPixelsToDevice(new Point(logicalThickness.Left, logicalThickness.Top));
90 | Point bottomRight = LogicalPixelsToDevice(new Point(logicalThickness.Right, logicalThickness.Bottom));
91 |
92 | return new Thickness(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Wpf/GlassHelper.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Diagnostics.CodeAnalysis;
7 | using System.Windows;
8 | using System.Windows.Interop;
9 | using System.Windows.Media;
10 |
11 | internal class GlassHelper
12 | {
13 | // Test Notes:
14 | // Things to manually verify when making changes to this class.
15 | // * Do modified windows look correct in non-composited themes?
16 | // * Does changing the theme back and forth leave the window in a visually ugly state?
17 | // * Does it matter which theme was used first?
18 | // * Does glass extension work properly in high-dpi?
19 | // * Which of SetWindowThemeAttribute and ExtendGlassFrame are set first shouldn't matter.
20 | // The hooks injected by one should not block the hooks of the other.
21 | // * Do captions and icons always show up when composition is disabled?
22 | //
23 | // There are not automated unit tests for this class ( Boo!!! :( )
24 | // Be careful not to break things...
25 |
26 | private static readonly Dictionary _extendedWindows = new Dictionary();
27 |
28 | // TODO:
29 | // Verify that this really is sufficient. There are DWMWINDOWATTRIBUTEs as well, so this may
30 | // be able to be turned off on a per-HWND basis, but I never see comments about that online...
31 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | public static bool IsCompositionEnabled
33 | {
34 | get
35 | {
36 | if (!Utility.IsOSVistaOrNewer)
37 | {
38 | return false;
39 | }
40 |
41 | return NativeMethods.DwmIsCompositionEnabled();
42 | }
43 | }
44 |
45 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
46 | public static bool ExtendGlassFrameComplete(Window window)
47 | {
48 | return ExtendGlassFrame(window, new Thickness(-1));
49 | }
50 |
51 | ///
52 | /// Extends the glass frame of a window. Only works on operating systems that support composition.
53 | ///
54 | /// The window to modify.
55 | /// The margins of the new frame.
56 | /// Whether the frame was successfully extended.
57 | ///
58 | /// This function adds hooks to the Window to respond to changes to whether composition is enabled.
59 | ///
60 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
61 | public static bool ExtendGlassFrame(Window window, Thickness margin)
62 | {
63 | Verify.IsNotNull(window, "window");
64 |
65 | window.VerifyAccess();
66 |
67 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
68 |
69 | if (_extendedWindows.ContainsKey(hwnd))
70 | {
71 | // The hook into the HWND's WndProc has the original margin cached.
72 | // Don't want to support dynamically adjusting that unless there's a need.
73 | throw new InvalidOperationException("Multiple calls to this function for the same Window are not supported.");
74 | }
75 |
76 | return _ExtendGlassFrameInternal(window, margin);
77 | }
78 |
79 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
80 | private static bool _ExtendGlassFrameInternal(Window window, Thickness margin)
81 | {
82 | Assert.IsNotNull(window);
83 | Assert.IsTrue(window.CheckAccess());
84 |
85 | // Expect that this might be called on OSes other than Vista.
86 | if (!Utility.IsOSVistaOrNewer)
87 | {
88 | // Not an error. Just not on Vista so we're not going to get glass.
89 | return false;
90 | }
91 |
92 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
93 | if (IntPtr.Zero == hwnd)
94 | {
95 | throw new InvalidOperationException("Window must be shown before extending glass.");
96 | }
97 |
98 | HwndSource hwndSource = HwndSource.FromHwnd(hwnd);
99 |
100 | bool isGlassEnabled = NativeMethods.DwmIsCompositionEnabled();
101 |
102 | if (!isGlassEnabled)
103 | {
104 | window.Background = SystemColors.WindowBrush;
105 | hwndSource.CompositionTarget.BackgroundColor = SystemColors.WindowColor;
106 | }
107 | else
108 | {
109 | // Apply the transparent background to both the Window and the HWND
110 | window.Background = Brushes.Transparent;
111 | hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent;
112 |
113 | // Thickness is going to be DIPs, need to convert to system coordinates.
114 | Point deviceTopLeft = DpiHelper.LogicalPixelsToDevice(new Point(margin.Left, margin.Top));
115 | Point deviceBottomRight = DpiHelper.LogicalPixelsToDevice(new Point(margin.Right, margin.Bottom));
116 |
117 | var dwmMargin = new MARGINS
118 | {
119 | // err on the side of pushing in glass an extra pixel.
120 | cxLeftWidth = (int)Math.Ceiling(deviceTopLeft.X),
121 | cxRightWidth = (int)Math.Ceiling(deviceBottomRight.X),
122 | cyTopHeight = (int)Math.Ceiling(deviceTopLeft.Y),
123 | cyBottomHeight = (int)Math.Ceiling(deviceBottomRight.Y),
124 | };
125 |
126 | NativeMethods.DwmExtendFrameIntoClientArea(hwnd, ref dwmMargin);
127 | }
128 |
129 | // Even if glass isn't currently enabled, add the hook so we can appropriately respond
130 | // if that changes.
131 |
132 | bool addHook = !_extendedWindows.ContainsKey(hwnd);
133 |
134 | if (addHook)
135 | {
136 | HwndSourceHook hook = delegate(IntPtr innerHwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
137 | {
138 | if (WM.DWMCOMPOSITIONCHANGED == (WM)msg)
139 | {
140 | _ExtendGlassFrameInternal(window, margin);
141 | handled = false;
142 | }
143 | return IntPtr.Zero;
144 | };
145 |
146 | _extendedWindows.Add(hwnd, hook);
147 | hwndSource.AddHook(hook);
148 | window.Closing += _OnExtendedWindowClosing;
149 | }
150 |
151 | return isGlassEnabled;
152 | }
153 |
154 | ///
155 | /// Handler for the Closing event on a Window with an extended glass frame.
156 | ///
157 | /// The source of the event.
158 | /// The instance containing the event data.
159 | ///
160 | /// When a Window with an extended glass frame closes, removes any local references to it.
161 | ///
162 | // BUGBUG: Doesn't handle if the Closing gets canceled.
163 | static void _OnExtendedWindowClosing(object sender, CancelEventArgs e)
164 | {
165 | var window = sender as Window;
166 | Assert.IsNotNull(window);
167 |
168 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
169 |
170 | // We use the Closing rather than the Closed event to ensure that we can get this value.
171 | Assert.AreNotEqual(IntPtr.Zero, hwnd);
172 |
173 | HwndSource hwndSource = HwndSource.FromHwnd(hwnd);
174 |
175 | Assert.IsTrue(_extendedWindows.ContainsKey(hwnd));
176 |
177 | hwndSource.RemoveHook(_extendedWindows[hwnd]);
178 | _extendedWindows.Remove(hwnd);
179 |
180 | window.Closing -= _OnExtendedWindowClosing;
181 | }
182 |
183 | private static readonly Dictionary _attributedWindows = new Dictionary();
184 |
185 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
186 | public static bool SetWindowThemeAttribute(Window window, bool showCaption, bool showIcon)
187 | {
188 | Verify.IsNotNull(window, "window");
189 |
190 | window.VerifyAccess();
191 |
192 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
193 |
194 | if (_attributedWindows.ContainsKey(hwnd))
195 | {
196 | // The hook into the HWND's WndProc has the original settings cached.
197 | // Don't want to support dynamically adjusting that unless there's a need.
198 | throw new InvalidOperationException("Multiple calls to this function for the same Window are not supported.");
199 | }
200 |
201 | return _SetWindowThemeAttribute(window, showCaption, showIcon);
202 | }
203 |
204 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
205 | private static bool _SetWindowThemeAttribute(Window window, bool showCaption, bool showIcon)
206 | {
207 | bool isGlassEnabled;
208 |
209 | Assert.IsNotNull(window);
210 | Assert.IsTrue(window.CheckAccess());
211 |
212 | // This only is expected to work if Aero glass is enabled.
213 | try
214 | {
215 | isGlassEnabled = NativeMethods.DwmIsCompositionEnabled();
216 | }
217 | catch (DllNotFoundException)
218 | {
219 | // Not an error. Just not on Vista so we're not going to get glass.
220 | return false;
221 | }
222 |
223 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
224 | if (IntPtr.Zero == hwnd)
225 | {
226 | throw new InvalidOperationException("Window must be shown before we can modify attributes.");
227 | }
228 |
229 | var options = new WTA_OPTIONS
230 | {
231 | dwMask = (WTNCA.NODRAWCAPTION | WTNCA.NODRAWICON)
232 | };
233 | if (isGlassEnabled)
234 | {
235 | if (!showCaption)
236 | {
237 | options.dwFlags |= WTNCA.NODRAWCAPTION;
238 | }
239 | if (!showIcon)
240 | {
241 | options.dwFlags |= WTNCA.NODRAWICON;
242 | }
243 | }
244 |
245 | NativeMethods.SetWindowThemeAttribute(hwnd, WINDOWTHEMEATTRIBUTETYPE.WTA_NONCLIENT, ref options, WTA_OPTIONS.Size);
246 |
247 | bool addHook = !_attributedWindows.ContainsKey(hwnd);
248 |
249 | if (addHook)
250 | {
251 | HwndSourceHook hook = delegate(IntPtr unusedHwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
252 | {
253 | if (WM.DWMCOMPOSITIONCHANGED == (WM)msg)
254 | {
255 | _SetWindowThemeAttribute(window, showCaption, showIcon);
256 | handled = false;
257 | }
258 | return IntPtr.Zero;
259 | };
260 |
261 | _attributedWindows.Add(hwnd, hook);
262 | HwndSource.FromHwnd(hwnd).AddHook(hook);
263 | window.Closing += _OnAttributedWindowClosing;
264 | }
265 |
266 | return isGlassEnabled;
267 | }
268 |
269 | static void _OnAttributedWindowClosing(object sender, CancelEventArgs e)
270 | {
271 | var window = sender as Window;
272 | Assert.IsNotNull(window);
273 |
274 | IntPtr hwnd = new WindowInteropHelper(window).Handle;
275 |
276 | // We use the Closing rather than the Closed event to ensure that we can get this value.
277 | Assert.AreNotEqual(IntPtr.Zero, hwnd);
278 |
279 | HwndSource hwndSource = HwndSource.FromHwnd(hwnd);
280 |
281 | Assert.IsTrue(_attributedWindows.ContainsKey(hwnd));
282 |
283 | hwndSource.RemoveHook(_attributedWindows[hwnd]);
284 | _attributedWindows.Remove(hwnd);
285 |
286 | window.Closing -= _OnExtendedWindowClosing;
287 | }
288 |
289 | }
290 | }
291 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Wpf/MessageWindow.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics.CodeAnalysis;
6 | using System.Runtime.InteropServices;
7 | using System.Windows;
8 | using System.Windows.Threading;
9 |
10 | internal sealed class MessageWindow : DispatcherObject, IDisposable
11 | {
12 | // Alias this to a static so the wrapper doesn't get GC'd
13 | private static readonly WndProc s_WndProc = new WndProc(_WndProc);
14 | private static readonly Dictionary s_windowLookup = new Dictionary();
15 |
16 | private WndProc _wndProcCallback;
17 | private string _className;
18 | private bool _isDisposed;
19 |
20 | public IntPtr Handle { get; private set; }
21 |
22 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
23 | [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
24 | public MessageWindow(CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback)
25 | {
26 | // A null callback means just use DefWindowProc.
27 | _wndProcCallback = callback;
28 | _className = "MessageWindowClass+" + Guid.NewGuid().ToString();
29 |
30 | var wc = new WNDCLASSEX
31 | {
32 | cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)),
33 | style = classStyle,
34 | lpfnWndProc = s_WndProc,
35 | hInstance = NativeMethods.GetModuleHandle(null),
36 | hbrBackground = NativeMethods.GetStockObject(StockObject.NULL_BRUSH),
37 | lpszMenuName = "",
38 | lpszClassName = _className,
39 | };
40 |
41 | NativeMethods.RegisterClassEx(ref wc);
42 |
43 | GCHandle gcHandle = default(GCHandle);
44 | try
45 | {
46 | gcHandle = GCHandle.Alloc(this);
47 | IntPtr pinnedThisPtr = (IntPtr)gcHandle;
48 |
49 | Handle = NativeMethods.CreateWindowEx(
50 | exStyle,
51 | _className,
52 | name,
53 | style,
54 | (int)location.X,
55 | (int)location.Y,
56 | (int)location.Width,
57 | (int)location.Height,
58 | IntPtr.Zero,
59 | IntPtr.Zero,
60 | IntPtr.Zero,
61 | pinnedThisPtr);
62 | }
63 | finally
64 | {
65 | gcHandle.Free();
66 | }
67 | }
68 |
69 | ~MessageWindow()
70 | {
71 | _Dispose(false, false);
72 | }
73 |
74 | public void Dispose()
75 | {
76 | _Dispose(true, false);
77 | GC.SuppressFinalize(this);
78 | }
79 |
80 | // This isn't right if the Dispatcher has already started shutting down.
81 | // The HWND itself will get cleaned up on thread completion, but it will wind up leaking the class ATOM...
82 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")]
83 | private void _Dispose(bool disposing, bool isHwndBeingDestroyed)
84 | {
85 | if (_isDisposed)
86 | {
87 | // Block against reentrancy.
88 | return;
89 | }
90 |
91 | _isDisposed = true;
92 |
93 | IntPtr hwnd = Handle;
94 | string className = _className;
95 |
96 | if (isHwndBeingDestroyed)
97 | {
98 | Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(IntPtr.Zero, className)));
99 | }
100 | else if (Handle != IntPtr.Zero)
101 | {
102 | if (CheckAccess())
103 | {
104 | _DestroyWindow(hwnd, className);
105 | }
106 | else
107 | {
108 | Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)(arg => _DestroyWindow(hwnd, className)));
109 | }
110 | }
111 |
112 | s_windowLookup.Remove(hwnd);
113 |
114 | _className = null;
115 | Handle = IntPtr.Zero;
116 | }
117 |
118 | [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")]
119 | private static IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam)
120 | {
121 | IntPtr ret = IntPtr.Zero;
122 | MessageWindow hwndWrapper = null;
123 |
124 | if (msg == WM.CREATE)
125 | {
126 | var createStruct = (CREATESTRUCT)Marshal.PtrToStructure(lParam, typeof(CREATESTRUCT));
127 | GCHandle gcHandle = GCHandle.FromIntPtr(createStruct.lpCreateParams);
128 | hwndWrapper = (MessageWindow)gcHandle.Target;
129 | s_windowLookup.Add(hwnd, hwndWrapper);
130 | }
131 | else
132 | {
133 | if (!s_windowLookup.TryGetValue(hwnd, out hwndWrapper))
134 | {
135 | return NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam);
136 | }
137 | }
138 | Assert.IsNotNull(hwndWrapper);
139 |
140 | WndProc callback = hwndWrapper._wndProcCallback;
141 | if (callback != null)
142 | {
143 | ret = callback(hwnd, msg, wParam, lParam);
144 | }
145 | else
146 | {
147 | ret = NativeMethods.DefWindowProc(hwnd, msg, wParam, lParam);
148 | }
149 |
150 | if (msg == WM.NCDESTROY)
151 | {
152 | hwndWrapper._Dispose(true, true);
153 | GC.SuppressFinalize(hwndWrapper);
154 | }
155 |
156 | return ret;
157 | }
158 |
159 | private static object _DestroyWindow(IntPtr hwnd, string className)
160 | {
161 | Utility.SafeDestroyWindow(ref hwnd);
162 | NativeMethods.UnregisterClass(className, NativeMethods.GetModuleHandle(null));
163 | return null;
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/Microsoft.Windows.Shell/standard.net/Wpf/SingleInstance.cs:
--------------------------------------------------------------------------------
1 | namespace Standard
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics.CodeAnalysis;
6 | using System.Runtime.Remoting;
7 | using System.Runtime.Remoting.Channels;
8 | using System.Runtime.Remoting.Channels.Ipc;
9 | using System.Runtime.Serialization.Formatters;
10 | using System.Threading;
11 |
12 | internal class SingleInstanceEventArgs : EventArgs
13 | {
14 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
15 | public IList Args { get; internal set; }
16 | }
17 |
18 | internal static class SingleInstance
19 | {
20 | public static event EventHandler SingleInstanceActivated;
21 |
22 | private class _IpcRemoteService : MarshalByRefObject
23 | {
24 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
25 | public int GetProcessId()
26 | {
27 | return System.Diagnostics.Process.GetCurrentProcess().Id;
28 | }
29 |
30 | /// Activate the first instance of the application.
31 | /// Command line arguemnts to proxy.
32 | [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
33 | public void InvokeFirstInstance(IList args)
34 | {
35 | if (System.Windows.Application.Current != null && !System.Windows.Application.Current.Dispatcher.HasShutdownStarted)
36 | {
37 | System.Windows.Application.Current.Dispatcher.BeginInvoke((Action