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