Adding server closing notification to clients.
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;
16 namespace SharpDisplayManager
18 public partial class MainForm : Form
20 DateTime LastTickTime;
22 System.Drawing.Bitmap iBmp;
23 bool iCreateBitmap; //Workaround render to bitmap issues when minimized
24 ServiceHost iServiceHost;
26 /// Our collection of clients
28 public Dictionary<string, IDisplayServiceCallback> iClients;
32 LastTickTime = DateTime.Now;
33 iDisplay = new Display();
34 iClients = new Dictionary<string, IDisplayServiceCallback>();
36 InitializeComponent();
40 marqueeLabelTop.Font = Properties.Settings.Default.DisplayFont;
41 marqueeLabelBottom.Font = Properties.Settings.Default.DisplayFont;
42 checkBoxShowBorders.Checked = Properties.Settings.Default.DisplayShowBorders;
43 checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
44 checkBoxReverseScreen.Checked = Properties.Settings.Default.DisplayReverseScreen;
46 tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
47 //We have a bug when drawing minimized and reusing our bitmap
48 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
49 iCreateBitmap = false;
52 private void MainForm_Load(object sender, EventArgs e)
56 if (Properties.Settings.Default.DisplayConnectOnStartup)
64 private void buttonFont_Click(object sender, EventArgs e)
66 //fontDialog.ShowColor = true;
67 //fontDialog.ShowApply = true;
68 fontDialog.ShowEffects = true;
69 fontDialog.Font = marqueeLabelTop.Font;
70 //fontDialog.ShowHelp = true;
72 //fontDlg.MaxSize = 40;
73 //fontDlg.MinSize = 22;
75 //fontDialog.Parent = this;
76 //fontDialog.StartPosition = FormStartPosition.CenterParent;
78 //DlgBox.ShowDialog(fontDialog);
80 //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
81 if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
84 //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
86 //MessageBox.Show("Ok");
87 marqueeLabelTop.Font = fontDialog.Font;
88 marqueeLabelBottom.Font = fontDialog.Font;
89 Properties.Settings.Default.DisplayFont = fontDialog.Font;
90 Properties.Settings.Default.Save();
91 //label1.Font = fontDlg.Font;
92 //textBox1.BackColor = fontDlg.Color;
93 //label1.ForeColor = fontDlg.Color;
97 private void buttonCapture_Click(object sender, EventArgs e)
99 System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
100 tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
101 //Bitmap bmpToSave = new Bitmap(bmp);
102 bmp.Save("D:\\capture.png");
104 marqueeLabelTop.Text = "Sweet";
107 string outputFileName = "d:\\capture.png";
108 using (MemoryStream memory = new MemoryStream())
110 using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
112 bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
113 byte[] bytes = memory.ToArray();
114 fs.Write(bytes, 0, bytes.Length);
121 private void CheckForRequestResults()
123 if (iDisplay.IsRequestPending())
125 switch (iDisplay.AttemptRequestCompletion())
127 case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
128 if (iDisplay.PowerSupplyStatus())
130 toolStripStatusLabelPower.Text = "ON";
134 toolStripStatusLabelPower.Text = "OFF";
136 //Issue next request then
137 iDisplay.RequestDeviceId();
140 case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
141 toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
142 //Issue next request then
143 iDisplay.RequestFirmwareRevision();
146 case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
147 toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
148 //No more request to issue
155 public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
158 public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
160 return aBmp.Width - aX - 1;
163 public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
165 return iBmp.Height - aY - 1;
168 public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
173 public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
179 //This is our timer tick responsible to perform our render
180 private void timer_Tick(object sender, EventArgs e)
182 //Update our animations
183 DateTime NewTickTime = DateTime.Now;
185 marqueeLabelTop.UpdateAnimation(LastTickTime, NewTickTime);
186 marqueeLabelBottom.UpdateAnimation(LastTickTime, NewTickTime);
189 if (iDisplay.IsOpen())
191 CheckForRequestResults();
196 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
198 tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
199 //iBmp.Save("D:\\capture.png");
201 //Select proper coordinate translation functions
202 //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
203 CoordinateTranslationDelegate screenX;
204 CoordinateTranslationDelegate screenY;
206 if (Properties.Settings.Default.DisplayReverseScreen)
208 screenX = ScreenReversedX;
209 screenY = ScreenReversedY;
217 //Send it to our display
218 for (int i = 0; i < iBmp.Width; i++)
220 for (int j = 0; j < iBmp.Height; j++)
224 uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
225 //For some reason when the app is minimized in the task bar only the alpha of our color is set.
226 //Thus that strange test for rendering to work both when the app is in the task bar and when it isn't.
227 iDisplay.SetPixel(screenX(iBmp, i), screenY(iBmp, j), Convert.ToInt32(!(color != 0xFF000000)));
232 iDisplay.SwapBuffers();
236 //Compute instant FPS
237 toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " FPS";
239 LastTickTime = NewTickTime;
243 private void buttonOpen_Click(object sender, EventArgs e)
248 iDisplay.RequestPowerSupplyStatus();
253 toolStripStatusLabelConnect.Text = "Connection error";
258 private void buttonClose_Click(object sender, EventArgs e)
264 private void buttonClear_Click(object sender, EventArgs e)
267 iDisplay.SwapBuffers();
270 private void buttonFill_Click(object sender, EventArgs e)
273 iDisplay.SwapBuffers();
276 private void trackBarBrightness_Scroll(object sender, EventArgs e)
278 Properties.Settings.Default.DisplayBrightness = trackBarBrightness.Value;
279 Properties.Settings.Default.Save();
280 iDisplay.SetBrightness(trackBarBrightness.Value);
284 private void UpdateStatus()
286 if (iDisplay.IsOpen())
288 buttonFill.Enabled = true;
289 buttonClear.Enabled = true;
290 buttonOpen.Enabled = false;
291 buttonClose.Enabled = true;
292 trackBarBrightness.Enabled = true;
293 trackBarBrightness.Minimum = iDisplay.MinBrightness();
294 trackBarBrightness.Maximum = iDisplay.MaxBrightness();
295 trackBarBrightness.Value = Properties.Settings.Default.DisplayBrightness;
296 trackBarBrightness.LargeChange = Math.Max(1,(iDisplay.MaxBrightness() - iDisplay.MinBrightness())/5);
297 trackBarBrightness.SmallChange = 1;
298 iDisplay.SetBrightness(Properties.Settings.Default.DisplayBrightness);
300 toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
301 //+ " - " + iDisplay.SerialNumber();
305 buttonFill.Enabled = false;
306 buttonClear.Enabled = false;
307 buttonOpen.Enabled = true;
308 buttonClose.Enabled = false;
309 trackBarBrightness.Enabled = false;
310 toolStripStatusLabelConnect.Text = "Disconnected";
316 private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
318 //Save our show borders setting
319 tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
320 Properties.Settings.Default.DisplayShowBorders = checkBoxShowBorders.Checked;
321 Properties.Settings.Default.Save();
324 private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
326 //Save our connect on startup setting
327 Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
328 Properties.Settings.Default.Save();
331 private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
333 //Save our reverse screen setting
334 Properties.Settings.Default.DisplayReverseScreen = checkBoxReverseScreen.Checked;
335 Properties.Settings.Default.Save();
338 private void MainForm_Resize(object sender, EventArgs e)
340 if (WindowState == FormWindowState.Minimized)
343 //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
344 iCreateBitmap = true;
348 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
353 public void StartServer()
355 iServiceHost = new ServiceHost
357 typeof(DisplayServer),
358 new Uri[] { new Uri("net.tcp://localhost:8001/") }
361 iServiceHost.AddServiceEndpoint(typeof(IDisplayService), new NetTcpBinding(), "DisplayService");
365 public void StopServer()
367 //Tell connected client first? Is that possible?
368 BroadcastCloseEvent();
369 iServiceHost.Close();
372 public void BroadcastCloseEvent()
374 var inactiveClients = new List<string>();
375 foreach (var client in iClients)
377 //if (client.Key != eventData.ClientName)
381 client.Value.OnServerClosing(/*eventData*/);
385 inactiveClients.Add(client.Key);
390 if (inactiveClients.Count > 0)
392 foreach (var client in inactiveClients)
394 iClients.Remove(client);