Newsgroup: it.comp.lang.visual-basic
Titolo: Di nuovo su ParamArray

Ciao,
ripropongo (e integro) una discussione aperta qualche giorno fa...
Dunque, avrei la necessità di passare l'indirizzo di un ParamArray
tramite PostMessage per poi ricostruire l'array nella WindowProc.
Ora il mio dubbio è questo: tra il momento nel quale recupero
l'indirizzo ed il momento in cui cerco di ricostruire l'array..questo
non viene distrutto perdendo la visibilità?
Cerco di spiegarmi:
Public Sub SendCustomMessage(hWnd As Long,
                             Msg As Long,
                             ParamArray Params() As Variant)
    Dim pVar As Long
    mParams = Params
    pVar = VarPtrArray(mParams)
    PostMessage hWnd, Msg, pVar
End Sub
Una volta terminata questa funzione...mParams non viene distrutto?
Se si ovviamente sono fregato...se uso una Classe CParams anziché un
ParamArray...la cosa non cambia perchè ObjPtr non richiama AddRef e il
mio oggetto verrebbe comunque distrutto!
Potei salvarmi l'array in una collezione usando come chiave il messaggio
(di messaggi non ne ho molti)...ma non mi garba molto!!
Avete qualche suggerimento?
Tnx.
Daniele.
-- 
Free As In Freedom
www.fsf.org

 non viene distrutto perdendo la visibilità?
Tu sei pazzo :)
Prima di tutto, la destinazione è sempre la tua app o è un'app esterna?
Se è esterna ti dico già che secondo me non funzionerà.
Spiego: le due app girano in aree di memoria separate (è questa la roba che 
chiamano "isolated level" o non c'entra un tubo?) che hanno reindirizzamenti 
differenti, quindi se tu passi da un'app all'altra un puntatore (se è un 
valore funziona), questo non si riferisce ad un valore assoluto della 
memoria, ma ad un valore relativo all'area dedicata all'app, cioè lo stesso 
indirizzo per due app diverse puntano a robe completamente diverse.
Comunque, è un pezzo che non uso più Send/PostMessage e non ho voglia di 
adare a guardare sulla guida, ma una delle due è sincrona (credo la 
PostMessage), mentra l'altra è asincrona.
Se questo funziona benissimo in linguaggi "normali", ad es. io l'ho 
verificato in Delphi, con VB mi pare che alla fine tutte e due funzionino in 
modo sincrono o comunque c'è qualcosa che non quadrava.
Premesso questo, e ammesso che funzioni davvero in modo sincrono (quindi la 
variabile continua ad essere nello scope fino al ritorno dalla PostMessage, 
ma qui tu ti sarai già preoccupato di fartene una copia), il problema mi 
pare che resti sempre il fatto che è un po' un problema gestire queste "cose 
strane" di VB come il ParamArray, anche se in realtà dovrebbe essere un 
"semplice" array di variant.
O mi sbaglio e ci sei davvero riuscito? 

 "semplice" array di variant.
Bè, veramente qui il problema è semplicemente lo scope del vettore!
ParamArray non è altro che un tipo SAFEARRAY di OLE Automation...nulla
di così strano!
Se ci sono soluzioni migliori per passare argomenti Variant di numero
variabile tra finestre, io sono tutto orecchi!
Ciao!


> Premesso questo, e ammesso che funzioni davvero in modo sincrono 
A me non serve in modo SINCRONO...altrimenti avrei usato una bella
interfaccia e sarebbe finita lì! ;)
-- 



forse se dici anche che cosa vuoi fare si riesce a darti un
aiuto, viceversa sembra tutta aria fritta.......
Perchè stravolgere la struttura dei parametri (ammesso che si possa fare
senza rischi) di una funzione?
Non e' meglio trovare una soluzione alternativa?


 Non e' meglio trovare una soluzione alternativa?
Ma Certo! Anzi, ne sarei felice.
Dunque, forse in effetti mi sono fasciato un po' la testa.
Ho un'applicazione che può lavorare in rete e può fungere sia da server
che da client (in base alla configurazione)...e qui nulla di strano.
Ora, ho pensato di gestire le modifiche tramite messaggi, mi spiego:
Se modifico (per esempio) un'anagrafica, invio un messaggio a tutte le
finestre per indicare che è avvenuta una modifica e le finestre
interessate reagiranno al messaggio aggiornandosi.
Il messaggio è spedito anche alle altre postazioni e, all'interno della
singola postazione, diramato alle finestre.
Ora, il mio 'problema' nasce dal fatto che devo inviare i messaggi alle
finestre in modalità Asincrona, altrimenti _penso_ che sarebbe troppo
macchinoso...ed avevo pensato di sfruttare il ParmaArray per cercare di
avere un'interfaccia il più unificata possibile: con un semplice
PostMessage facevo tutto.
Ma sono sicuro che ci sono soluzioni migliori e più eleganti...
Spero di essermi spiegato!
Grazie per il supporto!
Daniele.



allora, comincio col dirti che in effetti la PostMessage e' asincrona
e quindi farebbe al caso tuo, ma i parametri non si possono "sconvolgere"...
BOOL PostMessage(
  HWND hWnd,      // handle of destination window
  UINT Msg,       // message to post
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);
se usi dei messaggi custom (WM_USER+),
cio' che conta e' il valore del messaggio, wparam e lparam
possono essere NULL, in questo modo potresti prevedere
una serie di messaggi, dove a ogni messaggio corrisponde
un'azione da compiere da parte dell'applicazione ricevente.
Passare anche i dati attraverso la PostMessage tramite
lparam (che credo sia piu' appropriato di wparam) dovrebbe
essere possibile ma ti complica molto la gestione...fossi
in te mi farei bastare il messaggio e agirei di conseguenza
andando a pescare i dati da un'altra parte.
...piu' di cosi mi pare non si puo!
Ciao


 un'azione da compiere da parte dell'applicazione ricevente.
Infatti è quello che faccio...non voglio 'sconvolgere' i parametri.
In pratica, devo cercare di portarmi dietro (con il messaggio) un
puntatore (memorizzato in lParam) ad un SAFEARRAY (che nel mio caso è
proprio il ParamArray).
A questo punto l'unica via dovrebbe essere fare così:
creo una collezione (che funge da share area) con un elemento per ogni
messaggio e ci memorizzo il ParamArray prima di inviare il messaggio.
Poi nella WindowProc non faccio altro che recuperarmi l'elemento della
Collection associato al messaggio ricevuto.
Anche se questo è macchinoso e _pericoloso_
Cmq, grazie per il supporto!
Ciao!


Occhio che la PostMessage è sì asincrona, nel senso che accoda un messaggio
nella coda della finestra ed esce (mentre la SendMessage attende che sia stato
processato), ma perché la finestra destinazione possa processarlo occorre che ci
sia un doevents da qualche parte (o che il programma sia in idle).
Ricorda che in VB6 hai sempre e soltanto un solo thread (a meno di tecniche
avanzate).
Bye
Raf

 avanzate).
Mmmm... grazie per la dritta Raf, sinceramente a questo non avevo pensato.
Un DoEvents subito dopo la PostMessage potrebbe bastare oppure è meglio
una MsgWaitForMultipleObjects con un tempo di 50-100 ms?



Non ti seguo bene... chiami la PostMessage per non dover aspettare che il
messaggio venga processato e poi ci piazzi subito dopo un DoEvents o una Wait
per attendere che lo sia. Allora tanto valeva usare SendMessage. Anzi
l'interfaccia, così era ancora più semplice.
O c'è qualcosa che mi sfugge?
Bye
Raf

 O c'è qualcosa che mi sfugge?
Mmmm...aspetta...
mi sa che ho fatto io un po' di confusione...facevo i conti senza l'oste!!
Dunque, al momento ogni finestra che vuole ricevere i messaggi deve
implementare un'interfaccia IMessageSink e registrarsi alla classe
dispatcher che la subclassa:
######################################################################
- CMessages.cls -
Implements IHookSink
Dim MsgHandlers As Collection
Public Function AddMsgHandler(MsgSink As IMessageSink)
    'Sublcassing del Form
    MHookMe.HookWindow MsgSink.Handle, Me
    MsgHandlers.Add MsgSink.Handle, CStr(MsgSink.Handle)
End Function
######################################################################
######################################################################
- MioForm -
Implements IMessageSink
Private Sub Form_Load()
   'Mi registro
   MsgDispatcher.AddMsgHandler Me
End Sub
Public Sub IMessageSink_CustomMessageReceived(ByVal Msg As EMessages, _
                                         ParamArray Params() As Variant)
'
End Sub
Public Sub IMessageSink_WindowMessageReceived(ByVal hWnd As Long, _
                                              ByVal Msg As Long, _
                                              ByVal wp As Long, _
                                              ByVal lp As Long)
'
End Sub
Public Property Get IMessageSink_Handle() As Long
    IMessageSink_Handle = Me.hWnd
End Property
######################################################################
Quando Arriva un messaggio per un form, il dispatcher rigira il
messaggio all'interfaccia che il form stesso implementa.
Quindi pensavo che postando i messaggi alle varie finestre uno ad uno,
queste li processassero in maniera asincrona! Ma ciò accadrebbe solo se
vivessero in un Thread separato!!!!! Porca vacca!
######################################################################
Private Function IHookSink_WindowProc(hWnd As Long, _
                                      Msg As Long, _
                                      wp As Long, _
                                      lp As Long) As Long
    Dim RetVal As Long
    On Error GoTo IHookSink_WindowProc_Error
    If Msg > WM_USER  Then
        'E' un messaggio Custom
        MsgHandlers(CStr(hWnd)).CustomMessageReceived Msg, wp, lp
    Else
        'E' un messaggio standard di Windows
        MsgHandlers(CStr(hWnd)).WindowMessageReceived hWnd, Msg, wp, lp
        RetVal = MHookMe.InvokeWindowProc(hWnd, Msg, wp, lp)
        IHookSink_WindowProc = RetVal
    End If
    On Error GoTo 0
    Exit Function
IHookSink_WindowProc_Error:
    Debug.Print "IHookSink_WindowProc", Err.Description
End Function
######################################################################


 se vivessero in un Thread separato!!!!! Porca vacca!
Eh già... però... ti metto questa pulce: una delle tecniche per creare thread
secondari in un programma VB6 richiede che esso sia un EXE ActiveX, mi pare che
sia il tuo caso, no?
Leggi questo articolo:
http://www.fawcette.com/Archives/premier/mgznarch/vbpj/1999/06jun99/cb0699.pdf
Naturalmente questo complica oltremodo il meccanismo già intricato che hai
descritto...
Ciao
Raf

 descritto...
Mmmm..ho esagerato? E pensare che mi sembrava 'elegante'!! :)



Infatti elegante lo è. Anch'io in un'applicazione ho implementato un meccanismo
simile, solo che c'era un bel Timer "alla vecchia" che scandiva periodicamente
la coda dei "messaggi" di ogni finestra. Un multithreading casereccio...
Mi riferivo solo al fatto che se si aggiunge il grado di libertà in più dovuto
al multithreading occorre prestare la massima cautela a deadlock, rientranza,
oggetti condivisi etc...
Bye
Raf

 oggetti condivisi etc...
Bè, si potrebbe creare un oggetto (o controllo) che contenga il codice
per far girare un form in un Thread separato....ma impazzire a quale
scopo?! :)
Cmq, grazie per le dritte!
Adesso vedo come sbucciarmela!!
