├── .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)((arg) => SingleInstance._ActivateFirstInstance((IList)arg)), args); 38 | } 39 | } 40 | 41 | /// Overrides the default lease lifetime of 5 minutes so it will ever expire. 42 | public override object InitializeLifetimeService() 43 | { 44 | return null; 45 | } 46 | } 47 | 48 | private const string _RemoteServiceName = "SingleInstanceApplicationService"; 49 | private static Mutex _singleInstanceMutex; 50 | private static IpcServerChannel _channel; 51 | 52 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 53 | public static bool InitializeAsFirstInstance(string applicationName) 54 | { 55 | IList commandLineArgs = Environment.GetCommandLineArgs() ?? new string[0]; 56 | 57 | // Build a repeatable machine unique name for the channel. 58 | string appId = applicationName + Environment.UserName; 59 | string channelName = appId + ":SingleInstanceIPCChannel"; 60 | 61 | bool isFirstInstance; 62 | _singleInstanceMutex = new Mutex(true, appId, out isFirstInstance); 63 | if (isFirstInstance) 64 | { 65 | _CreateRemoteService(channelName); 66 | } 67 | else 68 | { 69 | _SignalFirstInstance(channelName, commandLineArgs); 70 | } 71 | 72 | return isFirstInstance; 73 | } 74 | 75 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 76 | public static void Cleanup() 77 | { 78 | Utility.SafeDispose(ref _singleInstanceMutex); 79 | 80 | if (_channel != null) 81 | { 82 | ChannelServices.UnregisterChannel(_channel); 83 | _channel = null; 84 | } 85 | } 86 | 87 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 88 | private static void _CreateRemoteService(string channelName) 89 | { 90 | _channel = new IpcServerChannel( 91 | new Dictionary 92 | { 93 | { "name", channelName }, 94 | { "portName", channelName }, 95 | { "exclusiveAddressUse", "false" }, 96 | }, 97 | new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Full }); 98 | 99 | ChannelServices.RegisterChannel(_channel, true); 100 | RemotingServices.Marshal(new _IpcRemoteService(), _RemoteServiceName); 101 | } 102 | 103 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 104 | private static void _SignalFirstInstance(string channelName, IList args) 105 | { 106 | var secondInstanceChannel = new IpcClientChannel(); 107 | ChannelServices.RegisterChannel(secondInstanceChannel, true); 108 | 109 | string remotingServiceUrl = "ipc://" + channelName + "/" + _RemoteServiceName; 110 | 111 | // Obtain a reference to the remoting service exposed by the first instance of the application 112 | var firstInstanceRemoteServiceReference = (_IpcRemoteService)RemotingServices.Connect(typeof(_IpcRemoteService), remotingServiceUrl); 113 | 114 | // Pass along the current arguments to the first instance if it's up and accepting requests. 115 | if (firstInstanceRemoteServiceReference != null) 116 | { 117 | // Allow the first instance to give itself user focus. 118 | // This could be done with ASFW_ANY if the IPC call is expensive. 119 | int procId = firstInstanceRemoteServiceReference.GetProcessId(); 120 | NativeMethods.AllowSetForegroundWindow(procId); 121 | 122 | firstInstanceRemoteServiceReference.InvokeFirstInstance(args); 123 | } 124 | } 125 | 126 | private static void _ActivateFirstInstance(IList args) 127 | { 128 | if (System.Windows.Application.Current != null && !System.Windows.Application.Current.Dispatcher.HasShutdownStarted) 129 | { 130 | var handler = SingleInstanceActivated; 131 | if (handler != null) 132 | { 133 | handler(System.Windows.Application.Current, new SingleInstanceEventArgs { Args = args }); 134 | } 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Microsoft.Windows.Shell/standard.net/Wpf/SplashScreen.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Standard 3 | { 4 | using System; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Globalization; 7 | using System.IO; 8 | using System.Reflection; 9 | using System.Resources; 10 | using System.Runtime.InteropServices; 11 | using System.Windows; 12 | using System.Windows.Threading; 13 | 14 | // Current issues with this implementation: 15 | // * FadeOutDuration will pop the splashscreen in front of the main window. This can be partially managed 16 | // by using IsTopMost, but that has other effects. I should be able to hook the WndProc to keep this 17 | // window from going inactive. 18 | // * FadeInDuration doesn't work because this is being created on the main UI thread. For multiple reasons we 19 | // should probably create this window on a background thread. 20 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] 21 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")] 22 | internal class SplashScreen 23 | { 24 | private static readonly BLENDFUNCTION _BaseBlendFunction = new BLENDFUNCTION 25 | { 26 | BlendOp = AC.SRC_OVER, 27 | BlendFlags = 0, 28 | SourceConstantAlpha = 255, 29 | AlphaFormat = AC.SRC_ALPHA, 30 | }; 31 | 32 | private MessageWindow _hwndWrapper; 33 | private SafeHBITMAP _hBitmap; 34 | private DispatcherTimer _dt; 35 | private DateTime _fadeOutEnd; 36 | private DateTime _fadeInEnd; 37 | private ResourceManager _resourceManager; 38 | private string _resourceName; 39 | private Dispatcher _dispatcher; 40 | private Assembly _resourceAssembly; 41 | private bool _isClosed = false; 42 | 43 | private void _VerifyMutability() 44 | { 45 | if (_hwndWrapper != null) 46 | { 47 | throw new InvalidOperationException("Splash screen has already been shown."); 48 | } 49 | } 50 | 51 | public SplashScreen() { } 52 | 53 | public Assembly ResourceAssembly 54 | { 55 | get { return _resourceAssembly; } 56 | set 57 | { 58 | _VerifyMutability(); 59 | 60 | Verify.IsNotNull(value, "value"); 61 | 62 | _resourceAssembly = value; 63 | AssemblyName name = new AssemblyName(_resourceAssembly.FullName); 64 | _resourceManager = new ResourceManager(name.Name + ".g", _resourceAssembly); 65 | } 66 | } 67 | 68 | [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] 69 | public string ResourceName 70 | { 71 | get { return _resourceName ?? ""; } 72 | set 73 | { 74 | Verify.IsNeitherNullNorEmpty(value, "value"); 75 | _resourceName = value.ToLowerInvariant(); 76 | } 77 | } 78 | 79 | public string ImageFileName { get; set; } 80 | public bool IsTopMost { get; set; } 81 | public bool CloseOnMainWindowCreation { get; set; } 82 | public TimeSpan FadeOutDuration { get; set; } 83 | public TimeSpan FadeInDuration { get; set; } 84 | 85 | private Stream _GetImageStream() 86 | { 87 | Stream imageStream = null; 88 | // Try to use the filepath first. If it's not provided or not available, use the embedded resource. 89 | if (!string.IsNullOrEmpty(ImageFileName) && File.Exists(ImageFileName)) 90 | { 91 | try 92 | { 93 | imageStream = new FileStream(ImageFileName, FileMode.Open); 94 | } 95 | catch (IOException) { } 96 | } 97 | 98 | if (imageStream == null) 99 | { 100 | imageStream = _resourceManager.GetStream(ResourceName, CultureInfo.CurrentUICulture); 101 | if (imageStream == null) 102 | { 103 | throw new IOException("The resource could not be found."); 104 | } 105 | } 106 | 107 | return imageStream; 108 | } 109 | 110 | public void Show() 111 | { 112 | _VerifyMutability(); 113 | 114 | using (Stream imageStream = _GetImageStream()) 115 | { 116 | Size bitmapSize; 117 | _hBitmap = _CreateHBITMAPFromImageStream(imageStream, out bitmapSize); 118 | 119 | Point location = new Point( 120 | (NativeMethods.GetSystemMetrics(SM.CXSCREEN) - bitmapSize.Width) / 2, 121 | (NativeMethods.GetSystemMetrics(SM.CYSCREEN) - bitmapSize.Height) / 2); 122 | 123 | // Pass a null WndProc. Let the MessageWindow use DefWindowProc. 124 | _hwndWrapper = new MessageWindow( 125 | CS.HREDRAW | CS.VREDRAW, 126 | WS.POPUP | WS.VISIBLE, 127 | WS_EX.WINDOWEDGE | WS_EX.TOOLWINDOW | WS_EX.LAYERED | (IsTopMost ? WS_EX.TOPMOST : 0), 128 | new Rect(location, bitmapSize), 129 | "Splash Screen", 130 | null); 131 | 132 | byte opacity = (byte)(FadeInDuration > TimeSpan.Zero ? 0 : 255); 133 | 134 | using (SafeDC hScreenDC = SafeDC.GetDesktop()) 135 | { 136 | using (SafeDC memDC = SafeDC.CreateCompatibleDC(hScreenDC)) 137 | { 138 | IntPtr hOldBitmap = NativeMethods.SelectObject(memDC, _hBitmap); 139 | 140 | RECT hwndRect = NativeMethods.GetWindowRect(_hwndWrapper.Handle); 141 | 142 | POINT hwndPos = hwndRect.Position; 143 | SIZE hwndSize = hwndRect.Size; 144 | POINT origin = new POINT(); 145 | BLENDFUNCTION bf = _BaseBlendFunction; 146 | bf.SourceConstantAlpha = opacity; 147 | 148 | NativeMethods.UpdateLayeredWindow(_hwndWrapper.Handle, hScreenDC, ref hwndPos, ref hwndSize, memDC, ref origin, 0, ref bf, ULW.ALPHA); 149 | NativeMethods.SelectObject(memDC, hOldBitmap); 150 | } 151 | } 152 | 153 | if (CloseOnMainWindowCreation) 154 | { 155 | Dispatcher.CurrentDispatcher.BeginInvoke( 156 | DispatcherPriority.Loaded, 157 | (DispatcherOperationCallback)delegate(object splashObj) 158 | { 159 | var splashScreen = (SplashScreen)splashObj; 160 | if (!splashScreen._isClosed) 161 | { 162 | splashScreen.Close(); 163 | } 164 | return null; 165 | }, 166 | this); 167 | } 168 | 169 | _dispatcher = Dispatcher.CurrentDispatcher; 170 | if (FadeInDuration > TimeSpan.Zero) 171 | { 172 | _fadeInEnd = DateTime.UtcNow + FadeInDuration; 173 | _dt = new DispatcherTimer(FadeInDuration, DispatcherPriority.Normal, _FadeInTick, _dispatcher); 174 | _dt.Start(); 175 | } 176 | } 177 | } 178 | 179 | [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] 180 | public void Close() 181 | { 182 | if (!_dispatcher.CheckAccess()) 183 | { 184 | _dispatcher.Invoke(DispatcherPriority.Normal, (Action)Close); 185 | return; 186 | } 187 | 188 | if (_isClosed) 189 | { 190 | throw new InvalidOperationException("Splash screen was already closed"); 191 | } 192 | 193 | _isClosed = true; 194 | 195 | if (FadeOutDuration <= TimeSpan.Zero) 196 | { 197 | _DestroyResources(); 198 | return; 199 | } 200 | 201 | try 202 | { 203 | NativeMethods.SetActiveWindow(_hwndWrapper.Handle); 204 | } 205 | catch 206 | { 207 | // SetActiveWindow fails if the application is not in the foreground. 208 | // If this is the case, don't bother animating the fade out. 209 | _DestroyResources(); 210 | return; 211 | } 212 | 213 | _fadeOutEnd = DateTime.UtcNow + FadeOutDuration; 214 | if (_dt != null) 215 | { 216 | _dt.Stop(); 217 | } 218 | _dt = new DispatcherTimer(TimeSpan.FromMilliseconds(30), DispatcherPriority.Normal, _FadeOutTick, _dispatcher); 219 | _dt.Start(); 220 | 221 | return; 222 | } 223 | 224 | private void _FadeOutTick(object unused, EventArgs args) 225 | { 226 | DateTime dtNow = DateTime.UtcNow; 227 | if (dtNow >= _fadeOutEnd) 228 | { 229 | _DestroyResources(); 230 | } 231 | else 232 | { 233 | double progress = (_fadeOutEnd - dtNow).TotalMilliseconds / FadeOutDuration.TotalMilliseconds; 234 | BLENDFUNCTION bf = _BaseBlendFunction; 235 | bf.SourceConstantAlpha = (byte)(255 * progress); 236 | NativeMethods.UpdateLayeredWindow(_hwndWrapper.Handle, 0, ref bf, ULW.ALPHA); 237 | } 238 | } 239 | 240 | private void _FadeInTick(object unused, EventArgs args) 241 | { 242 | DateTime dtNow = DateTime.UtcNow; 243 | if (dtNow >= _fadeInEnd) 244 | { 245 | _DestroyResources(); 246 | } 247 | else 248 | { 249 | double progress = 1 - (_fadeInEnd - dtNow).TotalMilliseconds / FadeInDuration.TotalMilliseconds; 250 | progress = Math.Max(0, Math.Min(progress, 1)); 251 | BLENDFUNCTION bf = _BaseBlendFunction; 252 | bf.SourceConstantAlpha = (byte)(int)(255 * progress); 253 | NativeMethods.UpdateLayeredWindow(_hwndWrapper.Handle, 0, ref bf, ULW.ALPHA); 254 | } 255 | } 256 | 257 | private void _DestroyResources() 258 | { 259 | if (_dt != null) 260 | { 261 | _dt.Stop(); 262 | _dt = null; 263 | } 264 | Utility.SafeDispose(ref _hwndWrapper); 265 | Utility.SafeDispose(ref _hBitmap); 266 | if (_resourceManager != null) 267 | { 268 | _resourceManager.ReleaseAllResources(); 269 | } 270 | } 271 | 272 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 273 | [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] 274 | private static SafeHBITMAP _CreateHBITMAPFromImageStream(Stream imgStream, out Size bitmapSize) 275 | { 276 | IWICImagingFactory pImagingFactory = null; 277 | IWICBitmapDecoder pDecoder = null; 278 | IWICStream pStream = null; 279 | IWICBitmapFrameDecode pDecodedFrame = null; 280 | IWICFormatConverter pBitmapSourceFormatConverter = null; 281 | IWICBitmapFlipRotator pBitmapFlipRotator = null; 282 | 283 | SafeHBITMAP hbmp = null; 284 | try 285 | { 286 | using (var istm = new ManagedIStream(imgStream)) 287 | { 288 | pImagingFactory = CLSID.CoCreateInstance(CLSID.WICImagingFactory); 289 | pStream = pImagingFactory.CreateStream(); 290 | pStream.InitializeFromIStream(istm); 291 | 292 | // Create an object that will decode the encoded image 293 | Guid vendor = Guid.Empty; 294 | pDecoder = pImagingFactory.CreateDecoderFromStream(pStream, ref vendor, WICDecodeMetadata.CacheOnDemand); 295 | 296 | pDecodedFrame = pDecoder.GetFrame(0); 297 | pBitmapSourceFormatConverter = pImagingFactory.CreateFormatConverter(); 298 | 299 | // Convert the image from whatever format it is in to 32bpp premultiplied alpha BGRA 300 | Guid pixelFormat = WICPixelFormat.WICPixelFormat32bppPBGRA; 301 | pBitmapSourceFormatConverter.Initialize(pDecodedFrame, ref pixelFormat, WICBitmapDitherType.None, IntPtr.Zero, 0, WICBitmapPaletteType.Custom); 302 | 303 | pBitmapFlipRotator = pImagingFactory.CreateBitmapFlipRotator(); 304 | pBitmapFlipRotator.Initialize(pBitmapSourceFormatConverter, WICBitmapTransform.FlipVertical); 305 | 306 | int width, height; 307 | pBitmapFlipRotator.GetSize(out width, out height); 308 | 309 | bitmapSize = new Size { Width = width, Height = height }; 310 | 311 | var bmi = new BITMAPINFO 312 | { 313 | bmiHeader = new BITMAPINFOHEADER 314 | { 315 | biSize = Marshal.SizeOf(typeof(BITMAPINFOHEADER)), 316 | biWidth = width, 317 | biHeight = height, 318 | biPlanes = 1, 319 | biBitCount = 32, 320 | biCompression = BI.RGB, 321 | biSizeImage = (width * height * 4), 322 | }, 323 | }; 324 | 325 | // Create a 32bpp DIB. This DIB must have an alpha channel for UpdateLayeredWindow to succeed. 326 | IntPtr pBitmapBits; 327 | hbmp = NativeMethods.CreateDIBSection(null, ref bmi, out pBitmapBits, IntPtr.Zero, 0); 328 | 329 | // Copy the decoded image to the new buffer which backs the HBITMAP 330 | var rect = new WICRect { X = 0, Y = 0, Width = width, Height = height }; 331 | pBitmapFlipRotator.CopyPixels(ref rect, width * 4, bmi.bmiHeader.biSizeImage, pBitmapBits); 332 | 333 | var ret = hbmp; 334 | hbmp = null; 335 | return ret; 336 | } 337 | } 338 | finally 339 | { 340 | Utility.SafeRelease(ref pImagingFactory); 341 | Utility.SafeRelease(ref pDecoder); 342 | Utility.SafeRelease(ref pStream); 343 | Utility.SafeRelease(ref pDecodedFrame); 344 | Utility.SafeRelease(ref pBitmapFlipRotator); 345 | Utility.SafeRelease(ref pBitmapSourceFormatConverter); 346 | Utility.SafeDispose(ref hbmp); 347 | } 348 | } 349 | } 350 | } -------------------------------------------------------------------------------- /Microsoft.Windows.Shell/standard.net/Wpf/WindowExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Standard 3 | { 4 | using System; 5 | using System.ComponentModel; 6 | using System.Windows; 7 | using System.Windows.Interop; 8 | using System.Windows.Media; 9 | 10 | /// 11 | /// Attached properties for WPF Windows. 12 | /// 13 | internal sealed class WindowExtensions 14 | { 15 | private IntPtr _hwnd = IntPtr.Zero; 16 | private Window _window = null; 17 | 18 | private event Action WindowSourceInitialized; 19 | 20 | private WindowExtensions(Window window) 21 | { 22 | Assert.IsNotNull(window); 23 | _window = window; 24 | _hwnd = new WindowInteropHelper(window).Handle; 25 | 26 | if (_hwnd == IntPtr.Zero) 27 | { 28 | _window.SourceInitialized += _OnWindowSourceInitialized; 29 | } 30 | } 31 | 32 | private void _OnWindowSourceInitialized(object sender, EventArgs e) 33 | { 34 | Assert.AreEqual(sender, _window); 35 | 36 | _window.SourceInitialized -= _OnWindowSourceInitialized; 37 | 38 | _hwnd = new WindowInteropHelper(_window).Handle; 39 | Assert.IsNotDefault(_hwnd); 40 | 41 | Action handler = WindowSourceInitialized; 42 | if (handler != null) 43 | { 44 | handler(); 45 | } 46 | } 47 | 48 | private static WindowExtensions _EnsureAttachedExtensions(Window window) 49 | { 50 | Assert.IsNotNull(window); 51 | 52 | var ext = (WindowExtensions)window.GetValue(WindowExtensionsProperty); 53 | if (ext == null) 54 | { 55 | ext = new WindowExtensions(window); 56 | window.SetValue(WindowExtensionsProperty, ext); 57 | } 58 | 59 | return ext; 60 | } 61 | 62 | private static readonly DependencyProperty WindowExtensionsProperty = DependencyProperty.RegisterAttached( 63 | "WindowExtensions", 64 | typeof(WindowExtensions), 65 | typeof(WindowExtensions), 66 | new PropertyMetadata(null)); 67 | 68 | // Not bothering with CLR attached property getter/setter since this is a private dependency property. 69 | 70 | 71 | public static readonly DependencyProperty HwndBackgroundBrushProperty = DependencyProperty.RegisterAttached( 72 | "HwndBackgroundBrush", 73 | typeof(SolidColorBrush), 74 | typeof(WindowExtensions), 75 | new PropertyMetadata( 76 | Brushes.Pink, 77 | (d,e) => _OnHwndBackgroundBrushChanged(d))); 78 | 79 | public static SolidColorBrush GetHwndBackgroundBrush(FrameworkElement window) 80 | { 81 | Verify.IsNotNull(window, "window"); 82 | return (SolidColorBrush)window.GetValue(HwndBackgroundBrushProperty); 83 | } 84 | 85 | public static void SetHwndBackgroundBrush(FrameworkElement window, SolidColorBrush value) 86 | { 87 | if (!(window is Window)) 88 | { 89 | return; 90 | } 91 | Verify.IsNotNull(window, "window"); 92 | window.SetValue(HwndBackgroundBrushProperty, value); 93 | } 94 | 95 | private static void _OnHwndBackgroundBrushChanged(DependencyObject d) 96 | { 97 | if (DesignerProperties.GetIsInDesignMode(d)) 98 | { 99 | return; 100 | } 101 | 102 | var window = d as Window; 103 | Verify.IsNotNull(window, "window"); 104 | 105 | WindowExtensions ext = _EnsureAttachedExtensions(window); 106 | 107 | if (ext._hwnd == IntPtr.Zero) 108 | { 109 | ext.WindowSourceInitialized += () => _OnHwndBackgroundBrushChanged(window); 110 | return; 111 | } 112 | 113 | SolidColorBrush backgroundBrush = (SolidColorBrush)window.GetValue(HwndBackgroundBrushProperty); 114 | //if (backgroundBrush == null) 115 | //{ 116 | // Nothing to change. 117 | // return; 118 | //} 119 | 120 | Color backgroundColor = backgroundBrush.Color; 121 | 122 | // Not really handling errors here, but they shouldn't matter... Might leak an HBRUSH. 123 | 124 | IntPtr hBrush = NativeMethods.CreateSolidBrush(Utility.RGB(backgroundColor)); 125 | 126 | // Note that setting this doesn't necessarily repaint the window right away. 127 | // Since the WPF content should cover the HWND background this doesn't matter. 128 | // The new background will get repainted when the window is resized. 129 | IntPtr hBrushOld = NativeMethods.SetClassLongPtr(ext._hwnd, GCLP.HBRBACKGROUND, hBrush); 130 | 131 | if (IntPtr.Zero != hBrushOld) 132 | { 133 | NativeMethods.DeleteObject(hBrushOld); 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WPF Shell Integration Library (Ex)tended Edition 2 | === 3 | 4 | This is a .Net library for providing custom chrome for WPF windows and some other deeper integration with 5 | the Windows Shell. It's a concrete implementation of techniques described here: 6 | 7 | http://blogs.msdn.com/b/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx 8 | 9 | It's a fork of the original [WPF Shell Integration Library](http://archive.msdn.microsoft.com/WPFShell), 10 | which hasn't been updated in a while, and the download links for that are for older frameworks and the 11 | source has some bugs that I've addressed since. Some of this code has since been incorporated into the 12 | current .Net framework, but this library gives the ability to use these features in older versions of the 13 | framework, or more deeply extend the interop code to enable more features. 14 | -------------------------------------------------------------------------------- /TaskbarSample/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 14 | 15 | 19 | 20 | 27 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /TaskbarSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | /**************************************************************************\ 2 | Copyright Microsoft Corporation. All Rights Reserved. 3 | \**************************************************************************/ 4 | 5 | namespace TaskbarSample 6 | { 7 | using System.Text; 8 | using System.Windows; 9 | using Microsoft.Windows.Shell; 10 | 11 | public partial class App : Application 12 | { 13 | private void OnJumpItemsRejected(object sender, JumpItemsRejectedEventArgs e) 14 | { 15 | var sb = new StringBuilder(); 16 | sb.AppendFormat("{0} Jump Items Rejected:\n", e.RejectionReasons.Count); 17 | for (int i = 0; i < e.RejectionReasons.Count; ++i) 18 | { 19 | sb.AppendFormat("Reason: {0}\tItem: {1}\n", e.RejectionReasons[i], e.RejectedItems[i]); 20 | } 21 | 22 | MessageBox.Show(sb.ToString()); 23 | } 24 | 25 | private void OnJumpItemsRemoved(object sender, JumpItemsRemovedEventArgs e) 26 | { 27 | StringBuilder sb = new StringBuilder(); 28 | sb.AppendFormat("{0} Jump Items Removed by the user:\n", e.RemovedItems.Count); 29 | for (int i = 0; i < e.RemovedItems.Count; ++i) 30 | { 31 | sb.AppendFormat("{0}\n", e.RemovedItems[i]); 32 | } 33 | 34 | MessageBox.Show(sb.ToString()); 35 | } 36 | 37 | private void OnStartup(object sender, StartupEventArgs e) 38 | { 39 | if (e.Args.Length > 0) 40 | { 41 | MessageBox.Show(e.Args[0], "Application Startup Argument"); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TaskbarSample/Images/CircleGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/CircleGreen.png -------------------------------------------------------------------------------- /TaskbarSample/Images/CircleRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/CircleRed.png -------------------------------------------------------------------------------- /TaskbarSample/Images/CircleYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/CircleYellow.png -------------------------------------------------------------------------------- /TaskbarSample/Images/Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/Copy.png -------------------------------------------------------------------------------- /TaskbarSample/Images/Cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/Cut.png -------------------------------------------------------------------------------- /TaskbarSample/Images/Paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/Images/Paste.png -------------------------------------------------------------------------------- /TaskbarSample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 36 | 42 | 48 | 54 | 57 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | None 125 | 126 | 127 | 128 | 129 | 130 | Show in taskbar? 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | Show Recent 146 | Show Frequent 147 | Defer Apply 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /TaskbarSample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | /**************************************************************************\ 2 | Copyright Microsoft Corporation. All Rights Reserved. 3 | \**************************************************************************/ 4 | 5 | namespace TaskbarSample 6 | { 7 | using System; 8 | using System.Windows; 9 | using Microsoft.Windows.Shell; 10 | 11 | public partial class MainWindow : Window 12 | { 13 | public MainWindow() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | private bool DeferApply 19 | { 20 | get 21 | { 22 | return _deferApply.IsChecked ?? false; 23 | } 24 | } 25 | 26 | private void ThumbButtonInfo_Click(object sender, EventArgs e) 27 | { 28 | } 29 | 30 | private void JumpTask_AddToRecent(object sender, RoutedEventArgs e) 31 | { 32 | JumpTask jt = GenerateJumpTask(); 33 | JumpList.AddToRecentCategory(jt); 34 | } 35 | 36 | private void JumpTask_AddToCategory(object sender, RoutedEventArgs e) 37 | { 38 | JumpTask jt = GenerateJumpTask(); 39 | var jl = JumpList.GetJumpList(Application.Current); 40 | jl.JumpItems.Add(jt); 41 | if (!DeferApply) 42 | { 43 | jl.Apply(); 44 | } 45 | } 46 | 47 | private void JumpPath_AddToRecent(object sender, RoutedEventArgs e) 48 | { 49 | JumpPath jp = GenerateJumpPath(); 50 | JumpList.AddToRecentCategory(jp); 51 | } 52 | 53 | private void JumpPath_AddToCategory(object sender, RoutedEventArgs e) 54 | { 55 | JumpPath jp = GenerateJumpPath(); 56 | var jl = JumpList.GetJumpList(Application.Current); 57 | jl.JumpItems.Add(jp); 58 | if (!DeferApply) 59 | { 60 | jl.Apply(); 61 | } 62 | } 63 | 64 | private void JumpList_Clear(object sender, RoutedEventArgs e) 65 | { 66 | var jl = JumpList.GetJumpList(Application.Current); 67 | jl.JumpItems.Clear(); 68 | if (!DeferApply) 69 | { 70 | jl.Apply(); 71 | } 72 | } 73 | 74 | private void JumpList_Apply(object sender, RoutedEventArgs e) 75 | { 76 | var jl = JumpList.GetJumpList(Application.Current); 77 | jl.Apply(); 78 | } 79 | 80 | private void UpdateKnownCategories(object sender, RoutedEventArgs e) 81 | { 82 | bool showRecent = _showRecentButton.IsChecked ?? false; 83 | bool showFrequent = _showFrequentButton.IsChecked ?? false; 84 | var jl = JumpList.GetJumpList(Application.Current); 85 | jl.ShowRecentCategory = showRecent; 86 | jl.ShowFrequentCategory = showFrequent; 87 | 88 | if (!DeferApply) 89 | { 90 | jl.Apply(); 91 | } 92 | } 93 | 94 | private JumpPath GenerateJumpPath() 95 | { 96 | return new JumpPath 97 | { 98 | Path = _jumpPathPathBox.Text, 99 | CustomCategory = _jumpPathCategoryBox.Text 100 | }; 101 | } 102 | 103 | private JumpTask GenerateJumpTask() 104 | { 105 | var jt = new JumpTask 106 | { 107 | ApplicationPath = _jumpTaskAppPathBox.Text, 108 | IconResourcePath = _jumpTaskIconResourcePathBox.Text, 109 | Arguments = _jumpTaskArgsBox.Text, 110 | Title = _jumpTaskTitleBox.Text, 111 | Description = _jumpTaskDescriptionBox.Text, 112 | WorkingDirectory = _jumpTaskWorkingDirBox.Text, 113 | CustomCategory = _jumpTaskCategoryBox.Text, 114 | }; 115 | 116 | int i; 117 | if (int.TryParse(_jumpTaskIconResourceIndexBox.Text, out i)) 118 | { 119 | jt.IconResourceIndex = i; 120 | } 121 | 122 | return jt; 123 | } 124 | 125 | private void ClearJumpTaskInput() 126 | { 127 | _jumpTaskAppPathBox.Text = ""; 128 | _jumpTaskIconResourcePathBox.Text = ""; 129 | _jumpTaskArgsBox.Text = ""; 130 | _jumpTaskTitleBox.Text = ""; 131 | _jumpTaskDescriptionBox.Text = ""; 132 | _jumpTaskWorkingDirBox.Text = ""; 133 | _jumpTaskCategoryBox.Text = ""; 134 | } 135 | 136 | private void JumpTask_ClearInput(object sender, RoutedEventArgs e) 137 | { 138 | ClearJumpTaskInput(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /TaskbarSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Reflection; 4 | using System.Resources; 5 | using System.Runtime.InteropServices; 6 | using System.Windows; 7 | 8 | [assembly: AssemblyTitle("TaskbarSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("TaskbarSample")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | [assembly: ComVisible(false)] 18 | [assembly: CLSCompliant(true)] 19 | 20 | [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)] 21 | [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] 22 | 23 | [assembly: AssemblyVersion("1.0.0.0")] 24 | [assembly: AssemblyFileVersion("1.0.0.0")] 25 | 26 | [assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] 27 | -------------------------------------------------------------------------------- /TaskbarSample/TaskbarSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {F7D0B052-2123-4DFD-B844-C545A1082514} 9 | WinExe 10 | Properties 11 | TaskbarSample 12 | TaskbarSample 13 | v3.5 14 | 512 15 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 4 17 | app.ico 18 | 3.5 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | true 33 | Client 34 | 35 | 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | AllRules.ruleset 44 | 45 | 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | AllRules.ruleset 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | MSBuild:Compile 66 | Designer 67 | MSBuild:Compile 68 | Designer 69 | 70 | 71 | MSBuild:Compile 72 | Designer 73 | MSBuild:Compile 74 | Designer 75 | 76 | 77 | App.xaml 78 | Code 79 | 80 | 81 | MainWindow.xaml 82 | Code 83 | 84 | 85 | 86 | 87 | Code 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | {8F016757-F022-4338-9989-9CEE39BFC087} 104 | Microsoft.Windows.Shell.v35 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /TaskbarSample/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /TaskbarSample/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/TaskbarSample/app.ico -------------------------------------------------------------------------------- /WindowChromeSample/App.xaml: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /WindowChromeSample/CaptionButtonRectToMarginConverter.cs: -------------------------------------------------------------------------------- 1 | /**************************************************************************\ 2 | Copyright Microsoft Corporation. All Rights Reserved. 3 | \**************************************************************************/ 4 | 5 | namespace WindowChromeSample 6 | { 7 | using System; 8 | using System.Windows; 9 | using System.Windows.Data; 10 | 11 | public class CaptionButtonRectToMarginConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 14 | { 15 | var captionLocation = (Rect)value; 16 | 17 | return new Thickness(0, captionLocation.Top, -captionLocation.Right, 0); 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 21 | { 22 | throw new NotSupportedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WindowChromeSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("WindowChromeSample")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Microsoft")] 14 | [assembly: AssemblyProduct("WindowChromeSample")] 15 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | [assembly: ComVisible(false)] 20 | 21 | [assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)] 22 | 23 | [assembly: AssemblyVersion("1.0.0.0")] 24 | [assembly: AssemblyFileVersion("1.0.0.0")] 25 | -------------------------------------------------------------------------------- /WindowChromeSample/SelectableChromeWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 47 | 48 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /WindowChromeSample/SelectableChromeWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | /**************************************************************************\ 2 | Copyright Microsoft Corporation. All Rights Reserved. 3 | \**************************************************************************/ 4 | 5 | namespace WindowChromeSample 6 | { 7 | using System.Windows; 8 | using System.Windows.Input; 9 | using Microsoft.Windows.Shell; 10 | 11 | public partial class SelectableChromeWindow 12 | { 13 | public SelectableChromeWindow() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | private void _OnStandardChromeClicked(object sender, RoutedEventArgs e) 19 | { 20 | this.Style = null; 21 | } 22 | 23 | private void _OnGradientChromeClicked(object sender, RoutedEventArgs e) 24 | { 25 | var style = (Style)Resources["GradientStyle"]; 26 | this.Style = style; 27 | } 28 | 29 | private void _OnGlassyChromeClicked(object sender, RoutedEventArgs e) 30 | { 31 | var style = (Style)Resources["GlassStyle"]; 32 | this.Style = style; 33 | } 34 | 35 | private void _OnSystemCommandCloseWindow(object sender, ExecutedRoutedEventArgs e) 36 | { 37 | SystemCommands.CloseWindow((Window)e.Parameter); 38 | } 39 | 40 | private void OnSystemCommandShowSystemMenu(object sender, ExecutedRoutedEventArgs e) 41 | { 42 | SystemCommands.ShowSystemMenu((Window)e.Parameter, this.PointToScreen(Mouse.GetPosition(this))); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /WindowChromeSample/WindowChromeSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {7E654166-1387-43D9-956C-6B473C514545} 9 | WinExe 10 | Properties 11 | WindowChromeSample 12 | WindowChromeSample 13 | v4.0 14 | 512 15 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 4 17 | 3.5 18 | false 19 | Client 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | AllRules.ruleset 30 | false 31 | 32 | 33 | pdbonly 34 | true 35 | bin\Release\ 36 | TRACE 37 | prompt 38 | 4 39 | AllRules.ruleset 40 | 41 | 42 | app.ico 43 | 44 | 45 | 46 | 47 | 48 | 3.0 49 | 50 | 51 | 3.0 52 | 53 | 54 | 3.0 55 | 56 | 57 | 58 | 59 | MSBuild:Compile 60 | Designer 61 | MSBuild:Compile 62 | Designer 63 | 64 | 65 | 66 | SelectableChromeWindow.xaml 67 | 68 | 69 | Designer 70 | MSBuild:Compile 71 | 72 | 73 | 74 | 75 | Code 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | {55D5297C-F1DF-4B76-A3C1-D82CC294EEBB} 86 | Microsoft.Windows.Shell.v4 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /WindowChromeSample/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WindowChromeSample/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joecastro/wpf-shell/72ef4e6fd05d4eea839a195e297bd860f90c70ca/WindowChromeSample/app.ico -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | #Microsoft Public License (Ms-PL) 2 | 3 | Copyright (c) 2015 Joe Castro 4 | 5 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 6 | 7 | ##1. Definitions 8 | 9 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. 10 | 11 | A "contribution" is the original software, or any additions or changes to the software. 12 | 13 | A "contributor" is any person that distributes its contribution under this license. 14 | 15 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 16 | 17 | ##2. Grant of Rights 18 | 19 | * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 20 | 21 | * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 22 | 23 | ##3. Conditions and Limitations 24 | 25 | * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 26 | 27 | * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 28 | 29 | * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 30 | 31 | * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 32 | 33 | * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 34 | --------------------------------------------------------------------------------