PDA

View Full Version : [C#] Form Personalizzata


calo182
25-03-2010, 22:47
Salve a tutti!
Questa è la prima discussione che inserisco in questo forum e ne approfitto per salutare e ringraziare chiunque mi risponderà.
Vorrei creare una form con gli angoli smussati...piu o meno come quelli di una tessera...sanitaria...del codice fiscale...
So benissimo che non è una cosa facile...ma se fosse possibile avere una breve guida, o un codice gia compilato e funzionate ve ne sarei infinitamente grato...
Utilizzo C# e le mie conoscenze sono quelli di un ragazzo di quarta informatici...
Vi ringrazio anticipatamente!
Aspetto fiducioso...

atragon
25-03-2010, 23:33
http://bytes.com/topic/c-sharp/answers/256570-how-do-i-create-windows-forms-rounded-corners

MarcoGG
26-03-2010, 00:02
http://bytes.com/topic/c-sharp/answers/256570-how-do-i-create-windows-forms-rounded-corners

Chiamare API da C# per una cosa come questa ?
"CreateRoundRectRgn" ?

E non mi piace nemmeno il consiglio di quel tizio : override di OnPaint ?!
Ma no, basta disegnarla una volta sola, la Form, alla sua creazione.

Io risolverei così :

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

//Selezione e mouse
private bool selezione = false;
private int eXSel = 0;
private int eYSel = 0;

private void Disegna()
{
int rectArcoWidth = 60;
int rectArcoHeight = 60;
System.Drawing.Drawing2D.GraphicsPath contorno = new System.Drawing.Drawing2D.GraphicsPath();

Graphics G = this.CreateGraphics();
contorno.StartFigure();
contorno.AddLine(rectArcoWidth / 2, 0, this.Width - rectArcoWidth / 2, 0);
contorno.AddArc(this.Width - rectArcoWidth, 0, rectArcoWidth, rectArcoHeight, -90, 90);
contorno.AddLine(this.Width, rectArcoHeight / 2, this.Width, this.Height - rectArcoHeight / 2);
contorno.AddArc(this.Width - rectArcoWidth, this.Height - rectArcoHeight, rectArcoWidth, rectArcoHeight, 0, 90);
contorno.AddLine(this.Width - rectArcoWidth / 2, this.Height, rectArcoWidth / 2, this.Height);
contorno.AddArc(0, this.Height - rectArcoHeight, rectArcoWidth, rectArcoHeight, 90, 90);
contorno.AddLine(0, this.Height - rectArcoHeight / 2, 0, rectArcoHeight / 2);
contorno.AddArc(0, 0, rectArcoWidth, rectArcoHeight, 180, 90);
contorno.CloseFigure();
Region R = new Region (new Rectangle(0, 0, this.Width , this.Height));
R.Intersect(contorno);
this.Region = R;
}

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
this.selezione = true;
eXSel = e.X;
eYSel = e.Y;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (this.selezione==true)
{
this.Left -= (this.eXSel - e.X);
this.Top -= (this.eYSel - e.Y);
}
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
this.selezione = false;
}
}

1. Posso ottenere archi di curvatura anche ellittici, giocando con i due valori rectArcoWidth e rectArcoHeight. Unico requisito è avere la Form con FormBorderStyle = None. Il resto lo fa tutto il codice.

2. C'ho già messo il codice per spostarla con il mouse.

3. A quanto sono bravo. :D :O :D

calo182
26-03-2010, 19:55
No no!
Ma che bravo!
Tu sei un grande!
Grazie 1000, veramente MarcoGG grazie cosi :sofico:
Chiaramente anche a atragon per la disponibilità!
Veramento non potevo chiedere di meglio! :) :) :) :D :D

MarcoGG
26-03-2010, 20:19
No no!
Ma che bravo!
Tu sei un grande!
Grazie 1000, veramente MarcoGG grazie cosi :sofico:
Chiaramente anche a atragon per la disponibilità!
Veramento non potevo chiedere di meglio! :) :) :) :D :D

Piccola auto-correzione su svista dovuta a fretta ( e all'ora tarda :D ) sul mio precedente post :
nel metodo Disegna() la riga di codice :
Graphics G = this.CreateGraphics();
può tranquillamente essere eliminata. ;)

calo182
26-03-2010, 20:39
:) grazie ancora!

atragon
26-03-2010, 21:17
Chiamare API da C# per una cosa come questa ?
"CreateRoundRectRgn" ?

E non mi piace nemmeno il consiglio di quel tizio : override di OnPaint ?!
Ma no, basta disegnarla una volta sola, la Form, alla sua creazione.

Io risolverei così :

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

//Selezione e mouse
private bool selezione = false;
private int eXSel = 0;
private int eYSel = 0;

private void Disegna()
{
int rectArcoWidth = 60;
int rectArcoHeight = 60;
System.Drawing.Drawing2D.GraphicsPath contorno = new System.Drawing.Drawing2D.GraphicsPath();

Graphics G = this.CreateGraphics();
contorno.StartFigure();
contorno.AddLine(rectArcoWidth / 2, 0, this.Width - rectArcoWidth / 2, 0);
contorno.AddArc(this.Width - rectArcoWidth, 0, rectArcoWidth, rectArcoHeight, -90, 90);
contorno.AddLine(this.Width, rectArcoHeight / 2, this.Width, this.Height - rectArcoHeight / 2);
contorno.AddArc(this.Width - rectArcoWidth, this.Height - rectArcoHeight, rectArcoWidth, rectArcoHeight, 0, 90);
contorno.AddLine(this.Width - rectArcoWidth / 2, this.Height, rectArcoWidth / 2, this.Height);
contorno.AddArc(0, this.Height - rectArcoHeight, rectArcoWidth, rectArcoHeight, 90, 90);
contorno.AddLine(0, this.Height - rectArcoHeight / 2, 0, rectArcoHeight / 2);
contorno.AddArc(0, 0, rectArcoWidth, rectArcoHeight, 180, 90);
contorno.CloseFigure();
Region R = new Region (new Rectangle(0, 0, this.Width , this.Height));
R.Intersect(contorno);
this.Region = R;
}

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
this.selezione = true;
eXSel = e.X;
eYSel = e.Y;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (this.selezione==true)
{
this.Left -= (this.eXSel - e.X);
this.Top -= (this.eYSel - e.Y);
}
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
this.selezione = false;
}
}

1. Posso ottenere archi di curvatura anche ellittici, giocando con i due valori rectArcoWidth e rectArcoHeight. Unico requisito è avere la Form con FormBorderStyle = None. Il resto lo fa tutto il codice.

2. C'ho già messo il codice per spostarla con il mouse.

3. A quanto sono bravo. :D :O :D

Veramente elegante :) devo dirlo al socio che mi ha passato il link.

MarcoGG
06-04-2010, 10:41
@calo182 : possiamo continuare qui.

Piccola parentesi : ragazzi, lo ripeto per la N-esima volta, non fatemi in pvt richieste che potreste tranquillamente fare in chiaro in un thread...

Pulsante ellittico, o comunque diciamo non rettangolare :
E' semplice, ad esempio con una Label ( che ha l'evento Click() come il Button, e che può essere perfettamente flat, senza bordi o ombreggiature... ).
La label può essere creata e aggiunta alla Form a design.
Anche qui, come per il caso precedente, diffidare di tutti quei "tutorial" che raccomandano cose come l'override dell'evento Paint, o peggio ancora l'accesso ad API esterne. Il semplice ridisegno dei controlli va fatto una volta sola, e può essere effettuato nell'evento Load della Form :

//Ridisegno di label1
System.Drawing.Drawing2D.GraphicsPath contorno = new System.Drawing.Drawing2D.GraphicsPath();
contorno.StartFigure();
contorno.AddEllipse(0, 0, label1.Width, label1.Height);
contorno.CloseFigure();
Region R = new Region(new Rectangle(0, 0, label1.Width, label1.Height));
R.Intersect(contorno);
label1.Region = R;
label1.Cursor = Cursors.Hand;

A questo punto la nostra label1 è un pulsante vero e proprio di forma ellittica, e con tanto di "manina"... :D

Basta solo usare l'evento Click() :
private void label1_Click(object sender, EventArgs e)
{

}
E il gioco è fatto. ;)

calo182
06-04-2010, 10:59
Grazie 1000 ancora una volta, ma che valori devo cambiare per restringere io allargare il bottone?

MarcoGG
06-04-2010, 11:04
Grazie 1000 ancora una volta, ma che valori devo cambiare per restringere io allargare il bottone?

Semplice, vai ad agire da codice su label1.Width e label1.Height. Considera che l'ellisse che in questo caso sarà la Region del controllo, è sempre inscritta nel Rectangle originario del controllo stesso.

calo182
06-04-2010, 11:08
èèèèèèèèèèèè gia!
Grazie! :)

gugoXX
06-04-2010, 11:43
Chiamare API da C# per una cosa come questa ?
"CreateRoundRectRgn" ?
..cut..

MarcoGG, Se non l'avessi ancora fatto ti consiglio di dare uno sguardo a WPF.
Sono sicuro che ci troveresti spunti parecchio interessanti.

MarcoGG
06-04-2010, 14:42
MarcoGG, Se non l'avessi ancora fatto ti consiglio di dare uno sguardo a WPF.
Sono sicuro che ci troveresti spunti parecchio interessanti.

Eh, c'hai ragione. Ammetto di non aver ancora adottato seriamente WPF, sarà perchè ormai dai tempi di VS 2003, mi sono appassionato alle GDI+, arrivando a fare cose "spaziali" ( o "turche", a seconda dei punti di vista :D ), sarà anche che normalmente nelle Form che costruisco cerco sempre di pensare molto alla funzionalità pratica lato-utente e non tanto all'aspetto estetico...
A maggior ragione se qualcuno mi chiede un consiglio sullo shaping di Forms e Controlli, preferibilmente senza uscire dal Windows Forms secco, come in questo caso, ci vado a nozze. :D
Il fatto è che, secondo l'idea comune, sembra che GDI+ sia pesante, e lo credo bene, se c'è una marea di gente in giro che consiglia tecniche come quelle. Andare a scrivere nel Paint() può portare una Form ad essere inutilizzabile, e nel 90% dei casi non è affatto necessario.
Cmq, prima o poi mi ci butterò, anche su WPF... ;)