2012/07/30(Mon)Win32APIで画面の明るさを変更する方法
2012/07/30 22:07
なお、API的にWindows VistaまたはServer 2008以降のみをサポートしており、Windows XPでは使用できないAPIを使っているので注意。
.net Framework 2.0で確認済み。
使うAPI一覧
Vistaから一新された電源管理DLLのPowrProf.dll*1に揃っている。P/Invoke
C4F Developer KitのPowerManagementNative.csから引用・参考にさせてもらうと…#region Constants /// <summary> /// Settings in this subgroup control configuration of the video power management features. /// </summary> public Guid GUID_VIDEO_SUBGROUP = new Guid("7516b95f-f776-4464-8c53-06167f40cc99"); /// <summary> /// Guid for display brightness setting. /// </summary> public Guid DisplayBrightnessGuid = new Guid("aded5e82-b909-4619-9949-f5d71dac0bcb"); #endregion #region Methods /// <summary> /// Retrieves the AC index of the specified power setting. /// </summary> /// <param name="RootPowerKey">This parameter is reserved for future use and must be set to NULL.</param> /// <param name="SchemeGuid">The identifier of the power scheme.</param> /// <param name="SubGroupOfPowerSettingsGuid">The subgroup of power settings. This parameter can be one of the following values defined in WinNT.h. Use NO_SUBGROUP_GUID to refer to the default power scheme.</param> /// <param name="PowerSettingGuid">The identifier of the power setting</param> /// <param name="AcValueIndex">A pointer to a variable that receives the AC value index.</param> /// <returns>Returns ERROR_SUCCESS (zero) if the call was successful, and a nonzero value if the call failed.</returns> [DllImport("powrprof.dll", EntryPoint = "PowerReadACValueIndex", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint PowerReadACValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, out uint AcValueIndex); /// <summary> /// Sets the AC value index of the specified power setting. /// </summary> /// <param name="RootPowerKey">This parameter is reserved for future use and must be set to NULL.</param> /// <param name="SchemeGuid">The identifier of the power scheme.</param> /// <param name="SubGroupOfPowerSettingsGuid">The subgroup of power settings. This parameter can be one of the following values defined in WinNT.h. Use NO_SUBGROUP_GUID to refer to the default power scheme.</param> /// <param name="PowerSettingGuid">The identifier of the power setting</param> /// <param name="AcValueIndex">The AC value index.</param> /// <returns>Returns ERROR_SUCCESS (zero) if the call was successful, and a nonzero value if the call failed.</returns> [DllImport("powrprof.dll", EntryPoint = "PowerWriteACValueIndex", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint PowerWriteACValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, uint AcValueIndex); /// <summary> /// Retrieves the AC index of the specified power setting. /// </summary> /// <param name="RootPowerKey">This parameter is reserved for future use and must be set to NULL.</param> /// <param name="SchemeGuid">The identifier of the power scheme.</param> /// <param name="SubGroupOfPowerSettingsGuid">The subgroup of power settings. This parameter can be one of the following values defined in WinNT.h. Use NO_SUBGROUP_GUID to refer to the default power scheme.</param> /// <param name="PowerSettingGuid">The identifier of the power setting</param> /// <param name="AcValueIndex">A pointer to a variable that receives the AC value index.</param> /// <returns>Returns ERROR_SUCCESS (zero) if the call was successful, and a nonzero value if the call failed.</returns> [DllImport("powrprof.dll", EntryPoint = "PowerReadDCValueIndex", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint PowerReadDCValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, out uint AcValueIndex); /// <summary> /// Sets the AC value index of the specified power setting. /// </summary> /// <param name="RootPowerKey">This parameter is reserved for future use and must be set to NULL.</param> /// <param name="SchemeGuid">The identifier of the power scheme.</param> /// <param name="SubGroupOfPowerSettingsGuid">The subgroup of power settings. This parameter can be one of the following values defined in WinNT.h. Use NO_SUBGROUP_GUID to refer to the default power scheme.</param> /// <param name="PowerSettingGuid">The identifier of the power setting</param> /// <param name="AcValueIndex">The AC value index.</param> /// <returns>Returns ERROR_SUCCESS (zero) if the call was successful, and a nonzero value if the call failed.</returns> [DllImport("powrprof.dll", EntryPoint = "PowerWriteDCValueIndex", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint PowerWriteDCValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, uint AcValueIndex); /// <summary> /// Sets the active power scheme for the current user. /// </summary> /// <param name="UserRootPowerKey">This parameter is reserved for future use and must be set to NULL.</param> /// <param name="SchemeGuid">The identifier of the power scheme.</param> /// <returns>Returns ERROR_SUCCESS (zero) if the call was successful, and a nonzero value if the call failed.</returns> [DllImport("powrprof.dll", EntryPoint = "PowerSetActiveScheme", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint PowerSetActiveScheme(IntPtr UserRootPowerKey, ref Guid SchemeGuid); #endregion
明るさの変更
powercfg
API一覧からも分かるように、Vista以降の電源管理ではAC接続時とバッテリ駆動時で呼び出すAPIが違う上、さらに電源プロファイル(バランス、高パフォーマンス、省電力など)という区分がある。したがって、これらのAPIを呼び出す際には、項目の設定値のほかに3つのGUIDキーを指定する必要がある。
- <SCHEME_GUID>
- 設定を反映させる電源プロファイルのGUID
powercfg.exe -l で一覧が取得できるので、メモしておく。以下、<SCHEME_GUID>の部分は、この値に置き換えること。 - <SUB_GUID>
- 電源設定のサブカテゴリのGUID
今回は、ディスプレイ関係の電源管理サブグループ(7516b95f-f776-4464-8c53-06167f40cc99)となる。 - <SETTING_GUID>
- 個々の電源設定のGUID
今回は、ディスプレイの明るさ(7516b95f-f776-4464-8c53-06167f40cc99)となる。
powercfg /q <SCHEME_GUID> <SUB_GUID>で確認すると分かるように、ディスプレイの明るさは0~100で指定できることが分かる。
(値は16進数で表示されているので、0x64 = 100である)
>powercfg -q <SCHEME_GUID> 7516b95f-f776-4464-8c53-06167f40cc99 電源設定の GUID: <SCHEME_GUID> (My Power Management Policy) サブグループの GUID: 7516b95f-f776-4464-8c53-06167f40cc99 (ディスプレイ) ...(略)... 電源設定の GUID: aded5e82-b909-4619-9949-f5d71dac0bcb (ディスプレイの明るさ) 利用可能な設定の最小値: 0x00000000 利用可能な設定の最大値: 0x00000064 利用可能な設定の増分: 0x00000001 利用可能な設定の単位: % 現在の AC 電源設定のインデックス: 0x00000064 現在の DC 電源設定のインデックス: 0x00000021 ...(略)...powercfgで変更する場合は、以下のように。-setactiveをしないと、実際に画面の明るさが変更しないことに注意。これは後々のAPI呼び出しの場合も同様である。
>powercfg -setacvalueindex <SCHEME_GUID> 7516b95f-f776-4464-8c53-06167f40cc99 aded5e82-b909-4619-9949-f5d71dac0bcb 50 >powercfg -setactive <SCHEME_GUID>画面の明るさがちょうど中間になったはず。
API
では、本題のAPI呼び出しでの変更。Guid MY_POWER_MANAGEMENT_POLICY = new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); // 今回は<SCHEME_GUID>をベタ指定 Guid GUID_VIDEO_SUBGROUP = new Guid("7516b95f-f776-4464-8c53-06167f40cc99"); Guid DisplayBrightnessGuid = new Guid("aded5e82-b909-4619-9949-f5d71dac0bcb"); bool SetACBrightness(int bright_ac) if(bright_ac < 0 || bright_ac > 100) return false; uint ret = PowerWriteACValueIndex(IntPtr.Zero, ref MY_POWER_MANAGEMENT_POLICY, ref GUID_VIDEO_SUBGROUP, ref DisplayBrightnessGuid, (uint)bright_ac); if(ret != 0) return false; ret = PowerSetActiveScheme(IntPtr.Zero, ref MY_POWER_MANAGEMENT_POLICY); if(ret != 0) return false; return true; }ちなみに、電源接続時とバッテリ駆動時で呼び出すAPIが異なるので、以下のようにして電源状態を取得して分岐すると良いかな。
System.Windows.Forms.PowerLineStatus ps = System.Windows.Forms.SystemInformation.PowerStatus.PowerLineStatus; switch(ps) { case System.Windows.Forms.PowerLineStatus.Online: // AC SetACBrightness(value); break; case System.Windows.Forms.PowerLineStatus.Offline: // DC SetDCBrightness(value); break; }