C# 调整控制台的事件大小

C# 调整控制台的事件大小,c#,events,console,message,wndproc,C#,Events,Console,Message,Wndproc,因此,我认为窗口调整大小事件将通过winproc实现,我可能弄错了,希望得到控制台调整大小事件的通知 我想在调整大小时最大化控制台缓冲区,一旦完成,基本上将其缩小到窗口大小,从而防止由于缓冲区小于窗口而导致溢出错误。1#您需要获得控制台窗口的引用,有多种方法可以做到这一点: 2#您需要使用setwindowshookex钩住WndProc 3.在WndProc内处理WM#U大小信息 需要注意的是,在SetWindowHookEx示例中,有一个家伙叫CallNextHookEx,这是因为挂钩是链接

因此,我认为窗口调整大小事件将通过winproc实现,我可能弄错了,希望得到控制台调整大小事件的通知

我想在调整大小时最大化控制台缓冲区,一旦完成,基本上将其缩小到窗口大小,从而防止由于缓冲区小于窗口而导致溢出错误。

1#您需要获得控制台窗口的引用,有多种方法可以做到这一点:

2#您需要使用setwindowshookex钩住WndProc

3.在WndProc内处理WM#U大小信息

需要注意的是,在SetWindowHookEx示例中,有一个家伙叫CallNextHookEx,这是因为挂钩是链接的

另一个完整的例子是,他获取键盘消息,但您也可以这样做来捕获大小事件

再来一次

您可以通过线程侦听并捕获调整大小事件:

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,因为。Spy++可以钩住其他进程的WNDPOC来读取窗口消息,Spy++甚至不能读取控制台窗口消息。即使可以解决安全问题,也不能使用C#钩住另一个进程

我的比赛条件和我的完全一样。在Windows 10上更糟糕,因为调整窗口大小会使文本回流,并更改缓冲区宽度和窗口宽度
Console.BufferWidth
Console.BufferHeight
和family是非原子的,如果在调整窗口大小时使用它们,将抛出托管和非托管错误

您完全可以在事后找到有关调整大小的信息,但这并不能解决您的问题。您仍然会有并发问题。因为这不是钩子,所以不能让resize等待您完成
控制台
类的非原子缓冲区/窗口大小操作

我认为处理竞争条件的唯一选择是一个重试循环,这就是我将使用的

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) { }

这是您的解决方案吗:(可能是所有控制台成员:)不幸的是,setWindowsSize不起作用,因为它会导致缓冲区小于窗口,从而导致错误(在窗口展开时)。我需要的是在第一次调整缓冲区并防止错误时访问resize。从技术上讲,我可以做一个真正的黑客版本,预测异常,将缓冲区设置为最大值,然后检查缓冲区大小和窗口大小是否不同并修复它,但我试图避免这种情况。您可能必须使用P/Invoke。您问错了问题。你不关心窗口程序。您希望收到调整大小通知。请编辑以澄清。你应该能够获得控制台窗口的句柄,在这一点上你可以截获操纵它的消息,我只是没有做这件事的经验。事实上,我已经获得了句柄并调整了窗口的其他方面,只是不知道如何监听该点的大小,您所做的违背了控制台应用程序的目的,您可以获得缓冲区大小console.BufferWidth和console.BufferHeight,但控制台应用程序只处理可以链接和重定向的标准流,这就是为什么你不能假设你的应用程序运行在像cmd.exe这样的控制台上。为什么你不用Winforms或WPF()编写应用程序呢?我明白你的意思,我仍然希望能够检测到它是否实际上是一个在窗口中运行的控制台程序,并且能够接收相应的事件,这不是一个好的解决方案。繁忙的循环将需要一个线程,消耗CPU,并且容易出现各种竞争情况。您不应该在六个不同的位置获取
控制台.WindowHeight
控制台.WindowWidth
;无法保证在两次读取之间不会发生变化,从而导致
if
逻辑出现故障。您需要p/invoke来同时读取高度和宽度,并且需要以原子方式写入逻辑,即使这样,您也会随机错过简短的中间大小或快速更改。