├── .gitattributes ├── .gitignore ├── LICENSE ├── NWSRMgr.sln └── NWSRMgr ├── App.xaml ├── App.xaml.cs ├── DPIWrapper.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── NWSRMgr.csproj ├── NWSRMgr.ico ├── NWSRMgr.manifest ├── Properties └── PublishProfiles │ ├── Windows (x64).pubxml │ └── Windows (x86).pubxml └── SystemRestore.cs /.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/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 M2-Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NWSRMgr.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29318.209 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NWSRMgr", "NWSRMgr\NWSRMgr.csproj", "{BA575C05-FDAF-465B-9757-A4E8588105F9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BA575C05-FDAF-465B-9757-A4E8588105F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {BA575C05-FDAF-465B-9757-A4E8588105F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {BA575C05-FDAF-465B-9757-A4E8588105F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {BA575C05-FDAF-465B-9757-A4E8588105F9}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {AA575FAB-47DF-4306-ABCC-20ED135CA6FA} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /NWSRMgr/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /NWSRMgr/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | 4 | namespace NWSRMgr 5 | { 6 | /// 7 | /// App.xaml 的交互逻辑 8 | /// 9 | public partial class App : Application 10 | { 11 | private void Application_Startup(object sender, StartupEventArgs e) 12 | { 13 | if (Environment.OSVersion.Version.Major >= 6) 14 | { 15 | StartupUri = new Uri("MainWindow.xaml", UriKind.RelativeOrAbsolute); 16 | } 17 | else 18 | { 19 | MessageBox.Show("本程序只支持Windows Vista以上操作系统", "NWSRMgr"); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NWSRMgr/DPIWrapper.cs: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | 描述:为wpf窗口实现Per-Monitor DPI Aware支持 3 | 维护者:Mouri_Naruto (M2-Team) 4 | 版本:1.1 (2016-08-29) 5 | 基于项目:无 6 | 协议:The MIT License 7 | 用法:在wpf窗口类的构造函数添加 new WpfPerMonitorDPIAwareSupport(this); 8 | 建议的.Net Framework版本:4.0及以后 9 | ***************************************************************************/ 10 | 11 | using System; 12 | using System.Runtime.InteropServices; 13 | using System.Windows; 14 | using System.Windows.Interop; 15 | using System.Windows.Media; 16 | 17 | namespace M2 18 | { 19 | class WpfPerMonitorDPIAwareSupport 20 | { 21 | // 本类私有Win32API定义 22 | #region PrivateWin32 23 | 24 | private const int WM_DPICHANGED = 0x02E0; 25 | 26 | private const long S_OK = 0x00000000L; 27 | private const long E_NOINTERFACE = 0x80004002L; 28 | 29 | [StructLayout(LayoutKind.Sequential)] 30 | private struct RECT 31 | { 32 | public int left; 33 | public int top; 34 | public int right; 35 | public int bottom; 36 | } 37 | 38 | public enum MONITOR_FLAGS 39 | { 40 | MONITOR_DEFAULTTONULL = 0x00000000, 41 | MONITOR_DEFAULTTOPRIMARY = 0x00000001, 42 | MONITOR_DEFAULTTONEAREST = 0x00000002, 43 | } 44 | 45 | public enum MONITOR_DPI_TYPE 46 | { 47 | MDT_EFFECTIVE_DPI = 0, 48 | MDT_ANGULAR_DPI = 1, 49 | MDT_RAW_DPI = 2, 50 | MDT_DEFAULT = MDT_EFFECTIVE_DPI 51 | } 52 | 53 | private ushort LOWORD(uint value) 54 | { 55 | return (ushort)(value & 0xFFFF); 56 | } 57 | private ushort HIWORD(uint value) 58 | { 59 | return (ushort)(value >> 16); 60 | } 61 | 62 | private T PtrToStructure(IntPtr Ptr) 63 | { 64 | return (T)Marshal.PtrToStructure(Ptr, typeof(T)); 65 | } 66 | 67 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 68 | private static extern bool EnableChildWindowDpiMessage( 69 | IntPtr hWnd, 70 | bool bEnable); 71 | 72 | [DllImport("win32u.dll", CharSet = CharSet.Unicode)] 73 | private static extern bool NtUserEnableChildWindowDpiMessage( 74 | IntPtr hWnd, 75 | bool bEnable); 76 | 77 | [DllImport("SHCore.dll", CharSet = CharSet.Unicode, 78 | EntryPoint = "GetDpiForMonitor")] 79 | private static extern long GetDpiForMonitor( 80 | IntPtr hmonitor, 81 | MONITOR_DPI_TYPE dpiType, 82 | ref uint dpiX, 83 | ref uint dpiY); 84 | 85 | // 依据窗口句柄获取显示器句柄 86 | [DllImport("User32.dll")] 87 | private static extern IntPtr MonitorFromWindow( 88 | IntPtr hwnd, MONITOR_FLAGS dwFlags); 89 | 90 | #endregion 91 | 92 | // WPF窗口对象 93 | private Window m_WpfWindow; 94 | 95 | // WPF窗口缩放 96 | private void ScaleWpfWindow(ScaleTransform Scale) 97 | { 98 | VisualTreeHelper.GetChild(m_WpfWindow, 0).SetValue( 99 | FrameworkElement.LayoutTransformProperty, Scale); 100 | } 101 | 102 | // 处理WM_DPICHANGED消息 103 | private IntPtr OnDPIChanged( 104 | IntPtr hWnd, 105 | int message, 106 | IntPtr wParam, 107 | IntPtr lParam, 108 | ref bool handled) 109 | { 110 | if (WM_DPICHANGED == message) 111 | { 112 | uint _wParam = Convert.ToUInt32(wParam.ToInt32()); 113 | 114 | RECT prcNewWindow = PtrToStructure(lParam); 115 | 116 | ScaleTransform Scale = new ScaleTransform( 117 | LOWORD(_wParam) / 96.0, HIWORD(_wParam) / 96.0); 118 | 119 | ScaleWpfWindow(Scale); 120 | 121 | m_WpfWindow.Left = prcNewWindow.left; 122 | m_WpfWindow.Top = prcNewWindow.top; 123 | 124 | m_WpfWindow.Width = prcNewWindow.right - prcNewWindow.left; 125 | m_WpfWindow.Height = prcNewWindow.bottom - prcNewWindow.top; 126 | } 127 | 128 | return IntPtr.Zero; 129 | } 130 | 131 | // WPF窗口Loaded事件处理 132 | private void OnLoaded(object sender, RoutedEventArgs e) 133 | { 134 | IntPtr hWnd = new WindowInteropHelper(m_WpfWindow).Handle; 135 | 136 | // 调用Windows 8.1新增的GetDpiForMonitor获取窗口的DPI 137 | long hr = E_NOINTERFACE; 138 | uint dpiX = 96; uint dpiY = 96; 139 | try 140 | { 141 | hr = GetDpiForMonitor( 142 | MonitorFromWindow( 143 | hWnd, 144 | MONITOR_FLAGS.MONITOR_DEFAULTTONEAREST), 145 | MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, 146 | ref dpiX, 147 | ref dpiY); 148 | } 149 | catch (DllNotFoundException) { } 150 | catch (EntryPointNotFoundException) { } 151 | 152 | // 如获取DPI失败即视本环境不支持Per-Monitor DPI Aware,执行返回 153 | if (S_OK != hr) return; 154 | 155 | // 先通知系统,让系统自动缩放非客户区(至少Win10) 156 | bool bRet = false; 157 | try 158 | { 159 | bRet = EnableChildWindowDpiMessage(hWnd, true); 160 | } 161 | catch (DllNotFoundException) { } 162 | catch (EntryPointNotFoundException) { } 163 | 164 | try 165 | { 166 | if (!bRet) bRet= NtUserEnableChildWindowDpiMessage(hWnd, true); 167 | } 168 | catch (DllNotFoundException) { } 169 | catch (EntryPointNotFoundException) { } 170 | 171 | // 再执行WPF窗口缩放 172 | ScaleTransform Scale = new ScaleTransform( 173 | dpiX / 96.0, dpiY / 96.0); 174 | 175 | ScaleWpfWindow(Scale); 176 | 177 | m_WpfWindow.Width *= Scale.ScaleX; 178 | m_WpfWindow.Height *= Scale.ScaleY; 179 | 180 | // 最后加入WM_DPICHANGED消息处理函数 181 | HwndSource hwndSource = 182 | (HwndSource)PresentationSource.FromVisual(m_WpfWindow); 183 | if (null != hwndSource) 184 | { 185 | hwndSource.AddHook(new HwndSourceHook(OnDPIChanged)); 186 | } 187 | } 188 | 189 | //构造函数 190 | public WpfPerMonitorDPIAwareSupport(Window WpfWindow) 191 | { 192 | m_WpfWindow = WpfWindow; 193 | m_WpfWindow.Loaded += new RoutedEventHandler(OnLoaded); 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /NWSRMgr/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 40 |