Informatika gyűjtemény

Egy szinttel feljebb BdgGraphic.cs

2004050607080910

NézetNyomtat

BdgGraphic.cs (Vissza)
Az alábbi letöltési lehetőségek közül választhatsz: (segítség)
Karakterkódolás:
Sortörés:
Típus: text/plain
Tartalmaz szöveget
Karakterkódolás: utf-8
Méret: 8 KB
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace Bdg
{

    public class BdgGraphic 
    {
        private static Window window;
        
        /// <summary>
        /// Az a szál, ami megnyitja az ablakot.
        /// </summary>
        private static Thread thread;
        
        /// <summary>
        /// Ez a szemafor jelzi, ha kinyílt az ablak, eztután lehet visszaadni
        /// a vezérlést a kliensnek.
        /// </summary>
        private static Semaphore ready = new Semaphore(0, 1);
        
        
        /// <summary>
        /// Megnyitja a grafikus ablakot.
        /// </summary>
        /// <param name="name">Az ablak címe.</param>
        /// <param name="width">Az ablak szélessége pixelben.</param>
        /// <param name="height">Az ablak magassága pixelben.</param>
        public static void Start(string name, int width, int height) {
            ParameterizedThreadStart job = new ParameterizedThreadStart(WinFormsThread);
            thread = new Thread(job);
            thread.Start(new object[] {name, width, height});
            
            //megvárjuk, hogy elkészüljön az ablak
            // (azaz megkapja az OnShown eseményt)
            ready.WaitOne();
        }
        
        /// <summary>
        /// A grafikus ablak szálja. Megnyitja a BdgGraphic formot.
        /// A Start függvény indítja el, a paraméterek egy listában jönnek.
        /// </summary>
        /// <param name="l">A paraméterek egy object[] tömbben.</param>
        private static void WinFormsThread(object l) {
            object[] list = (object[]) l;
            window = new Window(
                (string) list[0], 
                (int) list[1], 
                (int) list[2],
                ready);
            Application.Run(window);
        }
        
        public static void Kill() 
        {
            window.SendMessage(Window.WM_CLOSE);
            Application.Exit();
        }
        
                
        /// <summary>
        /// Újrarajzoltatja az ablak tartalmát.
        /// </summary>
        public static void Flush() {
            window.Invalidate();
            //window.SendMessage(Window.WM_PAINT);
        }
        
        public static void DrawLine(Color color, int x1, int y1, int x2, int y2) {
            window.DrawLine(color, x1, y1, x2, y2);
        }
        
        public static void DrawEllipse(Color color, int x, int y, int width, int height) {
            window.DrawEllipse(color, x, y, width, height);
        }
        
        public static void FillRectangle(Color color, int x, int y, int width, int height) {
            window.FillRectangle(color, x, y, width, height);
        }
        
        public static void FillEllipse(Color color, int x, int y, int width, int height) {
            window.FillEllipse(color, x, y, width, height);
        }       
        
        public static void DrawPixel(Color color, int x, int y) {
            window.FillRectangle(color, x, y, 1, 1);
        }
        
        public static int MouseX {
            get { return window.MouseX; }
        }
        
        public static int MouseY {
            get { return window.MouseY; }
        }       
        
        public static bool[] MouseButtons {
            get { return window.DownButtons; }
        }
        
        public static bool KeyAvailable {
            get { return window.KeyAvailable; }
        }
        
        public static char ReadKey() {
            return window.ReadKey();
        }
    }
    
    /// <summary>
    /// Segíti a rajzolást .NET-es programokhoz.
    /// 
    /// A .NET egy eseményvezérelt rendszer. Ez az egyszerűbb grafikus 
    /// programok írását feleslegesen bonyolulttá teszi. Másszóval olyan 
    /// problémákat old meg, amik egy kisebb programnál még nem fordulnak elő.
    /// Ez az osztály áthidalja ezt. Ha belenézel a kódjába látni fogod, hogy 
    /// tök bonyolult. Ennyire azért nem szívás nyers .NET-ben rajzolni: itt
    /// egy kicsit-bonyolult rendszert egyszerűvé alakítani nagyon bonyolult volt.
    /// </summary>
    public class Window : Form
    {
        public const uint WM_CLOSE = 0x0010;
        public const uint WM_PAINT = 0x000F;
        public const uint WM_SETREDRAW = 0x000B;

        /// <summary>
        /// A megnyitott ablak WinAPI-s azonosítója. Szerencsére ilyenekre
        /// .NET-ben nincs nagyon szükség. Itt is csak azért kell, hogy
        /// a "bezárás" üzenetet el lehessen küldeni programból az 
        /// ablaknak.
        /// </summary>
        private static IntPtr hWnd;
        
        /// <summary>
        /// Háttérbuffer. Ebbe lehet rajzolni, és amikor a Windowsnak kedve
        /// van, vagy mi külön kérjük, akkor kikerül a képernyőre.
        /// </summary>
        private Bitmap backBuffer;
        
        private Semaphore ready;
        
        /// <summary>
        /// ...
        /// </summary>
        private Graphics gc;
        private SolidBrush solidBrush;
        private Pen pen;
        
        private int mouseX, mouseY;
        public int MouseX {
            get { return mouseX; }
        }
        public int MouseY {
            get { return mouseY; }
        }
        
        private bool[] downButtons;
        public bool[] DownButtons {
            //FIXME másolat kéne
            get { return downButtons; }
        }
        
        private Queue<char> keyFifo;
        private Semaphore keySemaphore = new Semaphore(1, 1);
        
        /// <summary>
        /// Az ablak konstruktora.
        /// </summary>
        /// <param name="title"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public Window(string title, int width, int height, Semaphore ready)
        {
            ClientSize = new Size(width, height);
            MinimumSize = ClientSize;
            MaximumSize = ClientSize;
            
            backBuffer = new Bitmap(ClientSize.Width,ClientSize.Height);
            gc = Graphics.FromImage(backBuffer);
            solidBrush = new SolidBrush(Color.Black);
            pen = new Pen(Color.Black);
            
            this.ready = ready;
            this.Text=title;

            downButtons = new bool[3];
            keyFifo = new Queue<char>();
            
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            //ez elvben nem kéne, így most már tripla-buffer van
            SetStyle(ControlStyles.DoubleBuffer, true);
            
            
            
            Paint += new PaintEventHandler(OnPaint);
            Shown += new EventHandler(OnShown);
            MouseMove += new MouseEventHandler(OnMouseMove);
            MouseUp += new MouseEventHandler(OnMouseUp);
            MouseDown += new MouseEventHandler(OnMouseDown);
            KeyPress += new KeyPressEventHandler(OnKeyPress);
        }
        
        /// <summary>
        /// Shown esemény: amikor először megjelent az ablak
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnShown(object sender, EventArgs e) {
            //elmentjük az ablak WinAPI-s azonosítóját
            // (remélhetőleg ez végig ugyanez lesz...)
            hWnd = Handle;
            //jelzünk, hogy kész a megnyitás, mostantól lehet már
            //rajzolni
            ready.Release();
        }
        
        /// <summary>
        /// Paint esemény, amikor kirajzolódik az ablak
        /// </summary>
        /// <param name="_sender"></param>
        /// <param name="e"></param>
        private void OnPaint(object sender, PaintEventArgs e) {
            //kitesszük a háttérbuffer tartalmát
            e.Graphics.DrawImageUnscaled(backBuffer,0,0);
        }
        
        private void OnMouseMove(object sender, MouseEventArgs e) {
            mouseX = e.X;
            mouseY = e.Y;
        }

        private void SetButton(MouseButtons b, bool value) {
            switch (b) {
                case MouseButtons.Left:
                    downButtons[0] = value;
                    break;
                case MouseButtons.Middle:
                    downButtons[1] = value;
                    break;
                case MouseButtons.Right:
                    downButtons[2] = value;
                    break;
            }
        }
        
        private void OnMouseDown(object sender, MouseEventArgs e) {
            SetButton(e.Button, true);
        }

        private void OnMouseUp(object sender, MouseEventArgs e) {
            SetButton(e.Button, false);
        }
        
        private void OnKeyPress(object sender, KeyPressEventArgs e) {
            keySemaphore.WaitOne();
            keyFifo.Enqueue(e.KeyChar);
            keySemaphore.Release();
            e.Handled = true;
        }
                
        public bool KeyAvailable {
            get {
                return keyFifo.Count > 0;
            }
        }
        
        public char ReadKey() {
            keySemaphore.WaitOne();
            char ch = keyFifo.Dequeue();
            keySemaphore.Release();
            return ch;
        }
        
        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, UIntPtr wParam,IntPtr lParam);
        
        /// <summary>
        /// Üzenetet küld az ablaknak. lParam és wParam mindig 0.
        /// </summary>
        /// <param name="msg"></param>
        public void SendMessage(uint msg) {
            SendMessage(hWnd, msg, new UIntPtr(0), new IntPtr(0));
        }

        
        /// <summary>
        /// Becsukja az ablakot.
        /// </summary>
        public void Kill() {
//          instance.Close();
            SendMessage(WM_CLOSE);
        }
        
        public void DrawLine(Color color, int x1, int y1, int x2, int y2) {
            pen.Color = color;
            gc.DrawLine(pen, x1, y1, x2, y2);
        }
        
        public void DrawEllipse(Color color, int x, int y, int width, int height) {
            pen.Color = color;
            gc.DrawEllipse(pen, x, y, width, height);
        }
        
        
        public void FillRectangle(Color color, int x, int y, int width, int height) {
            solidBrush.Color = color;
            gc.FillRectangle(solidBrush, x, y, width, height);
        }
        
        public void FillEllipse(Color color, int x, int y, int width, int height) {
            solidBrush.Color = color;
            gc.FillEllipse(solidBrush, x, y, width, height);
        }       
        
        public void DrawPixel(Color color, int x, int y) {
            solidBrush.Color = color;
            gc.FillRectangle(solidBrush, x, y, 1, 1);
        }
    
    }
}
(Vissza)