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 :

Ouverture de fenetre sous windows


Sujet :

Windows

  1. #1
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut Ouverture de fenetre sous windows
    Bonjour !

    Je developpe une petite appli sous windows, sans utiliser les MFC.

    Je souhaite ouvrir une fenetre du type pop-up pour y mettre des outils de l'application (genre comme les palettes flottantes de photoshop)

    Pour ce faire, je declaire une window class :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    maWindowClass.style			= 0;
    maWindowClass.lpfnWndProc		= maFonction;
    maWindowClass.cbClsExtra		= 0;
    maWindowClass.cbWndExtra		= 0;
    maWindowClass.hInstance				= parentHINSTANCE;
    maWindowClass.hIcon			= NULL;
    maWindowClass.hCursor			= NULL;
    maWindowClass.hbrBackground		= (HBRUSH)(1 + COLOR_BTNFACE);
    maWindowClass.lpszMenuName    		= NULL;
    maWindowClass.lpszClassName    			= "Ma fenetre";
    Puis j'ouvre ma fenetre avec createWindow()

    Ma fenetre est ouverte par une fonction contenue dans une classe, qui contient dans ses données les infos sur la fenetre, du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    maClasse
    {
    	pleinsDeFonctionsEtDeVariables
    
    	WNDCLASS			maWindowClass;
    	HWND				maWindowHWND;
    }
    Je souhaiterais maintenant que la fonction "maFonction" fasse partie de la classe, et c'est là que ca coince !

    Si je declare un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    maClasse
    {
    	pleinsDeFonctionsEtDeVariables
    
    	WNDCLASS			maWindowClass;
    	HWND				maWindowHWND;
    	LRESULT CALLBACK			maFonction(HWND, UINT, WPARAM, LPARAM);
    }
    J'obtiens ces 2 erreurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    error C3867: &'maClasse::maFonction' : liste d'arguments manquante dans l'appel de fonction ; utilisez 'maClasse::maFonction' pour créer un pointeur vers membre
    
    error C2440: '=' : impossible de convertir de 'LRESULT (__stdcall maClasse::* )(HWND,UINT,WPARAM,LPARAM)' en 'WNDPROC'

    Pourquoi ? Comment ? Je ne vois pas le rapport !

    J'ai essayé avec differentes notations, pointeurs.... imposssible de donner l'adresse d'une fonction membre de la classe à ce parametre : maWindowClass.lpfnWndProc

    Y'a-t-il une raison precise ? Ou je m'y prend mal ?

    PS : je peux m'en passer, mais j'aimerais regrouper toutes les fonctions utiles à un objet dans sa classe, histoire que ce soit plus propre...

  2. #2
    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
    Ce n'est pas évident.
    Une WNDPROC intégrée à une classe doit être static, mais dans ce cas tu n'as plus le pointeur avec.
    Le mieux, c'est de passer le pointeur en paramètre de CreateWindow(), et de l'enregistrer avec SetWindowLong() dans le traitement de WM_CREATE (Tu peux utiliser l'index GWL_USERDATA, ou directement des données dédiées avec le membre cbWndExtra de la WNDCLASS). Et dans le traitement des autres messages, tu fais un GetWindowLong() pour obetnir le pointeur (qui sera NULL tant que la fenêtre n'aura pas reçu le WM_CREATE. C'est le cas notamment à la création: La fenêtre reçoit généralement un WM_GETMINMAXINFO en premier).
    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.

  3. #3
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Merci !

    Mais euh, ça ne me parait pas super clair tout ca...

    Je vais y regarder de plus pres !

    Si d'ici là, tu peux me donner plus de details, tant mieux !

    En fait, je voudrais surtout que les données de la classe soient accessibles à cette fonction.

    En terme d'optimisation/facilité de code, quelle est la meilleure methode ?

    * utiliser une fonction de la classe en tant que WNDPROC (comme ça elle a accès aux memebres de la classe)

    ou

    * passer en parametre à la fonction WNDPROC un pointeur sur l'instance de la classe à laquelle je veux acceder ?

    Merci !

  4. #4
    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
    Tu ne comprends pas: une WNDPROC a une liste de paramètre fixe, et comme c'est une fonction C à la base, elle ne peut pas être "livrée" avec l'objet.
    Le seul moyen, c'est de mémoriser un pointeur vers l'objet pour le récupérer à chaque appel.
    Pour mémoriser des données associées à une fenêtre, rien de tel que SetWindowLong()/GetWindowLong(). Et pour passer ces données à la fenêtre en premier lieu, il y a le dernier paramètre de CreateWindow(), que tu peux retrouver avec les données du message WM_CREATE.
    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.

  5. #5
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Merci pour les explications...

    Du coup, je vais simplement passer un pointeur sur l'instance de la classe à laquelle je veux acceder grace à la fonction CreateWindow, ça va etre plus simple...

    Du coup, une question me brule les levres :

    Si j'ouvre plusieurs fenetres en meme temps, qu'elles font toutes appel à la meme fonction de traitement des messages, mais que chacune est sensée traiter les données d'instances différentes d'une meme classe, que se passe-t-il ?

    La fonction est-elle "dupliquée" ....

    Enfin, je sais pas si tu saisi bien mon probleme, mais je souhaite pouvoir ouvrir plusieurs fois simultanement le meme type de pop-up (par exemple ouvrir 2 popup de selection de couleur : 1 pour le fond, 1 pour le premier plan)

    Vu que ces 2 popups ont le meme but, autant en faire une classe et creer des instances... non ?

  6. #6
    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
    La fonction est toujours unique, c'est pourquoi dès qu'on fait plusieurs fenêtres de la même WNDCLASS (donc avec la même WNDPROC), il ne faut pas utiliser de variables locales static pour mémoriser des données. SetWindowLong() et GetWindowLong() résolvent le problème en mémorisant des données spécifiques à une fenêtre.

    En fait, il te faut un truc de ce style:
    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
    class CFenetre
    {
    public:
    	BOOL RegisterWndClass(void);
    	LPCTSTR GetClassName(void);
    private:
    	static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    private:
    	int m_uneDonnee;
    	long m_uneAutreDonnee;
    };
     
     
    LRESULT CALLBACK CFenetre::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    LRESULT lrRetour = 0;
    //Attention, pObj peut être NULL;
    CFenetre *pObj = reinterpret_cast< CFenetre * >(GetWindowLong(hWnd, GWL_USERDATA));
     
    switch(uMsg)
    	{
    	case WM_CREATE:
    		{
    		LPCREATESTRUCT pCs = reinterpret_cast< LPCREATESTRUCT >(lParam);
    		pObj = static_cast< CFenetre * >(pCs->lpCreateParams);
    		SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast< LONG >(pObj));
    		}
    		break;
     
    	case WM_UN_MESSAGE:
    		if(pObj)
    			{
    			FaireUnTruc(pObj->m_uneDonnee);
    			}
    		break;
     
    	case WM_UN_AUTRE_MESSAGE:
    		if(pObj)
    			{
    			FaireUnAutreTruc(pObj->m_uneAutreDonnee);
    			}
    		break;
     
    	default:
    		lrRetour = DefWindowProc(hWnd, uMsg, wParam, lParam);
    		break;
    	}
    return lrRetour;
    }

    Je préviens, je n'ai même pas essayé de compiler. Mais c'est l'idée générale...

    Edit: Pour compatibilité avec les Windows récents, il faut utiliset SetWindowLongPtr() à la place de SetWindowLong().
    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.

  7. #7
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Merci beaucoup !

    Je sais pas pourquoi, mais je sens que cette fois je vais y arriver...

    En fait je pense avoir vraiment compris le principe avec ton bout de code.

    Je teste tout ca ce soir !

Discussions similaires

  1. [Débutant] Ouverture des .fig sous windows
    Par lemax911 dans le forum MATLAB
    Réponses: 0
    Dernier message: 21/06/2011, 11h42
  2. Ouverture de fichiers sous Windows
    Par F0ul dans le forum C
    Réponses: 4
    Dernier message: 13/06/2010, 13h28
  3. Réponses: 0
    Dernier message: 15/03/2010, 16h15
  4. empecher l'ouverture de la fenetre DOS sous windows
    Par fairlight dans le forum Windows
    Réponses: 3
    Dernier message: 04/08/2006, 14h13
  5. Probléme d'ouverture de session sous Windows 2000 server
    Par Orameur dans le forum Windows XP
    Réponses: 1
    Dernier message: 25/02/2006, 19h15

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