IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Package, initialisation et variables globales


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut Package, initialisation et variables globales
    Bonjour,

    Je suis sous Delphi 2006 et j'ai créé quelques composants visuels que j'ai mis dans un package. Jusqu'ici tout marche bien.

    Je voudrai maintenant modifier mes composants pour qu'ils réagissent mieux quand on utilise un écran tactile.

    J'ai ce morceau de code qu'il faut que j'appelle au préalable:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Procedure LoadTouchGestureAPI;
    var Handle:THandle; sm:Integer;
    begin
      Handle := LoadLibrary('user32.dll');
      try   // dynamicaly load Gesture function addresses, if fns available
        CloseTouchInputHandleFn   := GetProcAddress(Handle, 'CloseTouchInputHandle');
        PhysicalToLogicalPointFn  := GetProcAddress(Handle, 'PhysicalToLogicalPoint');
        GetTouchInputInfoFn       := GetProcAddress(Handle, 'GetTouchInputInfo');
        RegisterTouchWindowFn     := GetProcAddress(Handle, 'RegisterTouchWindow');
        UnregisterTouchWindowFn   := GetProcAddress(Handle, 'UnregisterTouchWindow');
        GetGestureInfoFn          := GetProcAddress(Handle, 'GetGestureInfo');
        CloseGestureInfoHandleFn  := GetProcAddress(Handle, 'CloseGestureInfoHandle');
        SetGestureConfigFn        := GetProcAddress(Handle, 'SetGestureConfig');
     
        bTouchGestureAPIPresent   := Assigned(GetTouchInputInfoFn);
     
      finally
        FreeLibrary(Handle);
      end;
     
      // Test for multi - touch hw
      bMultiTouchHardware := false;
      sm := GetSystemMetrics(SM_DIGITIZER);
      if (sm and NID_MULTI_INPUT <> 0) then
        bMultiTouchHardware := true;  // digitizer is multitouch 
    end;
    En effet suivant le matériel et l'Os le tactile n'est pas forcément géré et je ne peux pas faire une liaison statique.
    Je pense logiquement faire un appel à cette procédure dans une section Initialisation d'une des unité de mon package.

    La procédure initialise des variables "globales" de type fonction et les booleans "bTouchGestureAPIPresent" et "bMultiTouchHardware" qui indiquent si le système gère le tactile.

    Dans le code de mes composants je regarderai l'état de ces booleans pour savoir si je peux faire appel aux fonctions liées au tactile.

    J'ai cru comprendre qu'avec les DLL (et donc aussi les BPL) le code était partagé entre toutes les applications mais par contre chaque application avait sa propre version des variables.

    La première application qui va faire appel au package va lui faire exécuter sa procédure d'initialisation qui va initialiser les booleans, ça devrait marcher.
    Mais qu'est ce qui va se passer si on lance une deuxième application utilisant le package, le package étant déjà chargé il ne passera pas dans sa procédure d'initialisation (?)
    Est ce qu'on peut récupérer l'état des variables initialisées lors chargement initiale de mon package, est ce qu'on peut déclarer des variables qui seraient globales à toutes les instances de mon package ?
    Ou alors il faut géré le problème d'une autre façon ? Peut être qu'on peut détecter quand le package est utilisé par une nouvelle application et dans ce cas appeler ma procédure d'initialisation ?

    Merci

  2. #2
    Membre émérite Avatar de sergio_is_back
    Homme Profil pro
    Consultant informatique industrielle, développeur tout-terrain
    Inscrit en
    Juin 2004
    Messages
    1 188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Consultant informatique industrielle, développeur tout-terrain
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 188
    Par défaut
    Citation Envoyé par BeeB1 Voir le message
    Bonjour,

    Je suis sous Delphi 2006 et j'ai créé quelques composants visuels que j'ai mis dans un package. Jusqu'ici tout marche bien.

    Je voudrai maintenant modifier mes composants pour qu'ils réagissent mieux quand on utilise un écran tactile.

    J'ai ce morceau de code qu'il faut que j'appelle au préalable:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    Procedure LoadTouchGestureAPI;
    var Handle:THandle; sm:Integer;
    begin
      Handle := LoadLibrary('user32.dll');
      try   // dynamicaly load Gesture function addresses, if fns available
        CloseTouchInputHandleFn   := GetProcAddress(Handle, 'CloseTouchInputHandle');
        PhysicalToLogicalPointFn  := GetProcAddress(Handle, 'PhysicalToLogicalPoint');
        GetTouchInputInfoFn       := GetProcAddress(Handle, 'GetTouchInputInfo');
        RegisterTouchWindowFn     := GetProcAddress(Handle, 'RegisterTouchWindow');
        UnregisterTouchWindowFn   := GetProcAddress(Handle, 'UnregisterTouchWindow');
        GetGestureInfoFn          := GetProcAddress(Handle, 'GetGestureInfo');
        CloseGestureInfoHandleFn  := GetProcAddress(Handle, 'CloseGestureInfoHandle');
        SetGestureConfigFn        := GetProcAddress(Handle, 'SetGestureConfig');
     
        bTouchGestureAPIPresent   := Assigned(GetTouchInputInfoFn);
     
      finally
        FreeLibrary(Handle);
      end;
     
      // Test for multi - touch hw
      bMultiTouchHardware := false;
      sm := GetSystemMetrics(SM_DIGITIZER);
      if (sm and NID_MULTI_INPUT <> 0) then
        bMultiTouchHardware := true;  // digitizer is multitouch 
    end;
    En effet suivant le matériel et l'Os le tactile n'est pas forcément géré et je ne peux pas faire une liaison statique.
    Je pense logiquement faire un appel à cette procédure dans une section Initialisation d'une des unité de mon package.

    La procédure initialise des variables "globales" de type fonction et les booleans "bTouchGestureAPIPresent" et "bMultiTouchHardware" qui indiquent si le système gère le tactile.

    Dans le code de mes composants je regarderai l'état de ces booleans pour savoir si je peux faire appel aux fonctions liées au tactile.

    J'ai cru comprendre qu'avec les DLL (et donc aussi les BPL) le code était partagé entre toutes les applications mais par contre chaque application avait sa propre version des variables.

    La première application qui va faire appel au package va lui faire exécuter sa procédure d'initialisation qui va initialiser les booleans, ça devrait marcher.
    Mais qu'est ce qui va se passer si on lance une deuxième application utilisant le package, le package étant déjà chargé il ne passera pas dans sa procédure d'initialisation (?)
    Est ce qu'on peut récupérer l'état des variables initialisées lors chargement initiale de mon package, est ce qu'on peut déclarer des variables qui seraient globales à toutes les instances de mon package ?
    Ou alors il faut géré le problème d'une autre façon ? Peut être qu'on peut détecter quand le package est utilisé par une nouvelle application et dans ce cas appeler ma procédure d'initialisation ?

    Merci
    Le code peu être partagé mais pas le contexte (les variables)... Sinon toutes les applications qui utilisent la même DLL seraient quel que peu instables...

    De plus ton BPL (où du moins les unités concernées) sera compilé avec ton application, en effet les BPL sont liés statiquement contrairement aux DLL (même si il est possible en théorie, je l'ai jamais fait, de lier un BPL de façon dynamique)
    Donc si tu as deux applications Delphi en cours d’exécution chacune aura sa propre copie de ton code et des variables...

  3. #3
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut
    Citation Envoyé par sergio_is_back Voir le message
    Le code peu être partagé mais pas le contexte (les variables)... Sinon toutes les applications qui utilisent la même DLL seraient quel que peu instables...

    De plus ton BPL (où du moins les unités concernées) sera compilé avec ton application, en effet les BPL sont liés statiquement contrairement aux DLL (même si il est possible en théorie, je l'ai jamais fait, de lier un BPL de façon dynamique)
    Donc si tu as deux applications Delphi en cours d’exécution chacune aura sa propre copie de ton code et des variables...
    Merci pour ta réponse.

    Oui, si le BPL est compilé avec mes applications le problème disparaît.
    Mais je comptais utiliser mon BPL dans mes applications avec l'option "Construire avec les package d'exécution" cochée pour profiter des avantages d'utiliser les BPL (modularité, réduction de la taille des exécutables).

    Je me dis que peut être je ne devrai pas mettre d'appel à la procédure "LoadTouchGestureAPI" dans la section initialisation d'une unité de mon BPL mais dans la section initialisation d'une unité de l'application qui utilise le BPL.
    Ou alors dans le BPL encapsuler mes variables booléennes "bTouchGestureAPIPresent" et "bMultiTouchHardware" par des fonctions qui se chargeraient d'appeler "LoadTouchGestureAPI" si ça n'a pas déjà été fait

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 934
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 934
    Par défaut
    Citation Envoyé par BeeB1 Voir le message
    En effet suivant le matériel et l'Os le tactile n'est pas forcément géré et je ne peux pas faire une liaison statique.
    Question OS, ça ne devrait pas poser de problème depuis Vista.
    C'est l'utilisation qui est conditionnée par GetSystemMetrics(SM_DIGITIZER) and NID_MULTI_INPUT <> 0.

    Mais WM_TOUCH est l'ancienne façon de traiter le tactile. Depuis Windows 8, on passe plutôt par les messages WM_POINTER et leurs fonctions associées.

  5. #5
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    remarque, il peut être pratique d'utiliser le mot clé delayed (sous Windows uniquement), il permet de ne pas charger la DLL au lancement mais au premier appel à la fonction...ensuite il suffit de vérifier sur la DLL est disponible ou pas avant d'utiliser les fonctions

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    function nom(param):integer; stdcall; external 'madll.dll' delayed;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 934
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 934
    Par défaut
    Depuis D2010 oui.

  7. #7
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Question OS, ça ne devrait pas poser de problème depuis Vista.
    C'est l'utilisation qui est conditionnée par GetSystemMetrics(SM_DIGITIZER) and NID_MULTI_INPUT <> 0.

    Mais WM_TOUCH est l'ancienne façon de traiter le tactile. Depuis Windows 8, on passe plutôt par les messages WM_POINTER et leurs fonctions associées.
    En fait mon besoin n'est pas vraiment d'utiliser les fonctionnalités tactiles mais plutôt de ne plus les désactiver.

    Je m'explique:
    Mon application est utilisée dans le milieu industriel et sert entre autre à contrôler des machines via un écran tactile: on appuie sur un bouton il se passe quelque chose sur la machine, on relâche le bouton et l'action s'arrête.
    Au début les machines étaient sous Windows XP (XP Embedded) et les écrans tactiles étaient gérés avec un drivers qui les faisait se comporter comme une souris.
    C'est complètement transparent dans mon application, j'utilise le OnMouseDown pour démarrer l'action et le OnMouseUp pour finir l'action.
    Ces machines existent encore et mon application doit rester compatible avec elles.

    Maintenant les PC sont sous Windows 10 (IOT) et le tactile est géré directement par Windows mais pas de la même façon: quand on appuie sur le bouton il ne se passe rien (pas de OnMousedDown) tant qu'on ne bouge pas un petit peu le doigt.
    La problématique et la solution sont expliqués ici:
    https://stackoverflow.com/questions/...uch-down-event

    La solution que j'ai testé en dehors des packages et qui marche c'est d'appeler RegisterTouchWindow(handle, 0); avec le handle de mon bouton mais cette fonction de user32.dll n'existe pas dans les vieilles version de Windows.
    D’où mon besoin de chargement dynamique de 'user32.dll' effectué dans ma procédure LoadTouchGestureAPI

    Pour être tout à fait complet, il y avait aussi une autre problématique: quand on laisse son doigt appuyé longtemps ça émule un click droit et donc mon action se termine prématurément.
    Le problème est réglé en appelant ce bout de code avec le handle du bouton:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure DoDisablePressAndHold(aHandle :THandle);
    var
      AtomID :integer;
    const
      TABLET_DISABLE_PRESSANDHOLD = $000000001;
      TabletAtom = 'MicrosoftTabletPenServiceProperty';
     
    begin
      atomID := GlobalAddAtom(tabletAtom);
     
      if atomID <> 0 then
      begin
        SetProp(aHandle, tabletAtom, TABLET_DISABLE_PRESSANDHOLD);
        GlobalDeleteAtom(AtomID);
      end;
    end;

  8. #8
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut
    il faut lire
    En fait mon besoin n'est pas vraiment d'utiliser les fonctionnalités tactiles mais plutôt de les désactiver.

    au lieu de
    En fait mon besoin n'est pas vraiment d'utiliser les fonctionnalités tactiles mais plutôt de ne plus les désactiver.

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 934
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 934
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Question OS, ça ne devrait pas poser de problème depuis Vista.
    Non, depuis Seven

    Citation Envoyé par BeeB1 Voir le message
    mon besoin n'est pas vraiment d'utiliser les fonctionnalités tactiles mais plutôt de les désactiver.
    Compris !

    Mais est-ce bien utile de juste stocker des adresses puisque tu devras tout de même relancer tous les tests pour chaque fenêtre ? A la place je ferais juste une procédure d'initialisation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    procedure RegisterTouchWnd(aWnd :hWnd);
    var
      DLL  :THandle;
      Proc :function(aWnd :hWnd; aFlags :ulong):BOOL; stdcall;
     
    begin
      DLL := LoadLibrary('user32.dll');
     
      if DLL <> 0 then
      try
        Proc := GetProcAddress(DLL, 'RegisterTouchWindow');
     
        if Assigned(Proc) then
          Proc(aWnd, 0);
     
      finally
        FreeLibrary(DLL);
      end;
    end;
     
    procedure DisablePressAndHold(aWnd :hWnd);
    const
      TabletAtom = 'MicrosoftTabletPenServiceProperty';
      TABLET_DISABLE_PRESSANDHOLD = $000000001;
     
    var
      AtomID :integer;
     
    begin
      atomID := GlobalAddAtom(tabletAtom);
     
      if atomID <> 0 then
      begin
        SetProp(aWnd, tabletAtom, TABLET_DISABLE_PRESSANDHOLD);
        GlobalDeleteAtom(AtomID);
      end;
    end;
     
    procedure InitTouchWindow(aWnd :hWnd);
    const
      Mask = NID_MULTI_INPUT or NID_READY;
     
    begin
      if GetSystemMetrics(SM_DIGITIZER) and Mask = Mask then
      begin
        RegisterTouchWnd(aWnd);
        DisablePressAndHold(aWnd);
      end;
    end;
    Puis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      InitTouchWindow(Handle);
    end;

  10. #10
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut
    Tu as raison, je me complique la vie pour rien un LoadLibrary par bouton ne devrait pas être trop pénalisant.
    Je peux appeler ton InitTouchWindow(Handle) dans le code de création de mes boutons

    Par contre je ne devrais pas plutôt faire l'appel dans CreateWnd pour que le handle soit valide ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Procedure MonBouton.CreateWnd;
    begin
      inherited CreateWnd;
      InitTouchWindow(Handle);
    end;

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 934
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 934
    Par défaut
    Citation Envoyé par BeeB1 Voir le message
    un LoadLibrary par bouton ne devrait pas être trop pénalisant.
    Il ne le sera pas. User32.dll est déjà chargée et tu ne fais que récupérer un handle.

    Citation Envoyé par BeeB1 Voir le message
    Par contre je ne devrais pas plutôt faire l'appel dans CreateWnd pour que le handle soit valide ?
    Oui, c'est très bien.

  12. #12
    Membre habitué
    Inscrit en
    Novembre 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 11
    Par défaut
    Super, merci à tous pour vos précieux conseils

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [2.x] Initialisation de variable globale
    Par chezdevelopping dans le forum Symfony
    Réponses: 4
    Dernier message: 18/06/2013, 21h30
  2. DLL et initialisation des variables globales.
    Par Spidyy dans le forum C++
    Réponses: 5
    Dernier message: 21/06/2012, 17h09
  3. Initialisation variables globale
    Par reeda dans le forum VB.NET
    Réponses: 4
    Dernier message: 25/08/2007, 09h41
  4. Réponses: 8
    Dernier message: 09/07/2007, 10h18
  5. Initialisation des variables globales dans un package
    Par fred_hte_savoie dans le forum SQL
    Réponses: 2
    Dernier message: 17/04/2007, 10h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo