Appunti di Programmazione

Creative Commons License

Creiamo un Controllo Utente con VB .Net

Nella creazione di un'applicazione di tipo grafico, mi sono trovato di fronte alla necessità di riunire, in un unico pulsante, più funzionalità, ma mi sono reso conto ben presto che i controlli forniti dall'IDE di Visual Basic 2008 Express non contengono uno strumento adatto ai miei scopi.
Avevo bisogno di fare in modo che più funzioni dello stesso genere fossero raggiungibili e selezionabili attraverso la pressione di un solo pulsante. Pensate ai programmi di grafica o ai CAD dove, ad esempio, i comandi di ZOOM sono molti e ognuno con una specifica azione da svolgere ( Zoom Avanti, Zoom Indietro, Zoom Area, Zoom Tutto...). Collocare queste funzioni all'interno dei menù risulta piuttosto scomodo da usare e aggiungere un'icona per ognuna delle azioni, riempe troppo l'area dello schermo. Ogni applicazione che ha questo tipo di esigenza ha visto implementare in essa una propria soluzione:
Un pulsante che se viene tenuto premuto fa apparire un menù con le scelte possibili.
Un pulsante che se viene tenuto premuto fa apparire una seconda toolbar con tutte le possibili icone.
Un pulsante che se viene premuto fa apparire al centro dello schermo una lista di pulsanti con tutte le possibili opzioni.
...

Personalmente ho pensato di creare un pulsante che permette di cambiare le icone attraverso l'uso della rotellina del mouse o dei pulsanti SU/GIÙ ad esso affiancati. L'idea mi è venuta guardando alcune immagini di Slot Machines trovate in rete.
Allego l'immagine del pulsante finale.

Immagine ScrollButton

Si tratta di creare un button affiancato da 2 piccoli pulsanti, premendo i quali si può vedere scorrere verso l'alto o verso il basso, tutte le icone assegnate a questo controllo, come se fossero disegnate su un rullo e questo potesse ruotare in entrambi i sensi per poterci permettere di scegliere quella che preferiamo. Ovviamente una volta deciso quale funzione utilizzare, il controllo deve essere in grado di capire quale azione deve compiere quando il pulsante viene premuto.
Verrà implementato un unico metodo pubblico che consentirà di inserire le icone/immagini che desideriamo e una breve descrizione delle loro funzionalità.

ATTENZIONE! Il programma può caricare immagini di tipo JPEG, BMP, PNG e ICO, ma non le librerie di icone.

Avviate Visual Basic 2008 Express e create un nuovo progetto di tipo "Applicazione Windows Form", assegnandoli un nome significativo.

Dal menù "Progetto" selezionate la voce "Aggiungi controllo utente..." e nella finestra che appare inserite "ScrollButton" come nome per il proprio controllo.

Impostate le seguenti proprietà:

ScrollButton:
Name:ScrollButton
Margin:0;0;0;0
Maximum Size:60;40 (imposta la dimensione max del controllo impedendo un cambiamento delle sue dimensioni)
Minimum Size:60;40 (come Maximum Size per la dimensione minima)
Size:60;40

Quindi aggiungete 3 Button , un Timer e un controllo ToolTip assegnando loro queste proprietà:

Button1:
Name:btnIcona
Location:0;0
Margin:0;0;0;0
Size:40;40

Button2:
Name:btnUp
Font:Wingdings 3; 8,25pt(o qualunque font che abbia i simboli freccia su e giù)
Location:40;0
Margin:0;0;0;0
Size:20;20
Text:p (o qualunque carattere che nel font scelto rappresenta una freccia rivolta in alto)

Button3:
Name:btnDown
Font:Wingdings 3; 8,25pt(o qualunque font che abbia i simboli freccia su e giù)
Location:40;20
Margin:0;0;0;0
Size:20;20
Text:q (o qualunque carattere che nel font scelto rappresenta una freccia rivolta in basso)

Timer1:
Name:Timer1
Enabled:True
interval:10

ToolTip1:
Name:ToolTip1
BackColor:White
ShowAlways:True
Use Animation:False
Use Fading:False

Inserite il seguente codice:

Public Class ScrollButton

	'Definizione dell'indice dell'immagine Nuova, quella che appare dopo avere premuto i tasti SU/GIÙ o usato la rotellina
	Private intImmagineNuova As Integer = 0

	'Definizione delle due immagini: quella Vecchia che scompare e quella Nuova che appare
	Private immagineVecchia, immagineNuova As Bitmap

	'Definizione delle coordinate Y delle due immagini
	Private yVecchia, yNuova As Integer

	'Impostazione dei flag per determinare se viene fatta scorrere la lista verso l'alto o verso il basso
	Private scorreSu, scorreGiu As Boolean

	'Impostazione del flag per determinare se il mouse è sopra il pulsante (TRUE) o al di fuori di esso (FALSE)
	Private chkFocus As Boolean = False

	'Impostazione del testo da visualizzare come descrizione
	Private testo As String = Nothing

	'Impostazione del flag per determinare se sono state caricate (TRUE) o meno (FALSE) delle immagini nel pulsante
	Private chkListaInserita As Boolean = False

	'Lista che contiene l'elenco delle immagini
	Private _listaImmagini As New ImageList

	'Lista che contiene l'elenco delle descrizioni
	Private _descrizione As New List(Of String)

	'Definizione dell'evento relativo al click del mouse sullo ScrollButton
	Public Event Icona_MouseClick(ByVal nIcona As Integer)

	Public Sub New()

		InitializeComponent()
		_listaImmagini.ImageSize = New Size(32, 32)
		yVecchia = -34
		yNuova = 4

	End Sub

	''' <summary>
	''' Metodo per inserire le immagini da caricare e il relativo testo
	''' </summary>
	''' <param name="img">immagine da caricare</param>
	''' <param name="descr">descrizione allegata</param>
	''' <remarks></remarks>
	Public Sub InserisciImmagini(ByVal img As Bitmap, ByVal descr As String)

		_listaImmagini.Images.Add(img)
		_descrizione.Add(descr)
		immagineNuova = _listaImmagini.Images.Item(0)
		immagineVecchia = immagineNuova
		chkListaInserita = True

	End Sub

	''' <summary>
	''' Metodo per inserire un icona da caricare e il relativo testo
	''' </summary>
	''' <param name="icona">icona da caricare</param>
	''' <param name="descr">descrizione allegata</param>
	''' <remarks></remarks>
	Public Sub InserisciImmagini(ByVal icona As Icon, ByVal descr As String)

		_listaImmagini.Images.Add(icona)
		_descrizione.Add(descr)
		immagineNuova = _listaImmagini.Images.Item(0)
		immagineVecchia = immagineNuova
		chkListaInserita = True

	End Sub

	''' <summary>
	''' Metodo per inserire le immagini da caricare da file e il relativo testo
	''' </summary>
	''' <param name="img"></param>
	''' <param name="descr"></param>
	''' <remarks></remarks>
	Public Sub InserisciImmagini(ByVal img As String, ByVal descr As String)

		_listaImmagini.Images.Add(Image.FromFile(img))
		_descrizione.Add(descr)
		immagineNuova = _listaImmagini.Images.Item(0)
		immagineVecchia = immagineNuova
		chkListaInserita = True

	End Sub

	'Esposizione e consumo dell'evento Icona_MouseClick
	Private Sub btnIcona_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
	Handles btnIcona.MouseClick

		If _listaImmagini.Images.Empty = True Then Exit Sub

		Dim indice As Integer = intImmagineNuova Mod _listaImmagini.Images.Count

		If indice < 0 Then

				indice = _listaImmagini.Images.Count + indice

		End If

		RaiseEvent Icona_MouseClick(indice)

	End Sub

	'Evento per ottenere il focus sul pulsante quando il mouse vi staziona sopra
	Private Sub btnIcona_MouseHover(ByVal sender As Object, ByVal e As System.EventArgs) _
	Handles btnIcona.MouseHover

			Me.btnIcona.Focus()

	End Sub

	'Sub per realizzare l'animazione della rotazione delle immagini con l'uso della rotellina
	Private Sub btnIcona_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
	Handles btnIcona.MouseWheel

		Dim chk As Integer = intImmagineNuova
		immagineVecchia = immagineNuova
		intImmagineNuova += CInt(e.Delta / 120)
		Visualizza()

		If (intImmagineNuova - chk) > 0 Then

				yVecchia = 4
				yNuova = 42
				scorreSu = True

		Else

				yVecchia = 4
				yNuova = -34
				scorreGiu = True

		End If

		ToolTip1.SetToolTip(Me.btnIcona, testo)
		ToolTip1.SetToolTip(Me.btnDown, testo)
		ToolTip1.SetToolTip(Me.btnUp, testo)

	End Sub

	'Sub per determinare l'animazione della rotazione delle immagini con l'uso del pulsante GIÙ
	Private Sub btnDown_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDown.Click

		immagineVecchia = immagineNuova
		intImmagineNuova -= 1
		Visualizza()
		yVecchia = 4
		yNuova = -34
		ToolTip1.SetToolTip(Me.btnIcona, testo)
		ToolTip1.SetToolTip(Me.btnDown, testo)
		ToolTip1.SetToolTip(Me.btnUp, testo)
		scorreGiu = True

	End Sub

	'Sub per determinare l'animazione della rotazione delle immagini con l'uso del pulsante SU
	Private Sub btnUp_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUp.Click

		immagineVecchia = immagineNuova
		intImmagineNuova += 1
		Visualizza()
		yVecchia = 4
		yNuova = 42
		ToolTip1.SetToolTip(Me.btnIcona, testo)
		ToolTip1.SetToolTip(Me.btnDown, testo)
		ToolTip1.SetToolTip(Me.btnUp, testo)
		scorreSu = True

	End Sub

	'Sub per realizzare il movimento di scorrimento verso l'alto o il basso al trascorrere del tempo
	Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick

		If scorreSu Then

				yVecchia -= 2
				yNuova -= 2
				If yVecchia <= -33 AndAlso yNuova = 4 Then scorreSu = False

		End If

		If scorreGiu Then

				yVecchia += 2
				yNuova += 2
				If yVecchia >= 42 AndAlso yNuova = 4 Then scorreGiu = False

		End If

		Me.btnIcona.Invalidate()

		If scorreGiu = False AndAlso scorreSu = False Then Visualizza()

	End Sub

	'Sub per visualizzare le immagini e il testo caricate all'interno del pulsante
	Private Sub Visualizza()

		If chkListaInserita Then

				Dim numeroImmagini As Integer = _listaImmagini.Images.Count
				Dim valore As Integer = intImmagineNuova Mod numeroImmagini

				For i As Integer = 0 To numeroImmagini - 1

					If i = valore OrElse (i - numeroImmagini) = valore Then

						immagineNuova = _listaImmagini.Images.Item(i)
						testo = _descrizione.Item(i)
						Exit For
					End If

				Next

		End If

	End Sub

	'Sub per disegnare le immagini sul pulsante
	Private Sub btnIcona_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
	Handles btnIcona.Paint

		If chkListaInserita Then

				e.Graphics.DrawImage(immagineVecchia, 4, yVecchia, 32, 32)
				e.Graphics.DrawImage(immagineNuova, 4, yNuova, 32, 32)

		End If

	End Sub

End Class

Download sorgente "ScrollButton.zip" ( 169KB )