Example #1
0
        private static void With(short x, short y, short width, short height, Func <COORD, CHAR_INFO, CHAR_INFO> doAction, bool loadFromScreen, bool writeToBuffer = true)
        {
            if (x + width > System.Console.WindowWidth)
            {
                width = (short)((System.Console.WindowWidth - 1) - x - 1);
            }
            IntPtr buffer = IntPtr.Zero;

            try
            {
                var stdHandle = GetConsoleOutputHandle();
                buffer = Marshal.AllocHGlobal(width * height * Marshal.SizeOf(typeof(CHAR_INFO)));
                SMALL_RECT rect = new SMALL_RECT()
                {
                    Left = x, Top = y, Right = (short)(x + width), Bottom = (short)(y + height)
                };
                COORD leftTop = new COORD()
                {
                    X = 0, Y = 0
                };
                COORD size = new COORD()
                {
                    X = (short)(width), Y = height
                };

                if (loadFromScreen)
                {
                    if (!Native.ReadConsoleOutput(stdHandle.DangerousGetHandle(), buffer, size, leftTop, ref rect))
                    {
                        // 'Not enough storage is available to process this command' may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                }

                long LongPtr = buffer.ToInt64(); // Must work both on x86 and x64
                for (short h = 0; h < height; h++)
                {
                    for (short w = 0; w < width; w++)
                    {
                        IntPtr    RectPtr = new IntPtr(LongPtr);
                        CHAR_INFO ci      = (CHAR_INFO)Marshal.PtrToStructure(RectPtr, typeof(CHAR_INFO));
                        ci = doAction(new COORD()
                        {
                            X = w, Y = h
                        }, ci);
                        //save to safeBuffer
                        Marshal.StructureToPtr(ci, RectPtr, true); // You do not need to erase struct in this case
                        LongPtr += Marshal.SizeOf(typeof(CHAR_INFO));
                    }
                }
                if (writeToBuffer)
                {
                    Native.WriteConsoleOutput(stdHandle.DangerousGetHandle(), buffer, size, leftTop, ref rect);
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
Example #2
0
 public static extern bool WriteConsoleOutput(IntPtr hConsoleOutput, IntPtr lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, ref SMALL_RECT lpWriteRegion);