242 lines
8.2 KiB
C#
242 lines
8.2 KiB
C#
/*
|
|
* Created by SharpDevelop.
|
|
* User: EVXIO
|
|
* Date: 4/3/2025
|
|
* Time: 10:01 PM
|
|
*
|
|
* To change this template use Tools | Options | Coding | Edit Standard Headers.
|
|
*/
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
using System.Text;
|
|
|
|
namespace UPSNet {
|
|
public sealed class NotificationIcon {
|
|
private NotifyIcon notifyIcon;
|
|
private ContextMenu notificationMenu;
|
|
|
|
private readonly BackgroundTimer _monitoringTimer;
|
|
|
|
//UPSApp upsApp = new UPSApp();
|
|
|
|
private static NotificationIcon _instance;
|
|
|
|
private static int lastState = -1; //for save cpu by checking state
|
|
|
|
// Changed to .NET 4.0 compatible property
|
|
public static NotifyIcon NotifyIconInstance {
|
|
get { return _instance != null ? _instance.notifyIcon : null; }
|
|
}
|
|
|
|
#region Initialize icon and menu
|
|
public NotificationIcon() {
|
|
_instance = this;
|
|
notifyIcon = new NotifyIcon();
|
|
notificationMenu = new ContextMenu(InitializeMenu());
|
|
|
|
notifyIcon.BalloonTipText = "Application is running in the background";
|
|
notifyIcon.BalloonTipTitle = "UPS Net v1.0";
|
|
notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
|
|
notifyIcon.Text = "UPS Net \nBattery: - "; // This is the regular tooltip
|
|
|
|
notifyIcon.DoubleClick += IconDoubleClick;
|
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotificationIcon));
|
|
notifyIcon.Icon = (Icon)resources.GetObject("$this.Icon");
|
|
notifyIcon.ContextMenu = notificationMenu;
|
|
|
|
_monitoringTimer = new BackgroundTimer(CheckUPSStatus, 1000);
|
|
}
|
|
|
|
private MenuItem[] InitializeMenu() {
|
|
MenuItem[] menu = new MenuItem[]
|
|
{
|
|
new MenuItem("Show", menuShowClick),
|
|
new MenuItem("-"), // Separator
|
|
new MenuItem("About", menuAboutClick),
|
|
new MenuItem("Exit", menuExitClick)
|
|
};
|
|
|
|
// Enable OwnerDraw for each MenuItem (except separators)
|
|
foreach (MenuItem item in menu) {
|
|
if (item.Text != "-")
|
|
{
|
|
item.OwnerDraw = true;
|
|
// Attach events to EACH MenuItem (not ContextMenu)
|
|
item.DrawItem += MenuItem_DrawItem;
|
|
item.MeasureItem += MenuItem_MeasureItem;
|
|
}
|
|
}
|
|
|
|
return menu;
|
|
}
|
|
|
|
// Handle drawing for EACH MenuItem
|
|
private void MenuItem_DrawItem(object sender, DrawItemEventArgs e){
|
|
MenuItem menuItem = (MenuItem)sender;
|
|
|
|
// Draw background
|
|
e.DrawBackground();
|
|
|
|
// Draw icon (if available)
|
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotificationIcon));
|
|
Image icon = null;
|
|
switch (menuItem.Text) {
|
|
case "Show": icon = (Image) resources.GetObject("dashboard16"); break;
|
|
case "About": icon = (Image) resources.GetObject("info16"); break;
|
|
case "Exit": icon = (Image) resources.GetObject("close16"); break;
|
|
//case "About": icon = Properties.Resources.AboutIcon; break;
|
|
//case "Exit": icon = Properties.Resources.ExitIcon; break;
|
|
}
|
|
|
|
if (icon != null){
|
|
e.Graphics.DrawImage(
|
|
icon,
|
|
new Rectangle(
|
|
e.Bounds.X + 2,
|
|
e.Bounds.Y + (e.Bounds.Height - 16) / 2,
|
|
16,
|
|
16
|
|
)
|
|
);
|
|
}
|
|
|
|
// Draw text
|
|
TextRenderer.DrawText(
|
|
e.Graphics,
|
|
menuItem.Text,
|
|
SystemFonts.MenuFont,
|
|
new Rectangle(e.Bounds.X + 20, e.Bounds.Y, e.Bounds.Width - 20, e.Bounds.Height),
|
|
e.ForeColor,
|
|
TextFormatFlags.VerticalCenter | TextFormatFlags.Left
|
|
);
|
|
}
|
|
|
|
// Measure each MenuItem
|
|
private void MenuItem_MeasureItem(object sender, MeasureItemEventArgs e){
|
|
MenuItem menuItem = (MenuItem)sender;
|
|
SizeF textSize = e.Graphics.MeasureString(menuItem.Text, SystemFonts.MenuFont);
|
|
e.ItemHeight = Math.Max(16, (int)textSize.Height) + 4;
|
|
e.ItemWidth = (int)textSize.Width + 20; // 16 (icon) + 4 (padding)
|
|
}
|
|
#endregion
|
|
|
|
#region Main - Program entry point
|
|
/// <summary>Program entry point.</summary>
|
|
/// <param name="args">Command Line Arguments</param>
|
|
[STAThread]
|
|
public static void Main(string[] args) {
|
|
Application.EnableVisualStyles();
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
bool isFirstInstance;
|
|
// Please use a unique name for the mutex to prevent conflicts with other programs
|
|
using (Mutex mtx = new Mutex(true, "UPSNet", out isFirstInstance)) {
|
|
if (isFirstInstance) {
|
|
|
|
UPSApp.Init();
|
|
|
|
NotificationIcon notificationIcon = new NotificationIcon();
|
|
notificationIcon.notifyIcon.Visible = true;
|
|
|
|
if (SynchronizationContext.Current == null) {
|
|
SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext());
|
|
}
|
|
UPSApp.uiContext = SynchronizationContext.Current;
|
|
|
|
Application.Run();
|
|
|
|
notificationIcon.notifyIcon.Dispose();
|
|
} else {
|
|
// The application is already running
|
|
// TODO: Display message box or change focus to existing application instance
|
|
}
|
|
} // releases the Mutex
|
|
}
|
|
#endregion
|
|
|
|
#region Event Handlers
|
|
private void menuAboutClick(object sender, EventArgs e) {
|
|
MessageBox.Show(
|
|
"EVXIO UPS Net \nVersion 1.0.0 - Portable Edition \n\nCopyright ©2025 Victor Phoa. All Rights Reserved.",
|
|
"About - EVXIO UPS Net",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information
|
|
);
|
|
}
|
|
|
|
private void menuExitClick(object sender, EventArgs e) {
|
|
Application.Exit();
|
|
}
|
|
|
|
private void IconDoubleClick(object sender, EventArgs e) {
|
|
UPSApp.ShowOrHideForm();
|
|
//MessageBox.Show("The icon was double clicked");
|
|
}
|
|
|
|
private void menuShowClick(object sender, EventArgs e) {
|
|
UPSApp.ShowForm();
|
|
//MessageBox.Show("The icon was double clicked");
|
|
}
|
|
#endregion
|
|
|
|
public static string RepeatString(string str, int count){
|
|
if (count <= 0) return "";//string.Empty;
|
|
if (count == 1) return str;
|
|
|
|
var sb = new StringBuilder(str.Length * count);
|
|
for (int i = 0; i < count; i++) {
|
|
sb.Append(str);
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static void CheckUPSStatus() {
|
|
//string s = "";
|
|
if (UPSApp.fetcher.IsReachable) {
|
|
//s += "OnShut=" + UPSApp.fetcher.OnTimedShutdown + " Remaining=" + UPSApp.fetcher.TimedShutdownRemaining;
|
|
if (NotifyIconInstance != null) { // Explicit null check
|
|
if (UPSApp.fetcher.OnState){
|
|
int maxBars = 4;
|
|
int barCount = 0;
|
|
if (UPSApp.fetcher.BattMaxLevel > 0) {
|
|
barCount = (int)Math.Round((double)UPSApp.fetcher.ChargeLevel * maxBars / UPSApp.fetcher.BattMaxLevel);
|
|
} else {
|
|
barCount = UPSApp.fetcher.ChargeLevel > 4 ? (int)Math.Round(UPSApp.fetcher.ChargeLevel / 25.0) : UPSApp.fetcher.ChargeLevel;
|
|
}
|
|
barCount = Math.Max(0, Math.Min(maxBars, barCount));
|
|
|
|
if (lastState != (100 + barCount)){
|
|
lastState = 100 + barCount;
|
|
NotifyIconInstance.Text = "UPS Net \nBattery: " +
|
|
RepeatString("■", barCount) +
|
|
RepeatString(" ", maxBars - barCount);
|
|
}
|
|
}else{
|
|
if (lastState!=200){
|
|
lastState = 200;
|
|
NotifyIconInstance.Text = "UPS Net \nUPS OFF";
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
//s = "Unreachable";
|
|
if (NotifyIconInstance != null){
|
|
if (lastState!=300){
|
|
lastState = 300;
|
|
NotifyIconInstance.Text = "UPS Net \nNot Connected";
|
|
}
|
|
}
|
|
}
|
|
//Debug.WriteLine("CheckUPSStatus: " + s);
|
|
|
|
|
|
//UPSApp.ManageShutdownRoutine(); //this now managed from OnStatusChanged ata UPSApp
|
|
|
|
}
|
|
}
|
|
}
|