控制台的调整大小事件
Resize Event for Console
所以我认为 window 调整大小事件会通过 winproc 发生,我可能错了,希望得到控制台调整大小事件的通知。
我想在调整大小时最大化控制台缓冲区,一旦完成,它基本上会缩小到 window 大小,从而防止由于缓冲区小于 window 而导致的溢出错误].
1# 您需要获得对控制台的引用 window,有多种方法可以做到这一点:https://support.microsoft.com/en-us/kb/124103
2# 您需要使用 setwindowshookex SetWindowsHookEx in C#
挂钩您的 WndProc
3# 处理 WndProc 中的 WM_SIZE 消息 https://msdn.microsoft.com/en-us/library/windows/desktop/ms632646(v=vs.85).aspx
重要的是要注意,在 SetWindowHookEx 示例中,那个叫 CallNextHookEx 的家伙,那是因为挂钩是链接的。
另一个完整示例 http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx 他获取键盘消息,但您可以执行相同的操作来捕获大小事件。
还有一个
Capture all Windows Messages
您可以使用线程监听和捕获 Resize 事件:
class Program
{
private static bool _listnerOn;
static void Main(string[] args)
{
Thread listner = new Thread(EventListnerWork);
listner.Start();
Console.WriteLine("Press a key to exit...");
Console.ReadKey(true);
_listnerOn = false;
listner.Join();
}
static void ConsoleResizeEvent(int height, int width)
{
Console.WriteLine("Console Resize Event");
}
static void EventListnerWork()
{
Console.WriteLine("Listner is on");
_listnerOn = true;
int height = Console.WindowHeight;
int width = Console.WindowWidth;
while (_listnerOn)
{
if (height != Console.WindowHeight || width != Console.WindowWidth)
{
height = Console.WindowHeight;
width = Console.WindowWidth;
ConsoleResizeEvent(height,width);
}
Thread.Sleep(10);
}
Console.WriteLine("Listner is off");
}
}
不幸的是,答案是您无法挂接控制台的 WndProc,因为 it's in a separate, security-controlled process。 Spy++ 可以挂钩其他进程的 WndProcs 来读取 window 消息,而 Spy++ 甚至不能读取控制台 window 消息。即使您可以解决安全问题,C# 也不能用于挂接另一个进程。
我在调整大小时遇到了完全相同的竞争条件。在 Windows 10 上更糟,因为调整 window 的大小会重排文本并更改缓冲区宽度以及 window 宽度。 Console.BufferWidth
、Console.BufferHeight
和系列是非原子的,如果在调整 window 大小时使用它们,将抛出托管和非托管错误。
您绝对可以通过 Reading Input Buffer Events 了解有关 事后 调整大小的信息,但这并不能解决您的问题。您仍然会遇到并发问题。由于这不是一个钩子,您不能让调整大小等待您完成 Console
class 的非原子 buffer/window 大小操作。
我认为处理竞争条件的唯一选择是 重试循环,这就是我将使用的方法。
while (true) try
{
// Read and write the buffer size/location and window size/location and cursor position,
// but be aware it will be rudely interrupted if the console is resized by the user.
}
catch (IOException) { }
catch (ArgumentOutOfRangeException) { }
所以我认为 window 调整大小事件会通过 winproc 发生,我可能错了,希望得到控制台调整大小事件的通知。
我想在调整大小时最大化控制台缓冲区,一旦完成,它基本上会缩小到 window 大小,从而防止由于缓冲区小于 window 而导致的溢出错误].
1# 您需要获得对控制台的引用 window,有多种方法可以做到这一点:https://support.microsoft.com/en-us/kb/124103
2# 您需要使用 setwindowshookex SetWindowsHookEx in C#
挂钩您的 WndProc3# 处理 WndProc 中的 WM_SIZE 消息 https://msdn.microsoft.com/en-us/library/windows/desktop/ms632646(v=vs.85).aspx
重要的是要注意,在 SetWindowHookEx 示例中,那个叫 CallNextHookEx 的家伙,那是因为挂钩是链接的。
另一个完整示例 http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx 他获取键盘消息,但您可以执行相同的操作来捕获大小事件。
还有一个 Capture all Windows Messages
您可以使用线程监听和捕获 Resize 事件:
class Program
{
private static bool _listnerOn;
static void Main(string[] args)
{
Thread listner = new Thread(EventListnerWork);
listner.Start();
Console.WriteLine("Press a key to exit...");
Console.ReadKey(true);
_listnerOn = false;
listner.Join();
}
static void ConsoleResizeEvent(int height, int width)
{
Console.WriteLine("Console Resize Event");
}
static void EventListnerWork()
{
Console.WriteLine("Listner is on");
_listnerOn = true;
int height = Console.WindowHeight;
int width = Console.WindowWidth;
while (_listnerOn)
{
if (height != Console.WindowHeight || width != Console.WindowWidth)
{
height = Console.WindowHeight;
width = Console.WindowWidth;
ConsoleResizeEvent(height,width);
}
Thread.Sleep(10);
}
Console.WriteLine("Listner is off");
}
}
不幸的是,答案是您无法挂接控制台的 WndProc,因为 it's in a separate, security-controlled process。 Spy++ 可以挂钩其他进程的 WndProcs 来读取 window 消息,而 Spy++ 甚至不能读取控制台 window 消息。即使您可以解决安全问题,C# 也不能用于挂接另一个进程。
我在调整大小时遇到了完全相同的竞争条件。在 Windows 10 上更糟,因为调整 window 的大小会重排文本并更改缓冲区宽度以及 window 宽度。 Console.BufferWidth
、Console.BufferHeight
和系列是非原子的,如果在调整 window 大小时使用它们,将抛出托管和非托管错误。
您绝对可以通过 Reading Input Buffer Events 了解有关 事后 调整大小的信息,但这并不能解决您的问题。您仍然会遇到并发问题。由于这不是一个钩子,您不能让调整大小等待您完成 Console
class 的非原子 buffer/window 大小操作。
我认为处理竞争条件的唯一选择是 重试循环,这就是我将使用的方法。
while (true) try
{
// Read and write the buffer size/location and window size/location and cursor position,
// but be aware it will be rudely interrupted if the console is resized by the user.
}
catch (IOException) { }
catch (ArgumentOutOfRangeException) { }