Aide - Recherche - Membres - Calendrier
Version complète : "Hooker" la fermeture d'un programme ?
Les Forums de PalmAttitude.org > GENERAL PalmOS > Développement sous PalmOS > Développement HB++
maillaxa
Salut,

Je cherche à écrire un tout petit logiciel tout simple qui agit (se met en marche) lorsque l'utilisateur sort d'un programme (pour commencer).

Je cherche donc à intercepter le signal de cloture du programme en question pour faire une opération supplémentaire. Je sais qu'un programme comme OnGuardBackup sait faire cela et l'utilise pour sauvegarder des données/préférences. Je verux faire strictement la même chose.

Sauriez-vous comment réaliser cette chose et quel type de projet choisir dans la liste des possibilités offertes par HB++

Merci
Payalba
Regarde les notifications
Notify event, RegisterNotify, UnregisterNotify et la notification hbNotifyAppQuittingEvent


maillaxa
Mon problème est d'avoir un programme "résidant" qui tourne "en fond" et détecte ce signal pour un AppID bien déterminé. Palm OS n'étant pas multitâches, j'ai bien du mal à savoir comment tout cela peut se passer sourire.gif
Payalba
D'abord, il faut lire un minimum la doc. anim_wink.gif

Les notifications ce n'est pas nécessairement ce qu'il y a de plus simple.

En gros tu enregistres ton prog sur la notification désiré via la fonction registernotify

Quand la notification sera "lancé", ton programme sera appelé (a moins que quelqu'un ait intercepté la notification avant ton prog)

C'est la procedure notify de la classe claApplication qui recevra l'évenement :

Private Sub Application_Notify(ByVal eNotify As HbNotify, ByRef bHandled As Byte, ByVal objParams As StreamMemory, ByVal lUserData As Long)

End Sub

Et c'est à cette endroit que tu réaliseras ton traitement.
maillaxa
CITATION(Payalba @ 23/11/2007 à 19:47 ) *
D'abord, il faut lire un minimum la doc. anim_wink.gif

Les notifications ce n'est pas nécessairement ce qu'il y a de plus simple.

En gros tu enregistres ton prog sur la notification désiré via la fonction registernotify

Quand la notification sera "lancé", ton programme sera appelé (a moins que quelqu'un ait intercepté la notification avant ton prog)

C'est la procedure notify de la classe claApplication qui recevra l'évenement :

Private Sub Application_Notify(ByVal eNotify As HbNotify, ByRef bHandled As Byte, ByVal objParams As StreamMemory, ByVal lUserData As Long)

End Sub

Et c'est à cette endroit que tu réaliseras ton traitement.


Ok c'était un peu la piste qu'on m'avait donné par mail sleep.gif Concernant la documentation, c'est un peu la misère. Je lis le code des samples mais ce n'est pas si évident lorsqu'on ne connait pas l'envrionnement.

Un autre truc que je cherche à faire c'est un bloc try/catch qui en gros tente une connexion pendant disons 20 secondes et plonge dans le catch si la connexion ne se fait pas dans ce laps dde temps.
Payalba
Voici un extrait de la doc de Palm Source :
CITATION
sysNotifyAppQuittingEventThe sysNotifyAppQuittingEvent is broadcast right after anapplication that was launched withsysAppLaunchCmdNormalLaunch quits.sysNotifyAppLaunchingEvent Specific DatanotifyDetailsP points to aSysNotifyAppLaunchOrQuitType structure. See the descriptionof sysNotifyAppLaunchingEvent for a description of thisstructure.Compatibility This notification is declared in the Palm OS 4.0 SDK Update 1.Versions 4.1 and earlier of Palm OS don’t broadcast this notification.Palm OS Garnet releases do broadcast it. Later versions may or maynot broadcast this notification.The sysNotifyAppLaunchingEvent is broadcast before anapplication is launched with sysAppLaunchCmdNormalLaunch.sysNotifyAppLaunchingEvent Specific DatanotifyDetailsP points to a SysNotifyAppLaunchOrQuitTypestructure.Prototype typedef struct SysNotifyAppLaunchOrQuitTag {UInt32 version;UInt32 dbID;UInt16 cardNo;} SysNotifyAppLaunchOrQuitType;NotificationssysNotifyCardInsertedEventPalm OS Programmer’s API Reference 89Fields versionThe current version of this structure. The current version is 0.dbIDThe local ID of the application.cardNoThe number of the card on which the application resides.
Sur le fonctionnement de l'os, tu ne trouveras pas grand chose dans la doc HB++, il faut aller à la source (PalmSource).Pour ton try catch et bienje ne comprends pas ce que tu veux faire mais ca me semble pas une tres bonne idée.
Payalba
Tu as deux thread interressant sur le forum d'HB++

http://www.handheld-basic.com/forum/viewto...ppquittingevent
et
http://www.handheld-basic.com/forum/viewto...ppquittingevent
Payalba
En gros le code à mettre en oeuvre :

Pour l'enregistrement auprès de la notification :

CODE
app.registerNotify(hbNotifyAppQuittingEvent)


Pour se déseregistrement auprès de la notification :

CODE
    
app.unregisterNotify(hbNotifyAppQuittingEvent)


Pour traiter la notification

CODE
Private Sub Application_Notify(ByVal eNotify As HbNotify, ByRef bHandled As Byte, ByVal objParams As StreamMemory, ByVal lUserData As Long)
    dim version as long
    dim dbID as long
    dim cardNo as integer
    dim PADDING as integer
    Dim creatorID as Long
    
    objParams.read version
    objParams.read dbID
    objParams.read cardNo
    objParams.READ PADDING
    

  Dim di as New DatabaseInfo

  di.LocalID = dbID
    MsgBox (di.Name)



End Sub


Pour améliorer le truc, il faudrait s'assurer que la notification recu est la bonne : tester le eNotify
et se réenregistrer (si necessaire : prévoir un paramètrage) après une synchro et un reset.
maillaxa
C'est exactement ce que je fqis (après la lecture des différents posts) malheureusement, ça ne donne rien dans le simulateur dans lequel je teste avec l'application memo. J'ai mis comme code "PMem" et rien ne se fait.

J'avance tout doucement sourire.gif

Voilà en gros où j'en suis. Dans un module, on m'a dit de mettre ceci:

CODE
Public Const sysNotifyAppLaunchingEvent as string="PAdd"
Public Const sysTrapDmDatabaseInfo as Long=&HA046

Public Declare function DmDatabaseInfo(Byval cardNo as Integer, Byval dbID as Long, byref nameP as String, byref attributesP as Integer, byref versionP as Integer, byref crDateP as Long,byref modDateP as Long, byref bckUpDateP as Long,byref modNumP as Long, byref appInfoIDP as Long,byref sortInfoIDP as Long, byref typeP as Long,byref creatorP as Long) as Integer Trap sysTrapDmDatabaseInfo


Ceci devait permettre de s'accrocher aux événements de l'application sysNotifyAppLaunchingEvent (donc ici l'application contact).

Dans ma classe "principale", j'utilise ceci:

CODE
Private Sub Application_SyncNotify()
RegisterExtension sFileExtension
RegisterNotify hbNotifySyncStartEvent
RegisterNotify hbNotifyMenuCmdBarOpenEvent
RegisterNotify hbNotifyCardInsertedEvent
RegisterNotify hbNotifyCardRemovedEvent
RegisterNotify hbNotifyDBDeletedEvent
RegisterNotify hbNotifyDBCreatedEvent
RegisterNotify hbNotifyDBChangedEvent
RegisterNotify hbNotifyDBDirtyEvent
RegisterNotify hbNotifyAppLaunchingEvent
RegisterNotify hbNotifyAppQuittingEvent
' Register our application for our extension
RegisterExtension "vcf"
End Sub


Je demande à mon application de réagire à plusieurs Notify (bien sûr c'est un test, au final il y en aura beaucoup moins).

Enfin, pour traiter les notify, j'utilise :

CODE
Private Sub Application_Notify(ByVal eNotify As HbNotify, ByRef bHandled As Byte, ByVal objParams As StreamMemory, ByVal lUserData As Long)

Select Case eNotify
Case hbNotifySyncStartEvent
' TODO: insert your code here
Case hbNotifyMenuCmdBarOpenEvent
' TODO: insert your code here
Case hbNotifyCardInsertedEvent
' TODO: insert your code here
Case hbNotifyCardRemovedEvent
' TODO: insert your code here
Case hbNotifyDBDeletedEvent
' TODO: insert your code here
Case hbNotifyDBCreatedEvent
' TODO: insert your code here
Case hbNotifyDBChangedEvent
' TODO: insert your code here
Case hbNotifyDBDirtyEvent
' TODO: insert your code here
Case hbNotifyAppLaunchingEvent
' TODO: insert your code here
If eNotify = creatorToLong(sysNotifyAppLaunchingEvent) Then
Dim version as Long
Dim dbID as Long
Dim cardNo as Integer
Dim creatorID as Long
dim PADDING as integer

objParams.Read version
objParams.Read dbID
objParams.Read cardNo
objParams.READ PADDING

Dim szDBName as string

Dim di as New DatabaseInfo

di.LocalID = dbID
MsgBox (di.Name)
' szDBName=Space(32)
' DmDatabaseInfo cardNo ,dbID,szDBName,0,0,0,0,0,0,0,0,0,creatorID
'
' if Trim(szDBName)<>"" then
' Msgbox szDBName & " launched!"
' End if

bHandled =1
End If
Case hbNotifyAppQuittingEvent
' Msgbox "Action B"
' TODO: insert your code here
End Select
End Sub


Je sais que mon application réagit bien au notify car tester avec des actions simples comme afficher une boite de dialogue suivant le notify. Là où ça ne fonctionne plus, c'est lorsque je veux faire quelque chose en fonction de la "provenance" du notify. Je suis encore tout frais sur HB++ et le Palm donc le problème peut venir de moi sourire.gif
snark
Voilà un petit exemple, très très brut de décoffrage.
Il affiche quel est le programme précédent, depuis lequel il est lancé. Ce n'est pas toujours forcément le Launcher.
Faut le lancer d'abord une fois pour qu'il s'enregistre.
maillaxa
Je regarde cela très vite sourire.gif Merci snark
snark
Une nouvelle version, qui s'enregistre lors de la synchro. Plus besoin de le lancer une 1ère fois avant qu'il fonctionne.
Cliquez pour voir le fichier-joint

Au fait, c'est du HB++ 2.5.
maillaxa
Je suis perdu icon_cry2.gif Pourquoi créer une nouvelle classe ?
snark
Parce que je le vaux bien! anim_wink.gif

Tu peux aussi lire directement les paramètres passés dans le StreamMemory objParams un par un, avec des Read sans passer par une classe.
Payalba
Tu n'as pas bessoin de la function "Declare function DmDatabaseInfo".

La ligne de mon exemple (l'as tu essayé ?) : di.LocalID = dbID suffit à récupérer les données de la databaseinfo.

Dans l'objet di, tu as le creatorID.

Si ton appli dois réellement réagir à toutes les notifications auxquelles tu t'enegistres, tu as interret à avoir un code super efficace sous peine d'ecrouler les performances de ton Palm.
maillaxa
CITATION(Payalba @ 24/11/2007 à 09:01 ) *
Tu n'as pas bessoin de la function "Declare function DmDatabaseInfo".

La ligne de mon exemple (l'as tu essayé ?) : di.LocalID = dbID suffit à récupérer les données de la databaseinfo.

Dans l'objet di, tu as le creatorID.

Si ton appli dois réellement réagir à toutes les notifications auxquelles tu t'enegistres, tu as interret à avoir un code super efficace sous peine d'ecrouler les performances de ton Palm.


Comme dis plus haut, pour le moment je cherche à savoir quelle(s) notification(s) serait(ent) vraiment pertinente(s) pour ce que je veux faire. Je fais donc divers essais.

Ce que j'envisage déjà c'est d'utiliser les notifications de reset (relancer ou réenregistrer dès le soft reset). Celui là, j'ai déjà et il fonctionne. Ensuite j'hésite beaucoup entre le appquit et le dbchanged.

Concernant ta fonction, oui je l'ai testé et ça ne donne rien ici blink.gif

Enfin, pour le moment je ne cherche surtout pas à être ni efficace, ni exhaustif mais avoir quelque chose qui fonctionne et que je comprends. Les optimisations (si elles devaient avoir lieu) viendraient après sourire.gif
Payalba
OK chez moi mon exemple fonctionne nickel. (sur un vrai palm, je ne teste jamais les notifications sur le simulateur)

Je laisse le relais à Snark.
maillaxa
Hum j'ai également testé sur mon treo mais sans résultat. J'essaie de remettre mon code au propre pour être sûr sleep.gif
Payalba
Dans ton exemple la ligne

If eNotify = creatorToLong(sysNotifyAppLaunchingEvent)

ne sert à rien.

Le teste est déjà réalise par le switch case.
maillaxa
C'est ce que je viens de m'apercervoir sourire.gif J'ai supprimé le bloc select/case pour ne me consacrer qu'à une seule notification sleep.gif
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.
Invision Power Board © 2001-2008 Invision Power Services, Inc.