using System; using System.Collections; using System.Drawing; using System.IO.Ports; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; namespace iClicker { class Program { static ArrayList[] answerLists = new ArrayList[5]; static bool answerListsUpdated = true; static int mostAnswer; static NotifyIcon notifyIcon = new NotifyIcon(); static bool consoleVisibility = true; static String channel = "#AA"; static void Main(String[] args) { if (args.Length < 1) return; if (args.Length == 2) channel = "#" + args[1].ToUpper(); for (int i = 0; i < 5; i++) answerLists[i] = new ArrayList(); // notify icon menu notifyIcon.Visible = true; SetConsoleWindowVisibility(false); notifyIcon.DoubleClick += (s, e) => { consoleVisibility = !consoleVisibility; SetConsoleWindowVisibility(consoleVisibility); }; var contextMenu = new ContextMenuStrip(); contextMenu.Items.Add("Reset", null, (s, e) => { for (int i = 0; i < 5; i++) answerLists[i].Clear(); answerListsUpdated = true; }); contextMenu.Items.Add("Exit", null, (s, e) => { Application.Exit(); }); notifyIcon.ContextMenuStrip = contextMenu; SerialPort mySerialPort = new SerialPort(args[0].ToUpper()); mySerialPort.BaudRate = 115200; mySerialPort.Parity = Parity.None; mySerialPort.StopBits = StopBits.One; mySerialPort.DataBits = 8; mySerialPort.Handshake = Handshake.None; mySerialPort.RtsEnable = true; mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); mySerialPort.Open(); mySerialPort.WriteLine(channel); System.Timers.Timer timer = new System.Timers.Timer(1000); timer.Elapsed += async (sender, e) => await Task.Run(() => updateResult()); timer.Start(); Application.Run(); mySerialPort.Close(); } private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; String indata = sp.ReadExisting(); if (indata[0] == '$') { // received answer char ans = indata[1]; String id = indata.Substring(2, 8); if (ans >= 'A' && ans <= 'E') { for (int i = 0; i < 5; i++) answerLists[i].Remove(id); answerLists[ans - 'A'].Add(id); answerListsUpdated = true; } } } private static void updateResult() { if (!answerListsUpdated) return; Console.Clear(); notifyIcon.Text = ""; int total = answerLists[0].Count + answerLists[1].Count + answerLists[2].Count + answerLists[3].Count + answerLists[4].Count; if (total == 0) total = 1; mostAnswer = 0; for (int i = 1; i < 5; i++) if (answerLists[i].Count > answerLists[mostAnswer].Count) mostAnswer = i; for (int i = 0; i < 5; i++) { if (i == mostAnswer) Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("{0}: {1}\t{2} {3:F}%", (char)(i + 'A'), answerLists[i].Count, new String('▄', answerLists[i].Count * 50 / total), answerLists[i].Count * 100.0 / total); if (i == mostAnswer) Console.ForegroundColor = ConsoleColor.White; } for (int i = 0; i < 5; i++) { if (i == mostAnswer) notifyIcon.Text += String.Format(" - "); notifyIcon.Text += String.Format("{0}: {1:F}%\n", (char)(i + 'A'), answerLists[i].Count * 100.0 / total); } updateIcon(((char)(mostAnswer + 'A')).ToString(), answerLists[mostAnswer].Count * 100 / total + "%"); answerListsUpdated = false; } public static void SetConsoleWindowVisibility(bool visible) { IntPtr hWnd = FindWindow(null, Console.Title); if (hWnd != IntPtr.Zero) { if (visible) ShowWindow(hWnd, 1); //1 = SW_SHOWNORMAL else ShowWindow(hWnd, 0); //0 = SW_HIDE } } public static void updateIcon(String line1, String line2) { Font line1Font = new Font("Arial Black", 128, FontStyle.Regular, GraphicsUnit.Pixel); Font line2Font = new Font("Arial Black", 104, FontStyle.Regular, GraphicsUnit.Pixel); Brush brushToUse = new SolidBrush(Color.White); Bitmap bitmapText = new Bitmap(256, 256); Graphics g = System.Drawing.Graphics.FromImage(bitmapText); IntPtr hIcon; g.Clear(Color.Transparent); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; g.DrawString(line1, line1Font, brushToUse, 56, 0); g.DrawString(line2, line2Font, brushToUse, 0, 140); hIcon = (bitmapText.GetHicon()); notifyIcon.Icon = System.Drawing.Icon.FromHandle(hIcon); } [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); } }