2010-05-02 39 views
37

Tôi muốn học nếu có khác (nhanh) cách để ra văn bản để các cửa sổ ứng dụng giao diện điều khiển sử dụng C# .net hơn với Viết đơn giản, BackgroundColorForegroundColor phương pháp và tài sản? Tôi đã học được rằng mỗi ô có màu nền và màu nền trước, và tôi muốn cache/buffer/write nhanh hơn so với sử dụng các phương pháp đã đề cập.Làm thế nào tôi có thể viết đầu ra màu nhanh vào Bảng điều khiển?

Có thể có một số trợ giúp sử dụng bộ đệm Out, nhưng tôi không biết cách mã hóa màu thành luồng, nếu đó là nơi dữ liệu màu nằm.

Đây là trò chơi dựa trên kiểu chữ retro, tôi muốn triển khai nơi tôi sử dụng các màu tiêu chuẩn và ký tự ascii để đặt trò chơi.

Xin vui lòng giúp :)

Cập nhật:

Các Out và đệm có lẽ không phải những gì tôi cần phải mess xung quanh với. Dường như có một bộ đệm màn hình được sở hữu bởi giao diện điều khiển. Tôi không biết làm thế nào để truy cập nó, có lẽ tôi chỉ là may mắn trừ khi tôi nhập một số dlls.

Trả lời

38

Cập nhật: thêm mẫu
Nếu bạn chuẩn bị thực hiện một số công cụ P/Gọi, điều này có thể hữu ích. Về cơ bản nếu bạn nhận được một xử lý để đệm bộ điều khiển, sau đó bạn có thể sử dụng Win32 API tiêu chuẩn wot thao tác bộ đệm, thậm chí xây dựng toàn bộ bộ đệm tắt màn hình và blit nó vào giao diện điều khiển. Quay lại đầu trang |

Phần khó khăn nhất là xử lý bộ đệm bảng điều khiển. Tôi đã không cố gắng này trong .NET, nhưng trong nhiều năm trôi qua, bạn có thể có được xử lý để giao diện điều khiển hiện tại bằng cách sử dụng CreateFile (bạn sẽ cần P/Gọi này) và mở "CONOUT $" sau đó bạn có thể sử dụng xử lý là quay lại để chuyển sang các API khác.

P/Gọi cho CreateFile
http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html

Và bạn có thể sử dụng WriteConsoleOutput để di chuyển tất cả các ký tự và các thuộc tính của họ từ một bộ nhớ đệm để giao diện điều khiển đệm.
http://msdn.microsoft.com/en-us/library/ms687404(VS.85).aspx

Bạn có thể đặt cùng một thư viện đẹp để cung cấp quyền truy cập cấp thấp hơn vào bộ đệm bảng điều khiển.

Vì tôi đang cố gắng để có được .NET của tôi lên đến đầu một lần nữa tôi nghĩ rằng tôi sẽ cố gắng bàn tay của tôi lúc này và xem nếu tôi có thể làm cho nó hoạt động. Đây là một mẫu sẽ điền vào màn hình với tất cả các chữ cái A-Z và chạy qua tất cả các thuộc tính forground 0-15. Tôi nghĩ bạn sẽ rất ấn tượng với buổi biểu diễn. Tôi sẽ trung thực, tôi đã không dành nhiều thời gian xem xét mã này để kiểm tra lỗi là số không và có thể có một lỗi nhỏ ở đây hoặc ở đó nhưng nó sẽ giúp bạn đi với phần còn lại của các 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(); 
    } 
    } 
} 
+0

Cảm ơn rất nhiều vì sự giúp đỡ của bạn! Tôi chỉ có thể nhận được một số đầu ra cơ bản sau khi một số rối tung xung quanh. Tôi sử dụng GetStdHandle để có được bộ đệm, sau đó tôi chỉ cần vượt qua nó mảng chữ nhật của tôi CharInfo. Sẽ kiểm tra của bạn ra tiếp theo! – Statement

+2

Thực ra, GetStdHandle có thể thay thế cuộc gọi đến CreateFile. –

+0

cực kỳ thú vị .... – IAbstract

5

Nếu bạn xem xét việc thực hiện các thuộc tính của Console để thay đổi màu bàn điều khiển, họ ủy quyền cho phương thức SetConsoleTextAttribute từ kernel32.dll. Phương thức này mất character attributes làm đầu vào để đặt cả màu nền trước và màu nền.

Từ một số trang tài liệu MSDN, mỗi bộ đệm màn hình (trong đó một bảng điều khiển có bộ đệm) có mảng bản ghi thông tin ký tự hai chiều, mỗi bản được biểu thị bằng CHAR_INFO. Đây là những gì xác định màu sắc của mỗi nhân vật. Bạn có thể thao tác điều này bằng cách sử dụng phương thức SetConsoleTextAttribute, nhưng điều này được áp dụng cho bất kỳ văn bản mới nào được ghi vào bàn điều khiển - bạn không thể thao tác với văn bản hiện có đã có trên bảng điều khiển.

Trừ khi có móc cấp thấp hơn vào thuộc tính màu văn bản bảng điều khiển (không có khả năng), tôi nghĩ bạn đang bị mắc kẹt khi sử dụng các phương pháp này.


Một điều bạn có thể thử là để tạo ra một bộ đệm màn hình mới, hãy viết vào đó, và sau đó chuyển nó được đệm hiện hành của giao diện điều khiển sử dụng SetConsoleActiveScreenBuffer. Điều này có thể mang lại kết quả đầu ra nhanh hơn vì bạn sẽ ghi tất cả đầu ra vào bộ đệm không hoạt động.

Các vấn đề liên quan