Added dynamic icon (displays battery state)
This commit is contained in:
parent
aedeb4a6bb
commit
116750ec58
67
SoraV2Utils_Agent/DynamicIcon.cs
Normal file
67
SoraV2Utils_Agent/DynamicIcon.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing.Text;
|
||||
|
||||
namespace SoraV2Utils_Agent
|
||||
{
|
||||
internal class DynamicIcon
|
||||
{
|
||||
public static Icon CreateIcon(string text, Color textColor, Font font)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text) || text.Length > 3)
|
||||
throw new ArgumentException("Text must be between 1 and 3 characters long.", nameof(text));
|
||||
|
||||
// Create a 32x32 transparent bitmap
|
||||
using (Bitmap bitmap = new Bitmap(32, 32))
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(bitmap))
|
||||
{
|
||||
// Set up transparency
|
||||
g.Clear(Color.Transparent);
|
||||
|
||||
// Enable anti-aliasing for smoother text
|
||||
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
|
||||
|
||||
// Determine the largest font size that will fit within 32x32
|
||||
float maxFontSize = 48; // Start with a large font size
|
||||
SizeF textSize;
|
||||
Font adjustedFont;
|
||||
do
|
||||
{
|
||||
maxFontSize--;
|
||||
adjustedFont = new Font(font.FontFamily, maxFontSize, font.Style);
|
||||
textSize = g.MeasureString(text, adjustedFont);
|
||||
}
|
||||
while ((textSize.Width > 42 || textSize.Height > 42) && maxFontSize > 1);
|
||||
|
||||
if (textSize.Width > 42 || textSize.Height > 42)
|
||||
{
|
||||
// Reduce back if the scaled size exceeds 32x32
|
||||
maxFontSize /= 1.25f;
|
||||
adjustedFont = new Font(font.FontFamily, maxFontSize, font.Style);
|
||||
textSize = g.MeasureString(text, adjustedFont);
|
||||
}
|
||||
|
||||
// Calculate the position to center the text
|
||||
float x = (32 - textSize.Width) / 2;
|
||||
float y = (32 - textSize.Height) / 2;
|
||||
|
||||
// Draw the text
|
||||
using (SolidBrush textBrush = new SolidBrush(textColor))
|
||||
{
|
||||
g.DrawString(text, adjustedFont, textBrush, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and return the icon
|
||||
return Icon.FromHandle(bitmap.GetHicon());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
SoraV2Utils_Agent/TrayIconForm.cs
Normal file
94
SoraV2Utils_Agent/TrayIconForm.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
|
||||
namespace SoraV2Utils_Agent
|
||||
{
|
||||
public class TrayIconForm
|
||||
{
|
||||
public TrayIconForm()
|
||||
{
|
||||
// Create a NotifyIcon instance
|
||||
using (NotifyIcon trayIcon = new NotifyIcon())
|
||||
{
|
||||
// Set up the tray icon properties
|
||||
trayIcon.Icon = new Icon(DynamicIcon.CreateIcon("##",Color.Red, SystemFonts.IconTitleFont), 40, 40); // Choose your own icon
|
||||
trayIcon.Visible = true;
|
||||
|
||||
// Create a context menu
|
||||
var contextMenu = new ContextMenu();
|
||||
|
||||
// Add a non-clickable dynamic text item
|
||||
var batteryLevelItem = new MenuItem("Battery Level: Loading...");
|
||||
var batteryRuntimeItem = new MenuItem("Battery Runtime: Loading...");
|
||||
batteryLevelItem.Enabled = false;
|
||||
batteryRuntimeItem.Enabled = false;
|
||||
|
||||
contextMenu.MenuItems.Add("Exit", (sender, e) => ServiceIPC.Instance.Exit());
|
||||
contextMenu.MenuItems.Add("Check for Update ", (sender, e) => UpdateCheck.CheckUpdate());
|
||||
|
||||
contextMenu.MenuItems.Add(batteryLevelItem);
|
||||
contextMenu.MenuItems.Add(batteryRuntimeItem);
|
||||
|
||||
trayIcon.ContextMenu = contextMenu;
|
||||
|
||||
// Update the dynamic text in the context menu
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Format battery level with charging status
|
||||
string batteryLevelText = ServiceIPC.DeviceStatus.Charging == 1
|
||||
? $"Battery Level: {ServiceIPC.DeviceStatus.Battery} (Charging...)"
|
||||
: $"Battery Level: {ServiceIPC.DeviceStatus.Battery}";
|
||||
|
||||
// Format battery runtime (convert minutes to hours and minutes)
|
||||
string batteryRuntimeText = FormatBatteryRuntime(ServiceIPC.BatteryRuntime);
|
||||
|
||||
// Update the context menu items
|
||||
batteryLevelItem.Text = batteryLevelText;
|
||||
batteryRuntimeItem.Text = $"Battery Runtime: {batteryRuntimeText}";
|
||||
batteryRuntimeItem.Text = $"Battery Runtime: {batteryRuntimeText}";
|
||||
trayIcon.Icon = new Icon(DynamicIcon.CreateIcon(ServiceIPC.DeviceStatus.Battery.ToString(), Color.White, new Font("Arial",32)), 32, 32);
|
||||
|
||||
// Update every second
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
});
|
||||
|
||||
Application.Run();
|
||||
}
|
||||
}
|
||||
|
||||
// Formats the runtime in hours and minutes.
|
||||
private string FormatBatteryRuntime(double runtimeInMinutes)
|
||||
{
|
||||
if(runtimeInMinutes < 0)
|
||||
{
|
||||
return "No data yet";
|
||||
}
|
||||
|
||||
int hours = (int)(runtimeInMinutes / 60);
|
||||
int minutes = (int)(runtimeInMinutes % 60);
|
||||
|
||||
// If runtime is greater than 1 hour, display hours and minutes
|
||||
if (hours > 0)
|
||||
{
|
||||
return $"{hours} hour{(hours > 1 ? "s" : "")} {minutes} minute{(minutes > 1 ? "s" : "")}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{minutes} minute{(minutes > 1 ? "s" : "")}";
|
||||
}
|
||||
}
|
||||
|
||||
public void Display()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user