Newsgroup: it.comp.lang.visual-basic
Titolo: Definire una funzione esterna

Ciao a tutti,
spero di riuscire a spiegarmi....
Stò realizzando un'applicazione in VBA per AutoCAD la quale gira velocemente 
ed esegue il lavoro molto bene se non fosse per il fatto che la reiterazione 
della funzione GetPixel all'interno di un ciclo While causa il *crash* del 
software AutoCAD.
Ho quindi provato a copiare tutto il codice all'interno di VB e con le 
opportune modifiche farlo girare in AutoCAD:
    ................
    Dim acadApp As Object
    Set acadApp = GetObject(, "AutoCAD.Application")
    acadApp.Visible = True
    Dim acadDoc As Object
    Set acadDoc = acadApp.ActiveDocument
    ................
Funziona bene anche in VB e anzi non va in crash!!
tuttavia è molto più lento; rapporto velocità almeno 1/5 e forse anche di 
più...
Ho quindi pensato di mantenere l'applicazione in VBA di AutoCAD e tenere 
solo la parte di codice della funzione GetPixel (utilizzata dentro un ciclo 
while) in un progetto VB. Non so però come fare poi per richiamarlo, dargli 
i parametri necessari e quindi ricavarne il risultato.
Attualmente ho scritto:
Colore = GetPixel(GetDC(0), basePntPixel_X, basePntPixel_Y)
Io vorrei qualcosa del tipo:
Colore = AvviaFileGetPixelExe(GetDC(0), basePntPixel_X, basePntPixel_Y)
Potreste darmi qualche consiglio?
Forse serve un DLL? in questo caso come si fa?
Avete qualche esempio?
Grazie anticipatamente. 

> Grazie anticipatamente.
Visto che nessuno mi ha risposto, e di solito siete sempre molto preparati e 
veloci e vi ringrazierň sempre per questo) penso di aver detto una 
castroneria :-((
Oppure ho chiesto una cosa impossibile?
Grazie 

 ha
scritto:

Hai chiesto una cosa abbastanza difficile, almeno secondo me.
La GetPixel () č un api di windows e normalmente non dovrebbe far crashare il
programma, hai provato a cercare di capire perchč succede, dopo quanti cicli o
se ci sono altre ragioni?
La  GetLastError() puň aiutare
http://msdn.microsoft.com/it-it/library/yb8afh2h(VS.80).aspx
o anche la Err.LastDLLError, come spiega bene qui:
http://www.vbaccelerator.com/home/vb/Tips/Retrieving_the_Error_Message_for_a_Windows_API_Call_Error/article.asp
Poi una volta che hai le idee piů chiare se non va puoi provare a fare una dll,
perň con VB puoi fare solo delle dll ActiveX.
Se vuoi creare dll normali da chiamare con altri programmi qui spiega come fare:
http://www.boondog.com/tutorials/dlltutor/dlltutor.htm
ma io cercherei di capire prima l'errore che hai in VBA.
--
ciao
  Stefano


Ciao Stefano
ti ringrazio moltissimo per la risposta.
Scusami ma non sono un espertissimo di VB....
Ho visto i link che mi hai suggerito e volendo ricavare l'errore, non ho ben 
capito cosa devo fare, ed in questo momento purtroppo non posso effettuare 
delle prove.
Devo inserire il codice che determina l'errore subito dopo la funzione 
GetPixel??
come ho risportato di seguito...
      Colore = GetPixel(GetDC(0), basePntPixel_X, basePntPixel_Y)
      If Err.LastDllError = ERROR_INVALID_WINDOW_HANDLE Then
          MsgBox(ERROR_INVALID_WINDOW_HANDLE_DESCR, Title:="Error!")
      End If
Ho, comunque il dubbio che non riuscirņ a trovare questo errore in quanto va 
in crash, oltre al codice VBA che ho scritto, tutto l'applicativo AutoCAD!
Il crash si verifica circa dopo 6000-8000 cicli.
Grazie 

Il crash si verifica circa dopo 6000-8000 cicli.
potrebbe riempirsi troppo qualche buffer o anche andare in overflow lo stack.
--
ciao
  Stefano

 lo stack.
Traduco in "pricipiantese":
L'API in genere non fà esplodere nulla!
E' come la usi che fa esplodere tutto....!
Un ciclo infinito...prima o poi manda in esaurimento lo stack...e se ti va 
bene ti crasha l'applicazione...se ti va male ti si potrebbe "frizzare" il 
pc!
Ora la domanda sorge spontanea...al di là della singola api....
Tu che cosa vorresti fare?
6000 cicli di cosa?
tra un ciclo e l'altro liberi le risorse liberabili o le tieni in memoria?
6000 cicli di ad esempio traslazione di oggetti vettoriali...il tuo autocad 
li regge???
Io ...avendo un amico architetto con uno studio pieno di codesti 
"aggieggi"....dico che è più probabile che il tuo autocad esploda perchè 
esaurisce le risorse!
Prova a far partire il monitor delle risorse di windows....guarda un po cosa 
si impenna!
-- 
-----------------------------
Mio Blog
http://www.martek.it/dblog/default.asp
Mia città
http://wodka40hall.myminicity.com/

 cosa si impenna!
Il processore lavora, ma non al 100% e la ram è piuttosto libera.
N.B. Lo stesso codice all'interno di VB (e non VBA) funziona bene, se non 
fosse per la sua lentezza rispetto al VBA.
Grazie.

fosse per la sua lentezza rispetto al VBA.
Il VBA all'interno di un altro programma non è proprio come il VB e le sue
risorse disponibili dipendono anche dal programma che ospita la funzione, in
questo caso Autocad.
Per vedere le risorse usate puoi provare ad usare questa tecnica:
http://www.vbaccelerator.com/home/VB/Code/Techniques/Malloc_in_VB/article.asp
che realizza un equivalente della MALLOC che si usa in C per conoscere e
modificare l'uso della ram, non so se in VBA funziona, ma se non sai + cosa
provare...
--
ciao
  Stefano

 termina sempre correttamente.
Cosě facendo continui a richiedere al sistema di generare degli handle per 
il device context del desktop.
E come si sa, gli handle sono una risorsa tutt'altro che inesauribile.
Chiama GetDC(0) una volta sola prima del ciclo for, assegnando il valore di 
ritorno ad un'opportuna variabile di appoggio (es. hDC) che userai nella 
GetPixel.
Alla fine dei loop chiama ReleaseDC(0, hDC), in modo da rilasciare 
correttamente l'handle ottenuto dalla GetDC iniziale.
Bye
Raf

Ho cambiato un paio di cose.
Prova in questo modo:
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal
hdc As Long) As Long
Dim hWndDesk As Long, hDCDesk As Long '<-- Questa
hWndDesk = GetDesktopWindow() '<-- Questa
hDCDesk = GetDC(hWndDesk) '<-- Questa
Dim colorAutoCAD As AcadAcCmColor '<-- Questa
For Each BlockRef In ssSel
    basePnt = BlockRef.InsertionPoint
    basePntPixel_X = PointPixelA.x + ((basePnt(0) - returnPntA(0)) *
PixelForUnit_X)
    basePntPixel_Y = PointPixelA.y + ((basePnt(1) - returnPntA(1)) *
PixelForUnit_Y)
    Colore = GetPixel(hDCDesk, basePntPixel_X, basePntPixel_Y) '<-- Questa
    Red = Colore And &HFF
    Green = (Colore \ &H100) And &HFF
    Blue = (Colore \ &H10000) And &HFF
    Set colorAutoCAD =
AcadApplication.GetInterfaceObject("AutoCAD.AcCmColor.17")
    colorAutoCAD.SetRGB Red, Green, Blue
    BlockRef.TrueColor = colorAutoCAD
    NPix = NPix + 1
    If NPix = NPixMsg Then
        AutoCAD.Application.ActiveDocument.Utility.Prompt vbLf & "Attendere
elaborazione di : " & NPix & " di " & NObj & " blocchi..." & vbLf & vbLf
    NPixMsg = NPixMsg + 500
    End If
    DoEvents
Next
ReleaseDC hWndDesk, hDCDesk '<-- Questa
--
Ciao Fede
By Chicco Production
http://bcp.freetools.it

 3. Riavvio la macro per ulteriori 4000 cicli: risultato *CRASH*
zac
Il "verbo" che è corretto è quello di rafunk....
interpretando in "principiantese"
Umano: 4000 Handle di DC...
PC: Va beh...solo per questa volta eh!
Umano: Forza altri 4000 Handle di DC
PC: ....ue bello ma che fatica mi fai fare!...puff puff!
Umano : Altri 4000 cicli! yuhuuuu! giddap!
PC....aiuto argggggh....non ce la faccio più.....sto task di autocad mi ha 
rotta la ram-zebedei....kill kill process!!!...così impara!
S.O. interviene: Te capì ...faina???!!!!
:o)



Grazie mille Raf (anzi a tutti!!!!!!!!!!!!)
il problema era proprio nel fatto non rilasciavo l'handle.
Ora va tutto alla grande ed ad una velocità impressionante!
Solo un dubbio:
ho provato a scrivere
ReleaseDC(0, hDC)   però mi chiede l"0"
o quindi scritto
a=ReleaseDC(0, hDC) e funziona....
perchè?
Ancora grazie!


Essendo una function, o la chiami così, appunto
    a = ReleaseDC(0, hDC)
oppure come fosse una sub
    ReleaseDC 0, hDC
senza parentesi.
Ciao
Raf 

 senza parentesi.
Hai ragione!!
scusami l'avevo già imparato ma momentaneamente dimenticato :-(
Ancora grazie.