domenica 7 dicembre 2014

Array di controlli in C#

Ho realizzato un array di controlli.
Ecco il codice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Project10
{
    class mioForm:Form
    {
        Button[] bottone;
        public mioForm()
        {
            InitializeComponent();
        }

        public static void Main()
        {
            mioForm frm = new mioForm();
            Application.Run(frm);
            
           
        }
        
        private void InitializeComponent()
        {
           
            bottone = new Button[23];
            this.SuspendLayout();
            for (int n = 0; n < 23; n++)
            {
                bottone[n] = new Button();
                bottone[n].Width = 50;
                bottone[n].Height = 50;
                bottone[n].Left = bottone[n].Width * (n % 5);
                bottone[n].Top = bottone[n].Height * (n / 5);
                bottone[n].Text = (n+1).ToString();
                this.Controls.Add(bottone[n]);
               
            }

            
            this.ClientSize = new System.Drawing.Size(584, 561);
            
            this.Name = "mioForm";
            this.Load += new System.EventHandler(this.mioForm_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private void mioForm_Load(object sender, EventArgs e)
        {
           
        }

       

        
    }

}
Resta ancora da vedere come gestire l'evento Click di ciascuno dei controlli, altrimenti che ci faccio?
Per il momento, passo ad altro.

Creazione dal nulla di un'applicazione con un form in C#

Apro un progetto vuoto.
Ci aggiungo i riferimenti (System.Windows.Forms) e li collego al programma;
aggiungo una classe mioForm.cs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
    class mioForm
    {
    }
}
Adesso faccio ereditare la mia classe dalla classe Form.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
    class mioForm:Form
    {

    }
}
Aggiungo il metodo statico Main();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
    class mioForm:Form
    {


        public static void Main()
        {

        }
    }
}
Facendo partire questo, ottengo solo una fugace visualizzazione di una console.

Ora dichiaro e istanzio la mia classe derivata da Form, e faccio partire l'applicazione con il mio oggetto:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
    class mioForm:Form
    {


        public static void Main()
        {
            mioForm frm = new mioForm();
            Application.Run(frm);
        }
    }
}
Ottengo una console e un form, che resta lì e devo chiudere con la "crocetta" in alto a destra per terminare l'esecuzione.

Ecco che mi viene fuori un codice generato automaticamente:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
    class mioForm:Form
    {


        public static void Main()
        {
            mioForm frm = new mioForm();
            Application.Run(frm);
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // mioForm
            // 
            this.ClientSize = new System.Drawing.Size(284, 261);
            this.Name = "mioForm";
            this.Load += new System.EventHandler(this.mioForm_Load);
            this.ResumeLayout(false);

        }

        private void mioForm_Load(object sender, EventArgs e)
        {

        }
    }
}
In più mi viene fuori un errore relativo al Drawing:
Errore 1 Il tipo 'System.Drawing.Size' è definito in un assembly di cui manca il riferimento. Aggiungere un riferimento all'assembly 'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. c:\users\antonello\documents\visual studio 2010\Projects\Project10\Project10\mioForm.cs 24 13 Project10
Errore 2 Il tipo o il nome dello spazio dei nomi 'Drawing' non esiste nello spazio dei nomi 'System'; probabilmente manca un riferimento a un assembly c:\users\antonello\documents\visual studio 2010\Projects\Project10\Project10\mioForm.cs 24 42 Project10
Introduco il riferimento a Drawing...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
Adesso funziona di nuovo.
Bene.
Il codice che si genera automaticamente una volta che viene fatto "partire" il form è:
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // mioForm
            // 
            this.ClientSize = new System.Drawing.Size(284, 261);
            this.Name = "mioForm";
            this.Load += new System.EventHandler(this.mioForm_Load);
            this.ResumeLayout(false);

        }

        private void mioForm_Load(object sender, EventArgs e)
        {

        }
ossia il codice che inizializza il Form.
Però questo codice non viene eseguito all'atto della creazione del form.
Provo a cambiare il tipo di applicazione da "Applicazione Console" a "Applicazione WindowsForm" e ugualmente noto che il codice non viene eseguito, in quanto se cambio i parametri non risultano modificati.
Cambio le dimensioni del form:
        private void InitializeComponent()
        {
            this.SuspendLayout();
            
            // 
            // mioForm
            // 
            this.ClientSize = new System.Drawing.Size(584, 261);
            this.Name = "mioForm";
            this.Load += new System.EventHandler(this.mioForm_Load);
            this.ResumeLayout(false);

        }

        private void mioForm_Load(object sender, EventArgs e)
        {
           
        }
e il form mi viene sempre delle dimensioni standard.
Dunque devo ricreare il costruttore del form e metterci dentro la chiamata a InitializeComponent():
    class mioForm:Form
    {

        public mioForm()
        {
            InitializeComponent();
        }

        public static void Main()
        {
            mioForm frm = new mioForm();
            Application.Run(frm);
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            
            // 
            // mioForm
            // 
            this.ClientSize = new System.Drawing.Size(584, 261);
            this.Name = "mioForm";
            this.Load += new System.EventHandler(this.mioForm_Load);
            this.ResumeLayout(false);

        }

        private void mioForm_Load(object sender, EventArgs e)
        {
           
        }

        
    }
e adesso il form mi viene delle nuove dimensioni!


sabato 6 dicembre 2014

Pagina web di riferimento

Il device è quello che dà accesso diretto all'adattatore grafico.
Diretto accesso all'hardware.
Ovviamente, il device va dichiarato.
E su questo non abbiamo problemi.
namespace WindowsFormsApplication12
{
    public partial class Form1 : Form
    {
        private Device device;

        public Form1()
        {
            InitializeComponent();
            
        }

        static void Main()
        {
            
            Application.Run(new Form1());
        }
        private void Form1_Load(object sender, EventArgs e)
        {
        
        }     
    }
}
Bene.
Una volta dichiarato, come per tutte le variabili, bisogna istanziarlo.
Quindi sarà d'obbligo usare qualcosa tipo device = new Device(....).
Vediamo come.
Credo che sia il caso di istanziarlo nel costruttore.
mmmhhh... mi sa che qui viene istanziato nel metodo Main...
Ma andiamo per gradi.
Il costruttore del Device richiede come parametri PresentationParameters, e quindi viene creato un metodo InitializeDevice che setta i parametri e inizializza il device.
        public void InitializeDevice()
        {
            PresentParameters presentparams = new PresentParameters();
            presentparams.Windowed = true;
            presentparams.SwapEffect = SwapEffect.Discard;

            device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparams);
        }
Ecco, i parametri vanno inizializzati soltanto relativamente ad "applicazione a finestra", ossia non fullscreen, e a "scartare lo swapeffect", che a quanto ho capito consiste nello scrivere nel dispositivo mediante un buffer che viene presentato a runtime.

Quindi il costruttore del device richiede una serie di parametri, che magari vedo successivamente.
Per il momento mi basta aver dichiarato e istanziato il device con questi due pezzi di codice: la dichiarazione nel contesto delle variabili del form e l'istanziazione (inizializzazione) nel contesto del metodo InitializeDevice().
Ora inserisco il richiamo al metodo InitializeDevice() nel metodo Main() e poi avvio, e funziona.
C'è solo un form, uno stupidissimo form del tutto normale. Però dovrebbe essere stato creato un device.
Mi fido sulla parola!

venerdì 5 dicembre 2014

Ora apro un progetto di tipo Windows Form.
Se ci metto una Main come metodo nel form mi crea casini perché dice che è definito più di un punto di ingresso.
Perché?
Ma ecco: cosa ti vedo? Io creo un nuovo progetto di tipo Windows Form e oltre alla classe Form.cs mi si crea automaticamente una classe Program.cs, in cui è comunque contenuto un metodo Main.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication12
{
    static class Program
    {
        /// 
        /// Punto di ingresso principale dell'applicazione.
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
E' qui che sta la Main!
E' questo, il punto di ingresso!
Sperimentiamoci sopra...

    static class Program
    {
        /// 
        /// Punto di ingresso principale dell'applicazione.
        /// 
        [STAThread]
        static void Main()
        {
            MessageBox.Show("Ciao, bello");
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
Ecco, così facendo prima di mostrarmi il Form mi appare la MessageBox con il messaggio "Ciao, bello".
Da notare che il metodo Main è statico, e anche la classe è statica.
Adesso faccio diversamente e metto il Main nel contesto del Form.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication12
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        static void Main()
        {
            
            Application.Run(new Form1());
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}
E si apre regolarmente.
Però per far questo devo eliminare l'altro metodo Main che fa parte della classe statica Program.cs.

mercoledì 3 dicembre 2014

Studio dei rudimenti delle classi in C#

Ho aperto un'applicazione tipo Windows Form.
Ecco cosa mi trovo:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication9
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}
Ora, anziché fare iniziare il programma dal Form, voglio farlo iniziare con una Main.
Come fare? Credo che qui si possano solo creare classi...

Ecco, la cosa mi è stata risolta in parte automaticamente.
Se ho una classe da cui far partire il programma, essa dovrà essere static ed essere messa in un modulo a parte che abbia lo stesso nome della classe.
Ecco il modulo inizio.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;

namespace WindowsFormsApplication9
{
    static class Program
    {

        static void Main()
        {
            MessageBox.Show("Ciao mondo crudele");
            Form1 ciccio=new Form1();
            ciccio.BackColor = Color.Green;
            Application.Run(ciccio);

        }
    }
}
E questo è il modulo del Form1, Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication9
{
    partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }

    public class inizio
    {
        void Main()
        {
            MessageBox.Show("Ciao mondo crudele");
        }
    }
}

Il metodo Main della classe inizio.cs istanzia un oggetto di tipo Form1, lo colora di verde e lo mostra dopo aver esibito una MessageBox:
        static void Main()
        {
            MessageBox.Show("Ciao mondo crudele");
            Form1 ciccio=new Form1();
            ciccio.BackColor = Color.Green;
            Application.Run(ciccio);

        }
    }
Cominciamo a "quagliare"...

Brancolando nel buio con il DirectX senza un'adeguata preparazione sul C#

Credo di aver trovato un tutorial piuttosto valido...

Cominciamo a seguirlo, tentando di ricordare e rafforzare il mio approccio di apprendimento...




Per prima cosa, stando al tutorial, devo aprire un progetto di C# tipo Window...
Proviamo...
Fatto.

Ora aggiungiamo i riferimenti.
Fatto.
Inseriamo le linee di codice per l'uso delle librerie referenziate.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace DirectX
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}
Bene.
Adesso il tutorial dice di variare le dimensioni del form e il suo nome... giusto a titolo di esercizio.
Facciamolo.
Si fa dal metodo InitializeComponents(). Ora, InitializeComponents viene chiamato dal costruttore del form, ma non è presente sul modulo principale del form, bensì su quello chiamato Designer,dove c'è l'altra parte della partial class del Form...
Lo apro e ce lo trovo...
namespace DirectX
{
    partial class Form1
    {
        /// 
        /// Variabile di progettazione necessaria.
        /// 
        private System.ComponentModel.IContainer components = null;

        /// 
        /// Liberare le risorse in uso.
        /// 
        /// ha valore true se le risorse gestite devono essere eliminate, false in caso contrario.
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Codice generato da Progettazione Windows Form

        /// 
        /// Metodo necessario per il supporto della finestra di progettazione. Non modificare
        /// il contenuto del metodo con l'editor di codice.
        /// 
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 261);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }

        #endregion
    }
}
Provo a modificare, in questo metodo, i parametri.
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(500, 500);
            this.Name = "Form1";
            this.Text = "Form del cavolo";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }
Nessun problema...

Adesso mi dice di modificare la Main...

Bene, ho problemi perché avendo aperto un'applicazione tipo Windows non ho una Main...

Retrocediamo e studiamo un po' come si può avere un inizio da una Main che istanzia un form, anziché da un form stesso.

lunedì 1 dicembre 2014

Primi passi con il device (DirectX) in C#

Diamo una definizione di polimorfismo.
Un oggetto di un tipo può assumere valori di un tipo derivato dal suo tipo.
Un parametro di un certo tipo può essere sostituito da un parametro di un tipo derivato.

Dunque quando nel metodo OnPaint di un oggetto di classe derivata da form si mette la parola chiave override questo significa che questo metodo overridda (scavalca) quello della classe base.

Questo OnPaint è un metodo, non un evento.

Ma adesso trovo un codice diverso che non fa uso di OnPaint...

Il nucleo di questo codice è:
        static void Main()
        {
            MioForm frm = new MioForm();
            frm.initGraphics();

            frm.Show();

            while(frm.Created){
            frm.Render();
            Application.DoEvents();
            }
            
        }

La prima riga del metodo non fa altro che istanziare un nuovo frm di classe MioForm la quale è una classe derivata da Form.
Quindi chiama initGraphics che è il metodo nel quale viene creato il device.
        void initGraphics()
        {
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;

            dispositivo = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);
        }
Quindi si mostra il form, semplicemente:
frm.Show();
e quindi si usa frm.Created.
Che roba è?
Mentre il controllo esiste, si eseguono le successive istruzioni comprese fra parentesi graffe...
Se provo a sostituire while con if, il form sparisce, probabilmente perché la condizione di esistenza del form viene verificata solo una volta.
            while(frm.Created){
            frm.Render();
            Application.DoEvents();
            }


Quindi riassumendo inizialmente si crea il device, quindi si mostra il form e mentre il form esiste si esegue il metodo Render, che "aziona" il device evocandone dei metodi che portano al mostrare il form con certe caratteristiche...

Cominciamo a decifrare...