Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it L'avatar di luisa227
    Registrato dal
    Mar 2002
    Messaggi
    2,305

    [VB6] problemi su istanze di applicazione

    Il mio programma si avvia con windows, io devo passare dei parametri al programma tramite riga di comando, più precisamente devo rendere visibile l’icona sulla traybar.
    Però se io scrivo nella console

    Miaapp.exe AttivaIcona

    Il programma si avvia 2 volte (praticamente si avviano 2 programmi come fossero differenti)

    X farlo avviare una volta sola (solo la prima istanza), quindi, ho usato app.prevIstance

    codice:
    If App.PrevInstance Then 'se vi è già un'istanza mi passa solo i parametri poi termina
    MsgBox "APPLICAZIONE GIA AVVIATA"
    GetCommandLine
    End
    End If
    Essendoci l’END l’icona me la crea ma essa sparisce subito perché la seconda istanza dell’applicazione termina (e resta la prima che non aveva l’icona).

    Io praticamente devo tramite il comando terminare la seconda istanza (e fino a qui va bene l’end) ma devo attivare l’icona della prima istanza (e non l’icona della seconda…). Come faccio?
    Per creare l’icona uso shell_NotifyIcon()
    codice:
    Public Sub CREATEICON()
        TrayI.cbSize = Len(TrayI)
        TrayI.hwnd = pichook.hwnd 'Link the trayicon to this picturebox
        TrayI.uId = 1&
        TrayI.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
        
        TrayI.ucallbackMessage = WM_LBUTTONDOWN
        
        'icona da visualizzare
        TrayI.hIcon = imgIcon(2).Picture
       
        'Create the icon
        Shell_NotifyIcon NIM_ADD, TrayI
        Me.Hide
    End Sub
    Le mie richieste qui sul forum sono al 99,9% considerate assurde e senza senso, ma per me un senso lo hanno e gradirei una risposta più seria possibile. Grazie

  2. #2
    Ciao.
    La tua è una questione tanto interessante quanto problematica:
    mettere in comunicazione tra di loro 2 processi non deve essere la cosa + semplice del mondo... ammesso che sia possibile.

    Forse una soluzione puoi trovarla lavorando sulle Window.
    Conosci il subclassing ?

    Potresti gestire il tutto come un semplice invio di messaggi alle finestre utilizzando SendMessage.
    Ad esempio:


    If App.PrevInstance Then
    'se vi è già un'istanza mi passa solo i parametri poi termina
    MsgBox "APPLICAZIONE GIA AVVIATA"

    ' verifichi il comando ricevuto,
    ' se è quello che ti aspetti invii il messaggio
    If GetCommandLine = "tuo_comando" Then
    SendMessage HWND_BROADCAST, WM_NULL, 32768, -32767
    End
    End If
    End If


    La dichiarazione della funzione e la definizione delle costanti sono queste:

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    Const WM_NULL = &H0
    Const HWND_BROADCAST = &HFFFF&


    Quando usi SendMessage con HWND_BROADCAST invii un messaggio a tutte le finestre aperte in quell'istante...

    Se conoscessi l'handle della finestra dell'altra istanza del tuo programma potresti inviare il messaggio solo ad essa,
    purtroppo non lo conosci e determinarlo richiede un po' più di lavoro.

    Come dicevo, così facendo invii il messaggio a tutte le finestre. Per questo conviene inviare un messaggio WM_NULL
    (nullo non corrisponde a nessun evento), così da non "disturbare" gli altri programmi in esecuzione.

    Ora: lo scopo è quello di fare in modo che la prima istanza (quella che dovrà mostrare l'icona sulla tray) riceva questo messaggio e faccia quello che deve fare.
    VB non gestisce il messaggio WM_NULL come evento
    quindi, perchè il tuo programma sia in grado di intercettarlo, devi ricorrere al subclassing.

    Il subclassing, te lo spiego in 2 parole poi se vuoi + chiarimenti chiedi pure, consiste nel creare una WindowProcedure personalizzata in grado di intercettare i messaggi inviati dal S.O.
    Da questa WindowProcedure puoi gestire qualunque evento
    (anche quelli non resi disponibili da VB) prima di VB stesso.

    Ecco un esempio di cosa potresti fare:
    Nel Form metti il codice che ti ho scritto sopra...
    ovviamente puoi cambiarlo, basta che al momento giusto esegua SendMessage come hai visto.

    In un Modulo BAS:

    Option Explicit

    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal ndx As Long, ByVal newValue As Long) As Long
    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function IsWindow Lib "user32.dll" (ByVal hwnd As Long) As Long

    Const WM_NULL = &H0 ' Messaggio NULLO
    Const GWL_WNDPROC = -4 ' Per "SetWindowLong"
    Private SaveHWnd As Long ' L'Handle della finestra subclassata
    Private OldProcAddr As Long ' L'indirizzo della WindowProcedure originale

    '
    Sub StartSubclassing(ByVal hwnd As Long)

    ' Avvia il SubClassing
    SaveHWnd = hwnd ' Memorizza Hanlde Window della finestra da subclassare per ripristinarlo poi
    ' Modifica l'indirizzo della Window Procedure predefinita a quello della Function "WndProc"
    ' e memorizza in "OldProcAddr" quello originale.
    OldProcAddr = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc)

    End Sub

    '
    Sub StopSubclassing()

    ' Termina il SubClassing reimpostando l'indirizzo di Window Procedure predefinita
    SetWindowLong SaveHWnd, GWL_WNDPROC, OldProcAddr

    End Sub

    ' Window Procedure personalizzata:
    Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


    ' Se riceve un messaggio WM_CUSTOM
    If uMsg = WM_NULL Then
    ' verifica wParam e lParam
    If wParam = 32768 And lParam = -32767 Then
    ' QUI METTI L'ICONA SULLA TRAY
    MsgBox "QUI METTI L'ICONA SULLA TRAY !!!"
    End If
    End If

    WndProc = CallWindowProc(OldProcAddr, hwnd, uMsg, wParam, lParam)

    End Function


    nel Form_Load() aggiungi

    StartSubclassing Me.hwnd


    mentre, nel Form_QueryUnload scrivi

    StopSubclassing


    e tutto funzionerà a meraviglia !!!
    N.B: Nella WndProc sul modulo BAS, nel punto in cui ho commentato, devi richiamare il codice
    per mettere l'icona sulla TRAY.

    Sappimi dire se ti piace come soluzione, se vuoi qualcosa di
    meglio e, sopratutto, se ti è chiara la questione del subclassing e il codice del modulo.

    Ciao ciao
    Simo

  3. #3
    Utente di HTML.it L'avatar di luisa227
    Registrato dal
    Mar 2002
    Messaggi
    2,305
    grazie, guarderò quello che mi hai scritto poi ti farò sapere. di subclasing ne so poco, sono una principiante...
    Le mie richieste qui sul forum sono al 99,9% considerate assurde e senza senso, ma per me un senso lo hanno e gradirei una risposta più seria possibile. Grazie

  4. #4
    Utente di HTML.it L'avatar di luisa227
    Registrato dal
    Mar 2002
    Messaggi
    2,305
    SUBCLASSING
    Ci sono dei passaggi che non ho capito molto bene come per esempio i valori addizionali wparam e lparam (32768 e – 32767) che sono stati messi nell’ API SendMessage: sono valori casuali o no? Perché proprio -32767 e non 1 ad esempio?

    Nel tuo codice, quando la funzione WndProc controlla questi valori, ho notato che l’ultimo valore (lparam) non corrispondeva mai a –32767 ma il valore cambia sempre. Sono un po’ confusa essendo principiante.
    Allora per far funzionare il codice ho impostato il valore wparam a 1 mentre lparam a &0 (il tuo codice è giustissimo –credo- ma l’ho dovuto modificare in base al mio grado di intendimento ma non so se ho fatto bene o meno) in modo che mi controlli solo il valore wparam e in modo da passargli un messaggio diverso a seconda del parametro. Sbaglio facendo cosi? Se si perché?

    codice:
    ' Window Procedure personalizzata:
    Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    ' Se riceve un messaggio WM_CUSTOM
    If uMsg = WM_NULL Then
    ' verifica wParam e lParam
    MsgBox wParam & "/" & lParam
    If wParam = 2 Then
    ' QUI METTI L'ICONA SULLA TRAY
    MsgBox "QUI METTI L'ICONA SULLA TRAY !!!"
    End If
    If wParam = 1 Then
    ' QUI METTI L'ICONA SULLA TRAY
    MsgBox "vaaaaaaaaaaaaaaaa!!!"
    End If
    End If
    WndProc = CallWindowProc(OldProcAddr, hwnd, uMsg, wParam, lParam)
    End Function
    Cmq la questione del subclassing penso possa risolvere un altro problema che ho già postato tempo fa riguardo la scrittura nella console DOS attuale (vedi post http://forum.html.it/forum/showthrea...hreadid=702406 )
    Se potete aiutatemi, grazie
    Le mie richieste qui sul forum sono al 99,9% considerate assurde e senza senso, ma per me un senso lo hanno e gradirei una risposta più seria possibile. Grazie

  5. #5
    Utente di HTML.it L'avatar di luisa227
    Registrato dal
    Mar 2002
    Messaggi
    2,305
    aiutooooooo
    Le mie richieste qui sul forum sono al 99,9% considerate assurde e senza senso, ma per me un senso lo hanno e gradirei una risposta più seria possibile. Grazie

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.