Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Come aprire più documenti con una sola istanza attiva

ciao a tutti
ho fatto una applicazione multi document, e ho creato l'associazione dei
file di input con l'applicazione stessa, per cui al doppio click sul file
parte correttamente il programma.
Il mio problema sorge quando, con il programma attivo, si vuole aprire
un'altro documento facendo doppio click sul file relativo.
Non voglio che parta una seconda istanza dell'applicazione, ma che sia
l'stanza attiva a recepire l'intenzione di aprire il documento.
Il problema l'ho risolto in un modo un po particolare, mettendo un timer che
controlla una chiave di registro. In pratica il programma controlla se
esistono altre istanze. Se esiste una istanza allora si chiude e scrive sul
registro il percorso del documento da aprire. L'istanza attiva, tramite il
timer controlla la chiave di registro creata in precedenza, apre il
documento, e poi la elimina. Il tutto funzione e non si nota questo
barbatrucco, ma vorrei saper se esiste un modo più elegante di fare la cosa.
Un grazie anticipato a chi risponde
Rea

 un'altro documento facendo doppio click sul file relativo.
Ci sarebbe un modo perchè la cosa venga gestita dal sistema operativo: in
pratica si tratta di registrare l'associazione al tipo di file non con il
sistema classico "c:\pippo.exe %1" ma utilizzando i messaggi DDE, come ad
esempio trovi nei documenti gestiti da Office, Internet explorer ecc., dove in
pratica e' Windows che si preoccupa di avviare prima una conversazione DDE con
il programma e solo se non trova nessuna istanza attiva ne lancia un'altra.
Per implementarlo in VB e' sufficiente che in una form qualsiasi (diciamo il tuo
contenitore MDI) imposti la proprieta' LinkMode = vbLinkSource e la proprieta'
LinkTopic ad una stringa  arbitraria che servira' a identificare la
comunicazione, per convenzione si usa "System".
A questo punto puoi gestire l'evento Form_LinkExecute(CmdStr As String, Cancel
As Integer) dove CmdStr e' il comando che ti viene passato di volta in volta
mentre Cancel serve per stabilire l'esito della comunicazione, in maniera simile
a come si usa nel QueryUnload e simili.
Per quanto riguarda la registrazione del file ecco come appaiono le stringhe del
registry corrispondenti ad una ipotetica estensione ".fav" (ho tolto i doppi "\"
per chiarezza)
[HKEY_CLASSES_ROOT\favfile\Shell]
@=""
[HKEY_CLASSES_ROOT\favfile\Shell\open]
[HKEY_CLASSES_ROOT\favfile\Shell\open\command]
@="C:\WINDOWS\Desktop\Progetto1.exe %1"
[HKEY_CLASSES_ROOT\favfile\Shell\open\ddeexec]
@="[open "%1"]"
[HKEY_CLASSES_ROOT\favfile\Shell\open\ddeexec\Application]
@="Progetto1"
[HKEY_CLASSES_ROOT\favfile\Shell\open\ddeexec\topic]
@="System"
dove "topic" corrisponde alla stringa impostata in LinkTopic, "Application"
corrisponde al *titolo* del programma (non il nome dell'exe, ma quello che
imposti nella finestra "Crea") e "ddeexec" e' nuovamente una stringa a tua
scelta che identifica il comando e che sara' ricevuta dal tuo programma nel
parametro CmdStr di LinkExecute; anche qui la scelta [open "%1"] e' solo una
convenzione, portesti metterci semplicemente "%1" o altro, sta a te interpretare
il comando.
Mi rendo conto che forse non sono stato molto chiaro ma credimi, e' piu' facile
da fare che non da spiegare... in ogni caso chiedi pure.
Ciao
--
Luca Dormio
luca....@tin.it

 ha scritto nel messaggio
news:Zujw6.88122$yl2.6...@news1.tin.it...

Sul sito comune è stato aggiunto, di recente, la soluzione a tale problema
(dato che il PreviousIstance non funziona a dovere).
Prova un po' a vedere
    Saluti

Che problemi ha "App.PrevInstance"? Qual'e' il progetto aggiunto
recentemente che risolve l'eventuale problema?

grazie mille, sei stato molto esauriente.
Adesso provo a mettere in pratica la tua spiegazione.
ciao Rea

 recentemente che risolve l'eventuale problema?
Beh in realtà io mi ricordo di una serie di post di non so chi, per cercare
di risolvere il problema del PrevIstance.
Poi tale tizio era risuscito a risolvere il problema con una serie di
stratagemmi e disse che avrebbe inserito un mini progetto sul SC.
Di + non so ...
Saluti

 ---------------------------------
From: 
ali...@tiscalinet.it
 ("Stefano Dolcini - Tiscali")
Newsgroups: it.comp.lang.visual-basic
Subject: =?iso-8859-1?Q?Re:_Re:_Istanza_gi=E0_attiva_dell'applicazione?=
Date: 3 Dec 2000 19:45:40 +0100
Funziona poich=E8 non uso App.Previnstance ma utilizzo il registry di =
windows
Ciao Stefano
From: 
ali...@tiscalinet.it
 ("Stefano Dolcini - Tiscali")
Newsgroups: it.comp.lang.visual-basic
Subject: =?iso-8859-1?Q?Re:_Re:_Istanza_gi=E0_attiva_dell'applicazione?=
Date: 3 Dec 2000 20:34:47 +0100
Ciao Aldo,
hai giusto evidenziato il punto che sto ancora cercando di risolvere...
...anzi a dire il vero mentre sto rispondendo al post forse mi =E8 =
venuta un'idea, ma visto che non sono sicuro ne approfitto per avere un =
aiuto.
Nel caso di crash di sistema riavviando l'applicazione dopo il riavvio =
del sistema
andrei a leggere l'handle di un qualcosa non pi=F9 esistente o (non ne =
sono sicuro) assegnato, dopo il riavvio del sistema operativo, a =
qualcos'altro che non centra niente con la mia applicazione.
Sai se tramite l'handle =E8 possibile sapere se si sta fancendo =
riferimento al form
della mia applicazione.
A me =E8 venuta in mente questa possibile soluzione:
Utilizzo 1 flag nel registry per sapere se il metodo resize del form =E8 =
stato chiamato da un'altra applicazione o no, questo mettendo nel metodo =
main appena prima del
metodo QuitApplication la scrittura del flag nel registry. Nel metodo =
resize del form verificher=F2 nel registry la presenza di tale flag per =
capire se scrivere un secondo
flag per capire se =E8 effettivamente avviata un'altra istanza della mia =
applicazione. A questo punto nel metodo quit posso testare il secondo =
flag per capire se=20
=E8 stato effettivamente chiamato il metodo resize di una mia =
applicazione, in tal caso canceller=F2 dal registry tutte le chiavi.
MODULO: basApp.bas
---------------------------------
dim gl_HwndPrevInst as Long
...............
sub Main()
...............
' Ricevo l'handle eventualmente memorizzato dall'istanza attiva, se =
esistente
gl_HwndPrevInst =3D GetSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND, 0)
' - Se esiste gi=E0 un'istanza avviata segnalo l'errore e richiamo il =
metodo di uscita dall'applicazione con parametro false per non fare
' cancellare la chiave sul registry di windows.
' - Altrimenti carico il form principale
If (gl_HwndPrevInst > 0) Then
Call Segnala_Errore(...,...,...,...)
' - MODIFICA 3-12-2000
' MEMORIZZO IL PRIMO FLAG (AVVIO APPLICAZIONE)
Call SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, =
GCS_KEY_REGISTRY_APP_START, "1")
Call QuitApplication(False)
End If
Load frmMain
frmMain.Show
...............
End Sub
' Metodo di uscita dall'applicazione, per abbandonare l'applicazione si =
deve assolutamente richiamare questo metodo in quanto deve essere
' cancellata dal registry la chiave che indica la presenza di una =
istanza gi=E0 avviata
Public Sub QuitApplication(Optional pb_Registry As Boolean =3D True)
.............
' Cancello la chiave sul registry se non =E8 stato indicato =
diversamente dal parametro ricevuto
If pb_Registry =3D True Then
Call DeleteSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND)
End If
' Se =E8 stata rilevata una istanza gi=E0 avviata chiamo il metodo =
che mi permette di portarla in primo piano
If gl_HwndPrevInst > 0 Then
Call ShowPrevInstance(gl_HwndPrevInst)
' - MODIFICA 3-12-2000
' ELIMINO IL PRIMO FLAG DAL REGISTRY (AVVIO APPLICAZIONE)
Call DeleteSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_START)
' SE NEL REGISTRY E' PRESENTE IL SECONDO FLAG ALLORA SIGNIFICA CHE =
ESISTE UN'ISTANZA DELLA MIA APPLICAZIONE
If GetSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, =
GCS_KEY_REGISTRY_APP_EXIST, "0") =3D "1" then
' ELIMINO IL SECONDO FLAG DAL REGISTRY (APPLICAZIONE ESISTENTE)
Call DeleteSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_EXIST)
Else
' ELIMINO IL SECONDO FLAG DAL REGISTRY (APPLICAZIONE ESISTENTE) =
ANCHE IN QUESTO CASO, E CANCELLO ANCHE LA CHIAVE
' RELATIVA ALL'HANDLE DELLA APPLICAZIONE CHIUSA IN MODO ANOMALO
Call DeleteSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_EXIST)
Call DeleteSetting(GCS_APP_REGISTRY, =
GCS_SECTION_REGISTRY_EXECUTION, GCS_KEY_REGISTRY_APP_HWND)
' MANDO UNA SEGNALAZIONE CHE LA PRECEDENTE ESECUZIONE DEL =
PROGRAMMA NON E' STATA CHIUSA NEL MODO CORRETTO
msgbox "..........."
' ESCO DEL METODO SENZA CHIUDERE IL PROGRAMMA
Exit Sub
End If
End If
End
End Sub
-------------------------------------------------------
MODULO: basShowPrevInstance.bas
-------------------------------------------------------
' - API: ShowWindow
' Dichiarazione costanti API
Public Const SW_HIDE =3D 0 ' finestra nascosta ma attivata
Public Const SW_SHOWNORMAL =3D 1 ' posizione di default e attivata
Public Const SW_SHOWMINIMIZED =3D 2 ' ridotta a icona e attivata
Public Const SW_SHOWMAXIMIZED =3D 3 ' ingrandita e attiva
Public Const SW_SHOWNOACTIVATE =3D 4 ' pos. di default, non att.
Public Const SW_SHOW =3D 5 ' nella posizione corrente, attiva
Public Const SW_MINIMIZE =3D 6 ' riduce a icona
Public Const SW_SHOWMINNOACTIVE =3D 7 ' minimizza, non attiva
Public Const SW_SHOWNA =3D 8 ' nella pos. corrente, non attiva
Public Const SW_RESTORE =3D 9 ' alla posizione di default, attiva
Public Const SW_SHOWDEFAULT =3D 10 ' posizione di default, attiva
' Dichiarazione funzione API
Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal =
nCmdShow As Long) As Long
Public Function ShowPrevInstance(pl_Hwnd As Long) As Boolean
' Le 2 seguenti chiamate alle API permettono di scatenare l'evento =
resize del form relativo all' handle
' memorizzato nel registry all'avvio dell'applicazione nell'istanza =
precedente
Call ShowWindow(pl_Hwnd, SW_SHOWMINIMIZED)
Call ShowWindow(pl_Hwnd, SW_SHOWNORMAL)
End Function
-------------------------------------------------------------------------=
-------------------------------------------------------------------------=
--------
FORM: frmMain.frm
---------------------------------
Public Sub Form_Load()
...........
' Memorizzo nel registry l'handle del form principale (un form MDI =
sarebbe l'ideale)
Call SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, =
GCS_KEY_REGISTRY_APP_HWND, Me.hwnd)
...........
End Sub
Private Sub Form_Resize()
' Quando viene scatenato l'evento resize porto in primo piano e =
assegno il focus al form in questione
On Error Resume Next
' - MODIFICA 3-12-2000
' SE NEL REGISTRY E' PRESENTE IL PRIMO FLAG ALLORA VALORIZZO IL =
SECONDO FLAG SEMPRE NEL REGISTRY
If GetSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, =
GCS_KEY_REGISTRY_APP_START, "0") =3D "1" then
' MEMORIZZO NEL REGISTRY IL SECONDO FLAG
Call SaveSetting(GCS_APP_REGISTRY, GCS_SECTION_REGISTRY_EXECUTION, =
GCS_KEY_REGISTRY_APP_EXIST, "1")
End If
Me.ZOrder 0
Me.SetFocus
On Error GoTo 0
End Sub
-------------------------------------------------------------------------=
-------------------------------------------------------------------------=
--------
Dovrebbe funzionare ma non l'ho provato, ho scritto direttamente sulla =
mail, per=F2 a logica mi sembra funzionare.
Ciao Stefano