mirror of
https://github.com/jkocon/g-helper.git
synced 2026-02-23 13:00:52 +01:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
306697f026 | ||
|
|
c5a32cc9d5 | ||
|
|
51acd9a612 | ||
|
|
457a37049c | ||
|
|
6d2cece4f2 | ||
|
|
265611009c | ||
|
|
2714b6dca7 | ||
|
|
f6de5eba64 | ||
|
|
13f7c81689 |
@@ -71,13 +71,17 @@ namespace Starlight.AnimeMatrix
|
||||
private const int UpdatePageLength = 0x0278;
|
||||
|
||||
public int LedCount => 1450;
|
||||
public int Rows => 61;
|
||||
|
||||
private byte[] _displayBuffer = new byte[UpdatePageLength * 3];
|
||||
private List<byte[]> frames = new List<byte[]>();
|
||||
|
||||
private int pages = 3;
|
||||
|
||||
public int MaxColumns = 34;
|
||||
public int MaxRows = 61;
|
||||
|
||||
public int FullRows = 11;
|
||||
|
||||
private int frameIndex = 0;
|
||||
|
||||
public AnimeMatrixDevice()
|
||||
@@ -88,6 +92,10 @@ namespace Starlight.AnimeMatrix
|
||||
if (model is not null && model.Contains("401"))
|
||||
{
|
||||
pages = 2;
|
||||
|
||||
FullRows = 6;
|
||||
MaxColumns = 33;
|
||||
MaxRows = 55;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,12 +145,12 @@ namespace Starlight.AnimeMatrix
|
||||
|
||||
public int EmptyColumns(int row)
|
||||
{
|
||||
return (int)Math.Ceiling(Math.Max(0, row - 11) / 2.0);
|
||||
return (int)Math.Ceiling(Math.Max(0, row - FullRows) / 2.0);
|
||||
}
|
||||
public int Columns(int row)
|
||||
{
|
||||
EnsureRowInRange(row);
|
||||
return 34 - EmptyColumns(row);
|
||||
return MaxColumns - EmptyColumns(row);
|
||||
}
|
||||
|
||||
public int RowToLinearAddress(int row)
|
||||
@@ -265,8 +273,8 @@ namespace Starlight.AnimeMatrix
|
||||
public void GenerateFrame(Image image)
|
||||
{
|
||||
|
||||
int width = 34 * 3;
|
||||
int height = 61;
|
||||
int width = MaxColumns * 3;
|
||||
int height = MaxRows;
|
||||
float scale;
|
||||
|
||||
Bitmap canvas = new Bitmap(width, height);
|
||||
@@ -283,7 +291,7 @@ namespace Starlight.AnimeMatrix
|
||||
|
||||
graph.DrawImage(image, ((int)width - scaleWidth), ((int)height - scaleHeight) / 2, scaleWidth, scaleHeight);
|
||||
|
||||
Bitmap bmp = new Bitmap(canvas, 34, 61);
|
||||
Bitmap bmp = new Bitmap(canvas, MaxColumns, MaxRows);
|
||||
|
||||
for (int y = 0; y < bmp.Height; y++)
|
||||
{
|
||||
@@ -299,9 +307,9 @@ namespace Starlight.AnimeMatrix
|
||||
|
||||
private void EnsureRowInRange(int row)
|
||||
{
|
||||
if (row < 0 || row >= Rows)
|
||||
if (row < 0 || row >= MaxRows)
|
||||
{
|
||||
throw new IndexOutOfRangeException($"Y-coordinate should fall in range of [0, {Rows - 1}].");
|
||||
throw new IndexOutOfRangeException($"Y-coordinate should fall in range of [0, {MaxRows - 1}].");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
52
Fans.Designer.cs
generated
52
Fans.Designer.cs
generated
@@ -28,9 +28,10 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea5 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
|
||||
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea6 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
|
||||
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea3 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
|
||||
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea4 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
|
||||
panelFans = new Panel();
|
||||
labelFans = new Label();
|
||||
checkAuto = new CheckBox();
|
||||
chartGPU = new System.Windows.Forms.DataVisualization.Charting.Chart();
|
||||
buttonReset = new Button();
|
||||
@@ -51,6 +52,7 @@
|
||||
labelApplied = new Label();
|
||||
pictureFine = new PictureBox();
|
||||
labelInfo = new Label();
|
||||
checkBoost = new CheckBox();
|
||||
panelFans.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)chartGPU).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)chartCPU).BeginInit();
|
||||
@@ -64,6 +66,8 @@
|
||||
//
|
||||
// panelFans
|
||||
//
|
||||
panelFans.Controls.Add(checkBoost);
|
||||
panelFans.Controls.Add(labelFans);
|
||||
panelFans.Controls.Add(checkAuto);
|
||||
panelFans.Controls.Add(chartGPU);
|
||||
panelFans.Controls.Add(buttonReset);
|
||||
@@ -78,11 +82,21 @@
|
||||
panelFans.Size = new Size(872, 1089);
|
||||
panelFans.TabIndex = 12;
|
||||
//
|
||||
// labelFans
|
||||
//
|
||||
labelFans.AutoSize = true;
|
||||
labelFans.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
|
||||
labelFans.Location = new Point(24, 15);
|
||||
labelFans.Name = "labelFans";
|
||||
labelFans.Size = new Size(138, 32);
|
||||
labelFans.TabIndex = 28;
|
||||
labelFans.Text = "Fan Curves";
|
||||
//
|
||||
// checkAuto
|
||||
//
|
||||
checkAuto.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
checkAuto.AutoSize = true;
|
||||
checkAuto.Location = new Point(584, 981);
|
||||
checkAuto.Location = new Point(411, 1030);
|
||||
checkAuto.Margin = new Padding(4, 2, 4, 2);
|
||||
checkAuto.Name = "checkAuto";
|
||||
checkAuto.Size = new Size(165, 36);
|
||||
@@ -93,9 +107,9 @@
|
||||
// chartGPU
|
||||
//
|
||||
chartGPU.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||
chartArea5.Name = "ChartArea1";
|
||||
chartGPU.ChartAreas.Add(chartArea5);
|
||||
chartGPU.Location = new Point(22, 502);
|
||||
chartArea3.Name = "ChartArea1";
|
||||
chartGPU.ChartAreas.Add(chartArea3);
|
||||
chartGPU.Location = new Point(22, 547);
|
||||
chartGPU.Margin = new Padding(4, 2, 4, 2);
|
||||
chartGPU.Name = "chartGPU";
|
||||
chartGPU.Size = new Size(810, 460);
|
||||
@@ -127,9 +141,9 @@
|
||||
// chartCPU
|
||||
//
|
||||
chartCPU.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||
chartArea6.Name = "ChartArea1";
|
||||
chartCPU.ChartAreas.Add(chartArea6);
|
||||
chartCPU.Location = new Point(22, 21);
|
||||
chartArea4.Name = "ChartArea1";
|
||||
chartCPU.ChartAreas.Add(chartArea4);
|
||||
chartCPU.Location = new Point(22, 66);
|
||||
chartCPU.Margin = new Padding(10);
|
||||
chartCPU.Name = "chartCPU";
|
||||
chartCPU.Size = new Size(810, 460);
|
||||
@@ -166,7 +180,7 @@
|
||||
//
|
||||
checkApplyPower.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
checkApplyPower.AutoSize = true;
|
||||
checkApplyPower.Location = new Point(17, 981);
|
||||
checkApplyPower.Location = new Point(21, 982);
|
||||
checkApplyPower.Margin = new Padding(4, 2, 4, 2);
|
||||
checkApplyPower.Name = "checkApplyPower";
|
||||
checkApplyPower.Size = new Size(165, 36);
|
||||
@@ -294,7 +308,7 @@
|
||||
pictureFine.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
pictureFine.BackgroundImageLayout = ImageLayout.Zoom;
|
||||
pictureFine.Image = Properties.Resources.everything_is_fine_itsfine;
|
||||
pictureFine.Location = new Point(17, 694);
|
||||
pictureFine.Location = new Point(17, 671);
|
||||
pictureFine.Margin = new Padding(4, 2, 4, 2);
|
||||
pictureFine.Name = "pictureFine";
|
||||
pictureFine.Size = new Size(327, 254);
|
||||
@@ -308,10 +322,22 @@
|
||||
labelInfo.Location = new Point(17, 603);
|
||||
labelInfo.Margin = new Padding(4, 0, 4, 0);
|
||||
labelInfo.Name = "labelInfo";
|
||||
labelInfo.Size = new Size(327, 371);
|
||||
labelInfo.Size = new Size(327, 330);
|
||||
labelInfo.TabIndex = 19;
|
||||
labelInfo.Text = "label";
|
||||
//
|
||||
// checkBoost
|
||||
//
|
||||
checkBoost.AutoSize = true;
|
||||
checkBoost.ForeColor = SystemColors.ControlText;
|
||||
checkBoost.Location = new Point(512, 15);
|
||||
checkBoost.Margin = new Padding(4, 2, 4, 2);
|
||||
checkBoost.Name = "checkBoost";
|
||||
checkBoost.Size = new Size(320, 36);
|
||||
checkBoost.TabIndex = 35;
|
||||
checkBoost.Text = "CPU Turbo Boost enabled";
|
||||
checkBoost.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// Fans
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(192F, 192F);
|
||||
@@ -369,5 +395,7 @@
|
||||
private PictureBox pictureFine;
|
||||
private Label labelInfo;
|
||||
private Label labelPowerLimits;
|
||||
private Label labelFans;
|
||||
private CheckBox checkBoost;
|
||||
}
|
||||
}
|
||||
24
Fans.cs
24
Fans.cs
@@ -22,7 +22,7 @@ namespace GHelper
|
||||
title = "CPU Fan Profile";
|
||||
|
||||
if (Program.settingsForm.perfName.Length > 0)
|
||||
title += ": " + Program.settingsForm.perfName;
|
||||
labelFans.Text = "Fan Profiles: " + Program.settingsForm.perfName;
|
||||
|
||||
if (chart.Titles.Count > 0)
|
||||
chart.Titles[0].Text = title;
|
||||
@@ -102,11 +102,33 @@ namespace GHelper
|
||||
|
||||
InitFans();
|
||||
InitPower();
|
||||
InitBoost();
|
||||
|
||||
checkBoost.Click += CheckBoost_Click;
|
||||
|
||||
Shown += Fans_Shown;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void InitBoost()
|
||||
{
|
||||
int boost = NativeMethods.GetCPUBoost();
|
||||
checkBoost.Checked = (boost > 0);
|
||||
}
|
||||
|
||||
private void CheckBoost_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is null)
|
||||
return;
|
||||
|
||||
CheckBox chk = (CheckBox)sender;
|
||||
if (chk.Checked)
|
||||
NativeMethods.SetCPUBoost(2);
|
||||
else
|
||||
NativeMethods.SetCPUBoost(0);
|
||||
}
|
||||
|
||||
private void CheckApplyPower_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is null) return;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<AssemblyName>GHelper</AssemblyName>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||
<AssemblyVersion>0.18</AssemblyVersion>
|
||||
<AssemblyVersion>0.20</AssemblyVersion>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
427
NativeMethods.cs
427
NativeMethods.cs
@@ -1,11 +1,316 @@
|
||||
using System.Diagnostics;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using Tools;
|
||||
using static Tools.ScreenInterrogatory;
|
||||
|
||||
namespace Tools
|
||||
{
|
||||
public static class ScreenInterrogatory
|
||||
{
|
||||
public const int ERROR_SUCCESS = 0;
|
||||
|
||||
#region enums
|
||||
|
||||
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
|
||||
{
|
||||
QDC_ALL_PATHS = 0x00000001,
|
||||
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
|
||||
QDC_DATABASE_CURRENT = 0x00000004
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
|
||||
{
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
|
||||
{
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_ROTATION : uint
|
||||
{
|
||||
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
|
||||
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_SCALING : uint
|
||||
{
|
||||
DISPLAYCONFIG_SCALING_IDENTITY = 1,
|
||||
DISPLAYCONFIG_SCALING_CENTERED = 2,
|
||||
DISPLAYCONFIG_SCALING_STRETCHED = 3,
|
||||
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
|
||||
DISPLAYCONFIG_SCALING_CUSTOM = 5,
|
||||
DISPLAYCONFIG_SCALING_PREFERRED = 128,
|
||||
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_PIXELFORMAT : uint
|
||||
{
|
||||
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
|
||||
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
|
||||
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
|
||||
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
|
||||
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
|
||||
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
|
||||
{
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
|
||||
{
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
|
||||
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region structs
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LUID
|
||||
{
|
||||
public uint LowPart;
|
||||
public int HighPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
public uint statusFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_TARGET_INFO
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
|
||||
private DISPLAYCONFIG_ROTATION rotation;
|
||||
private DISPLAYCONFIG_SCALING scaling;
|
||||
private DISPLAYCONFIG_RATIONAL refreshRate;
|
||||
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
|
||||
public bool targetAvailable;
|
||||
public uint statusFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_RATIONAL
|
||||
{
|
||||
public uint Numerator;
|
||||
public uint Denominator;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
|
||||
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
|
||||
public uint flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_2DREGION
|
||||
{
|
||||
public uint cx;
|
||||
public uint cy;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
|
||||
{
|
||||
public ulong pixelRate;
|
||||
public DISPLAYCONFIG_RATIONAL hSyncFreq;
|
||||
public DISPLAYCONFIG_RATIONAL vSyncFreq;
|
||||
public DISPLAYCONFIG_2DREGION activeSize;
|
||||
public DISPLAYCONFIG_2DREGION totalSize;
|
||||
public uint videoStandard;
|
||||
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_TARGET_MODE
|
||||
{
|
||||
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINTL
|
||||
{
|
||||
private int x;
|
||||
private int y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_SOURCE_MODE
|
||||
{
|
||||
public uint width;
|
||||
public uint height;
|
||||
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
|
||||
public POINTL position;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct DISPLAYCONFIG_MODE_INFO_UNION
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public DISPLAYCONFIG_TARGET_MODE targetMode;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_MODE_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
|
||||
public uint id;
|
||||
public LUID adapterId;
|
||||
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
|
||||
{
|
||||
public uint value;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
|
||||
public uint size;
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
|
||||
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
|
||||
public ushort edidManufactureId;
|
||||
public ushort edidProductCodeId;
|
||||
public uint connectorInstance;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string monitorFriendlyDeviceName;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string monitorDevicePath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DLL-Imports
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetDisplayConfigBufferSizes(
|
||||
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int QueryDisplayConfig(
|
||||
QUERY_DEVICE_CONFIG_FLAGS flags,
|
||||
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
|
||||
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
|
||||
IntPtr currentTopologyId
|
||||
);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
|
||||
|
||||
#endregion
|
||||
|
||||
private static DISPLAYCONFIG_TARGET_DEVICE_NAME DeviceName(LUID adapterId, uint targetId)
|
||||
{
|
||||
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
|
||||
{
|
||||
header =
|
||||
{
|
||||
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
|
||||
adapterId = adapterId,
|
||||
id = targetId,
|
||||
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
|
||||
}
|
||||
};
|
||||
var error = DisplayConfigGetDeviceInfo(ref deviceName);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public static IEnumerable<DISPLAYCONFIG_TARGET_DEVICE_NAME> GetAllDevices()
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
|
||||
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
|
||||
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
|
||||
for (var i = 0; i < modeCount; i++)
|
||||
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
|
||||
yield return DeviceName(displayModes[i].adapterId, displayModes[i].id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class NativeMethods
|
||||
{
|
||||
|
||||
|
||||
public const int KEYEVENTF_EXTENDEDKEY = 1;
|
||||
public const int KEYEVENTF_KEYUP = 2;
|
||||
|
||||
@@ -162,43 +467,6 @@ public class NativeMethods
|
||||
string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd,
|
||||
DisplaySettingsFlags dwflags, IntPtr lParam);
|
||||
|
||||
// ENUM DISPLAYS
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool EnumDisplayDevicesA(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
|
||||
|
||||
[Flags()]
|
||||
public enum DisplayDeviceStateFlags : int
|
||||
{
|
||||
AttachedToDesktop = 0x1,
|
||||
MultiDriver = 0x2,
|
||||
PrimaryDevice = 0x4,
|
||||
MirroringDriver = 0x8,
|
||||
VGACompatible = 0x10,
|
||||
Removable = 0x20,
|
||||
ModesPruned = 0x8000000,
|
||||
Remote = 0x4000000,
|
||||
Disconnect = 0x2000000
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct DISPLAY_DEVICE
|
||||
{
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
public int cb;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string DeviceName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceString;
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
public DisplayDeviceStateFlags StateFlags;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceID;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceKey;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
public static DEVMODE CreateDevmode()
|
||||
{
|
||||
DEVMODE dm = new DEVMODE();
|
||||
@@ -209,83 +477,40 @@ public class NativeMethods
|
||||
}
|
||||
|
||||
public const int ENUM_CURRENT_SETTINGS = -1;
|
||||
public const string laptopScreenName = "\\\\.\\DISPLAY1";
|
||||
public const string defaultDevice = "\\\\.\\DISPLAY1";
|
||||
|
||||
public static string FindLaptopScreen()
|
||||
{
|
||||
string laptopScreen = null;
|
||||
|
||||
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
|
||||
d.cb = Marshal.SizeOf(d);
|
||||
|
||||
List<string> activeScreens = new List<string>();
|
||||
int counter = 0;
|
||||
int deviceNum = -1;
|
||||
|
||||
try
|
||||
{
|
||||
var searcherActive = new ManagementObjectSearcher(@"\\.\root\wmi", "SELECT * FROM WmiMonitorBasicDisplayParams");
|
||||
var resultsActive = searcherActive.Get();
|
||||
foreach (var result in resultsActive)
|
||||
var devices = GetAllDevices();
|
||||
int count = 0, displayNum = -1;
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
activeScreens.Add(result["InstanceName"].ToString());
|
||||
if (device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL)
|
||||
displayNum = count;
|
||||
count++;
|
||||
//Debug.WriteLine(device.outputTechnology);
|
||||
//Debug.WriteLine(device.monitorFriendlyDeviceName);
|
||||
}
|
||||
|
||||
var searcher = new ManagementObjectSearcher(@"\\.\root\wmi", "SELECT * FROM WmiMonitorConnectionParams");
|
||||
var results = searcher.Get();
|
||||
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
long technology;
|
||||
long.TryParse(result["VideoOutputTechnology"].ToString(), out technology);
|
||||
string instanceName = result["InstanceName"].ToString();
|
||||
|
||||
if (technology == 0x80000000 && activeScreens.Contains(instanceName))
|
||||
{
|
||||
deviceNum = counter;
|
||||
//Debug.WriteLine(result["InstanceName"]);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
} catch
|
||||
{
|
||||
Debug.WriteLine("Failed to detect built in display");
|
||||
deviceNum = 0;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
counter = 0;
|
||||
for (uint id = 0; EnumDisplayDevicesA(null, id, ref d, 0); id++)
|
||||
{
|
||||
if ((d.StateFlags & DisplayDeviceStateFlags.AttachedToDesktop) != 0)
|
||||
{
|
||||
//Debug.WriteLine(d.DeviceID);
|
||||
//Debug.WriteLine(d.DeviceName);
|
||||
if (counter == deviceNum)
|
||||
{
|
||||
laptopScreen = d.DeviceName;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
}
|
||||
} catch
|
||||
{
|
||||
Debug.WriteLine("Failed to enumerate displays");
|
||||
}
|
||||
|
||||
// Mismatch between active screens and enumerated screens, fallback to old method
|
||||
if (counter != activeScreens.Count)
|
||||
{
|
||||
laptopScreen = null;
|
||||
count = 0;
|
||||
foreach (var screen in Screen.AllScreens)
|
||||
if (screen.DeviceName == laptopScreenName)
|
||||
{
|
||||
if (count == displayNum)
|
||||
laptopScreen = screen.DeviceName;
|
||||
//Debug.WriteLine(screen.DeviceName);
|
||||
count++;
|
||||
}
|
||||
} catch
|
||||
{
|
||||
Debug.WriteLine("Can't find internal screen");
|
||||
}
|
||||
|
||||
|
||||
return laptopScreen;
|
||||
}
|
||||
|
||||
|
||||
60
Program.cs
60
Program.cs
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class HardwareMonitor
|
||||
{
|
||||
@@ -36,6 +37,32 @@ namespace GHelper
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
|
||||
// Native methods for sleep detection
|
||||
|
||||
[DllImport("Powrprof.dll", SetLastError = true)]
|
||||
static extern uint PowerRegisterSuspendResumeNotification(uint flags, ref DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS receipient, ref IntPtr registrationHandle);
|
||||
|
||||
|
||||
private const int WM_POWERBROADCAST = 536; // (0x218)
|
||||
private const int PBT_APMPOWERSTATUSCHANGE = 10; // (0xA) - Power status has changed.
|
||||
private const int PBT_APMRESUMEAUTOMATIC = 18; // (0x12) - Operation is resuming automatically from a low-power state.This message is sent every time the system resumes.
|
||||
private const int PBT_APMRESUMESUSPEND = 7; // (0x7) - Operation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
|
||||
private const int PBT_APMSUSPEND = 4; // (0x4) - System is suspending operation.
|
||||
private const int PBT_POWERSETTINGCHANGE = 32787; // (0x8013) - A power setting change event has been received.
|
||||
private const int DEVICE_NOTIFY_CALLBACK = 2;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
|
||||
{
|
||||
public DeviceNotifyCallbackRoutine Callback;
|
||||
public IntPtr Context;
|
||||
}
|
||||
|
||||
public delegate int DeviceNotifyCallbackRoutine(IntPtr context, int type, IntPtr setting);
|
||||
|
||||
//
|
||||
|
||||
public static NotifyIcon trayIcon = new NotifyIcon
|
||||
{
|
||||
Text = "G-Helper",
|
||||
@@ -75,7 +102,6 @@ namespace GHelper
|
||||
wmi.SubscribeToEvents(WatcherEventArrived);
|
||||
|
||||
settingsForm.InitGPUMode();
|
||||
settingsForm.InitBoost();
|
||||
settingsForm.InitAura();
|
||||
settingsForm.InitMatrix();
|
||||
|
||||
@@ -85,6 +111,16 @@ namespace GHelper
|
||||
|
||||
SetAutoModes();
|
||||
|
||||
IntPtr registrationHandle = new IntPtr();
|
||||
DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS();
|
||||
recipient.Callback = new DeviceNotifyCallbackRoutine(DeviceNotifyCallback);
|
||||
recipient.Context = IntPtr.Zero;
|
||||
|
||||
IntPtr pRecipient = Marshal.AllocHGlobal(Marshal.SizeOf(recipient));
|
||||
Marshal.StructureToPtr(recipient, pRecipient, false);
|
||||
|
||||
uint result = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, ref recipient, ref registrationHandle);
|
||||
|
||||
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
|
||||
|
||||
IntPtr ds = settingsForm.Handle;
|
||||
@@ -93,6 +129,28 @@ namespace GHelper
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static int DeviceNotifyCallback(IntPtr context, int type, IntPtr setting)
|
||||
{
|
||||
//Debug.WriteLine($"Power callback type: {type}");
|
||||
switch (type)
|
||||
{
|
||||
case PBT_APMRESUMEAUTOMATIC:
|
||||
settingsForm.BeginInvoke(delegate
|
||||
{
|
||||
// Setting "other" mode to prevent bios bugging with PPTs after wake up from sleep
|
||||
int PerformanceMode = (config.getConfig("performance_mode") + 1) % 3;
|
||||
wmi.DeviceSet(ASUSWmi.PerformanceMode, PerformanceMode);
|
||||
Thread.Sleep(1000);
|
||||
|
||||
SetAutoModes();
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void SetAutoModes()
|
||||
{
|
||||
PowerLineStatus isPlugged = SystemInformation.PowerStatus.PowerLineStatus;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# G-Helper (For Asus ROG Zephyrus G14, G15, Flow X13, Flow X16, and others)
|
||||
# G-Helper / GHelper for Asus ROG Zephyrus G14, G15, Flow X13, Flow X16, and other models
|
||||
|
||||
A small utility that allows you do almost everyting you could do with Armory Crate but without extra bloat and unnecessary services.
|
||||
|
||||
|
||||
15
Settings.Designer.cs
generated
15
Settings.Designer.cs
generated
@@ -48,7 +48,6 @@
|
||||
checkStartup = new CheckBox();
|
||||
panelPerformance = new Panel();
|
||||
buttonFans = new Button();
|
||||
checkBoost = new CheckBox();
|
||||
picturePerf = new PictureBox();
|
||||
labelPerf = new Label();
|
||||
labelCPUFan = new Label();
|
||||
@@ -323,7 +322,6 @@
|
||||
// panelPerformance
|
||||
//
|
||||
panelPerformance.Controls.Add(buttonFans);
|
||||
panelPerformance.Controls.Add(checkBoost);
|
||||
panelPerformance.Controls.Add(picturePerf);
|
||||
panelPerformance.Controls.Add(labelPerf);
|
||||
panelPerformance.Controls.Add(labelCPUFan);
|
||||
@@ -348,18 +346,6 @@
|
||||
buttonFans.Text = "Fans and Power";
|
||||
buttonFans.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// checkBoost
|
||||
//
|
||||
checkBoost.AutoSize = true;
|
||||
checkBoost.ForeColor = SystemColors.GrayText;
|
||||
checkBoost.Location = new Point(27, 154);
|
||||
checkBoost.Margin = new Padding(4, 2, 4, 2);
|
||||
checkBoost.Name = "checkBoost";
|
||||
checkBoost.Size = new Size(320, 36);
|
||||
checkBoost.TabIndex = 33;
|
||||
checkBoost.Text = "CPU Turbo Boost enabled";
|
||||
checkBoost.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// picturePerf
|
||||
//
|
||||
picturePerf.BackgroundImage = (Image)resources.GetObject("picturePerf.BackgroundImage");
|
||||
@@ -872,7 +858,6 @@
|
||||
private CheckBox checkStartup;
|
||||
private Panel panelPerformance;
|
||||
private Button buttonFans;
|
||||
private CheckBox checkBoost;
|
||||
private PictureBox picturePerf;
|
||||
private Label labelPerf;
|
||||
private Label labelCPUFan;
|
||||
|
||||
79
Settings.cs
79
Settings.cs
@@ -61,7 +61,6 @@ namespace GHelper
|
||||
|
||||
buttonQuit.Click += ButtonQuit_Click;
|
||||
|
||||
checkBoost.Click += CheckBoost_Click;
|
||||
|
||||
checkScreen.CheckedChanged += checkScreen_CheckedChanged;
|
||||
|
||||
@@ -93,11 +92,26 @@ namespace GHelper
|
||||
|
||||
buttonMatrix.Click += ButtonMatrix_Click;
|
||||
|
||||
checkStartup.CheckedChanged += CheckStartup_CheckedChanged;
|
||||
|
||||
SetTimer();
|
||||
|
||||
}
|
||||
|
||||
private void CheckStartup_CheckedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is null) return;
|
||||
CheckBox chk = (CheckBox)sender;
|
||||
|
||||
if (chk.Checked)
|
||||
{
|
||||
Startup.Schedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
Startup.UnSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckMatrix_CheckedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
@@ -468,19 +482,6 @@ namespace GHelper
|
||||
SetAuraMode(cmb.SelectedIndex);
|
||||
}
|
||||
|
||||
|
||||
private void CheckBoost_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is null)
|
||||
return;
|
||||
|
||||
CheckBox chk = (CheckBox)sender;
|
||||
if (chk.Checked)
|
||||
NativeMethods.SetCPUBoost(2);
|
||||
else
|
||||
NativeMethods.SetCPUBoost(0);
|
||||
}
|
||||
|
||||
private void Button120Hz_Click(object? sender, EventArgs e)
|
||||
{
|
||||
SetScreen(1000, 1);
|
||||
@@ -523,13 +524,6 @@ namespace GHelper
|
||||
InitScreen();
|
||||
}
|
||||
|
||||
|
||||
public void InitBoost()
|
||||
{
|
||||
int boost = NativeMethods.GetCPUBoost();
|
||||
checkBoost.Checked = (boost > 0);
|
||||
}
|
||||
|
||||
public void InitScreen()
|
||||
{
|
||||
|
||||
@@ -702,12 +696,28 @@ namespace GHelper
|
||||
Program.wmi.DeviceSet(ASUSWmi.PPT_TotalA0, limit_total);
|
||||
Program.wmi.DeviceSet(ASUSWmi.PPT_TotalA1, limit_total);
|
||||
Program.wmi.DeviceSet(ASUSWmi.PPT_CPUB0, limit_cpu);
|
||||
|
||||
|
||||
Debug.WriteLine(limit_total.ToString() + ", " + limit_cpu.ToString());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void AutoFansAndPower()
|
||||
{
|
||||
|
||||
if (Program.config.getConfigPerf("auto_apply") == 1)
|
||||
{
|
||||
Program.wmi.SetFanCurve(0, Program.config.getFanConfig(0));
|
||||
Program.wmi.SetFanCurve(1, Program.config.getFanConfig(1));
|
||||
}
|
||||
|
||||
if (Program.config.getConfigPerf("auto_apply_power") == 1)
|
||||
{
|
||||
SetPower();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPerformanceMode(int PerformanceMode = ASUSWmi.PerformanceBalanced, bool notify = false)
|
||||
{
|
||||
|
||||
@@ -738,16 +748,7 @@ namespace GHelper
|
||||
|
||||
Program.wmi.DeviceSet(ASUSWmi.PerformanceMode, PerformanceMode);
|
||||
|
||||
if (Program.config.getConfigPerf("auto_apply") == 1)
|
||||
{
|
||||
Program.wmi.SetFanCurve(0, Program.config.getFanConfig(0));
|
||||
Program.wmi.SetFanCurve(1, Program.config.getFanConfig(1));
|
||||
}
|
||||
|
||||
if (Program.config.getConfigPerf("auto_apply_power") == 1)
|
||||
{
|
||||
SetPower();
|
||||
}
|
||||
AutoFansAndPower();
|
||||
|
||||
if (fans != null && fans.Text != "")
|
||||
{
|
||||
@@ -755,6 +756,8 @@ namespace GHelper
|
||||
fans.InitPower();
|
||||
}
|
||||
|
||||
Debug.WriteLine("Perf:" + PerformanceMode);
|
||||
|
||||
if (notify && (oldMode != PerformanceMode))
|
||||
{
|
||||
try
|
||||
@@ -985,18 +988,6 @@ namespace GHelper
|
||||
{
|
||||
checkStartup.Checked = status;
|
||||
}
|
||||
private void checkStartup_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
CheckBox chk = (CheckBox)sender;
|
||||
if (chk.Checked)
|
||||
{
|
||||
Startup.Schedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
Startup.UnSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBatteryChargeLimit(int limit)
|
||||
{
|
||||
|
||||
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.4 MiB |
Reference in New Issue
Block a user