Script for upgrading certain versions of AME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
9.8 KiB

1 year ago
  1. using System;
  2. using System.Diagnostics;
  3. using System.Runtime.InteropServices;
  4. using System.Windows.Forms;
  5. using Microsoft.Win32;
  6. namespace Ameliorated.ConsoleUtils
  7. {
  8. public static partial class ConsoleTUI
  9. {
  10. private const int MF_BYCOMMAND = 0x00000000;
  11. private const int SC_CLOSE = 0xF060;
  12. private const int SC_MINIMIZE = 0xF020;
  13. private const int SC_MAXIMIZE = 0xF030;
  14. private const int SC_SIZE = 0xF000; //resize
  15. private const uint CHECK_QUICK_EDIT = 0x0040;
  16. private const int ENABLE_QUICK_EDIT = 0x40 | 0x80;
  17. // STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
  18. private const int STD_INPUT_HANDLE = -10;
  19. private static string PreviousTitle;
  20. private static int PreviousBufferHeight = 26;
  21. private static int PreviousBufferWidth = 80;
  22. private static int PreviousSizeHeight = 26;
  23. private static int PreviousSizeWidth = 80;
  24. private static bool IsInitialized;
  25. private static int InitializedWidth = 80;
  26. public static void ShowErrorBox(string message, string caption)
  27. {
  28. NativeWindow window = new NativeWindow();
  29. window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle);
  30. MessageBox.Show(window, message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
  31. }
  32. public enum BackdropType
  33. {
  34. None = 1,
  35. Mica = 2,
  36. Acrylic = 3,
  37. Tabbed = 4
  38. }
  39. public static readonly int WinVer = Int32.Parse(Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("CurrentBuildNumber").ToString());
  40. [DllImport("dwmapi.dll")]
  41. private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int pvAttribute, int cbAttribute);
  42. public static void Initialize(string title, int width = 80, int height = 26, bool resize = false, bool quickedit = false)
  43. {
  44. if (width < 2) throw new ArgumentException("Width must be greater than one.");
  45. IsInitialized = true;
  46. PreviousSizeHeight = Console.WindowHeight;
  47. PreviousSizeWidth = Console.WindowWidth;
  48. PreviousBufferHeight = Console.BufferHeight;
  49. PreviousBufferWidth = Console.BufferWidth;
  50. Console.SetWindowSize(width, height);
  51. Console.SetBufferSize(width, height);
  52. Console.SetWindowSize(width, height);
  53. InitializedWidth = width;
  54. Console.Clear();
  55. Console.CursorVisible = false;
  56. PreviousTitle = Console.Title;
  57. Console.Title = title;
  58. try
  59. {
  60. if ((Console.CursorLeft == 0 && Console.CursorTop == 0) || ParentProcess.ProcessName.Equals("Explorer", StringComparison.OrdinalIgnoreCase))
  61. {
  62. var bd = (int)BackdropType.Mica;
  63. var trueA = 0x01;
  64. if (WinVer >= 22523)
  65. {
  66. var handle = Process.GetCurrentProcess().MainWindowHandle;
  67. DwmSetWindowAttribute(handle, 38, ref bd, Marshal.SizeOf<int>());
  68. DwmSetWindowAttribute(handle, 20, ref trueA, Marshal.SizeOf<int>());
  69. }
  70. }
  71. } catch (Exception e) { }
  72. if (!resize)
  73. try
  74. {
  75. DisableResize();
  76. } catch (Exception e)
  77. {
  78. //ConsoleUtils.WriteError("Error disabling window resize - " + e.Message);
  79. }
  80. if (!quickedit)
  81. try
  82. {
  83. DisableQuickEdit();
  84. } catch (Exception e)
  85. {
  86. //ConsoleUtils.WriteError("Error disabling quickedit - " + e.Message);
  87. }
  88. }
  89. public static void Close()
  90. {
  91. if (!IsInitialized) throw new MethodAccessException("Console TUI must be initialized before calling other TUI functions.");
  92. IsInitialized = false;
  93. var parent = ParentProcess.ProcessName;
  94. if (parent.Equals("Explorer", StringComparison.CurrentCultureIgnoreCase)) return;
  95. try
  96. {
  97. EnableResize();
  98. } catch (Exception e)
  99. {
  100. //ConsoleUtils.WriteError("Error enabling window resize - " + e.Message);
  101. }
  102. try
  103. {
  104. EnableQuickEdit();
  105. } catch (Exception e)
  106. {
  107. //ConsoleUtils.WriteError("Error enabling quickedit - " + e.Message);
  108. }
  109. Console.CursorVisible = true;
  110. Console.Clear();
  111. Console.Title = PreviousTitle;
  112. Console.SetWindowSize(PreviousSizeWidth, PreviousSizeHeight);
  113. Console.SetBufferSize(PreviousBufferWidth, PreviousBufferHeight);
  114. }
  115. [DllImport("user32.dll")]
  116. public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
  117. [DllImport("user32.dll")]
  118. private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
  119. [DllImport("kernel32.dll", ExactSpelling = true)]
  120. private static extern IntPtr GetConsoleWindow();
  121. private static void DisableResize()
  122. {
  123. var handle = GetConsoleWindow();
  124. var sysMenu = GetSystemMenu(handle, false);
  125. if (handle != IntPtr.Zero)
  126. {
  127. //DeleteMenu(sysMenu, SC_CLOSE, MF_BYCOMMAND);
  128. //DeleteMenu(sysMenu, SC_MINIMIZE, MF_BYCOMMAND);
  129. DeleteMenu(sysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  130. DeleteMenu(sysMenu, SC_SIZE, MF_BYCOMMAND); //resize
  131. }
  132. }
  133. private static void EnableResize()
  134. {
  135. var handle = GetConsoleWindow();
  136. GetSystemMenu(handle, true);
  137. }
  138. [DllImport("kernel32.dll", SetLastError = true)]
  139. private static extern IntPtr GetStdHandle(int nStdHandle);
  140. [DllImport("kernel32.dll")]
  141. private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
  142. [DllImport("kernel32.dll")]
  143. private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
  144. private static void DisableQuickEdit()
  145. {
  146. var consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
  147. // get current console mode
  148. uint consoleMode;
  149. GetConsoleMode(consoleHandle, out consoleMode);
  150. // set the new mode
  151. SetConsoleMode(consoleHandle, consoleMode &= ~CHECK_QUICK_EDIT);
  152. }
  153. private static void EnableQuickEdit()
  154. {
  155. var consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
  156. // get current console mode
  157. uint consoleMode;
  158. GetConsoleMode(consoleHandle, out consoleMode);
  159. // set the new mode
  160. SetConsoleMode(consoleHandle, consoleMode | ENABLE_QUICK_EDIT);
  161. }
  162. }
  163. public class ChoicePrompt : Prompt
  164. {
  165. public string Choices { get; set; } = "YN";
  166. public bool BeepSound { get; set; } = true;
  167. public bool CaseSensitive { get; set; } = false;
  168. public bool AllowEscape { get; set; } = true;
  169. public bool AnyKey { get; set; } = false;
  170. public ConsoleColor? TextForeground { get; set; }
  171. private bool _bindToOpenFrame;
  172. public new int? Start()
  173. {
  174. if (Choices.Length < 1 && !AnyKey) throw new ArgumentException("There must be at least 1 choice.");
  175. Console.Write(Text);
  176. var cursorVisibility = Console.CursorVisible;
  177. int? result;
  178. while (true)
  179. {
  180. Console.CursorVisible = true;
  181. var key = Console.ReadKey(true);
  182. if (AnyKey)
  183. {
  184. Console.CursorVisible = cursorVisibility;
  185. return key.KeyChar;
  186. }
  187. if (key.Key == ConsoleKey.Escape && AllowEscape)
  188. {
  189. Console.CursorVisible = cursorVisibility;
  190. return null;
  191. }
  192. if (CaseSensitive)
  193. result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.Ordinal);
  194. else
  195. result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.OrdinalIgnoreCase);
  196. if (result >= 0)
  197. {
  198. if (!CaseSensitive) Console.Write(key.KeyChar.ToString().ToUpper());
  199. else Console.Write(key.KeyChar.ToString());
  200. break;
  201. }
  202. else if (BeepSound) Console.Beep();
  203. }
  204. Console.CursorVisible = cursorVisibility;
  205. Console.WriteLine();
  206. return result.Value;
  207. }
  208. }
  209. public abstract class Prompt
  210. {
  211. /// <summary>
  212. /// Text to be displayed before the input.
  213. /// </summary>
  214. public string Text { get; set; } = "";
  215. public int? MaxLength { get; set; }
  216. /// <summary>
  217. /// (Optional)
  218. /// </summary>
  219. public ConsoleColor? InputForeground { get; set; } = null;
  220. public ConsoleColor? InputBackground { get; set; } = null;
  221. public bool BindToOpenFrame { get; set; } = true;
  222. public bool AllowEscape { get; set; } = true;
  223. }
  224. }