Newsgroup: it.comp.lang.visual-basic
Titolo: [!] visualizzare immagini in scala + scrollbar e [?] come spostare linee e cerchi in una picture box?

ciao a tutti.
sto lavorando all'editor grafico minimale del mio programma per
libretti uso e manutenzione.
l'editor non deve fare un gran che': ricevere un file .gif --l'esploso
su cui lavorare--, visualizzarlo rimpicciolito mantenendo le
proporzioni --le scansioni o i salvataggi fatti al cad sono degli a4 a
300dpi quindi i .gif che apro sono *enormi*-- e permettere di
disegnarci sopra alcuni cerchietti ed alcuni numeri --che sono, poi,
gli indicatori dei componenti nell'esploso--.
una volta disegnati i cerchietti *non* deve salvare il file .gif
modificato: deve solo salvare le coordinate dei cerchietti e dei
numeri --mi e' piu' comodo gestirli nelle successive modifiche--.
ho trovato vagonate di post in rete sulla visualizzazione in scala di
immagini, ma non avevo trovato niente di funzionante per lo
spostamento, tramite una scrollbar, dell'immagine rimpicciolita.
avendo io una certa repulsione verso l'uso di ocx, ho scritto un po'
di codice che funge allo scopo. credo che a qualcuno possa
interessarlo e lo pubblico.
in calce al codice pongo il mio problema.
riassumo il da farsi: ho immagini enormi. in un form voglio
visualizzarle:
- mantenendo le proporzioni
- scalandola di un fattore stabilito dalla dimensione meno
"stringente"
- avendo una sola scrollbar che mi permette di scorrerla lungo l'altra
direzione
per comodita', disegno comunque 2 scrollbar, solo che una delle 2
avra' .max=0, quindi non sara' utilizzabile.
ad esempio, se ho una 5000x1000 pixel e la picturebox e' grande
500x500 pixel, dovro' scalare l'immagine al 50% ed avere una scrollbar
orizzontale. infatti la scala verticale deve essere 1:2 e quella
orizzontale 1:5, quindi scelgo la scala verticale --per sfruttare
tutta l'area disponibile-- e muovo l'immagine lungo l'altro asse
mediante la hscrollbar.
le variabili indicate sono globali perche' mi servono per altre cose
al di fuori di quello di cui parlo in questo post. solo voffset e
hoffset e' necessario che siano globali --del modulo--.
...
'var globali sborellanti
Private HOffset As Long
Private VOffset As Long
Private Immagine As IPictureDisp
Private Altezza As Long
Private Larghezza As Long
Private RapportoAltezze As Single
Private RapportoLarghezze As Single
...
'procedura troppo competitiva
Private Sub HScrollEsploso_Change()
 
    With picEsploso
        HOffset = -HScrollEsploso.Value * Screen.TwipsPerPixelX
        .PaintPicture Immagine, HOffset, VOffset, Larghezza, Altezza
    End With
 
End Sub
Private Sub HScrollEsploso_Scroll()
 
    With picEsploso
        HOffset = -HScrollEsploso.Value * Screen.TwipsPerPixelX
        .PaintPicture Immagine, HOffset, VOffset, Larghezza, Altezza
    End With
 
End Sub
'procedura troppo competitiva
Private Sub picEsploso_OLEDragDrop(Data As DataObject, Effect As Long,
Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim Differenza As Long
Dim AltezzaTW As Long
Dim LarghezzaTW As Long
Dim AltezzaPX As Long
Dim LarghezzaPX As Long
    With picEsploso
 
        Set Immagine = LoadPicture(Data.Files(1))
        AltezzaTW = Immagine.Height
        LarghezzaTW = Immagine.Width
 
        AltezzaPX = AltezzaTW / Screen.TwipsPerPixelY
        LarghezzaPX = LarghezzaTW / Screen.TwipsPerPixelX
 
        RapportoAltezze = Round(AltezzaTW / .Height, 1)
        RapportoLarghezze = Round(LarghezzaTW / .Width, 1)
 
        'assalto alla diligenza: davanti o di fianco?
        If RapportoAltezze > RapportoLarghezze Then
            Larghezza = .Width
            Altezza = .Width / LarghezzaPX * AltezzaPX
            .PaintPicture Immagine, 0, 0, Larghezza, Altezza
            imgAnteprima.Height = 1575
            imgAnteprima.Width = imgAnteprima.Height / AltezzaPX *
LarghezzaPX
            imgAnteprima.Left = 120 + (1335 - imgAnteprima.Width) / 2
            imgAnteprima.Top = 225
 
            Differenza = Int((Altezza - .Height) /
Screen.TwipsPerPixelY)
            With VScrollEsploso
                If Differenza > 0 Then
                    .Max = Differenza
                    .LargeChange = Int(.Max / 15)
                Else
                    .Max = 0
                End If
                HScrollEsploso.Max = 0
            End With
 
        Else
            Altezza = .Height
            Larghezza = .Height * LarghezzaPX / AltezzaPX
            .PaintPicture Immagine, 0, 0, Larghezza, Altezza
            imgAnteprima.Width = 1355
            imgAnteprima.Height = imgAnteprima.Width * AltezzaPX /
LarghezzaPX
            imgAnteprima.Left = 120
            imgAnteprima.Top = 225 + (1575 - imgAnteprima.Height) / 2
 
            Differenza = Int((Larghezza - .Width) /
Screen.TwipsPerPixelX)
            With HScrollEsploso
                If Differenza > 0 Then
                    .Max = Differenza
                    .LargeChange = Int(.Max / 15)
                Else
                    .Max = 0
                End If
                VScrollEsploso.Max = 0
            End With
 
        End If
 
        Set imgAnteprima.Picture = LoadPicture(Data.Files(1))
 
    End With
 
'Clipboard.Clear
'Clipboard.SetData Form1.Picture2.Picture
'Form2.Picture1.Picture = Clipboard.GetData(2)
'Savepicture Form2.Picture1.Picture "c:\save.bmp"
 
 
End Sub
...
naturalmente, vscrollbar funziona in modo analogo a hscrollbar
cambiando asse.
ora veniamo al mio problema.
su questa immagine devo disegnare alcuni cerchietti. diciamo che
saranno praticamente sempre meno di 100. dentro ad ogni cerchietto ci
sara' un numero progressivo.
essendo lo scroll dell'immagine gestito a mano, ogni volta che scrollo
ridisegno l'immagine "di sfondo" a mano. questo non so quanto sia
lento o veloce, comunque e' apparentemente accettabile --sul mio pc
domestico molto veloce: in ufficio devo ancora verificare--. il
ridisegno dello sfondo mi richiede, pero', anche il ridisegno di tutti
i cerchietti ed i numeri introdotti fin'ora, che potrebbero essere,
come dicevo, molte decine. questo, probabilmente, diventa bello
pesantuccio per il sistema. l'autoredraw=true della picturebox non mi
aiuta perche' l'immagine di sfondo viene disegnata col .paintpicture
piuttosto che con il set .picture = blabla per scalarla, quindi...
avete idee piu' performanti? qualsiasi suggerimento? indicazioni per
il totip di domani? una sestina vincente per il superenalotto?
per ora ringrazio per la vostra attenzione.
saluti.
-- 
Gianni Rondinini
Icem s.r.l.
Tel: 
+39 0545 78036
Fax: 
+39 0545 78727

 numeri
Il tuo post è veramente Km, quindi magari non ho capito benissimo
l'esigenza, ma ti dico come farei io:
Usa una PictureBox grande quanto vorresti fosse grande la tua Gif.
Sulla PictureBox metti:
   una Image in cui caricare la Gif e demanda a lei il resize della Gif
   un array di shape Tonde (trasparenti) per i cerchietti.
   un array di Label (trasparenti, con AutoSize=True) per i numerini (usando
il font giusto).
Per scrollare, limitati a spostare la PictureBox lungo l'asse X e Y e tutto
il resto gli va dietro automaticamente.
Ecco fatto. :-)
Ciao
*Roby*

il font giusto).
ho provato anche la tua soluzione. rispetto a quella che avevo pensato
io e' un po' piu' lenta, anche se molto piu' comoda, perche' i
controlli vengono spostati dal sistema. per il momento, quindi,
mantengo la mia precedente, ma ti ringrazio per il suggerimento.
riassumendo, allo stato attuale, faccio cosi'.
solo una volta, al caricamento:
- metto in una var l'immagine da caricare
- guardo quanto e' larga e alta
- vedo se mi conviene trattarla come immagine alta oppure larga
- ridimensiono form e picturebox per avere un fattore di scala intero
--1, 2, 3, 50, ecc...--: il ridisegno dell'immagine sara' piu' preciso
e veloce rispetto a scale frazionarie, tipo 1.2, 3.9, 6.4
- visualizzo l'immagine in scala
- nascondo la scrollbar che non mi interessa usare
- calcolo il valore max dell'altra scrollbar
- calcolo l'incremento in pixel per ogni scroll della scrollbar attiva
ad ogni scroll:
- ridisegno nella picturebox spostata di un certo offset --verticale
od orizzontale a seconda del tipo di immagine alta o larga--
- ridisegno nella picturebox i cerchietti con picturebox.circle
- scrivo dentor al cerchietto con picturebox.print numero
ho provato e fino a 70/80 numeri il tempo di ridisegno e' trascurabile
--sulla mia macchina-- piu' di 70/80 non ho avuto la pazienza di farli
;)
vi faro' sapere i risultati.
ciao e grazie ancora.
