Interop.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. ConFrames - Gui Stuff for Console Windows
  3. Copyright (C) 2017-2018 Topten Software.
  4. ConFrames is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. ConFrames is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with ConFrames. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Runtime.InteropServices;
  19. using System.Text;
  20. using System.Threading.Tasks;
  21. namespace ConFrames
  22. {
  23. public class Interop
  24. {
  25. [DllImport("kernel32.dll", SetLastError = true)]
  26. public static extern IntPtr GetStdHandle(int nStdHandle);
  27. public const int STD_OUTPUT_HANDLE = -11;
  28. public const int STD_INPUT_HANDLE = -10;
  29. public const int STD_ERROR_HANDLE = -12;
  30. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  31. public static extern bool WriteConsoleOutput(
  32. IntPtr hConsoleOutput,
  33. CharInfo[] lpBuffer,
  34. Coord dwBufferSize,
  35. Coord dwBufferCoord,
  36. ref SmallRect lpWriteRegion);
  37. [DllImport("Kernel32.dll", SetLastError = true)]
  38. public static extern IntPtr CreateConsoleScreenBuffer(
  39. uint dwDesiredAccess,
  40. uint dwShareMode,
  41. IntPtr secutiryAttributes,
  42. UInt32 flags,
  43. IntPtr screenBufferData
  44. );
  45. [DllImport("kernel32.dll", SetLastError = true)]
  46. public static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, Coord dwSize);
  47. [DllImport("kernel32.dll", SetLastError = true)]
  48. public static extern bool SetConsoleActiveScreenBuffer(IntPtr hConsoleOutput);
  49. [DllImport("kernel32.dll", SetLastError = true)]
  50. public static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, Coord dwCursorPosition);
  51. [DllImport("kernel32.dll", SetLastError = true)]
  52. public static extern bool SetConsoleCursorInfo(IntPtr hConsoleOutput, ref CONSOLE_CURSOR_INFO info);
  53. [DllImport("kernel32.dll", SetLastError = true)]
  54. public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO info);
  55. [DllImport("kernel32.dll", SetLastError = true)]
  56. public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool absolute, ref SmallRect rect);
  57. [DllImport("kernel32.dll", SetLastError = true)]
  58. public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO info);
  59. [DllImport("kernel32.dll", SetLastError = true)]
  60. public static extern IntPtr GetConsoleWindow();
  61. [DllImport("user32.dll")]
  62. [return: MarshalAs(UnmanagedType.Bool)]
  63. public static extern bool SetForegroundWindow(IntPtr hWnd);
  64. [DllImport("user32.dll")]
  65. public static extern IntPtr GetForegroundWindow();
  66. [DllImport("user32.dll")]
  67. public static extern IntPtr GetActiveWindow();
  68. public static bool SetConsoleCursorVisible(IntPtr hConsole, bool visible)
  69. {
  70. CONSOLE_CURSOR_INFO info;
  71. if (!GetConsoleCursorInfo(hConsole, out info))
  72. return false;
  73. if (info.bVisible != visible)
  74. {
  75. info.bVisible = visible;
  76. return SetConsoleCursorInfo(hConsole, ref info);
  77. }
  78. return true;
  79. }
  80. [StructLayout(LayoutKind.Sequential)]
  81. public struct CONSOLE_CURSOR_INFO
  82. {
  83. public uint dwSize;
  84. public bool bVisible;
  85. };
  86. [StructLayout(LayoutKind.Sequential)]
  87. public struct CONSOLE_SCREEN_BUFFER_INFO
  88. {
  89. public Coord dwSize;
  90. public Coord dwCursorPosition;
  91. public ushort wAttributes;
  92. public SmallRect srWindow;
  93. public Coord dwMaximumWindowSize;
  94. }
  95. [StructLayout(LayoutKind.Sequential)]
  96. public struct CONSOLE_SCREEN_BUFFER_INFOEX
  97. {
  98. public int cbSize;
  99. public Coord dwSize;
  100. public Coord dwCursorPosition;
  101. public ushort wAttributes;
  102. public SmallRect srWindow;
  103. public Coord dwMaximumWindowSize;
  104. public ushort wPopupAttributes;
  105. public bool bFullscreenSupported;
  106. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
  107. public uint[] ColorTable;
  108. }
  109. [DllImport("kernel32.dll", SetLastError = true)]
  110. public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFOEX info);
  111. [DllImport("kernel32.dll", SetLastError = true)]
  112. public static extern bool SetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFOEX info);
  113. [DllImport("kernel32.dll", SetLastError = true)]
  114. public static extern Coord GetLargestConsoleWindowSize(IntPtr hConsoleOutput);
  115. public static void SetBufferAndScreenSize(IntPtr hConsoleOutput, short x, short y)
  116. {
  117. var largestSize = GetLargestConsoleWindowSize(hConsoleOutput);
  118. if (x > largestSize.X || y > largestSize.Y)
  119. throw new ArgumentException(string.Format("requested size is too big (max = {0} x {1})", largestSize.X, largestSize.Y));
  120. CONSOLE_SCREEN_BUFFER_INFO bi;
  121. if (!GetConsoleScreenBufferInfo(hConsoleOutput, out bi))
  122. throw new InvalidOperationException("GetConsoleScreenBufferInfo failed");
  123. Coord windowSize = new Coord((short)(bi.srWindow.Width + 1), (short)(bi.srWindow.Height + 1));
  124. if (windowSize.X > x || windowSize.Y > y)
  125. {
  126. var shrink = new SmallRect();
  127. shrink.Right = (short)(x < windowSize.X ? x - 1 : windowSize.X - 1);
  128. shrink.Bottom = (short)(y < windowSize.Y ? y - 1 : windowSize.Y - 1);
  129. if (!SetConsoleWindowInfo(hConsoleOutput, true, ref shrink))
  130. throw new InvalidOperationException("Failed to shrink window");
  131. }
  132. if (!SetConsoleScreenBufferSize(hConsoleOutput, new Coord(x, y)))
  133. throw new InvalidOperationException("Failed to resize buffer");
  134. var info = new SmallRect();
  135. info.Right = (short)(x - 1);
  136. info.Bottom = (short)(y - 1);
  137. if (!SetConsoleWindowInfo(hConsoleOutput, true, ref info))
  138. throw new InvalidOperationException("Failed to resize window");
  139. CONSOLE_SCREEN_BUFFER_INFO cbi;
  140. GetConsoleScreenBufferInfo(hConsoleOutput, out cbi);
  141. }
  142. public const uint CONSOLE_TEXTMODE_BUFFER = 0x00000001;
  143. public const uint GENERIC_READ = 0x80000000;
  144. public const uint GENERIC_WRITE = 0x40000000;
  145. public const uint GENERIC_READWRITE = GENERIC_READ | GENERIC_WRITE;
  146. [StructLayout(LayoutKind.Sequential)]
  147. public struct Coord
  148. {
  149. public short X;
  150. public short Y;
  151. public Coord(short X, short Y)
  152. {
  153. this.X = X;
  154. this.Y = Y;
  155. }
  156. };
  157. [StructLayout(LayoutKind.Sequential)]
  158. public struct SmallRect
  159. {
  160. public short Left;
  161. public short Top;
  162. public short Right;
  163. public short Bottom;
  164. public short Width { get { return (short)(Right - Left); } }
  165. public short Height { get { return (short)(Bottom - Top); } }
  166. }
  167. }
  168. }