Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 12 sur 12
  1. #1
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut win32 - Gestion des messages sans procedure de fenetre -

    Bonjours a tous.
    Mon message concerne l'API Win32.
    J'aurai voulu savoir si il etait possible de gerer les messages(WM_COMMAND, WM_USER, ect...) sans avoir a utiliser du tout la procedure de fenetre "LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)" ?
    Le tout en C/C++ evidement. Je ne parle pas de MFC, DotNet, ect...

    Merci

    ps : je precise que je connais deja un peu, mais pas beaucoup, cette API ayant realiser avec il y a quelque temps un petit moteur de jeu 2D et quelques autres petites applications.

    Il me semble qu'avec les MFC, que je ne connais pas, la procedure de fenetre ne soit pas utilisee. Savez vous comment cela fonctionne en interne ?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    juin 2002
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : juin 2002
    Messages : 129
    Points : 252
    Points
    252

    Par défaut

    Bonjour.

    L'API Win32 offre deux fonctions de base pour recevoir les messages :
    GetMessage et PeekMessage.

    La première attend qu'un message soit disponible avant de revenir, la seconde revient tout de suite même s'il n' y a pas de message disponible.

    Voir la MSDN à leur sujet.

  3. #3
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Merci pour ta reponse, mais ca n'etait pas ma question. Je connais GetMessage() et PeekMessage().
    Je demandais si il etait possible de se passer de la procedure de fenetre LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM) pour le traitement des message WM_... , est-ce qu'il existe des fonctions dans l'API qui permet le traitement des messages d'une maniere differente ?

  4. #4
    Rédacteur/Modérateur
    Avatar de Melem
    Homme Profil pro Jessee Michaël Christian Edouard
    Ingénieur développement logiciels
    Inscrit en
    janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Nom : Homme Jessee Michaël Christian Edouard
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : janvier 2006
    Messages : 3 656
    Points : 7 427
    Points
    7 427

    Par défaut

    GetMessage et PeekMessage piquent le message actuellement en tête de file dans la queue de messages du thread courant. On en fait ensuite ce qu'il nous plaît. Cela veut très bien dire qu'avoir une WndProc n'est pas intrinsèquement indispensable dans une application Windows. Cependant, tous les messages ne passent pas obligatoirement par la queue des messages. Au contraire, la majorité des messages sont directement envoyés vers les fenêtres, c'est-à-dire directement vers les procédures de fenêtre. Généralement, Windows met dans la queue des messages les événements liés aux entrées de l'utilisateur (les keydown, mousemove, etc.) et tout ce qu'ils provoquent (WM_CHAR, WM_COMMAND, etc.), ainsi que certains messages non prioritaires (WM_TIMER, WM_PAINT, etc.). Les autres vont directement chez leur destinataire. Cette différence se voit également au niveaux de certaines APIs et non seulement au niveau des notifications. Par exemple, SendMessage appelle directement la procédure de fenêtre alors que PostMessage place un message dans la queue des messages. La procédure de fenêtre est donc finalement indispensable, en pratique .

  5. #5
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Ok, merci. Je me doutais bien qu'elle etait indispensable... En fait, je suis en train de me fabriquer un petit framework et je voudrais pouvoir encapsuler dans mes classes(CMenu, CButton, ect...) des fonctions qui traitent les messages (CMenu::OnClick(), CButton::Onclick(), ect...), sans rien avoir a rajouter dans la procedure de fenetre lorsque j'utilise mon framework.
    Je crois avoir trouve la solution a l'aide d'un container de struct contenant, entre autre, des pointeurs de fonction, et l'identite du message, et ce container sera place dans la procedure de fenetre et je le remplirai a l'utilisation du framework et non pendant sa compilation... Je ne sais pas si c'est clair.. Je vais voir ce que cela donne.

    Merci encore pour vos reponses :-)

  6. #6
    Rédacteur/Modérateur
    Avatar de Melem
    Homme Profil pro Jessee Michaël Christian Edouard
    Ingénieur développement logiciels
    Inscrit en
    janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Nom : Homme Jessee Michaël Christian Edouard
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : janvier 2006
    Messages : 3 656
    Points : 7 427
    Points
    7 427

    Par défaut

    Il y a quelques années je me suis amusé à faire un truc de ce type, et je m'en suis même longtemps servi. Les sources se trouvent sur le forum C++ : Encapsuler l'API Windows. Ce code a été écrit alors que je débutais en C++ donc ne sois pas surpris de voir des horreurs comme une struct dans une classe là où on aurait pu utiliser l'héritage, etc. A part ce détail, il aura au moins le mérite de mettre en évidence l'architecture des frameworks ou des libs telles que la VCL ou les MFC . Et bien sûr n'hésite pas s'il y a des choses que tu ne comprends pas.

  7. #7
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Merci, je vais y jeter un œil :-)

  8. #8
    Expert Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 908
    Points : 31 936
    Points
    31 936

    Par défaut

    Attention, le prototype de la DialogProc est obsolète; il faut retourner un INT_PTR de nos jours (à cause des messages WM_CTLCOLORxxx)
    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 éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Citation Envoyé par Médinoc Voir le message
    Attention, le prototype de la DialogProc est obsolète; il faut retourner un INT_PTR de nos jours (à cause des messages WM_CTLCOLORxxx)
    Le prototype etait celui de la procedure de fenetre et pas celui d'une boite de dialogue quelconque.

    Sinon, sauriez vous combien il y a de WM_... en tout ? La question peut paraitre saugrenue, mais j'ai vraiment besoin de le savoir. Je n'ai pas trouve la reponse sur msdn, ni ailleurs sur le web...

    Merci.

  10. #10
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Voila ma solution afin de gerer les messages sans avoir a remplir la procedure de fenetre lorsque j'utilise mon framework. C'est pour l'instant tres basique, je voulais juste poser les bases.
    Dites moi ce que vous en pensez, et si vous auriez fais autrement,dites moi comment vous auriez fait.

    Code :
    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
    //
    // Xevents.h
    
    // Voici la structure qui s'occupe de la gestion des messages. Les messages 
    // sont stockes dans un tableau XArray.
    
    #ifndef X_EVENTS_H
    #define X_EVENTS_H
    
    #include "Xdefs.h"
    #include "Xarray.h"
    
    X_NAMESPACE_BEGIN
    
    struct XEvent{
    	
    	inline XEvent() : Type(0), Name(nullptr){}
    	inline ~XEvent() { X_DELETE_POINTER_ARRAY(Name) }
    	
    	Xbool (*Event)(HWND wnd, WPARAM wPAram, LPARAM lParam);
    	
    	Xuint Type;
    	Xchar* Name;
    	static XArray<X::XEvent> EventsArray;
    };
    
    XArray<X::XEvent> XEvent::EventsArray(100);
    
    X_NAMESPACE_END
    #endif

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    LRESULT CALLBACK XWindow::WindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	for(Xint i=0; i<X::XEvent::EventsArray.Size(); i++)
    	{
    		if(msg == X::XEvent::EventsArray[i].Type)
    		{
    			if(X::XEvent::EventsArray[i].Event(wnd, wParam, lParam))
    			    return 0;
    		}
    	}
    	return DefWindowProc(wnd, msg, wParam, lParam);
    		
    }
    Code :
    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
    //
    // main.cpp
    // Je commence avec main et non WinMain. WinMain est charger par ma lib. Je me suis inspire de QT sur ce coup la, si un jours je veux rendre mon code portable, ca sera plus facile...
    
    #include "../X.h"
    
    Xbool Event_Escape(HWND wnd, WPARAM wParam, LPARAM lParam);
    Xbool Event_Destroy(HWND wnd, WPARAM wParam, LPARAM lParam);
    
    int main(int argc, char** argv)
    {
    	X::XApplication app(argc, argv); // initialisation du programme.
    
    	X::XWindow* window; // Creation de la fenetre.
    	window = new X::XWindow("X_Window");
    	window->Create(150, 150, 640, 480);
    	window->Show(SW_SHOW);
    
    	X::XEvent event1;
    	event1.Type = WM_KEYDOWN;
    	event1.Name = "ESCAPE";
    	event1.Event = &Event_Escape;
    	X::XEvent::EventsArray.Append(event1);
    
    	X::XEvent event2;
    	event2.Type = WM_DESTROY;
    	event2.Name = "DESTROY";
    	event2.Event = &Event_Destroy;
    	X::XEvent::EventsArray.Append(event2);
    
    	app.Exec(X::GETMESSAGE); // Je lance la boucle de message 
                                                                                                       
           delete window;
           return EXIT_SUCCESS;
    	
    }
    
    Xbool Event_Escape(HWND wnd, WPARAM wParam, LPARAM lParam)
    {
    	X_UNUSED_TYPE(lParam);
    
    	if(X_ON_CLICK(VK_ESCAPE)){
    		DestroyWindow(wnd);
                    return true;
             }
             return false;
    }
    
    
    Xbool Event_Destroy(HWND wnd, WPARAM wParam, LPARAM lParam)
    {
    	X_UNUSED_TYPE(wParam);
    	X_UNUSED_TYPE(lParam);
    
    	ReleaseDC(wnd, X::XWindow::GetDeviceContext());
    	PostQuitMessage(0);
    
            return true;
    }

  11. #11
    Expert Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 908
    Points : 31 936
    Points
    31 936

    Par défaut

    J'ai l'impression qu'un tel code donne des événements communs à tous les types de fenêtre.

    Et en plus, ça remplit le tableau en run-time, alors qu'il peut être défini en compile-time comme le fait MFC (mais MFC utilise un tableau "Message Map" par classe de fenêtre).

    Aussi, je ne suis pas sûr qu'une recherche linéaire soit la meilleure idée pour ça. Vu que le tableau n'est modifié qu'au début et qu'il est consulté très souvent, tu devrais au moins en faire un tableau trié et faire une recherche dichotomique dessus (avec bsearch() en C ou std::binary_search<>() en C++).

    Edit: J'ai du mal à voir l'utilité du nom, aussi. Surtout que tu y mets une chaîne littérale et que tu sembles faire un delete dessus dans le destructeur...
    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.

  12. #12
    Membre éclairé Avatar de nikau6
    Homme Profil pro
    Inscrit en
    février 2008
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2008
    Messages : 152
    Points : 301
    Points
    301

    Par défaut

    Merci pour ta reponse. Pour le run time tu as raison. Sinon, pour le reste, j'ai bien dit que ce n'etait qu'une base, je vais bien evidement l'optimiser. En tous les cas, merci pour les pistes :-)

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •