Guest User

Untitled

a guest
Nov 21st, 2017
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.39 KB | None | 0 0
  1. public class ConsoleEx
  2. {
  3. static object accessToken = new object(); // блокировка
  4. int currX, currY; // текущие координаты этого объекта
  5. static ConsoleEx focusOwner = null;
  6.  
  7. public ConsoleEx(int startX, int startY)
  8. {
  9. currX = startX;
  10. currY = startY;
  11. }
  12.  
  13. // эти два метода должны вызываться под блокировкой
  14. void SaveCursorPosition()
  15. {
  16. currX = Console.CursorLeft;
  17. currY = Console.CursorTop;
  18. }
  19. void RestoreCursorPosition()
  20. {
  21. Console.SetCursorPosition(currX, currY);
  22. }
  23.  
  24. // в пустом конструкторе запоминаем текущие координаты
  25. public ConsoleEx()
  26. {
  27. lock (accessToken)
  28. SaveCursorPosition();
  29. }
  30.  
  31. // вспомогательный метод: выполнить действие и запомнить обновлённую позицию курсора
  32. // если есть фокус, отдать курсор ему
  33. void Execute(Action a)
  34. {
  35. lock (accessToken)
  36. {
  37. RestoreCursorPosition();
  38. a();
  39. SaveCursorPosition();
  40. if (focusOwner != null && focusOwner != this)
  41. focusOwner.RestoreCursorPosition();
  42. }
  43. }
  44.  
  45. // запись происходит очевидным образом
  46. public void Write(string s) => Execute(() => Console.Write(s));
  47. public void WriteLine(string s) => Execute(() => Console.WriteLine(s));
  48.  
  49. // чтение сложнее, делаем посимвольно
  50. public string ReadLine()
  51. {
  52. ConsoleEx oldFocus = Focus();
  53. try
  54. {
  55. StringBuilder line = new StringBuilder();
  56. int startX = currX, startY = currY;
  57. while (true)
  58. {
  59. // читаем нажатие без отображения
  60. var key = Console.ReadKey(intercept: true);
  61. lock (accessToken)
  62. {
  63. // если фокус не наш, игнорируем
  64. if (focusOwner != null && focusOwner != this)
  65. continue;
  66. }
  67. // Enter -> заканчиваем ввод
  68. if (key.Key == ConsoleKey.Enter)
  69. {
  70. Execute(Console.WriteLine);
  71. return line.ToString();
  72. }
  73. // Backspace -> уничтожаем предыдущий символ
  74. else if (key.Key == ConsoleKey.Backspace)
  75. {
  76. if (line.Length == 0)
  77. continue;
  78. lock (accessToken)
  79. {
  80. line[line.Length - 1] = ' ';
  81. Console.SetCursorPosition(startX, startY);
  82. Console.Write(line.ToString());
  83. line.Length--;
  84. Console.SetCursorPosition(startX, startY);
  85. Console.Write(line.ToString());
  86. SaveCursorPosition();
  87. }
  88. }
  89. // остальные символы выводим как есть
  90. else
  91. {
  92. line.Append(key.KeyChar);
  93. Execute(() => Console.Write(key.KeyChar));
  94. }
  95. }
  96. }
  97. finally
  98. {
  99. SetFocus(oldFocus);
  100. }
  101. }
  102.  
  103. public ConsoleEx Focus() => SetFocus(this);
  104. public void Unfocus() => SetFocus(null);
  105.  
  106. public static ConsoleEx SetFocus(ConsoleEx k)
  107. {
  108. lock (accessToken)
  109. {
  110. var oldFocusOwner = focusOwner;
  111. focusOwner = k;
  112. focusOwner?.RestoreCursorPosition();
  113. return oldFocusOwner;
  114. }
  115. }
  116. }
  117.  
  118. class Program
  119. {
  120. static void Main(string[] args)
  121. {
  122. ConsoleEx kin = new ConsoleEx(0, 0);
  123. Task.Run(async () =>
  124. {
  125. ConsoleEx kout = new ConsoleEx(0, 10);
  126. for (int i = 0; i < 100; i++)
  127. {
  128. await Task.Delay(1000);
  129. kout.Write($"{i} ");
  130. }
  131. });
  132. var result = kin.ReadLine();
  133. kin.WriteLine($"You entered: {result}");
  134. kin.WriteLine("Press any key");
  135. Console.ReadKey(intercept: true);
  136. }
  137. }
Add Comment
Please, Sign In to add comment