OSDN Git Service

#34825 DTXManiaの動作中のみ、電源プランを高パフォーマンス(High Performance)に変更し、終了時に元に戻す機能を追加。
authoryyagi <yyagi@16f42ceb-6dc6-49c8-ba94-f2d53467949d>
Mon, 14 Mar 2016 17:33:32 +0000 (17:33 +0000)
committeryyagi <yyagi@16f42ceb-6dc6-49c8-ba94-f2d53467949d>
Mon, 14 Mar 2016 17:33:32 +0000 (17:33 +0000)
現時点では、この機能をON/OFFする設定機能はなく、必ず高パフォーマンスに変更する。
ただし、Connected Standbyに対応している場合は、この動作を行わない。
Win8.1 x64 デスクトップ機(Connected Standby非対応)と、Win10 x86 タブレット機(Connected Standby対応)で、動作確認済み。

git-svn-id: http://svn.osdn.jp/svnroot/dtxmania/trunk@927 16f42ceb-6dc6-49c8-ba94-f2d53467949d

DTXManiaプロジェクト/コード/全体/CDTXMania.cs
FDK17プロジェクト/FDK19.csproj
FDK17プロジェクト/コード/00.共通/COS.cs
FDK17プロジェクト/コード/00.共通/CPowerPlan.cs [new file with mode: 0644]
FDK17プロジェクト/コード/00.共通/CWin32.cs

index 2fb6eb5..1a8262f 100644 (file)
@@ -343,7 +343,6 @@ namespace DTXMania
                        //---------------------\r
                        #endregion\r
 \r
-\r
                        #region [ Input管理 の初期化 ]\r
                        //---------------------\r
                        Trace.TraceInformation("DirectInput, MIDI入力の初期化を行います。");\r
@@ -888,6 +887,14 @@ namespace DTXMania
                                st.plugin.OnManagedリソースの作成();\r
                                Directory.SetCurrentDirectory(CDTXMania.Instance.strEXEのあるフォルダ);\r
                        }\r
+\r
+                       #region [ 現在の電源プランをバックアップし、HighPerformanceに変更 ]\r
+                       cPowerPlan = new CPowerPlan();\r
+                       cPowerPlan.BackupCurrentPowerPlan();\r
+                       cPowerPlan.ChangeHighPerformance();\r
+                       #endregion\r
+\r
+\r
 #if GPUFlushAfterPresent\r
                        FrameEnd += dtxmania_FrameEnd;\r
 #endif\r
@@ -964,6 +971,7 @@ namespace DTXMania
                }\r
                protected override void OnExiting(EventArgs e)\r
                {\r
+                       cPowerPlan.RestoreCurrentPowerPlan();                   // 電源プランを元のものに戻す\r
                        CPowerManagement.tEnableMonitorSuspend();               // スリープ抑止状態を解除\r
                        this.t終了処理();\r
                        base.OnExiting(e);\r
@@ -2023,6 +2031,7 @@ namespace DTXMania
                }\r
                private CSound previewSound;\r
                private CCounter ccMouseShow;\r
+               private CPowerPlan cPowerPlan;\r
 \r
 \r
                public void ShowWindowTitleWithSoundType()\r
index 50b278f..420c406 100644 (file)
@@ -81,6 +81,7 @@
   <ItemGroup>\r
     <Compile Include="コード\00.共通\COS.cs" />\r
     <Compile Include="コード\00.共通\CPowerManagement.cs" />\r
+    <Compile Include="コード\00.共通\CPowerPlan.cs" />\r
     <Compile Include="コード\00.共通\CSendMessage.cs" />\r
     <Compile Include="コード\00.共通\CTimerBase.cs" />\r
     <Compile Include="コード\00.共通\C一定間隔処理.cs" />\r
index f30c355..d8a6b2a 100644 (file)
@@ -31,5 +31,30 @@ namespace FDK
                                }\r
                        }\r
                }\r
+               /// <summary>\r
+               /// OSがXP以前ならfalse, Vista以降ならtrueを返す\r
+               /// </summary>\r
+               /// <returns></returns>\r
+               public static bool bIsWin8OrLater\r
+               {\r
+                       get\r
+                       {\r
+                               //プラットフォームの取得\r
+                               System.OperatingSystem os = System.Environment.OSVersion;\r
+                               if ( os.Platform != PlatformID.Win32NT )                // NT系でなければ、XP以前か、PC Windows系以外のOSのため、Vista以降ではない。よってfalseを返す。\r
+                               {\r
+                                       return false;\r
+                               }\r
+\r
+                               if ( os.Version.Major >= 6 && os.Version.Minor >= 2 )\r
+                               {\r
+                                       return true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
        }\r
 }\r
diff --git a/FDK17プロジェクト/コード/00.共通/CPowerPlan.cs b/FDK17プロジェクト/コード/00.共通/CPowerPlan.cs
new file mode 100644 (file)
index 0000000..cb4b4c9
--- /dev/null
@@ -0,0 +1,169 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Runtime.InteropServices;\r
+using System.Diagnostics;\r
+\r
+namespace FDK\r
+{\r
+       /// <summary>\r
+       /// 電源プランの制御を行う\r
+       /// </summary>\r
+       public class CPowerPlan\r
+       {\r
+               // 参考: 電源プラン制御: http://www.fsmpi.uni-bayreuth.de/~dun3/archives/programmatically-change-power-options-using-cshar/519.html\r
+               // 参考: ConnectedStandby判別: https://social.msdn.microsoft.com/Forums/en-US/eeb164a3-8ceb-4eb2-8768-4faaa7218c59/how-to-experimentally-confirm-that-connected-standby-mode-is-enabled-on-a-computer-system?forum=tailoringappsfordevices\r
+               //                             http://stackoverflow.com/questions/20407094/c-sharp-how-to-use-callntpowerinformation-with-interop-to-get-system-power-infor\r
+\r
+               readonly private Guid GuidHighPerformance = new Guid( "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c" );         // Vista以降は全部これのはず\r
+               private Guid GuidCurrent;\r
+               private bool bConnectedStandbySupported = false;\r
+\r
+\r
+\r
+\r
+               public CPowerPlan()\r
+               {\r
+                       GuidCurrent = System.Guid.Empty;\r
+               }\r
+\r
+\r
+               public void BackupCurrentPowerPlan()\r
+               {\r
+                       bConnectedStandbySupported = IsConnetedStandbySupported();\r
+                       \r
+                       if ( bConnectedStandbySupported )\r
+                       {\r
+                               // 何もしない\r
+                       }\r
+                       else\r
+                       {\r
+                               GuidCurrent = GetActivePowerPlan();\r
+                               Trace.TraceInformation( "現在の電源プラン「{0}」をバックアップしました。", GetFriendlyName( GuidCurrent ) );\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Connected Standbyサポート機種かどうかの判定\r
+               /// (Connected Standby機種に対しては、電源プラン操作を行わない)\r
+               /// </summary>\r
+               private static bool IsConnetedStandbySupported()\r
+               {\r
+                       if ( !COS.bIsWin8OrLater )\r
+                       {\r
+                               // Win8以前であれば、ConnectedStandby非サポートが確定\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               CWin32.SYSTEM_POWER_CAPABILITIES cap;\r
+                               uint retval = CWin32.CallNtPowerInformation(\r
+                                       (int) CWin32.POWER_INFORMATION_LEVEL.SystemPowerCapabilities,\r
+                                       IntPtr.Zero,\r
+                                       0,\r
+                                       out cap,\r
+                                       Marshal.SizeOf( typeof( CWin32.SYSTEM_POWER_CAPABILITIES ) )\r
+                               );\r
+                               if ( retval == 0 )\r
+                               {\r
+                                       Debug.WriteLine( "SYSTEM_POWER_CAPABILITIES.AOAC: " + cap.AoAc );\r
+                                       if ( cap.AoAc )\r
+                                       {\r
+                                               Debug.WriteLine( "Connected Standby is enabled." );\r
+                                               return true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               Debug.WriteLine( "Connected Standby is NOT enabled." );\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       Debug.WriteLine( "CallNtPowerInformation returned: " + retval );\r
+                                       //Debug.WriteLine( "Call to CallNTPowerInformation failed. GetLastError: %d\n", GetLastError() );\r
+                                       return false;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               public void RestoreCurrentPowerPlan()\r
+               {\r
+                       if ( bConnectedStandbySupported )\r
+                       {\r
+                               // 何もしない\r
+                       }\r
+                       else\r
+                       {\r
+                               if ( GuidCurrent != System.Guid.Empty )\r
+                               {\r
+                                       SetActivePowerPlan( GuidCurrent );\r
+                                       Trace.TraceInformation( "電源プランを、「{0}」に戻しました。", GetFriendlyName( GuidCurrent ) );\r
+                                       GuidCurrent = System.Guid.Empty;\r
+                               }\r
+                       }\r
+               }\r
+               public void ChangeHighPerformance()\r
+               {\r
+                       if ( bConnectedStandbySupported )\r
+                       {\r
+                               Trace.TraceInformation( "ConnectedStandby対応機種のため、電源プランの変更を行いません。" );\r
+                       }\r
+                       else\r
+                       {\r
+                               SetActivePowerPlan( GuidHighPerformance );\r
+                               Trace.TraceInformation( "電源プランを、「{0}」に変更しました。", GetFriendlyName( GuidHighPerformance ) );\r
+                       }\r
+               }\r
+\r
+\r
+\r
+               private void SetActivePowerPlan( Guid powerSchemeId )\r
+               {\r
+                       var schemeGuid = powerSchemeId;\r
+                       CWin32.PowerSetActiveScheme( IntPtr.Zero, ref schemeGuid );\r
+               }\r
+\r
+               private Guid GetActivePowerPlan()\r
+               {\r
+                       IntPtr pCurrentSchemeGuid = IntPtr.Zero;\r
+                       CWin32.PowerGetActiveScheme( IntPtr.Zero, ref pCurrentSchemeGuid );\r
+                       var currentSchemeGuid = (Guid) Marshal.PtrToStructure( pCurrentSchemeGuid, typeof( Guid ) );\r
+                       return currentSchemeGuid;\r
+               }\r
+\r
+\r
+               public IEnumerable<Guid> FindAll()\r
+               {\r
+                       var schemeGuid = Guid.Empty;\r
+                       uint sizeSchemeGuid = (uint) Marshal.SizeOf( typeof( Guid ) );\r
+                       uint schemeIndex = 0;\r
+                       while ( CWin32.PowerEnumerate( IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint) CWin32.AccessFlags.ACCESS_SCHEME,\r
+                               schemeIndex, ref schemeGuid, ref sizeSchemeGuid ) == 0 )\r
+                       {\r
+                               yield return schemeGuid;\r
+                               schemeIndex++;\r
+                       }\r
+               }\r
+\r
+               private string GetFriendlyName( Guid schemeGuid )\r
+               {\r
+                       uint sizeName = 1024;\r
+                       IntPtr pSizeName = Marshal.AllocHGlobal( (int) sizeName );\r
+                       string friendlyName;\r
+\r
+                       try\r
+                       {\r
+                               CWin32.PowerReadFriendlyName( IntPtr.Zero, ref schemeGuid, IntPtr.Zero, IntPtr.Zero, pSizeName, ref sizeName );\r
+                               friendlyName = Marshal.PtrToStringUni( pSizeName );\r
+                       }\r
+                       finally\r
+                       {\r
+                               Marshal.FreeHGlobal( pSizeName );\r
+                       }\r
+                       return friendlyName;\r
+               }\r
+       }\r
+}\r
index 08e6489..d87bd9c 100644 (file)
@@ -363,8 +363,8 @@ namespace FDK
                [return: MarshalAs( UnmanagedType.Bool )]\r
                [DllImport( "user32.dll", CharSet = CharSet.Auto )]\r
                public static extern bool PeekMessage( out WindowMessage message, IntPtr hwnd, uint messageFilterMin, uint messageFilterMax, uint flags );\r
-               [DllImport( "kernel32.dll", CharSet = CharSet.Auto )]\r
-               public static extern uint SetThreadExecutionState( uint esFlags );\r
+               //[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]\r
+               //public static extern uint SetThreadExecutionState( uint esFlags );\r
                [DllImport( "Kernel32.Dll" )]\r
                public static unsafe extern void CopyMemory( void* pDest, void* pSrc, uint numOfBytes );\r
 \r
@@ -386,6 +386,32 @@ namespace FDK
                public static extern void GetSystemInfo( ref SYSTEM_INFO ptmpsi );\r
                [DllImport( "kernel32.dll" )]\r
                internal static extern ExecutionState SetThreadExecutionState( ExecutionState esFlags );\r
+\r
+               \r
+               [DllImport("PowrProf.dll")]\r
+               public static extern UInt32 PowerEnumerate(IntPtr RootPowerKey, IntPtr SchemeGuid, IntPtr SubGroupOfPowerSettingGuid, UInt32 AcessFlags, UInt32 Index, ref Guid Buffer, ref UInt32 BufferSize);\r
+               public enum AccessFlags : uint\r
+               {\r
+                       ACCESS_SCHEME = 16,\r
+                       ACCESS_SUBGROUP = 17,\r
+                       ACCESS_INDIVIDUAL_SETTING = 18\r
+               }\r
+               [DllImport( "PowrProf.dll" )]\r
+               public static extern UInt32 PowerReadFriendlyName( IntPtr RootPowerKey, ref Guid SchemeGuid, IntPtr SubGroupOfPowerSettingGuid, IntPtr PowerSettingGuid, IntPtr Buffer, ref UInt32 BufferSize );\r
+               [DllImport( "PowrProf.dll" )]\r
+               public static extern uint PowerGetActiveScheme( IntPtr UserRootPowerKey, ref IntPtr ActivePolicyGuid );\r
+               [DllImport( "PowrProf.dll" )]\r
+               public static extern uint PowerSetActiveScheme(IntPtr UserRootPowerKey, ref Guid SchemeGuid);\r
+               [DllImport( "powrprof.dll" )]\r
+               public static extern uint CallNtPowerInformation(\r
+                       int InformationLevel,\r
+                       IntPtr lpInputBuffer,\r
+                       int nInputBufferSize,\r
+                       out SYSTEM_POWER_CAPABILITIES spi,\r
+                       int nOutputBufferSize\r
+               );\r
+\r
+\r
                //-----------------\r
                #endregion\r
 \r
@@ -486,6 +512,114 @@ namespace FDK
                        public uint dwProcessorLevel;\r
                        public uint dwProcessorRevision;\r
                }\r
+               public struct BATTERY_REPORTING_SCALE\r
+               {\r
+                       public ulong Granularity;\r
+                       public ulong Capacity;\r
+               }\r
+               public enum SYSTEM_POWER_STATE\r
+               {\r
+                       PowerSystemUnspecified = 0,\r
+                       PowerSystemWorking = 1,\r
+                       PowerSystemSleeping1 = 2,\r
+                       PowerSystemSleeping2 = 3,\r
+                       PowerSystemSleeping3 = 4,\r
+                       PowerSystemHibernate = 5,\r
+                       PowerSystemShutdown = 6,\r
+                       PowerSystemMaximum = 7\r
+               }\r
+               public struct SYSTEM_POWER_INFORMATION\r
+               {\r
+                       public uint MaxIdlenessAllowed;\r
+                       public uint Idleness;\r
+                       public uint TimeRemaining;\r
+                       public byte CoolingMode;\r
+               }\r
+               public enum POWER_INFORMATION_LEVEL : int\r
+               {\r
+                       AdministratorPowerPolicy                = 9,\r
+                       LastSleepTime1                                  = 5,\r
+                       LastWakeTime                                    = 14,\r
+                       ProcessorInformation                    = 11,\r
+                       ProcessorPowerPolicyAc                  = 18,\r
+                       ProcessorPowerPolicyCurrent             = 22,\r
+                       ProcessorPowerPolicyDc                  = 19,\r
+                       SystemBatteryState                              = 5,\r
+                       SystemExecutionState                    = 16,\r
+                       SystemPowerCapabilities                 = 4,\r
+                       SystemPowerInformation                  = 12,\r
+                       SystemPowerPolicyAc                             = 0,\r
+                       SystemPowerPolicyCurrent                = 8,\r
+                       SystemPowerPolicyDc                             = 1,\r
+                       SystemReserveHiberFile                  = 10,\r
+                       VerifyProcessorPowerPolicyAc    = 20,\r
+                       VerifyProcessorPowerPolicyDc    = 21,\r
+                       VerifySystemPolicyAc                    = 2,\r
+                       VerifySystemPolicyDc                    = 3\r
+               }\r
+\r
+               // http://www.pinvoke.net/default.aspx/Structures/SYSTEM_POWER_STATE.html\r
+               public struct SYSTEM_POWER_CAPABILITIES\r
+               {\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool PowerButtonPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SleepButtonPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool LidPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemS1;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemS2;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemS3;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemS4;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemS5;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool HiberFilePresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool FullWake;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool VideoDimPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool ApmPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool UpsPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool ThermalControl;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool ProcessorThrottle;\r
+                       public byte ProcessorMinThrottle;\r
+                       public byte ProcessorMaxThrottle;   // Also known as ProcessorThrottleScale before Windows XP\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool FastSystemS4;                       // Ignore if earlier than Windows XP\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool Hiberboot;                          // Ignore if earlier than Windows XP\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool WakeAlarmPresent;           // Ignore if earlier than Windows XP\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool AoAc;                                       // Ignore if earlier than Windows XP\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool DiskSpinDown;\r
+                       public byte HiberFileType;                      // Ignore if earlier than Windows 10 (10.0.10240.0)\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool AoAcConnectivitySupported;  // Ignore if earlier than Windows 10 (10.0.10240.0)\r
+                       [MarshalAs( UnmanagedType.ByValArray, SizeConst = 6 )]\r
+                       private readonly byte[] spare3;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool SystemBatteriesPresent;\r
+                       [MarshalAs( UnmanagedType.U1 )]\r
+                       public bool BatteriesAreShortTerm;\r
+                       [MarshalAs( UnmanagedType.ByValArray, SizeConst = 3 )]\r
+                       public BATTERY_REPORTING_SCALE[] BatteryScale;\r
+                       public SYSTEM_POWER_STATE AcOnLineWake;\r
+                       public SYSTEM_POWER_STATE SoftLidWake;\r
+                       public SYSTEM_POWER_STATE RtcWake;\r
+                       public SYSTEM_POWER_STATE MinDeviceWakeState;\r
+                       public SYSTEM_POWER_STATE DefaultLowLatencyWake;\r
+               }\r
                //-----------------\r
                #endregion\r
 \r