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