Как я могу записать быстрый цветной вывод на консоль?

Шаблоны должны использоваться в заголовках, потому что компилятор должен создавать экземпляры разных версий кода в зависимости от параметров, заданных / выведенных для параметров шаблона. Помните, что шаблон не представляет собой код напрямую, а шаблон для нескольких версий этого кода. Когда вы компилируете функцию non-template в файле .cpp, вы компилируете конкретную функцию / класс. Это не относится к шаблонам, которые могут быть созданы с использованием разных типов, а именно, если при замене параметров шаблона конкретными типами необходимо исправить конкретный код.

Была функция с ключевым словом export, которая была предназначенный для отдельной компиляции. Функция export устарела в C++11 и, AFAIK, только один компилятор реализовал ее. Вы не должны использовать export. Отдельная компиляция невозможна в C++ или C++11, но, возможно, в C++17, если понятия в нее входят, мы могли бы иметь некоторый способ отдельной компиляции.

Для отдельной компиляции, которая должна быть достигнута, разделить проверка шаблона тела должна быть возможна. Кажется, что решение возможно с концепциями. Взгляните на этот документ , недавно представленный на совещании по стандартам. Я думаю, что это не единственное требование, поскольку вам все равно необходимо создать код кода шаблона в коде пользователя.

Отдельная проблема компиляции для шаблонов, я думаю, это также проблема, возникающая при миграции на модули, которые в настоящее время работают.

41
задан Statement 2 May 2010 в 19:07
поделиться

3 ответа

Обновление: добавлен образец
Если вы готовы выполнить некоторые действия P / Invoke, это может помочь.

В основном, если вы получаете дескриптор буфера консоли, вы можете использовать стандартные API Win32 для управления буфером, даже для создания всего буфера за пределами экрана и переноса его в консоль.

Единственная сложная часть - получить дескриптор буфера консоли. Я не пробовал это в .NET, но в прошедшие годы вы могли получить дескриптор текущей консоли с помощью CreateFile (вам нужно будет P / Invoke this) и открыть «CONOUT $», затем вы можете использовать дескриптор, который возвращается для перехода к другим API.

P / Invoke для CreateFile
http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html

И вы можете использовать WriteConsoleOutput для перемещения всех символов и их атрибутов из буфера памяти в буфер консоли.
http://msdn.microsoft.com/en-us/library/ms687404 (VS.85) .aspx

Вероятно, вы могли бы собрать хорошую библиотеку для обеспечения низкоуровневого доступа к буферу консоли.

Так как я снова пытаюсь довести свой .NET до нуля, я подумал, что попробую свои силы и посмотрю, смогу ли я заставить его работать. Вот пример, который заполнит экран всеми буквами A-Z и пройдёт через все атрибуты фона 0-15. Думаю, вы будете впечатлены игрой. Честно говоря, я не тратил много времени на просмотр этого кода, поэтому проверка ошибок равна нулю, и здесь может быть небольшая ошибка, но она должна помочь вам с остальными API.

using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace ConsoleApplication1
{
  class Program
  {

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern SafeFileHandle CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] uint fileAccess,
        [MarshalAs(UnmanagedType.U4)] uint fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        [MarshalAs(UnmanagedType.U4)] int flags,
        IntPtr template);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteConsoleOutput(
      SafeFileHandle hConsoleOutput, 
      CharInfo[] lpBuffer, 
      Coord dwBufferSize, 
      Coord dwBufferCoord, 
      ref SmallRect lpWriteRegion);

    [StructLayout(LayoutKind.Sequential)]
    public struct Coord
    {
      public short X;
      public short Y;

      public Coord(short X, short Y)
      {
        this.X = X;
        this.Y = Y;
      }
    };

    [StructLayout(LayoutKind.Explicit)]
    public struct CharUnion
    {
      [FieldOffset(0)] public char UnicodeChar;
      [FieldOffset(0)] public byte AsciiChar;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct CharInfo
    {
      [FieldOffset(0)] public CharUnion Char;
      [FieldOffset(2)] public short Attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SmallRect
    {
      public short Left;
      public short Top;
      public short Right;
      public short Bottom;
    }


    [STAThread]
    static void Main(string[] args)
    {
      SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

      if (!h.IsInvalid)
      {
        CharInfo[] buf = new CharInfo[80 * 25];
        SmallRect rect = new SmallRect() { Left = 0, Top = 0, Right = 80, Bottom = 25 };

        for (byte character = 65; character < 65 + 26; ++character)
        {
          for (short attribute = 0; attribute < 15; ++attribute)
          {
            for (int i = 0; i < buf.Length; ++i)
            {
              buf[i].Attributes = attribute;
              buf[i].Char.AsciiChar = character;
            }

            bool b = WriteConsoleOutput(h, buf,
              new Coord() { X = 80, Y = 25 },
              new Coord() { X = 0, Y = 0 },
              ref rect);
          }
        }
      }
      Console.ReadKey();
    }
  }
}  
45
ответ дан 26 November 2019 в 23:06
поделиться

Я имел успех с помощью

using (var stdout = Console.OpenStandardOutput(Cols * Rows))
{
    // fill
    stdout.Write(buffer, 0, buffer.Length);
    // rinse and repeat
}

, Но если кто-либо может консультировать меня по вопросам того, как я пишу, расширил ASCII до этого, я буду благодарен

0
ответ дан 26 November 2019 в 23:06
поделиться

Если вы посмотрите на реализацию свойств Console для изменения цветов консоли, они делегируются методу SetConsoleTextAttribute из kernel32.dll. Этот метод принимает атрибуты символов в качестве входных данных для установки цветов переднего и заднего плана.

Согласно нескольким документам MSDN, каждый экранный буфер (из которых консоль имеет один) имеет двумерный массив записей информации о символах, каждая из которых представлена CHAR_INFO. Это то, что определяет цвет каждого символа. Вы можете управлять этим с помощью метода SetConsoleTextAttribute, но он применяется к любому новому тексту, который записывается в консоль - вы не можете управлять существующим текстом, уже находящимся на консоли.

Если только не существует низкоуровневого доступа к свойствам цвета текста консоли (что маловероятно), я думаю, вы застряли на использовании этих методов.


Можно попробовать создать новый буфер экрана, записать в него текст, а затем переключить его в качестве текущего буфера консоли с помощью SetConsoleActiveScreenBuffer. Это может дать более быстрый вывод, поскольку вы будете записывать весь вывод в неактивный буфер.

5
ответ дан 26 November 2019 в 23:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: