diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c7473d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/bin +/obj diff --git a/App.config b/App.config new file mode 100644 index 0000000..d60005b --- /dev/null +++ b/App.config @@ -0,0 +1,21 @@ + + + + +
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/IconBrowser.Designer.cs b/IconBrowser.Designer.cs new file mode 100644 index 0000000..26f5141 --- /dev/null +++ b/IconBrowser.Designer.cs @@ -0,0 +1,317 @@ +namespace OledMonitor +{ + partial class IconBrowser + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panelTop = new System.Windows.Forms.Panel(); + this.btnBrowse = new System.Windows.Forms.Button(); + this.txtIconDirectory = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.panelBottom = new System.Windows.Forms.Panel(); + this.txtIconDimensions = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.numY = new System.Windows.Forms.NumericUpDown(); + this.numX = new System.Windows.Forms.NumericUpDown(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.txtIconName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.btnCancel = new System.Windows.Forms.Button(); + this.btnInsert = new System.Windows.Forms.Button(); + this.lblStatus = new System.Windows.Forms.Label(); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.lstIcons = new System.Windows.Forms.ListBox(); + this.flowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); + this.panelTop.SuspendLayout(); + this.panelBottom.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numY)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numX)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // panelTop + // + this.panelTop.Controls.Add(this.btnBrowse); + this.panelTop.Controls.Add(this.txtIconDirectory); + this.panelTop.Controls.Add(this.label1); + this.panelTop.Dock = System.Windows.Forms.DockStyle.Top; + this.panelTop.Location = new System.Drawing.Point(0, 0); + this.panelTop.Name = "panelTop"; + this.panelTop.Size = new System.Drawing.Size(584, 40); + this.panelTop.TabIndex = 0; + // + // btnBrowse + // + this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnBrowse.Location = new System.Drawing.Point(497, 9); + this.btnBrowse.Name = "btnBrowse"; + this.btnBrowse.Size = new System.Drawing.Size(75, 23); + this.btnBrowse.TabIndex = 2; + this.btnBrowse.Text = "Browse..."; + this.btnBrowse.UseVisualStyleBackColor = true; + this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click); + // + // txtIconDirectory + // + this.txtIconDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtIconDirectory.Location = new System.Drawing.Point(119, 10); + this.txtIconDirectory.Name = "txtIconDirectory"; + this.txtIconDirectory.Size = new System.Drawing.Size(372, 23); + this.txtIconDirectory.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 13); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(101, 15); + this.label1.TabIndex = 0; + this.label1.Text = "Icons Directory:"; + // + // panelBottom + // + this.panelBottom.Controls.Add(this.txtIconDimensions); + this.panelBottom.Controls.Add(this.label5); + this.panelBottom.Controls.Add(this.numY); + this.panelBottom.Controls.Add(this.numX); + this.panelBottom.Controls.Add(this.label4); + this.panelBottom.Controls.Add(this.label3); + this.panelBottom.Controls.Add(this.txtIconName); + this.panelBottom.Controls.Add(this.label2); + this.panelBottom.Controls.Add(this.btnCancel); + this.panelBottom.Controls.Add(this.btnInsert); + this.panelBottom.Controls.Add(this.lblStatus); + this.panelBottom.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panelBottom.Location = new System.Drawing.Point(0, 341); + this.panelBottom.Name = "panelBottom"; + this.panelBottom.Size = new System.Drawing.Size(584, 120); + this.panelBottom.TabIndex = 1; + // + // txtIconDimensions + // + this.txtIconDimensions.Location = new System.Drawing.Point(119, 39); + this.txtIconDimensions.Name = "txtIconDimensions"; + this.txtIconDimensions.ReadOnly = true; + this.txtIconDimensions.Size = new System.Drawing.Size(100, 23); + this.txtIconDimensions.TabIndex = 10; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(12, 42); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(77, 15); + this.label5.TabIndex = 9; + this.label5.Text = "Dimensions:"; + // + // numY + // + this.numY.Location = new System.Drawing.Point(119, 82); + this.numY.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.numY.Name = "numY"; + this.numY.Size = new System.Drawing.Size(60, 23); + this.numY.TabIndex = 8; + // + // numX + // + this.numX.Location = new System.Drawing.Point(119, 68); + this.numX.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.numX.Name = "numX"; + this.numX.Size = new System.Drawing.Size(60, 23); + this.numX.TabIndex = 7; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(12, 84); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 15); + this.label4.TabIndex = 6; + this.label4.Text = "Y Position:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(12, 70); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(67, 15); + this.label3.TabIndex = 5; + this.label3.Text = "X Position:"; + // + // txtIconName + // + this.txtIconName.Location = new System.Drawing.Point(119, 10); + this.txtIconName.Name = "txtIconName"; + this.txtIconName.ReadOnly = true; + this.txtIconName.Size = new System.Drawing.Size(200, 23); + this.txtIconName.TabIndex = 4; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 13); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(101, 15); + this.label2.TabIndex = 3; + this.label2.Text = "Selected Icon:"; + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(497, 85); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 2; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // btnInsert + // + this.btnInsert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnInsert.Location = new System.Drawing.Point(416, 85); + this.btnInsert.Name = "btnInsert"; + this.btnInsert.Size = new System.Drawing.Size(75, 23); + this.btnInsert.TabIndex = 1; + this.btnInsert.Text = "Insert"; + this.btnInsert.UseVisualStyleBackColor = true; + this.btnInsert.Click += new System.EventHandler(this.btnInsert_Click); + // + // lblStatus + // + this.lblStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.lblStatus.AutoSize = true; + this.lblStatus.Location = new System.Drawing.Point(325, 13); + this.lblStatus.Name = "lblStatus"; + this.lblStatus.Size = new System.Drawing.Size(0, 15); + this.lblStatus.TabIndex = 0; + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.Location = new System.Drawing.Point(0, 40); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.lstIcons); + this.splitContainer.Panel1Collapsed = true; + this.splitContainer.Panel1MinSize = 0; + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.flowLayoutPanel); + this.splitContainer.Size = new System.Drawing.Size(584, 301); + this.splitContainer.SplitterDistance = 194; + this.splitContainer.TabIndex = 2; + // + // lstIcons + // + this.lstIcons.Dock = System.Windows.Forms.DockStyle.Fill; + this.lstIcons.FormattingEnabled = true; + this.lstIcons.ItemHeight = 15; + this.lstIcons.Location = new System.Drawing.Point(0, 0); + this.lstIcons.Name = "lstIcons"; + this.lstIcons.Size = new System.Drawing.Size(194, 301); + this.lstIcons.TabIndex = 0; + // + // flowLayoutPanel + // + this.flowLayoutPanel.AutoScroll = true; + this.flowLayoutPanel.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.flowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel.Location = new System.Drawing.Point(0, 0); + this.flowLayoutPanel.Name = "flowLayoutPanel"; + this.flowLayoutPanel.Padding = new System.Windows.Forms.Padding(10); + this.flowLayoutPanel.Size = new System.Drawing.Size(584, 301); + this.flowLayoutPanel.TabIndex = 0; + // + // IconBrowser + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 461); + this.Controls.Add(this.splitContainer); + this.Controls.Add(this.panelBottom); + this.Controls.Add(this.panelTop); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(400, 400); + this.Name = "IconBrowser"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Icon Browser"; + this.Load += new System.EventHandler(this.IconBrowser_Load); + this.panelTop.ResumeLayout(false); + this.panelTop.PerformLayout(); + this.panelBottom.ResumeLayout(false); + this.panelBottom.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numY)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numX)).EndInit(); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private Panel panelTop; + private Button btnBrowse; + private TextBox txtIconDirectory; + private Label label1; + private Panel panelBottom; + private Button btnCancel; + private Button btnInsert; + private Label lblStatus; + private SplitContainer splitContainer; + private ListBox lstIcons; + private FlowLayoutPanel flowLayoutPanel; + private TextBox txtIconName; + private Label label2; + private NumericUpDown numY; + private NumericUpDown numX; + private Label label4; + private Label label3; + private TextBox txtIconDimensions; + private Label label5; + } +} \ No newline at end of file diff --git a/IconBrowser.cs b/IconBrowser.cs new file mode 100644 index 0000000..472c179 --- /dev/null +++ b/IconBrowser.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Windows.Forms; + +namespace OledMonitor +{ + public partial class IconBrowser : Form + { + private string _selectedIconPath = ""; + private int _selectedIconWidth = 0; + private int _selectedIconHeight = 0; + public string SelectedIconName { get; private set; } = ""; + + public IconBrowser() + { + InitializeComponent(); + } + + private void IconBrowser_Load(object? sender, EventArgs e) + { + // Load last used directory from settings if available + string lastDir = Properties.Settings.Default.LastIconDirectory; + if (!string.IsNullOrEmpty(lastDir) && Directory.Exists(lastDir)) + { + txtIconDirectory.Text = lastDir; + LoadIconsFromDirectory(lastDir); + } + } + + private void btnBrowse_Click(object? sender, EventArgs e) + { + using FolderBrowserDialog dialog = new(); + if (!string.IsNullOrEmpty(txtIconDirectory.Text) && Directory.Exists(txtIconDirectory.Text)) + { + dialog.InitialDirectory = txtIconDirectory.Text; + } + + if (dialog.ShowDialog() == DialogResult.OK) + { + txtIconDirectory.Text = dialog.SelectedPath; + LoadIconsFromDirectory(dialog.SelectedPath); + + // Save the directory for next time + Properties.Settings.Default.LastIconDirectory = dialog.SelectedPath; + Properties.Settings.Default.Save(); + } + } + + private void LoadIconsFromDirectory(string directory) + { + try + { + lstIcons.Items.Clear(); + flowLayoutPanel.Controls.Clear(); + + string[] xbmFiles = Directory.GetFiles(directory, "*.bin"); + if (xbmFiles.Length == 0) + { + MessageBox.Show("No XBM icon files found in the selected directory.", + "No Icons Found", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + foreach (string file in xbmFiles) + { + // Create a button for each icon + Button iconButton = new(); + + // Parse the XBM file to get dimensions + (int width, int height) = ParseXbmDimensions(file); + + string fileName = Path.GetFileNameWithoutExtension(file); + iconButton.Text = $"{fileName} ({width}x{height})"; + iconButton.Tag = new IconInfo + { + Path = file, + Name = fileName, + Width = width, + Height = height + }; + + iconButton.Size = new Size(150, 40); + iconButton.Click += IconButton_Click; + flowLayoutPanel.Controls.Add(iconButton); + } + + lblStatus.Text = $"Found {xbmFiles.Length} XBM files"; + } + catch (Exception ex) + { + MessageBox.Show($"Error loading icons: {ex.Message}", + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private (int width, int height) ParseXbmDimensions(string filePath) + { + int width = 0; + int height = 0; + + try + { + // Read the first few lines of the XBM file + using StreamReader reader = new(filePath); + string line; + while ((line = reader.ReadLine()) != null && (width == 0 || height == 0)) + { + // Look for width and height definitions in XBM format + if (line.Contains("_width")) + { + width = ExtractNumberFromLine(line); + } + else if (line.Contains("_height")) + { + height = ExtractNumberFromLine(line); + } + } + } + catch + { + // If we can't parse, default to unknown dimensions + width = 0; + height = 0; + } + + return (width, height); + } + + private int ExtractNumberFromLine(string line) + { + // Extract the numeric value from a line like "#define icon_width 16" + try + { + string[] parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length >= 3) + { + if (int.TryParse(parts[2], out int result)) + { + return result; + } + } + } + catch { } + + return 0; + } + + private void IconButton_Click(object? sender, EventArgs e) + { + if (sender is Button button && button.Tag is IconInfo info) + { + // Highlight the selected button + foreach (Control control in flowLayoutPanel.Controls) + { + if (control is Button btn) + { + btn.BackColor = SystemColors.Control; + } + } + button.BackColor = Color.LightBlue; + + // Store the selected icon info + SelectedIconName = info.Name; + _selectedIconPath = info.Path; + _selectedIconWidth = info.Width; + _selectedIconHeight = info.Height; + + // Update UI + txtIconName.Text = info.Name; + txtIconDimensions.Text = $"{info.Width} x {info.Height}"; + numX.Value = 0; + numY.Value = 0; + } + } + + private void btnInsert_Click(object? sender, EventArgs e) + { + if (string.IsNullOrEmpty(SelectedIconName)) + { + MessageBox.Show("Please select an icon first.", + "No Icon Selected", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + // Mark as success and close + DialogResult = DialogResult.OK; + Close(); + } + + private void btnCancel_Click(object? sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + public string GetIconMarkup() + { + if (string.IsNullOrEmpty(SelectedIconName)) + return string.Empty; + + return $""; + } + + // Helper class for icon information + private class IconInfo + { + public string Path { get; set; } = ""; + public string Name { get; set; } = ""; + public int Width { get; set; } + public int Height { get; set; } + } + } +} \ No newline at end of file diff --git a/IconBrowser.resx b/IconBrowser.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/IconBrowser.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs new file mode 100644 index 0000000..3700767 --- /dev/null +++ b/MainForm.Designer.cs @@ -0,0 +1,337 @@ +namespace OledMonitor +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + groupBoxConnection = new GroupBox(); + lblStatus = new Label(); + btnRefreshPorts = new Button(); + btnConnect = new Button(); + comboBoxPorts = new ComboBox(); + label1 = new Label(); + groupBoxMarkup = new GroupBox(); + splitContainer1 = new SplitContainer(); + txtMarkupEditor = new TextBox(); + label3 = new Label(); + txtHelpText = new TextBox(); + label4 = new Label(); + panelButtons = new Panel(); + chkAutoUpdate = new CheckBox(); + btnSendNow = new Button(); + btnInsertIcon = new Button(); + btnLoadExample = new Button(); + btnRefreshSensors = new Button(); + groupBoxPreview = new GroupBox(); + txtMarkupPreview = new TextBox(); + groupBoxConnection.SuspendLayout(); + groupBoxMarkup.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); + splitContainer1.Panel1.SuspendLayout(); + splitContainer1.Panel2.SuspendLayout(); + splitContainer1.SuspendLayout(); + panelButtons.SuspendLayout(); + groupBoxPreview.SuspendLayout(); + SuspendLayout(); + // + // groupBoxConnection + // + groupBoxConnection.Controls.Add(lblStatus); + groupBoxConnection.Controls.Add(btnRefreshPorts); + groupBoxConnection.Controls.Add(btnConnect); + groupBoxConnection.Controls.Add(comboBoxPorts); + groupBoxConnection.Controls.Add(label1); + groupBoxConnection.Location = new Point(12, 12); + groupBoxConnection.Name = "groupBoxConnection"; + groupBoxConnection.Size = new Size(351, 100); + groupBoxConnection.TabIndex = 0; + groupBoxConnection.TabStop = false; + groupBoxConnection.Text = "Connection"; + // + // lblStatus + // + lblStatus.AutoSize = true; + lblStatus.Location = new Point(15, 73); + lblStatus.Name = "lblStatus"; + lblStatus.Size = new Size(86, 15); + lblStatus.TabIndex = 4; + lblStatus.Text = "Not connected"; + // + // btnRefreshPorts + // + btnRefreshPorts.Location = new Point(150, 38); + btnRefreshPorts.Name = "btnRefreshPorts"; + btnRefreshPorts.Size = new Size(75, 23); + btnRefreshPorts.TabIndex = 3; + btnRefreshPorts.Text = "Refresh"; + btnRefreshPorts.UseVisualStyleBackColor = true; + btnRefreshPorts.Click += btnRefreshPorts_Click; + // + // btnConnect + // + btnConnect.Location = new Point(242, 38); + btnConnect.Name = "btnConnect"; + btnConnect.Size = new Size(89, 23); + btnConnect.TabIndex = 2; + btnConnect.Text = "Connect"; + btnConnect.UseVisualStyleBackColor = true; + btnConnect.Click += btnConnect_Click; + // + // comboBoxPorts + // + comboBoxPorts.DropDownStyle = ComboBoxStyle.DropDownList; + comboBoxPorts.FormattingEnabled = true; + comboBoxPorts.Location = new Point(68, 39); + comboBoxPorts.Name = "comboBoxPorts"; + comboBoxPorts.Size = new Size(76, 23); + comboBoxPorts.TabIndex = 1; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(15, 42); + label1.Name = "label1"; + label1.Size = new Size(63, 15); + label1.TabIndex = 0; + label1.Text = "COM Port:"; + // + // groupBoxMarkup + // + groupBoxMarkup.Controls.Add(splitContainer1); + groupBoxMarkup.Controls.Add(panelButtons); + groupBoxMarkup.Location = new Point(12, 118); + groupBoxMarkup.Name = "groupBoxMarkup"; + groupBoxMarkup.Size = new Size(776, 292); + groupBoxMarkup.TabIndex = 1; + groupBoxMarkup.TabStop = false; + groupBoxMarkup.Text = "Markup Editor"; + // + // splitContainer1 + // + splitContainer1.Dock = DockStyle.Fill; + splitContainer1.Location = new Point(3, 19); + splitContainer1.Name = "splitContainer1"; + splitContainer1.Orientation = Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + splitContainer1.Panel1.Controls.Add(txtMarkupEditor); + splitContainer1.Panel1.Controls.Add(label3); + // + // splitContainer1.Panel2 + // + splitContainer1.Panel2.Controls.Add(txtHelpText); + splitContainer1.Panel2.Controls.Add(label4); + splitContainer1.Size = new Size(770, 224); + splitContainer1.SplitterDistance = 110; + splitContainer1.TabIndex = 0; + // + // txtMarkupEditor + // + txtMarkupEditor.Dock = DockStyle.Fill; + txtMarkupEditor.Font = new Font("Consolas", 9.75F); + txtMarkupEditor.Location = new Point(0, 18); + txtMarkupEditor.Multiline = true; + txtMarkupEditor.Name = "txtMarkupEditor"; + txtMarkupEditor.ScrollBars = ScrollBars.Vertical; + txtMarkupEditor.Size = new Size(770, 92); + txtMarkupEditor.TabIndex = 1; + // + // label3 + // + label3.AutoSize = true; + label3.Dock = DockStyle.Top; + label3.Location = new Point(0, 0); + label3.Name = "label3"; + label3.Padding = new Padding(0, 0, 0, 3); + label3.Size = new Size(577, 18); + label3.TabIndex = 0; + label3.Text = "Enter markup with optional {sensor_variables} (e.g., CPU: {CPU_Total_Load}%)"; + // + // txtHelpText + // + txtHelpText.Dock = DockStyle.Fill; + txtHelpText.Font = new Font("Consolas", 9F); + txtHelpText.Location = new Point(0, 18); + txtHelpText.Multiline = true; + txtHelpText.Name = "txtHelpText"; + txtHelpText.ReadOnly = true; + txtHelpText.ScrollBars = ScrollBars.Vertical; + txtHelpText.Size = new Size(770, 92); + txtHelpText.TabIndex = 1; + // + // label4 + // + label4.AutoSize = true; + label4.Dock = DockStyle.Top; + label4.Location = new Point(0, 0); + label4.Name = "label4"; + label4.Padding = new Padding(0, 0, 0, 3); + label4.Size = new Size(144, 18); + label4.TabIndex = 0; + label4.Text = "Available sensor variables:"; + // + // panelButtons + // + panelButtons.Controls.Add(chkAutoUpdate); + panelButtons.Controls.Add(btnSendNow); + panelButtons.Controls.Add(btnInsertIcon); + panelButtons.Controls.Add(btnLoadExample); + panelButtons.Controls.Add(btnRefreshSensors); + panelButtons.Dock = DockStyle.Bottom; + panelButtons.Location = new Point(3, 243); + panelButtons.Name = "panelButtons"; + panelButtons.Size = new Size(770, 46); + panelButtons.TabIndex = 1; + // + // chkAutoUpdate + // + chkAutoUpdate.AutoSize = true; + chkAutoUpdate.Checked = true; + chkAutoUpdate.CheckState = CheckState.Checked; + chkAutoUpdate.Location = new Point(587, 15); + chkAutoUpdate.Name = "chkAutoUpdate"; + chkAutoUpdate.Size = new Size(171, 19); + chkAutoUpdate.TabIndex = 3; + chkAutoUpdate.Text = "Auto-update display (1 sec)"; + chkAutoUpdate.UseVisualStyleBackColor = true; + chkAutoUpdate.CheckedChanged += chkAutoUpdate_CheckedChanged; + // + // btnSendNow + // + btnSendNow.Location = new Point(483, 11); + btnSendNow.Name = "btnSendNow"; + btnSendNow.Size = new Size(98, 26); + btnSendNow.TabIndex = 2; + btnSendNow.Text = "Send Now"; + btnSendNow.UseVisualStyleBackColor = true; + btnSendNow.Click += btnSendNow_Click; + // + // btnInsertIcon + // + btnInsertIcon.Location = new Point(261, 11); + btnInsertIcon.Name = "btnInsertIcon"; + btnInsertIcon.Size = new Size(123, 26); + btnInsertIcon.TabIndex = 4; + btnInsertIcon.Text = "Insert Icon"; + btnInsertIcon.UseVisualStyleBackColor = true; + btnInsertIcon.Click += btnInsertIcon_Click; + // + // btnLoadExample + // + btnLoadExample.Location = new Point(132, 11); + btnLoadExample.Name = "btnLoadExample"; + btnLoadExample.Size = new Size(123, 26); + btnLoadExample.TabIndex = 1; + btnLoadExample.Text = "Load Example"; + btnLoadExample.UseVisualStyleBackColor = true; + btnLoadExample.Click += btnLoadExample_Click; + // + // btnRefreshSensors + // + btnRefreshSensors.Location = new Point(3, 11); + btnRefreshSensors.Name = "btnRefreshSensors"; + btnRefreshSensors.Size = new Size(123, 26); + btnRefreshSensors.TabIndex = 0; + btnRefreshSensors.Text = "Refresh Sensors"; + btnRefreshSensors.UseVisualStyleBackColor = true; + btnRefreshSensors.Click += btnRefreshSensors_Click; + // + // groupBoxPreview + // + groupBoxPreview.Controls.Add(txtMarkupPreview); + groupBoxPreview.Location = new Point(12, 416); + groupBoxPreview.Name = "groupBoxPreview"; + groupBoxPreview.Size = new Size(776, 123); + groupBoxPreview.TabIndex = 2; + groupBoxPreview.TabStop = false; + groupBoxPreview.Text = "Markup Preview (sent to device)"; + // + // txtMarkupPreview + // + txtMarkupPreview.Font = new Font("Consolas", 9F); + txtMarkupPreview.Location = new Point(14, 22); + txtMarkupPreview.Multiline = true; + txtMarkupPreview.Name = "txtMarkupPreview"; + txtMarkupPreview.ReadOnly = true; + txtMarkupPreview.Size = new Size(756, 86); + txtMarkupPreview.TabIndex = 0; + // + // MainForm + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 551); + Controls.Add(groupBoxPreview); + Controls.Add(groupBoxMarkup); + Controls.Add(groupBoxConnection); + FormBorderStyle = FormBorderStyle.FixedSingle; + MaximizeBox = false; + Name = "MainForm"; + StartPosition = FormStartPosition.CenterScreen; + Text = "OLED Hardware Monitor"; + FormClosing += Form_FormClosing; + groupBoxConnection.ResumeLayout(false); + groupBoxConnection.PerformLayout(); + groupBoxMarkup.ResumeLayout(false); + splitContainer1.Panel1.ResumeLayout(false); + splitContainer1.Panel1.PerformLayout(); + splitContainer1.Panel2.ResumeLayout(false); + splitContainer1.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit(); + splitContainer1.ResumeLayout(false); + panelButtons.ResumeLayout(false); + panelButtons.PerformLayout(); + groupBoxPreview.ResumeLayout(false); + groupBoxPreview.PerformLayout(); + ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.GroupBox groupBoxConnection; + private System.Windows.Forms.Label lblStatus; + private System.Windows.Forms.Button btnRefreshPorts; + private System.Windows.Forms.Button btnConnect; + private System.Windows.Forms.ComboBox comboBoxPorts; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBoxMarkup; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Panel panelButtons; + private System.Windows.Forms.Button btnRefreshSensors; + private System.Windows.Forms.Button btnLoadExample; + private System.Windows.Forms.Button btnSendNow; + private System.Windows.Forms.CheckBox chkAutoUpdate; + private System.Windows.Forms.Button btnInsertIcon; + private System.Windows.Forms.TextBox txtMarkupEditor; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtHelpText; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.GroupBox groupBoxPreview; + private System.Windows.Forms.TextBox txtMarkupPreview; + } +} \ No newline at end of file diff --git a/MainForm.cs b/MainForm.cs new file mode 100644 index 0000000..dd25574 --- /dev/null +++ b/MainForm.cs @@ -0,0 +1,299 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Text; +using System.Windows.Forms; +using LibreHardwareMonitor.Hardware; + +namespace OledMonitor +{ + public partial class MainForm : Form + { + private readonly Computer _computer; + private SerialPort? _serialPort; + private readonly System.Windows.Forms.Timer _updateTimer = new(); + private readonly Dictionary _sensorValues = new(); + private bool _autoUpdate = true; + + public MainForm() + { + InitializeComponent(); + + // Initialize LibreHardwareMonitor + _computer = new Computer + { + IsCpuEnabled = true, + IsGpuEnabled = true, + IsMemoryEnabled = true, + IsMotherboardEnabled = true, + IsControllerEnabled = false, + IsNetworkEnabled = false, + IsStorageEnabled = false + }; + _computer.Open(); + + // Find available serial ports + RefreshComPorts(); + + // Setup timer for updates + _updateTimer.Interval = 1000; // 1 second updates + _updateTimer.Tick += UpdateTimer_Tick; + + // Add sensor variable examples to help text + UpdateHelpText(); + } + + private void UpdateHelpText() + { + // Collect available sensors to show as examples + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Available sensor variables:"); + sb.AppendLine(); + + // Update hardware readings + foreach (var hardware in _computer.Hardware) + { + hardware.Update(); + + foreach (var sensor in hardware.Sensors) + { + if (sensor.Value.HasValue && + (sensor.SensorType == SensorType.Load || + sensor.SensorType == SensorType.Temperature || + sensor.SensorType == SensorType.Clock || + sensor.SensorType == SensorType.Power)) + { + string sensorId = GetSensorVariableName(hardware.Name, sensor.Name); + _sensorValues[sensorId] = sensor.Value.Value; + + string unit = GetSensorUnit(sensor.SensorType); + sb.AppendLine($"{sensorId} = {sensor.Value.Value:F1}{unit}"); + } + } + } + + txtHelpText.Text = sb.ToString(); + } + + private string GetSensorVariableName(string hardwareName, string sensorName) + { + // Create a simplified and safe variable name + string name = $"{hardwareName}_{sensorName}" + .Replace(" ", "_") + .Replace("%", "Percent") + .Replace("#", "Num") + .Replace("/", "_") + .Replace("\\", "_") + .Replace("(", "") + .Replace(")", "") + .Replace(",", ""); + + return name; + } + + private string GetSensorUnit(SensorType sensorType) + { + return sensorType switch + { + SensorType.Temperature => "°C", + SensorType.Load => "%", + SensorType.Clock => "MHz", + SensorType.Power => "W", + _ => "" + }; + } + + private void RefreshComPorts() + { + comboBoxPorts.Items.Clear(); + foreach (string port in SerialPort.GetPortNames()) + { + comboBoxPorts.Items.Add(port); + } + + if (comboBoxPorts.Items.Count > 0) + comboBoxPorts.SelectedIndex = 0; + } + + private void btnConnect_Click(object? sender, EventArgs e) + { + if (_serialPort != null && _serialPort.IsOpen) + { + DisconnectFromDevice(); + btnConnect.Text = "Connect"; + lblStatus.Text = "Disconnected"; + _updateTimer.Stop(); + } + else + { + try + { + string selectedPort = comboBoxPorts.SelectedItem?.ToString() ?? ""; + if (string.IsNullOrEmpty(selectedPort)) + { + MessageBox.Show("Please select a COM port."); + return; + } + + _serialPort = new SerialPort(selectedPort, 115200); + _serialPort.Open(); + btnConnect.Text = "Disconnect"; + lblStatus.Text = $"Connected to {selectedPort}"; + _updateTimer.Start(); + + // Send immediately after connecting + SendMarkupToDevice(); + } + catch (Exception ex) + { + MessageBox.Show($"Error connecting to device: {ex.Message}"); + } + } + } + + private void DisconnectFromDevice() + { + if (_serialPort != null && _serialPort.IsOpen) + { + _serialPort.Close(); + _serialPort.Dispose(); + _serialPort = null; + } + } + + private void UpdateTimer_Tick(object? sender, EventArgs e) + { + if (_serialPort == null || !_serialPort.IsOpen) + return; + + // Update all hardware readings + UpdateSensorValues(); + + // If set to auto-update, send markup to device + if (_autoUpdate) + { + SendMarkupToDevice(); + } + } + + private void UpdateSensorValues() + { + // Update all hardware readings + foreach (var hardware in _computer.Hardware) + { + hardware.Update(); + + foreach (var sensor in hardware.Sensors) + { + if (sensor.Value.HasValue) + { + string sensorId = GetSensorVariableName(hardware.Name, sensor.Name); + _sensorValues[sensorId] = sensor.Value.Value; + } + } + } + } + + private void SendMarkupToDevice() + { + if (_serialPort == null || !_serialPort.IsOpen) + return; + + try + { + string markup = ProcessVariablesInMarkup(txtMarkupEditor.Text); + _serialPort.WriteLine(markup); + txtMarkupPreview.Text = markup; + } + catch (Exception ex) + { + lblStatus.Text = $"Error: {ex.Message}"; + _updateTimer.Stop(); + DisconnectFromDevice(); + btnConnect.Text = "Connect"; + } + } + + private string ProcessVariablesInMarkup(string markup) + { + // Replace variables with actual values + foreach (var sensor in _sensorValues) + { + // Look for {variable} syntax in the markup + string variablePattern = $"{{{sensor.Key}}}"; + + // Format value based on type (integers vs decimals) + string formattedValue; + if (Math.Abs(sensor.Value - Math.Round(sensor.Value)) < 0.01) + { + formattedValue = $"{sensor.Value:F0}"; + } + else + { + formattedValue = $"{sensor.Value:F1}"; + } + + markup = markup.Replace(variablePattern, formattedValue); + } + + return markup; + } + + private void btnRefreshPorts_Click(object? sender, EventArgs e) + { + RefreshComPorts(); + } + + private void btnRefreshSensors_Click(object? sender, EventArgs e) + { + UpdateSensorValues(); + UpdateHelpText(); + } + + private void btnSendNow_Click(object? sender, EventArgs e) + { + UpdateSensorValues(); + SendMarkupToDevice(); + } + + private void chkAutoUpdate_CheckedChanged(object? sender, EventArgs e) + { + _autoUpdate = chkAutoUpdate.Checked; + } + + private void Form_FormClosing(object? sender, FormClosingEventArgs e) + { + _updateTimer.Stop(); + DisconnectFromDevice(); + _computer.Close(); + } + + private void btnLoadExample_Click(object? sender, EventArgs e) + { + txtMarkupEditor.Text = + "CPU: {CPU_Core_i7-6700K_Total_Load}%" + + "" + + "GPU: {GPU_NVIDIA_GeForce_GTX_1080_Load_GPU_Core}%" + + "" + + "RAM: {Memory_Load}%" + + ""; + } + + private void btnInsertIcon_Click(object? sender, EventArgs e) + { + using IconBrowser browser = new(); + if (browser.ShowDialog() == DialogResult.OK) + { + // Get the icon markup and insert it at the cursor position + string iconMarkup = browser.GetIconMarkup(); + if (!string.IsNullOrEmpty(iconMarkup)) + { + int selectionStart = txtMarkupEditor.SelectionStart; + txtMarkupEditor.Text = txtMarkupEditor.Text.Insert(selectionStart, iconMarkup); + txtMarkupEditor.SelectionStart = selectionStart + iconMarkup.Length; + txtMarkupEditor.Focus(); + } + } + } + } +} \ No newline at end of file diff --git a/MainForm.resx b/MainForm.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Oled test.csproj b/Oled test.csproj new file mode 100644 index 0000000..5bd1248 --- /dev/null +++ b/Oled test.csproj @@ -0,0 +1,37 @@ + + + + WinExe + net8.0-windows + OledMonitor + true + enable + enable + + + + + + + + + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/Oled test.csproj.user b/Oled test.csproj.user new file mode 100644 index 0000000..c4bae63 --- /dev/null +++ b/Oled test.csproj.user @@ -0,0 +1,12 @@ + + + + + + Form + + + Form + + + \ No newline at end of file diff --git a/Oled test.sln b/Oled test.sln new file mode 100644 index 0000000..678f687 --- /dev/null +++ b/Oled test.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35828.75 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oled test", "Oled test.csproj", "{14435653-939D-4F2C-ADA3-11C784DCAA81}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {14435653-939D-4F2C-ADA3-11C784DCAA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14435653-939D-4F2C-ADA3-11C784DCAA81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14435653-939D-4F2C-ADA3-11C784DCAA81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14435653-939D-4F2C-ADA3-11C784DCAA81}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {407FAD6B-096D-4FC1-B6AD-9CCF9F09CAC9} + EndGlobalSection +EndGlobal diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..864d1aa --- /dev/null +++ b/Program.cs @@ -0,0 +1,17 @@ +namespace OledMonitor +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new MainForm()); + } + } +} \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..48a467b --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OledMonitor.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string LastIconDirectory { + get { + return ((string)(this["LastIconDirectory"])); + } + set { + this["LastIconDirectory"] = value; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..81978ae --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file