├── .gitattributes ├── .gitignore ├── CommonLibrary ├── CommonLibrary.csproj ├── Controls │ ├── GifRenderer │ │ ├── GifFileHandler.cs │ │ ├── GifPropertiesHelper.cs │ │ ├── GifRenderer.cs │ │ ├── InactiveGifManager.cs │ │ ├── ScaleSettings.cs │ │ ├── Structs │ │ │ ├── FrameProperties.cs │ │ │ └── ImageProperties.cs │ │ └── Themes │ │ │ └── GifRendererTheme.xaml │ └── ImageControl │ │ ├── ImageCrop │ │ ├── AspectRatio.cs │ │ ├── BitmapHelper.cs │ │ ├── Converter.cs │ │ ├── Crop │ │ │ ├── CropImageControl.cs │ │ │ └── CropImageSourceChangedEventHandler.cs │ │ ├── CropSelection.cs │ │ ├── CropSelectionSize.cs │ │ ├── FrameworkElementExtensions.cs │ │ ├── ImageTool.cs │ │ └── PlatformIndependent.cs │ │ └── Themes │ │ ├── CropImageControl.xaml │ │ └── ImageTool.xaml ├── DeviceInfoHelper.cs ├── DownloadHelper.cs ├── FileHelper.cs ├── ImageHelper.cs ├── ImageProcessing.cs ├── LocalCacheManager.cs ├── Properties │ ├── AssemblyInfo.cs │ └── CommonLibrary.rd.xml ├── SecurityHelper.cs ├── StorageHelper.cs ├── StorageManager.cs ├── StorageManagerEx.cs ├── Themes │ └── Generic.xaml ├── project.json └── project.lock.json ├── README.md ├── UWPToolkit.sln ├── UWPToolkit ├── App.xaml ├── App.xaml.cs ├── ApplicationInsights.config ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── Controls │ ├── BasePage.cs │ ├── PictureCropControl.xaml │ ├── PictureCropControl.xaml.cs │ ├── PictureEditor.xaml │ ├── PictureEditor.xaml.cs │ ├── PreviewPictureControl.xaml │ └── PreviewPictureControl.xaml.cs ├── MasterPage.xaml ├── MasterPage.xaml.cs ├── Package.appxmanifest ├── Pages │ ├── PictureEditorPage.xaml │ ├── PictureEditorPage.xaml.cs │ ├── PreviewPicturePage.xaml │ └── PreviewPicturePage.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── Styles │ └── Dictionary.xaml ├── UWPToolkit.csproj ├── UWPToolkit_TemporaryKey.pfx ├── project.json └── project.lock.json └── lib └── InkToolbarControl ├── ARM ├── debug │ ├── Microsoft.Labs.InkToolbarControl.dll │ ├── Microsoft.Labs.InkToolbarControl.pri │ └── Microsoft.Labs.InkToolbarControl.winmd └── release │ ├── Microsoft.Labs.InkToolbarControl.dll │ ├── Microsoft.Labs.InkToolbarControl.pri │ └── Microsoft.Labs.InkToolbarControl.winmd └── x86 ├── debug ├── Microsoft.Labs.InkToolbarControl.dll ├── Microsoft.Labs.InkToolbarControl.pri └── Microsoft.Labs.InkToolbarControl.winmd └── release ├── Microsoft.Labs.InkToolbarControl.dll ├── Microsoft.Labs.InkToolbarControl.pri └── Microsoft.Labs.InkToolbarControl.winmd /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /CommonLibrary/CommonLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D} 8 | Library 9 | Properties 10 | CommonLibrary 11 | CommonLibrary 12 | zh-CN 13 | UAP 14 | 10.0.10586.0 15 | 10.0.10240.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | prompt 37 | 4 38 | 39 | 40 | x86 41 | true 42 | bin\x86\Debug\ 43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 44 | ;2008 45 | full 46 | x86 47 | false 48 | prompt 49 | 50 | 51 | x86 52 | bin\x86\Release\ 53 | TRACE;NETFX_CORE;WINDOWS_UWP 54 | true 55 | ;2008 56 | pdbonly 57 | x86 58 | false 59 | prompt 60 | 61 | 62 | ARM 63 | true 64 | bin\ARM\Debug\ 65 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 66 | ;2008 67 | full 68 | ARM 69 | false 70 | prompt 71 | 72 | 73 | ARM 74 | bin\ARM\Release\ 75 | TRACE;NETFX_CORE;WINDOWS_UWP 76 | true 77 | ;2008 78 | pdbonly 79 | ARM 80 | false 81 | prompt 82 | 83 | 84 | x64 85 | true 86 | bin\x64\Debug\ 87 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 88 | ;2008 89 | full 90 | x64 91 | false 92 | prompt 93 | 94 | 95 | x64 96 | bin\x64\Release\ 97 | TRACE;NETFX_CORE;WINDOWS_UWP 98 | true 99 | ;2008 100 | pdbonly 101 | x64 102 | false 103 | prompt 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | MSBuild:Compile 136 | Designer 137 | 138 | 139 | MSBuild:Compile 140 | Designer 141 | 142 | 143 | Designer 144 | MSBuild:Compile 145 | PreserveNewest 146 | 147 | 148 | 149 | 150 | Windows Desktop Extensions for the UWP 151 | 152 | 153 | Windows Mobile Extensions for the UWP 154 | 155 | 156 | 157 | 14.0 158 | 159 | 160 | 167 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/GifFileHandler.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary.Cache; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using Windows.Storage; 8 | using System.Runtime.Serialization.Json; 9 | 10 | namespace CommonLibrary 11 | { 12 | public class GifFileHandler 13 | { 14 | public async Task GetCacheOrDownloadAsStorageFileFromUri(Uri source) 15 | { 16 | StorageFile file = null; 17 | 18 | try 19 | { 20 | string filename = string.Concat(source.Segments).Replace("/", ""); 21 | //TODO: Improve and compare by URL rather than just relying on filename 22 | 23 | if (source.AbsoluteUri.Contains("http")) 24 | { 25 | //caches the file, never replaces it. Consider adding expirydate 26 | if (await StorageHelper.FileExistsAsync(filename) == false) 27 | { 28 | file = await DownloadFileToStorageAsync(filename, source, file); 29 | } 30 | else 31 | { 32 | file = await StorageHelper.TryGetFileAsync(filename);//.GetIfFileExistsAsync(filename, ApplicationData.Current.LocalFolder); 33 | } 34 | } 35 | else 36 | { 37 | file = await StorageHelper.TryGetFileFromApplicationUriAsync(source);//.GetFileFromApplicationUriAsync(source); 38 | } 39 | 40 | } 41 | catch (Exception) 42 | { 43 | } 44 | 45 | return file; 46 | } 47 | 48 | public async Task DownloadFileToStorageAsync(string filename, Uri source, StorageFile outputFile) 49 | { 50 | using (HttpClient client = new HttpClient()) 51 | { 52 | byte[] buffer = await client.GetByteArrayAsync(source); // Download file 53 | filename = filename != "/" ? filename : Guid.NewGuid().ToString(); 54 | outputFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting); 55 | 56 | // TODO: Autodelete guids after eg. 2 weeks 57 | using (Stream stream = await outputFile.OpenStreamForWriteAsync()) 58 | { 59 | stream.Write(buffer, 0, buffer.Length); 60 | } 61 | } 62 | 63 | return outputFile; 64 | } 65 | 66 | internal async Task RemoveFileFromStorage(Uri source) 67 | { 68 | try 69 | { 70 | string filename = string.Empty; 71 | filename = source.Segments.Last().Contains("giphy") ? string.Concat(source.Segments).Replace("/", "") : source.Segments.Last(); 72 | var file = await StorageHelper.TryGetFileAsync(filename); 73 | if (file != null) 74 | { 75 | await file.DeleteAsync(); 76 | } 77 | return !(await StorageHelper.FileExistsAsync(file.Path)); 78 | 79 | } 80 | catch (Exception) 81 | { 82 | return false; 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/GifPropertiesHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | using Windows.Foundation; 5 | using Windows.Graphics.Imaging; 6 | 7 | namespace CommonLibrary 8 | { 9 | public class GifPropertiesHelper 10 | { 11 | /// 12 | /// Retrieve frame specific properties. Each frame has an individual delay before the next, as well as top & left from where the first change appears in the bytes. 13 | /// 14 | public async Task RetrieveFramePropertiesAsync(BitmapFrame frame, int index) 15 | { 16 | const string leftProperty = "/imgdesc/Left"; 17 | const string topProperty = "/imgdesc/Top"; 18 | const string widthProperty = "/imgdesc/Width"; 19 | const string heightProperty = "/imgdesc/Height"; 20 | const string delayProperty = "/grctlext/Delay"; 21 | const string disposalProperty = "/grctlext/Disposal"; 22 | 23 | var propertiesView = frame.BitmapProperties; 24 | var requiredProperties = new[] { leftProperty, topProperty, widthProperty, heightProperty }; 25 | var properties = await propertiesView.GetPropertiesAsync(requiredProperties); 26 | 27 | var left = (ushort)properties[leftProperty].Value; 28 | var top = (ushort)properties[topProperty].Value; 29 | var width = (ushort)properties[widthProperty].Value; 30 | var height = (ushort)properties[heightProperty].Value; 31 | 32 | var delayMilliseconds = 30.0; 33 | var shouldDispose = false; 34 | 35 | try 36 | { 37 | var extensionProperties = new[] { delayProperty, disposalProperty }; 38 | properties = await propertiesView.GetPropertiesAsync(extensionProperties); 39 | 40 | if (properties.ContainsKey(delayProperty) && properties[delayProperty].Type == PropertyType.UInt16) 41 | { 42 | var delayInHundredths = (ushort)properties[delayProperty].Value; 43 | if (delayInHundredths >= 3u) // Prevent degenerate frames with no delay time 44 | { 45 | delayMilliseconds = 10.0 * delayInHundredths; 46 | } 47 | } 48 | 49 | if (properties.ContainsKey(disposalProperty) && properties[disposalProperty].Type == PropertyType.UInt8) 50 | { 51 | var disposal = (byte)properties[disposalProperty].Value; 52 | if (disposal == 2) 53 | { 54 | shouldDispose = true; 55 | } 56 | } 57 | } 58 | catch 59 | { 60 | } 61 | 62 | return new FrameProperties( 63 | new Rect(left, top, width, height), 64 | delayMilliseconds, 65 | shouldDispose, 66 | index); 67 | } 68 | 69 | /// 70 | /// The entire gif image has properties such as width and height thats required and has to be used in calculating bytes. BitmapDecoder comes with width and height, but those are inaccurate compared to these properties. 71 | /// 72 | public async Task RetrieveImagePropertiesAsync(BitmapDecoder bitmapDecoder) 73 | { 74 | // Properties not currently supported: background color, pixel aspect ratio. 75 | const string widthProperty = "/logscrdesc/Width"; 76 | const string heightProperty = "/logscrdesc/Height"; 77 | const string applicationProperty = "/appext/application"; 78 | const string dataProperty = "/appext/data"; 79 | 80 | var propertiesView = bitmapDecoder.BitmapContainerProperties; 81 | var requiredProperties = new[] { widthProperty, heightProperty }; 82 | var properties = await propertiesView.GetPropertiesAsync(requiredProperties); 83 | 84 | var pixelWidth = (ushort)properties[widthProperty].Value; 85 | var pixelHeight = (ushort)properties[heightProperty].Value; 86 | 87 | var loopCount = 0; 88 | var isAnimated = true; 89 | 90 | try 91 | { 92 | var extensionProperties = new[] { applicationProperty, dataProperty }; 93 | properties = await propertiesView.GetPropertiesAsync(extensionProperties); 94 | 95 | if (properties.ContainsKey(applicationProperty) && 96 | properties[applicationProperty].Type == PropertyType.UInt8Array) 97 | { 98 | var bytes = (byte[])properties[applicationProperty].Value; 99 | var applicationName = Encoding.UTF8.GetString(bytes, 0, bytes.Length); 100 | 101 | if (applicationName == "NETSCAPE2.0" || applicationName == "ANIMEXTS1.0") 102 | { 103 | if (properties.ContainsKey(dataProperty) && properties[dataProperty].Type == PropertyType.UInt8Array) 104 | { 105 | var data = (byte[])properties[dataProperty].Value; 106 | loopCount = data[2] | data[3] << 8; 107 | isAnimated = data[1] == 1; 108 | } 109 | } 110 | } 111 | } 112 | catch 113 | { 114 | } 115 | 116 | return new ImageProperties(pixelWidth, pixelHeight, isAnimated, loopCount); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/InactiveGifManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace CommonLibrary 5 | { 6 | public static class InactiveGifManager 7 | { 8 | private static int _inactiveCheckDelayInMiliseconds = 200; 9 | private static List _inactiveRenderers; 10 | private static List _inactiveRenderersCleanup; 11 | private static bool _isInactiveRunning; 12 | 13 | public static void Add(GifRenderer renderer) 14 | { 15 | if (_inactiveRenderers == null) 16 | { 17 | _inactiveRenderers = new List(); 18 | _inactiveRenderersCleanup = new List(); 19 | } 20 | 21 | _inactiveRenderers.Add(renderer); 22 | 23 | if (!_isInactiveRunning) 24 | { 25 | Start(); 26 | } 27 | } 28 | 29 | public static void Remove(GifRenderer renderer) 30 | { 31 | _inactiveRenderers.Remove(renderer); 32 | } 33 | 34 | private static async void Start() 35 | { 36 | _isInactiveRunning = true; 37 | 38 | while (_isInactiveRunning) 39 | { 40 | CheckForInactivesBackOnScreen(); 41 | await Task.Delay(_inactiveCheckDelayInMiliseconds); 42 | } 43 | } 44 | 45 | private static void CheckForInactivesBackOnScreen() 46 | { 47 | var copy = _inactiveRenderers.ToArray(); 48 | foreach (var item in copy) 49 | { 50 | if (!item.IsOffScreen()) 51 | { 52 | item.Restart(); 53 | _inactiveRenderersCleanup.Add(item); 54 | } 55 | } 56 | 57 | foreach (var item in _inactiveRenderersCleanup) 58 | { 59 | Remove(item); 60 | } 61 | 62 | _inactiveRenderersCleanup.Clear(); 63 | 64 | if (_inactiveRenderers.Count == 0) 65 | { 66 | Stop(); 67 | } 68 | } 69 | 70 | private static void Stop() 71 | { 72 | _isInactiveRunning = false; 73 | } 74 | 75 | internal static void Clear() 76 | { 77 | Stop(); 78 | if (_inactiveRenderers != null) 79 | _inactiveRenderers.Clear(); 80 | 81 | if (_inactiveRenderersCleanup != null) 82 | _inactiveRenderersCleanup.Clear(); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/ScaleSettings.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLibrary 2 | { 3 | public enum ScaleSettings 4 | { 5 | None, Scale, Fill 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/Structs/FrameProperties.cs: -------------------------------------------------------------------------------- 1 | using Windows.Foundation; 2 | 3 | namespace CommonLibrary 4 | { 5 | public struct FrameProperties 6 | { 7 | public readonly Rect Rect; 8 | public readonly double DelayMilliseconds; 9 | public readonly bool ShouldDispose; 10 | public readonly int Index; 11 | 12 | public FrameProperties(Rect rect, double delayMilliseconds, bool shouldDispose, int index) 13 | { 14 | Index = index; 15 | Rect = rect; 16 | DelayMilliseconds = delayMilliseconds; 17 | ShouldDispose = shouldDispose; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/Structs/ImageProperties.cs: -------------------------------------------------------------------------------- 1 | namespace CommonLibrary 2 | { 3 | public struct ImageProperties 4 | { 5 | public readonly int PixelWidth; 6 | public readonly int PixelHeight; 7 | public readonly bool IsAnimated; 8 | public readonly int LoopCount; 9 | 10 | public ImageProperties(int pixelWidth, int pixelHeight, bool isAnimated, int loopCount) 11 | { 12 | PixelWidth = pixelWidth; 13 | PixelHeight = pixelHeight; 14 | IsAnimated = isAnimated; 15 | LoopCount = loopCount; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/GifRenderer/Themes/GifRendererTheme.xaml: -------------------------------------------------------------------------------- 1 |  5 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/AspectRatio.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CommonLibrary 8 | { 9 | public enum AspectRatio 10 | { 11 | Custom, 12 | Square 13 | //4X3 14 | // 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace CommonLibrary 10 | { 11 | /// 12 | /// Value converter that translates true to and false to 13 | /// . 14 | /// 15 | public sealed class VisibilityConverter : IValueConverter 16 | { 17 | /// 18 | /// If true - converts from Visibility to Boolean. 19 | /// 20 | public bool IsReversed { get; set; } 21 | 22 | /// 23 | /// If true - converts true to Collapsed and false to Visible. 24 | /// 25 | public bool IsInversed { get; set; } 26 | 27 | /// 28 | /// Modifies the source data before passing it to the target for display in the UI. 29 | /// 30 | /// The source data being passed to the target. 31 | /// The type of the target property, specified by a helper structure that wraps the type name. 32 | /// An optional parameter to be used in the converter logic. 33 | /// The language of the conversion. 34 | /// The value to be passed to the target dependency property. 35 | public object Convert(object value, Type targetType, object parameter, string language) 36 | { 37 | if (IsReversed) 38 | { 39 | return (value is Visibility && (Visibility)value == Visibility.Visible) ^ IsInversed; 40 | } 41 | 42 | return (value is bool && (bool)value) ^ IsInversed ? Visibility.Visible : Visibility.Collapsed; 43 | } 44 | 45 | /// 46 | /// Modifies the target data before passing it to the source object. This method is called only in TwoWay bindings. 47 | /// 48 | /// The target data being passed to the source.. 49 | /// The type of the target property, specified by a helper structure that wraps the type name. 50 | /// An optional parameter to be used in the converter logic. 51 | /// The language of the conversion. 52 | /// The value to be passed to the source object. 53 | public object ConvertBack(object value, Type targetType, object parameter, string language) 54 | { 55 | if (IsReversed) 56 | { 57 | return (value is bool && (bool)value) ^ IsInversed ? Visibility.Visible : Visibility.Collapsed; 58 | } 59 | 60 | return (value is Visibility && (Visibility)value == Visibility.Visible) ^ IsInversed; 61 | } 62 | } 63 | 64 | 65 | /// 66 | /// Get the middle of two number 67 | /// 4 and 6 is 5 68 | /// 69 | public sealed class CropImageControlLineCoordinateConverter : DependencyObject, IValueConverter 70 | { 71 | 72 | 73 | public double No1 74 | { 75 | get { return (double)GetValue(No1Property); } 76 | set { SetValue(No1Property, value); } 77 | } 78 | 79 | // Using a DependencyProperty as the backing store for No1. This enables animation, styling, binding, etc... 80 | public static readonly DependencyProperty No1Property = 81 | DependencyProperty.Register("No1", typeof(double), typeof(CropImageControlLineCoordinateConverter), new PropertyMetadata(0.0)); 82 | 83 | 84 | 85 | public double No2 86 | { 87 | get { return (double)GetValue(No2Property); } 88 | set { SetValue(No2Property, value); } 89 | } 90 | 91 | // Using a DependencyProperty as the backing store for No2. This enables animation, styling, binding, etc... 92 | public static readonly DependencyProperty No2Property = 93 | DependencyProperty.Register("No2", typeof(double), typeof(CropImageControlLineCoordinateConverter), new PropertyMetadata(0.0)); 94 | 95 | 96 | 97 | 98 | public object Convert(object value, Type targetType, object parameter, string language) 99 | { 100 | if (value==null || parameter==null) 101 | { 102 | return 0.0; 103 | } 104 | double no1 = (double)value; 105 | double no2 = double.Parse(parameter.ToString()); 106 | return (no2+ no1)/2; 107 | 108 | } 109 | 110 | public object ConvertBack(object value, Type targetType, object parameter, string language) 111 | { 112 | throw new NotImplementedException(); 113 | } 114 | } 115 | 116 | 117 | public sealed class DateTimeConverter : IValueConverter 118 | { 119 | public object Convert(object value, Type targetType, object parameter, string language) 120 | { 121 | var datetime = (DateTime)value; 122 | var format = (string)parameter; 123 | if (datetime!=null) 124 | { 125 | return datetime.ToString(format); 126 | } 127 | return ""; 128 | } 129 | 130 | public object ConvertBack(object value, Type targetType, object parameter, string language) 131 | { 132 | throw new NotImplementedException(); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/Crop/CropImageSourceChangedEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.UI.Xaml.Media; 3 | 4 | namespace CommonLibrary 5 | { 6 | 7 | 8 | public delegate void CropImageSourceChangedEventHandler(object sender, CropImageSourceChangedEventArgs e); 9 | 10 | public class CropImageSourceChangedEventArgs:EventArgs 11 | { 12 | public ImageSource CropImageSource { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/CropSelection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.Foundation; 8 | using Windows.UI.Xaml; 9 | 10 | namespace CommonLibrary 11 | { 12 | public class CropSelection : INotifyPropertyChanged 13 | { 14 | 15 | #region Property 16 | 17 | /// 18 | /// The minimun size of the seleced region 19 | /// 20 | public double MinSelectRegionSize { get; set; } 21 | 22 | public AspectRatio CropAspectRatio { get; set; } 23 | 24 | private Rect outerRect; 25 | 26 | /// 27 | /// The outer rect. The non-selected region can be represented by the 28 | /// OuterRect and the SelectedRect. 29 | /// 30 | public Rect OuterRect 31 | { 32 | get { return outerRect; } 33 | set 34 | { 35 | if (outerRect != value) 36 | { 37 | outerRect = value; 38 | 39 | this.OnPropertyChanged("OuterRect"); 40 | } 41 | } 42 | } 43 | 44 | private Rect selectedRect; 45 | 46 | /// 47 | /// The selected region, which is represented by the four Thumbs. 48 | /// 49 | public Rect SelectedRect 50 | { 51 | get { return selectedRect; } 52 | set 53 | { 54 | if (selectedRect != value) 55 | { 56 | selectedRect = value; 57 | HorizontalLine1 = new Rect(selectedRect.Left, selectedRect.Top + selectedRect.Height / 3, selectedRect.Width, 0.5); 58 | HorizontalLine2 = new Rect(selectedRect.Left, selectedRect.Top + selectedRect.Height / 3 * 2, selectedRect.Width, 0.5); 59 | VerticalLine1 = new Rect(selectedRect.Left + selectedRect.Width / 3, selectedRect.Top, 0.5, selectedRect.Height); 60 | VerticalLine2 = new Rect(selectedRect.Left + selectedRect.Width / 3 * 2, selectedRect.Top, 0.5, selectedRect.Height); 61 | 62 | //HorizontalLine1StartPoint = new Point(selectedRect.Left, selectedRect.Top + selectedRect.Height / 3); 63 | //HorizontalLine1EndPoint = new Point(selectedRect.Left + selectedRect.Width, selectedRect.Top + selectedRect.Height / 3); 64 | 65 | //HorizontalLine2StartPoint = new Point(selectedRect.Left, selectedRect.Top + selectedRect.Height / 3 * 2); 66 | //HorizontalLine2EndPoint = new Point(selectedRect.Left + selectedRect.Width, selectedRect.Top + selectedRect.Height / 3 * 2); 67 | 68 | //VerticalLine1StartPoint = new Point(selectedRect.Left + selectedRect.Width / 3, selectedRect.Top); 69 | //VerticalLine1EndPoint = new Point(selectedRect.Left + selectedRect.Width / 3, selectedRect.Top + selectedRect.Height); 70 | 71 | //VerticalLine2StartPoint = new Point(selectedRect.Left + selectedRect.Width / 3 * 2, selectedRect.Top); 72 | //VerticalLine2EndPoint = new Point(selectedRect.Left + selectedRect.Width / 3 * 2, selectedRect.Top + selectedRect.Height); 73 | 74 | this.OnPropertyChanged("SelectedRect"); 75 | //OnPropertyChanged("HorizontalLineCanvasTop"); 76 | //OnPropertyChanged("VerticalLineCanvasLeft"); 77 | //OnPropertyChanged("HorizontalLine1CanvasTop"); 78 | //OnPropertyChanged("VerticalLine1CanvasLeft"); 79 | } 80 | } 81 | } 82 | 83 | private Rect horizontalLine1; 84 | public Rect HorizontalLine1 85 | { 86 | get { return horizontalLine1; } 87 | set 88 | { 89 | if (horizontalLine1 != value) 90 | { 91 | horizontalLine1 = value; 92 | 93 | OnPropertyChanged("HorizontalLine1"); 94 | } 95 | } 96 | } 97 | 98 | private Rect horizontalLine2; 99 | public Rect HorizontalLine2 100 | { 101 | get { return horizontalLine2; } 102 | set 103 | { 104 | if (horizontalLine2 != value) 105 | { 106 | horizontalLine2 = value; 107 | 108 | OnPropertyChanged("HorizontalLine2"); 109 | } 110 | } 111 | } 112 | 113 | private Rect verticalLine1; 114 | public Rect VerticalLine1 115 | { 116 | get { return verticalLine1; } 117 | set 118 | { 119 | if (verticalLine1 != value) 120 | { 121 | verticalLine1 = value; 122 | 123 | OnPropertyChanged("VerticalLine1"); 124 | } 125 | } 126 | } 127 | 128 | private Rect verticalLine2; 129 | public Rect VerticalLine2 130 | { 131 | get { return verticalLine2; } 132 | set 133 | { 134 | if (verticalLine2 != value) 135 | { 136 | verticalLine2 = value; 137 | 138 | OnPropertyChanged("VerticalLine2"); 139 | } 140 | } 141 | } 142 | 143 | //private Point horizontalLine1StartPoint; 144 | //public Point HorizontalLine1StartPoint 145 | //{ 146 | // get { return horizontalLine1StartPoint; } 147 | // set 148 | // { 149 | // if (horizontalLine1StartPoint != value) 150 | // { 151 | // horizontalLine1StartPoint = value; 152 | 153 | // OnPropertyChanged("HorizontalLine1StartPoint"); 154 | // } 155 | // } 156 | //} 157 | 158 | //private Point horizontalLine1EndPoint; 159 | //public Point HorizontalLine1EndPoint 160 | //{ 161 | // get { return horizontalLine1EndPoint; } 162 | // set 163 | // { 164 | // if (horizontalLine1EndPoint != value) 165 | // { 166 | // horizontalLine1EndPoint = value; 167 | 168 | // OnPropertyChanged("HorizontalLine1EndPoint"); 169 | // } 170 | // } 171 | //} 172 | 173 | //private Point horizontalLine2StartPoint; 174 | //public Point HorizontalLine2StartPoint 175 | //{ 176 | // get { return horizontalLine2StartPoint; } 177 | // set 178 | // { 179 | // if (horizontalLine2StartPoint != value) 180 | // { 181 | // horizontalLine2StartPoint = value; 182 | 183 | // OnPropertyChanged("HorizontalLine2StartPoint"); 184 | // } 185 | // } 186 | //} 187 | 188 | //private Point horizontalLine2EndPoint; 189 | //public Point HorizontalLine2EndPoint 190 | //{ 191 | // get { return horizontalLine2EndPoint; } 192 | // set 193 | // { 194 | // if (horizontalLine2EndPoint != value) 195 | // { 196 | // horizontalLine2EndPoint = value; 197 | 198 | // OnPropertyChanged("HorizontalLine2EndPoint"); 199 | // } 200 | // } 201 | //} 202 | 203 | //private Point verticalLine1StartPoint; 204 | //public Point VerticalLine1StartPoint 205 | //{ 206 | // get { return verticalLine1StartPoint; } 207 | // set 208 | // { 209 | // if (verticalLine1StartPoint != value) 210 | // { 211 | // verticalLine1StartPoint = value; 212 | 213 | // OnPropertyChanged("VerticalLine1StartPoint"); 214 | // } 215 | // } 216 | //} 217 | 218 | //private Point verticalLine1EndPoint; 219 | //public Point VerticalLine1EndPoint 220 | //{ 221 | // get { return verticalLine1EndPoint; } 222 | // set 223 | // { 224 | // if (verticalLine1EndPoint != value) 225 | // { 226 | // verticalLine1EndPoint = value; 227 | 228 | // OnPropertyChanged("VerticalLine1EndPoint"); 229 | // } 230 | // } 231 | //} 232 | 233 | //private Point verticalLine2StartPoint; 234 | //public Point VerticalLine2StartPoint 235 | //{ 236 | // get { return verticalLine2StartPoint; } 237 | // set 238 | // { 239 | // if (verticalLine2StartPoint != value) 240 | // { 241 | // verticalLine2StartPoint = value; 242 | 243 | // OnPropertyChanged("VerticalLine2StartPoint"); 244 | // } 245 | // } 246 | //} 247 | 248 | //private Point verticalLine2EndPoint; 249 | //public Point VerticalLine2EndPoint 250 | //{ 251 | // get { return verticalLine2EndPoint; } 252 | // set 253 | // { 254 | // if (verticalLine2EndPoint != value) 255 | // { 256 | // verticalLine2EndPoint = value; 257 | 258 | // OnPropertyChanged("VerticalLine2EndPoint"); 259 | // } 260 | // } 261 | //} 262 | 263 | public double HorizontalLineCanvasTop 264 | { 265 | get 266 | { 267 | return (SelectedRect.Bottom - SelectedRect.Top) / 3 * 1 + SelectedRect.Top; 268 | } 269 | 270 | } 271 | public double HorizontalLine1CanvasTop 272 | { 273 | get 274 | { 275 | return (SelectedRect.Bottom - SelectedRect.Top) / 3 * 2 + SelectedRect.Top; 276 | } 277 | 278 | } 279 | 280 | public double VerticalLineCanvasLeft 281 | { 282 | get 283 | { 284 | return (SelectedRect.Right - SelectedRect.Left) / 3 * 1 + SelectedRect.Left; 285 | } 286 | } 287 | 288 | public double VerticalLine1CanvasLeft 289 | { 290 | get 291 | { 292 | return (SelectedRect.Right - SelectedRect.Left) / 3 * 2 + SelectedRect.Left; 293 | } 294 | } 295 | 296 | 297 | private Visibility _cropSelectionVisibility=Visibility.Collapsed; 298 | 299 | public Visibility CropSelectionVisibility 300 | { 301 | get { return _cropSelectionVisibility; } 302 | set 303 | { 304 | _cropSelectionVisibility = value; 305 | this.OnPropertyChanged("CropSelectionVisibility"); 306 | } 307 | } 308 | 309 | 310 | #endregion 311 | 312 | #region INotifyPropertyChanged 313 | public event PropertyChangedEventHandler PropertyChanged; 314 | 315 | void OnPropertyChanged(string propertyName) 316 | { 317 | if (PropertyChanged != null) 318 | { 319 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 320 | } 321 | } 322 | 323 | 324 | #endregion 325 | 326 | #region Method 327 | internal void UpdateSelectedRect(float scale, double x, double y) 328 | { 329 | var rect = new Rect() { X = SelectedRect.X + x, Y = SelectedRect.Y + y, Width = SelectedRect.Width * scale, Height = SelectedRect.Height * scale }; 330 | var leftTop = new Point(rect.Left, rect.Top); 331 | var leftBottom = new Point(rect.Left, rect.Bottom); 332 | var rightTop = new Point(rect.Right, rect.Top); 333 | var rightBottom = new Point(rect.Right, rect.Bottom); 334 | 335 | if (OuterRect.Contains(leftTop) 336 | && OuterRect.Contains(leftBottom) 337 | && OuterRect.Contains(rightTop) 338 | && OuterRect.Contains(rightBottom) 339 | && rect.Width >= 2 * MinSelectRegionSize 340 | && rect.Height >= 2 * MinSelectRegionSize) 341 | { 342 | SelectedRect = rect; 343 | } 344 | 345 | } 346 | 347 | internal void UpdateSelectedRect(string ThumbName, double xUpdate, double yUpdate,Rect? outerRect=null) 348 | { 349 | 350 | 351 | var left = SelectedRect.Left; 352 | var top = SelectedRect.Top; 353 | 354 | var right = SelectedRect.Right; 355 | var bottom = SelectedRect.Bottom; 356 | 357 | 358 | if (ThumbName == "topLeftThumb") 359 | { 360 | left += xUpdate; 361 | top += yUpdate; 362 | } 363 | else if (ThumbName == "topRightThumb") 364 | { 365 | right += xUpdate; 366 | top += yUpdate; 367 | } 368 | else if (ThumbName == "bottomLeftThumb") 369 | { 370 | left += xUpdate; 371 | bottom += yUpdate; 372 | } 373 | else if (ThumbName == "bottomRightThumb") 374 | { 375 | right += xUpdate; 376 | bottom += yUpdate; 377 | } 378 | 379 | var rect = new Rect(new Point(left, top), new Point(right, bottom)); 380 | var leftTop = new Point(rect.Left, rect.Top); 381 | var leftBottom = new Point(rect.Left, rect.Bottom); 382 | var rightTop = new Point(rect.Right, rect.Top); 383 | var rightBottom = new Point(rect.Right, rect.Bottom); 384 | 385 | var outerRect1 = outerRect!=null ? outerRect.Value: OuterRect; 386 | 387 | if (outerRect1.Contains(leftTop) 388 | && outerRect1.Contains(leftBottom) 389 | && outerRect1.Contains(rightTop) 390 | && outerRect1.Contains(rightBottom) 391 | && rect.Width >= 2 * MinSelectRegionSize 392 | && rect.Height >= 2 * MinSelectRegionSize) 393 | { 394 | SelectedRect = rect; 395 | } 396 | } 397 | 398 | 399 | internal void ResizeSelectedRect(double scale) 400 | { 401 | var rect = new Rect() { X = SelectedRect.X * scale, Y = SelectedRect.Y * scale, Width = SelectedRect.Width * scale, Height = SelectedRect.Height * scale }; 402 | var leftTop = new Point(rect.Left, rect.Top); 403 | var leftBottom = new Point(rect.Left, rect.Bottom); 404 | var rightTop = new Point(rect.Right, rect.Top); 405 | var rightBottom = new Point(rect.Right, rect.Bottom); 406 | 407 | if (OuterRect.Contains(leftTop) 408 | && OuterRect.Contains(leftBottom) 409 | && OuterRect.Contains(rightTop) 410 | && OuterRect.Contains(rightBottom) 411 | && rect.Width >= 2 * MinSelectRegionSize 412 | && rect.Height >= 2 * MinSelectRegionSize) 413 | { 414 | SelectedRect = rect; 415 | } 416 | } 417 | #endregion 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/CropSelectionSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CommonLibrary 8 | { 9 | public enum CropSelectionSize 10 | { 11 | Full=1, 12 | Half=2, 13 | OneFourth=4 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/FrameworkElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Foundation; 7 | using Windows.UI.Xaml; 8 | using Windows.UI.Xaml.Controls; 9 | using Windows.UI.Xaml.Media; 10 | 11 | namespace CommonLibrary.Util 12 | { 13 | public static class FrameworkElementExtensions 14 | { 15 | public static FrameworkElement FindDescendantByName(this FrameworkElement element, string name) 16 | { 17 | if (element == null || string.IsNullOrWhiteSpace(name)) { return null; } 18 | 19 | if (name.Equals(element.Name, StringComparison.OrdinalIgnoreCase)) 20 | { 21 | return element; 22 | } 23 | var childCount = VisualTreeHelper.GetChildrenCount(element); 24 | for (int i = 0; i < childCount; i++) 25 | { 26 | var result = (VisualTreeHelper.GetChild(element, i) as FrameworkElement).FindDescendantByName(name); 27 | if (result != null) { return result; } 28 | } 29 | return null; 30 | } 31 | 32 | 33 | public static IEnumerable GetVisibleItems(this ItemsControl itemsControl) 34 | { 35 | for (int i = 0; i < itemsControl.Items.Count; i++) 36 | { 37 | var obj = itemsControl.ContainerFromIndex(i) as FrameworkElement; 38 | if (obj != null) 39 | { 40 | GeneralTransform gt = obj.TransformToVisual(itemsControl); 41 | var rect = gt.TransformBounds(new Rect(0, 0, obj.ActualWidth, obj.ActualHeight)); 42 | 43 | if (rect.Bottom < 0 || rect.Top > itemsControl.ActualHeight) 44 | { 45 | continue; 46 | } 47 | 48 | yield return itemsControl.Items[i]; 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/ImageCrop/PlatformIndependent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls.Primitives; 8 | using Windows.UI.Xaml.Media; 9 | 10 | namespace CommonLibrary.Util 11 | { 12 | public static class PlatformIndependent 13 | { 14 | /// 15 | /// Indicates whether the running device is windows phone device. 16 | /// 17 | public static bool IsWindowsPhoneDevice 18 | { 19 | get 20 | { 21 | if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) 22 | { 23 | return true; 24 | } 25 | return false; 26 | } 27 | } 28 | 29 | /// 30 | /// [Platform safe] Determines whether the specified element is in visual tree. 31 | /// 32 | /// The framework element. 33 | /// 34 | /// true if the specified element is in visual tree; otherwise, false. 35 | /// 36 | public static bool IsInVisualTree(this FrameworkElement elem) 37 | { 38 | var current = elem; 39 | FrameworkElement temp = null; // <> take parent once 40 | while ((temp = (current.Parent ?? VisualTreeHelper.GetParent(current)) as FrameworkElement) != null) 41 | { 42 | if (Windows.UI.Xaml.Window.Current.Content == temp) 43 | { 44 | return true; 45 | } 46 | current = temp; 47 | } 48 | 49 | try 50 | { 51 | return current == Windows.UI.Xaml.Window.Current.Content || 52 | (current is Popup && ((Popup)current).IsOpen); 53 | } 54 | catch 55 | { 56 | return false; 57 | } 58 | 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CommonLibrary/Controls/ImageControl/Themes/CropImageControl.xaml: -------------------------------------------------------------------------------- 1 |  5 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 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 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 86 | 87 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /CommonLibrary/DownloadHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Windows.Networking.BackgroundTransfer; 8 | using Windows.Storage; 9 | using System.Diagnostics; 10 | using Windows.Web.Http; 11 | 12 | namespace CommonLibrary 13 | { 14 | public class DownloadHelper 15 | { 16 | private const string _tempFolderName = ""; 17 | private static object _lockObj = new object(); 18 | private static Dictionary> _downloadQueue = new Dictionary>(); 19 | 20 | private async static void ProgressChanged(DownloadOperation download) 21 | { 22 | try 23 | { 24 | if (download?.Progress.BytesReceived > 0) 25 | { 26 | var percent = download.Progress.BytesReceived * 100 / download.Progress.TotalBytesToReceive; 27 | //var res = download.GetResponseInformation(); 28 | //var ext = res.Headers["Content-Type"]; 29 | 30 | if (percent == 100) 31 | { 32 | await Task.Delay(50);//wait for current thread complete 33 | var url = download.RequestedUri?.OriginalString; 34 | 35 | if (_downloadQueue.ContainsKey(url)) 36 | { 37 | var dir = System.IO.Path.GetDirectoryName(download.ResultFile?.Path); 38 | var md5Name = GetDownloadedLocalFileName(url); 39 | var path = System.IO.Path.Combine(dir, md5Name); 40 | 41 | if (!StorageHelper.FileExists(path)) 42 | { 43 | await download.ResultFile.RenameAsync(md5Name, NameCollisionOption.ReplaceExisting); 44 | } 45 | 46 | lock (_lockObj) 47 | { 48 | _downloadQueue[url](path, url); 49 | } 50 | 51 | await Task.Delay(50);//wait for notice 52 | 53 | lock (_lockObj) 54 | { 55 | _downloadQueue.Remove(url); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | catch 62 | { 63 | } 64 | } 65 | 66 | private static HttpClient client = new HttpClient(); 67 | 68 | public static async void DownloadAsync(string url, StorageFolder folder, Action downloadCompleted, string subType = "") 69 | { 70 | if (string.IsNullOrEmpty(url) || folder == null) return; 71 | 72 | var md5Name = GetDownloadedLocalFileName(url, subType); 73 | 74 | var path = System.IO.Path.Combine(folder.Path, md5Name); 75 | var tempPath = _tempFolderName + md5Name; 76 | 77 | StorageFile downloadedFile = null; 78 | 79 | if (downloadCompleted != null) 80 | { 81 | if (StorageHelper.FileExists(path)) 82 | { 83 | downloadCompleted(path, url); 84 | 85 | return; 86 | } 87 | 88 | lock (_lockObj) 89 | { 90 | if (_downloadQueue.ContainsKey(url)) 91 | { 92 | _downloadQueue[url] += downloadCompleted; 93 | 94 | return; 95 | } 96 | else 97 | { 98 | _downloadQueue.Add(url, downloadCompleted); 99 | } 100 | } 101 | } 102 | 103 | try 104 | { 105 | #if USE_HTTP_FOR_DOWNLOADER 106 | 107 | var resp = await client.GetAsync(new Uri(url, UriKind.RelativeOrAbsolute)); 108 | 109 | //var type = resp.Content.Headers.ContentType.MediaType.Split(new char[] { '/' }); 110 | 111 | //var subType = type.Length == 2 ? type[1] : ""; 112 | 113 | var filename = GetDownloadedLocalFileName(url, subType); 114 | 115 | var file = await folder.TryCreateFileAsync(tempPath, CreationCollisionOption.ReplaceExisting); 116 | 117 | await FileIO.WriteBufferAsync(file, await resp.Content.ReadAsBufferAsync()); 118 | 119 | if (_downloadQueue.ContainsKey(url)) 120 | { 121 | _downloadQueue[url]?.Invoke(file.Path, url); 122 | 123 | lock (_lockObj) 124 | { 125 | _downloadQueue.Remove(url); 126 | } 127 | } 128 | 129 | #else 130 | 131 | var cts = new CancellationTokenSource(); 132 | 133 | var transferUri = new Uri(Uri.EscapeUriString(url), UriKind.RelativeOrAbsolute); 134 | 135 | downloadedFile = await folder.TryCreateFileAsync(tempPath, CreationCollisionOption.ReplaceExisting); 136 | 137 | var downloader = new BackgroundDownloader(); 138 | 139 | var downloadoperation = downloader.CreateDownload(transferUri, downloadedFile); 140 | 141 | await downloadoperation.StartAsync().AsTask(cts.Token, new Progress(ProgressChanged)); 142 | #endif 143 | } 144 | catch (Exception ex) 145 | { 146 | lock (_lockObj) 147 | { 148 | if (_downloadQueue.ContainsKey(url)) 149 | { 150 | _downloadQueue[url](downloadedFile?.Path, url); 151 | _downloadQueue.Remove(url); 152 | } 153 | } 154 | } 155 | } 156 | 157 | public static async Task CopyAsync(StorageFile file, StorageFolder folder) 158 | { 159 | return (await CopyFileAsync(file, folder))?.Path; 160 | } 161 | 162 | public static async Task CopyFileAsync(StorageFile file, StorageFolder folder) 163 | { 164 | if (file == null) return null; 165 | 166 | var fileCopy = await file.CopyAsync(folder, GetDownloadedLocalFileName(file.Path), NameCollisionOption.ReplaceExisting); 167 | 168 | return fileCopy; 169 | } 170 | 171 | public static async void CleanUpCurrentDownloadsAsync() 172 | { 173 | var downloaders = await BackgroundDownloader.GetCurrentDownloadsAsync(); 174 | foreach (var downloader in downloaders) 175 | { 176 | try 177 | { 178 | downloader.AttachAsync().Cancel(); 179 | } 180 | catch (Exception) 181 | { 182 | } 183 | } 184 | } 185 | 186 | public static string GetDownloadedLocalFileName(string url, string subType = "") 187 | { 188 | if (string.IsNullOrEmpty(url)) return ""; 189 | 190 | var ext = ""; 191 | 192 | if (string.IsNullOrEmpty(subType)) 193 | { 194 | ext = System.IO.Path.GetExtension(url); 195 | //if (!string.IsNullOrEmpty(ext)) 196 | //{ 197 | // ext = ext.Replace("?", ""); 198 | //} 199 | if (!string.IsNullOrEmpty(ext)) 200 | { 201 | char[] anyOf = { '?', '&', '=' }; 202 | int nIndex = ext.IndexOfAny(anyOf); 203 | if (-1 != nIndex) 204 | { 205 | ext = ext.Substring(0, nIndex); 206 | } 207 | } 208 | } 209 | else 210 | { 211 | ext = "." + subType; 212 | } 213 | 214 | return SecurityHelper.MD5(url) + ext; 215 | } 216 | 217 | public static async Task GetFullMappedPathAsync(string url, StorageFolderType folderType, string fileName = "", string subType = "") 218 | { 219 | var storageManager = await LocalCacheManager.InitializeAsync(folderType); 220 | var dir = storageManager.CurrentFolder?.Path; 221 | 222 | if (string.IsNullOrEmpty(fileName)) 223 | { 224 | fileName = GetDownloadedLocalFileName(url, subType); 225 | } 226 | 227 | return System.IO.Path.Combine(dir, fileName); 228 | } 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /CommonLibrary/FileHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.Serialization.Json; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Windows.Media.Capture; 9 | using Windows.Storage; 10 | using Windows.Storage.Pickers; 11 | using Windows.Storage.Streams; 12 | 13 | namespace CommonLibrary 14 | { 15 | public static class FileHelper 16 | { 17 | public static async Task ReadObjectFromFile(this IStorageFile file) where T : class 18 | { 19 | T result = default(T); 20 | 21 | if (file != null) 22 | { 23 | using (var randomStream = await file.OpenReadAsync()) 24 | { 25 | if (randomStream.Size > 0) 26 | { 27 | var js = new DataContractJsonSerializer(typeof(T)); 28 | 29 | try 30 | { 31 | result = js.ReadObject(randomStream.AsStream()) as T; 32 | } 33 | catch (Exception ex) 34 | { 35 | System.Diagnostics.Debug.WriteLine(ex.Message); 36 | } 37 | 38 | } 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | 45 | public static async Task WriteObjectToFile(this IStorageFile file, T obj) where T : class 46 | { 47 | var js = new DataContractJsonSerializer(typeof(T)); 48 | using (var stream = new MemoryStream()) 49 | { 50 | string result; 51 | // we should use async method to write, or we will get nothing 52 | await Task.Factory.StartNew(() => js.WriteObject(stream, obj)); 53 | 54 | stream.Seek(0, SeekOrigin.Begin); 55 | 56 | using (var reader = new StreamReader(stream)) 57 | { 58 | result = await reader.ReadToEndAsync(); 59 | } 60 | try 61 | { 62 | await FileIO.WriteTextAsync(file, result); 63 | } 64 | catch 65 | { 66 | 67 | } 68 | } 69 | } 70 | 71 | public static async Task CheckFileType(StorageFile file) 72 | { 73 | using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read)) 74 | { 75 | return await CheckFileType(stream); 76 | } 77 | } 78 | 79 | public static async Task CheckFileType(RandomAccessStreamReference streamref) 80 | { 81 | IRandomAccessStream istream = await streamref.OpenReadAsync(); 82 | 83 | return await CheckFileType(istream); 84 | } 85 | 86 | public static async Task CheckFileType(IRandomAccessStream istream) 87 | { 88 | return await CheckFileType(istream.AsStreamForRead()); 89 | } 90 | public static async Task CheckFileType(Stream stream) 91 | { 92 | System.IO.BinaryReader br = new System.IO.BinaryReader(stream); 93 | string fileType = string.Empty; 94 | FileExtension extension; 95 | try 96 | { 97 | 98 | byte data = br.ReadByte(); 99 | fileType += data.ToString(); 100 | data = br.ReadByte(); 101 | fileType += data.ToString(); 102 | 103 | try 104 | { 105 | extension = (FileExtension)Enum.Parse(typeof(FileExtension), fileType); 106 | } 107 | catch 108 | { 109 | extension = FileExtension.validfile; 110 | } 111 | return extension; 112 | } 113 | catch 114 | { 115 | extension = FileExtension.validfile; 116 | return extension; 117 | } 118 | finally 119 | { 120 | stream.Position = 0; 121 | } 122 | } 123 | public static async Task GetSinglePictureFileFromAlbumAsync(string filters = "jpeg,jpg,png,bmp") 124 | { 125 | var openPicker = new FileOpenPicker 126 | { 127 | ViewMode = PickerViewMode.Thumbnail, 128 | SuggestedStartLocation = PickerLocationId.PicturesLibrary 129 | }; 130 | 131 | if (!string.IsNullOrEmpty(filters)) 132 | { 133 | var filtersArr = filters.Split(new char[] { ',' }); 134 | foreach (var filter in filtersArr) 135 | { 136 | openPicker.FileTypeFilter.Add("." + filter); 137 | } 138 | } 139 | try 140 | { 141 | return await openPicker.PickSingleFileAsync(); 142 | } 143 | catch 144 | { 145 | } 146 | 147 | return null; 148 | } 149 | public static async Task GetSinglePictureFileFromCameraAsync() 150 | { 151 | var cameraUI = new CameraCaptureUI(); 152 | 153 | cameraUI.PhotoSettings.AllowCropping = false; 154 | cameraUI.PhotoSettings.MaxResolution = CameraCaptureUIMaxPhotoResolution.Large3M; 155 | try 156 | { 157 | return await cameraUI.CaptureFileAsync(CameraCaptureUIMode.Photo); 158 | } 159 | catch 160 | { 161 | } 162 | 163 | return null; 164 | } 165 | } 166 | public enum FileExtension 167 | { 168 | jpg = 255216, 169 | gif = 7173, 170 | png = 13780, 171 | bmp = 6677, 172 | swf = 6787, 173 | //TIF = 7373, 174 | //PDF = 3780, 175 | //rar = 8297, 176 | //zip = 8075, 177 | //_7Z = 55122, 178 | validfile = 9999999 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /CommonLibrary/ImageProcessing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Runtime.InteropServices.WindowsRuntime; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Windows.UI.Xaml.Media.Imaging; 9 | using Windows.Graphics.Imaging; 10 | using Windows.Storage.Streams; 11 | 12 | namespace CommonLibrary 13 | { 14 | public class ImageProcessing 15 | { 16 | public ImageProcessing() 17 | { 18 | } 19 | public static async Task ResizeByDecoderAsync(WriteableBitmap sourceImage, int newWidth, int newHeight, bool IsProportion) 20 | { 21 | int lW = sourceImage.PixelWidth; 22 | int lH = sourceImage.PixelHeight; 23 | 24 | if (newWidth != 0 && newHeight != 0) 25 | { 26 | double nWidthFactor = (double)lW / (double)newWidth; 27 | double nHeightFactor = (double)lH / (double)newHeight; 28 | 29 | if (nWidthFactor != nHeightFactor && !IsProportion) 30 | { 31 | if (Math.Abs(nWidthFactor - 1.0f) > Math.Abs(nHeightFactor - 1.0f)) 32 | { 33 | newWidth = (int)((double)lW / nHeightFactor); 34 | nWidthFactor = nHeightFactor; 35 | } 36 | else 37 | { 38 | newHeight = (int)((double)lH / nWidthFactor); 39 | nHeightFactor = nWidthFactor; 40 | } 41 | } 42 | } 43 | 44 | // Get the pixel buffer of the writable bitmap in bytes 45 | Stream stream = sourceImage.PixelBuffer.AsStream(); 46 | byte[] pixels = new byte[(uint)stream.Length]; 47 | await stream.ReadAsync(pixels, 0, pixels.Length); 48 | //Encoding the data of the PixelBuffer we have from the writable bitmap 49 | var inMemoryRandomStream = new InMemoryRandomAccessStream(); 50 | var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, inMemoryRandomStream); 51 | encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)sourceImage.PixelWidth, (uint)sourceImage.PixelHeight, 96, 96, pixels); 52 | await encoder.FlushAsync(); 53 | // At this point we have an encoded image in inMemoryRandomStream 54 | // We apply the transform and decode 55 | var transform = new BitmapTransform 56 | { 57 | ScaledWidth = (uint)newWidth, 58 | ScaledHeight = (uint)newHeight, 59 | InterpolationMode = BitmapInterpolationMode.Fant 60 | }; 61 | inMemoryRandomStream.Seek(0); 62 | var decoder = await BitmapDecoder.CreateAsync(inMemoryRandomStream); 63 | var pixelData = await decoder.GetPixelDataAsync( 64 | BitmapPixelFormat.Bgra8, 65 | BitmapAlphaMode.Straight, 66 | transform, 67 | ExifOrientationMode.IgnoreExifOrientation, 68 | ColorManagementMode.DoNotColorManage); 69 | // An array containing the decoded image data 70 | var sourceDecodedPixels = pixelData.DetachPixelData(); 71 | // Approach 1 : Encoding the image buffer again: 72 | // Encoding data 73 | var inMemoryRandomStream2 = new InMemoryRandomAccessStream(); 74 | var encoder2 = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, inMemoryRandomStream2); 75 | encoder2.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)newWidth, (uint)newHeight, 96, 96, sourceDecodedPixels); 76 | await encoder2.FlushAsync(); 77 | inMemoryRandomStream2.Seek(0); 78 | // finally the resized writablebitmap 79 | var bitmap = new WriteableBitmap((int)newWidth, (int)newHeight); 80 | await bitmap.SetSourceAsync(inMemoryRandomStream2); 81 | return bitmap; 82 | } 83 | public static async Task ResizeAsync(WriteableBitmap sourceImage, int newWidth, int newHeight, bool IsProportion) 84 | { 85 | int lW = sourceImage.PixelWidth; 86 | int lH = sourceImage.PixelHeight; 87 | byte[] src = ConvertBitmapToByteArray(sourceImage); 88 | //return await ResizeAsync(src, lW, lH, newWidth, newHeight, IsProportion); 89 | 90 | WriteableBitmap retImage = new WriteableBitmap(newWidth, newHeight); 91 | if (newWidth != 0 && newHeight != 0) 92 | { 93 | double nWidthFactor = (double)lW / (double)newWidth; 94 | double nHeightFactor = (double)lH / (double)newHeight; 95 | 96 | if (nWidthFactor != nHeightFactor && !IsProportion) 97 | { 98 | if (Math.Abs(nWidthFactor - 1.0f) > Math.Abs(nHeightFactor - 1.0f)) 99 | { 100 | newWidth = (int)((double)lW / nHeightFactor); 101 | nWidthFactor = nHeightFactor; 102 | } 103 | else 104 | { 105 | newHeight = (int)((double)lH / nWidthFactor); 106 | nHeightFactor = nWidthFactor; 107 | } 108 | retImage = new WriteableBitmap(newWidth, newHeight); 109 | } 110 | } 111 | byte[] srcc = new byte[newWidth * 4 * newHeight]; 112 | await Task.Run(() => 113 | { 114 | srcc = Resize(src, lW, lH, newWidth, newHeight); 115 | }); 116 | Stream s = retImage.PixelBuffer.AsStream(); 117 | s.Seek(0, SeekOrigin.Begin); 118 | s.Write(srcc, 0, newWidth * 4 * newHeight); 119 | return retImage; 120 | } 121 | /// 122 | /// 123 | /// 124 | /// 125 | /// 126 | /// 127 | /// 是否长宽按比例缩放 128 | /// 129 | public static byte[] Resize(byte[] src, int lW, int lH, int newWidth, int newHeight) 130 | { 131 | //缩放 132 | double nWidthFactor = (double)lW / (double)newWidth; 133 | double nHeightFactor = (double)lH / (double)newHeight; 134 | 135 | byte[] srcc = new byte[newWidth * 4 * newHeight]; 136 | 137 | double fx, fy, nx, ny; 138 | int cx, cy, fr_x, fr_y; 139 | int[] color1 = new int[3]; 140 | int[] color2 = new int[3]; 141 | int[] color3 = new int[3]; 142 | int[] color4 = new int[3]; 143 | int alpha1, alpha2, alpha3, alpha4; 144 | byte nRed, nGreen, nBlue, nAlpha; 145 | 146 | byte bp1, bp2; 147 | 148 | for (int x = 0; x < newWidth; ++x) 149 | { 150 | for (int y = 0; y < newHeight; ++y) 151 | { 152 | 153 | fr_x = (int)Math.Floor(x * nWidthFactor); 154 | fr_y = (int)Math.Floor(y * nHeightFactor); 155 | cx = fr_x + 1; 156 | if (cx >= lW) cx = fr_x; 157 | cy = fr_y + 1; 158 | if (cy >= lH) cy = fr_y; 159 | fx = x * nWidthFactor - fr_x; 160 | fy = y * nHeightFactor - fr_y; 161 | nx = 1.0 - fx; 162 | ny = 1.0 - fy; 163 | 164 | color1 = getRGB(src, fr_x, fr_y, lW); 165 | color2 = getRGB(src, cx, fr_y, lW); 166 | color3 = getRGB(src, fr_x, cy, lW); 167 | color4 = getRGB(src, cx, cy, lW); 168 | 169 | alpha1 = GAP(src, fr_x, fr_y, lW); 170 | alpha2 = GAP(src, cx, fr_y, lW); 171 | alpha3 = GAP(src, fr_x, cy, lW); 172 | alpha4 = GAP(src, cx, cy, lW); 173 | 174 | // Blue 175 | bp1 = (byte)(nx * color1[2] + fx * color2[2]); 176 | 177 | bp2 = (byte)(nx * color3[2] + fx * color4[2]); 178 | 179 | nBlue = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); 180 | 181 | // Green 182 | bp1 = (byte)(nx * color1[1] + fx * color2[1]); 183 | 184 | bp2 = (byte)(nx * color3[1] + fx * color4[1]); 185 | 186 | nGreen = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); 187 | 188 | // Red 189 | bp1 = (byte)(nx * color1[0] + fx * color2[0]); 190 | 191 | bp2 = (byte)(nx * color3[0] + fx * color4[0]); 192 | 193 | nRed = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); 194 | 195 | // Alpha 196 | bp1 = (byte)(nx * alpha1 + fx * alpha2); 197 | 198 | bp2 = (byte)(nx * alpha3 + fx * alpha4); 199 | 200 | nAlpha = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); 201 | 202 | srcc[(y * newWidth + x) * 4] = (byte)nBlue; 203 | srcc[(y * newWidth + x) * 4 + 1] = (byte)nGreen; 204 | srcc[(y * newWidth + x) * 4 + 2] = (byte)nRed; 205 | srcc[(y * newWidth + x) * 4 + 3] = (byte)nAlpha; 206 | } 207 | } 208 | 209 | 210 | lW = newWidth; 211 | lH = newHeight; 212 | src = srcc; 213 | 214 | return srcc; 215 | } 216 | public static byte[] Combine(byte[] basesrc, byte[] floatsrc, int width, int height) 217 | { 218 | byte[] retsrc = new byte[height * 4 * width]; 219 | 220 | for (int x = 0; x < width; ++x) 221 | { 222 | for (int y = 0; y < height; ++y) 223 | { 224 | int[] color_float = getBGR(floatsrc, x, y, width); 225 | int alpha_float = GAP(floatsrc, x, y, width); 226 | 227 | int[] color_base = getBGR(basesrc, x, y, width); 228 | int alpha_base = GAP(basesrc, x, y, width); 229 | 230 | int R = 0, G = 0, B = 0, A = 0; 231 | 232 | if (alpha_base != 255) 233 | { 234 | color_base[0] = color_base[1] = color_base[2] = alpha_base = 255; 235 | color_base[0] = (255 * (255 - alpha_float) + color_float[0] * alpha_base) / 255; 236 | color_base[1] = (255 * (255 - alpha_float) + color_float[1] * alpha_base) / 255; 237 | color_base[2] = (255 * (255 - alpha_float) + color_float[2] * alpha_base) / 255; 238 | alpha_base = 255; 239 | } 240 | 241 | if (color_float[0] == 0 && color_float[1] == 0 && color_float[2] == 0 && alpha_float == 0) 242 | { 243 | B = color_base[0]; 244 | G = color_base[1]; 245 | R = color_base[2]; 246 | A = alpha_base; 247 | } 248 | else 249 | { 250 | B = (color_base[0] * (255 - alpha_float) + color_float[0] * alpha_float) / 255; 251 | G = (color_base[1] * (255 - alpha_float) + color_float[1] * alpha_float) / 255; 252 | R = (color_base[2] * (255 - alpha_float) + color_float[2] * alpha_float) / 255; 253 | A = alpha_float + (255 - alpha_float) * (alpha_base / 255); 254 | A = A > 255 ? 255 : A; 255 | } 256 | 257 | putpixel(retsrc, x, y, width, R, G, B, A); 258 | } 259 | } 260 | 261 | return retsrc; 262 | } 263 | public static async Task CombineAsync(WriteableBitmap BaseImage, WriteableBitmap FloatingImage) 264 | { 265 | if (BaseImage.PixelHeight != FloatingImage.PixelHeight || BaseImage.PixelWidth != FloatingImage.PixelWidth) 266 | return BaseImage; 267 | 268 | WriteableBitmap bmp = new WriteableBitmap(BaseImage.PixelWidth, BaseImage.PixelHeight); 269 | Stream s = bmp.PixelBuffer.AsStream(); 270 | 271 | byte[] basesrc = ConvertBitmapToByteArray(BaseImage); 272 | byte[] floatsrc = ConvertBitmapToByteArray(FloatingImage); 273 | 274 | byte[] retsrc = new byte[BaseImage.PixelHeight * 4 * BaseImage.PixelWidth]; 275 | 276 | int height = BaseImage.PixelHeight, width = BaseImage.PixelWidth; 277 | await Task.Run(() => 278 | { 279 | retsrc = Combine(basesrc, floatsrc, width, height); 280 | }); 281 | s.Seek(0, SeekOrigin.Begin); 282 | s.Write(retsrc, 0, BaseImage.PixelHeight * 4 * BaseImage.PixelWidth); 283 | return bmp; 284 | } 285 | static void putpixel(byte[] src, int x, int y, int size, int R, int G, int B, int A) 286 | { 287 | src[(y * size + x) * 4] = (byte)B; 288 | src[(y * size + x) * 4 + 1] = (byte)G; 289 | src[(y * size + x) * 4 + 2] = (byte)R; 290 | src[(y * size + x) * 4 + 3] = (byte)A; 291 | } 292 | 293 | static int[] getRGB(byte[] src, int x, int y, int lW) 294 | { 295 | int[] RGB = new int[3]; 296 | RGB[0] = GRP(src, x, y, lW); 297 | RGB[1] = GGP(src, x, y, lW); 298 | RGB[2] = GBP(src, x, y, lW); 299 | return RGB; 300 | } 301 | 302 | static int[] getBGR(byte[] src, int x, int y, int lW) 303 | { 304 | int[] RGB = new int[3]; 305 | RGB[0] = GBP(src, x, y, lW); 306 | RGB[1] = GGP(src, x, y, lW); 307 | RGB[2] = GRP(src, x, y, lW); 308 | return RGB; 309 | } 310 | 311 | static int GAP(byte[] src, int x, int y, int lW) 312 | { 313 | return src[(y * lW + x) * 4 + 3]; 314 | } 315 | 316 | static int GRP(byte[] src, int x, int y, int lW) 317 | { 318 | return src[(y * lW + x) * 4 + 2]; 319 | } 320 | static int GGP(byte[] src, int x, int y, int lW) 321 | { 322 | return src[(y * lW + x) * 4 + 1]; 323 | } 324 | static int GBP(byte[] src, int x, int y, int lW) 325 | { 326 | return src[(y * lW + x) * 4]; 327 | } 328 | 329 | static int GGRYP(byte[] src, int x, int y, int lW) 330 | { 331 | return (GRP(src, x, y, lW) * 3 + GRP(src, x, y, lW) * 6 + GRP(src, x, y, lW) * 1) / 10; 332 | } 333 | 334 | static byte[] ConvertBitmapToByteArray(WriteableBitmap bitmap) 335 | { 336 | return bitmap.PixelBuffer.ToArray(); 337 | //using (Stream stream = bitmap.PixelBuffer.AsStream()) 338 | //using (MemoryStream memoryStream = new MemoryStream()) 339 | //{ 340 | // stream.CopyToAsync(memoryStream); 341 | // return memoryStream.ToArray(); 342 | //} 343 | } 344 | } 345 | 346 | } 347 | -------------------------------------------------------------------------------- /CommonLibrary/LocalCacheManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CommonLibrary 8 | { 9 | public class LocalCacheManager : StorageManager 10 | { 11 | protected LocalCacheManager() : base() 12 | { 13 | } 14 | 15 | public static async Task InitializeAsync(StorageFolderType secondaryFolderType, string currentFolderName = "") 16 | { 17 | var manager = new LocalCacheManager(); 18 | manager.RootFolder = StorageHelper.LocalCacheFolder; 19 | manager.SecondaryFolderType = secondaryFolderType; 20 | manager.SecondaryFolder = await manager.GetOrCreateSecondaryFolderAsync()/*.ConfigureAwait(false)*/; 21 | manager.CurrentFolder = await manager.GetOrCreateCurrentFolderAsync(currentFolderName)/*.ConfigureAwait(false)*/; 22 | return manager; 23 | } 24 | 25 | public static async Task ClearAsync(StorageFolderType secondaryFolderType) 26 | { 27 | var manager = await InitializeAsync(secondaryFolderType); 28 | return await manager.ClearAsync(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CommonLibrary/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CommonLibrary")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CommonLibrary")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /CommonLibrary/Properties/CommonLibrary.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CommonLibrary/SecurityHelper.cs: -------------------------------------------------------------------------------- 1 | using Windows.Security.Cryptography; 2 | using Windows.Security.Cryptography.Core; 3 | using Windows.Storage.Streams; 4 | 5 | namespace CommonLibrary 6 | { 7 | public class SecurityHelper 8 | { 9 | public static string MD5(string input) 10 | { 11 | IBuffer bufInput = CryptographicBuffer.ConvertStringToBinary(input, BinaryStringEncoding.Utf8); 12 | HashAlgorithmProvider algo = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); 13 | IBuffer bufOutput = algo.HashData(bufInput); 14 | if (bufOutput.Length != algo.HashLength) 15 | { 16 | return string.Empty; 17 | } 18 | string output = CryptographicBuffer.EncodeToHexString(bufOutput).ToUpper(); 19 | return output; 20 | } 21 | 22 | public static string UrlEncoder(string input) 23 | { 24 | return System.Net.WebUtility.UrlEncode(input); 25 | } 26 | 27 | public static string UrlDecode(string input) 28 | { 29 | return System.Net.WebUtility.UrlDecode(input); 30 | } 31 | 32 | public static string AESEncrypt(string key, string value) 33 | { 34 | try 35 | { 36 | IBuffer bufMsg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8); 37 | IBuffer bufKey = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); 38 | string strAlgName = Windows.Security.Cryptography.Core.SymmetricAlgorithmNames.AesCbcPkcs7; 39 | SymmetricKeyAlgorithmProvider alg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName); 40 | CryptographicKey encryptKey = alg.CreateSymmetricKey(bufKey); 41 | IBuffer bufOutput = CryptographicEngine.Encrypt(encryptKey, bufMsg, bufKey); 42 | string output = CryptographicBuffer.EncodeToBase64String(bufOutput); 43 | return output; 44 | } 45 | catch 46 | { 47 | return string.Empty; 48 | } 49 | } 50 | 51 | public static string AESDecrypt(string key, string value) 52 | { 53 | try 54 | { 55 | IBuffer bufMsg = CryptographicBuffer.DecodeFromBase64String(value); 56 | IBuffer bufKey = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); 57 | string strAlgName = Windows.Security.Cryptography.Core.SymmetricAlgorithmNames.AesCbcPkcs7; 58 | SymmetricKeyAlgorithmProvider alg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName); 59 | CryptographicKey encryptKey = alg.CreateSymmetricKey(bufKey); 60 | IBuffer bufOutput = CryptographicEngine.Decrypt(encryptKey, bufMsg, bufKey); 61 | string output = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, bufOutput); 62 | return output; 63 | } 64 | catch 65 | { 66 | return string.Empty; 67 | } 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /CommonLibrary/StorageHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Storage; 7 | 8 | namespace CommonLibrary 9 | { 10 | public class StorageHelper 11 | { 12 | public static ApplicationDataContainer LocalSettings 13 | { 14 | get 15 | { 16 | return ApplicationData.Current.LocalSettings; 17 | } 18 | } 19 | 20 | public static StorageFolder PicturesLibrary 21 | { 22 | get 23 | { 24 | return KnownFolders.PicturesLibrary; 25 | } 26 | } 27 | 28 | public static StorageFolder LocalFolder 29 | { 30 | get 31 | { 32 | return ApplicationData.Current.LocalFolder; 33 | } 34 | } 35 | 36 | public static StorageFolder LocalCacheFolder 37 | { 38 | get 39 | { 40 | return ApplicationData.Current.LocalCacheFolder; 41 | } 42 | } 43 | 44 | public static StorageFolder TemporaryFolder 45 | { 46 | get 47 | { 48 | return ApplicationData.Current.TemporaryFolder; 49 | } 50 | } 51 | 52 | public static async Task TryGetFileFromApplicationUriAsync(Uri uri) 53 | { 54 | try 55 | { 56 | return await StorageFile.GetFileFromApplicationUriAsync(uri); 57 | } 58 | catch 59 | { 60 | return null; 61 | } 62 | } 63 | 64 | public static async Task TryGetFileFromPathAsync(string path) 65 | { 66 | try 67 | { 68 | return await StorageFile.GetFileFromPathAsync(path); 69 | } 70 | catch 71 | { 72 | return null; 73 | } 74 | } 75 | 76 | public static async Task TryGetFileAsync(string path) 77 | { 78 | var file = await TryGetFileFromPathAsync(path); 79 | if (file == null) 80 | { 81 | try 82 | { 83 | var uri = new Uri(path, UriKind.Absolute); 84 | file = await TryGetFileFromApplicationUriAsync(uri); 85 | } 86 | catch 87 | { 88 | } 89 | } 90 | 91 | return file; 92 | } 93 | 94 | public static async Task TryGetFolderFromPathAsync(string path) 95 | { 96 | try 97 | { 98 | return await StorageFolder.GetFolderFromPathAsync(path); 99 | } 100 | catch 101 | { 102 | return null; 103 | } 104 | } 105 | 106 | public static async Task FileExistsAsync(string path) 107 | { 108 | var file = await TryGetFileFromPathAsync(path); 109 | if (file == null) return false; 110 | return true; 111 | } 112 | 113 | public static async Task DirectoryExistsAsync(string path) 114 | { 115 | var folder = await TryGetFolderFromPathAsync(path); 116 | if (folder == null) return false; 117 | return true; 118 | } 119 | 120 | public static bool FileExists(string path) 121 | { 122 | var isExists = false; 123 | try 124 | { 125 | isExists = System.IO.File.Exists(path); 126 | } 127 | catch 128 | { 129 | isExists = false; 130 | } 131 | 132 | return isExists; 133 | } 134 | 135 | public static async Task ClearAsync(ApplicationDataLocality locality) 136 | { 137 | try 138 | { 139 | await ApplicationData.Current.ClearAsync(locality); 140 | 141 | return true; 142 | } 143 | catch 144 | { 145 | return false; 146 | } 147 | } 148 | 149 | public static async Task ClearAllCacheAsync() 150 | { 151 | try 152 | { 153 | await ApplicationData.Current.ClearAsync(ApplicationDataLocality.LocalCache); 154 | await ApplicationData.Current.ClearAsync(ApplicationDataLocality.Temporary); 155 | return true; 156 | } 157 | catch 158 | { 159 | return false; 160 | } 161 | } 162 | 163 | public static async Task ClearAllAsync() 164 | { 165 | try 166 | { 167 | await ApplicationData.Current.ClearAsync(ApplicationDataLocality.Local); 168 | await ApplicationData.Current.ClearAsync(ApplicationDataLocality.LocalCache); 169 | await ApplicationData.Current.ClearAsync(ApplicationDataLocality.Temporary); 170 | 171 | return true; 172 | } 173 | catch 174 | { 175 | return false; 176 | } 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /CommonLibrary/StorageManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Storage; 7 | using Windows.Storage.Streams; 8 | using System.IO; 9 | 10 | namespace CommonLibrary 11 | { 12 | public class StorageManager 13 | { 14 | public StorageFolder RootFolder { get; protected set; } 15 | public StorageFolder SecondaryFolder { get; protected set; } 16 | public StorageFolder CurrentFolder { get; protected set; } 17 | public StorageFolderType SecondaryFolderType { get; protected set; } 18 | 19 | protected StorageManager() 20 | { 21 | } 22 | 23 | public async Task GetFileAsync(string name) 24 | { 25 | return await CurrentFolder?.TryGetFileAsync(name); 26 | } 27 | 28 | public async Task CreateFileAsync(string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 29 | { 30 | return await CurrentFolder?.TryCreateFileAsync(name, options); 31 | } 32 | 33 | public async Task CreateFileAsync(byte[] bytes, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 34 | { 35 | var file = await CreateFileAsync(name, options); 36 | await file.TryWriteBytesAsync(bytes); 37 | return file; 38 | } 39 | 40 | public async Task CreateFileAsync(IRandomAccessStream stream, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 41 | { 42 | var file = await CreateFileAsync(name, options); 43 | await file.TryWriteStreamAsync(stream); 44 | return file; 45 | } 46 | 47 | public async Task CreateFileAsync(Stream stream, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 48 | { 49 | var file = await CreateFileAsync(name, options); 50 | await file.TryWriteStreamAsync(stream); 51 | return file; 52 | } 53 | 54 | public async Task CreateFileAsync(IBuffer buffer, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 55 | { 56 | var file = await CreateFileAsync(name, options); 57 | await file.TryWriteBufferAsync(buffer); 58 | return file; 59 | } 60 | 61 | public async Task AppendTextAsync(string text, string name) 62 | { 63 | var file = await GetOrCreateFileAsync(name); 64 | return await file.TryAppendTextAsync(text); 65 | } 66 | 67 | public async Task AppendLinesAsync(IEnumerable lines, string name) 68 | { 69 | var file = await GetOrCreateFileAsync(name); 70 | return await file.TryAppendLinesAsync(lines); 71 | } 72 | 73 | private async Task GetOrCreateFileAsync(string name) 74 | { 75 | var file = await GetFileAsync(name); 76 | if (file == null) file = await CurrentFolder?.TryCreateFileAsync(name); 77 | return file; 78 | } 79 | 80 | public async Task ReadTextAsync(string name) 81 | { 82 | var file = await GetFileAsync(name); 83 | return await file.TryReadTextAsync(); 84 | } 85 | 86 | public async Task> ReadLinesAsync(string name) 87 | { 88 | var file = await GetFileAsync(name); 89 | return await file.TryReadLinesAsync(); 90 | } 91 | 92 | public async Task ClearAsync() 93 | { 94 | if (SecondaryFolderType == StorageFolderType.Root) 95 | return await StorageHelper.ClearAsync(ApplicationDataLocality.LocalCache); 96 | 97 | return await SecondaryFolder.TryDeleteAsync(); 98 | } 99 | 100 | public string SecondaryFolderName 101 | { 102 | get 103 | { 104 | if (SecondaryFolderType == StorageFolderType.Root) return ""; 105 | 106 | return SecondaryFolderType.ToString(); 107 | } 108 | } 109 | 110 | protected async Task GetOrCreateSecondaryFolderAsync() 111 | { 112 | if (string.IsNullOrEmpty(SecondaryFolderName)) return RootFolder; 113 | 114 | var folder = await RootFolder.TryGetFolderAsync(SecondaryFolderName); 115 | 116 | if (folder == null) 117 | folder = await RootFolder.TryCreateFolderAsync(SecondaryFolderName); 118 | 119 | return folder; 120 | } 121 | 122 | protected async Task GetOrCreateCurrentFolderAsync(string name) 123 | { 124 | if (string.IsNullOrEmpty(name)) return SecondaryFolder; 125 | 126 | var currentFolder = await SecondaryFolder.TryGetFolderAsync(name); 127 | 128 | if (currentFolder == null) 129 | return await SecondaryFolder.TryCreateFolderAsync(name); 130 | 131 | return currentFolder; 132 | } 133 | } 134 | public enum StorageFolderType 135 | { 136 | Root, 137 | Pictures, 138 | Documents, 139 | Downloads, 140 | Media 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /CommonLibrary/StorageManagerEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Storage; 7 | using Windows.Storage.Streams; 8 | using System.Runtime.InteropServices.WindowsRuntime; 9 | using System.IO; 10 | 11 | namespace CommonLibrary 12 | { 13 | public static class StorageManagerEx 14 | { 15 | #region StorageFolder 16 | 17 | public static async Task TryCreateFolderAsync(this StorageFolder storageFolder, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 18 | { 19 | StorageFolder folder = null; 20 | try 21 | { 22 | folder = await storageFolder.CreateFolderAsync(name, options); 23 | } 24 | catch 25 | { 26 | } 27 | 28 | return folder; 29 | } 30 | 31 | public static async Task TryGetFolderAsync(this StorageFolder storageFolder, string name) 32 | { 33 | StorageFolder folder = null; 34 | try 35 | { 36 | folder = await storageFolder.GetFolderAsync(name); 37 | } 38 | catch 39 | { 40 | } 41 | 42 | return folder; 43 | } 44 | 45 | public static async Task TryDeleteFileAsync(this StorageFolder storageFolder, string name) 46 | { 47 | try 48 | { 49 | var file = await storageFolder.TryGetFileAsync(name); 50 | file?.TryDeleteAsync(); 51 | return true; 52 | } 53 | catch 54 | { 55 | } 56 | 57 | return false; 58 | } 59 | 60 | public static async Task TryDeleteAsync(this StorageFolder storageFolder) 61 | { 62 | try 63 | { 64 | await storageFolder.TryClearAsync(); 65 | await storageFolder.DeleteAsync(); 66 | return true; 67 | } 68 | catch 69 | { 70 | } 71 | 72 | return false; 73 | } 74 | 75 | public static async Task TryClearAsync(this StorageFolder storageFolder) 76 | { 77 | var success = true; 78 | 79 | var items = await storageFolder.GetItemsAsync(); 80 | 81 | foreach (var item in items) 82 | { 83 | if (item.IsOfType(StorageItemTypes.Folder)) 84 | { 85 | success = success && await TryClearAsync(item as StorageFolder); 86 | } 87 | try 88 | { 89 | await item.DeleteAsync(); 90 | } 91 | catch 92 | { 93 | success = false; 94 | } 95 | } 96 | 97 | return success; 98 | } 99 | 100 | public static async Task TryCreateFileAsync(this StorageFolder storageFolder, string name, CreationCollisionOption options = CreationCollisionOption.OpenIfExists) 101 | { 102 | StorageFile file = null; 103 | try 104 | { 105 | file = await storageFolder.CreateFileAsync(name, options); 106 | } 107 | catch 108 | { 109 | } 110 | 111 | return file; 112 | } 113 | 114 | public static async Task TryGetFileAsync(this StorageFolder storageFolder, string name) 115 | { 116 | StorageFile file = null; 117 | try 118 | { 119 | file = await storageFolder.GetFileAsync(name); 120 | } 121 | catch 122 | { 123 | } 124 | 125 | return file; 126 | } 127 | 128 | public static async Task FileExistsAsync(this StorageFolder storageFolder, string name) 129 | { 130 | var item = await storageFolder.TryGetItemAsync(name); 131 | if (item is StorageFile) return true; 132 | 133 | return false; 134 | } 135 | 136 | public static async Task FolderExistsAsync(this StorageFolder storageFolder, string name) 137 | { 138 | var item = await storageFolder.TryGetItemAsync(name); 139 | if (item is StorageFolder) return true; 140 | 141 | return false; 142 | } 143 | 144 | #endregion 145 | 146 | 147 | #region StorageFile 148 | 149 | public static async Task TryDeleteAsync(this StorageFile storageFile) 150 | { 151 | try 152 | { 153 | await storageFile.DeleteAsync(); 154 | 155 | return true; 156 | } 157 | catch 158 | { 159 | } 160 | 161 | return false; 162 | } 163 | 164 | public static async Task TryWriteStringAsync(this StorageFile storageFile, string textContent) 165 | { 166 | try 167 | { 168 | using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) 169 | { 170 | using (DataWriter dataWriter = new DataWriter(transaction.Stream)) 171 | { 172 | dataWriter.WriteString(textContent); 173 | transaction.Stream.Size = await dataWriter.StoreAsync(); 174 | await transaction.CommitAsync(); 175 | return true; 176 | } 177 | } 178 | } 179 | catch 180 | { 181 | return false; 182 | } 183 | } 184 | 185 | public static async Task TryWriteBufferAsync(this StorageFile storageFile, IBuffer buffer) 186 | { 187 | try 188 | { 189 | using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) 190 | { 191 | using (DataWriter dataWriter = new DataWriter(transaction.Stream)) 192 | { 193 | dataWriter.WriteBuffer(buffer); 194 | transaction.Stream.Size = await dataWriter.StoreAsync(); 195 | await transaction.CommitAsync(); 196 | return true; 197 | } 198 | } 199 | } 200 | catch 201 | { 202 | return false; 203 | } 204 | } 205 | 206 | public static async Task TryWriteBufferAsync(this StorageFile storageFile, IBuffer buffer, uint start, uint count) 207 | { 208 | try 209 | { 210 | using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) 211 | { 212 | using (DataWriter dataWriter = new DataWriter(transaction.Stream)) 213 | { 214 | dataWriter.WriteBuffer(buffer, start, count); 215 | transaction.Stream.Size = await dataWriter.StoreAsync(); 216 | await transaction.CommitAsync(); 217 | return true; 218 | } 219 | } 220 | } 221 | catch 222 | { 223 | return false; 224 | } 225 | } 226 | 227 | public static async Task TryWriteBytesAsync(this StorageFile storageFile, byte[] bytes) 228 | { 229 | if (bytes == null) return false; 230 | 231 | try 232 | { 233 | using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()) 234 | { 235 | using (DataWriter dataWriter = new DataWriter(transaction.Stream)) 236 | { 237 | dataWriter.WriteBytes(bytes); 238 | transaction.Stream.Size = await dataWriter.StoreAsync(); 239 | await transaction.CommitAsync(); 240 | return true; 241 | } 242 | } 243 | } 244 | catch 245 | { 246 | return false; 247 | } 248 | } 249 | 250 | public static async Task TryWriteStreamAsync(this StorageFile storageFile, IRandomAccessStream stream) 251 | { 252 | stream.Seek(0); 253 | IBuffer buffer = new byte[stream.Size].AsBuffer(); 254 | await stream.ReadAsync(buffer, buffer.Length, InputStreamOptions.None); 255 | return await TryWriteBufferAsync(storageFile, buffer); 256 | } 257 | 258 | public static async Task TryWriteStreamAsync(this StorageFile storageFile, Stream stream) 259 | { 260 | return await TryWriteStreamAsync(storageFile, stream.AsRandomAccessStream()); 261 | } 262 | 263 | public static async Task TryAppendTextAsync(this StorageFile storageFile, string text) 264 | { 265 | try 266 | { 267 | await FileIO.AppendTextAsync(storageFile, text); 268 | } 269 | catch 270 | { 271 | } 272 | 273 | return storageFile; 274 | } 275 | 276 | public static async Task TryAppendLinesAsync(this StorageFile storageFile, IEnumerable lines) 277 | { 278 | try 279 | { 280 | await FileIO.AppendLinesAsync(storageFile, lines); 281 | } 282 | catch 283 | { 284 | } 285 | 286 | return storageFile; 287 | } 288 | 289 | public static async Task TryReadTextAsync(this StorageFile storageFile) 290 | { 291 | if (storageFile == null) return ""; 292 | 293 | try 294 | { 295 | return await FileIO.ReadTextAsync(storageFile); 296 | } 297 | catch 298 | { 299 | return ""; 300 | } 301 | } 302 | 303 | public static async Task> TryReadLinesAsync(this StorageFile storageFile) 304 | { 305 | if (storageFile == null) return new List(); 306 | 307 | try 308 | { 309 | return await FileIO.ReadLinesAsync(storageFile); 310 | } 311 | catch 312 | { 313 | return new List(); 314 | } 315 | } 316 | 317 | public static async Task TryReadStreamAsync(this StorageFile storageFile) 318 | { 319 | try 320 | { 321 | if (storageFile != null) 322 | { 323 | return await storageFile.OpenAsync(FileAccessMode.Read); 324 | } 325 | else 326 | { 327 | return null; 328 | } 329 | } 330 | catch 331 | { 332 | return null; 333 | } 334 | } 335 | 336 | #endregion 337 | } 338 | 339 | } 340 | -------------------------------------------------------------------------------- /CommonLibrary/Themes/Generic.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /CommonLibrary/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UWP_Toolkit -------------------------------------------------------------------------------- /UWPToolkit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWPToolkit", "UWPToolkit\UWPToolkit.csproj", "{A82469BE-A664-4D1E-9511-210EC2A631F0}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLibrary", "CommonLibrary\CommonLibrary.csproj", "{1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|Any CPU.ActiveCfg = Debug|x86 23 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|ARM.ActiveCfg = Debug|ARM 24 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|ARM.Build.0 = Debug|ARM 25 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|ARM.Deploy.0 = Debug|ARM 26 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x64.ActiveCfg = Debug|x64 27 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x64.Build.0 = Debug|x64 28 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x64.Deploy.0 = Debug|x64 29 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x86.ActiveCfg = Debug|x86 30 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x86.Build.0 = Debug|x86 31 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Debug|x86.Deploy.0 = Debug|x86 32 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|Any CPU.ActiveCfg = Release|x86 33 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|ARM.ActiveCfg = Release|ARM 34 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|ARM.Build.0 = Release|ARM 35 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|ARM.Deploy.0 = Release|ARM 36 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x64.ActiveCfg = Release|x64 37 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x64.Build.0 = Release|x64 38 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x64.Deploy.0 = Release|x64 39 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x86.ActiveCfg = Release|x86 40 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x86.Build.0 = Release|x86 41 | {A82469BE-A664-4D1E-9511-210EC2A631F0}.Release|x86.Deploy.0 = Release|x86 42 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|ARM.ActiveCfg = Debug|ARM 45 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|ARM.Build.0 = Debug|ARM 46 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|x64.ActiveCfg = Debug|x64 47 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|x64.Build.0 = Debug|x64 48 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|x86.ActiveCfg = Debug|x86 49 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Debug|x86.Build.0 = Debug|x86 50 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|ARM.ActiveCfg = Release|ARM 53 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|ARM.Build.0 = Release|ARM 54 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|x64.ActiveCfg = Release|x64 55 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|x64.Build.0 = Release|x64 56 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|x86.ActiveCfg = Release|x86 57 | {1FAA2DB6-1203-4DF4-AC1A-8EC415F6681D}.Release|x86.Build.0 = Release|x86 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /UWPToolkit/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /UWPToolkit/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Activation; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | namespace UWPToolkit 19 | { 20 | /// 21 | /// 提供特定于应用程序的行为,以补充默认的应用程序类。 22 | /// 23 | sealed partial class App : Application 24 | { 25 | /// 26 | /// 初始化单一实例应用程序对象。这是执行的创作代码的第一行, 27 | /// 已执行,逻辑上等同于 main() 或 WinMain()。 28 | /// 29 | public App() 30 | { 31 | this.InitializeComponent(); 32 | this.Suspending += OnSuspending; 33 | } 34 | 35 | /// 36 | /// 在应用程序由最终用户正常启动时进行调用。 37 | /// 将在启动应用程序以打开特定文件等情况下使用。 38 | /// 39 | /// 有关启动请求和过程的详细信息。 40 | protected override void OnLaunched(LaunchActivatedEventArgs e) 41 | { 42 | #if DEBUG 43 | if (System.Diagnostics.Debugger.IsAttached) 44 | { 45 | this.DebugSettings.EnableFrameRateCounter = true; 46 | } 47 | #endif 48 | Frame rootFrame = Window.Current.Content as Frame; 49 | 50 | // 不要在窗口已包含内容时重复应用程序初始化, 51 | // 只需确保窗口处于活动状态 52 | if (rootFrame == null) 53 | { 54 | // 创建要充当导航上下文的框架,并导航到第一页 55 | rootFrame = new Frame(); 56 | 57 | rootFrame.NavigationFailed += OnNavigationFailed; 58 | 59 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 60 | { 61 | //TODO: 从之前挂起的应用程序加载状态 62 | } 63 | 64 | // 将框架放在当前窗口中 65 | Window.Current.Content = rootFrame; 66 | } 67 | 68 | if (e.PrelaunchActivated == false) 69 | { 70 | if (rootFrame.Content == null) 71 | { 72 | // 当导航堆栈尚未还原时,导航到第一页, 73 | // 并通过将所需信息作为导航参数传入来配置 74 | // 参数 75 | rootFrame.Navigate(typeof(MasterPage), e.Arguments); 76 | } 77 | // 确保当前窗口处于活动状态 78 | Window.Current.Activate(); 79 | } 80 | } 81 | 82 | /// 83 | /// 导航到特定页失败时调用 84 | /// 85 | ///导航失败的框架 86 | ///有关导航失败的详细信息 87 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 88 | { 89 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 90 | } 91 | 92 | /// 93 | /// 在将要挂起应用程序执行时调用。 在不知道应用程序 94 | /// 无需知道应用程序会被终止还是会恢复, 95 | /// 并让内存内容保持不变。 96 | /// 97 | /// 挂起的请求的源。 98 | /// 有关挂起请求的详细信息。 99 | private void OnSuspending(object sender, SuspendingEventArgs e) 100 | { 101 | var deferral = e.SuspendingOperation.GetDeferral(); 102 | //TODO: 保存应用程序状态并停止任何后台活动 103 | deferral.Complete(); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /UWPToolkit/ApplicationInsights.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /UWPToolkit/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/StoreLogo.png -------------------------------------------------------------------------------- /UWPToolkit/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /UWPToolkit/Controls/BasePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.Foundation; 8 | using Windows.UI.Core; 9 | using Windows.UI.Xaml; 10 | using Windows.UI.Xaml.Controls; 11 | using Windows.UI.Xaml.Input; 12 | using Windows.UI.Xaml.Media; 13 | using Windows.UI.Xaml.Media.Animation; 14 | using Windows.UI.Xaml.Navigation; 15 | 16 | namespace UWPToolkit.Controls 17 | { 18 | public class BasePage : Page 19 | { 20 | private PageStytle _pageStytle = PageStytle.None; 21 | public PageStytle PageStytle 22 | { 23 | get 24 | { 25 | return _pageStytle; 26 | } 27 | set 28 | { 29 | if (_pageStytle != value) 30 | { 31 | _pageStytle = value; 32 | } 33 | } 34 | } 35 | 36 | public int PageID = 0; 37 | public BasePage(PageStytle style = PageStytle.None) 38 | { 39 | this.IsTextScaleFactorEnabled = false; 40 | this.SizeChanged += BasePage_SizeChanged; 41 | this.Loaded += BasePage_Loaded; 42 | this.Unloaded += BasePage_Unloaded; 43 | PageStytle = style; 44 | if (PageStytle != PageStytle.Main) 45 | { 46 | this.ManipulationMode = ManipulationModes.TranslateX; 47 | this.ManipulationCompleted += BasePage_ManipulationCompleted; 48 | this.ManipulationDelta += BasePage_ManipulationDelta; 49 | 50 | _tt = this.RenderTransform as TranslateTransform; 51 | if (_tt == null) this.RenderTransform = _tt = new TranslateTransform(); 52 | } 53 | } 54 | 55 | private void BasePage_Loaded(object sender, RoutedEventArgs e) 56 | { 57 | OnLoaded(e); 58 | SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible; 59 | SystemNavigationManager.GetForCurrentView().BackRequested += BasePage_BackRequested; 60 | } 61 | 62 | private void BasePage_BackRequested(object sender, BackRequestedEventArgs e) 63 | { 64 | MasterPage.BackRequest(); 65 | } 66 | 67 | private void BasePage_Unloaded(object sender, RoutedEventArgs e) 68 | { 69 | OnUnloaded(e); 70 | } 71 | 72 | private void BasePage_SizeChanged(object sender, SizeChangedEventArgs e) 73 | { 74 | var eArgs = new PageSizeChangedEventArgs(e.OriginalSource, e.PreviousSize, e.NewSize); 75 | OnPageSizeChanged(eArgs); 76 | } 77 | 78 | protected virtual void OnLoaded(RoutedEventArgs e) 79 | { 80 | } 81 | 82 | protected virtual void OnUnloaded(RoutedEventArgs e) 83 | { 84 | } 85 | 86 | protected override void OnNavigatedTo(NavigationEventArgs e) 87 | { 88 | base.OnNavigatedTo(e); 89 | } 90 | 91 | protected override void OnNavigatedFrom(NavigationEventArgs e) 92 | { 93 | base.OnNavigatedFrom(e); 94 | } 95 | 96 | protected virtual void OnPageSizeChanged(PageSizeChangedEventArgs e) 97 | { 98 | 99 | } 100 | 101 | #region Swipe Gestures 手势滑动 102 | private TranslateTransform _tt; 103 | /// 104 | /// 0:后退 -1:向左划 1:向右划 105 | /// 106 | private int action = 0; 107 | 108 | private void BasePage_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) 109 | { 110 | 111 | if (_tt.X + e.Delta.Translation.X < 0) 112 | { 113 | _tt.X = 0; 114 | return; 115 | } 116 | _tt.X += e.Delta.Translation.X; 117 | 118 | } 119 | 120 | 121 | private void BasePage_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) 122 | { 123 | 124 | double abs_delta = Math.Abs(e.Cumulative.Translation.X); 125 | double speed = Math.Abs(e.Velocities.Linear.X); 126 | double delta = e.Cumulative.Translation.X; 127 | double to = 0; 128 | 129 | if (abs_delta < this.ActualWidth / 3 && speed < 0.5) 130 | { 131 | _tt.X = 0; 132 | return; 133 | } 134 | 135 | 136 | action = 0; 137 | if (delta > 0) 138 | to = this.ActualWidth; 139 | else if (delta < 0) 140 | return; 141 | 142 | 143 | var s = new Storyboard(); 144 | var doubleanimation = new DoubleAnimation() { Duration = new Duration(TimeSpan.FromMilliseconds(120)), From = _tt.X, To = to }; 145 | doubleanimation.Completed += Doubleanimation_Completed; 146 | Storyboard.SetTarget(doubleanimation, _tt); 147 | Storyboard.SetTargetProperty(doubleanimation, "X"); 148 | s.Children.Add(doubleanimation); 149 | s.Begin(); 150 | } 151 | 152 | private void Doubleanimation_Completed(object sender, object e) 153 | { 154 | if (action == 0) 155 | { 156 | MasterPage.BackRequest(); 157 | } 158 | else 159 | { 160 | } 161 | 162 | _tt = this.RenderTransform as TranslateTransform; 163 | if (_tt == null) this.RenderTransform = _tt = new TranslateTransform(); 164 | _tt.X = 0; 165 | 166 | } 167 | } 168 | #endregion 169 | 170 | public class PageSizeChangedEventArgs : EventArgs 171 | { 172 | public PageSizeChangedEventArgs(object originalSource, Size previousSize, Size newSize) 173 | { 174 | this.OriginalSource = originalSource; 175 | this.PreviousSize = previousSize; 176 | this.NewSize = newSize; 177 | } 178 | 179 | public Size NewSize { private set; get; } 180 | public Size PreviousSize { private set; get; } 181 | public object OriginalSource { private set; get; } 182 | } 183 | 184 | public enum PopupMode 185 | { 186 | H5, 187 | Native, 188 | None 189 | } 190 | 191 | public enum PageStytle 192 | { 193 | Main, 194 | Left, 195 | Right, 196 | Detail, 197 | None 198 | } 199 | } 200 | 201 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PictureCropControl.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PictureCropControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Runtime.InteropServices.WindowsRuntime; 8 | using System.Threading.Tasks; 9 | using Windows.Foundation; 10 | using Windows.Foundation.Collections; 11 | using Windows.Graphics.Imaging; 12 | using Windows.Media.Capture; 13 | using Windows.Storage; 14 | using Windows.Storage.Pickers; 15 | using Windows.Storage.Streams; 16 | using Windows.UI.ViewManagement; 17 | using Windows.UI.Xaml; 18 | using Windows.UI.Xaml.Controls; 19 | using Windows.UI.Xaml.Controls.Primitives; 20 | using Windows.UI.Xaml.Data; 21 | using Windows.UI.Xaml.Input; 22 | using Windows.UI.Xaml.Media; 23 | using Windows.UI.Xaml.Media.Imaging; 24 | using Windows.UI.Xaml.Navigation; 25 | 26 | // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介绍 27 | 28 | namespace UWPToolkit.Controls 29 | { 30 | /// 31 | /// 可用于自身或导航至 Frame 内部的空白页。 32 | /// 33 | public sealed partial class PictureCropControl : UserControl 34 | { 35 | public delegate void PictureCrop_Handler(StorageFile file); 36 | public PictureCrop_Handler PictureCrop_HandlerEvent; 37 | public PictureCropControl() 38 | { 39 | this.InitializeComponent(); 40 | } 41 | private StorageFile file; 42 | private AspectRatio aspect; 43 | private CropSelectionSize cropsize; 44 | public PictureCropControl(StorageFile file, AspectRatio aspect = AspectRatio.Custom, CropSelectionSize cropsize = CropSelectionSize.Half) 45 | { 46 | this.InitializeComponent(); 47 | this.file = file; 48 | this.aspect = aspect; 49 | this.cropsize = cropsize; 50 | } 51 | async Task Init() 52 | { 53 | CropImageControl.SourceImageFile = file; 54 | CropImageControl.CropAspectRatio = aspect; 55 | CropImageControl.DefaultCropSelectionSize = cropsize; 56 | } 57 | Popup popup; 58 | public async void Show() 59 | { 60 | await Init(); 61 | var appView = ApplicationView.GetForCurrentView(); 62 | 63 | popup = new Popup(); 64 | //popup.IsLightDismissEnabled = true; 65 | popup.Child = this; 66 | this.Height = appView.VisibleBounds.Height; 67 | this.Width = appView.VisibleBounds.Width; 68 | if (CommonLibrary.DeviceInfoHelper.IsStatusBarPresent) 69 | { 70 | this.Margin = new Thickness(0, 24, 0, 0); 71 | } 72 | //popup.VerticalOffset = Window.Current.Bounds.Height / 2; 73 | 74 | EventHandler PageNavHelper_BeforeBackRequest = (s, e) => 75 | { 76 | if (popup.IsOpen) 77 | { 78 | e.Handled = true; 79 | popup.IsOpen = false; 80 | } 81 | }; 82 | 83 | TypedEventHandler handler = (s, e) => 84 | { 85 | try 86 | { 87 | if (popup.IsOpen) 88 | { 89 | this.Height = appView.VisibleBounds.Height; 90 | this.Width = appView.VisibleBounds.Width; 91 | } 92 | } 93 | catch (Exception ex) 94 | { 95 | // ignored 96 | Debug.WriteLine(ex); 97 | } 98 | }; 99 | 100 | TappedEventHandler tapped = (s, e) => 101 | { 102 | if (popup.IsOpen) 103 | { 104 | //popup.IsOpen = false; 105 | } 106 | }; 107 | 108 | popup.Opened += (s, e) => 109 | { 110 | this.Visibility = Visibility.Visible; 111 | mask_grid.Tapped += tapped; 112 | appView.VisibleBoundsChanged += handler; 113 | //PageNavHelper.BeforeFrameBackRequest += PageNavHelper_BeforeBackRequest; 114 | }; 115 | 116 | popup.Closed += (s, e) => 117 | { 118 | this.Visibility = Visibility.Collapsed; 119 | mask_grid.Tapped -= tapped; 120 | appView.VisibleBoundsChanged -= handler; 121 | //PageNavHelper.BeforeFrameBackRequest -= PageNavHelper_BeforeBackRequest; 122 | }; 123 | 124 | popup.IsOpen = true; 125 | } 126 | 127 | private async void Button_Click(object sender, RoutedEventArgs e) 128 | { 129 | Button btn = sender as Button; 130 | StorageFile photo = null; 131 | if (btn.Content.ToString() == "Take a photo") 132 | { 133 | photo = await GetPhotoByCameraCapture(); 134 | } 135 | else 136 | { 137 | photo = await GetPhotoByPictureLibrary(); 138 | } 139 | 140 | if (photo != null) 141 | { 142 | CropImageControl.SourceImageFile = photo; 143 | } 144 | } 145 | 146 | private async Task GetPhotoByPictureLibrary() 147 | { 148 | FileOpenPicker openPicker = new FileOpenPicker(); 149 | openPicker.ViewMode = PickerViewMode.Thumbnail; 150 | openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; 151 | openPicker.FileTypeFilter.Add(".jpg"); 152 | openPicker.FileTypeFilter.Add(".jpeg"); 153 | openPicker.FileTypeFilter.Add(".png"); 154 | openPicker.FileTypeFilter.Add(".bmp"); 155 | 156 | return await openPicker.PickSingleFileAsync(); 157 | } 158 | 159 | private async Task GetPhotoByCameraCapture() 160 | { 161 | var cameraCaptureUI = new CameraCaptureUI(); 162 | cameraCaptureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg; 163 | cameraCaptureUI.PhotoSettings.AllowCropping = false; 164 | 165 | var photo = await cameraCaptureUI.CaptureFileAsync(CameraCaptureUIMode.Photo); 166 | 167 | if (photo != null) 168 | { 169 | using (var stream = await photo.OpenAsync(FileAccessMode.ReadWrite)) 170 | { 171 | //旋转图片 172 | await BitmapHelper.RotateCaptureImageByDisplayInformationAutoRotationPreferences(stream, stream); 173 | } 174 | } 175 | 176 | 177 | return photo; 178 | } 179 | 180 | public async Task WriteToFile(WriteableBitmap wb) 181 | { 182 | SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, wb.PixelWidth, wb.PixelHeight); 183 | softwareBitmap.CopyFromBuffer(wb.PixelBuffer); 184 | string fileName = Path.GetRandomFileName() + ".png"; 185 | StorageFile file = null; 186 | if (softwareBitmap != null) 187 | { 188 | // save image file to cache 189 | file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists); 190 | using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite)) 191 | { 192 | BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); 193 | encoder.SetSoftwareBitmap(softwareBitmap); 194 | await encoder.FlushAsync(); 195 | } 196 | } 197 | return file; 198 | } 199 | 200 | private async void btn_OK_Tapped(object sender, TappedRoutedEventArgs e) 201 | { 202 | WriteableBitmap wb = (WriteableBitmap)await CropImageControl.GetCropImageSource(); 203 | StorageFile file = await WriteToFile(wb); 204 | 205 | if (PictureCrop_HandlerEvent != null) 206 | PictureCrop_HandlerEvent(file); 207 | //Popup p = new Popup(); 208 | //Image image = new Image(); 209 | //image.Source = await CropImageControl.GetCropImageSource(); 210 | //p.Child = image; 211 | //p.IsOpen = true; 212 | 213 | if (popup.IsOpen) 214 | { 215 | popup.IsOpen = false; 216 | } 217 | 218 | e.Handled = true; 219 | } 220 | 221 | private void btn_Cancel_Tapped(object sender, TappedRoutedEventArgs e) 222 | { 223 | if (popup.IsOpen) 224 | { 225 | popup.IsOpen = false; 226 | } 227 | } 228 | 229 | private void mask_grid_SizeChanged(object sender, SizeChangedEventArgs e) 230 | { 231 | this.btn_OK.Width = this.ActualWidth / 2; 232 | this.btn_Cancel.Width = this.ActualWidth / 2; 233 | } 234 | 235 | private void UserControl_Unloaded(object sender, RoutedEventArgs e) 236 | { 237 | PictureCrop_HandlerEvent = null; 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PictureEditor.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 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 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PictureEditor.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary; 2 | using Microsoft.Graphics.Canvas; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Runtime.InteropServices.WindowsRuntime; 9 | using System.Threading.Tasks; 10 | using Windows.Foundation; 11 | using Windows.Foundation.Collections; 12 | using Windows.Graphics.Imaging; 13 | using Windows.Storage; 14 | using Windows.Storage.AccessCache; 15 | using Windows.Storage.FileProperties; 16 | using Windows.Storage.Streams; 17 | using Windows.UI; 18 | using Windows.UI.Core; 19 | using Windows.UI.Input.Inking; 20 | using Windows.UI.ViewManagement; 21 | using Windows.UI.Xaml; 22 | using Windows.UI.Xaml.Controls; 23 | using Windows.UI.Xaml.Controls.Primitives; 24 | using Windows.UI.Xaml.Data; 25 | using Windows.UI.Xaml.Input; 26 | using Windows.UI.Xaml.Media; 27 | using Windows.UI.Xaml.Media.Imaging; 28 | using Windows.UI.Xaml.Navigation; 29 | 30 | // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 31 | 32 | namespace UWPToolkit.Controls 33 | { 34 | public sealed partial class PictureEditor : UserControl 35 | { 36 | public delegate void OK_Handler(StorageFile file); 37 | public OK_Handler OK_HandlerEvent; 38 | 39 | public delegate void Cancel_Handler(StorageFile file); 40 | public Cancel_Handler Cancel_HandlerEvent; 41 | 42 | StorageFile sourcefile; 43 | StorageFile finishfile; 44 | int DrawSize; 45 | 46 | WriteableBitmap sourceImage; 47 | StorageFolder storageFolder; 48 | 49 | bool Isfile = false; 50 | 51 | string Url; 52 | public PictureEditor(StorageFile file) 53 | { 54 | this.InitializeComponent(); 55 | this.InitializeComponent(); 56 | InitPen(); 57 | this.sourcefile = file; 58 | Isfile = true; 59 | } 60 | public PictureEditor(string Url) 61 | { 62 | this.InitializeComponent(); 63 | InitPen(); 64 | this.Url = Url; 65 | Isfile = false; 66 | } 67 | private void InitPen() 68 | { 69 | Clear(); 70 | 71 | ink_canvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch | CoreInputDeviceTypes.Pen; 72 | 73 | //InkDrawingAttributes attr = new InkDrawingAttributes(); 74 | //attr.Color = Colors.Red; 75 | //attr.IgnorePressure = true; 76 | //attr.PenTip = PenTipShape.Circle; 77 | //attr.Size = new Size(4, 10); 78 | //attr.PenTipTransform = Matrix3x2.CreateRotation((float)(70 * Math.PI / 180)); 79 | //ink_canvas.InkPresenter.UpdateDefaultDrawingAttributes(attr) 80 | 81 | //inktoolbar.TargetInkCanvas = ink_canvas; 82 | if (DeviceInfoHelper.IsMobileFamily) 83 | { 84 | DrawSize = (int)ApplicationView.GetForCurrentView().VisibleBounds.Width - 10; 85 | 86 | inktoolbar.PenSize = new Size(2, 5); 87 | //inktoolbar.PenColor = Colors.Red; 88 | } 89 | else 90 | { 91 | DrawSize = 500; 92 | 93 | inktoolbar.PenSize = new Size(4, 10); 94 | //inktoolbar.PenColor = Colors.Red; 95 | } 96 | 97 | 98 | img_grid.Height = DrawSize; 99 | img_grid.Width = DrawSize; 100 | } 101 | async Task InitDrawArea() 102 | { 103 | sourceImage = await ImageHelper.StorageFileToWriteableBitmap(sourcefile); 104 | img.Source = sourceImage; 105 | 106 | if (sourceImage.PixelHeight != sourceImage.PixelWidth) 107 | { 108 | double ratio1, ratio2; 109 | ratio1 = (double)sourceImage.PixelWidth / (double)DrawSize; 110 | ratio2 = (double)sourceImage.PixelHeight / (double)DrawSize; 111 | 112 | if (ratio1 > ratio2) 113 | { 114 | ink_canvas.Height = sourceImage.PixelHeight / ratio1; 115 | ink_canvas.Width = DrawSize; 116 | } 117 | else 118 | { 119 | ink_canvas.Height = DrawSize; 120 | ink_canvas.Width = sourceImage.PixelWidth / ratio2; 121 | } 122 | } 123 | 124 | } 125 | 126 | public async void InitFromUrl(string imageUrl) 127 | { 128 | ProgressAction(true); 129 | 130 | if (await StorageHelper.FileExistsAsync(imageUrl)) 131 | { 132 | this.sourcefile = await StorageHelper.TryGetFileFromPathAsync(imageUrl); 133 | 134 | await InitDrawArea(); 135 | 136 | ProgressAction(false); 137 | 138 | return; 139 | } 140 | 141 | var tcs = new TaskCompletionSource(); 142 | var storageManager = await LocalCacheManager.InitializeAsync(StorageFolderType.Pictures); 143 | 144 | DownloadHelper.DownloadAsync(imageUrl, storageManager.CurrentFolder, async (path, url) => 145 | { 146 | if (imageUrl == url) 147 | { 148 | this.sourcefile = await StorageHelper.TryGetFileFromPathAsync(path); 149 | 150 | await InitDrawArea(); 151 | } 152 | else 153 | { 154 | 155 | } 156 | 157 | ProgressAction(false); 158 | }); 159 | } 160 | 161 | private async void ProgressAction(bool si) 162 | { 163 | if (si) 164 | { 165 | 166 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => 167 | { 168 | ringGrid.Visibility = Visibility.Visible; 169 | ring.IsActive = true; 170 | }); 171 | } 172 | else 173 | { 174 | 175 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => 176 | { 177 | ringGrid.Visibility = Visibility.Collapsed; 178 | ring.IsActive = false; 179 | }); 180 | } 181 | } 182 | 183 | Popup popup; 184 | public async void Show() 185 | { 186 | if (Isfile) 187 | { 188 | await InitDrawArea(); 189 | } 190 | else 191 | { 192 | InitFromUrl(Url); 193 | } 194 | 195 | var appView = ApplicationView.GetForCurrentView(); 196 | 197 | popup = new Popup(); 198 | appView.VisibleBoundsChanged += AppView_VisibleBoundsChanged; 199 | //popup.SizeChanged += Popup_SizeChanged; 200 | //popup.IsLightDismissEnabled = true; 201 | popup.Child = this; 202 | this.Height = appView.VisibleBounds.Height; 203 | this.Width = appView.VisibleBounds.Width; 204 | if (CommonLibrary.DeviceInfoHelper.IsStatusBarPresent) 205 | { 206 | this.Margin = new Thickness(0, 24, 0, 0); 207 | } 208 | //popup.VerticalOffset = Window.Current.Bounds.Height / 2; 209 | 210 | EventHandler PageNavHelper_BeforeBackRequest = (s, e) => 211 | { 212 | if (popup.IsOpen) 213 | { 214 | e.Handled = true; 215 | popup.IsOpen = false; 216 | } 217 | }; 218 | 219 | TypedEventHandler handler = (s, e) => 220 | { 221 | try 222 | { 223 | if (popup.IsOpen) 224 | { 225 | this.Height = appView.VisibleBounds.Height; 226 | this.Width = appView.VisibleBounds.Width; 227 | } 228 | } 229 | catch (Exception ex) 230 | { 231 | // ignored 232 | Debug.WriteLine(ex); 233 | } 234 | }; 235 | 236 | TappedEventHandler tapped = (s, e) => 237 | { 238 | if (popup.IsOpen) 239 | { 240 | popup.IsOpen = false; 241 | } 242 | }; 243 | 244 | popup.Opened += (s, e) => 245 | { 246 | this.Visibility = Visibility.Visible; 247 | //mask_grid.Tapped += tapped; 248 | appView.VisibleBoundsChanged += handler; 249 | //PageNavHelper.BeforeFrameBackRequest += PageNavHelper_BeforeBackRequest; 250 | }; 251 | 252 | popup.Closed += (s, e) => 253 | { 254 | this.Visibility = Visibility.Collapsed; 255 | //mask_grid.Tapped -= tapped; 256 | appView.VisibleBoundsChanged -= handler; 257 | //PageNavHelper.BeforeFrameBackRequest -= PageNavHelper_BeforeBackRequest; 258 | appView.VisibleBoundsChanged -= AppView_VisibleBoundsChanged; 259 | }; 260 | 261 | popup.IsOpen = true; 262 | } 263 | private void AppView_VisibleBoundsChanged(ApplicationView sender, object args) 264 | { 265 | //sv.Width = sender.VisibleBounds.Width; 266 | //sv.Height = sender.VisibleBounds.Height; 267 | } 268 | private async void CropButton_Click(object sender, RoutedEventArgs e) 269 | { 270 | ProgressAction(true); 271 | StorageFile file = await SaveDoodle(); 272 | ProgressAction(false); 273 | 274 | using (IRandomAccessStream fileStream = await sourcefile.OpenAsync(Windows.Storage.FileAccessMode.Read)) 275 | { 276 | BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream); 277 | 278 | //图片太小就不用截图了 279 | if (decoder.PixelHeight > 88 && decoder.PixelWidth > 88) 280 | { 281 | PictureCropControl cropPic = new PictureCropControl(file); 282 | cropPic.PictureCrop_HandlerEvent += PictureCrop_HandlerEvent; 283 | cropPic.Show(); 284 | } 285 | } 286 | } 287 | 288 | private async void PictureCrop_HandlerEvent(StorageFile file) 289 | { 290 | sourcefile = file; 291 | await InitDrawArea(); 292 | } 293 | 294 | private async void SaveButton_Click(object sender, RoutedEventArgs e) 295 | { 296 | ProgressAction(true); 297 | await SaveDoodle(); 298 | ProgressAction(false); 299 | 300 | Clear(); 301 | popup.IsOpen = false; 302 | 303 | OK_HandlerEvent?.Invoke(finishfile); 304 | } 305 | 306 | public async Task SaveDoodle() 307 | { 308 | storageFolder = KnownFolders.SavedPictures; 309 | //var file = await storageFolder.CreateFileAsync("ink.png", CreationCollisionOption.ReplaceExisting); 310 | 311 | if (ink_canvas.InkPresenter.StrokeContainer.GetStrokes().Count == 0) 312 | { 313 | finishfile = sourcefile; 314 | } 315 | else 316 | { 317 | CanvasDevice device = CanvasDevice.GetSharedDevice(); 318 | CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int)ink_canvas.ActualWidth, (int)ink_canvas.ActualHeight, 96); 319 | renderTarget.SetPixelBytes(new byte[(int)ink_canvas.ActualWidth * 4 * (int)ink_canvas.ActualHeight]); 320 | using (var ds = renderTarget.CreateDrawingSession()) 321 | { 322 | IReadOnlyList inklist = ink_canvas.InkPresenter.StrokeContainer.GetStrokes(); 323 | 324 | Debug.WriteLine("Ink_Strokes Count: " + inklist.Count); 325 | //ds.Clear(Colors.White); 326 | ds.DrawInk(inklist); 327 | } 328 | 329 | //直接存的ink 330 | //using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) 331 | //{ 332 | // await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f); 333 | //} 334 | 335 | var inkpixel = renderTarget.GetPixelBytes(); 336 | //var color = renderTarget.GetPixelColors(); 337 | 338 | WriteableBitmap bmp = new WriteableBitmap((int)ink_canvas.ActualWidth, (int)ink_canvas.ActualHeight); 339 | Stream s = bmp.PixelBuffer.AsStream(); 340 | s.Seek(0, SeekOrigin.Begin); 341 | s.Write(inkpixel, 0, (int)ink_canvas.ActualWidth * 4 * (int)ink_canvas.ActualHeight); 342 | 343 | WriteableBitmap ink_wb = await ImageProcessing.ResizeByDecoderAsync(bmp, sourceImage.PixelWidth, sourceImage.PixelHeight, true); 344 | //await SaveToFile("ink_scale.png", ink_wb); 345 | WriteableBitmap combine_wb = await ImageProcessing.CombineAsync(sourceImage, ink_wb); 346 | finishfile = await WriteableBitmapSaveToFile(combine_wb); 347 | } 348 | Clear(); 349 | return finishfile; 350 | } 351 | 352 | private void Clear() 353 | { 354 | ink_canvas.InkPresenter.StrokeContainer?.Clear(); 355 | } 356 | 357 | public async Task WriteableBitmapSaveToFile(WriteableBitmap combine_wb) 358 | { 359 | if (combine_wb == null) 360 | return null; 361 | 362 | var storageManager = await LocalCacheManager.InitializeAsync(StorageFolderType.Pictures); 363 | var filename = "ink" + SecurityHelper.MD5(DateTime.Now.ToString(("yyyy-MM-dd HH:mm:ss fff"))) + ".jpg"; 364 | var path = Path.Combine(storageManager.CurrentFolder.Path, filename); 365 | var md5Name = DownloadHelper.GetDownloadedLocalFileName(path); 366 | StorageFile file = await storageManager.CurrentFolder.CreateFileAsync(md5Name, CreationCollisionOption.ReplaceExisting); 367 | using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) 368 | { 369 | //await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f); 370 | 371 | SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, combine_wb.PixelWidth, combine_wb.PixelHeight); 372 | softwareBitmap.CopyFromBuffer(combine_wb.PixelBuffer); 373 | 374 | BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, fileStream); 375 | encoder.SetSoftwareBitmap(softwareBitmap); 376 | await encoder.FlushAsync(); 377 | } 378 | return file; 379 | } 380 | 381 | private void CancelButton_Click(object sender, RoutedEventArgs e) 382 | { 383 | Clear(); 384 | popup.IsOpen = false; 385 | Cancel_HandlerEvent?.Invoke(sourcefile); 386 | } 387 | 388 | private void UserControl_Unloaded(object sender, RoutedEventArgs e) 389 | { 390 | OK_HandlerEvent = null; 391 | Cancel_HandlerEvent = null; 392 | } 393 | 394 | private void inktoolbar_Loaded(object sender, RoutedEventArgs e) 395 | { 396 | inktoolbar.TargetInkCanvas = this.ink_canvas; 397 | inktoolbar.HighlighterVisibility = Visibility.Collapsed; 398 | inktoolbar.ButtonHeight = 60; 399 | inktoolbar.ButtonWidth = 60; 400 | } 401 | } 402 | } 403 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PreviewPictureControl.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /UWPToolkit/Controls/PreviewPictureControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Runtime.InteropServices.WindowsRuntime; 8 | using System.Threading.Tasks; 9 | using Windows.Foundation; 10 | using Windows.Foundation.Collections; 11 | using Windows.Graphics.Imaging; 12 | using Windows.Storage; 13 | using Windows.Storage.Streams; 14 | using Windows.UI.ViewManagement; 15 | using Windows.UI.Xaml; 16 | using Windows.UI.Xaml.Controls; 17 | using Windows.UI.Xaml.Controls.Primitives; 18 | using Windows.UI.Xaml.Data; 19 | using Windows.UI.Xaml.Input; 20 | using Windows.UI.Xaml.Media; 21 | using Windows.UI.Xaml.Media.Imaging; 22 | using Windows.UI.Xaml.Navigation; 23 | using Windows.Web.Http; 24 | using static CommonLibrary.FileHelper; 25 | 26 | 27 | // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 28 | 29 | namespace UWPToolkit.Controls 30 | { 31 | public sealed partial class PreviewPictureControl : UserControl 32 | { 33 | public PreviewPictureControl(StorageFile file) 34 | { 35 | this.InitializeComponent(); 36 | _file = file; 37 | ShowType = 0; 38 | 39 | //this.Img.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Scale | ManipulationModes.TranslateInertia; 40 | this.sv.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Scale | ManipulationModes.TranslateInertia; 41 | this.sv.ManipulationCompleted += Img_ManipulationCompleted; 42 | this.sv.ManipulationDelta += Img_ManipulationDelta; 43 | this.sv.ManipulationStarted += Img_ManipulationStarted; 44 | 45 | Init(); 46 | } 47 | 48 | private async void Init() 49 | { 50 | await InitSize(); 51 | this.Img.Source = await ImageHelper.StorageFileToWriteableBitmap(_file); 52 | } 53 | 54 | /// 55 | /// 0:null 56 | /// 1:长按 57 | /// 2:右键 58 | /// 59 | int ShowType; 60 | 61 | private StorageFile _file; 62 | 63 | Popup popup; 64 | public void Show() 65 | { 66 | var appView = ApplicationView.GetForCurrentView(); 67 | 68 | 69 | appView.VisibleBoundsChanged += AppView_VisibleBoundsChanged; 70 | //popup.SizeChanged += Popup_SizeChanged; 71 | //popup.IsLightDismissEnabled = true; 72 | popup = new Popup(); 73 | 74 | //Popup popup = new Popup(); 75 | popup.Child = this; 76 | 77 | this.Height = appView.VisibleBounds.Height; 78 | this.Width = appView.VisibleBounds.Width; 79 | if (CommonLibrary.DeviceInfoHelper.IsStatusBarPresent) 80 | { 81 | this.Margin = new Thickness(0, 24, 0, 0); 82 | } 83 | //popup.VerticalOffset = Window.Current.Bounds.Height / 2; 84 | 85 | EventHandler PageNavHelper_BeforeBackRequest = (s, e) => 86 | { 87 | if (popup.IsOpen) 88 | { 89 | e.Handled = true; 90 | popup.IsOpen = false; 91 | } 92 | }; 93 | 94 | TypedEventHandler handler = (s, e) => 95 | { 96 | try 97 | { 98 | if (popup.IsOpen) 99 | { 100 | this.Height = appView.VisibleBounds.Height; 101 | this.Width = appView.VisibleBounds.Width; 102 | } 103 | } 104 | catch (Exception ex) 105 | { 106 | // ignored 107 | Debug.WriteLine(ex); 108 | } 109 | }; 110 | 111 | popup.Opened += (s, e) => 112 | { 113 | this.Visibility = Visibility.Visible; 114 | 115 | appView.VisibleBoundsChanged += handler; 116 | //PageNavHelper.BeforeFrameBackRequest += PageNavHelper_BeforeBackRequest; 117 | }; 118 | 119 | popup.Closed += (s, e) => 120 | { 121 | this.Visibility = Visibility.Collapsed; 122 | 123 | appView.VisibleBoundsChanged -= handler; 124 | //PageNavHelper.BeforeFrameBackRequest -= PageNavHelper_BeforeBackRequest; 125 | appView.VisibleBoundsChanged -= AppView_VisibleBoundsChanged; 126 | this.sv.ManipulationCompleted -= Img_ManipulationCompleted; 127 | this.sv.ManipulationDelta -= Img_ManipulationDelta; 128 | this.sv.ManipulationStarted -= Img_ManipulationStarted; 129 | }; 130 | 131 | popup.IsOpen = true; 132 | } 133 | 134 | private void AppView_VisibleBoundsChanged(ApplicationView sender, object args) 135 | { 136 | sv.Width = sender.VisibleBounds.Width; 137 | sv.Height = sender.VisibleBounds.Height; 138 | } 139 | 140 | async Task InitSize() 141 | { 142 | try 143 | { 144 | // this._file = await StorageHelper.TryGetFileFromPathAsync(path); 145 | 146 | if (this._file == null) return; 147 | 148 | var appView = ApplicationView.GetForCurrentView(); 149 | 150 | //this.gifViewer.Visibility = Visibility.Collapsed; 151 | this.Img.Visibility = Visibility.Visible; 152 | 153 | IInputStream inputStream = await this._file.OpenReadAsync(); 154 | IRandomAccessStream memStream = new InMemoryRandomAccessStream(); 155 | await RandomAccessStream.CopyAsync(inputStream, memStream); 156 | BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream); 157 | SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); 158 | 159 | if (softwareBitmap == null) 160 | return; 161 | SoftwareBitmapSource source = new SoftwareBitmapSource(); 162 | await source.SetBitmapAsync(softwareBitmap); 163 | 164 | if (softwareBitmap.PixelHeight > appView.VisibleBounds.Height || softwareBitmap.PixelWidth > appView.VisibleBounds.Width) 165 | { 166 | double ratio1, ratio2; 167 | ratio1 = (double)softwareBitmap.PixelWidth / (double)appView.VisibleBounds.Width; 168 | ratio2 = (double)softwareBitmap.PixelHeight / (double)appView.VisibleBounds.Height; 169 | 170 | if (ratio1 > ratio2) 171 | { 172 | this.Img.Width = appView.VisibleBounds.Width; 173 | this.Img.Height = softwareBitmap.PixelHeight / ratio1; 174 | if (ratio1 > 1.0) 175 | this.sv.MaxZoomFactor *= (float)ratio1; 176 | } 177 | else 178 | { 179 | this.Img.Width = softwareBitmap.PixelWidth / ratio2; 180 | this.Img.Height = appView.VisibleBounds.Height; 181 | if (ratio2 > 1.0) 182 | this.sv.MaxZoomFactor *= (float)ratio2; 183 | } 184 | } 185 | else 186 | { 187 | this.Img.Width = softwareBitmap.PixelWidth; 188 | this.Img.Height = softwareBitmap.PixelHeight; 189 | } 190 | 191 | this.sv.Width = appView.VisibleBounds.Width; 192 | this.sv.Height = appView.VisibleBounds.Height; 193 | } 194 | catch (Exception ex) 195 | { 196 | Debug.WriteLine(ex.ToString()); 197 | } 198 | } 199 | private void sv_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) 200 | { 201 | var appView = ApplicationView.GetForCurrentView(); 202 | //if (this.sv.Height < appView.VisibleBounds.Height && this.sv.Width < appView.VisibleBounds.Width) 203 | //{ 204 | // this.sv.Width = appView.VisibleBounds.Width; 205 | // this.sv.Height = appView.VisibleBounds.Height; 206 | //} 207 | //if (this.Img.Height < appView.VisibleBounds.Height && this.Img.Width < appView.VisibleBounds.Width) 208 | //{ 209 | // double ratio1, ratio2; 210 | // ratio1 = (double)this.Img.Width / (double)appView.VisibleBounds.Width; 211 | // ratio2 = (double)this.Img.Height / (double)appView.VisibleBounds.Height; 212 | 213 | // if (ratio1 > ratio2) 214 | // { 215 | // this.Img.Width = appView.VisibleBounds.Width; 216 | // this.Img.Height = this.Img.Height / ratio1; 217 | // } 218 | // else 219 | // { 220 | // this.Img.Width = this.Img.Width / ratio2; 221 | // this.Img.Height = appView.VisibleBounds.Height; 222 | // } 223 | // //this.sv.Width = appView.VisibleBounds.Width; 224 | // //this.sv.Height = appView.VisibleBounds.Height; 225 | //} 226 | } 227 | 228 | int tapped_times = 0; 229 | 230 | private void Img_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) 231 | { 232 | tapped_times = 2; 233 | 234 | if (this.sv.ZoomFactor == this.sv.MinZoomFactor) 235 | { 236 | var appView = ApplicationView.GetForCurrentView(); 237 | 238 | var point = e.GetPosition(Window.Current.Content); 239 | var point1 = e.GetPosition(Img); 240 | var point2 = e.GetPosition(sv); 241 | 242 | double X, Y, deltaX, deltaY; 243 | deltaX = (appView.VisibleBounds.Width - Img.ActualWidth) / 2; 244 | deltaY = (appView.VisibleBounds.Height - Img.ActualHeight) / 2; 245 | X = point.X - deltaX; 246 | Y = point.Y - deltaY; 247 | 248 | this.sv.ZoomToFactor(this.sv.MaxZoomFactor); 249 | 250 | sv.ScrollToHorizontalOffset(X * (this.sv.MaxZoomFactor - 1) - deltaX); 251 | sv.ScrollToVerticalOffset(Y * (this.sv.MaxZoomFactor - 1) - deltaY); 252 | } 253 | else 254 | { 255 | this.sv.ZoomToFactor(this.sv.MinZoomFactor); 256 | } 257 | 258 | 259 | e.Handled = true; 260 | tapped_times = 0; 261 | } 262 | 263 | private async void grid_Tapped(object sender, TappedRoutedEventArgs e) 264 | { 265 | tapped_times = 1; 266 | await Task.Delay(200); 267 | 268 | if (popup.IsOpen && tapped_times == 1) 269 | { 270 | popup.IsOpen = false; 271 | } 272 | e.Handled = false; 273 | tapped_times = 0; 274 | } 275 | 276 | private async void Img_Tapped(object sender, TappedRoutedEventArgs e) 277 | { 278 | tapped_times = 1; 279 | await Task.Delay(200); 280 | 281 | if (popup.IsOpen && tapped_times == 1) 282 | { 283 | popup.IsOpen = false; 284 | } 285 | e.Handled = false; 286 | } 287 | 288 | private void Img_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) 289 | { 290 | // dim the image while panning 291 | //this.Img.Opacity = 0.4; 292 | } 293 | private void Img_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) 294 | { 295 | //this.Transform.TranslateX += e.Delta.Translation.X; 296 | //this.Transform.TranslateY += e.Delta.Translation.Y; 297 | sv.ScrollToHorizontalOffset(sv.HorizontalOffset - e.Delta.Translation.X); 298 | sv.ScrollToVerticalOffset(sv.VerticalOffset - e.Delta.Translation.Y); 299 | e.Handled = false; 300 | } 301 | 302 | void Img_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) 303 | { 304 | // reset the Opacity 305 | //this.Img.Opacity = 1; 306 | } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /UWPToolkit/MasterPage.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /UWPToolkit/MasterPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using UWPToolkit.Pages; 7 | using Windows.Foundation; 8 | using Windows.Foundation.Collections; 9 | using Windows.UI.Core; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | //“空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 上有介绍 19 | 20 | namespace UWPToolkit 21 | { 22 | /// 23 | /// 可用于自身或导航至 Frame 内部的空白页。 24 | /// 25 | public sealed partial class MasterPage : Page 26 | { 27 | private static MasterPage _instance = null; 28 | public MasterPage() 29 | { 30 | this.InitializeComponent(); 31 | _instance = this; 32 | this.Right_Frame.Navigate(typeof(Page)); 33 | } 34 | 35 | private void Picture_Editor_Tapped(object sender, TappedRoutedEventArgs e) 36 | { 37 | this.Right_Frame.Visibility = Visibility.Visible; 38 | this.Right_Frame.Navigate(typeof(PictureEditorPage)); 39 | } 40 | 41 | private void Picture_Preview_Tapped(object sender, TappedRoutedEventArgs e) 42 | { 43 | this.Right_Frame.Visibility = Visibility.Visible; 44 | this.Right_Frame.Navigate(typeof(PreviewPicturePage)); 45 | } 46 | 47 | private GridLength _glLeft = new GridLength(720d); 48 | private void Page_SizeChanged(object sender, SizeChangedEventArgs e) 49 | { 50 | GridLength glAlign = new GridLength(e.NewSize.Width); 51 | if (this.ActualWidth < 720) 52 | { 53 | this.Left_Col.Width = glAlign; 54 | this.Right_Col.Width = glAlign; 55 | this.Right_Frame.SetValue(Grid.ColumnProperty, 0); 56 | } 57 | else 58 | { 59 | this.Left_Col.Width = new GridLength(2, GridUnitType.Star); 60 | this.Right_Col.Width = new GridLength(3, GridUnitType.Star); 61 | this.Right_Frame.SetValue(Grid.ColumnProperty, 2); 62 | } 63 | } 64 | 65 | public static void BackRequest() 66 | { 67 | if (_instance.Right_Frame.CanGoBack) 68 | { 69 | _instance.Right_Frame.GoBack(); 70 | } 71 | 72 | _instance.Right_Frame.Visibility = Visibility.Collapsed; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /UWPToolkit/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | UWPToolkit 7 | weiql 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /UWPToolkit/Pages/PictureEditorPage.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /UWPToolkit/Pages/PictureEditorPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices.WindowsRuntime; 7 | using System.Threading.Tasks; 8 | using UWPToolkit.Controls; 9 | using Windows.Foundation; 10 | using Windows.Foundation.Collections; 11 | using Windows.Storage; 12 | using Windows.Storage.Pickers; 13 | using Windows.UI.Core; 14 | using Windows.UI.Xaml; 15 | using Windows.UI.Xaml.Controls; 16 | using Windows.UI.Xaml.Controls.Primitives; 17 | using Windows.UI.Xaml.Data; 18 | using Windows.UI.Xaml.Input; 19 | using Windows.UI.Xaml.Media; 20 | using Windows.UI.Xaml.Navigation; 21 | 22 | // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介绍 23 | 24 | namespace UWPToolkit.Pages 25 | { 26 | /// 27 | /// 可用于自身或导航至 Frame 内部的空白页。 28 | /// 29 | public sealed partial class PictureEditorPage : BasePage 30 | { 31 | public PictureEditorPage() 32 | { 33 | this.InitializeComponent(); 34 | } 35 | 36 | private async void Select_Picture(object sender, TappedRoutedEventArgs e) 37 | { 38 | var file = await FileHelper.GetSinglePictureFileFromAlbumAsync("jpeg,jpg,png,gif"); 39 | if (file == null) 40 | return; 41 | PictureEditor it = new PictureEditor(file); 42 | it.OK_HandlerEvent += PictureEditor_OK_HandlerEvent; 43 | it.Show(); 44 | } 45 | 46 | private async void PictureEditor_OK_HandlerEvent(StorageFile file) 47 | { 48 | img.Source = await ImageHelper.StorageFileToWriteableBitmap(file); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /UWPToolkit/Pages/PreviewPicturePage.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /UWPToolkit/Pages/PreviewPicturePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommonLibrary; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices.WindowsRuntime; 7 | using UWPToolkit.Controls; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介绍 19 | 20 | namespace UWPToolkit.Pages 21 | { 22 | /// 23 | /// 可用于自身或导航至 Frame 内部的空白页。 24 | /// 25 | public sealed partial class PreviewPicturePage : BasePage 26 | { 27 | public PreviewPicturePage() 28 | { 29 | this.InitializeComponent(); 30 | } 31 | 32 | private async void Select_Picture(object sender, TappedRoutedEventArgs e) 33 | { 34 | var file = await FileHelper.GetSinglePictureFileFromAlbumAsync("jpeg,jpg,png,gif"); 35 | if (file == null) 36 | return; 37 | img.Source = await ImageHelper.StorageFileToWriteableBitmap(file); 38 | 39 | PreviewPictureControl previewPic = new PreviewPictureControl(file); 40 | 41 | previewPic.Show(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /UWPToolkit/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UWPToolkit")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UWPToolkit")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /UWPToolkit/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /UWPToolkit/Styles/Dictionary.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | #ff00b4ff 9 | #99000000 10 | #ff009de2 11 | #ff0082bd 12 | #FFE0EEFF 13 | #ff424242 14 | #ff525252 15 | #ffffffff 16 | #fffe5200 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | #222222 47 | #666666 48 | Blue 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 63 | 64 | 70 | 71 | 72 | 77 | 78 | 79 | 84 | 85 | 86 | 92 | 93 | 94 | 100 | 101 | 106 | 107 | 111 | 112 | -------------------------------------------------------------------------------- /UWPToolkit/UWPToolkit.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {A82469BE-A664-4D1E-9511-210EC2A631F0} 8 | AppContainerExe 9 | Properties 10 | UWPToolkit 11 | UWPToolkit 12 | zh-CN 13 | UAP 14 | 10.0.10586.0 15 | 10.0.10240.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | UWPToolkit_TemporaryKey.pfx 20 | 21 | 22 | true 23 | bin\x86\Debug\ 24 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 25 | ;2008 26 | full 27 | x86 28 | false 29 | prompt 30 | true 31 | 32 | 33 | bin\x86\Release\ 34 | TRACE;NETFX_CORE;WINDOWS_UWP 35 | true 36 | ;2008 37 | pdbonly 38 | x86 39 | false 40 | prompt 41 | true 42 | true 43 | 44 | 45 | true 46 | bin\ARM\Debug\ 47 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 48 | ;2008 49 | full 50 | ARM 51 | false 52 | prompt 53 | true 54 | 55 | 56 | bin\ARM\Release\ 57 | TRACE;NETFX_CORE;WINDOWS_UWP 58 | true 59 | ;2008 60 | pdbonly 61 | ARM 62 | false 63 | prompt 64 | true 65 | true 66 | 67 | 68 | true 69 | bin\x64\Debug\ 70 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 71 | ;2008 72 | full 73 | x64 74 | false 75 | prompt 76 | true 77 | 78 | 79 | bin\x64\Release\ 80 | TRACE;NETFX_CORE;WINDOWS_UWP 81 | true 82 | ;2008 83 | pdbonly 84 | x64 85 | false 86 | prompt 87 | true 88 | true 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | App.xaml 97 | 98 | 99 | 100 | PictureCropControl.xaml 101 | 102 | 103 | PictureEditor.xaml 104 | 105 | 106 | PreviewPictureControl.xaml 107 | 108 | 109 | MasterPage.xaml 110 | 111 | 112 | PictureEditorPage.xaml 113 | 114 | 115 | PreviewPicturePage.xaml 116 | 117 | 118 | 119 | 120 | 121 | Designer 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | MSBuild:Compile 138 | Designer 139 | 140 | 141 | Designer 142 | MSBuild:Compile 143 | 144 | 145 | Designer 146 | MSBuild:Compile 147 | 148 | 149 | Designer 150 | MSBuild:Compile 151 | 152 | 153 | Designer 154 | MSBuild:Compile 155 | 156 | 157 | Designer 158 | MSBuild:Compile 159 | PreserveNewest 160 | 161 | 162 | MSBuild:Compile 163 | Designer 164 | 165 | 166 | Designer 167 | MSBuild:Compile 168 | 169 | 170 | 171 | 172 | {1faa2db6-1203-4df4-ac1a-8ec415f6681d} 173 | CommonLibrary 174 | 175 | 176 | 177 | 178 | False 179 | ..\lib\InkToolbarControl\$(PlatformTarget)\$(Configuration)\Microsoft.Labs.InkToolbarControl.winmd 180 | 181 | 182 | 183 | 14.0 184 | 185 | 186 | 193 | -------------------------------------------------------------------------------- /UWPToolkit/UWPToolkit_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/UWPToolkit/UWPToolkit_TemporaryKey.pfx -------------------------------------------------------------------------------- /UWPToolkit/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.ApplicationInsights": "1.0.0", 4 | "Microsoft.ApplicationInsights.PersistenceChannel": "1.0.0", 5 | "Microsoft.ApplicationInsights.WindowsApps": "1.0.0", 6 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0", 7 | "Win2D.uwp": "1.18.0" 8 | }, 9 | "frameworks": { 10 | "uap10.0": {} 11 | }, 12 | "runtimes": { 13 | "win10-arm": {}, 14 | "win10-arm-aot": {}, 15 | "win10-x86": {}, 16 | "win10-x86-aot": {}, 17 | "win10-x64": {}, 18 | "win10-x64-aot": {} 19 | } 20 | } -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.dll -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.pri: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.pri -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/debug/Microsoft.Labs.InkToolbarControl.winmd -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.dll -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.pri: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.pri -------------------------------------------------------------------------------- /lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/ARM/release/Microsoft.Labs.InkToolbarControl.winmd -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.dll -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.pri: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.pri -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/debug/Microsoft.Labs.InkToolbarControl.winmd -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.dll -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.pri: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.pri -------------------------------------------------------------------------------- /lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoLeeCN/UWP_ToolKit_CommonLibrary/4ac8024a0e1e7fa9bfb20b524a58b6e3f760f654/lib/InkToolbarControl/x86/release/Microsoft.Labs.InkToolbarControl.winmd --------------------------------------------------------------------------------