Server/MainForm.cs
author sl
Thu, 14 Aug 2014 09:30:14 +0200
changeset 25 6f10207a89a8
parent 22 cac466b1b6e6
child 27 9c49c04fc620
permissions -rw-r--r--
Fixing hang when closing server with live client due to client instance context
throwing an exception when closing.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Threading.Tasks;
     9 using System.Windows.Forms;
    10 using System.IO;
    11 using CodeProject.Dialog;
    12 using System.Drawing.Imaging;
    13 using System.ServiceModel;
    14 using System.Threading;
    15 //
    16 using SharpDisplayInterface;
    17 using SharpDisplayClient;
    18 
    19 
    20 namespace SharpDisplayManager
    21 {
    22     public partial class MainForm : Form
    23     {
    24         DateTime LastTickTime;
    25         Display iDisplay;
    26         System.Drawing.Bitmap iBmp;
    27         bool iCreateBitmap; //Workaround render to bitmap issues when minimized
    28         ServiceHost iServiceHost;
    29         /// <summary>
    30         /// Our collection of clients
    31         /// </summary>
    32         public Dictionary<string, IDisplayServiceCallback> iClients;
    33 
    34         public MainForm()
    35         {
    36             LastTickTime = DateTime.Now;
    37             iDisplay = new Display();
    38             iClients = new Dictionary<string, IDisplayServiceCallback>();
    39 
    40             InitializeComponent();
    41             UpdateStatus();
    42 
    43             //Load settings
    44             marqueeLabelTop.Font = Properties.Settings.Default.DisplayFont;
    45             marqueeLabelBottom.Font = Properties.Settings.Default.DisplayFont;
    46             checkBoxShowBorders.Checked = Properties.Settings.Default.DisplayShowBorders;
    47             checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
    48             checkBoxReverseScreen.Checked = Properties.Settings.Default.DisplayReverseScreen;
    49             //
    50             tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
    51             //We have a bug when drawing minimized and reusing our bitmap
    52             iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
    53             iCreateBitmap = false;
    54         }
    55 
    56         private void MainForm_Load(object sender, EventArgs e)
    57         {
    58             StartServer();
    59 
    60             if (Properties.Settings.Default.DisplayConnectOnStartup)
    61             {
    62                 iDisplay.Open();
    63                 UpdateStatus();
    64             }
    65         }
    66 
    67 
    68         private void buttonFont_Click(object sender, EventArgs e)
    69         {
    70             //fontDialog.ShowColor = true;
    71             //fontDialog.ShowApply = true;
    72             fontDialog.ShowEffects = true;
    73             fontDialog.Font = marqueeLabelTop.Font;
    74             //fontDialog.ShowHelp = true;
    75 
    76             //fontDlg.MaxSize = 40;
    77             //fontDlg.MinSize = 22;
    78 
    79             //fontDialog.Parent = this;
    80             //fontDialog.StartPosition = FormStartPosition.CenterParent;
    81 
    82             //DlgBox.ShowDialog(fontDialog);
    83 
    84             //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
    85             if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
    86             {
    87 
    88                 //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
    89 
    90                 //MessageBox.Show("Ok");
    91                 marqueeLabelTop.Font = fontDialog.Font;
    92                 marqueeLabelBottom.Font = fontDialog.Font;
    93                 Properties.Settings.Default.DisplayFont = fontDialog.Font;
    94                 Properties.Settings.Default.Save();
    95                 //label1.Font = fontDlg.Font;
    96                 //textBox1.BackColor = fontDlg.Color;
    97                 //label1.ForeColor = fontDlg.Color;
    98             }
    99         }
   100 
   101         private void buttonCapture_Click(object sender, EventArgs e)
   102         {
   103             System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
   104             tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
   105             //Bitmap bmpToSave = new Bitmap(bmp);
   106             bmp.Save("D:\\capture.png");
   107 
   108             marqueeLabelTop.Text = "Sweet";
   109 
   110             /*
   111             string outputFileName = "d:\\capture.png";
   112             using (MemoryStream memory = new MemoryStream())
   113             {
   114                 using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
   115                 {
   116                     bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
   117                     byte[] bytes = memory.ToArray();
   118                     fs.Write(bytes, 0, bytes.Length);
   119                 }
   120             }
   121              */
   122 
   123         }
   124 
   125         private void CheckForRequestResults()
   126         {
   127             if (iDisplay.IsRequestPending())
   128             {
   129                 switch (iDisplay.AttemptRequestCompletion())
   130                 {
   131                     case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
   132                         if (iDisplay.PowerSupplyStatus())
   133                         {
   134                             toolStripStatusLabelPower.Text = "ON";
   135                         }
   136                         else
   137                         {
   138                             toolStripStatusLabelPower.Text = "OFF";
   139                         }
   140                         //Issue next request then
   141                         iDisplay.RequestDeviceId();
   142                         break;
   143 
   144                     case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
   145                         toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
   146                         //Issue next request then
   147                         iDisplay.RequestFirmwareRevision();
   148                         break;
   149 
   150                     case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
   151                         toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
   152                         //No more request to issue
   153                         break;
   154                 }
   155             }
   156         }
   157 
   158 
   159         public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
   160 
   161 
   162         public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
   163         {
   164             return aBmp.Width - aX - 1;
   165         }
   166 
   167         public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
   168         {
   169             return iBmp.Height - aY - 1;
   170         }
   171 
   172         public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
   173         {
   174             return aX;
   175         }
   176 
   177         public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
   178         {
   179             return aY;
   180         }
   181 
   182 
   183         //This is our timer tick responsible to perform our render
   184         private void timer_Tick(object sender, EventArgs e)
   185         {
   186             //Update our animations
   187             DateTime NewTickTime = DateTime.Now;
   188 
   189             marqueeLabelTop.UpdateAnimation(LastTickTime, NewTickTime);
   190             marqueeLabelBottom.UpdateAnimation(LastTickTime, NewTickTime);
   191 
   192             //Update our display
   193             if (iDisplay.IsOpen())
   194             {
   195                 CheckForRequestResults();
   196 
   197                 //Draw to bitmap
   198                 if (iCreateBitmap)
   199                 {
   200                     iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
   201                 }
   202                 tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
   203                 //iBmp.Save("D:\\capture.png");
   204 
   205                 //Select proper coordinate translation functions
   206                 //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
   207                 CoordinateTranslationDelegate screenX;
   208                 CoordinateTranslationDelegate screenY;
   209 
   210                 if (Properties.Settings.Default.DisplayReverseScreen)
   211                 {
   212                     screenX = ScreenReversedX;
   213                     screenY = ScreenReversedY;
   214                 }
   215                 else
   216                 {
   217                     screenX = ScreenX;
   218                     screenY = ScreenY;
   219                 }
   220 
   221                 //Send it to our display
   222                 for (int i = 0; i < iBmp.Width; i++)
   223                 {
   224                     for (int j = 0; j < iBmp.Height; j++)
   225                     {
   226                         unchecked
   227                         {
   228                             uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
   229                             //For some reason when the app is minimized in the task bar only the alpha of our color is set.
   230                             //Thus that strange test for rendering to work both when the app is in the task bar and when it isn't.
   231                             iDisplay.SetPixel(screenX(iBmp, i), screenY(iBmp, j), Convert.ToInt32(!(color != 0xFF000000)));
   232                         }
   233                     }
   234                 }
   235 
   236                 iDisplay.SwapBuffers();
   237 
   238             }
   239 
   240             //Compute instant FPS
   241             toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " FPS";
   242 
   243             LastTickTime = NewTickTime;
   244 
   245         }
   246 
   247         private void buttonOpen_Click(object sender, EventArgs e)
   248         {
   249             if (iDisplay.Open())
   250             {
   251                 UpdateStatus();
   252                 iDisplay.RequestPowerSupplyStatus();
   253             }
   254             else
   255             {
   256                 UpdateStatus();
   257                 toolStripStatusLabelConnect.Text = "Connection error";
   258             }
   259 
   260         }
   261 
   262         private void buttonClose_Click(object sender, EventArgs e)
   263         {
   264             iDisplay.Close();
   265             UpdateStatus();
   266         }
   267 
   268         private void buttonClear_Click(object sender, EventArgs e)
   269         {
   270             iDisplay.Clear();
   271             iDisplay.SwapBuffers();
   272         }
   273 
   274         private void buttonFill_Click(object sender, EventArgs e)
   275         {
   276             iDisplay.Fill();
   277             iDisplay.SwapBuffers();
   278         }
   279 
   280         private void trackBarBrightness_Scroll(object sender, EventArgs e)
   281         {
   282             Properties.Settings.Default.DisplayBrightness = trackBarBrightness.Value;
   283             Properties.Settings.Default.Save();
   284             iDisplay.SetBrightness(trackBarBrightness.Value);
   285 
   286         }
   287 
   288         private void UpdateStatus()
   289         {
   290             if (iDisplay.IsOpen())
   291             {
   292                 buttonFill.Enabled = true;
   293                 buttonClear.Enabled = true;
   294                 buttonOpen.Enabled = false;
   295                 buttonClose.Enabled = true;
   296                 trackBarBrightness.Enabled = true;
   297                 trackBarBrightness.Minimum = iDisplay.MinBrightness();
   298                 trackBarBrightness.Maximum = iDisplay.MaxBrightness();
   299                 trackBarBrightness.Value = Properties.Settings.Default.DisplayBrightness;
   300                 trackBarBrightness.LargeChange = Math.Max(1,(iDisplay.MaxBrightness() - iDisplay.MinBrightness())/5);
   301                 trackBarBrightness.SmallChange = 1;
   302                 iDisplay.SetBrightness(Properties.Settings.Default.DisplayBrightness);
   303 
   304                 toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
   305                 //+ " - " + iDisplay.SerialNumber();
   306             }
   307             else
   308             {
   309                 buttonFill.Enabled = false;
   310                 buttonClear.Enabled = false;
   311                 buttonOpen.Enabled = true;
   312                 buttonClose.Enabled = false;
   313                 trackBarBrightness.Enabled = false;
   314                 toolStripStatusLabelConnect.Text = "Disconnected";
   315             }
   316         }
   317 
   318 
   319 
   320         private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
   321         {
   322             //Save our show borders setting
   323             tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
   324             Properties.Settings.Default.DisplayShowBorders = checkBoxShowBorders.Checked;
   325             Properties.Settings.Default.Save();
   326         }
   327 
   328         private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
   329         {
   330             //Save our connect on startup setting
   331             Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
   332             Properties.Settings.Default.Save();
   333         }
   334 
   335         private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
   336         {
   337             //Save our reverse screen setting
   338             Properties.Settings.Default.DisplayReverseScreen = checkBoxReverseScreen.Checked;
   339             Properties.Settings.Default.Save();
   340         }
   341 
   342         private void MainForm_Resize(object sender, EventArgs e)
   343         {
   344             if (WindowState == FormWindowState.Minimized)
   345             {
   346                 // Do some stuff
   347                 //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
   348                 iCreateBitmap = true;
   349             }
   350         }
   351 
   352         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
   353         {
   354             StopServer();
   355         }
   356 
   357         public void StartServer()
   358         {
   359             iServiceHost = new ServiceHost
   360                 (
   361                     typeof(DisplayServer),
   362                     new Uri[] { new Uri("net.tcp://localhost:8001/") }
   363                 );
   364 
   365             iServiceHost.AddServiceEndpoint(typeof(IDisplayService), new NetTcpBinding(), "DisplayService");
   366             iServiceHost.Open();
   367         }
   368 
   369         public void StopServer()
   370         {
   371             //Tell connected client first? Is that possible?
   372             BroadcastCloseEvent();
   373             iServiceHost.Close();
   374         }
   375 
   376         public void BroadcastCloseEvent()
   377         {
   378             var inactiveClients = new List<string>();
   379             foreach (var client in iClients)
   380             {
   381                 //if (client.Key != eventData.ClientName)
   382                 {
   383                     try
   384                     {
   385                         client.Value.OnServerClosing(/*eventData*/);
   386                     }
   387                     catch (Exception ex)
   388                     {
   389                         inactiveClients.Add(client.Key);
   390                     }
   391                 }
   392             }
   393 
   394             if (inactiveClients.Count > 0)
   395             {
   396                 foreach (var client in inactiveClients)
   397                 {
   398                     iClients.Remove(client);
   399                 }
   400             }
   401         }
   402 
   403         private void buttonStartClient_Click(object sender, EventArgs e)
   404         {
   405             Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
   406             clientThread.Start();
   407         }
   408 
   409 
   410 
   411     }
   412 }