Opakowanie kodu w osobną klasę

0

Witam

chyba wypłynąłem na za głębokie wody jak dla mnie :)

Ogólnie staram się napisać grę w konsoli i potrzebne mi szybkie rysowanie po niej.

Znalazłem kod który działa dobrze :

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();
    }
  }
}  

Kod przeniosłem do klasy gdzie rysuje główne okno. Rysowanie trochę zmieniłem i wszystko ok.

Tylko teraz fajnie było by i w innych klasach użyć tego kodu. I chciałem spakować ten kod w jedną klasę.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace unicodes
{
    class BuforKonsoli
    {
        public SafeFileHandle h;
        public CharInfo[] buf;
        public SmallRect rect;

        public BuforKonsoli(short x, short y, short dx, short dy)
        {
            h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
            buf = new CharInfo[x * y];
            rect = new SmallRect() { Left = dx, Top = dy, Right = x, Bottom = y };
        }

        // BRZYDKI KOD //

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public 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)]
        public 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;
        }
        // BRZYDKI KOD //
    }
}

I w innych klasach korzystać z tego mniej więcej tak :

public BuforKonsoli bufor;
bufor = new BuforKonsoli(81,40,0,0);
//i gdzieś w funkcji rysującej 
bufor.WriteConsoleOutput(bufor.h, bufor.buf, new Coord() { X = 81, Y = 40 }, new Coord() { X = 0, Y = 0 }, ref bufor.rect);

jak mam operatorem new stworzyć obiekt z innej klasy ? chodzi dokładnie o Coord.
a pierwszego błędu nie rozumiem (dlaczego tak nie może być)

Błędy :

Member 'BuforKonsoli.WriteConsoleOutput(Microsoft.Win32.SafeHandles.SafeFileHandle, unicodes.BuforKonsoli.CharInfo[], unicodes.Coord, unicodes.Coord, ref unicodes.BuforKonsoli.SmallRect)' cannot be accessed with an instance reference; qualify it with a type name instead

cannot convert from 'unicodes.Coord' to 'unicodes.BuforKonsoli.Coord'

C# uczę się od paru tygodni, więc to trochę mnie przerasta ale chcę pisać w miarę poprawnie i mieć szybką konsole :)
Ogólnie mógłbym ten 'brzydki' kod umieścić w każdej klasie gdzie będzie mi potrzebny ale wiem że to złe rozwiązanie.

0
  1. Przy odwolywaniu sie do skladowych statycznych, musisz to zrobic za pomoca nazwy klasy, a nie obiektu.
  2. Wyglada na to, ze masz juz gdzies typ o nazwie Coord poza ta klasa i tworzysz jego obiekt, probujac go wepchnac na typ BuforKonsoli.Coord, sprobuj napisac:
 new BuforkKonsoli.Coord() { X = 81, Y = 40 }
  1. Nie mieszaj polskich identyfikator z angielskimi. Najlepiej w ogole polskich nie uzywaj.
0

identyfikatory pewnie zostały z wytnij/wklej.

0

Fakt nie zauważyłem że WriteConsoleOutput jest statyczną metodą. Poprawione.
I miałem Coord zdefiniowane dwa razy.

Ale z tworzeniem obiektów dalej mam problem.

public ConsoleBuffor cb;
cb = new ConsoleBuffor(0,0,81,40);

2 błędy znów na new cb.Coord

ConsoleBuffor.WriteConsoleOutput(cb.h, cb.buf, new cb.Coord() { X = 81, Y = 40 }, new cb.Coord() { X = 0, Y = 0 }, ref cb.rect);

cb is a 'field' but is used like a 'type'

Czytać błędy umiem ale dużo mi to nie mówi od strony praktycznej.

0
ConsoleBuffor.WriteConsoleOutput(cb.h, cb.buf, new cb.Coord() { X = 81, Y = 40 }, new cb.Coord() { X = 0, Y = 0 }, ref cb.rect);

Niepoprawnie tworzysz instancję klasy Coord. Próbujesz wywołać konstruktor na właściwości cb, a powinieneś użyć new Coord ( X = 81, Y = 40 )

ConsoleBuffor.WriteConsoleOutput(cb.h, cb.buf, new Coord ( X = 81, Y = 40 ), new Coord( X = 0, Y = 0 ), ref cb.rect);
0

Wciąż nie działa.

Coord jest w klasie ConsoleBuffer
A funkcje wywołuje w innej klasie więc błędy dotyczą że nie widzi X,Y i Coorda.

dodam że nie rozumiem czemu w C# nie można się odwołać przez kropkę '.' poza klasą do publicznej struktury umieszczonej w klasie. Chodzi mi o cb.[tutaj] nie widać Coord.

A czytelnością kodu będę się zajmował jak zacznie działać :)

0

Juz Ci napisalem co masz zrobic z tymi wszystkimi bledami, przeczytaj moj pierwszy post i 200 razy jak nie lapiesz tego. Jak masz jakies inne bledy niezwiazane z pierwotnym tematem, to zaloz nowy watek...

0

n0name_l - Twoim sposobem tworzenia obiektu wywala mi błąd - Mapa.cb' is a 'field' but is used like a 'type'.
Jeśli piszesz że twój kod powinien działać to błąd musi być z klasą lub obiektem ConsoleBuffer.
Do pól statycznych odwołuję się już prawidłowo, Coord mam tylko jeden raz zdeklarowane. Gdzie jeszcze może być błąd ?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace unicodes
{
    class Mapa
    {
        public ConsoleBuffer cb;

        public Mapa()
        {
            cb = new ConsoleBuffer(0,0,81,40);
        }

        public void rysuj_mape()
        {
            for (int i = 0; i < cb.buf.Length; ++i)
            {    
                //cb.buf[i].Attributes = (short)kolor[i];
                //cb.buf[i].Char.AsciiChar = (byte)kafelek[i];
            }

            ConsoleBuffer.WriteConsoleOutput(cb.h, cb.buf, new cb.Coord() { X = 81, Y = 40 }, new cb.Coord() { X = 81, Y = 40 }, ref cb.rect);
        }
}

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace unicodes
{
    class ConsoleBuffer
    {
        public ConsoleBuffer(short x0,short y0, short x, short y)
        {
            h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
            buf = new CharInfo[x * y];
            rect = new SmallRect() { Left = x0, Top = y0, Right = x, Bottom = y };
        }
        public SafeFileHandle h;
        public CharInfo[] buf;
        public SmallRect rect;

        // BRZYDKI KOD //

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public 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)]
        public static extern bool WriteConsoleOutput(
          SafeFileHandle hConsoleOutput,
          CharInfo[] lpBuffer,
          Coord dwBufferSize,
          Coord dwBufferCoord,
          ref SmallRect lpWriteRegion);

        public struct cos
        {
            public int pole { get; set; }
        }

        [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;
        }
        // BRZYDKI KOD //
    }
}

foo

0

W ogole przeczytales to co napisalem?
new [NazwaKlasyZewnetrznej].[NazwaKlasyWewnetrznej]()

0

Tak teraz dotarło. Dzięki

1 użytkowników online, w tym zalogowanych: 0, gości: 1