/ src / modules / MouseWithoutBorders / App / Form / frmMatrix.cs
frmMatrix.cs
   1  // Copyright (c) Microsoft Corporation
   2  // The Microsoft Corporation licenses this file to you under the MIT license.
   3  // See the LICENSE file in the project root for more information.
   4  
   5  using System;
   6  using System.Diagnostics;
   7  using System.Diagnostics.CodeAnalysis;
   8  using System.Drawing;
   9  using System.Globalization;
  10  using System.Text.RegularExpressions;
  11  using System.Windows.Forms;
  12  
  13  using Microsoft.PowerToys.Telemetry;
  14  
  15  // <summary>
  16  //     Matrix/Settings form.
  17  // </summary>
  18  // <history>
  19  //     2008 created by Truong Do (ductdo).
  20  //     2009-... modified by Truong Do (TruongDo).
  21  //     2023- Included in PowerToys.
  22  // </history>
  23  using MouseWithoutBorders.Class;
  24  using MouseWithoutBorders.Core;
  25  
  26  using Clipboard = MouseWithoutBorders.Core.Clipboard;
  27  using Timer = System.Windows.Forms.Timer;
  28  
  29  [module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#buttonOK_Click(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
  30  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#buttonSendHello_Click(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
  31  [module: SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#frmMatrix_Load(System.Object,System.EventArgs)", MessageId = "System.String.ToLower", Justification = "Dotnet port with style preservation")]
  32  
  33  // [module: SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#ChangeUI2OneRow(System.Boolean)")]
  34  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#logoTimer_Tick(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
  35  [module: SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#Dispose(System.Boolean)", MessageId = "logoBitmap", Justification = "Dotnet port with style preservation")]
  36  [module: SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#frmMatrix_Shown(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
  37  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#PaintMyLogo()", Justification = "Dotnet port with style preservation")]
  38  [module: SuppressMessage("Style", "IDE1006:Naming Styles", Scope = "member", Target = "~M:MouseWithoutBorders.FrmMatrix.M_EnabledChanged(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
  39  
  40  namespace MouseWithoutBorders
  41  {
  42      internal partial class FrmMatrix : System.Windows.Forms.Form, IDisposable
  43      {
  44  #pragma warning disable CA2213 // Disposing is done by ComponentResourceManager
  45          private Timer helperTimer;
  46  #pragma warning restore CA2213
  47          private bool formShown;
  48          private int formOrgHeight;
  49          private bool matrixOneRow;
  50  
  51          internal FrmMatrix()
  52          {
  53              InitializeComponent();
  54  
  55              textBoxEnc.Font = new System.Drawing.Font(Control.DefaultFont.Name, 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0);
  56  
  57              Text = Application.ProductName + " " + Application.ProductVersion + " - Settings";
  58              toolTip.ToolTipTitle = Application.ProductName;
  59              toolTipManual.ToolTipTitle = Application.ProductName;
  60              labelExitMM.Text = "Exit the application, Ctrl+Alt+Shift+:";
  61              textBoxMachineName2IP.Text = Setting.Values.Name2IP;
  62          }
  63  
  64          private void ButtonCancel_Click(object sender, EventArgs e)
  65          {
  66              buttonCancel.Enabled = false;
  67              Close();
  68              Common.MatrixForm = null;
  69          }
  70  
  71          private void ButtonOK_Click(object sender, EventArgs e)
  72          {
  73              buttonOK.Enabled = false;
  74  
  75              if (!UpdateKey(Regex.Replace(textBoxEnc.Text, @"\s+", string.Empty)))
  76              {
  77                  buttonOK.Enabled = true;
  78                  return;
  79              }
  80  
  81              string[] st = new string[MachineStuff.MAX_MACHINE];
  82              for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
  83              {
  84                  if (machines[i].MachineEnabled)
  85                  {
  86                      for (int j = 0; j < i; j++)
  87                      {
  88                          if (st[j].Equals(machines[i].MachineName, StringComparison.OrdinalIgnoreCase))
  89                          {
  90                              machines[i].MachineName = string.Empty;
  91                              machines[i].MachineEnabled = false;
  92                          }
  93                      }
  94  
  95                      st[i] = machines[i].MachineName;
  96                  }
  97                  else
  98                  {
  99                      st[i] = string.Empty;
 100                  }
 101              }
 102  
 103              MachineStuff.MachineMatrix = st;
 104              Setting.Values.MatrixOneRow = matrixOneRow = !checkBoxTwoRow.Checked;
 105  
 106              if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
 107              {
 108                  Program.StartService();
 109                  Common.ShowToolTip("New settings applied on the physical console session!", 3000, ToolTipIcon.Warning, false);
 110              }
 111              else
 112              {
 113                  SocketStuff.InvalidKeyFound = false;
 114                  showInvalidKeyMessage = false;
 115                  InitAndCleanup.ReopenSocketDueToReadError = true;
 116                  Common.ReopenSockets(true);
 117  
 118                  for (int i = 0; i < 10; i++)
 119                  {
 120                      if (Common.AtLeastOneSocketConnected())
 121                      {
 122                          Common.MMSleep(0.5);
 123                          break;
 124                      }
 125  
 126                      Common.MMSleep(0.2);
 127                  }
 128  
 129                  MachineStuff.SendMachineMatrix();
 130              }
 131  
 132              buttonOK.Enabled = true;
 133          }
 134  
 135          internal void UpdateKeyTextBox()
 136          {
 137              _ = Helper.GetUserName();
 138              textBoxEnc.Text = Encryption.MyKey;
 139          }
 140  
 141          private void InitAll()
 142          {
 143              formOrgHeight = Height;
 144              matrixOneRow = Setting.Values.MatrixOneRow;
 145              CreateMachines();
 146              LoadSettingsToUI();
 147              UpdateKeyTextBox();
 148          }
 149  
 150          private void LoadMachines()
 151          {
 152              bool meAdded = false;
 153              string machineName;
 154  
 155              if (MachineStuff.MachineMatrix != null && MachineStuff.MachineMatrix.Length == MachineStuff.MAX_MACHINE)
 156              {
 157                  Logger.LogDebug("LoadMachines: Machine Matrix: " + Setting.Values.MachineMatrixString);
 158  
 159                  for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
 160                  {
 161                      machineName = MachineStuff.MachineMatrix[i].Trim();
 162                      machines[i].MachineName = machineName;
 163  
 164                      if (string.IsNullOrEmpty(machineName))
 165                      {
 166                          machines[i].CheckAble = true;
 167                      }
 168                      else
 169                      {
 170                          machines[i].MachineEnabled = true;
 171                      }
 172  
 173                      bool found = MachineStuff.MachinePool.TryFindMachineByName(machineName, out MachineInf machineInfo);
 174                      if (found)
 175                      {
 176                          if (machineInfo.Id == Common.MachineID)
 177                          {
 178                              machines[i].LocalHost = true;
 179                              meAdded = true;
 180                          }
 181                      }
 182                  }
 183              }
 184  
 185              if (!meAdded)
 186              {
 187                  foreach (Machine m in machines)
 188                  {
 189                      if (string.IsNullOrEmpty(m.MachineName))
 190                      {
 191                          m.MachineName = Common.MachineName.Trim();
 192                          m.LocalHost = true;
 193                          meAdded = true;
 194                          break;
 195                      }
 196                  }
 197              }
 198          }
 199  
 200          private void CheckBoxShowKey_CheckedChanged(object sender, EventArgs e)
 201          {
 202              textBoxEnc.PasswordChar = checkBoxShowKey.Checked ? (char)0 : '*';
 203          }
 204  
 205          private void FrmMatrix_Shown(object sender, EventArgs e)
 206          {
 207              if (Setting.Values.FirstRun)
 208              {
 209                  Setting.Values.FirstRun = false;
 210                  Common.ReopenSockets(false);
 211  
 212                  /*
 213                  string fireWallLog = Path.GetDirectoryName(Application.ExecutablePath) + "\\FirewallError.log";
 214  
 215                  if (File.Exists(fireWallLog))
 216                  {
 217                      //@"http://bing.com/search?q=Allow+a+program+through+Windows+Firewall"
 218  
 219                      MessageBox.Show(Application.ProductName + " was unable to add itself to the Firewall exception list.\r\n" +
 220                          "The following application needs to be added to the Firewall exception list:\r\n\r\n" +
 221                          Application.ExecutablePath +
 222                          "\r\n\r\nYou can go to bing.com and do a search on" + "\r\n'Allow a program through Windows Firewall' to know how.",
 223                          Application.ProductName,
 224                          MessageBoxButtons.OK, MessageBoxIcon.Error);
 225                  }
 226  
 227                  linkLabelHelp_LinkClicked(null, null);
 228                   * */
 229              }
 230  
 231              InitAll();
 232  
 233              if (Setting.Values.IsMyKeyRandom)
 234              {
 235                  Setting.Values.IsMyKeyRandom = false;
 236                  checkBoxShowKey.Checked = true;
 237              }
 238  
 239              if (helperTimer == null)
 240              {
 241                  helperTimer = new Timer();
 242                  helperTimer.Interval = 200;
 243                  helperTimer.Tick += new EventHandler(HelperTimer_Tick);
 244                  helperTimer.Start();
 245              }
 246  
 247              formShown = true;
 248          }
 249  
 250          private void FrmMatrix_FormClosed(object sender, FormClosedEventArgs e)
 251          {
 252              /*
 253              if (logoTimer != null)
 254              {
 255                  logoTimer.Stop();
 256                  logoTimer.Dispose();
 257                  logoTimer = null;
 258              }
 259               * */
 260  
 261              if (helperTimer != null)
 262              {
 263                  helperTimer.Stop();
 264                  helperTimer.Dispose();
 265                  helperTimer = null;
 266              }
 267  
 268              // if (logoBitmap != null) logoBitmap.Dispose();
 269              Common.MatrixForm = null;
 270          }
 271  
 272          private int pivot;
 273          private Bitmap logoBitmap;
 274  
 275          private void PaintMyLogo()
 276          {
 277              if (!Visible || !(tabControlSetting.SelectedTab == tabPageAdvancedSettings))
 278              {
 279                  return;
 280              }
 281  
 282              uint rv = 0;
 283              try
 284              {
 285                  Color c;
 286                  uint cl;
 287                  double dC;
 288                  logoBitmap ??= new Bitmap(pictureBoxMouseWithoutBorders0.BackgroundImage);
 289                  int bWidth = logoBitmap.Width;
 290                  int bHeight = logoBitmap.Height;
 291                  double dx = (double)pictureBoxMouseWithoutBorders.Width / bWidth;
 292                  double dy = (double)pictureBoxMouseWithoutBorders.Height / bHeight;
 293  
 294                  IntPtr hdc = NativeMethods.GetWindowDC(pictureBoxMouseWithoutBorders.Handle);
 295                  for (int i = 0; i < bWidth; i++)
 296                  {
 297                      for (int j = 0; j < bHeight; j++)
 298                      {
 299                          c = logoBitmap.GetPixel(i, j);
 300  
 301                          // c.G > 245
 302                          if (c.R < 240 && c.B < 240)
 303                          {
 304                              dC = Math.Abs(pivot - i);
 305                              if (bWidth - pivot + i < dC)
 306                              {
 307                                  dC = bWidth - pivot + i;
 308                              }
 309  
 310                              if (bWidth - i + pivot < dC)
 311                              {
 312                                  dC = bWidth - i + pivot;
 313                              }
 314  
 315                              dC /= bWidth;
 316  
 317                              // c = Color.FromArgb(80, (int)(255 - 255 * dC), 80);
 318                              cl = (160 << 16) | ((uint)(255 - (255 * dC)) << 8) | 160;
 319  
 320                              // Using GDI SetPixel so we dont have to assign the image later on
 321                              // b.SetPixel(i, j, c);
 322                              rv = NativeMethods.SetPixel(hdc, (int)(i * dx), (int)(j * dy), cl);
 323                          }
 324                      }
 325                  }
 326  
 327                  // Image im = pictureBoxMouseWithoutBorders.BackgroundImage;
 328                  // pictureBoxMouseWithoutBorders.BackgroundImage = b;
 329                  // if (im != null) im.Dispose();
 330                  rv = (uint)NativeMethods.ReleaseDC(pictureBoxMouseWithoutBorders.Handle, hdc);
 331                  pivot = (pivot + 5) % bWidth;
 332              }
 333              catch (Exception ee)
 334              {
 335                  Logger.Log(ee);
 336                  Logger.Log(rv.ToString(CultureInfo.CurrentCulture));
 337              }
 338          }
 339  
 340          private void AddNewMachine()
 341          {
 342              string newMachine;
 343              Machine unUsedMachine;
 344  
 345              foreach (MachineInf inf in MachineStuff.MachinePool.ListAllMachines())
 346              {
 347                  bool found = false;
 348                  unUsedMachine = null;
 349                  newMachine = inf.Name.Trim();
 350                  foreach (Machine m in machines)
 351                  {
 352                      if (m.MachineName.Equals(
 353                          newMachine,
 354                          StringComparison.OrdinalIgnoreCase))
 355                      {
 356                          found = true;
 357                      }
 358                      else if (unUsedMachine == null && string.IsNullOrEmpty(m.MachineName.Trim()))
 359                      {
 360                          unUsedMachine = m;
 361                      }
 362                  }
 363  
 364                  if (!found && unUsedMachine != null)
 365                  {
 366                      unUsedMachine.MachineName = newMachine;
 367                  }
 368              }
 369          }
 370  
 371          private int helperTimerCounter;
 372          private bool showInvalidKeyMessage;
 373  
 374          private void HelperTimer_Tick(object sender, EventArgs e)
 375          {
 376              string keyNotMatchedMachines = string.Empty;
 377  
 378              if (Setting.Values.Changed)
 379              {
 380                  Setting.Values.Changed = false;
 381                  matrixOneRow = Setting.Values.MatrixOneRow;
 382                  LoadSettingsToUI();
 383  
 384                  /*
 385                  if (!Common.InMachineMatrix(Common.MachineName))
 386                  {
 387                      foreach (Machine m in machines)
 388                      {
 389                          if (!m.LocalHost)
 390                          {
 391                              m.MachineEnabled = false;
 392                          }
 393                      }
 394                  }
 395                   * */
 396              }
 397  
 398              helperTimerCounter++;
 399  
 400              // 1 sec
 401              if (helperTimerCounter % 5 == 0)
 402              {
 403                  comboBoxEasyMouseOption.Text = ((EasyMouseOption)Setting.Values.EasyMouse).ToString();
 404  
 405                  if (!textBoxMachineName2IP.Text.Equals(Setting.Values.Name2IP, StringComparison.OrdinalIgnoreCase))
 406                  {
 407                      Setting.Values.Name2IP = textBoxMachineName2IP.Text;
 408                  }
 409  
 410                  // 2 times
 411                  if (helperTimerCounter < 15)
 412                  {
 413                      Common.SendHello();
 414                  }
 415  
 416                  AddNewMachine();
 417              }
 418  
 419              // NOTE(@yuyoyuppe): this option is deprecated
 420              // checkBoxVKMap.Checked = Setting.Values.UseVKMap;
 421              foreach (Machine m in machines)
 422              {
 423                  if (m.StatusClient != SocketStatus.NA)
 424                  {
 425                      m.StatusClient = SocketStatus.NA;
 426                  }
 427  
 428                  if (m.StatusServer != SocketStatus.NA)
 429                  {
 430                      m.StatusServer = SocketStatus.NA;
 431                  }
 432              }
 433  
 434              SocketStuff sk = Common.Sk;
 435  
 436              if (sk != null)
 437              {
 438                  lock (sk.TcpSocketsLock)
 439                  {
 440                      if (sk.TcpSockets != null)
 441                      {
 442                          foreach (TcpSk t in sk.TcpSockets)
 443                          {
 444                              if (t.Status == SocketStatus.InvalidKey)
 445                              {
 446                                  keyNotMatchedMachines += string.Format(CultureInfo.CurrentCulture, "[{0}]", t.MachineName);
 447                              }
 448  
 449                              foreach (Machine m in machines)
 450                              {
 451                                  if (m.MachineEnabled)
 452                                  {
 453                                      if (m.MachineName.Equals(t.MachineName, StringComparison.OrdinalIgnoreCase))
 454                                      {
 455                                          if (t.IsClient)
 456                                          {
 457                                              if (t.Status > m.StatusClient)
 458                                              {
 459                                                  m.StatusClient = t.Status;
 460                                              }
 461                                          }
 462                                          else
 463                                          {
 464                                              if (t.Status > m.StatusServer)
 465                                              {
 466                                                  m.StatusServer = t.Status;
 467                                              }
 468                                          }
 469                                      }
 470                                  }
 471                              }
 472                          }
 473                      }
 474                  }
 475              }
 476  
 477              if (SocketStuff.InvalidKeyFound)
 478              {
 479                  if (!showInvalidKeyMessage)
 480                  {
 481                      showInvalidKeyMessage = true;
 482  
 483                      Common.ShowToolTip(
 484                          "Security Keys not matched.\r\nVerify that you entered the same key in all machines.\r\nAnd make sure you run the same version of "
 485                          + Application.ProductName + " in all machines.\r\n" + keyNotMatchedMachines + "\r\nThis version: " + FrmAbout.AssemblyVersion,
 486                          20000,
 487                          ToolTipIcon.Warning,
 488                          Setting.Values.ShowClipNetStatus);
 489                  }
 490              }
 491              else
 492              {
 493                  showInvalidKeyMessage = false;
 494              }
 495  
 496              PaintMyLogo();
 497          }
 498  
 499          private void ShowKeyErrorMsg(string msg)
 500          {
 501              Common.ShowToolTip(msg, 10000, ToolTipIcon.Error, false);
 502              _ = textBoxEnc.Focus();
 503              textBoxEnc.SelectAll();
 504          }
 505  
 506          private bool UpdateKey(string newKey)
 507          {
 508              if (!Encryption.IsKeyValid(newKey, out string rv))
 509              {
 510                  ShowKeyErrorMsg(rv);
 511                  return false;
 512              }
 513  
 514              if (!newKey.Equals(Encryption.MyKey, StringComparison.OrdinalIgnoreCase))
 515              {
 516                  Encryption.MyKey = newKey;
 517                  Encryption.GeneratedKey = false;
 518              }
 519  
 520              Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey);
 521              return true;
 522          }
 523  
 524          private readonly Machine[] machines = new Machine[MachineStuff.MAX_MACHINE];
 525          private Machine dragDropMachine;
 526          private Machine desMachine;
 527          private Machine desMachineX;
 528          private Machine desMachineY;
 529          private Machine oldDesMachine;
 530          private Point desMachinePos;
 531          private Point oldDesMachinePos;
 532  
 533          private void CreateMachines()
 534          {
 535              for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
 536              {
 537                  Machine m = new();
 538                  m.MouseDown += Machine_MouseDown;
 539                  m.EnabledChanged += new EventHandler(M_EnabledChanged);
 540                  m.Parent = groupBoxMachineMatrix;
 541                  m.MachineEnabled = false;
 542                  machines[i] = m;
 543              }
 544  
 545              FrmMatrix_Resize(this, EventArgs.Empty);
 546              ArrangeMachines();
 547          }
 548  
 549          private void ArrangeMachines()
 550          {
 551              Height = matrixOneRow ? formOrgHeight : formOrgHeight + 60;
 552              int dx = (groupBoxMachineMatrix.Width - 40) / 4;
 553              int yOffset = groupBoxMachineMatrix.Height / 3;
 554  
 555              for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
 556              {
 557                  machines[i].Left = matrixOneRow ? 22 + (i * dx) : 22 + dx + ((i % 2) * dx);
 558                  machines[i].Top = matrixOneRow ? yOffset : (yOffset / 2) + (i / 2 * (machines[i].Width + 2));
 559                  machines[i].Visible = true;
 560              }
 561          }
 562  
 563          private void M_EnabledChanged(object sender, EventArgs e)
 564          {
 565              Machine m = sender as Machine;
 566  
 567              SocketStuff sk = Common.Sk;
 568  
 569              if (!m.MachineEnabled && sk != null)
 570              {
 571                  lock (sk.TcpSocketsLock)
 572                  {
 573                      if (sk.TcpSockets != null)
 574                      {
 575                          foreach (TcpSk t in sk.TcpSockets)
 576                          {
 577                              if (t.MachineName != null && t.MachineName.Equals(m.MachineName.Trim(), StringComparison.OrdinalIgnoreCase))
 578                              {
 579                                  t.Status = SocketStatus.NA;
 580                              }
 581                          }
 582                      }
 583                  }
 584              }
 585          }
 586  
 587          private void Machine_MouseDown(object sender, MouseEventArgs e)
 588          {
 589              oldDesMachine = desMachine = dragDropMachine = sender as Machine;
 590              desMachinePos.X = desMachine.Left;
 591              desMachinePos.Y = desMachine.Top;
 592              oldDesMachinePos.X = oldDesMachine.Left;
 593              oldDesMachinePos.Y = oldDesMachine.Top;
 594  
 595              dragDropMachineOrgX = dragDropMachine.Left;
 596              dragDropMachineOrgY = dragDropMachine.Top;
 597              dragDropMachine.BringToFront();
 598              _ = DoDragDrop(dragDropMachine, DragDropEffects.Move);
 599          }
 600  
 601          private int startX;
 602          private int startY;
 603          private int dragDropMachineOrgX;
 604          private int dragDropMachineOrgY;
 605  
 606          private void Form_DragEnter(object sender, DragEventArgs e)
 607          {
 608              startX = e.X;
 609              startY = e.Y;
 610              e.Effect = DragDropEffects.Move;
 611          }
 612  
 613          private bool IsOnSameRow(Machine m1, Machine m2)
 614          {
 615              return matrixOneRow || (m1 == dragDropMachine ? desMachinePos.Y : m1.Top) == m2.Top;
 616          }
 617  
 618          private bool IsOnSameCol(Machine m1, Machine m2)
 619          {
 620              return !matrixOneRow && (m1 == dragDropMachine ? desMachinePos.X : m1.Left) == m2.Left;
 621          }
 622  
 623          private long lastMove;
 624  
 625          private void Form_DragOver(object sender, DragEventArgs e)
 626          {
 627              if (dragDropMachine == null)
 628              {
 629                  return;
 630              }
 631  
 632              e.Effect = DragDropEffects.Move;
 633  
 634              dragDropMachine.Left = dragDropMachineOrgX + (e.X - startX);
 635              dragDropMachine.Top = dragDropMachineOrgY + (e.Y - startY);
 636  
 637              /*
 638              dragDropMachine.Left = e.X - dragDropMachine.MouseDownPos.X - Left - 3
 639                  - groupBoxMachineMatrix.Left - tabControlSetting.Left;
 640              dragDropMachine.Top = e.Y - dragDropMachine.MouseDownPos.Y - Top - 25
 641                  - groupBoxMachineMatrix.Top - tabControlSetting.Top;
 642               * */
 643  
 644              if (!matrixOneRow && Common.GetTick() - lastMove < 500)
 645              {
 646                  return;
 647              }
 648  
 649              int minX = Math.Abs(dragDropMachine.Left - desMachinePos.X);
 650              int minY = Math.Abs(dragDropMachine.Top - desMachinePos.Y);
 651  
 652              desMachineX = desMachineY = desMachine;
 653  
 654              for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
 655              {
 656                  if (machines[i] == dragDropMachine)
 657                  {
 658                      continue;
 659                  }
 660  
 661                  if (IsOnSameRow(oldDesMachine, machines[i]))
 662                  {
 663                      if (minX > Math.Abs(dragDropMachine.Left - machines[i].Left))
 664                      {
 665                          minX = Math.Abs(dragDropMachine.Left - machines[i].Left);
 666                          desMachineX = machines[i];
 667                      }
 668                  }
 669  
 670                  if (IsOnSameCol(oldDesMachine, machines[i]))
 671                  {
 672                      if (minY > Math.Abs(dragDropMachine.Top - machines[i].Top))
 673                      {
 674                          minY = Math.Abs(dragDropMachine.Top - machines[i].Top);
 675                          desMachineY = machines[i];
 676                      }
 677                  }
 678              }
 679  
 680              oldDesMachine = desMachine;
 681              desMachine = desMachineY == oldDesMachine ? desMachineX : desMachineX == oldDesMachine ? desMachineY : minX < minY ? desMachineX : desMachineY;
 682  
 683              if (desMachine != oldDesMachine)
 684              {
 685                  oldDesMachinePos.X = desMachinePos.X;
 686                  desMachinePos.X = desMachine.Left;
 687  
 688                  oldDesMachinePos.Y = desMachinePos.Y;
 689                  desMachinePos.Y = desMachine.Top;
 690  
 691                  desMachine.Left = oldDesMachinePos.X;
 692                  desMachine.Top = oldDesMachinePos.Y;
 693  
 694                  desMachine = dragDropMachine;
 695  
 696                  lastMove = Common.GetTick();
 697              }
 698          }
 699  
 700          private void Form_DragDrop(object sender, DragEventArgs e)
 701          {
 702              if (desMachine != null)
 703              {
 704                  dragDropMachine.Left = desMachinePos.X;
 705                  dragDropMachine.Top = desMachinePos.Y;
 706  
 707                  Machine tmp;
 708                  for (int i = 0; i < MachineStuff.MAX_MACHINE - 1; i++)
 709                  {
 710                      for (int j = 0; j < MachineStuff.MAX_MACHINE - 1 - i; j++)
 711                      {
 712                          if (machines[j + 1].Top < machines[j].Top || (machines[j + 1].Top == machines[j].Top && machines[j + 1].Left < machines[j].Left))
 713                          {
 714                              tmp = machines[j];
 715                              machines[j] = machines[j + 1];
 716                              machines[j + 1] = tmp;
 717                          }
 718                      }
 719                  }
 720              }
 721          }
 722  
 723          private void FrmMatrix_DragLeave(object sender, EventArgs e)
 724          {
 725              Form_DragDrop(sender, null);
 726              InputSimulation.MouseUp();
 727          }
 728  
 729          private void LoadSettingsToUI()
 730          {
 731              checkBoxCircle.Checked = Setting.Values.MatrixCircle;
 732              checkBoxTwoRow.Checked = !matrixOneRow;
 733              checkBoxBlockMouseAtCorners.Checked = Setting.Values.BlockMouseAtCorners;
 734              checkBoxDrawMouse.Checked = Setting.Values.DrawMouse;
 735              checkBoxReverseLookup.Checked = Setting.Values.ReverseLookup;
 736              checkBoxSameSubNet.Checked = Setting.Values.SameSubNetOnly;
 737  
 738              // NOTE(@yuyoyuppe): this option is deprecated
 739              // checkBoxVKMap.Checked = Setting.Values.UseVKMap;
 740              foreach (Machine m in machines)
 741              {
 742                  m.MachineName = string.Empty;
 743                  m.MachineEnabled = false;
 744                  m.LocalHost = false;
 745              }
 746  
 747              LoadMachines();
 748          }
 749  
 750          internal static readonly string[] Separator = new string[] { "\r\n" };
 751  
 752          internal void ShowTip(ToolTipIcon icon, string text, int duration)
 753          {
 754              int x = 0;
 755              text += "\r\n ";
 756              int y = (-text.Split(Separator, StringSplitOptions.None).Length * 15) - 30;
 757  
 758              toolTipManual.Hide(this);
 759  
 760              toolTipManual.ToolTipIcon = icon;
 761              toolTipManual.Show(text, this, x, y, duration);
 762          }
 763  
 764          private void LinkLabelHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
 765          {
 766              linkLabelHelp.Enabled = false;
 767              linkLabelHelp.Enabled = true;
 768          }
 769  
 770          private void CheckBoxShareClipboard_CheckedChanged(object sender, EventArgs e)
 771          {
 772              Setting.Values.ShareClipboard = checkBoxShareClipboard.Checked;
 773  
 774              checkBoxTransferFile.Enabled = checkBoxTransferFile.Checked = Setting.Values.ShareClipboard;
 775  
 776              ShowUpdateMessage();
 777          }
 778  
 779          private void CheckBoxTransferFile_CheckedChanged(object sender, EventArgs e)
 780          {
 781              Setting.Values.TransferFile = checkBoxTransferFile.Checked;
 782  
 783              ShowUpdateMessage();
 784  
 785              Clipboard.HasSwitchedMachineSinceLastCopy = true;
 786          }
 787  
 788          private void CheckBoxDisableCAD_CheckedChanged(object sender, EventArgs e)
 789          {
 790              if (!Common.RunWithNoAdminRight)
 791              {
 792                  Helper.ApplyCADSetting();
 793                  ShowUpdateMessage();
 794              }
 795          }
 796  
 797          private void FrmMatrix_Load(object sender, EventArgs e)
 798          {
 799              if (Common.RunWithNoAdminRight)
 800              {
 801                  checkBoxDisableCAD.Enabled = false;
 802                  checkBoxHideLogo.Enabled = false;
 803              }
 804  
 805              // Note(@htcfreek): Disable checkboxes of settings that we don't support in the PowerToys implementation
 806              checkBoxDisableCAD.Enabled = false;
 807              checkBoxDisableCAD.Text = checkBoxDisableCAD.Text + " [Unsupported!]";
 808              checkBoxHideLogo.Enabled = false;
 809              checkBoxHideLogo.Text = checkBoxHideLogo.Text + " [Unsupported!]";
 810              checkBoxSendLog.Enabled = false;
 811              checkBoxSendLog.Text = checkBoxSendLog.Text + " [Unsupported!]";
 812  
 813              checkBoxShareClipboard.Checked = Setting.Values.ShareClipboard;
 814  
 815              if (!Setting.Values.ShareClipboard)
 816              {
 817                  checkBoxTransferFile.Enabled = checkBoxTransferFile.Checked = false;
 818              }
 819              else
 820              {
 821                  checkBoxTransferFile.Checked = Setting.Values.TransferFile;
 822              }
 823  
 824              checkBoxDisableCAD.Checked = Setting.Values.DisableCAD;
 825              checkBoxHideLogo.Checked = Setting.Values.HideLogonLogo;
 826              checkBoxHideMouse.Checked = Setting.Values.HideMouse;
 827              checkBoxBlockScreenSaver.Checked = Setting.Values.BlockScreenSaver;
 828              checkBoxMouseMoveRelatively.Checked = Setting.Values.MoveMouseRelatively;
 829              checkBoxClipNetStatus.Checked = Setting.Values.ShowClipNetStatus;
 830              checkBoxSendLog.Checked = Setting.Values.SendErrorLogV2;
 831  
 832              if (Setting.Values.HotKeySwitchMachine == (int)VK.F1)
 833              {
 834                  radioButtonF1.Checked = true;
 835              }
 836              else if (Setting.Values.HotKeySwitchMachine == '1')
 837              {
 838                  radioButtonNum.Checked = true;
 839              }
 840              else
 841              {
 842                  radioButtonDisable.Checked = true;
 843              }
 844  
 845              comboBoxShowSettings.Text = "Disable";
 846  
 847              comboBoxExitMM.Text = Setting.Values.HotKeyExitMM == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyExitMM });
 848  #if OBSOLETE_SHORTCUTS
 849              comboBoxLockMachine.Text = Setting.Values.HotKeyLockMachine == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyLockMachine });
 850  
 851              comboBoxReconnect.Text = Setting.Values.HotKeyReconnect == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyReconnect });
 852  
 853              comboBoxSwitchToAllPC.Text = Setting.Values.HotKeySwitch2AllPC == 1
 854                  ? "Ctrl*3"
 855                  : Setting.Values.HotKeySwitch2AllPC == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeySwitch2AllPC });
 856  
 857              comboBoxEasyMouseOption.Text = ((EasyMouseOption)Setting.Values.EasyMouse).ToString();
 858  
 859              comboBoxEasyMouse.Text = Setting.Values.HotKeyToggleEasyMouse == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyToggleEasyMouse });
 860  #endif
 861  
 862              // Apply policy configuration on UI elements
 863              // Has to be the last action
 864              if (Setting.Values.ShareClipboardIsGpoConfigured)
 865              {
 866                  checkBoxShareClipboard.Enabled = false;
 867                  checkBoxShareClipboard.Text += " [Managed]";
 868  
 869                  // transfer file setting depends on clipboard sharing
 870                  checkBoxTransferFile.Enabled = false;
 871              }
 872  
 873              if (Setting.Values.TransferFileIsGpoConfigured)
 874              {
 875                  checkBoxTransferFile.Enabled = false;
 876                  checkBoxTransferFile.Text += " [Managed]";
 877              }
 878  
 879              if (Setting.Values.BlockScreenSaverIsGpoConfigured)
 880              {
 881                  checkBoxBlockScreenSaver.Enabled = false;
 882                  checkBoxBlockScreenSaver.Text += " [Managed]";
 883              }
 884  
 885              if (Setting.Values.SameSubNetOnlyIsGpoConfigured)
 886              {
 887                  checkBoxSameSubNet.Enabled = false;
 888                  checkBoxSameSubNet.Text += " [Managed]";
 889              }
 890  
 891              if (Setting.Values.ReverseLookupIsGpoConfigured)
 892              {
 893                  checkBoxReverseLookup.Enabled = false;
 894                  checkBoxReverseLookup.Text += " [Managed]";
 895              }
 896  
 897              if (Setting.Values.Name2IpIsGpoConfigured)
 898              {
 899                  textBoxMachineName2IP.Enabled = false;
 900                  groupBoxDNS.ForeColor = Color.DimGray;
 901                  groupBoxDNS.Text += " [Managed]";
 902              }
 903  
 904              if (Setting.Values.Name2IpPolicyListIsGpoConfigured)
 905              {
 906                  pictureBoxMouseWithoutBorders.Visible = false;
 907                  groupBoxName2IPPolicyList.Visible = true;
 908                  textBoxMachineName2IPPolicyList.Visible = true;
 909                  textBoxMachineName2IPPolicyList.Text = Setting.Values.Name2IpPolicyList;
 910              }
 911          }
 912  
 913          private void RadioButton_CheckedChanged(object sender, EventArgs e)
 914          {
 915              RadioButton r = sender as RadioButton;
 916  
 917              if (r.Checked)
 918              {
 919                  Setting.Values.HotKeySwitchMachine = sender.Equals(radioButtonF1) ? (int)VK.F1 : sender.Equals(radioButtonNum) ? '1' : 0;
 920  
 921                  ShowUpdateMessage();
 922              }
 923          }
 924  
 925          private void ComboBoxShowSettings_TextChanged(object sender, EventArgs e)
 926          {
 927              ShowUpdateMessage();
 928          }
 929  
 930          private void ComboBoxExitMM_TextChanged(object sender, EventArgs e)
 931          {
 932              ShowUpdateMessage();
 933          }
 934  
 935          private void ComboBoxLockMachine_TextChanged(object sender, EventArgs e)
 936          {
 937  #if OBSOLETE_SHORTCUTS
 938              if (comboBoxLockMachine.Text.Contains("Disable"))
 939              {
 940                  Setting.Values.HotKeyLockMachine = 0;
 941              }
 942              else if (comboBoxLockMachine.Text.Length > 0)
 943              {
 944                  Setting.Values.HotKeyLockMachine = comboBoxLockMachine.Text[0];
 945              }
 946  #endif
 947          }
 948  
 949          private void ComboBoxSwitchToAllPC_TextChanged(object sender, EventArgs e)
 950          {
 951  #if OBSOLETE_SHORTCUTS
 952              if (comboBoxSwitchToAllPC.Text.Contains("Disable"))
 953              {
 954                  Setting.Values.HotKeySwitch2AllPC = 0;
 955              }
 956              else if (comboBoxSwitchToAllPC.Text.Contains("Ctrl*3"))
 957              {
 958                  Setting.Values.HotKeySwitch2AllPC = 1;
 959              }
 960              else if (comboBoxSwitchToAllPC.Text.Length > 0)
 961              {
 962                  Setting.Values.HotKeySwitch2AllPC = comboBoxSwitchToAllPC.Text[0];
 963              }
 964  #endif
 965              ShowUpdateMessage();
 966          }
 967  
 968          private void CheckBoxHideLogo_CheckedChanged(object sender, EventArgs e)
 969          {
 970              ShowUpdateMessage();
 971          }
 972  
 973          private void ShowUpdateMessage()
 974          {
 975              if (!formShown)
 976              {
 977                  return;
 978              }
 979  
 980              foreach (Control c in tabPageOther.Controls)
 981              {
 982                  if (c != groupBoxShortcuts)
 983                  {
 984                      c.Enabled = false;
 985                  }
 986              }
 987  
 988              foreach (Control c in groupBoxShortcuts.Controls)
 989              {
 990                  if (c != pictureBoxMouseWithoutBorders)
 991                  {
 992                      c.Enabled = false;
 993                  }
 994              }
 995  
 996              for (int i = 0; i < 3; i++)
 997              {
 998                  Application.DoEvents();
 999                  Thread.Sleep(20);
1000              }
1001  
1002              foreach (Control c in tabPageOther.Controls)
1003              {
1004                  if (c != groupBoxShortcuts)
1005                  {
1006                      c.Enabled = true;
1007                  }
1008              }
1009  
1010              foreach (Control c in groupBoxShortcuts.Controls)
1011              {
1012                  if (c != pictureBoxMouseWithoutBorders && c != comboBoxExitMM && c != comboBoxShowSettings && c != comboBoxScreenCapture)
1013                  {
1014                      c.Enabled = true;
1015                  }
1016              }
1017          }
1018  
1019          private void CheckBoxBlockScreenSaver_CheckedChanged(object sender, EventArgs e)
1020          {
1021              Setting.Values.BlockScreenSaver = checkBoxBlockScreenSaver.Checked;
1022              ShowUpdateMessage();
1023          }
1024  
1025          private void ComboBoxReconnect_TextChanged(object sender, EventArgs e)
1026          {
1027  #if OBSOLETE_SHORTCUTS
1028              if (comboBoxReconnect.Text.Contains("Disable"))
1029              {
1030                  Setting.Values.HotKeyReconnect = 0;
1031              }
1032              else if (comboBoxReconnect.Text.Length > 0)
1033              {
1034                  Setting.Values.HotKeyReconnect = comboBoxReconnect.Text[0];
1035              }
1036  #endif
1037              ShowUpdateMessage();
1038          }
1039  
1040          private void CheckBoxCircle_CheckedChanged(object sender, EventArgs e)
1041          {
1042              if (Setting.Values.MatrixCircle != checkBoxCircle.Checked)
1043              {
1044                  Setting.Values.MatrixCircle = checkBoxCircle.Checked;
1045                  ShowUpdateMessage();
1046                  MachineStuff.SendMachineMatrix();
1047              }
1048          }
1049  
1050          private void CheckBoxBlockMouseAtCorners_CheckedChanged(object sender, EventArgs e)
1051          {
1052              Setting.Values.BlockMouseAtCorners = checkBoxBlockMouseAtCorners.Checked;
1053              ShowUpdateMessage();
1054          }
1055  
1056          private void CheckBoxHideMouse_CheckedChanged(object sender, EventArgs e)
1057          {
1058              Setting.Values.HideMouse = checkBoxHideMouse.Checked;
1059              ShowUpdateMessage();
1060          }
1061  
1062          private void ComboBoxEasyMouseOption_TextChanged(object sender, EventArgs e)
1063          {
1064              string selectedOption = comboBoxEasyMouseOption.Text;
1065              int oldEasyMouseOption = Setting.Values.EasyMouse;
1066  
1067              Setting.Values.EasyMouse = Enum.TryParse<EasyMouseOption>(selectedOption, out EasyMouseOption easyMouseOption) ? (int)easyMouseOption : (int)EasyMouseOption.Enable;
1068  
1069              if (oldEasyMouseOption != Setting.Values.EasyMouse)
1070              {
1071                  ShowUpdateMessage();
1072              }
1073          }
1074  
1075          private void ComboBoxEasyMouse_TextChanged(object sender, EventArgs e)
1076          {
1077  #if OBSOLETE_SHORTCUTS
1078              if (comboBoxEasyMouse.Text.Contains("Disable"))
1079              {
1080                  Setting.Values.HotKeyToggleEasyMouse = 0;
1081              }
1082              else if (comboBoxEasyMouse.Text.Length > 0)
1083              {
1084                  Setting.Values.HotKeyToggleEasyMouse = comboBoxEasyMouse.Text[0];
1085              }
1086  #endif
1087              ShowUpdateMessage();
1088          }
1089  
1090          private void CheckBoxMouseMoveRelatively_CheckedChanged(object sender, EventArgs e)
1091          {
1092              Setting.Values.MoveMouseRelatively = checkBoxMouseMoveRelatively.Checked;
1093              ShowUpdateMessage();
1094          }
1095  
1096          private void CheckBoxDrawMouse_CheckedChanged(object sender, EventArgs e)
1097          {
1098              if (!(Setting.Values.DrawMouse = checkBoxDrawMouse.Checked))
1099              {
1100                  CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
1101              }
1102  
1103              ShowUpdateMessage();
1104          }
1105  
1106          private void CheckBoxTwoRow_CheckedChanged(object sender, EventArgs e)
1107          {
1108              matrixOneRow = !checkBoxTwoRow.Checked;
1109              ArrangeMachines();
1110          }
1111  
1112          private void ButtonNewKey_Click(object sender, EventArgs e)
1113          {
1114              string message = "Do you really want to generate a new key?\r\n" +
1115                  "(You would need to enter this key in all other machines to re-establish the connections)";
1116  
1117              if (MessageBox.Show(message, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
1118              {
1119                  Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
1120                  textBoxEnc.Text = Encryption.MyKey;
1121                  checkBoxShowKey.Checked = true;
1122                  Encryption.GeneratedKey = true;
1123                  ButtonOK_Click(null, null);
1124                  Common.ShowToolTip("New security key was generated, update other machines to the same key.", 10000, ToolTipIcon.Info, false);
1125              }
1126          }
1127  
1128          private void CheckBoxClipNetStatus_CheckedChanged(object sender, EventArgs e)
1129          {
1130              Setting.Values.ShowClipNetStatus = checkBoxClipNetStatus.Checked;
1131              ShowUpdateMessage();
1132          }
1133  
1134          private void CheckBoxSendLog_CheckedChanged(object sender, EventArgs e)
1135          {
1136              ShowUpdateMessage();
1137          }
1138  
1139          private void FrmMatrix_Resize(object sender, EventArgs e)
1140          {
1141              if (WindowState != FormWindowState.Minimized)
1142              {
1143                  groupBoxMachineMatrix.Top = groupBoxKeySetup.Top + groupBoxKeySetup.Height + 10;
1144                  groupBoxMachineMatrix.Height = ClientSize.Height - groupBoxKeySetup.Height - (int)(buttonOK.Height * 3.5);
1145                  checkBoxTwoRow.Top = groupBoxMachineMatrix.Height - (int)(checkBoxTwoRow.Height * 1.4);
1146                  buttonOK.Top = groupBoxMachineMatrix.Bottom + (int)(buttonOK.Height * 0.3);
1147                  buttonCancel.Top = groupBoxMachineMatrix.Bottom + (int)(buttonCancel.Height * 0.3);
1148                  groupBoxShortcuts.Height = ClientSize.Height - groupBoxOtherOptions.Bottom - 40;
1149                  groupBoxDNS.Height = ClientSize.Height - pictureBoxMouseWithoutBorders.Height - textBoxDNS.Height - 70;
1150              }
1151          }
1152  
1153          private void CheckBoxReverseLookup_CheckedChanged(object sender, EventArgs e)
1154          {
1155              Setting.Values.ReverseLookup = checkBoxReverseLookup.Checked;
1156              ShowUpdateMessage();
1157          }
1158  
1159          private void CheckBoxVKMap_CheckedChanged(object sender, EventArgs e)
1160          {
1161              // NOTE(@yuyoyuppe): this option is deprecated
1162              // Setting.Values.UseVKMap = checkBoxVKMap.Checked;
1163              ShowUpdateMessage();
1164          }
1165  
1166          private void LinkLabelMiniLog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
1167          {
1168              string miniLog = Helper.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
1169  
1170              Clipboard.SetText(miniLog);
1171              Common.ShowToolTip("Log has been placed in the clipboard.", 30000, ToolTipIcon.Info, false);
1172          }
1173  
1174          private void ComboBoxScreenCapture_TextChanged(object sender, EventArgs e)
1175          {
1176              ShowUpdateMessage();
1177          }
1178  
1179          private void LinkLabelReConfigure_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
1180          {
1181              string message = "WARNING: This will clear the Computer Matrix and allows you to run the setup experience like the first time you installed the program.\r\n";
1182              message += "You need to start this setup experience in all machines. In the next Dialog, click NO in the first machine and click YES in the rest of the machines.\r\n";
1183              message += "And then follow the steps to complete the configuration.\r\n\r\n";
1184              message += "Are you sure you want to continue?";
1185  
1186              if (MessageBox.Show(message, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
1187              {
1188                  PowerToysTelemetry.Log.WriteEvent(new MouseWithoutBorders.Telemetry.MouseWithoutBordersOldUIReconfigureEvent());
1189                  ButtonCancel_Click(this, new EventArgs());
1190                  Setting.Values.FirstRun = true;
1191                  Setting.Values.EasyMouse = (int)EasyMouseOption.Enable;
1192                  MachineStuff.ClearComputerMatrix();
1193                  MachineStuff.ShowSetupForm(true);
1194              }
1195          }
1196  
1197          private void CheckBoxSameSubNet_CheckedChanged(object sender, EventArgs e)
1198          {
1199              Setting.Values.SameSubNetOnly = checkBoxSameSubNet.Checked;
1200              ShowUpdateMessage();
1201          }
1202  
1203  #if USE_TO_CREATE_LOGO_BITMAP
1204          private void PaintMyLogo()
1205          {
1206              Graphics g = Graphics.FromHwnd(this.Handle);
1207              Font font = new Font("Chiller", 40);
1208              g.DrawString(Common.BinaryName, font, Brushes.Lime, comboBoxIPs.Right + 50, comboBoxIPs.Bottom - 5);
1209  
1210              Bitmap b = new Bitmap(220, 100);
1211              Graphics g2 = Graphics.FromImage(b);
1212              g2.FillRectangle(Brushes.WhiteSmoke, 0, 0, 220, 100);
1213              g2.DrawString(Common.BinaryName, font, Brushes.Lime, 0, 0);
1214              b.Save("c:\\zzz.bmp");
1215              string p = "";
1216              Color c;
1217              int l = 0;
1218              for (int i = 0; i < b.Width; i++)
1219              {
1220                  for (int j = 0; j < b.Height; j++)
1221                  {
1222                      c = b.GetPixel(i, j);
1223                      if (c.G > 0)
1224                      {
1225                          p += "{" + i + "," + j + "},";
1226                          l++;
1227                      }
1228                  }
1229                  p += "\r\n";
1230              }
1231              //File.WriteAllText("c:\\zzz.txt", l + ":" + p, Encoding.Unicode);
1232              b.Dispose();
1233              g2.Dispose();
1234          }
1235  #endif
1236      }
1237  }