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

Windows Discussion :

callback Win32 dans des classes perso


Sujet :

Windows

  1. #1
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut callback Win32 dans des classes perso
    bonjour,

    je me fais mes propres classes fenetre, bouton, etc...

    Dans le constructeur de ma classe fenetre, j'ai donc :
    hwnd = CreateWindow( ...

    Or je dois lui donner une callback via :

    WNDCLASS wc;
    wc.lpfnWndProc = callbackproc;

    Si la callback est située dans mon main et que je passe son adresse par le constructeur de fenetre, ça marche, mais ce n'est pas du tout ce que je veux.

    Je veux avoir ma fonction callback dans ma classe fenetre et la passer comme ça :

    wc.lpfnWndProc = &fenetre::callbackproc;

    Et là ça coince à la compilation...
    J'ai cette erreur :

    Erreur 1 error C2440: '='*: impossible de convertir de 'LRESULT (__stdcall fenetre::* )(HWND,UINT,WPARAM,LPARAM)' en 'WNDPROC'
    J'ai essayé de caster wc.lpfnWndProc = (WNDPROC) &fenetre::callbackproc; mais rien à faire...

    J'ai afficher la valeur de l'addresse du main et celle de ma classe, elle sont différentes mais très proches.
    J'ai affiché un sizeof des deux et elles font toutes les deux 4 octets. Alors pourquoi le cast est impossible ?

    aidez moi svp

  2. #2
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    http://www.gamedev.net/community/for...opic_id=387255

    ok j'ai trouvé un type qui apparement à le même problème que moi.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ainsi que j'allais le dire avant d'être grossièrement interrompu par la maintenance, une fonction callback Win32 doit être statique, ce qui signifie qu'elle n'a pas de this.
    Si tu veux récupérer this, cherche sur ce méme forum: WM_CREATE ou WM_INITDIALOG, GetWindowLong(), SetWindowLong(), CreateWindow()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Merci de ta réponse,
    oui j'ai compris en lisant mon lien que les fonctions membres des classes ajoutaient implicitement en début de signature un pointeur vers l'objet...
    Ce qui rend effectivement impossible leur utilisation par une callback.

    J'ai effectivement recréé ma méthode en static et je dois alors faire un test sur le hwnd avec ceux que j'ai référencé dans un vector static de toutes mes fénètres pour appeller une méthode particulière d'un objet particulier... pas pratique mais ça marche pour le moment.

    Par contre pour ma liste, je trouve qu'un vector est peu pratique... je cherche une classe qui ait le même comportement que la classe Collection en .Net. J'ai trouvé un schéma de tout ce qui existe en STL queue vector list ... mais rien ne semble correspondre... dois-je perdre du temps à ré écrire une classe ou ais-je ratté la bonne classe ??

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attache l'objet à une fenêtre plutôt...
    Get/SetWindowLong() servent à ça...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Fais une recherche sur le forum, j'ai posé exactement la même question, dont Médinoc a trouvé la réponse, comme dit plus haut. Il me semble que le nom était "méthode callback".

    T'y trouveras la manipulation avec Get/SetWindowLong, en principe.
    Vive l'embarqué.

  7. #7
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    ok le thread est là : http://www.developpez.net/forums/sho...light=callback

    Ca me semble une bonne solution Médinoc, ça m'éviterai de parcourir mon vector. Seulement je ne vois pas comment utiliser get set windowslong dans ce cas précis.

    Généralement je l'utilise pour modifier l'apparence d'une Wnd.

    Tu pourrais me montrer les bouts de code qui font passer le pointeur vers l'objet et qui le récuppèrent ?

    merci

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ah c'était SetWindowLong() qu'il fallait rechercher, pas Callback:
    http://www.developpez.net/forums/sho...=SetWindowLong

    Et encore, on peut faire mieux, en mettant directement une fonction virtuelle dans ta classe.

    J'ai ça chez moi, mais pas ici. Je vais essayer de poster mon code ce soir, n'hésite pas à me rappeler de le faire.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    ok merci j'avais juste besoin d'un exemple avec ces deux lignes :

    SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast< LONG >(pObj));

    CFenetre *pObj = reinterpret_cast< CFenetre * >(GetWindowLong(hWnd, GWL_USERDATA));

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    J'ai retrouvé mon exemple plus complexe (un poil simplifié).
    Note: Ici, je ne stocke plus le pointeur à GWL_USERDATA, mais à zéro. Pour ça, il faut penser à régler cbWndExtra avant d'appeler RegisterClass() ou RegisterClassEx()...
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Player
    {
    public:
    	Player();
    	static bool registerClass(HINSTANCE hInst, bool bAllowAlready);
     
    	static LRESULT CALLBACK SProc(HWND, UINT, WPARAM, LPARAM);
    	virtual LRESULT proc(UINT, WPARAM, LPARAM);
     
    private:
    	HWND _hwnd;
    };
    Code C++ : 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
    //Note: J'ai ajouté la taille d'un Player* à cbWndExtra
    //[static]
    bool Player::registerClass(HINSTANCE hInst, bool bAllowAlready)
    {
    	WNDCLASSEX wincl;
     
    	wincl.hInstance = hInst;
    	wincl.lpszClassName = CLASSNAME;
    	wincl.lpfnWndProc = SProc;
    	wincl.style = CS_DBLCLKS;
    	wincl.cbSize = sizeof(wincl);
    	wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    	wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wincl.lpszMenuName = NULL;
    	wincl.cbClsExtra = 0;
    	wincl.cbWndExtra = sizeof(Player *); // <--- ici!
    	//Ne pas oublier le +1...
    	wincl.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
     
    	if(!RegisterClassEx(&wincl))
    	{
    		if(!bAllowAlready || GetLastError()!=ERROR_ALREADY_EXISTS)
    			return false;
    	}
    	return true;
    }
     
    //[static]
    LRESULT CALLBACK Player::SProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	LRESULT ret = 0;
    	Player * pOwner = reinterpret_cast< Player * >(GetWindowLongPtr(hWnd, 0));
     
    	if(message==WM_CREATE)
    	{
    		CREATESTRUCT const * pcCS = reinterpret_cast< CREATESTRUCT const * >(lParam);
    		pOwner = static_cast< Player * >(pcCS->lpCreateParams);
     
    		SetWindowLongPtr(hWnd, 0, reinterpret_cast< LONG_PTR >(pOwner));
    		assert(pOwner->_hwnd==NULL || pOwner->_hwnd==hWnd);
    		pOwner->_hwnd = hWnd;
    	}
     
    	if(pOwner)
    		ret = pOwner->proc(message, wParam, lParam);
    	else
    		ret = DefWindowProc(hWnd, message, wParam, lParam);
    	return ret;
    }
     
    //[virtual]
    LRESULT Player::proc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    	LRESULT ret = 0;
    	assert(this != NULL);
     
    	switch(message)
    	{
    		case WM_CREATE:
    			break;
     
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			break;
     
    		default:
    			ret = DefWindowProc(_hwnd, message, wParam, lParam);
    	}
    	return ret;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    A quoi sert de faire comme celà plutôt qu'avec GWL_USERDATA ?
    C'est pour laisser l'emplacement vide pour pouvoir stocker autre chose dans GWL_USERDATA ?

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Oui.
    C'est surtout utile quand tu développes tes propres classes de contrôles, car si je me souviens bien, GWL_USERDATA est supposé être également disponible pour l'utilisateur d'un contrôle (en clair, il me semble bien que tu peux utiliser le GWL_USERDATA d'un bouton).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    ok merci ça marche bien

Discussions similaires

  1. [C#]Remonter des événements dans des classes imbriquées
    Par Kcirtap dans le forum Windows Forms
    Réponses: 9
    Dernier message: 14/12/2013, 12h43
  2. Réponses: 4
    Dernier message: 29/05/2009, 00h17
  3. distribution d'elements dans des classes
    Par christine1985 dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 31/08/2006, 11h15
  4. distribution d'elements dans des classes
    Par christine1985 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 28/08/2006, 17h57
  5. [WSDL][Axis] Récupération de valeur dans des classes java
    Par cosmos38240 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 09/01/2006, 17h38

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