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

C++ Discussion :

Callback d'une fenetre API Win32 dans une classe instanciable


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Callback d'une fenetre API Win32 dans une classe instanciable
    Bonjour,

    J'aimerais savoir s'il est possible de déclarer une classe instanciable qui contiendrait à la fois la méthode de création d'une fenetre win32 avec CreateWindowEx et une méthode pour gérer les événements de cette fenêtre, de sorte que les 2 puissent accéder aux données membre de ma classe.

    Typiquement j'ai deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    LRESULT CALLBACK EvenementsFenetre(HWND hwnd, UINT mes, WPARAM wParam, LPARAM lParam)
    {
       [...]
    }
     
    void CreerFenetre()
    {
       [...]
       WNDCLASSEX uneFenetre;
       // Adresse WNDPROC de ma fonction CallBack
       uneFenetre.lpfnWndProc = EvenementsFenetre;
       [...]
    }
    Je voudrais savoir comment faire pour les intégrer dans une classe instanciable du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class MaFenetre
    {
       int donneeMembre;
       void CreerFenetre();
       LRESULT CALLBACK EvenementsFenetre(HWND hwnd, UINT mes, WPARAM wParam, LPARAM lParam);
    }
    Le problème qui se pose est que, dans le fonction CreerFenetre(), l'instruction uneFenetre.lpfnWndProc attend l'adresse d'une fonction classique et n'apprécie pas du tout la fonction membre que je lui donne.

    Je pourrais la déclarer en static mais je cherche à ce que la classe soit instanciable et à pouvoir accéder aux données membres.

    Est-ce possible et où est-ce que je m'y prends mal ?

  2. #2
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Tu ne peux pas directement donner l'adresse d'une méthode parce que windows ne saurait pas sur quelle instance appeler cette méthode.
    Tu vas devoir faire une fonction globale (ou une méthode statique) qui va dispatcher les évènements aux bonnes instances. Pour que cette fonction globale sache à quelle instance elle doit renvoyer les messages, tu as la possibilité de stocker des données dans une fenêtre windows (SetWindowLongPtr et GetWindowLongPtr).
    Ton code peut ressembler à ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class MaFenetre
    {
       int donneeMembre;
       void CreerFenetre();
       LRESULT CALLBACK EvenementsFenetre(HWND hwnd, UINT mes, WPARAM wParam, LPARAM lParam);
    }
    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
    LRESULT CALLBACK EvenementsFenetreDispatcher(HWND hwnd, UINT mes, WPARAM wParam, LPARAM lParam)
    {
        // cast à faire
        MaFenetre *maFenetre = GetWindowLongPtr(hwnd, GWL_USERDATA);
        maFenetre->EvenementsFenetre(hwnd, mes, wParam, lParam);
    }
     
    void CreerFenetre()
    {
       [...]
       WNDCLASSEX uneFenetre;
       // Adresse WNDPROC de ma fonction CallBack
       uneFenetre.lpfnWndProc = EvenementsFenetreDispatcher;
     
       [...]
     
       MaFenetre *maFenetre = [...];
       SetWindowLongPtr(hWnd, GWL_USERDATA, maFenetre);
       [...]
    }

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    C'est très intéressant ça, merci beaucoup !

  4. #4
    Membre régulier Avatar de cynique
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Points : 72
    Points
    72
    Par défaut
    Citation Envoyé par Twindruff Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LRESULT CALLBACK EvenementsFenetreDispatcher(HWND hwnd, UINT mes, WPARAM wParam, LPARAM lParam)
    {
        // cast à faire
        MaFenetre *maFenetre = GetWindowLongPtr(hwnd, GWL_USERDATA);
        maFenetre->EvenementsFenetre(hwnd, mes, wParam, lParam);
    }
    Ah, presque... Pendant l'appel à CreateWindow ou CreateWindowEx, il y a plusieurs messages envoyés à la nouvelle fenêtre. Mais la fenêtre ne sait pas son objet, parce que tu ne peux pas faire SetWindowLong() avant que CreateWindow est finie... Alors, sur le premier appel à EvenementsFenetreDispatcher, maFenetre sera NULL.



    Il n'y a pas qu'une solution pour ça. MFC utilise un "hook" pour détecté la création de la fenêtre avant le premier message, et un pointeur "statique" pour savoir l'objet. Ma solution, il y a quelques années, utilise une fonction comme la tienne, avec un pointeur statique...

  5. #5
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    C'était l'idée en gros après il y a des adaptations à faire, pour plus de détails il y a ces documents qui sont très bien faits: C++ in Action 1, 2, ...

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/03/2011, 15h58
  2. Réponses: 1
    Dernier message: 26/12/2010, 21h20
  3. Réponses: 1
    Dernier message: 11/01/2008, 17h54
  4. Réponses: 4
    Dernier message: 03/05/2005, 09h03

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