Newsgroup: it.comp.lang.visual-basic
Titolo: Creare form a run-time

E' possibile (e come) creare una form a run-time e popolarla di controlli ?
Grazie
Gabriele

 ha scritto nel messaggio
news:381aa...@news.megasys.it...


 popolarla di controlli ?
si: ne crei uno e ne generi un altro con Load [nomecontrollo]
miao

Creare delle finestre è possibile con CreateWindow, ma dopo ti voglio vedere
a gestirle....
Dovresti sublassare tutte le finestre...conoscere esattamente tutti i
messaggi....sapere come funziona internamente Win (non pretendo che tu lo
capisca 8-) eccc...
Auguroni...
--------
Ciao
Sabba

Un form non penso (a meno che non ci sia un mudulo form _già incluso_ nel
progetto), una finestra sì. Avevo descritto tutta la procedura, è complesso ma è
anche un ottimo esercizio (munisciti comunque di una guida alle windows API o
preparati a lunghe ore su MSDN Online, perchè ovviamente l'argomento non si può
esaurire in un messaggio)
-----
COME CREARE UN PROGRAMMA VB
COMPOSTO DA UN SOLO MODULO DI CODICE
Innanzitutto raccogliamo il materiale necessario. Lavoreremo parecchio con le
API, ecco quelle che useremo (ometto le Declare - usate il Visualizzatore API):
CreateWindowEx()
[ in un sistema operativo chiamato Windows, l'avrete capito, le finestre sono
essenziali. Mai più senza ]
ShowWindow()
[ le finestre create con l'API precedente sono restie a mostrarsi. Questa
funzione serve a convincerle ]
DefWindowProc()
CallWindowProc()
[ come le gestisce Windows, le finestre, non le gestisce nessun altro... ]
SetWindowLong()
[ ...ma per certe cose dovremo cavarcela da soli ]
RegisterClass()
UnregisterClass()
[ creiamoci la nostra classe personale di finestre ]
PostQuitMessage()
[ altro che End, gente... ]
Indispensabile infine il Type WNDCLASS. Gradite le Const WS_, WS_EX_ e WM_
Ora che abbiamo le Declare che ci servivano, pensiamo a mettere giù un po' di
codice.
Sub Main()
End Sub
[ questa è indispensabile ]
Function WinProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
WinProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
End Function
[ ecco un esempio di callback. Windows, come vedremo, chiamerà questa funzione
ad ogni evento avvenga sulla finestra che creeremo. La chiamata alla funzione
DefWindowProc rimette il controllo della situazione in mano alle librerie di
Windows. Ad esempio, se il sistema deve ridisegnare la finestra, noi non ci
sporcheremo le mani con un compito così basso e servile, ma lo delegheremo a
Windows ]
Sub Main()
Dim myclass as WNDCLASS
With myclass
.lpfwndproc = Dummy(AddressOf WinProc)
.hInstance = App.hInstance
.lpszClassName = "myclass"
End With
End Sub
Cosa ho fatto? Sto cercando di creare una nuova classe di finestre chiamata
"myclass", e assegno ad una struttura WNDCLASS gli attributi più importanti
della nostra classe: il nome, indispensabile e obbligatoriamente unico, l'handle
dell'istanza dell'applicazione e l'handle della nostra callback, ottenuto
tramite l'operatore AddressOf ed una funzione Dummy, che altro non è se non:
Function Dummy (d As Long) As Long
Dummy = d
End Function
che è un piccolo trucco per salvare un puntatore ricavato con AddressOf in una
variabile
Vediamo se il sistema operativo è pronto ad accogliere la nostra finestra.
retval = RegisterClass(myclass)
Se retval è uguale a 0 al sistema la nostra classe di finestre decisamente non
piace. Non ci resta che arrenderci.
If retval = 0 Then
    End
End If
Proviamo a cambiare nome alla classe, magari usando un nome che nessun serio
programmatore oserebbe usare, del tipo "The Super Duper Window Class". Comunque,
in genere "myclass" va benissimo.
Se il sistema ha gradito, allora procediamo
If retval = 0 Then
    End
Else
    hwnd1 = CreateWindowEx(0, "myclass", "My window", WS_OVERLAPPEDWINDOW _
    , 100, 100, 200, 150, 0, 0, App.hInstance, 0)
End If
Se non funziona, hwnd1 sarà uguale a 0, quindi togliamo il disturbo e
un-registriamo la classe che abbiamo registrato. Se funziona, hwnd1 conterrà
l'handle della finestra creata, quindi, se serve, la mostriamo (nell'IDE
mostratela sempre, o saremo costretti ad usare il pulsante Stop, e il crash sarà
assicurato)
(non vi sto a spiegare tutti gli argomenti di CreateWindowEx, ci sono delle
guide per questo che lo fanno pure meglio di me)
If retval = 0 Then
    End
Else
    hwnd1 = CreateWindowEx(...)
    If hwnd1 = 0 Then
        UnregisterClass "myclass", App.hInstance
        End
    Else
        ShowWindow hwnd1, 1
    End If
End If
Bene. Per ottenere la residenza in memoria, facciamo semplicemente:
Do
DoEvents 'se non ci fosse bisognerebbe inventarlo
If dead Then Exit Do
'dead è una variabile Boolean da definire nelle dichiarazioni del modulo
Loop
--
Function WinProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Select Case uMsg
    Case WM_DESTROY
        'notifichiamo la distruzione della finestra alla Sub Main
        dead = true
        'Lasciamo che Windows distrugga la finestra
        WinProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
    Case Else
        'In tutti gli altri casi lasciamo che se ne occupi Windows
        WinProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
End Select
End Function
Questo significa che quando la finestra viene chiusa, il programma esce dal
Loop, dopodichè:
Do
DoEvents 'se non ci fosse bisognerebbe inventarlo
If dead Then Exit Do
'dead è una variabile Boolean da definire nelle dichiarazioni del modulo
Loop
'De-registriamo la nostra classe
UnregisterClass "myclass", App.hInstance
'Il thread chiede al sistema di ucciderlo e ritornare 0 come valore
PostQuitMessage 0
--
Questo programma ha una sola finestra, nuda. L'ideale se vi serve semplicemente
intercettare messaggi o monitorare il sistema.