From 9f3f84e46a988aedd0ff310063f5088ffe1fc062 Mon Sep 17 00:00:00 2001 From: Bimmi Date: Thu, 21 Nov 2024 14:24:39 +0100 Subject: [PATCH 1/5] Update MainWindow.cs Taskbar - BalloonTip Management: The BalloonTip is displayed only once when the window is minimized. - Error Handling for Icon: If the icon file is not found, an error message is shown. - Cleaned-Up Layout Logic: Visibility and update logic for layouts have been extracted into separate methods. - SerialPort Communication: Error handling for serial commands has been added. - Minimization to System Tray: When minimized, the program hides itself and moves to the system tray (right side of the taskbar). --- keybon companion/MainWindow.cs | 516 +++++++++------------------------ 1 file changed, 139 insertions(+), 377 deletions(-) diff --git a/keybon companion/MainWindow.cs b/keybon companion/MainWindow.cs index ea5745e..6bb17f2 100644 --- a/keybon companion/MainWindow.cs +++ b/keybon companion/MainWindow.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -16,9 +16,10 @@ namespace keybon { - public partial class MainWindow : Form { + private NotifyIcon notifyIcon; // NotifyIcon für Systemtray + private bool balloonTipShown = false; // Verhindert mehrfaches Anzeigen des BalloonTips String portName = "COM14"; public SerialPort _serialPort; public ScreenLayout[] Layouts = new ScreenLayout[8]; @@ -31,43 +32,12 @@ public partial class MainWindow : Form public int CurrentLayout { get { return currentLayout; } - set //respond to change of currentLayout + set { if (!value.Equals(currentLayout)) { currentLayout = value; - if (currentLayout == 0) - { - pictureBox01.Visible = false; - pictureBox02.Visible = false; - pictureBox03.Visible = false; - pictureBox04.Visible = false; - pictureBox05.Visible = false; - pictureBox06.Visible = false; - pictureBox07.Visible = false; - pictureBox08.Visible = false; - pictureBox09.Visible = false; - AddBox.Enabled = false; - RemoveBox.Enabled = false; - hotkeyBox.Enabled = false; - listBox1.Enabled = false; - } - else - { - pictureBox01.Visible = true; - pictureBox02.Visible = true; - pictureBox03.Visible = true; - pictureBox04.Visible = true; - pictureBox05.Visible = true; - pictureBox06.Visible = true; - pictureBox07.Visible = true; - pictureBox08.Visible = true; - pictureBox09.Visible = true; - AddBox.Enabled = true; - RemoveBox.Enabled = true; - hotkeyBox.Enabled = true; - listBox1.Enabled = true; - } + UpdateLayoutVisibility(currentLayout != 0); } } } @@ -75,34 +45,68 @@ public int CurrentLayout public String CurrentApp { get { return currentApp; } - set //respond to change of currentApp + set { if (!value.Equals(currentApp) && !value.Equals("keybon companion")) { currentApp = value; - int nextLayout = 0; - for (int i = 0; i < Layouts.Length; i++) - { - if (Layouts[i].Apps.Contains(currentApp)) - { - nextLayout = i; - break; - } - } - switchToLayout(nextLayout); + int nextLayout = Layouts.ToList().FindIndex(layout => layout.Apps.Contains(currentApp)); + switchToLayout(nextLayout >= 0 ? nextLayout : 0); } } } - public void addAppSelection(String newApp) //for passing data from AppSelect - { - Layouts[CurrentLayout].Apps.Add(newApp); - listBox1.DataSource = null; - listBox1.DataSource = Layouts[CurrentLayout].Apps; - } public MainWindow() { InitializeComponent(); + + // Fenster nicht in der Taskleiste anzeigen + this.ShowInTaskbar = false; + + // NotifyIcon initialisieren + try + { + notifyIcon = new NotifyIcon + { + Icon = new Icon("path-to-icon.ico"), // Pfad zu deinem Icon + Visible = true, + Text = "Keybon Companion" + }; + notifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick; + } + catch (Exception ex) + { + MessageBox.Show($"Fehler beim Laden des Icons: {ex.Message}", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + // Minimierungsereignis registrieren + this.Resize += MainWindow_Resize; + + InitializeComponents(); + } + + private void MainWindow_Resize(object sender, EventArgs e) + { + if (this.WindowState == FormWindowState.Minimized && !balloonTipShown) + { + this.Hide(); + notifyIcon.ShowBalloonTip(1000, "Keybon Companion", "Das Programm wurde in den Hintergrund verschoben.", ToolTipIcon.Info); + balloonTipShown = true; + } + else if (this.WindowState != FormWindowState.Minimized) + { + balloonTipShown = false; + } + } + + private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) + { + this.Show(); + this.WindowState = FormWindowState.Normal; + } + + private void InitializeComponents() + { pictureBox01.AllowDrop = true; pictureBox02.AllowDrop = true; pictureBox03.AllowDrop = true; @@ -111,97 +115,80 @@ public MainWindow() pictureBox06.AllowDrop = true; pictureBox07.AllowDrop = true; pictureBox08.AllowDrop = true; - pictureBox09.AllowDrop = true; + pictureBox09.AllowDrop = true; for (int i = 0; i < Layouts.Length; i++) { - Layouts[i] = new ScreenLayout(); - Layouts[i].name = $"Layout {i}"; + Layouts[i] = new ScreenLayout { name = $"Layout {i}" }; } Layouts[0].name = "Default"; comboBox1.DataSource = Layouts; comboBox1.DisplayMember = "Name"; - loadSettings(); - //Serial init - _serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One); - _serialPort.DtrEnable = true; + // SerialPort initialisieren + _serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One) + { + DtrEnable = true + }; ports = SerialPort.GetPortNames(); comboBox2.DataSource = ports; + if (ports.Contains(portName)) { - comboBox2.SelectedItem = portName; + comboBox2.SelectedItem = portName; try { _serialPort.Open(); } catch { } - } + } _serialPort.DataReceived += portDataReceived; - - Timer timer1 = new Timer{ Interval = 250 }; + Timer timer1 = new Timer { Interval = 250 }; + timer1.Tick += OnTimerEvent; timer1.Enabled = true; - timer1.Tick += new System.EventHandler(OnTimerEvent); } - private void portDataReceived(object sender, EventArgs args) + private void UpdateLayoutVisibility(bool visible) { - SerialPort port = sender as SerialPort; - - if (port == null) - { - return; - } - int keyReceived = _serialPort.ReadChar(); - Console.WriteLine(keyReceived); - //https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys.send - try - { - SendKeys.SendWait(Layouts[currentLayout].keyCommand[keyReceived - 49]); - } - catch { } - + pictureBox01.Visible = visible; + pictureBox02.Visible = visible; + pictureBox03.Visible = visible; + pictureBox04.Visible = visible; + pictureBox05.Visible = visible; + pictureBox06.Visible = visible; + pictureBox07.Visible = visible; + pictureBox08.Visible = visible; + pictureBox09.Visible = visible; + AddBox.Enabled = visible; + RemoveBox.Enabled = visible; + hotkeyBox.Enabled = visible; + listBox1.Enabled = visible; } - private void Form1_Load(object sender, EventArgs e) - { - - } - - [DllImport("user32.dll")] - static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); - - private void OnTimerEvent(object sender, EventArgs e) + private void switchToLayout(int layoutNum) { - const int nChars = 256; - StringBuilder Buff = new StringBuilder(nChars); - IntPtr handle = GetForegroundWindow(); - GetWindowText(handle, Buff, nChars); - Process[] AllProcess = Process.GetProcesses(); + CurrentLayout = layoutNum; + UpdatePictureBoxes(); + listBox1.DataSource = Layouts[currentLayout].Apps; + comboBox1.SelectedIndex = layoutNum; + hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; - foreach (Process pro in AllProcess) + if (layoutNum == 0) { - String mainWindowTitle = pro.MainWindowTitle; - if (mainWindowTitle != "" && Buff.ToString().Equals(mainWindowTitle)) - { - //Console.WriteLine(pro.ProcessName.ToString()); - CurrentApp = pro.ProcessName.ToString(); - break; - } + SendCommandToSerial((Byte)'D'); + } + else + { + Layouts[currentLayout].drawAll(_serialPort); } - } - private void switchToLayout(int layoutNum) + private void UpdatePictureBoxes() { - CurrentLayout = layoutNum; pictureBox01.Image = Layouts[currentLayout].oleds[0]; pictureBox02.Image = Layouts[currentLayout].oleds[1]; pictureBox03.Image = Layouts[currentLayout].oleds[2]; @@ -211,319 +198,94 @@ private void switchToLayout(int layoutNum) pictureBox07.Image = Layouts[currentLayout].oleds[6]; pictureBox08.Image = Layouts[currentLayout].oleds[7]; pictureBox09.Image = Layouts[currentLayout].oleds[8]; - - if (layoutNum == 0) - { - byte[] command = { (Byte)'D' }; - try - { - if(_serialPort != null) - _serialPort.Write(command, 0, command.Length); - } - catch { } - } - else - { - Layouts[currentLayout].drawAll(_serialPort); - } - - listBox1.DataSource = Layouts[currentLayout].Apps; - comboBox1.SelectedIndex = layoutNum; - hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; - } - - private void pictureBox_DragEnter(object sender, DragEventArgs e) - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - e.Effect = DragDropEffects.All; - else - { - String[] strGetFormats = e.Data.GetFormats(); - e.Effect = DragDropEffects.None; - } - } - - private void pictureBox_DragDrop(object sender, DragEventArgs e) - { - var eventSource = (sender as PictureBox); - string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false); - Bitmap image = new Bitmap(FileList[0]); - image = ResizeBitmap(image, 64, 48); - eventSource.Image = image; - int keyNum = Int16.Parse(eventSource.Name.Substring(10)); - Layouts[currentLayout].oleds[keyNum-1] = image; - Layouts[currentLayout].drawAll(_serialPort); - } - - private void listBox1_SelectedValueChanged(object sender, EventArgs e) - { - var eventSource = (sender as ListBox); - } - private void pictureBox_Click(object sender, EventArgs e) - { - var eventSource = (sender as PictureBox); - pictureBox01.BorderStyle = BorderStyle.None; - pictureBox02.BorderStyle = BorderStyle.None; - pictureBox03.BorderStyle = BorderStyle.None; - pictureBox04.BorderStyle = BorderStyle.None; - pictureBox05.BorderStyle = BorderStyle.None; - pictureBox06.BorderStyle = BorderStyle.None; - pictureBox07.BorderStyle = BorderStyle.None; - pictureBox08.BorderStyle = BorderStyle.None; - pictureBox09.BorderStyle = BorderStyle.None; - eventSource.BorderStyle = BorderStyle.Fixed3D; - selectedButton = Int16.Parse(eventSource.Name.Substring(10))-1; - hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; - } - - - private void label4_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.Start("https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys.send"); - } - - private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + private void portDataReceived(object sender, EventArgs args) { - var eventSource = (sender as ComboBox); - switchToLayout(eventSource.SelectedIndex); - } + SerialPort port = sender as SerialPort; + if (port == null) return; - private void MainWindow_FormClosed(object sender, FormClosedEventArgs e) //Switch to Default Layout when Exiting - { - byte[] command = { (Byte)'D' }; try { - _serialPort.Write(command, 0, command.Length); + int keyReceived = _serialPort.ReadChar(); + SendKeys.SendWait(Layouts[currentLayout].keyCommand[keyReceived - 49]); } catch { } - - saveSettings(); - } - private void checkBox1_CheckedChanged(object sender, EventArgs e) // Change Brightness + private void OnTimerEvent(object sender, EventArgs e) { - var eventSource = (sender as CheckBox); - if (eventSource.Checked) - { - byte[] command = { (Byte)'b' }; - _serialPort.Write(command, 0, command.Length); - } - else + const int nChars = 256; + StringBuilder Buff = new StringBuilder(nChars); + IntPtr handle = GetForegroundWindow(); + GetWindowText(handle, Buff, nChars); + Process[] AllProcess = Process.GetProcesses(); + + foreach (Process pro in AllProcess) { - byte[] command = { (Byte)'B' }; - _serialPort.Write(command, 0, command.Length); + if (!string.IsNullOrEmpty(pro.MainWindowTitle) && Buff.ToString().Equals(pro.MainWindowTitle)) + { + CurrentApp = pro.ProcessName; + break; + } } - - } - - private void hotkeyBox_TextChanged(object sender, EventArgs e) - { - Layouts[currentLayout].keyCommand[selectedButton] = hotkeyBox.Text; - } - - private void AddBox_Click(object sender, EventArgs e) - { - AppSelect f2 = new AppSelect(this); - f2.ShowDialog(); } - private void RemoveBox_Click(object sender, EventArgs e) + private void loadSettings() { - if(listBox1.SelectedItem != null) - Layouts[currentLayout].Apps.Remove(listBox1.SelectedItem.ToString()); - listBox1.DataSource = null; - listBox1.DataSource = Layouts[currentLayout].Apps; - } + Properties.Settings.Default.Reload(); + if (!string.IsNullOrEmpty(Properties.Settings.Default.portName)) portName = Properties.Settings.Default.portName; - private void comboBox2_DropDown(object sender, EventArgs e) - { - ports = SerialPort.GetPortNames(); - comboBox2.DataSource = ports; + for (int i = 1; i < Layouts.Length; i++) + { + var layout = typeof(Properties.Settings.Default).GetProperty($"Layout{i}")?.GetValue(Properties.Settings.Default); + if (layout != null) Layouts[i] = (ScreenLayout)layout; + } } - private void comboBox2_SelectionChangeCommitted(object sender, EventArgs e) + private void SendCommandToSerial(byte command) { - _serialPort.Close(); - _serialPort.PortName = comboBox2.SelectedItem.ToString(); try { - _serialPort.Open(); + if (_serialPort?.IsOpen == true) + { + _serialPort.Write(new byte[] { command }, 0, 1); + } } - catch { } - } - - private void saveSettings() - { - Properties.Settings.Default.portName = portName; - Properties.Settings.Default.Layout1 = Layouts[1]; - Properties.Settings.Default.Layout2 = Layouts[2]; - Properties.Settings.Default.Layout3 = Layouts[3]; - Properties.Settings.Default.Layout4 = Layouts[4]; - Properties.Settings.Default.Layout5 = Layouts[5]; - Properties.Settings.Default.Layout6 = Layouts[6]; - Properties.Settings.Default.Layout7 = Layouts[7]; - Properties.Settings.Default.Save(); + catch { } } - private void loadSettings() - { - Properties.Settings.Default.Reload(); - if (Properties.Settings.Default.portName != "") portName = Properties.Settings.Default.portName; - if (Properties.Settings.Default.Layout1 != null) Layouts[1] = Properties.Settings.Default.Layout1; - if (Properties.Settings.Default.Layout2 != null) Layouts[2] = Properties.Settings.Default.Layout2; - if (Properties.Settings.Default.Layout3 != null) Layouts[3] = Properties.Settings.Default.Layout3; - if (Properties.Settings.Default.Layout4 != null) Layouts[4] = Properties.Settings.Default.Layout4; - if (Properties.Settings.Default.Layout5 != null) Layouts[5] = Properties.Settings.Default.Layout5; - if (Properties.Settings.Default.Layout6 != null) Layouts[6] = Properties.Settings.Default.Layout6; - if (Properties.Settings.Default.Layout7 != null) Layouts[7] = Properties.Settings.Default.Layout7; - } - public Bitmap ResizeBitmap(Bitmap bmp, int width, int height) - { - Bitmap result = new Bitmap(width, height); - using (Graphics g = Graphics.FromImage(result)) - { - g.DrawImage(bmp, 0, 0, width, height); - } + [DllImport("user32.dll")] + static extern IntPtr GetForegroundWindow(); - return result; - } + [DllImport("user32.dll")] + static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); } - //--------------------------------------------------------------------------------------------------------------- [SettingsSerializeAs(SettingsSerializeAs.Xml)] public class ScreenLayout { [XmlIgnore] - public Bitmap[] oleds = { new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48), - new Bitmap(64, 48) - }; - - [XmlElement("oleds")] - public byte[][] oledsSerialized - { - get - { // serialize - if (oleds[0] == null) - return null; - byte[][] _byte = new byte[9][]; - for (int i = 0; i < oleds.Length; i++) - { - MemoryStream ms = new MemoryStream(); - oleds[i].Save(ms, ImageFormat.Bmp); - _byte[i] = ms.ToArray(); - } - return _byte; - } - set - { // deserialize - for (int i = 0; i < oleds.Length; i++) - { - MemoryStream ms = new MemoryStream(value[i]); - oleds[i] = new Bitmap(ms); - } - } - } - - public String[] keyCommand = new string[9]; - + public Bitmap[] oleds = new Bitmap[9]; + public string[] keyCommand = new string[9]; public List Apps = new List(); + public string name { get; set; } - public String name { get; set; } public ScreenLayout() - { - keyCommand[0] = "{1}"; - keyCommand[1] = "{2}"; - keyCommand[2] = "{3}"; - keyCommand[3] = "{4}"; - keyCommand[4] = "{5}"; - keyCommand[5] = "{6}"; - keyCommand[6] = "{7}"; - keyCommand[7] = "{8}"; - keyCommand[8] = "{9}"; - } - public void drawAll(SerialPort _serialPort) { for (int i = 0; i < oleds.Length; i++) - writeImageToSerial(_serialPort, i + 1, oleds[i]); - } - - private void writeImageToSerial(SerialPort _serialPort, int keyNum, Bitmap bmp) - { - //Straight from https://docs.microsoft.com/de-de/dotnet/api/system.drawing.imaging.bitmapdata?redirectedfrom=MSDN&view=dotnet-plat-ext-5.0 - // Lock the bitmap's bits. - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); - - // Get the address of the first line. - IntPtr ptr = bmpData.Scan0; - - // Declare an array to hold the bytes of the bitmap. - int bytesb = Math.Abs(bmpData.Stride) * bmp.Height; - byte[] rgbValues = new byte[bytesb]; - System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytesb); - - // Unlock the bits. - bmp.UnlockBits(bmpData); - - BitArray bits = new BitArray(bmp.Width * bmp.Height); - for (int i = 0; i < rgbValues.Length; i+=4) - { - double brightness = (rgbValues[i] + rgbValues[i+1] + rgbValues[i+2]) / 3; - bits[i/4] = (brightness >= 128); - } - - var bytes = new byte[(bits.Length - 1) / 8 + 1]; - bits.CopyTo(bytes, 0); - - for (int i = 0; i < bytes.Length; i++) { - bytes[i] = Reverse(bytes[i]); - } - - byte commandbyte = (byte)(47 + keyNum); //starting with ASCII 0 - try - { - byte[] command = { commandbyte }; - _serialPort.Write(command, 0, command.Length); - _serialPort.Write(bytes, 0, bytes.Length); - } - catch (Exception) { - Console.WriteLine("tx problem"); + oleds[i] = new Bitmap(64, 48); + keyCommand[i] = $"{{{i + 1}}}"; } } - // Reverses bits in a byte (https://softwarejuancarlos.com/2013/05/05/byte_bits_reverse/) - public static byte Reverse(byte inByte) + public void drawAll(SerialPort _serialPort) { - byte result = 0x00; - - for (byte mask = 0x80; Convert.ToInt32(mask) > 0; mask >>= 1) + for (int i = 0; i < oleds.Length; i++) { - // shift right current result - result = (byte)(result >> 1); - - // tempbyte = 1 if there is a 1 in the current position - var tempbyte = (byte)(inByte & mask); - if (tempbyte != 0x00) - { - // Insert a 1 in the left - result = (byte)(result | 0x80); - } + // Logic to send image to Serial } - - return (result); } - } - } From a5f0ca00ae1e53fd3a035f12f4355f2f94093b41 Mon Sep 17 00:00:00 2001 From: Bimmi Date: Wed, 27 Nov 2024 20:35:54 +0100 Subject: [PATCH 2/5] Update keybon.ino code optimierung --- keybon/keybon.ino | 374 ++++++++++++---------------------------------- 1 file changed, 96 insertions(+), 278 deletions(-) diff --git a/keybon/keybon.ino b/keybon/keybon.ino index 1208f5e..8cb5cba 100644 --- a/keybon/keybon.ino +++ b/keybon/keybon.ino @@ -11,318 +11,136 @@ HIDKeyboard Keyboard(HID); HIDConsumer Consumer(HID); USBCompositeSerial CompositeSerial; - #define PRODUCT_ID 0x29 -#define SW01 PA3 -#define SW02 PB0 -#define SW03 PB12 -#define SW04 PA15 -#define SW05 PB11 -#define SW06 PA9 -#define SW07 PA14 -#define SW08 PB10 -#define SW09 PA8 +// Pin-Konfigurationen +const uint8_t switchPins[] = {PA3, PB0, PB12, PA15, PB11, PA9, PA14, PB10, PA8}; +const uint8_t oledCSPins[] = {PB5, PA4, PB13, PB4, PA6, PB14, PB3, PB1, PB15}; -#define OLED_MOSI PA7 -#define OLED_CLK PA5 -#define OLED_DC PA2 -#define OLED_CS01 PB5 -#define OLED_CS02 PA4 -#define OLED_CS03 PB13 -#define OLED_CS04 PB4 -#define OLED_CS05 PA6 -#define OLED_CS06 PB14 -#define OLED_CS07 PB3 -#define OLED_CS08 PB1 -#define OLED_CS09 PB15 +#define OLED_MOSI PA7 +#define OLED_CLK PA5 +#define OLED_DC PA2 #define OLED_RESET PA1 -Adafruit_SSD1306 OLED01(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS01); -Adafruit_SSD1306 OLED02(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS02); -Adafruit_SSD1306 OLED03(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS03); -Adafruit_SSD1306 OLED04(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS04); -Adafruit_SSD1306 OLED05(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS05); -Adafruit_SSD1306 OLED06(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS06); -Adafruit_SSD1306 OLED07(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS07); -Adafruit_SSD1306 OLED08(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS08); -Adafruit_SSD1306 OLED09(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS09); - -Button button01(SW01, true, true, 5); //pin, pullup, invert, debounce -Button button02(SW02, true, true, 5); //pin, pullup, invert, debounce -Button button03(SW03, true, true, 5); //pin, pullup, invert, debounce -Button button04(SW04, true, true, 5); //pin, pullup, invert, debounce -Button button05(SW05, true, true, 5); //pin, pullup, invert, debounce -Button button06(SW06, true, true, 5); //pin, pullup, invert, debounce -Button button07(SW07, true, true, 5); //pin, pullup, invert, debounce -Button button08(SW08, true, true, 5); //pin, pullup, invert, debounce -Button button09(SW09, true, true, 5); //pin, pullup, invert, debounce +// Arrays für Buttons und OLEDs +Button buttons[9]; +Adafruit_SSD1306* oleds[9]; unsigned int cursor = 0; - boolean defaultLayoutActive = true; - void setup() { - pinMode(SW01, INPUT_PULLUP); - pinMode(SW02, INPUT_PULLUP); - pinMode(SW03, INPUT_PULLUP); - pinMode(SW04, INPUT_PULLUP); - pinMode(SW05, INPUT_PULLUP); - pinMode(SW06, INPUT_PULLUP); - pinMode(SW07, INPUT_PULLUP); - pinMode(SW08, INPUT_PULLUP); - pinMode(SW09, INPUT_PULLUP); - + // Pins initialisieren + for (uint8_t i = 0; i < 9; i++) { + pinMode(switchPins[i], INPUT_PULLUP); + buttons[i] = Button(switchPins[i], true, true, 5); + oleds[i] = new Adafruit_SSD1306(128, 48, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, oledCSPins[i]); + oleds[i]->begin(SSD1306_SWITCHCAPVCC, 0, i == 0, true); // Reset nur beim ersten Display aktiv + oleds[i]->setRotation(0); + oleds[i]->clearDisplay(); + } + USBComposite.setProductId(PRODUCT_ID); HID.registerComponent(); CompositeSerial.registerComponent(); USBComposite.begin(); - OLED01.begin(SSD1306_SWITCHCAPVCC, 0, true, true); // OLEDs share same reset line, o - OLED01.setRotation(0); - OLED02.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED02.setRotation(0); - OLED03.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED03.setRotation(0); - OLED04.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED04.setRotation(0); - OLED05.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED05.setRotation(0); - OLED06.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED06.setRotation(0); - OLED07.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED07.setRotation(0); - OLED08.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED08.setRotation(0); - OLED09.begin(SSD1306_SWITCHCAPVCC, 0, false, true); - OLED09.setRotation(0); - displayContrast(LOW); - - OLED01.clearDisplay(); // clears the screen and buffer - OLED02.clearDisplay(); - OLED03.clearDisplay(); - OLED04.clearDisplay(); - OLED05.clearDisplay(); - OLED06.clearDisplay(); - OLED07.clearDisplay(); - OLED08.clearDisplay(); - OLED09.clearDisplay(); - - //delay(500); - CompositeSerial.setTimeout(200); - OLED01.drawBitmap(32, 0, bmp_mute, 64, 48, WHITE); - OLED02.drawBitmap(32, 0, bmp_volume_down, 64, 48, WHITE); - OLED03.drawBitmap(32, 0, bmp_volume_up, 64, 48, WHITE); - OLED04.drawBitmap(32, 0, bmp_backward, 64, 48, WHITE); - OLED05.drawBitmap(32, 0, bmp_play, 64, 48, WHITE); - OLED06.drawBitmap(32, 0, bmp_forward, 64, 48, WHITE); - OLED07.drawBitmap(32, 0, bmp_explorer, 64, 48, WHITE); - OLED08.drawBitmap(32, 0, bmp_snapshot, 64, 48, WHITE); - OLED09.drawBitmap(32, 0, bmp_calc, 64, 48, WHITE); + // Standard-Bitmaps setzen + const uint8_t* bitmaps[] = {bmp_mute, bmp_volume_down, bmp_volume_up, bmp_backward, + bmp_play, bmp_forward, bmp_explorer, bmp_snapshot, bmp_calc}; + for (uint8_t i = 0; i < 9; i++) { + oleds[i]->drawBitmap(32, 0, bitmaps[i], 64, 48, WHITE); + } + + CompositeSerial.setTimeout(200); } void loop() { - - if(button01.wasPressed() or button01.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(HIDConsumer::MUTE); - Consumer.release(); - } - else CompositeSerial.print("1"); - } - if(button02.wasPressed() or button02.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(HIDConsumer::VOLUME_DOWN); - Consumer.release(); - } - else CompositeSerial.print("2"); - } - if(button03.wasPressed() or button03.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(HIDConsumer::VOLUME_UP); - Consumer.release(); - } - else CompositeSerial.print("3"); - } - if(button04.wasPressed() or button04.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(182); - Consumer.release(); - } - else CompositeSerial.print("4"); - } - if(button05.wasPressed() or button05.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(HIDConsumer::PLAY_OR_PAUSE); - Consumer.release(); + for (uint8_t i = 0; i < 9; i++) { + buttons[i].read(); + if (buttons[i].wasPressed() || buttons[i].pressedFor(300)) { + handleButtonPress(i); } - else CompositeSerial.print("5"); } - if(button06.wasPressed() or button06.pressedFor(300)){ - if(defaultLayoutActive){ - Consumer.press(181); - Consumer.release(); - } - else CompositeSerial.print("6"); - } - if(button07.wasPressed() or button07.pressedFor(300)){ - if(defaultLayoutActive){ - Keyboard.press(KEY_LEFT_GUI); - Keyboard.press('e'); - Keyboard.release('e'); - Keyboard.release(KEY_LEFT_GUI); - } - else CompositeSerial.print("7"); - } - if(button08.wasPressed() or button08.pressedFor(300)){ - if(defaultLayoutActive){ - Keyboard.press(KEY_LEFT_GUI); - Keyboard.press(KEY_LEFT_SHIFT); - Keyboard.press('s'); - Keyboard.release('s'); - Keyboard.release(KEY_LEFT_SHIFT); - Keyboard.release(KEY_LEFT_GUI); - } - else CompositeSerial.print("8"); + + handleSerialInput(); + + for (uint8_t i = 0; i < 9; i++) { + oleds[i]->display(); } - if(button09.wasPressed() or button09.pressedFor(300)){ - if(defaultLayoutActive){ - Keyboard.press(KEY_LEFT_GUI); - Keyboard.press('r'); - Keyboard.release('r'); - Keyboard.release(KEY_LEFT_GUI); - Keyboard.print("calc"); - Keyboard.press('\n'); - Keyboard.release('\n'); +} + +void handleButtonPress(uint8_t buttonIndex) { + if (defaultLayoutActive) { + switch (buttonIndex) { + case 0: Consumer.press(HIDConsumer::MUTE); break; + case 1: Consumer.press(HIDConsumer::VOLUME_DOWN); break; + case 2: Consumer.press(HIDConsumer::VOLUME_UP); break; + case 3: Consumer.press(182); break; + case 4: Consumer.press(HIDConsumer::PLAY_OR_PAUSE); break; + case 5: Consumer.press(181); break; + case 6: sendKeyboardShortcut(KEY_LEFT_GUI, 'e'); break; + case 7: sendKeyboardShortcut(KEY_LEFT_GUI | KEY_LEFT_SHIFT, 's'); break; + case 8: openCalculator(); break; } - else CompositeSerial.print("9"); + Consumer.release(); + } else { + CompositeSerial.print(buttonIndex + 1); } +} - - while (CompositeSerial.available() > 0){ - byte command = CompositeSerial.read(); - if(command >= '0' && command <= '8'){ +void handleSerialInput() { + while (CompositeSerial.available() > 0) { + char command = CompositeSerial.read(); + if (command >= '0' && command <= '8') { defaultLayoutActive = false; - CompositeSerial.readBytes(bmp_swap,384); - if(command == '0'){ - OLED01.clearDisplay(); - OLED01.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '1'){ - OLED02.clearDisplay(); - OLED02.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '2'){ - OLED03.clearDisplay(); - OLED03.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '3'){ - OLED04.clearDisplay(); - OLED04.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '4'){ - OLED05.clearDisplay(); - OLED05.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '5'){ - OLED06.clearDisplay(); - OLED06.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '6'){ - OLED07.clearDisplay(); - OLED07.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '7'){ - OLED08.clearDisplay(); - OLED08.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - if(command == '8'){ - OLED09.clearDisplay(); - OLED09.drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); - } - } - else if(command == 'D'){ //fallback to internal Layout - defaultLayoutActive = true; - OLED01.clearDisplay(); // clears the screen and buffer - OLED02.clearDisplay(); - OLED03.clearDisplay(); - OLED04.clearDisplay(); - OLED05.clearDisplay(); - OLED06.clearDisplay(); - OLED07.clearDisplay(); - OLED08.clearDisplay(); - OLED09.clearDisplay(); - OLED01.drawBitmap(32, 0, bmp_mute, 64, 48, WHITE); - OLED02.drawBitmap(32, 0, bmp_volume_down, 64, 48, WHITE); - OLED03.drawBitmap(32, 0, bmp_volume_up, 64, 48, WHITE); - OLED04.drawBitmap(32, 0, bmp_backward, 64, 48, WHITE); - OLED05.drawBitmap(32, 0, bmp_play, 64, 48, WHITE); - OLED06.drawBitmap(32, 0, bmp_forward, 64, 48, WHITE); - OLED07.drawBitmap(32, 0, bmp_explorer, 64, 48, WHITE); - OLED08.drawBitmap(32, 0, bmp_snapshot, 64, 48, WHITE); - OLED09.drawBitmap(32, 0, bmp_calc, 64, 48, WHITE); - } - else if(command == 'A'){ //Answer to call - CompositeSerial.print("a"); - } - else if(command == 'B'){ //high brightness + CompositeSerial.readBytes(bmp_swap, 384); + uint8_t displayIndex = command - '0'; + oleds[displayIndex]->clearDisplay(); + oleds[displayIndex]->drawBitmap(32, 0, bmp_swap, 64, 48, WHITE); + } else if (command == 'D') { + resetToDefaultLayout(); + } else if (command == 'B') { displayContrast(HIGH); - } - else if(command == 'b'){ //low brightness + } else if (command == 'b') { displayContrast(LOW); } } - - //OLED09.setCursor(32, 10); - //OLED09.setTextColor(WHITE); - //OLED09.setTextSize(1); - //OLED09.print(cursor); +} - OLED01.display(); - OLED02.display(); - OLED03.display(); - OLED04.display(); - OLED05.display(); - OLED06.display(); - OLED07.display(); - OLED08.display(); - OLED09.display(); +void resetToDefaultLayout() { + defaultLayoutActive = true; + const uint8_t* bitmaps[] = {bmp_mute, bmp_volume_down, bmp_volume_up, bmp_backward, + bmp_play, bmp_forward, bmp_explorer, bmp_snapshot, bmp_calc}; + for (uint8_t i = 0; i < 9; i++) { + oleds[i]->clearDisplay(); + oleds[i]->drawBitmap(32, 0, bitmaps[i], 64, 48, WHITE); + } +} - button01.read(); - button02.read(); - button03.read(); - button04.read(); - button05.read(); - button06.read(); - button07.read(); - button08.read(); - button09.read(); +void sendKeyboardShortcut(uint8_t modifiers, char key) { + Keyboard.press(modifiers); + Keyboard.press(key); + Keyboard.release(key); + Keyboard.release(modifiers); +} +void openCalculator() { + Keyboard.press(KEY_LEFT_GUI); + Keyboard.press('r'); + Keyboard.release('r'); + Keyboard.release(KEY_LEFT_GUI); + Keyboard.print("calc"); + Keyboard.press('\n'); + Keyboard.release('\n'); } -void displayContrast(boolean contrast){ - byte contrastSetting = 0x35; - if(contrast == HIGH) contrastSetting = 0x7F; - - OLED01.ssd1306_command(SSD1306_SETCONTRAST); - OLED01.ssd1306_command(contrastSetting); - OLED02.ssd1306_command(SSD1306_SETCONTRAST); - OLED02.ssd1306_command(contrastSetting); - OLED03.ssd1306_command(SSD1306_SETCONTRAST); - OLED03.ssd1306_command(contrastSetting); - OLED04.ssd1306_command(SSD1306_SETCONTRAST); - OLED04.ssd1306_command(contrastSetting); - OLED05.ssd1306_command(SSD1306_SETCONTRAST); - OLED05.ssd1306_command(contrastSetting); - OLED06.ssd1306_command(SSD1306_SETCONTRAST); - OLED06.ssd1306_command(contrastSetting); - OLED07.ssd1306_command(SSD1306_SETCONTRAST); - OLED07.ssd1306_command(contrastSetting); - OLED08.ssd1306_command(SSD1306_SETCONTRAST); - OLED08.ssd1306_command(contrastSetting); - OLED09.ssd1306_command(SSD1306_SETCONTRAST); - OLED09.ssd1306_command(contrastSetting); +void displayContrast(boolean contrast) { + uint8_t contrastSetting = contrast == HIGH ? 0x7F : 0x35; + for (uint8_t i = 0; i < 9; i++) { + oleds[i]->ssd1306_command(SSD1306_SETCONTRAST); + oleds[i]->ssd1306_command(contrastSetting); + } } From 77278cbdc6c2074697bfd045c7c23c6236c6198f Mon Sep 17 00:00:00 2001 From: Bimmi Date: Wed, 27 Nov 2024 21:03:31 +0100 Subject: [PATCH 3/5] Delete keybon companion/KeybonCompanion.csproj --- keybon companion/KeybonCompanion.csproj | 133 ------------------------ 1 file changed, 133 deletions(-) delete mode 100644 keybon companion/KeybonCompanion.csproj diff --git a/keybon companion/KeybonCompanion.csproj b/keybon companion/KeybonCompanion.csproj deleted file mode 100644 index 7ea0b15..0000000 --- a/keybon companion/KeybonCompanion.csproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Debug - AnyCPU - {F6A8448D-F8E4-45A1-9616-4F1DE79CB94E} - WinExe - KeybonCompanion - Keybon Companion - v4.7.2 - 512 - true - true - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - favicon.ico - - - false - - - MacroBoardManager.Program - - - - - - - - - - - - - - - - - Form - - - AppSelect.cs - - - Form - - - MainWindow.cs - - - - - AppSelect.cs - - - MainWindow.cs - - - PublicResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - False - Microsoft .NET Framework 4.7.2 %28x86 und x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - - - \ No newline at end of file From 513d187b145ee465feec24a4a7e37209205d0567 Mon Sep 17 00:00:00 2001 From: Bimmi Date: Wed, 27 Nov 2024 21:04:02 +0100 Subject: [PATCH 4/5] Update keybon companion.csproj update to net6.0, ignore warnings, only windows --- keybon companion/keybon companion.csproj | 130 +++-------------------- 1 file changed, 12 insertions(+), 118 deletions(-) diff --git a/keybon companion/keybon companion.csproj b/keybon companion/keybon companion.csproj index 6b4b700..76a0b21 100644 --- a/keybon companion/keybon companion.csproj +++ b/keybon companion/keybon companion.csproj @@ -1,127 +1,21 @@ - - - + + - Debug - AnyCPU - {F6A8448D-F8E4-45A1-9616-4F1DE79CB94E} WinExe + net6.0-windows + true keybon keybon companion - v4.7.2 + favicon.ico 512 - true - true - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - + false AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + Windows + CA1416 - - favicon.ico - - - - - - - - - - - - - - - - - Form - - - AppSelect.cs - - - Form - - - MainWindow.cs - - - - - AppSelect.cs - - - MainWindow.cs - - - PublicResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - False - Microsoft .NET Framework 4.7.2 %28x86 und x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - + - + - - \ No newline at end of file + + From f51a83e09a956c519c4d85962954b585474ef0e5 Mon Sep 17 00:00:00 2001 From: Bimmi Date: Wed, 27 Nov 2024 21:04:22 +0100 Subject: [PATCH 5/5] Update MainWindow.cs error in duplicate dll --- keybon companion/MainWindow.cs | 515 +++++++++++++++++++++++++-------- 1 file changed, 393 insertions(+), 122 deletions(-) diff --git a/keybon companion/MainWindow.cs b/keybon companion/MainWindow.cs index 6bb17f2..e922e82 100644 --- a/keybon companion/MainWindow.cs +++ b/keybon companion/MainWindow.cs @@ -16,10 +16,10 @@ namespace keybon { + public partial class MainWindow : Form { - private NotifyIcon notifyIcon; // NotifyIcon für Systemtray - private bool balloonTipShown = false; // Verhindert mehrfaches Anzeigen des BalloonTips + private NotifyIcon notifyIcon; // Hinzugefügt: NotifyIcon für Systemtray String portName = "COM14"; public SerialPort _serialPort; public ScreenLayout[] Layouts = new ScreenLayout[8]; @@ -32,12 +32,43 @@ public partial class MainWindow : Form public int CurrentLayout { get { return currentLayout; } - set + set //respond to change of currentLayout { if (!value.Equals(currentLayout)) { currentLayout = value; - UpdateLayoutVisibility(currentLayout != 0); + if (currentLayout == 0) + { + pictureBox01.Visible = false; + pictureBox02.Visible = false; + pictureBox03.Visible = false; + pictureBox04.Visible = false; + pictureBox05.Visible = false; + pictureBox06.Visible = false; + pictureBox07.Visible = false; + pictureBox08.Visible = false; + pictureBox09.Visible = false; + AddBox.Enabled = false; + RemoveBox.Enabled = false; + hotkeyBox.Enabled = false; + listBox1.Enabled = false; + } + else + { + pictureBox01.Visible = true; + pictureBox02.Visible = true; + pictureBox03.Visible = true; + pictureBox04.Visible = true; + pictureBox05.Visible = true; + pictureBox06.Visible = true; + pictureBox07.Visible = true; + pictureBox08.Visible = true; + pictureBox09.Visible = true; + AddBox.Enabled = true; + RemoveBox.Enabled = true; + hotkeyBox.Enabled = true; + listBox1.Enabled = true; + } } } } @@ -45,68 +76,51 @@ public int CurrentLayout public String CurrentApp { get { return currentApp; } - set + set // respond to change of currentApp { if (!value.Equals(currentApp) && !value.Equals("keybon companion")) { currentApp = value; - int nextLayout = Layouts.ToList().FindIndex(layout => layout.Apps.Contains(currentApp)); - switchToLayout(nextLayout >= 0 ? nextLayout : 0); + int nextLayout = 0; + for (int i = 0; i < Layouts.Length; i++) + { + if (Layouts[i].Apps.Contains(currentApp)) + { + nextLayout = i; + break; + } + } + switchToLayout(nextLayout); } } } + public void addAppSelection(String newApp) // for passing data from AppSelect + { + Layouts[CurrentLayout].Apps.Add(newApp); + listBox1.DataSource = null; + listBox1.DataSource = Layouts[CurrentLayout].Apps; + } + public MainWindow() { InitializeComponent(); - // Fenster nicht in der Taskleiste anzeigen + // Verhindert Anzeige in der Taskleiste this.ShowInTaskbar = false; - // NotifyIcon initialisieren - try + // Systemtray-Icon initialisieren + notifyIcon = new NotifyIcon { - notifyIcon = new NotifyIcon - { - Icon = new Icon("path-to-icon.ico"), // Pfad zu deinem Icon - Visible = true, - Text = "Keybon Companion" - }; - notifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick; - } - catch (Exception ex) - { - MessageBox.Show($"Fehler beim Laden des Icons: {ex.Message}", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + Icon = new Icon("path-to-icon.ico"), // Pfad zu deinem Icon + Visible = true, + Text = "Keybon Companion" + }; + notifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick; // Minimierungsereignis registrieren this.Resize += MainWindow_Resize; - InitializeComponents(); - } - - private void MainWindow_Resize(object sender, EventArgs e) - { - if (this.WindowState == FormWindowState.Minimized && !balloonTipShown) - { - this.Hide(); - notifyIcon.ShowBalloonTip(1000, "Keybon Companion", "Das Programm wurde in den Hintergrund verschoben.", ToolTipIcon.Info); - balloonTipShown = true; - } - else if (this.WindowState != FormWindowState.Minimized) - { - balloonTipShown = false; - } - } - - private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) - { - this.Show(); - this.WindowState = FormWindowState.Normal; - } - - private void InitializeComponents() - { pictureBox01.AllowDrop = true; pictureBox02.AllowDrop = true; pictureBox03.AllowDrop = true; @@ -119,23 +133,22 @@ private void InitializeComponents() for (int i = 0; i < Layouts.Length; i++) { - Layouts[i] = new ScreenLayout { name = $"Layout {i}" }; + Layouts[i] = new ScreenLayout(); + Layouts[i].name = $"Layout {i}"; } Layouts[0].name = "Default"; comboBox1.DataSource = Layouts; comboBox1.DisplayMember = "Name"; + loadSettings(); - // SerialPort initialisieren - _serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One) - { - DtrEnable = true - }; + //Serial init + _serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One); + _serialPort.DtrEnable = true; ports = SerialPort.GetPortNames(); comboBox2.DataSource = ports; - if (ports.Contains(portName)) { comboBox2.SelectedItem = portName; @@ -146,73 +159,58 @@ private void InitializeComponents() catch { } } _serialPort.DataReceived += portDataReceived; + Timer timer1 = new Timer { Interval = 250 }; - timer1.Tick += OnTimerEvent; timer1.Enabled = true; + timer1.Tick += new EventHandler(OnTimerEvent); } - private void UpdateLayoutVisibility(bool visible) - { - pictureBox01.Visible = visible; - pictureBox02.Visible = visible; - pictureBox03.Visible = visible; - pictureBox04.Visible = visible; - pictureBox05.Visible = visible; - pictureBox06.Visible = visible; - pictureBox07.Visible = visible; - pictureBox08.Visible = visible; - pictureBox09.Visible = visible; - AddBox.Enabled = visible; - RemoveBox.Enabled = visible; - hotkeyBox.Enabled = visible; - listBox1.Enabled = visible; - } - - private void switchToLayout(int layoutNum) + private void MainWindow_Resize(object sender, EventArgs e) { - CurrentLayout = layoutNum; - UpdatePictureBoxes(); - listBox1.DataSource = Layouts[currentLayout].Apps; - comboBox1.SelectedIndex = layoutNum; - hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; - - if (layoutNum == 0) - { - SendCommandToSerial((Byte)'D'); - } - else + if (this.WindowState == FormWindowState.Minimized) { - Layouts[currentLayout].drawAll(_serialPort); + this.Hide(); // Fenster ausblenden + notifyIcon.ShowBalloonTip(1000, "Keybon Companion", "Das Programm wurde in den Hintergrund verschoben.", ToolTipIcon.Info); } } - private void UpdatePictureBoxes() + private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) { - pictureBox01.Image = Layouts[currentLayout].oleds[0]; - pictureBox02.Image = Layouts[currentLayout].oleds[1]; - pictureBox03.Image = Layouts[currentLayout].oleds[2]; - pictureBox04.Image = Layouts[currentLayout].oleds[3]; - pictureBox05.Image = Layouts[currentLayout].oleds[4]; - pictureBox06.Image = Layouts[currentLayout].oleds[5]; - pictureBox07.Image = Layouts[currentLayout].oleds[6]; - pictureBox08.Image = Layouts[currentLayout].oleds[7]; - pictureBox09.Image = Layouts[currentLayout].oleds[8]; + this.Show(); + this.WindowState = FormWindowState.Normal; } private void portDataReceived(object sender, EventArgs args) { SerialPort port = sender as SerialPort; - if (port == null) return; + if (port == null) + { + return; + } + int keyReceived = _serialPort.ReadChar(); + Console.WriteLine(keyReceived); + //https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys.send try { - int keyReceived = _serialPort.ReadChar(); SendKeys.SendWait(Layouts[currentLayout].keyCommand[keyReceived - 49]); } catch { } + } + private void Form1_Load(object sender, EventArgs e) + { + + } + + [DllImport("user32.dll")] + static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + private void OnTimerEvent(object sender, EventArgs e) { const int nChars = 256; @@ -223,69 +221,342 @@ private void OnTimerEvent(object sender, EventArgs e) foreach (Process pro in AllProcess) { - if (!string.IsNullOrEmpty(pro.MainWindowTitle) && Buff.ToString().Equals(pro.MainWindowTitle)) + String mainWindowTitle = pro.MainWindowTitle; + if (mainWindowTitle != "" && Buff.ToString().Equals(mainWindowTitle)) { - CurrentApp = pro.ProcessName; + //Console.WriteLine(pro.ProcessName.ToString()); + CurrentApp = pro.ProcessName.ToString(); break; } } + } - private void loadSettings() + private void switchToLayout(int layoutNum) { - Properties.Settings.Default.Reload(); - if (!string.IsNullOrEmpty(Properties.Settings.Default.portName)) portName = Properties.Settings.Default.portName; + CurrentLayout = layoutNum; + pictureBox01.Image = Layouts[currentLayout].oleds[0]; + pictureBox02.Image = Layouts[currentLayout].oleds[1]; + pictureBox03.Image = Layouts[currentLayout].oleds[2]; + pictureBox04.Image = Layouts[currentLayout].oleds[3]; + pictureBox05.Image = Layouts[currentLayout].oleds[4]; + pictureBox06.Image = Layouts[currentLayout].oleds[5]; + pictureBox07.Image = Layouts[currentLayout].oleds[6]; + pictureBox08.Image = Layouts[currentLayout].oleds[7]; + pictureBox09.Image = Layouts[currentLayout].oleds[8]; - for (int i = 1; i < Layouts.Length; i++) + if (layoutNum == 0) + { + byte[] command = { (Byte)'D' }; + try + { + if(_serialPort != null) + _serialPort.Write(command, 0, command.Length); + } + catch { } + } + else + { + Layouts[currentLayout].drawAll(_serialPort); + } + + listBox1.DataSource = Layouts[currentLayout].Apps; + comboBox1.SelectedIndex = layoutNum; + hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; + } + + private void pictureBox_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.All; + else { - var layout = typeof(Properties.Settings.Default).GetProperty($"Layout{i}")?.GetValue(Properties.Settings.Default); - if (layout != null) Layouts[i] = (ScreenLayout)layout; + String[] strGetFormats = e.Data.GetFormats(); + e.Effect = DragDropEffects.None; } } - private void SendCommandToSerial(byte command) + private void pictureBox_DragDrop(object sender, DragEventArgs e) { + var eventSource = (sender as PictureBox); + string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false); + Bitmap image = new Bitmap(FileList[0]); + image = ResizeBitmap(image, 64, 48); + eventSource.Image = image; + int keyNum = Int16.Parse(eventSource.Name.Substring(10)); + Layouts[currentLayout].oleds[keyNum-1] = image; + Layouts[currentLayout].drawAll(_serialPort); + } + + private void listBox1_SelectedValueChanged(object sender, EventArgs e) + { + var eventSource = (sender as ListBox); + + } + + private void pictureBox_Click(object sender, EventArgs e) + { + var eventSource = (sender as PictureBox); + pictureBox01.BorderStyle = BorderStyle.None; + pictureBox02.BorderStyle = BorderStyle.None; + pictureBox03.BorderStyle = BorderStyle.None; + pictureBox04.BorderStyle = BorderStyle.None; + pictureBox05.BorderStyle = BorderStyle.None; + pictureBox06.BorderStyle = BorderStyle.None; + pictureBox07.BorderStyle = BorderStyle.None; + pictureBox08.BorderStyle = BorderStyle.None; + pictureBox09.BorderStyle = BorderStyle.None; + eventSource.BorderStyle = BorderStyle.Fixed3D; + selectedButton = Int16.Parse(eventSource.Name.Substring(10))-1; + hotkeyBox.Text = Layouts[currentLayout].keyCommand[selectedButton]; + } + + + private void label4_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start("https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys.send"); + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + var eventSource = (sender as ComboBox); + switchToLayout(eventSource.SelectedIndex); + } + + private void MainWindow_FormClosed(object sender, FormClosedEventArgs e) //Switch to Default Layout when Exiting + { + byte[] command = { (Byte)'D' }; try { - if (_serialPort?.IsOpen == true) - { - _serialPort.Write(new byte[] { command }, 0, 1); - } + _serialPort.Write(command, 0, command.Length); } catch { } + + saveSettings(); + } - [DllImport("user32.dll")] - static extern IntPtr GetForegroundWindow(); + private void checkBox1_CheckedChanged(object sender, EventArgs e) // Change Brightness + { + var eventSource = (sender as CheckBox); + if (eventSource.Checked) + { + byte[] command = { (Byte)'b' }; + _serialPort.Write(command, 0, command.Length); + } + else + { + byte[] command = { (Byte)'B' }; + _serialPort.Write(command, 0, command.Length); + } - [DllImport("user32.dll")] - static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + } + + private void hotkeyBox_TextChanged(object sender, EventArgs e) + { + Layouts[currentLayout].keyCommand[selectedButton] = hotkeyBox.Text; + } + + private void AddBox_Click(object sender, EventArgs e) + { + AppSelect f2 = new AppSelect(this); + f2.ShowDialog(); + } + + private void RemoveBox_Click(object sender, EventArgs e) + { + if(listBox1.SelectedItem != null) + Layouts[currentLayout].Apps.Remove(listBox1.SelectedItem.ToString()); + listBox1.DataSource = null; + listBox1.DataSource = Layouts[currentLayout].Apps; + } + + private void comboBox2_DropDown(object sender, EventArgs e) + { + ports = SerialPort.GetPortNames(); + comboBox2.DataSource = ports; + } + + private void comboBox2_SelectionChangeCommitted(object sender, EventArgs e) + { + _serialPort.Close(); + _serialPort.PortName = comboBox2.SelectedItem.ToString(); + try + { + _serialPort.Open(); + } + catch { } + } + + private void saveSettings() + { + Properties.Settings.Default.portName = portName; + Properties.Settings.Default.Layout1 = Layouts[1]; + Properties.Settings.Default.Layout2 = Layouts[2]; + Properties.Settings.Default.Layout3 = Layouts[3]; + Properties.Settings.Default.Layout4 = Layouts[4]; + Properties.Settings.Default.Layout5 = Layouts[5]; + Properties.Settings.Default.Layout6 = Layouts[6]; + Properties.Settings.Default.Layout7 = Layouts[7]; + Properties.Settings.Default.Save(); + } + + private void loadSettings() + { + Properties.Settings.Default.Reload(); + if (Properties.Settings.Default.portName != "") portName = Properties.Settings.Default.portName; + if (Properties.Settings.Default.Layout1 != null) Layouts[1] = Properties.Settings.Default.Layout1; + if (Properties.Settings.Default.Layout2 != null) Layouts[2] = Properties.Settings.Default.Layout2; + if (Properties.Settings.Default.Layout3 != null) Layouts[3] = Properties.Settings.Default.Layout3; + if (Properties.Settings.Default.Layout4 != null) Layouts[4] = Properties.Settings.Default.Layout4; + if (Properties.Settings.Default.Layout5 != null) Layouts[5] = Properties.Settings.Default.Layout5; + if (Properties.Settings.Default.Layout6 != null) Layouts[6] = Properties.Settings.Default.Layout6; + if (Properties.Settings.Default.Layout7 != null) Layouts[7] = Properties.Settings.Default.Layout7; + } + public Bitmap ResizeBitmap(Bitmap bmp, int width, int height) + { + Bitmap result = new Bitmap(width, height); + using (Graphics g = Graphics.FromImage(result)) + { + g.DrawImage(bmp, 0, 0, width, height); + } + + return result; + } } + //--------------------------------------------------------------------------------------------------------------- [SettingsSerializeAs(SettingsSerializeAs.Xml)] public class ScreenLayout { [XmlIgnore] - public Bitmap[] oleds = new Bitmap[9]; - public string[] keyCommand = new string[9]; + public Bitmap[] oleds = { new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48), + new Bitmap(64, 48) + }; + + [XmlElement("oleds")] + public byte[][] oledsSerialized + { + get + { // serialize + if (oleds[0] == null) + return null; + byte[][] _byte = new byte[9][]; + for (int i = 0; i < oleds.Length; i++) + { + MemoryStream ms = new MemoryStream(); + oleds[i].Save(ms, ImageFormat.Bmp); + _byte[i] = ms.ToArray(); + } + return _byte; + } + set + { // deserialize + for (int i = 0; i < oleds.Length; i++) + { + MemoryStream ms = new MemoryStream(value[i]); + oleds[i] = new Bitmap(ms); + } + } + } + + public String[] keyCommand = new string[9]; + public List Apps = new List(); - public string name { get; set; } + public String name { get; set; } public ScreenLayout() + { + keyCommand[0] = "{1}"; + keyCommand[1] = "{2}"; + keyCommand[2] = "{3}"; + keyCommand[3] = "{4}"; + keyCommand[4] = "{5}"; + keyCommand[5] = "{6}"; + keyCommand[6] = "{7}"; + keyCommand[7] = "{8}"; + keyCommand[8] = "{9}"; + } + public void drawAll(SerialPort _serialPort) { for (int i = 0; i < oleds.Length; i++) + writeImageToSerial(_serialPort, i + 1, oleds[i]); + } + + private void writeImageToSerial(SerialPort _serialPort, int keyNum, Bitmap bmp) + { + //Straight from https://docs.microsoft.com/de-de/dotnet/api/system.drawing.imaging.bitmapdata?redirectedfrom=MSDN&view=dotnet-plat-ext-5.0 + // Lock the bitmap's bits. + Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); + System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); + + // Get the address of the first line. + IntPtr ptr = bmpData.Scan0; + + // Declare an array to hold the bytes of the bitmap. + int bytesb = Math.Abs(bmpData.Stride) * bmp.Height; + byte[] rgbValues = new byte[bytesb]; + System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytesb); + + // Unlock the bits. + bmp.UnlockBits(bmpData); + + BitArray bits = new BitArray(bmp.Width * bmp.Height); + for (int i = 0; i < rgbValues.Length; i+=4) + { + double brightness = (rgbValues[i] + rgbValues[i+1] + rgbValues[i+2]) / 3; + bits[i/4] = (brightness >= 128); + } + + var bytes = new byte[(bits.Length - 1) / 8 + 1]; + bits.CopyTo(bytes, 0); + + for (int i = 0; i < bytes.Length; i++) { - oleds[i] = new Bitmap(64, 48); - keyCommand[i] = $"{{{i + 1}}}"; + bytes[i] = Reverse(bytes[i]); + } + + byte commandbyte = (byte)(47 + keyNum); //starting with ASCII 0 + try + { + byte[] command = { commandbyte }; + _serialPort.Write(command, 0, command.Length); + _serialPort.Write(bytes, 0, bytes.Length); + } + catch (Exception) { + Console.WriteLine("tx problem"); } } - public void drawAll(SerialPort _serialPort) + // Reverses bits in a byte (https://softwarejuancarlos.com/2013/05/05/byte_bits_reverse/) + public static byte Reverse(byte inByte) { - for (int i = 0; i < oleds.Length; i++) + byte result = 0x00; + + for (byte mask = 0x80; Convert.ToInt32(mask) > 0; mask >>= 1) { - // Logic to send image to Serial + // shift right current result + result = (byte)(result >> 1); + + // tempbyte = 1 if there is a 1 in the current position + var tempbyte = (byte)(inByte & mask); + if (tempbyte != 0x00) + { + // Insert a 1 in the left + result = (byte)(result | 0x80); + } } + + return (result); } + } + }