Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1

    [VB 2010 winform] classe graphics

    Ciao!

    Sono fermo da giorni (ai neofiti capita di aprire per giorni il codice, guardarlo per ore, e poi richiudere senza aver aggiunto neanche una riga di codice) cercando di capire come si usa la classe graphics. In sostanza devo creare delle linee sull'oggetto time_base che è un panel. Questo panel, insieme a molti altri, e all'interno di un'altro panel (timetable) che funge un pò come contenitore (ho scelto il panel come contenitore perchè mette la barra di scorrimento in automatico). Tuttavia se faccio le line da progettazione con lineshape sull'oggetto timetable, le linee non vengono coperte dall'oggetto time_base, ma nel momento in cui ci draggo e ci muovo un oggetto è come se passassi una gomma da cancellare. Allora dico, le disegno in fase di programmazione sull'oggetto time_base.. ma non compare neanche un pixel. Il mio obbiettivo sarebbe quella di far scivolare l'oggetto che draggo su time_base, sotto le linee che dovrebbero essere visibili anche sopra l'oggetto che sposto. Penso di non essermi spiegato bene.. devo fare una griglia orario tipo la guida tv di sky; solo che ci devono essere delle righe che, per ogni ora, solcano tutti gli oggetti presenti! posto il link..

    http://guidatv.sky.it/guidatv/grid.html


    codice:
     Sub obj_creator()
    
            Dim y As Int16
            Dim k As Int16
            Dim z As Int16
    
            z = 5
            k = 0
            y = 30
            'costruisco tanti oggetti per quante sono le sale. Un texbox (num_posti) per il numero dei posti; 
            'delle label per evidenziare il numero della sala (obj)
            'è3d e èDgt sono dei chekbox per definire se la sala è solo digitale o anche 3d. in mancanza di check
            'significa che la sala è in 35mm
    
            For i = 1 To cinema.Length
                'dichiarazione oggetti
                Dim obj As New Label()
                Dim num_posti As New TextBox
                Dim è3d As New CheckBox()
                Dim èDgt As New CheckBox()
                Dim labsal As New Label
                Dim time_base As New Panel
                Dim pansal As New Panel
    
    
                'costruzione oggetti sul controllo voluto: in questo caso panel1
                Me.Panel1.Controls.Add(obj)
                Me.Panel1.Controls.Add(num_posti)
                Me.Panel1.Controls.Add(è3d)
                Me.Panel1.Controls.Add(èDgt)
                Me.timetable.Controls.Add(time_base)
                Me.timetable.Controls.Add(labsal)
    
                'definizione delle proprietà degli oggetti
                num_posti.Left = num_posti.Left + 130
                num_posti.Name = "num_posti" & i
                num_posti.Width = 50
                num_posti.Text = cinema(i - 1).capienza
                num_posti.Top = y
                'chiamata della funzione necessaria nel momento in cui l'utente compila gli oggetti
                AddHandler num_posti.TextChanged, AddressOf inputposti_change
    
                'label con numero sale
                obj.Top = y
                obj.Left = obj.Left + 10
                obj.BackColor = Color.Orange
                obj.Name = "obj" & i
                obj.Text = "sala " & i
                obj.TextAlign = ContentAlignment.MiddleCenter
    
                'checkbox se è 3D
                è3d.Top = y
                è3d.Width = 50
                è3d.Left = 250
                è3d.Name = "è3d" & i
                è3d.Text = "3D"
                è3d.Checked = cinema(i - 1).s3d
                AddHandler è3d.Click, AddressOf verifica3d_click
    
                'checkbox se è Dgt
                èDgt.Top = y
                èDgt.Left = 350
                èDgt.Text = "Dgt"
                èDgt.Name = "èDgt" & i
                èDgt.Checked = cinema(i - 1).sdg
                AddHandler èDgt.Click, AddressOf verificaDgt_click
    
                'time_base
                With time_base
                    .Top = k
                    .Left = 60
                    .Name = "time_base" & i
                    .BackColor = Color.LightYellow
                    .BorderStyle = BorderStyle.FixedSingle
                    .Width = 1490
                    .Height = 50
                    .AllowDrop = True
                    Dim p As New Pen(Brushes.Black, 2)
                    time_base.CreateGraphics.DrawLine(p, 25, 25, 1490, 25)
    
                    AddHandler time_base.DragEnter, AddressOf time_base_DragEnter
                    AddHandler time_base.DragDrop, AddressOf time_base_DragDrop
    
                End With
    
                'numero di sala della time table
                With labsal
                    .Top = k
                    .Left = 0
                    .Height = 50
                    .Name = "labsal" & i
                    .BorderStyle = BorderStyle.FixedSingle
                    .BackColor = Color.Azure
                    .Text = "SALA  " & i & vbCr & "posti: " & cinema(i - 1).capienza
                    If cinema(i - 1).s35mm = True Then
                        .BackColor = Color.Violet
                    ElseIf cinema(i - 1).s3d = True Then
                        .BackColor = Color.Gold
                    ElseIf cinema(i - 1).sdg = True Then
                        .BackColor = Color.Cyan
                    End If
                End With
    
                'panel per area sala
                With pansal
                    .Top = z
                    .Left = 60
                    .AutoScroll = True
                    .Height = 40
                    .Width = 220
                    .AllowDrop = True
                    .Name = "pansal" & i
                    .BackColor = Color.Lavender
                End With
    
    
    
                k = k + 50
                y = y + 30
                z = z + 50
            Next i
            MessageBeep(0)
        End Sub
    ringrazio tutte le anime pie che sono arrivate a leggere fin qui

  2. #2
    In Windows Forms il disegno nell'area del controllo avviene mediante l'evento Paint, che viene automaticamente invocato dal sistema operativo tutte le volte lo ritenga necessario (per esempio quando sposti la finestra o fai operazioni di drag sopra essa). Il sistema che hai usato tu (time_base.CreateGraphics.DrawLine) è invece esterno all'evento Paint e di conseguenza funziona solo all'atto della creazione del controllo.

    Io procederei in maniera un po' diversa rispetto a quello che hai fatto tu, anche se all'inizio ti potrebbe sembrare un sistema un po' ostico. Si tratta di creare un UserControl all'interno del tuo progetto oppure un progetto separato di tipo Windows Forms Control Library.
    Un esempio di disegno tramite l'evento Paint:
    codice:
        Private Sub UserControl1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            e.Graphics.DrawLine(Pens.Black, 0, 0, Me.Width, Me.Height)
        End Sub
    Per una migliore resa grafica in questi casi è consigliabile impostare la proprietà dello UserControl DoubleBuffered=True.
    Chi non cerca trova.

  3. #3
    Grazie Tas,

    E' un punto di partenza per studiare la problematica.

  4. #4
    Utente di HTML.it L'avatar di Vinsent
    Registrato dal
    May 2011
    Messaggi
    314
    Ho un problema simile e per risolverlo è venuto fuori un' accrocchio indicibile...quindi un grazie anche da parte mia per Tas!
    Come fatto notare il problema stà nella creazione e nel disegno dei vari panel, se dopo time_base.CreateGraphics.DrawLine metti Threading.Thread.Sleep(1000) puoi vedere che la linea viene creata ma alla fine scompare. Quindi dovresti scriverla dopo aver creato il tutto, non mi ricordo come si fa a richiamare il singolo tipo di controllo ma dovrebbe essere qualcosa del genere:
    codice:
        Private Sub disegna_linea()
            For a = 0 To timetable.Controls.Count - 1 Step 1
                Dim p As New Pen(Brushes.Black, 2)
                timetable.Controls(a).CreateGraphics.DrawLine(p, 25, 25, 1490, 25)
            Next
        End Sub
    poi nasce il problema se scrolli il panel principale, minimizzi la finestra, ecc, le linee fuori dalla visuale scompaiono, per ognuno di questi eventi dovresti fare il refresh dei panel e richiamare la sub sopra...

  5. #5
    alla fine ho risolto cosi (vedi codice).. ma ho alcune domande.

    - quando ci si riferisce a usercontrol, si parla di un controllo creato da codice (come in questo caso time_base che è dichiarato prima con dim time_base as new panel), o è un controllo costruito ad hoc partendo dai controlli base?

    - Ho costruito la griglia, ma il controllo (una label) che viene trascinato non passa sotto ma va sopra la griglia stessa. Vabbè pazienza.. non credo proprio sia possibile e in fin dei conti se un giorno riuscirò a finire sto programma spero che non lo usino dei cretini.. ma se ora volessi creare una linea verticale che passi per la coordinata left del controllo, che si sposti con il trascinamento dell'oggetto, e che quindi, vada dalla parte alta alla parte bassa del contenitore di time_base (un'altro panel che contiene tutti i panel time_base), lo potrei fare?
    in sostanza riprendendo ad esempio la pagina di sky, ogni inizio e fine film dovrebbero avere una linea che attraversa tutto il contenitore sovrapponendosi agli altri film.. questo mi sarebbe necessario per capire quando dei film partono insieme e a che ora.. in sostanza il fulcro di tutto il programma. Secondo voi, si può fare? e soprattutto, questa domanda non ve la potevo fare prima di iniziare tutto quanto?

    codice:
     With time_base
                    .Top = k
                    .Left = 60
                    .Name = "time_base" & i
                    .BackColor = Color.LightYellow
                    .BorderStyle = BorderStyle.FixedSingle
                    .Width = 1490
                    .Height = 50
                    .AllowDrop = True
                    Dim p As New Pen(Brushes.Black, 2)
                    Me.timetable.CreateGraphics.DrawLine(p, 15, 15, 150, 150)
                    time_base.CreateGraphics.DrawLine(p, 25, 25, 1490, 25)
    
                    AddHandler time_base.DragEnter, AddressOf time_base_DragEnter
                    AddHandler time_base.DragDrop, AddressOf time_base_DragDrop
                    AddHandler time_base.Paint, AddressOf time_base_Paint
    
                End With
    
       Private Sub time_base_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
            Dim p As New Pen(Brushes.Peru, 3)
    
            p.DashStyle = DashStyle.DashDotDot
            For i = 60 To 1440
                e.Graphics.DrawLine(p, i, 0, i, 50)
                i = i + 60
            Next
    
        End Sub

  6. #6
    Utente di HTML.it L'avatar di Vinsent
    Registrato dal
    May 2011
    Messaggi
    314
    Provato con Bringtofront?

  7. #7
    caspita ho capito.. il programma disegnava tutto, ma poi la eliminava..

    con timetable.controls.cont individui i controlli nel contenitore?

    cmq grazie vinsent.. grazie al tuo codice ho come avuto l'intuizione per riuscire a far si che due controlli che vengono trascinati su time_base si accorgtano della presenza dell'altro e quindi non scorrano uno sotto l'altro... altro elemento fondamentale che deve avere questo programmino..



    Originariamente inviato da Vinsent
    Ho un problema simile e per risolverlo è venuto fuori un' accrocchio indicibile...quindi un grazie anche da parte mia per Tas!
    Come fatto notare il problema stà nella creazione e nel disegno dei vari panel, se dopo time_base.CreateGraphics.DrawLine metti Threading.Thread.Sleep(1000) puoi vedere che la linea viene creata ma alla fine scompare. Quindi dovresti scriverla dopo aver creato il tutto, non mi ricordo come si fa a richiamare il singolo tipo di controllo ma dovrebbe essere qualcosa del genere:
    codice:
        Private Sub disegna_linea()
            For a = 0 To timetable.Controls.Count - 1 Step 1
                Dim p As New Pen(Brushes.Black, 2)
                timetable.Controls(a).CreateGraphics.DrawLine(p, 25, 25, 1490, 25)
            Next
        End Sub
    poi nasce il problema se scrolli il panel principale, minimizzi la finestra, ecc, le linee fuori dalla visuale scompaiono, per ognuno di questi eventi dovresti fare il refresh dei panel e richiamare la sub sopra...

  8. #8
    Originariamente inviato da eternauta
    alla fine ho risolto cosi (vedi codice).. ma ho alcune domande.

    - quando ci si riferisce a usercontrol, si parla di un controllo creato da codice (come in questo caso time_base che è dichiarato prima con dim time_base as new panel), o è un controllo costruito ad hoc partendo dai controlli base?
    Per usercontrol intendevo proprio... usercontrol
    Lo puoi aggiungere al progetto col menu Project/Add User Control.

    Una volta compilato il progetto ti ritroverai una nuova icona nella toolbox che ti permetterà di inserire il tuo nuovo controllo nel form, allo stesso modo con il quale inserisci tutti gli altri controlli predefiniti di VB.

    Come ti ho già accennato nel messaggio precedente, io sposterei tutta la complessità del disegno della griglia e dei box all'interno dello usercontrol. Eviterei di usare, all'interno dello usercontrol, ulteriori componenti (Label ecc.) ma lascerei fare tutto all'evento Paint usando le primitive messe a disposizione dall'oggetto Graphics (linee, sfondi, testi, ecc.). Devi ovviamente progettare una serie di proprietà con le quali il form che ospita il tuo usercontrol possa interagire con esso. Ecco un abbozzo di usercontrol:
    codice:
    Public Class GrigliaProgrammi
        Private _canali As Canali
    
        Public ReadOnly Property Canali() As Canali
            Get
                Return _canali
            End Get
        End Property
    
        Public Sub New()
    
            ' This call is required by the designer.
            InitializeComponent()
    
            ' Add any initialization after the InitializeComponent() call.
            _canali = New Canali
        End Sub
    
        Private Sub GrigliaProgrammi_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            'disegna la timeline
            '...
    
            'disegna le righe dei canali
            If _canali.Count > 0 Then
                For Each c As Canale In _canali
                    'disegna box con il nome del canale
                    '...
    
                    'disegna i box dei vari programmi
                    For Each ev As Evento In c.Eventi
                        '...
                    Next
                Next
    
            End If
        End Sub
    End Class
    
    Public Class Canale
        Private _eventi As Eventi
    
        Public Property ID As Integer
        Public Property Descrizione As String
        Public ReadOnly Property Eventi As Eventi
            Get
                Return _eventi
            End Get
        End Property
    
        Public Sub New()
            _eventi = New Eventi
        End Sub
    End Class
    
    Public Class Canali
        Inherits List(Of Canale)
    End Class
    
    Public Class Evento
        Public Property Titolo As String
        Public Property Inizio As Date
        Public Property Fine As Date
    
        Public Sub New()
            '
        End Sub
    
        Public Sub New(titolo As String, inizio As Date, fine As Date)
            Me.Titolo = titolo
            Me.Inizio = inizio
            Me.Fine = fine
        End Sub
    End Class
    
    Public Class Eventi
        Inherits List(Of Evento)
    End Class
    Nel tuo form sarà necessario definire alcune proprietà, esempio:
    codice:
    Dim c As Canale
    Dim ev As Evento
    
    c = New Canale
    c.ID = 1
    c.Descrizione = "TeleDico"
    
    ev = New Evento("TG24", New Date(2011, 6, 29, 10, 0, 0), New Date(2011, 6, 29, 10, 15, 0))
    c.Eventi.Add(ev)
    
    ev = New Evento("Oroscopo", New Date(2011, 6, 29, 10, 12, 0), New Date(2011, 6, 29, 10, 18, 0))
    c.Eventi.Add(ev)
    
    GrigliaProgrammi1.Canali.Add(c)
    Chi non cerca trova.

  9. #9
    ok.. ho capito il suggerimento di Tas e ho dedicato tutto oggi (non ho dato da mangiare neanche ai gatti) per capire come costruire un usercontrol che mi aiutasse. Ho capito che se riesco a proggettarli bene, infatti me ne servirà un'altro oltre a questa griglia temporale (quello che tas indica come evento), i miei problemi si ridurranno notevolmente e in fondo, come diceva la mi prof di informatica, per imparare ci devi sbattere la testa .

    quindi ho buttato giù questo:

    codice:
    Imports System.Drawing.Drawing2D
    
    'questo è il mio user control.
    <Serializable()> _
    Public Class griglia
        Public _numero_sale As Integer
        Dim _capienza As Int32
        Dim _s3d As Boolean, _sdg As Boolean, _s35mm As Boolean
    
    
    
        
    
        Public Sub New()
    'questo lo metto perchè lo ha messo tas. è questo il costruttore?
            InitializeComponent()
        End Sub
    
        Public Property numero_sale As Integer
            Get
                Return _numero_sale
            End Get
            Set(ByVal value As Integer)
                _numero_sale = value
            End Set
        End Property
    
        Public Property capienza() As Int32
            Get
                Return _capienza
            End Get
            Set(ByVal value As Int32)
                If value > 0 Then
                    _capienza = value
                End If
            End Set
        End Property
    
        Property s3d() As Boolean
            Get
                Return _s3d
            End Get
            Set(ByVal value As Boolean)
                _s3d = value
            End Set
        End Property
    
        Property sdg() As Boolean
            Get
                Return _sdg
            End Get
            Set(ByVal value As Boolean)
                _sdg = value
            End Set
        End Property
    
        Property s35mm() As Boolean
            Get
                Return _s35mm
            End Get
            Set(ByVal value As Boolean)
                _s35mm = value
            End Set
        End Property
    
        Private Sub Griglia_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            'disegna la timeline
            '...
            Dim p As New Pen(Brushes.Peru, 3)
            Dim y As Integer
            p.DashStyle = DashStyle.DashDotDot
            For i = 60 To 1440
                e.Graphics.DrawLine(p, i, 0, i, 1000)
                i = i + 60
            Next
            y = 5
    'ora, vorrei disegnare un rettangolo (quello che prima era il panel) ogni tre pixel tanti quante sale sono..
            For i = 0 To numero_sale - 1
    y+=3
                e.Graphics.DrawRectangle(Pens.Maroon, 5, y, 50, 1440)
                y += 50
            Next
        End Sub
    End Class
    ecco i miei problemi:

    - cosi come è, quando metto il controllo non crea nessun rettangolo per sala.. certo! le sale glielo posso comunicare solo da codice (io non so prima quante sale deve gestire l'utente finale). Allora, seguendo il totem, ho provato a mettere una proprietà parametrizzata:

    codice:
    Public Sub New(byval numsal)
            InitializeComponent()
            numero_sale=numsal.
        End Sub
    ma guai.. appena porto il controllo sul form, vb mi riempie di parolacce.

    -altra cosa. in:

    codice:
    e.Graphics.DrawLine(p, i, 0, i, 1000)
    1000 è un valore cosi, tanto per metterci qualcosa (la mia prof di info mi avrebbe messo 4) in realtà ci dovrebbe essere il bordo inferiore del controllo.. ma come posso controllare un controllo che non controllo?.. nel senso.. in base al numero di sale l'altezza del controllo varia.. ma griglia.height etc non ha senso per lui!



    Insomma.. vi asscuro che ci sto provando, ma se mi accannate lo capirei. Tuttavia sono decisamente migliorato dal primo post.. no?

    cmq ragazzi che giornata!!

  10. #10
    La firma del costruttore non la devi cambiare, altrimenti salta tutto!
    La comunicazione tra il form e il controllo deve avvenire attraverso delle proprietà pubbliche, mentre ti sconsiglierei di esporre direttamente delle variabili pubbliche (per esempio _numero_sale). L'uso della property permette inoltre di generare delle eccezioni qualora l'utilizzatore del controllo inserisca valori non consentiti (per esempio un numero negativo).

    Riguardo al problema con DrawLine, puoi riferirti alle proprietà dello usercontrol Me.Size, Me.Width, Me.height, Me.ClientRectangle...
    Chi non cerca trova.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.