View Full Version : [VB.NET] Tab control con pulsante di chiusura..
Buonasera,
vorrei creare un Tab Control con un pulsante di chiusura (Tipo Firefox) e nella tabpage vorrei aprire un form.
In Pratica vorrei creare un'applicazione stile MDI solo che quando apro un nuovo form si va a inserire in una TabPages del TabControl con la propria X per la chiusura della scheda.
La mia idea è creare un controllo personalizzato ereditando il TabControl ma non so minimamente come iniziare per creare questo pulsante di chiusura per ogni tab pages.
Per aprire un form nella tabpages ho intensione di utilizzare questo codice:
Dim frmx As New Form3 'o come si chiama il form da inserire nella prima TabPage
frmx.TopLevel = False
frmx.Visible = True
TabPage1.Controls.Add(frmx) 'o come si chiama la prima TabPage
è corretto?
Grazie in anticipo a tutti :help:
E' una richiesta abbastanza... insolita.
Cioè tu hai una Form principale, diciamo Form1, con un TabControl, e ci apri dentro una o più Form, con un codice tipo questo :
Dim TP As New TabPage
TabControl1.TabPages.Add(TP)
Dim F As New Form2
F.TopLevel = False
TP.Controls.Add(F)
F.Show()
E funziona.
E poi vuoi che sulla Form inclusa nella TabPage ci sia un pulsante di chiusura che oltre a chiudere la Form stessa fa sparire anche la TabPage che la contiene ?
E' una richiesta abbastanza... insolita.
Cioè tu hai una Form principale, diciamo Form1, con un TabControl, e ci apri dentro una o più Form, con un codice tipo questo :
Dim TP As New TabPage
TabControl1.TabPages.Add(TP)
Dim F As New Form2
F.TopLevel = False
TP.Controls.Add(F)
F.Show()
E funziona.
E poi vuoi che sulla Form inclusa nella TabPage ci sia un pulsante di chiusura che oltre a chiudere la Form stessa fa sparire anche la TabPage che la contiene ?
Non intendevo proprio questo ma la tua idea non è male ora la domanda è:
è più semplice la tua idea oppure creare un tabcontrol personalizzato con la x per chiudere il tab pages e la form (come l'immagine allegata)?
Ah, ho capito. Tu vuoi il pulsante di chiusura proprio sulla "linguetta" della TabPage, giusto ?
Ah, ho capito. Tu vuoi il pulsante di chiusura proprio sulla "linguetta" della TabPage, giusto ?
sisi giusto :D
Ci sono.
Per fare un test della soluzione predisporre una Form nuova, e aggiungere un controllo TabControl ( TC ), con un certo numero di TabPages.
Predisporre una bitmap 16x16 destinata a rappresentare il simbolo di chiusura ( la X ) : nel mio caso C:\close.bmp.
Codice Form :
Public Class Form1
'Coordinate disegno bitmap di chiusura
Private BMP As New Bitmap("C:\close.bmp") 'Bitmap 16x16
Private coordinateBmp As New Point(20, 5)
'Font per ridisegno Titoli TabControl
Private tcFont As New Font("Arial", 16, FontStyle.Regular, GraphicsUnit.Pixel)
Private titoloTPB As Brush = New SolidBrush(Color.Black)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Proprietà per TabControl
TC.Font = tcFont
TC.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed
For Each TP As TabPage In TC.TabPages
TP.Text = TP.Text.PadRight(25, " ")
Next
'Handler per ridisegno delle TabPages con TabDrawMode.OwnerDrawFixed
AddHandler TC.DrawItem, AddressOf RidisegnaTC
End Sub
Private Sub RidisegnaTC(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs)
Dim R As Rectangle = Me.TC.GetTabRect(e.Index)
Dim titoloTP As String = Me.TC.TabPages(e.Index).Text
e.Graphics.DrawString(titoloTP, tcFont, titoloTPB, New PointF(R.X, R.Y))
e.Graphics.DrawImage(BMP, New Point(R.X + (TC.GetTabRect(e.Index).Width - coordinateBmp.X), coordinateBmp.Y))
End Sub
Private Sub TC_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TC.MouseClick
Dim TPWidth As Integer = TC.GetTabRect(TC.SelectedIndex).Width - coordinateBmp.X
Dim R As Rectangle = TC.GetTabRect(TC.SelectedIndex)
R.Offset(TPWidth, coordinateBmp.Y)
R.Size = New Size(BMP.Width, BMP.Height)
If R.Contains(e.Location) Then TC.TabPages.Remove(DirectCast(TC.TabPages.Item(TC.SelectedIndex), TabPage))
End Sub
End Class
Le jeux son faits. :D
Ovviamente è una soluzione che va ottimizzata.
La cosa migliore sarebbe creare una propria classe che eredita da TabControl, ma per ora l'ho messa giù così, come esempio. ;)
Se hai domande, spara. :)
Marco intanto grazie per il codice adesso ci do un'occhiata e faccio delle prove e poi ti faccio sapere :cool:
Ciao Marco,
grazie molto per l'avvio che mi hai dato.
Ho fatto una classe ereditata dal TabControl ti posto il progetto se per favore ci puoi dare un'occhiata per capire se ho fatto tutto correttamente.
Il progetto lo puoi scaricare da qui: TabControlNew (http://jackvc09.altervista.org/TabControlNew.zip)
Poi continuo sull'aspetto grafico e se mi viene utile inserisco qualche nuova proprieta
grazie ancora aspetto una tua risposta :)
Ciao Marco,
grazie molto per l'avvio che mi hai dato.
Ho fatto una classe ereditata dal TabControl ti posto il progetto se per favore ci puoi dare un'occhiata per capire se ho fatto tutto correttamente.
Il progetto lo puoi scaricare da qui: TabControlNew (http://jackvc09.altervista.org/TabControlNew.zip)
Poi continuo sull'aspetto grafico e se mi viene utile inserisco qualche nuova proprieta
grazie ancora aspetto una tua risposta :)
Mi sa che non ci siamo.
Vedo troppe cose "strane" :
1. Private PuntoPadding As New Point(15, 3)
Non mi spiego il perchè di questa property...
2. Protected Overrides Sub OnDrawItem
Perchè ? Tutto quello che io ho messo nel Form Load va messo nel metodo costruttore della classe ( Public Sub New() ).
Facendo così tu aggiungi un Handler per il ridisegno in OnDrawItem !
Quindi si vanno a creare uno sproposito di Handlers...
3. Questa non va :
For Each test As TabPage In Me.TabPages
Me.Text = Me.Text.PadRight(25, " ")
Next
Che senso ha cambiare il Text del parent N volte per ogni child ?!
Infatti la mia era :
For Each TP As TabPage In TC.TabPages
TP.Text = TP.Text.PadRight(25, " ")
Next
Lo scopo di questo era di dare una spaziatura più o meno uniforme per tutte le "linguette". Inoltre avrebbero la stessa dimensione, rendendo il controllo più elegante...
4. Fonts :
Non capisco perchè hai eliminato l'impostazione interna per la Font.
E poi fai :
e.Graphics.DrawString(titoloTP, Me.Font, titoloTPB, New PointF(R.X, R.Y))
Quando io invece ho fatto :
e.Graphics.DrawString(titoloTP, tcFont, titoloTPB, New PointF(R.X, R.Y))
tcFont ha uno scopo ben preciso. Se usi una bitmap 16x16 non puoi permettere che il testo della linguetta sia corpo 8 !
Ovviamente così il box chiusura uscirà dai bordi... :(
In generale devi farla molto aderente al mio esempio.
E devi accettare il fatto che questo ti impone di ridisegnare il controllo, perciò perdi sempre qualcosa in flessibilità rispetto al controllo standard.
Se vuoi creare una Classe TabControl veramente completa, devi gestire tutti i casi, calcolare la lunghezza delle stringhe dei titoli ( nel senso grafico del termine ), adattare le linguette a diverse dimensioni possibili delle bmp di chiusura ( o vice-versa )... Prevedere Font di ogni tipo... Insomma, è un bel casino. C'è da lavorarci. ;)
Marco grazie ancora una volta per le osservazioni mi metto subito a lavoro e se ho qualche domanda ti scrivo qui..grazie ancora :)
Ciao Marco ho dato uno sguardo al progetto e ineffetti era un pò un disastro penso che è stata distrazione adesso ho corretto tutto ma volevo farti una domanda.
Se io vorrei che quando un tappage prende il focus cambia l'immagine e quando lo perde ritorna com'era?e se voglio anche che al passaggio del mouse sopra la x cambia di nuovo immagine?
per esempio ogni tappage ha l'immagine della x grigia io vorrei che al focus gli carico l'immagine rossa e al passaggio sulla x gli carico l'immagine con la x evidenziata.
E' una cosa fattibile oppure sto andando sul complesso?ho penso un'overrides di OnGotFocus,OnLostFocus,onMouseOver ma non so minimamente come gestire il cambio immagine.
Grazie ancora :help:
Ecco qui il mio TabControl definitivo ( o quasi ;) ) con pulsanti di chiusura.
3 bitmap diverse per ogni situazione.
E già che c'ero gli ho dato una ripulita, perciò sostituisce totalmente la mia soluzione precedente.
Parto sempre dall'esempio Form :
Public Class Form1
'Coordinate/Dimensioni disegno bitmap di chiusura
Private bmpW As Integer = 16
Private bmpH As Integer = 16
Private coordBmp As New Point(20, 5)
'Le bitmap devono avere esattamente le dimensioni bmpW e bmpH !
Private bmpFocusOn As New Bitmap("C:\close_focuson.bmp")
Private bmpFocusOff As New Bitmap("C:\close_focusoff.bmp")
Private bmpHover As New Bitmap("C:\close_hover.bmp")
'Font per ridisegno Titoli TabControl
Private tcFont As New Font("Arial", 16, FontStyle.Regular, GraphicsUnit.Pixel)
Private titoloTPB As Brush = New SolidBrush(Color.Black)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Proprietà per TabControl
TC.Font = tcFont
TC.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed
For Each TP As TabPage In TC.TabPages
TP.Text = TP.Text.PadRight(25, " ")
Next
'Handler per ridisegno delle TabPages con TabDrawMode.OwnerDrawFixed
AddHandler TC.DrawItem, AddressOf RidisegnaTC
End Sub
Private Sub RidisegnaTC(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs)
'Disegno Titoli
Dim R As Rectangle = TC.GetTabRect(e.Index)
Dim titoloTP As String = TC.TabPages(e.Index).Text
e.Graphics.DrawString(titoloTP, tcFont, titoloTPB, New PointF(R.X, R.Y))
'Disegno Bmp Chiusura
If e.State = DrawItemState.Selected Then
e.Graphics.DrawImage(bmpFocusOn, New Point(R.X + R.Width - coordBmp.X, coordBmp.Y))
Else
e.Graphics.DrawImage(bmpFocusOff, New Point(R.X + R.Width - coordBmp.X, coordBmp.Y))
End If
End Sub
Private Sub TC_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TC.MouseClick
Dim R As Rectangle = TC.GetTabRect(TC.SelectedIndex)
Dim rectBmp As New Rectangle(New Point(R.X + R.Width - coordBmp.X, coordBmp.Y), New Size(bmpW, bmpH))
If rectBmp.Contains(e.Location) Then TC.TabPages.Remove(DirectCast(TC.TabPages.Item(TC.SelectedIndex), TabPage))
End Sub
Private Sub TC_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TC.MouseMove
Dim R As Rectangle = TC.GetTabRect(TC.SelectedIndex)
Dim rectBmp As New Rectangle(New Point(R.X + R.Width - coordBmp.X, coordBmp.Y), New Size(bmpW, bmpH))
If rectBmp.Contains(e.Location) Then
TC.CreateGraphics.DrawImage(bmpHover, New Point(R.X + R.Width - coordBmp.X, coordBmp.Y))
Else
TC.CreateGraphics.DrawImage(bmpFocusOn, New Point(R.X + R.Width - coordBmp.X, coordBmp.Y))
End If
End Sub
End Class
:cool:
Ciao MArco ti ringrazio di cuore moltissimo adesso è perfetto :D grazie ancora
Per chiunque fosse interessato all'argomento segnalo questo mio articolo :
Controllo TabControl Personalizzato
(http://forum.masterdrive.it/visual-basic-net-tutorials-and-how-to-36/vb-2008-forms-controllo-tabcontrol-personalizzato-49987/)
;)
Dexter97
13-04-2011, 13:31
Non usare un immagine come questa guida (http://forum.masterdrive.it/visual-basic-net-tutorials-and-how-to-36/vb-2008-forms-controllo-tabcontrol-personalizzato-49987/)?
Non usare un immagine come questa guida (http://forum.masterdrive.it/visual-basic-net-tutorials-and-how-to-36/vb-2008-forms-controllo-tabcontrol-personalizzato-49987/)?
La guida a cui ti riferisci è la stessa che ho linkato al post precedente.
L'autore sono sempre io. ;)
Comunque, in quella guida, NON si fa uso di immagini. I tasti di chiusura vengono "disegnati" a runtime...
Dexter97
14-04-2011, 15:39
La guida a cui ti riferisci è la stessa che ho linkato al post precedente.
L'autore sono sempre io. ;)
Comunque, in quella guida, NON si fa uso di immagini. I tasti di chiusura vengono "disegnati" a runtime...
Infatti, mi potresti dare il solo il codice per disegnare la x please?
Perchè sono ancora alle prime armi della Programmazione.
Grazie delle risposte che mi darete :D
*Questi codici mi servono per il mio browser (http://www.flashbrowser.altervista.org/)
P.S. Questo forum è fantastico!!! Ho trovato moltissime cose che cercavo sopratutto sulla programmazione.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.