Fixing table borders in non-inverted mode.
Experimention with color FX chessboard which is just awesome.
2 using System.Collections.Generic;
3 using System.ComponentModel;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
11 using CodeProject.Dialog;
12 using System.Drawing.Imaging;
13 using System.ServiceModel;
14 using System.Threading;
15 using System.Diagnostics;
17 using SharpDisplayClient;
20 namespace SharpDisplayManager
23 public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
24 public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
27 /// Our Display manager main form
29 public partial class MainForm : Form
32 DateTime LastTickTime;
34 System.Drawing.Bitmap iBmp;
35 bool iCreateBitmap; //Workaround render to bitmap issues when minimized
36 ServiceHost iServiceHost;
38 /// Our collection of clients
40 public Dictionary<string, ClientData> iClients;
42 ColorProcessingDelegate iColorFx;
43 CoordinateTranslationDelegate iScreenX;
44 CoordinateTranslationDelegate iScreenY;
48 LastTickTime = DateTime.Now;
49 iDisplay = new Display();
50 iClients = new Dictionary<string, ClientData>();
52 InitializeComponent();
54 //We have a bug when drawing minimized and reusing our bitmap
55 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
56 iCreateBitmap = false;
58 //this.tableLayoutPanel.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPanel_CellPaint);
61 private void MainForm_Load(object sender, EventArgs e)
65 if (Properties.Settings.Default.DisplayConnectOnStartup)
67 OpenDisplayConnection();
72 private void tableLayoutPanel_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
74 var panel = sender as TableLayoutPanel;
75 //e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
76 var rectangle = e.CellBounds;
77 using (var pen = new Pen(Color.Black, 1))
79 pen.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
80 pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
82 if (e.Row == (panel.RowCount - 1))
84 rectangle.Height -= 1;
87 if (e.Column == (panel.ColumnCount - 1))
92 e.Graphics.DrawRectangle(pen, rectangle);
97 private void buttonFont_Click(object sender, EventArgs e)
99 //fontDialog.ShowColor = true;
100 //fontDialog.ShowApply = true;
101 fontDialog.ShowEffects = true;
102 fontDialog.Font = marqueeLabelTop.Font;
104 fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
106 //fontDialog.ShowHelp = true;
108 //fontDlg.MaxSize = 40;
109 //fontDlg.MinSize = 22;
111 //fontDialog.Parent = this;
112 //fontDialog.StartPosition = FormStartPosition.CenterParent;
114 //DlgBox.ShowDialog(fontDialog);
116 //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
117 if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
120 //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
122 //MessageBox.Show("Ok");
123 marqueeLabelTop.Font = fontDialog.Font;
124 marqueeLabelBottom.Font = fontDialog.Font;
125 cds.Font = fontDialog.Font;
126 Properties.Settings.Default.Save();
135 void CheckFontHeight()
137 //Show font height and width
138 labelFontHeight.Text = "Font height: " + cds.Font.Height;
139 float charWidth = IsFixedWidth(cds.Font);
140 if (charWidth == 0.0f)
142 labelFontWidth.Visible = false;
146 labelFontWidth.Visible = true;
147 labelFontWidth.Text = "Font width: " + charWidth;
150 //Now check font height and show a warning if needed.
151 if (marqueeLabelBottom.Font.Height > marqueeLabelBottom.Height)
153 labelWarning.Text = "WARNING: Selected font is too height by " + (marqueeLabelBottom.Font.Height - marqueeLabelBottom.Height) + " pixels!";
154 labelWarning.Visible = true;
158 labelWarning.Visible = false;
163 private void buttonCapture_Click(object sender, EventArgs e)
165 System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
166 tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
167 //Bitmap bmpToSave = new Bitmap(bmp);
168 bmp.Save("D:\\capture.png");
170 marqueeLabelTop.Text = "Sweet";
173 string outputFileName = "d:\\capture.png";
174 using (MemoryStream memory = new MemoryStream())
176 using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
178 bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
179 byte[] bytes = memory.ToArray();
180 fs.Write(bytes, 0, bytes.Length);
187 private void CheckForRequestResults()
189 if (iDisplay.IsRequestPending())
191 switch (iDisplay.AttemptRequestCompletion())
193 case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
194 toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
195 //Issue next request then
196 iDisplay.RequestPowerSupplyStatus();
199 case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
200 if (iDisplay.PowerSupplyStatus())
202 toolStripStatusLabelPower.Text = "ON";
206 toolStripStatusLabelPower.Text = "OFF";
208 //Issue next request then
209 iDisplay.RequestDeviceId();
212 case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
213 toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
214 //No more request to issue
220 public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
222 if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
229 public static uint ColorUntouched(int aX, int aY, uint aPixel)
234 public static uint ColorInversed(int aX, int aY, uint aPixel)
239 public static uint ColorChessboard(int aX, int aY, uint aPixel)
241 if ((aX % 2 == 0) && (aY % 2 == 0))
245 else if ((aX % 2 != 0) && (aY % 2 != 0))
253 public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
255 return aBmp.Width - aX - 1;
258 public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
260 return iBmp.Height - aY - 1;
263 public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
268 public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
274 /// Select proper pixel delegates according to our current settings.
276 private void SetupPixelDelegates()
278 //Select our pixel processing routine
279 if (cds.InverseColors)
281 //iColorFx = ColorChessboard;
282 iColorFx = ColorInversed;
286 iColorFx = ColorWhiteIsOn;
289 //Select proper coordinate translation functions
290 //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
291 if (cds.ReverseScreen)
293 iScreenX = ScreenReversedX;
294 iScreenY = ScreenReversedY;
304 //This is our timer tick responsible to perform our render
305 private void timer_Tick(object sender, EventArgs e)
307 //Update our animations
308 DateTime NewTickTime = DateTime.Now;
310 marqueeLabelTop.UpdateAnimation(LastTickTime, NewTickTime);
311 marqueeLabelBottom.UpdateAnimation(LastTickTime, NewTickTime);
314 if (iDisplay.IsOpen())
316 CheckForRequestResults();
321 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
323 tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
324 //iBmp.Save("D:\\capture.png");
326 //Send it to our display
327 for (int i = 0; i < iBmp.Width; i++)
329 for (int j = 0; j < iBmp.Height; j++)
333 //Get our processed pixel coordinates
334 int x = iScreenX(iBmp, i);
335 int y = iScreenY(iBmp, j);
337 uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
338 //Apply color effects
339 color = iColorFx(x,y,color);
341 iDisplay.SetPixel(x, y, color);
346 iDisplay.SwapBuffers();
350 //Compute instant FPS
351 toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
353 LastTickTime = NewTickTime;
357 private void OpenDisplayConnection()
359 CloseDisplayConnection();
361 if (iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
364 iDisplay.RequestFirmwareRevision();
369 toolStripStatusLabelConnect.Text = "Connection error";
373 private void CloseDisplayConnection()
379 private void buttonOpen_Click(object sender, EventArgs e)
381 OpenDisplayConnection();
384 private void buttonClose_Click(object sender, EventArgs e)
386 CloseDisplayConnection();
389 private void buttonClear_Click(object sender, EventArgs e)
392 iDisplay.SwapBuffers();
395 private void buttonFill_Click(object sender, EventArgs e)
398 iDisplay.SwapBuffers();
401 private void trackBarBrightness_Scroll(object sender, EventArgs e)
403 cds.Brightness = trackBarBrightness.Value;
404 Properties.Settings.Default.Save();
405 iDisplay.SetBrightness(trackBarBrightness.Value);
411 /// CDS stands for Current Display Settings
413 private DisplaySettings cds
417 DisplaysSettings settings = Properties.Settings.Default.DisplaySettings;
418 if (settings == null)
420 settings = new DisplaysSettings();
422 Properties.Settings.Default.DisplaySettings = settings;
425 //Make sure all our settings have been created
426 while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
428 settings.Displays.Add(new DisplaySettings());
431 DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
432 return displaySettings;
437 /// Check if the given font has a fixed character pitch.
439 /// <param name="ft"></param>
440 /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
441 public float IsFixedWidth(Font ft)
443 Graphics g = CreateGraphics();
444 char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
445 float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
447 bool fixedWidth = true;
449 foreach (char c in charSizes)
450 if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
461 private void UpdateStatus()
463 //Synchronize UI with settings
465 checkBoxShowBorders.Checked = cds.ShowBorders;
466 tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
467 marqueeLabelTop.Font = cds.Font;
468 marqueeLabelBottom.Font = cds.Font;
470 checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
471 checkBoxReverseScreen.Checked = cds.ReverseScreen;
472 checkBoxInverseColors.Checked = cds.InverseColors;
473 comboBoxDisplayType.SelectedIndex = cds.DisplayType;
474 timer.Interval = cds.TimerInterval;
475 maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
477 SetupPixelDelegates();
479 if (iDisplay.IsOpen())
481 //Only setup brightness if display is open
482 trackBarBrightness.Minimum = iDisplay.MinBrightness();
483 trackBarBrightness.Maximum = iDisplay.MaxBrightness();
484 trackBarBrightness.Value = cds.Brightness;
485 trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
486 trackBarBrightness.SmallChange = 1;
487 iDisplay.SetBrightness(cds.Brightness);
489 buttonFill.Enabled = true;
490 buttonClear.Enabled = true;
491 buttonOpen.Enabled = false;
492 buttonClose.Enabled = true;
493 trackBarBrightness.Enabled = true;
494 toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
495 //+ " - " + iDisplay.SerialNumber();
497 if (iDisplay.SupportPowerOnOff())
499 buttonPowerOn.Enabled = true;
500 buttonPowerOff.Enabled = true;
504 buttonPowerOn.Enabled = false;
505 buttonPowerOff.Enabled = false;
508 if (iDisplay.SupportClock())
510 buttonShowClock.Enabled = true;
511 buttonHideClock.Enabled = true;
515 buttonShowClock.Enabled = false;
516 buttonHideClock.Enabled = false;
521 buttonFill.Enabled = false;
522 buttonClear.Enabled = false;
523 buttonOpen.Enabled = true;
524 buttonClose.Enabled = false;
525 trackBarBrightness.Enabled = false;
526 buttonPowerOn.Enabled = false;
527 buttonPowerOff.Enabled = false;
528 buttonShowClock.Enabled = false;
529 buttonHideClock.Enabled = false;
530 toolStripStatusLabelConnect.Text = "Disconnected";
531 toolStripStatusLabelPower.Text = "N/A";
537 private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
539 //Save our show borders setting
540 tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
541 cds.ShowBorders = checkBoxShowBorders.Checked;
542 Properties.Settings.Default.Save();
546 private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
548 //Save our connect on startup setting
549 Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
550 Properties.Settings.Default.Save();
553 private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
555 //Save our reverse screen setting
556 cds.ReverseScreen = checkBoxReverseScreen.Checked;
557 Properties.Settings.Default.Save();
558 SetupPixelDelegates();
561 private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
563 //Save our inverse colors setting
564 cds.InverseColors = checkBoxInverseColors.Checked;
565 Properties.Settings.Default.Save();
566 SetupPixelDelegates();
569 private void MainForm_Resize(object sender, EventArgs e)
571 if (WindowState == FormWindowState.Minimized)
574 //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
575 iCreateBitmap = true;
579 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
585 public void StartServer()
587 iServiceHost = new ServiceHost
590 new Uri[] { new Uri("net.tcp://localhost:8001/") }
593 iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
597 public void StopServer()
599 if (iClients.Count > 0 && !iClosing)
603 BroadcastCloseEvent();
607 if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
609 iClosing = false; //We make sure we force close if asked twice
614 //We removed that as it often lags for some reason
615 //iServiceHost.Close();
619 public void BroadcastCloseEvent()
621 Trace.TraceInformation("BroadcastCloseEvent - start");
623 var inactiveClients = new List<string>();
624 foreach (var client in iClients)
626 //if (client.Key != eventData.ClientName)
630 Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
631 client.Value.Callback.OnCloseOrder(/*eventData*/);
635 inactiveClients.Add(client.Key);
640 if (inactiveClients.Count > 0)
642 foreach (var client in inactiveClients)
644 iClients.Remove(client);
645 Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
650 private void buttonStartClient_Click(object sender, EventArgs e)
652 Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
653 clientThread.Start();
657 private void buttonSuspend_Click(object sender, EventArgs e)
659 LastTickTime = DateTime.Now; //Reset timer to prevent jump
660 timer.Enabled = !timer.Enabled;
663 buttonSuspend.Text = "Run";
667 buttonSuspend.Text = "Pause";
671 private void buttonCloseClients_Click(object sender, EventArgs e)
673 BroadcastCloseEvent();
676 private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
681 //Delegates are used for our thread safe method
682 public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
683 public delegate void RemoveClientDelegate(string aSessionId);
684 public delegate void SetTextDelegate(string SessionId, TextField aTextField);
685 public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList<TextField> aTextFields);
686 public delegate void SetClientNameDelegate(string aSessionId, string aName);
692 /// <param name="aSessionId"></param>
693 /// <param name="aCallback"></param>
694 public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
696 if (this.InvokeRequired)
698 //Not in the proper thread, invoke ourselves
699 AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
700 this.Invoke(d, new object[] { aSessionId, aCallback });
704 //We are in the proper thread
705 //Add this session to our collection of clients
706 ClientData newClient = new ClientData(aSessionId, aCallback);
707 Program.iMainForm.iClients.Add(aSessionId, newClient);
708 //Add this session to our UI
709 UpdateClientTreeViewNode(newClient);
716 /// <param name="aSessionId"></param>
717 public void RemoveClientThreadSafe(string aSessionId)
719 if (this.InvokeRequired)
721 //Not in the proper thread, invoke ourselves
722 RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
723 this.Invoke(d, new object[] { aSessionId });
727 //We are in the proper thread
728 //Remove this session from both client collection and UI tree view
729 if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
731 Program.iMainForm.iClients.Remove(aSessionId);
732 Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
735 if (iClosing && iClients.Count == 0)
737 //We were closing our form
738 //All clients are now closed
739 //Just resume our close operation
749 /// <param name="aLineIndex"></param>
750 /// <param name="aText"></param>
751 public void SetTextThreadSafe(string aSessionId, TextField aTextField)
753 if (this.InvokeRequired)
755 //Not in the proper thread, invoke ourselves
756 SetTextDelegate d = new SetTextDelegate(SetTextThreadSafe);
757 this.Invoke(d, new object[] { aSessionId, aTextField });
761 ClientData client = iClients[aSessionId];
764 //Make sure all our texts are in place
765 while (client.Texts.Count < (aTextField.Index + 1))
767 //Add a text field with proper index
768 client.Texts.Add(new TextField(client.Texts.Count));
770 client.Texts[aTextField.Index] = aTextField;
772 //We are in the proper thread
773 //Only support two lines for now
774 if (aTextField.Index == 0)
776 marqueeLabelTop.Text = aTextField.Text;
777 marqueeLabelTop.TextAlign = aTextField.Alignment;
779 else if (aTextField.Index == 1)
781 marqueeLabelBottom.Text = aTextField.Text;
782 marqueeLabelBottom.TextAlign = aTextField.Alignment;
786 UpdateClientTreeViewNode(client);
794 /// <param name="aTexts"></param>
795 public void SetTextsThreadSafe(string aSessionId, System.Collections.Generic.IList<TextField> aTextFields)
797 if (this.InvokeRequired)
799 //Not in the proper thread, invoke ourselves
800 SetTextsDelegate d = new SetTextsDelegate(SetTextsThreadSafe);
801 this.Invoke(d, new object[] { aSessionId, aTextFields });
805 //We are in the proper thread
806 ClientData client = iClients[aSessionId];
809 //Populate our client with the given text fields
811 foreach (TextField textField in aTextFields)
813 if (client.Texts.Count < (j + 1))
815 client.Texts.Add(textField);
819 client.Texts[j] = textField;
823 //Only support two lines for now
824 for (int i = 0; i < aTextFields.Count; i++)
826 if (aTextFields[i].Index == 0)
828 marqueeLabelTop.Text = aTextFields[i].Text;
829 marqueeLabelTop.TextAlign = aTextFields[i].Alignment;
831 else if (aTextFields[i].Index == 1)
833 marqueeLabelBottom.Text = aTextFields[i].Text;
834 marqueeLabelBottom.TextAlign = aTextFields[i].Alignment;
839 UpdateClientTreeViewNode(client);
848 /// <param name="aSessionId"></param>
849 /// <param name="aName"></param>
850 public void SetClientNameThreadSafe(string aSessionId, string aName)
852 if (this.InvokeRequired)
854 //Not in the proper thread, invoke ourselves
855 SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
856 this.Invoke(d, new object[] { aSessionId, aName });
860 //We are in the proper thread
862 ClientData client = iClients[aSessionId];
867 //Update our tree-view
868 UpdateClientTreeViewNode(client);
876 /// <param name="aClient"></param>
877 private void UpdateClientTreeViewNode(ClientData aClient)
884 TreeNode node = null;
885 //Check that our client node already exists
886 //Get our client root node using its key which is our session ID
887 TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
890 //We already have a node for that client
892 //Clear children as we are going to recreate them below
897 //Client node does not exists create a new one
898 treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
899 node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
905 if (aClient.Name != "")
907 //We have a name, us it as text for our root node
908 node.Text = aClient.Name;
909 //Add a child with SessionId
910 node.Nodes.Add(new TreeNode(aClient.SessionId));
914 //No name, use session ID instead
915 node.Text = aClient.SessionId;
918 if (aClient.Texts.Count > 0)
920 //Create root node for our texts
921 TreeNode textsRoot = new TreeNode("Text");
922 node.Nodes.Add(textsRoot);
923 //For each text add a new entry
924 foreach (TextField field in aClient.Texts)
926 textsRoot.Nodes.Add(new TreeNode(field.Text));
934 private void buttonAddRow_Click(object sender, EventArgs e)
936 if (tableLayoutPanel.RowCount < 6)
938 tableLayoutPanel.RowCount++;
943 private void buttonRemoveRow_Click(object sender, EventArgs e)
945 if (tableLayoutPanel.RowCount > 1)
947 tableLayoutPanel.RowCount--;
952 private void buttonAddColumn_Click(object sender, EventArgs e)
954 if (tableLayoutPanel.ColumnCount < 8)
956 tableLayoutPanel.ColumnCount++;
961 private void buttonRemoveColumn_Click(object sender, EventArgs e)
963 if (tableLayoutPanel.ColumnCount > 1)
965 tableLayoutPanel.ColumnCount--;
970 private void buttonAlignLeft_Click(object sender, EventArgs e)
972 marqueeLabelTop.TextAlign = ContentAlignment.MiddleLeft;
973 marqueeLabelBottom.TextAlign = ContentAlignment.MiddleLeft;
976 private void buttonAlignCenter_Click(object sender, EventArgs e)
978 marqueeLabelTop.TextAlign = ContentAlignment.MiddleCenter;
979 marqueeLabelBottom.TextAlign = ContentAlignment.MiddleCenter;
982 private void buttonAlignRight_Click(object sender, EventArgs e)
984 marqueeLabelTop.TextAlign = ContentAlignment.MiddleRight;
985 marqueeLabelBottom.TextAlign = ContentAlignment.MiddleRight;
988 private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
990 Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
991 cds.DisplayType = comboBoxDisplayType.SelectedIndex;
992 Properties.Settings.Default.Save();
993 if (iDisplay.IsOpen())
995 OpenDisplayConnection();
1004 private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
1006 if (maskedTextBoxTimerInterval.Text != "")
1008 int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
1012 timer.Interval = interval;
1013 cds.TimerInterval = timer.Interval;
1014 Properties.Settings.Default.Save();
1019 private void buttonPowerOn_Click(object sender, EventArgs e)
1024 private void buttonPowerOff_Click(object sender, EventArgs e)
1026 iDisplay.PowerOff();
1029 private void buttonShowClock_Click(object sender, EventArgs e)
1031 iDisplay.ShowClock();
1034 private void buttonHideClock_Click(object sender, EventArgs e)
1036 iDisplay.HideClock();
1042 /// A UI thread copy of a client relevant data.
1043 /// Keeping this copy in the UI thread helps us deal with threading issues.
1045 public class ClientData
1047 public ClientData(string aSessionId, ICallback aCallback)
1049 SessionId = aSessionId;
1051 Texts = new List<TextField>();
1052 Callback = aCallback;
1055 public string SessionId { get; set; }
1056 public string Name { get; set; }
1057 public List<TextField> Texts { get; set; }
1058 public ICallback Callback { get; set; }