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

API, COM et SDKs Delphi Discussion :

Appel d'une methode de classe par message inopérant dans une dll


Sujet :

API, COM et SDKs Delphi

  1. #1
    Nouveau membre du Club Avatar de Jacques Deyrieux
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Octobre 2002
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 27
    Points : 33
    Points
    33
    Par défaut Appel d'une methode de classe par message inopérant dans une dll
    Bonjour,

    je développe une dll qui a besoin d'être appelée par une fonction externe (dll SimConnect).
    J'ai pris le choix de gérer les appels par messages du style WM_USER + xxx.

    Mon problème est que la méthode de ma classe n'est jamais appelée. Je pense que ça viens du handle de ma dll ou du principe d'une dll qui bloquerai ce genre de chose... je suis

    ci dessous le code de la dll et quelques explications. Pour info je charge la dll dynamiquement

    Si quelqu'un arrive à m'expliquer pourquoi cela ne marche pas ce serait cool,

    merci

    Jacques
    --------------------
    J'ai créé la classe suivante:
    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
     
    const
    WM_USER_EFBCONNECT  = WM_USER + 3;
     
    type
      TEfbConnect = class
        procedure EfbConnectMessage(var Message: TMessage); message WM_USER_EFBCONNECT;
     
      private
        FpEventHandler: PEfbConnEventHandler;
      public
      end;
    ...
    procedure TEfbConnect.EfbConnectMessage(var Message: TMessage);
    begin
      SimConnect_CallDispatch(hSimConnect, DispatchHandlerFSX, nil);
    end;
    hSimConnect est un handle fourni par la SDK de FSX (FlightSimulator X)
    DispatchHandlerFSX est une procédure de ma dll appelée par le dispacher du SDK FSX

    Pour initialiser le processus d'appel, j'utilise la commande suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        Result := SimConnect_Open(hSimConnect, 'Request Data', HandleModule, WM_USER_EFBCONNECT, 0, 0);
    hSimConnect est différent de 0 quand un handle est fourni,
    HandleModule est le handle de ma dll (sinon de la form quand le code est placé dans un programme).

    Le handleModule est initialisé avec la ligne suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HandleModule := GetModuleHandle(AnsiString('efbconnect.dll'));
    Si je compare la valeur de HandleModule et du handle retourné par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    hEfbConnect := LoadLibrary(dllName);
    j'ai la même chose.

  2. #2
    Nouveau membre du Club Avatar de Jacques Deyrieux
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Octobre 2002
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 27
    Points : 33
    Points
    33
    Par défaut
    Bon en fait j'ai trouvé d'où venais le pb!

    a) Windows a besoin d'un handle d'application pour enregistrer et traiter un message et un listener.
    b) Seule une méthode de class peut être définie avec un message WM_USER
    c) Delphi implemente dans un classe objet un listener par défaut

    Hors une dll semble ne pas être une application à proprement parler.

    Assemblez tout ça et ça donne :
    => une classe qui créé un handle windows dans son constructeur,
    => un enregistrement du listener avec le handle créé
    => la méthode WndProc surchargée pour dériver les messages WM_USER... vers la bonne méthode,
    => un destructeur qui libère le handle à la fermeture de la dll.

    bon je rajoute les bouts de code qui vont bien et voilà

    Jacques

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 737
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 737
    Points : 25 654
    Points
    25 654
    Par défaut
    Peux-tu utiliser PostThreadMessage pour appeler la DLL
    car dans ce cas, tu lance un thread dans la section initialization de ta DLL, et tu boucles sur WaitMessage et GetMessage !

    Voir dans le Code du TTimer, il contient lui aussi la création d'un contrôle uniquement pour l'écoute des messages hors d'une application, comme pour un Service par exemple !

  4. #4
    Nouveau membre du Club Avatar de Jacques Deyrieux
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Octobre 2002
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 27
    Points : 33
    Points
    33
    Par défaut
    Salut,

    merci pour ta réponse je vais regarder plus tard si cela est plus pertinent, en attendant, ci dessous le code que j'ai réalisé et qui marche bien

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    const
     WM_USER_EFBCONNECT                    = WM_USER + 3;
     
    type
      TEfbConnect = class
      private
        FpEventHandler: PEfbConnEventHandler;
      protected
         FWinHandle: HWND;
         procedure WndProc(var msg: TMessage);
      public
        constructor Create;
        destructor Destroy; override;
      end;
    ......
    procedure DispatchHandlerFSX(pData: PSimConnectRecv; cbData: DWORD; pContext: Pointer); far; stdcall;
    begin
      // Handle the various types of message
      case TSimConnectRecvId(pData^.dwID) of
        SIMCONNECT_RECV_ID_OPEN:
          begin
            RecvOpenData := PSimConnectRecvOpen(pData);
            checkFSXVersion;
          end;
        SIMCONNECT_RECV_ID_EVENT:
     
    ......
     
    end;
     
    ......
     
    procedure EfbConnectMessage(var Message: TMessage); far; stdcall;
    begin
      SimConnect_CallDispatch(hSimConnect, DispatchHandlerFSX, nil);
    end;
    ......
    constructor TEfbConnect.Create;
    begin
      Inherited;
      FWinHandle := AllocateHWND(WndProc);
    end;
     
    destructor TEfbConnect.Destroy;
    begin
      DeallocateHWnd(FWinHandle);
      inherited;
    end;
     
    procedure TEfbConnect.WndProc(var msg: TMessage);
    begin
      if Msg.Msg = WM_USER_EFBCONNECT then
        EfbConnectMessage(Msg);
     
      // call default proc
      Msg.Result := DefWindowProc(FWinHandle, Msg.Msg, Msg.wParam, Msg.lParam);
    end;
     
    { dll handler for dynamic load }
    procedure DLLHandler(Reason: integer); local;
    begin
      case Reason of
        DLL_PROCESS_ATTACH:
          begin
            hSimConnect := 0;
            ExitCode := 0;
            HandleModule := HInstance;
            OpenSimConnect;
            // create efbconnect object
            cEfbConnect := TEfbConnect.Create;
          end;
        DLL_PROCESS_DETACH:
          begin
            { disconnect fsx }
            if IsSimConnectInitialized then
            begin
              CloseSimConnect;
              FreeAndNil(cEfbConnect);
            end;
          end;
      end;
    end;
     
    begin
    {$IFDEF Debug}
      { True means Delphi checks & reports memleaks }
      ReportMemoryLeaksOnShutdown := DebugHook <> 0;
    {$ENDIF}
      { Make the Memory-Manager aware that this DLL is used in Thread-environments }
      IsMultiThread := true;
     { use dll handler for track dynamic attachments }
      DllProc := @DLLHandler;
      DllProc(DLL_PROCESS_ATTACH);
     
    end.
    voilà, no problem, mes messages sont bien reçus, par mon listener puis l'appel à au Dispatch de SimConnect fonctionne nickel.

    Je pense que mon code n'est peut-être pas full multithread ready , si tu as des liens vers de la documentation donnant les règles à ne pas enfreindre, genre déclaration des variables dans la dll et autre subtilité, c'est top,

    a+

    Jacques

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/02/2010, 04h45
  2. Réponses: 1
    Dernier message: 26/09/2008, 17h38
  3. Réponses: 3
    Dernier message: 04/07/2008, 13h00
  4. Réponses: 3
    Dernier message: 30/04/2007, 13h22
  5. execution de blt dans une methode de classe
    Par micflor dans le forum DirectX
    Réponses: 2
    Dernier message: 13/03/2006, 21h31

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