begin process at 2012 05 27 15:05:26
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Tutoriaux

 > C/C++ SOUS WINDOWS SANS MFC TUTORIAL 1

C/C++ SOUS WINDOWS SANS MFC TUTORIAL 1


 Information sur la source

Note :
9,29 / 10 - par 7 personnes
9,29 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Tutoriaux Classé sous :tutorial, mfc, windows Niveau :Débutant Date de création :26/06/2004 Date de mise à jour :26/06/2004 23:46:37 Vu / téléchargé :18 631 / 1 248

Auteur : LaPatoshe

Ecrire un message privé
Commentaire sur cette source (19)
Ajouter un commentaire et/ou une note

 Description

J'ai pas mal galéré pour comprendre le fonctionnement de C ou C++ sous Windows sans faire usage de MFC. Ce premier tutorial explique les bases de la programmation Windows avec C ou C++ . Il contient une introduction et une partie explicative générale de la programmation windows, suivi d'un exemple simple commenté. Il contient également quelques annotations pour ceux qui viennent de Visual Basic 5 ou 6.

Source

  • /*TUTORIAL C sous WINDOWS
  • Leçon 1
  • Pour bien comprendre ce Tutorial il est utile de connaitre le C sous DOS au niveau des appels de fonction, et des pointeurs. Plusieurs rapprochements avec Visual Basic sont également effectués, mais ce tutorial ne nécessite en aucun cas l'apprentissage de ce langage.
  • Introduction
  • La Programmation C ou C++ sous windows semble relativement complexe lorsque l'on vient de la programmation C sous MS DOS, ou d'autres langages évolués tels que Visual Basic.
  • Pour ma part, j'ai débuté la programmation PC avec Visual Basic. Ce langage permet de créer des application répidement sous Windows, car tous les éléments de feuille, de contrôle et autre peuvent se créer en un click de souris. Ensuite, il ne reste plus qu'à rajouter à ces éléments des valeur de propriété (taille de feuille, texte, couleur, aspect,...) et des méthodes d'évènement (Click, Change, GetFocus...)
  • Sous Windows, la programmation en C ressemble à Visual Basic, seulement nos éléments ne seront plus créés en cliquant dans une boite à outils et en rajoutant du code, mais en codant la totalité de notre programme qui sera composé au moins de deux grandes parties : La partie Création et Réception des Messages et la partie Traitement des Messages.
  • Tout cela va vous sembler nouveau, mais vous allez normalement très vite vous y faire.
  • I) Structure d'un Programme Windows.
  • Windows est un système d'exploitation multitache (c'est à dire qu'il permet de faire tourner plusieurs applications en même temps) et qui réagit à des évènements causés par l'utilisateur (Click de la souris, appuis d'une touche du clavier, relachement d'une touche, mouvement de la souris...), ou par l'ordinateur lui même (temps écoulé, fin d'impression de l'imprimante...)
  • Lorsqu'on programme en C sous Windows, il faut créer une application dans laquelle les évènements seront attendus, et aussi dans laquelle ces évènements seront traduit pour donner lieu à des actions que vous souhaitez. Il faut donc pour cela créer deux Procédures qui sont les suivantes :
  • Procédure de Réception des Messages
  • int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  • {
  • }
  • Procédure de Traitement des Messages
  • LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam)
  • {
  • }
  • Lorsque vous lisez ces deux procédures si vous n'avez fait jusqu'à présent que du C ou C++ sous Dos, vous allez dire Qu'est ce que c'est que ce M.......
  • Ne nous affolons pas, j'ai oublié de vous parler d'une chose assez importante. Dans Windows, la programmation se fait à l'aide de l'API. l'API est une bibliothèque de fonctions servant à communiquer avec Windows. Seulement, on ne communique pas avec l'API en utilisant des fonctions simples telles que int Resultat(int NombreA, facteur, int NombreB). l'API le plus souvent possède ses propres type de variables. Par exemple, le type LPSTR de la fonction WinMain est en fait un type de chaine de caractère. Il est pour certaines et peut être la plupart des fonctions de l'API totalement compatible avec une chaine de caractère déclarée en char *. Si vous créez par exemple une chaine de caractère en utilisant char*, elle pourra être passée en paramètre dans une fonction de l'API demandant comme paramètre une chaine de type LPSTR. Il existe comme vous pouvez le voir dans les deux fonctions WinMain et WinProc d'autres types inconnus du monde MS DOS comme HINSTANCE, WPARAM, LPARAM, UINT) , nous les commenterons au fur et à mesure.
  • Donc, pour en revenir à nos deux fonctions WinMain et WinProc, ce sont elles qui vont gérer tout notre programme.
  • WinMain va contenir au moins deux choses :
  • _ La Création de l'application à son démarrage
  • _ Une boucle d'attente des Messages
  • La Création de l'application à son démarrage, c'est généralement la création d'une feuille avec dessus des controles tels que des boutons, des zones de texte ...
  • Nous nous contenterons pour cette première leçon d'une simple feuille vide.
  • La Boucle d'attente des Messages c'est tout simplement une boucle du style while.
  • Dans cette boucle, on va demander via une fonction de l'API, que Windows envoie tous les évènements vers la procédure WinProc qui va les traiter.
  • WinProc va contenir la chose suivante :
  • _ Un ensemble de branchement du type Switch Case
  • Cet ensemble va permettre à l'utilisateur de dire ce qu'il veut voir se passer lorsque tel ou tel évènement est envoyé. Pour les arrivant de Visual Basic, cela correspond aux méthodes d'évènements.
  • Une différence est à noter, c'est qu'il n'y a pas à la base de méthode d'évènement pour chaque contrôle d'une feuille. Il y a un évènement global qui envoie un message contenant le nom du controle concerné.
  • Nous verrons cela en détail un peu plus loin.
  • II) Notre premier Programme Windows
  • Pour parler avec l'API de Windows et donc utiliser ses fonctions un peu tordues, et ses types de variables sorties d'on ne sait où il faut inclure deux fichiers d'En-tête
  • */
  • #include <windows.h>
  • #include <windowsx.h>
  • /* Puis, nous allons déclarer les prototype de nos deux fonctions principales. Oui, on le fait, même si ces fonctions sont contenues dans l'API. C'est un peut comme lorsque on utilise directement l'API depuis Visual Basic, on Déclare quand même les fonctions à utiliser. Je vais les commenter une par une.
  • */
  • int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
  • /* Cette fonction est la fonction principale de Windows. C'est la même que la fonction main pour un programme DOS. Elle attend un int en retour comme pour les programmes console, on retournera 0 à la fin de l'application pour indiquer à Windows qu'on est sorti du programme sans encombre. Vient ensuite le mot WINAPI . Alors, là, j'ai pas trop d'explications à donner si ce n'est une sorte de protocole à indiquer à Windows. Sachez pour l'instant uniquement qu'il faut le mettre dans la fonction principale.
  • WinMain est donc le nom de la fonction (à bien respecter). Ensuite viennent des paramètres un peu bizarre.
  • hInstance de type HINSTANCE correspond à l'application elle même. Si hInstance était égal à 0 cela voudrait dire que l'application ne fonctionne pas. C'est une sorte de pointeur indiquant combien de fois le programme est chargé (Rappelons le on est en multitache).
  • hPrevInstance de type HINSTANCE également est un peu la même chose, mais est actuellement reclus car il était utilisé sous les anciens systèmes en 16 bits.
  • LPSTR lpCmdLine est comme nous l'avons vu une chaine de caractère. elle correspond à la chaine de caractère qu'on peut entrer à la suite d'un lancement de programme. Si vous éxécutiez Word par exemple et que vous le lanciez sans utiliser l'icone mais en tapant dans Programme/Exécuter word.exe fichier.doc, word s'éxécuterait et fichier.doc serait chargé dans word. lpCmdLine contiendrait alors "fichier.doc".
  • Le dernier paramètre nCmdShow est de type int. Je n'ai pas de précisions sur lui pour l'instant, mais ce paramètre nous le verrons est utilisé lors de la création des fenêtres et contrôles.
  • Déclarons maintenant le prototype de la fonction de traitement des messages
  • */
  • LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  • /* Comme pour la précédente, cette fonction attend un retour. Le type de ce retour est ici LRESULT, qui est apparement spécifique au retour d'une procédure de traitement de messages Windows.
  • CALLBACK est comme WINAPI une sorte de protocole. WinProc est le nom de la procédure qui va traiter les messages envoyés par WinMain.
  • Voici ses paramètres :
  • _HWND hWnd : HWND est une sorte de pointeur sur un objet. Dans Visual Basic on appelle une fenetre par son nom, un bouton par son nom... En C sous Windows, on appelle généralement les choses par leur Handle. Il s'agit d'un pointeur désignant un objet.
  • _ UINT uMsg : C'est le message envoyé par WinMain. La valeur contenue par ce message sera de type UINT qui est en fait une appellation de l'API pour le type unsigned int. La valeur de uMsg va désigner l'évènement qui vient de se produire.
  • _ wParam est un paramètre lié au Message envoyé. Il est de type WPARAM c'est une sorte d'entier long.
  • _lParam est aussi lié au Message envoyé . Ils vont contenir par exemple les positions de la souris lors d'un évènement MouseMove, le code de la touche enfoncée lors d'un évènement KeyDown...
  • Cette Procédure WinProc va en somme recevoir de WinMain l'objet concerné par l'évènement (hWnd), le nom de l'évènement (uMsg), deux paramètres précisant l'évènement (wParam et lParam).
  • Voici maintenant la suite du programme avec le contenu de la Procédure WinMain. Nous allons créer une fenêtre, puis la charger et enfin la faire apparaitre à l'écran. Nous placerons ensuite la boucle d'attente de messages.
  • */
  • bool stop = false; /* Je place cette variable globale ici qui indique si le programme se termine ou non, nous verrons son utilité plus tard*/
  • int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  • {
  • /*On créé d'abord les variables dont nous aurons besoin et pour la fenêtre et pour la boucle des messages après.*/
  • HWND hFenetre; /* Il va s'agir du Handle qui contiendra l'objet Fenetre que nous créérons.*/
  • MSG MessagesAEnvoyer; /*Il s'agit de la variable de type MSG qui sera envoyée à WinProc lorsque un évènement arrivera. */
  • /*
  • Pour créer une fenêtre dans une application Windows, il faut trois phases:
  • _ La déclaration avec implémentation de certaines propriétés
  • _ L'Enregistrement en mémoire en utilisant une fonction de l'API
  • _ La Création finale en utilisant une fonction de l'API.
  • Ne vous inquiétez pas, on va décortiquer.
  • La création de la fenêtre avec implémentation des propriétés donne ce qui suit :
  • */
  • WNDCLASS Fenetre; /* Déclaration de Fenetre, objet de la Structure WNDCLASS.*/
  • Fenetre.lpszMenuName =NULL; /* Il s'agit d'une propriété indiquant le nom du menu que la fenêtre doit contenir. Ici, il n'y en aura pas.*/
  • Fenetre.cbClsExtra =0; /* Je laisse ce paramètre propre à Windows à 0*/
  • Fenetre.cbWndExtra =0; /* Je laisse ce paramètre propre à Windows à 0*/
  • Fenetre.hInstance = hInstance; /* J'indique que la fenêtre va fonctionner dans l'actuel programme.*/
  • Fenetre.lpfnWndProc = WinProc; /* J'indique le nom de la procédure vers laquelle seront envoyés les messages Windows propres à cette fenêtre.*/
  • Fenetre.lpszClassName = "FENETRE DE TYPE A MOI"; /* J'indique le nom que va porter le type de Fenêtre que je suis en train de créer actuellement. */
  • Fenetre.style = CS_VREDRAW | CS_HREDRAW; /* J'indique que la fenêtre devra être redessinée à chaque modification de la fenêtre.*/
  • Fenetre.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  • /*hBackGround est la couleur de fond de la fenêtre. On utilise la couleur WHITE_BRUSH. WHITE_BRUSH on ne sait pas ce que c'est vu comme ça, mais en utilisant la fonction GetStockObject de l'API, le retour va correspondre à une donnée. Cette donnée castée en (HBRUSH) v a être compatible pour cette propriété de hBackGround ce qui donnera à notre fenêtre la couleur blanche. Pour désigner une couleur sinon, il aurait fallut caster en HBRUSH un nombre Hexadécimal correspondant à la couleur demandée, mais les héxa, c'est un peu galère à se rappeler. (En Visual Basic, je préfère utiliser RGB(a,b,c) plutôt que &HF00...)*/
  • Fenetre.hIcon =(HICON) LoadIcon(hInstance, IDI_APPLICATION);
  • /*hIcon est la forme de l'icone qui va se trouver dans le bandeau de notre fenêtre. En utilisant la fonction LoadIcon de l'API, à laquelle on envoie l'instance du programme et la valeur IDI_APPLICATION, on obtiendra une donnée qui castée sous la forme (HICON) sera compatible avec Fenetre.hIcon.*/
  • Fenetre.hCursor =(HCURSOR) LoadCursor(hInstance, IDC_ARROW);
  • /*Ici, c'est la même chose que pour hIcon, on indique que l'on veut IDC_ARROW comme pointeur de souris soit une flèche. Il existe également IDC_WAIT, IDC_CROSS...*/
  • /* Voilà, nous venons de créer un type de fenêtre propre à nous qui s'appelle Fenetre. Mais Fenetre n'est pas une fenêtre à part entière. Il s'agit en fait d'une sorte de modèle dont le nom usuel est "FENETRE DE TYPE A MOI".
  • Pour créer une fenêtre prête à être affichée, il faut en premier lieu l'enregistrer en mémoire*/
  • RegisterClass(&Fenetre);
  • /* Ne me demandez pas pourquoi il faut faire cela, je n'en sais rien, je sais uniquement qu'il s'agit d'une étape obligatoire avant de vraiment créer la fenêtre. l'API a apparement besoin d'enregistrer la fenêtre via la fonction RegisterClass pour la continuation de notre création.
  • Vient ensuite l'étape finale : la création finale de notre fenêtre.
  • Dans cette partie, nous allons attribuer un handle à notre fenêtre, en la créant à l'aide de la fonction CreateWindow de l'API, et en passant comme paramètre pour cette création non pas l'objet Fenetre, mais son nom de baptème FENETRE DE TYPE A MOI. C'est peut être pour cela qu'il fallait l'enregistrer dans l'étape deux avec RegisterClass.*/
  • hFenetre = CreateWindow("FENETRE DE TYPE A MOI", "Voici la fenêtre", WS_OVERLAPPEDWINDOW, 200, 200, 300, 250, NULL, NULL, hInstance, NULL);
  • /*Je commente :
  • hFenetre c'est le Handle désignant notre fenêtre qui va se créer. Ce Handle comme je l'ai déjà dit va servir à nommer notre fenêtre dans la plupart des fonctions de l'API.
  • CreateWindow : C'est la fonction qui va créer notre fenêtre.
  • "FENETRE DE TYPE A MOI" : C'est le nom que l'on a donné à notre type de Fenetre dans l'étape 1.
  • CreateWindow se sert de cela pour savoir quel type de fenêtre créer.
  • "Voici la fenêtre": C'est la chaine de caractère que l'on veut voir apparaitre dans le bandeau
  • WS_OVERLAPPEDWINDOW : Il s'agit d'un paramètre qui va indiquer comment notre fenêtre doit apparaitre. (Avec ou sans bandeau, avec ou sans bouton de controle...). Ici, elle sera complète (bandeau, redimensionnable, avec boutons d'agrandissement, de réduction et de fermeture)
  • 200,200,300,250 : Il s'agit des coordonnées de notre fenêtre à l'écran. 200,200 : c'est le point en haut à gauche par rapport au bord gauche et haut de l'écran. 300 est la longueur de la fenêtre et ,250 la hauteur.
  • NULL,NULL, hInstance, NULL :
  • Cela correspond à :
  • FenêtreParent de type HWND, hMenu de type HMENU, Instance de l'appplication, Paramètre Windows de type LP VOID.
  • la Fenêtre Parent correspond à la fenêtre qui contiendrait la fenêtre que nous créons.
  • hMenu est le handle du menu de la fenêtre.
  • Instance est l'instance du programme
  • Paramètre Windows est utile apparement dans le cadre de la création d'une application en multidocuments nous ne nous y attarderons pas ici.
  • Pour notre exemple, vu que nous voulons une fenêtre toute simple, nous utiliserons donc les paramètres tels qu'ils sont dans l'exemple.
  • Maintenant que notre fenêtre est crée, il faut la faire apparaître à l'écran. On va utiliser pour cela la fonction de l'API ShowWindow. Il faut passer à cette fonction deux paramètres : le Handle de l'objet que l'on veut faire apparaître (ici hFenetre), et le paramètre de WinMain nShowCmd.*/
  • ShowWindow(hFenetre,nShowCmd);
  • /*Voilà, notre fenêtre est créée et peut apparaitre. Notre programme est cependant incomplet, voici la suite, la boucle d'attente des messages.
  • Si nous laissions tourner notre programme comme cela, la fenêtre apparaitrait à l'écran en un milliardième de seconde, et notre programme se terminerait. Il faut donc une boucle qui ne se terminera que si l'utilisateur clique par exemple sur la fermeture de la fenêtre.
  • Dans cette boucle, il faut insérer une procédure qui va capturer les évènements et les envoyer dans WinProc pour y être traités.*/
  • while (!stop)
  • {
  • GetMessage(&MessagesAEnvoyer, hFenetre, 0, 0); /* Cherche et lit les évènements liés à la fenêtre*/
  • TranslateMessage (&MessagesAEnvoyer); /* Traduit ces évènements*/
  • DispatchMessage (&MessagesAEnvoyer); /* Envoie ces évènements sous entendu dans WinProc)*/
  • }
  • return 0; /*fin du programme*/
  • }
  • /*Voilà, cette boucle va empêcher au programme de se terminer tant que la variable stop est à false. Le Programme est donc comme cela condamné à attendre les message d'évènement de la fenêtre et à les envoyer à WinProc
  • Nous allons donc maintenant voir la fonction WinProc
  • */
  • LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  • {
  • switch (uMsg) /* On s'interroge sur le message envoyé par Window.*/
  • {
  • /* A partir de maintenant, on va voir à quoi correspond ce message*/
  • case WM_DESTROY: /* Message de destruction de la fenêtre. Est envoyé lorsque la fenêtre se ferme (si l'utilisateur a cliqué sur la croix de fermeture par exemple)*/
  • {
  • stop = true ;/* On met stop = true pour terminer la boucle d'attente de message de WinMain*/
  • PostQuitMessage(0); /*Fonction de l'API indiquant à Windows que le programme va se terminer.*/
  • return 0; /*On renvoie 0 pour dire que le traitement du message a été effectué. */
  • }
  • }
  • return DefWindowProc(hWnd, uMsg, wParam, lParam); /*dans tout autre cas on renvoie le message tel quel*/
  • }
  • /* Nous venons de voir la procédure WM_DESTROY qui est un message de fermeture de notre fenêtre. Il s'agit d'un des messages les plus simples car nous n'avons utilisé aucun paramètre wParam ni lParam. Il existe plusieurs autres évènements qui aurait pu nous faire quitter l'appplication si nous l'aviosn voulu tel qu'un clique de souris dans la fenêtre, ou un mouvement de souris comme dans les écrans de veille. Nous verrons cela dans un prochain cours.*/
  • /*LISTING COMPLET DU PROGRAMME*/
  • #include <windows.h>
  • #include <windowsx.h>
  • int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
  • LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  • bool stop = false;
  • int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  • {
  • HWND hFenetre;
  • MSG MessagesAEnvoyer;
  • WNDCLASS Fenetre;
  • Fenetre.lpszMenuName =NULL;
  • Fenetre.cbClsExtra =0;
  • Fenetre.cbWndExtra =0;
  • Fenetre.hInstance = hInstance;
  • Fenetre.lpfnWndProc = WinProc;
  • Fenetre.lpszClassName = "FENETRE DE TYPE A MOI";
  • Fenetre.style = CS_VREDRAW | CS_HREDRAW;
  • Fenetre.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  • Fenetre.hIcon =(HICON) LoadIcon(hInstance, IDI_APPLICATION);
  • Fenetre.hCursor =(HCURSOR) LoadCursor(hInstance, IDC_ARROW);
  • RegisterClass(&Fenetre);
  • hFenetre = CreateWindow("FENETRE DE TYPE A MOI", "Voici la fenêtre", WS_OVERLAPPEDWINDOW, 200, 200, 300, 250, NULL, NULL, hInstance, NULL);
  • ShowWindow(hFenetre,nShowCmd);
  • while (!stop)
  • {
  • GetMessage(&MessagesAEnvoyer, hFenetre, 0, 0);
  • TranslateMessage (&MessagesAEnvoyer);
  • DispatchMessage (&MessagesAEnvoyer);
  • }
  • return 0;
  • }
  • LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  • {
  • switch (uMsg)
  • {
  • case WM_DESTROY:
  • {
  • stop = true ;
  • PostQuitMessage(0);
  • return 0;
  • }
  • }
  • return DefWindowProc(hWnd, uMsg, wParam, lParam);
  • }
  • /*Copiez ou faites un copier coller du programme dans un nouveau fichier C/C++ d'un Projet Window Application sous un IDE tel que Visual C++, Borland C++, DevC++.... Vous devez obtenir une fenêtre dont le bandeau affiche 'voici la fenêtre'. Cette fenêtre doit être de taille 300 / 250 et doit comporter les boutons de maximisation, minimisation et de fermeture. Elle doit également comporter une icone. Son fond doit être blanc.
  • */
/*TUTORIAL C sous WINDOWS
Leçon 1

                Pour bien comprendre ce Tutorial il est utile de connaitre le C sous DOS au niveau des appels de fonction, et des pointeurs. Plusieurs rapprochements avec Visual Basic sont également effectués, mais ce tutorial ne nécessite en aucun cas l'apprentissage de ce langage.

Introduction
	La Programmation C ou C++ sous windows semble relativement complexe lorsque l'on vient de la programmation C sous MS DOS, ou d'autres langages évolués tels que Visual Basic. 
	Pour ma part, j'ai débuté la programmation PC avec Visual Basic. Ce langage permet de créer des application répidement sous Windows, car tous les éléments de feuille, de contrôle et autre peuvent se créer en un click de souris. Ensuite, il ne reste plus qu'à rajouter à ces éléments des valeur de propriété (taille de feuille, texte, couleur, aspect,...) et des méthodes d'évènement (Click, Change, GetFocus...)
	Sous Windows, la programmation en C ressemble à Visual Basic, seulement nos éléments ne seront plus créés en cliquant dans une boite à outils et en rajoutant du code, mais en codant la totalité de notre programme qui sera composé au moins de deux grandes parties : La partie Création et Réception des Messages et la partie Traitement des Messages.
	Tout cela va vous sembler nouveau, mais vous allez normalement très vite vous y faire.

I) Structure d'un Programme Windows.
	Windows est un système d'exploitation multitache (c'est à dire qu'il permet de faire tourner plusieurs applications en même temps) et qui réagit à des évènements causés par l'utilisateur  (Click de la souris, appuis d'une touche du clavier, relachement d'une touche, mouvement de la souris...), ou par l'ordinateur lui même (temps écoulé, fin d'impression de l'imprimante...)

	Lorsqu'on programme en C sous Windows, il faut créer une application dans laquelle les évènements seront attendus, et aussi dans laquelle ces évènements seront traduit pour donner lieu à des actions que vous souhaitez. Il faut donc pour cela créer deux Procédures qui sont les suivantes : 

Procédure de Réception des Messages
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
}

Procédure de Traitement des Messages
LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
}

	Lorsque vous lisez ces deux procédures si vous n'avez fait jusqu'à présent que du C ou C++ sous Dos, vous allez dire Qu'est ce que c'est que ce M.......

	Ne nous affolons pas, j'ai oublié de vous parler d'une chose assez importante. Dans Windows, la programmation se fait à l'aide de l'API. l'API est une bibliothèque de fonctions servant à communiquer avec Windows. Seulement, on ne communique pas avec l'API en utilisant des fonctions simples telles que int Resultat(int NombreA, facteur, int  NombreB). l'API le plus souvent possède ses propres type de variables. Par exemple, le type LPSTR de la fonction WinMain est en fait un type de chaine de caractère. Il est pour certaines et peut être la plupart des fonctions de l'API totalement compatible avec une chaine de caractère déclarée en char *. Si vous créez par exemple une chaine de caractère en utilisant char*, elle pourra être passée en paramètre dans une fonction de l'API demandant comme paramètre une chaine de type LPSTR. Il existe comme vous pouvez le voir dans les deux fonctions WinMain et WinProc d'autres types inconnus du monde MS DOS comme HINSTANCE, WPARAM, LPARAM, UINT) , nous les commenterons au fur et à mesure.

Donc, pour en revenir à nos deux fonctions WinMain et WinProc, ce sont elles qui vont gérer tout notre programme.

 WinMain va contenir au moins deux choses : 
	_ La Création de l'application à son démarrage
	_ Une boucle d'attente des Messages

La Création de l'application à son démarrage, c'est généralement la création d'une feuille avec dessus des controles tels que des boutons, des zones de texte ...
Nous nous contenterons pour cette première leçon d'une simple feuille vide.

La Boucle d'attente des Messages c'est tout simplement une boucle du style while.
Dans cette boucle, on va demander via une fonction de l'API, que Windows envoie tous les évènements vers la procédure WinProc qui va les traiter.

WinProc va contenir la chose suivante : 
	_ Un ensemble de branchement du type Switch Case

Cet ensemble va permettre à l'utilisateur de dire ce qu'il veut voir se passer lorsque tel ou tel évènement est envoyé. Pour les arrivant de Visual Basic, cela correspond aux méthodes d'évènements.
Une différence est à noter, c'est qu'il n'y a pas à la base de méthode d'évènement pour chaque contrôle d'une feuille. Il y a un évènement global qui envoie un message contenant le nom du controle concerné.
Nous verrons cela en détail un peu plus loin.


II) Notre premier Programme Windows
	Pour parler avec l'API de Windows et donc utiliser ses fonctions un peu tordues, et ses types de variables sorties d'on ne sait où il faut inclure deux fichiers d'En-tête
*/

#include <windows.h>
#include <windowsx.h>

/*	Puis, nous allons déclarer les prototype de nos deux fonctions principales. Oui, on le fait, même si ces fonctions sont contenues dans l'API. C'est un peut comme lorsque on utilise directement l'API depuis Visual Basic, on Déclare quand même les fonctions à utiliser. Je vais les commenter une par une.
*/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);

/*	Cette fonction est la fonction principale de Windows. C'est la même que la fonction main pour un programme DOS. Elle attend un int en retour comme pour les programmes console, on retournera 0 à la fin de l'application pour indiquer à Windows qu'on est sorti du programme sans encombre. Vient ensuite le mot WINAPI . Alors, là, j'ai pas trop d'explications à donner si ce n'est une sorte de protocole à indiquer à Windows. Sachez pour l'instant uniquement qu'il faut le mettre dans la fonction principale. 

	WinMain est donc le nom de la fonction (à bien respecter). Ensuite viennent des paramètres un peu bizarre. 
hInstance de type HINSTANCE correspond à l'application elle même. Si hInstance était égal à 0 cela voudrait dire que l'application ne fonctionne pas. C'est une sorte de pointeur indiquant combien de fois le programme est chargé (Rappelons le on est en multitache). 
hPrevInstance de type HINSTANCE également est un peu la même chose, mais est actuellement reclus car il était utilisé sous les anciens systèmes en  16 bits. 
LPSTR lpCmdLine est comme nous l'avons vu une chaine de caractère. elle correspond à la chaine de caractère qu'on peut entrer à la suite d'un lancement de programme. Si vous éxécutiez Word par exemple et que vous le lanciez sans utiliser l'icone mais en tapant dans Programme/Exécuter word.exe fichier.doc, word s'éxécuterait et fichier.doc serait chargé dans word. lpCmdLine contiendrait alors "fichier.doc". 
Le dernier paramètre nCmdShow est de type int. Je n'ai pas de précisions sur lui pour l'instant, mais ce paramètre nous le verrons est utilisé lors de la création des fenêtres et contrôles.

Déclarons maintenant le prototype de la fonction de traitement des messages
*/

LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

/*	Comme pour la précédente, cette fonction attend un retour. Le type de ce retour est ici LRESULT, qui est apparement spécifique au retour d'une procédure de traitement de messages Windows.
CALLBACK est comme WINAPI une sorte de protocole. WinProc est le nom de la procédure qui va traiter les messages envoyés par WinMain.
Voici ses paramètres : 
_HWND hWnd : HWND est une sorte de pointeur sur un objet. Dans Visual Basic on appelle une fenetre par son nom, un bouton par son nom... En C sous Windows, on appelle généralement les choses par leur Handle. Il s'agit d'un pointeur désignant un objet.

_ UINT uMsg : C'est le message envoyé par WinMain. La valeur contenue par ce message sera de type UINT qui est en fait une appellation de l'API pour le type unsigned int. La valeur de uMsg va désigner l'évènement qui vient de se produire.

_ wParam est un paramètre lié au Message envoyé. Il est de type WPARAM c'est une sorte d'entier long. 
_lParam est aussi lié au Message envoyé . Ils vont contenir par exemple les positions de la souris lors d'un évènement MouseMove, le code de la touche enfoncée lors d'un évènement KeyDown...

	Cette Procédure WinProc va en somme recevoir de WinMain l'objet concerné par l'évènement (hWnd), le nom de l'évènement (uMsg), deux paramètres précisant l'évènement (wParam et lParam).

	Voici maintenant la suite du programme avec le contenu de la Procédure WinMain. Nous allons créer une fenêtre, puis la charger et enfin la faire apparaitre à l'écran. Nous placerons ensuite la boucle d'attente de messages.
*/

bool stop = false; /* Je place cette variable globale ici qui indique si le programme se termine ou non, nous verrons son utilité plus tard*/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

/*On créé d'abord les variables dont nous aurons besoin et pour la fenêtre et pour la boucle des messages après.*/

HWND hFenetre; /* Il va s'agir du Handle qui contiendra l'objet Fenetre que nous créérons.*/

MSG MessagesAEnvoyer; /*Il s'agit de la variable de type MSG qui sera envoyée à WinProc lorsque un évènement arrivera. */

/*
Pour créer une fenêtre dans une application Windows, il faut trois phases:
_ La déclaration avec implémentation de certaines propriétés
_ L'Enregistrement en mémoire en utilisant une fonction de l'API
_ La Création finale en utilisant une fonction de l'API.
Ne vous inquiétez pas, on va décortiquer.

La création de la fenêtre avec implémentation des propriétés donne ce qui suit : 
*/

WNDCLASS Fenetre; /* Déclaration de Fenetre, objet de la Structure WNDCLASS.*/

Fenetre.lpszMenuName =NULL; /* Il s'agit d'une propriété indiquant le nom du menu que la fenêtre doit contenir. Ici, il n'y en aura pas.*/

Fenetre.cbClsExtra  =0; /* Je laisse ce paramètre propre à Windows à 0*/

Fenetre.cbWndExtra =0; /* Je laisse ce paramètre propre à Windows à 0*/

Fenetre.hInstance = hInstance; /* J'indique que la fenêtre va fonctionner dans l'actuel programme.*/

Fenetre.lpfnWndProc = WinProc; /* J'indique le nom de la procédure vers laquelle seront envoyés les messages Windows propres à cette fenêtre.*/

Fenetre.lpszClassName = "FENETRE DE TYPE A MOI"; /* J'indique le nom que va porter le type de Fenêtre que je suis en train de créer actuellement. */

Fenetre.style =  CS_VREDRAW | CS_HREDRAW; /* J'indique que la fenêtre devra être redessinée à chaque modification de la fenêtre.*/

Fenetre.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
/*hBackGround est la couleur de fond de la fenêtre. On utilise la couleur WHITE_BRUSH. WHITE_BRUSH on ne sait pas ce que c'est vu comme ça, mais en utilisant la fonction GetStockObject de l'API, le retour va correspondre à une donnée. Cette donnée castée en 	(HBRUSH) v a être compatible pour cette propriété de hBackGround ce qui donnera à notre fenêtre la couleur blanche. Pour désigner une couleur sinon, il aurait fallut caster en HBRUSH un nombre Hexadécimal correspondant à la couleur demandée, mais les héxa, c'est un peu galère à se rappeler. (En Visual Basic, je préfère utiliser RGB(a,b,c) plutôt que &HF00...)*/

Fenetre.hIcon =(HICON)  LoadIcon(hInstance, IDI_APPLICATION);
/*hIcon est la forme de l'icone qui va se trouver dans le bandeau de notre fenêtre. En utilisant la fonction LoadIcon de l'API, à laquelle on envoie l'instance du programme et la valeur IDI_APPLICATION, on obtiendra une donnée qui castée sous la forme (HICON) sera compatible avec Fenetre.hIcon.*/

Fenetre.hCursor =(HCURSOR)  LoadCursor(hInstance, IDC_ARROW);
/*Ici, c'est la même chose que pour hIcon, on indique que l'on veut IDC_ARROW comme pointeur de souris soit une flèche. Il existe également IDC_WAIT, IDC_CROSS...*/

/*	Voilà, nous venons de créer un type de fenêtre propre à nous qui s'appelle Fenetre. Mais Fenetre n'est pas une fenêtre à part entière. Il s'agit en fait d'une sorte de modèle dont le nom usuel est "FENETRE DE TYPE A MOI".

Pour créer une fenêtre prête à être affichée, il faut en premier lieu l'enregistrer en mémoire*/

RegisterClass(&Fenetre);

/*	Ne me demandez pas pourquoi il faut faire cela, je n'en sais rien, je sais uniquement qu'il s'agit d'une étape obligatoire avant de vraiment créer la fenêtre. l'API a apparement besoin d'enregistrer la fenêtre via la fonction RegisterClass pour la continuation de notre création.

Vient ensuite l'étape finale : la création finale de notre fenêtre.

	Dans cette partie, nous allons attribuer un handle à notre fenêtre, en la créant à l'aide de la fonction CreateWindow de l'API, et en passant comme paramètre pour cette création non pas l'objet Fenetre, mais son nom de baptème FENETRE DE TYPE A MOI. C'est peut être pour cela qu'il fallait l'enregistrer dans l'étape deux avec RegisterClass.*/

hFenetre = CreateWindow("FENETRE DE TYPE A MOI", "Voici la fenêtre", WS_OVERLAPPEDWINDOW, 200, 200, 300, 250, NULL, NULL, hInstance, NULL);

/*Je commente :
 hFenetre c'est le Handle désignant notre fenêtre qui va se créer. Ce Handle comme je l'ai déjà dit va servir à nommer notre fenêtre dans la plupart des fonctions de l'API.

CreateWindow : C'est la fonction qui va créer notre fenêtre.

"FENETRE DE TYPE A MOI" : C'est le nom que l'on a donné à notre type de Fenetre dans l'étape 1. 
CreateWindow se sert de cela pour savoir quel type de fenêtre créer.

"Voici la fenêtre": C'est la chaine de caractère que l'on veut voir apparaitre dans le bandeau

WS_OVERLAPPEDWINDOW : Il s'agit d'un paramètre qui va indiquer comment notre fenêtre doit apparaitre. (Avec ou sans bandeau, avec ou sans bouton de controle...). Ici, elle sera complète (bandeau, redimensionnable, avec boutons d'agrandissement, de réduction et de fermeture)

200,200,300,250 : Il s'agit des coordonnées de notre fenêtre à l'écran. 200,200 : c'est le point en haut à gauche par rapport au bord gauche et haut de l'écran. 300 est la longueur de la fenêtre et ,250 la hauteur. 

NULL,NULL, hInstance, NULL : 
Cela correspond à :
FenêtreParent de type HWND, hMenu de type HMENU, Instance de l'appplication, Paramètre Windows de type LP VOID.

la Fenêtre Parent correspond à la fenêtre qui contiendrait la fenêtre que nous créons.
hMenu est le handle du menu de la fenêtre. 
Instance est l'instance du programme
Paramètre Windows est utile apparement dans le cadre de la création d'une application en multidocuments nous ne nous y attarderons pas ici.
Pour notre exemple, vu que nous voulons une fenêtre toute simple, nous utiliserons donc les paramètres  tels qu'ils sont dans l'exemple. 

	Maintenant que notre fenêtre est crée, il faut la faire apparaître à l'écran. On va utiliser pour cela la fonction de l'API ShowWindow. Il faut passer à cette fonction deux paramètres : le Handle de l'objet que l'on veut faire apparaître (ici hFenetre), et le paramètre de WinMain nShowCmd.*/

ShowWindow(hFenetre,nShowCmd);

/*Voilà, notre fenêtre est créée et peut apparaitre. Notre programme est cependant incomplet, voici la suite, la boucle d'attente des messages.

	Si nous laissions tourner notre programme comme cela, la fenêtre apparaitrait à l'écran en un milliardième de seconde, et notre programme se terminerait. Il faut donc une boucle qui ne se terminera que si l'utilisateur clique par exemple sur la fermeture de la fenêtre.
Dans cette boucle, il faut insérer une procédure qui va capturer les évènements et les envoyer dans WinProc pour y être traités.*/

while (!stop)
{
	GetMessage(&MessagesAEnvoyer, hFenetre, 0, 0); /* Cherche et lit les évènements liés à la fenêtre*/
	TranslateMessage (&MessagesAEnvoyer); /* Traduit ces évènements*/
	DispatchMessage (&MessagesAEnvoyer); /* Envoie ces évènements sous entendu dans WinProc)*/
}

return 0; /*fin du programme*/
}

/*Voilà, cette boucle va empêcher au programme de se terminer tant que la variable stop est à false. Le Programme est donc comme cela condamné à attendre les message d'évènement de la fenêtre et à les envoyer à WinProc

Nous allons donc maintenant voir la fonction WinProc
*/

LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) /* On s'interroge sur le message envoyé par Window.*/
	{
		/* A partir de maintenant, on va voir à quoi correspond ce message*/
		case WM_DESTROY: /* Message de destruction de la fenêtre. Est envoyé lorsque la fenêtre se ferme (si l'utilisateur a cliqué sur la croix de fermeture par exemple)*/
		{
			stop = true ;/* On met stop = true pour terminer la boucle d'attente de 	message de WinMain*/
			PostQuitMessage(0); /*Fonction de l'API indiquant à Windows que le programme va se terminer.*/
			return 0; /*On renvoie 0 pour dire que le traitement du message a été effectué. */
		}
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam); /*dans tout autre cas on renvoie le message tel quel*/
}

/*	Nous venons de voir la procédure WM_DESTROY qui est un message de fermeture de notre fenêtre. Il s'agit d'un des messages les plus simples car nous n'avons utilisé aucun paramètre wParam ni lParam. Il existe plusieurs autres évènements qui aurait pu nous faire quitter l'appplication si nous l'aviosn voulu tel qu'un clique de souris dans la fenêtre, ou un mouvement de souris comme dans les écrans de veille. Nous verrons cela dans un prochain cours.*/

/*LISTING COMPLET DU PROGRAMME*/ 
#include <windows.h>
#include <windowsx.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);

LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
bool stop = false; 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

HWND hFenetre;
MSG MessagesAEnvoyer;

WNDCLASS Fenetre; 
Fenetre.lpszMenuName =NULL;
Fenetre.cbClsExtra  =0;
Fenetre.cbWndExtra =0;
Fenetre.hInstance = hInstance; 
Fenetre.lpfnWndProc = WinProc;
Fenetre.lpszClassName = "FENETRE DE TYPE A MOI";
Fenetre.style =  CS_VREDRAW | CS_HREDRAW; 
Fenetre.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
Fenetre.hIcon =(HICON)  LoadIcon(hInstance, IDI_APPLICATION);
Fenetre.hCursor =(HCURSOR)  LoadCursor(hInstance, IDC_ARROW);

RegisterClass(&Fenetre);

hFenetre = CreateWindow("FENETRE DE TYPE A MOI", "Voici la fenêtre", WS_OVERLAPPEDWINDOW, 200, 200, 300, 250, NULL, NULL, hInstance, NULL);

ShowWindow(hFenetre,nShowCmd);

while (!stop)
{
	GetMessage(&MessagesAEnvoyer, hFenetre, 0, 0); 
	TranslateMessage (&MessagesAEnvoyer); 
	DispatchMessage (&MessagesAEnvoyer);
}

return 0; 
}


LRESULT CALLBACK WinProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		case WM_DESTROY:
		{
			stop = true ;
			PostQuitMessage(0);
			return 0;
		}
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam); 
}


/*Copiez ou faites un copier coller du programme dans un nouveau fichier C/C++ d'un Projet Window Application sous un IDE tel que Visual C++, Borland C++,  DevC++.... Vous devez obtenir une fenêtre dont le bandeau affiche 'voici la fenêtre'. Cette fenêtre doit être de taille 300 / 250 et doit comporter les boutons de maximisation, minimisation et de fermeture. Elle doit également comporter une icone. Son fond doit être blanc.
*/

 Conclusion

Ce Tutorial contient le même programme deux fois, une fois commenté pas à pas, et au final vous pouvez trouver le listing complet. vous pouvez copier coller soit l'un soit l'autre, le premier ayant ses commentaire sous forme de commentaire C (/*.... */). En revanche bien faire attention de ne pas copier coller dans votre IDE C/C++ les deux programmes, sinon, BUG.
Voilà, n'hésitez pas à commenter, poser des questions, je m'éforcerai d'y répondre dans la limite de mes possibilités.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   Documents and Settings
    •   Patoshe
      •   Mes documents
        •   LaPatoshe
          • Tutorial1 Win32 Cpp final.rtfTélécharger ce fichier [Réservé aux membres club]5 516 463 octets

Télécharger le zip


 Sources du même auteur

C/C++ SOUS WINDOWS TUTORIAL 3 : CREATION ET AFFICHAGE DE CON...
C/C++ SOUS WINDOWS SANS MFC - TUTORIAL 2 : ECRITURE DANS UNE...
Source avec Zip ENREGISTREMENT ET RESTITUTION DE TEXTE EN EDIT MULTILINE
Source avec Zip CRÉATION DE CONTROLES AVEC CLASSE ET LIBRAIRIE PERSO SANS MF...

 Sources de la même categorie

LISTER FICHIERS ET RÉPERTOIRES (MULTIPLATEFORME) par christophedlr
UTILISATION DES TYPELIST EN C++ par wyden
Source avec Zip Source avec une capture QCSSCOMPRESSOR par alphaone
AFFICHAGE D'UN TRIANGLE ISOCELE par nabche
Source avec Zip GESTION D'UNE BIBLOTHEQUE par leclerro19

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture POUR AFFICHER LES CARACTÈRES ACCENTUÉS SOUS WINDOWS EN MODE ... par pgl10
Source avec Zip Source avec une capture SOKOBAN EN C POUR DÉBUTANT (VERSION AMÉLIORÉE BASÉE SUR LE T... par eustatika
Source avec Zip [MYLIB] GESTION DE FICHIERS par Galaad2908
Source avec Zip PROTECTION AU DÉMARAGE DE WINDOWS ET PENDANT par daminator2
Source avec Zip MDZ WTK par mdelomez

Commentaires et avis

Commentaire de BruNews le 26/06/2004 18:33:00 administrateur CS

Salut,

un tuto Windows, vaste sujet, bon courage.
Ne prends pas mal, j'annote quelques points:

WinMain() n'est pas une proc de reception des messsages mais le simple point d'entree du prog.

Les types win ne sont que des alias des types primaires.
LPSTR est un #define de char*, sera donc compatible a tout coup.

"message contenant le nom du controle" NON, rien que du numerique et toujours.

Je deconseille ce: #include &lt;windowsx.h&gt; qui inclut des macros predefinies.
Autant apprendre en voyant clairement ce qui se passe.

Aucun besoin de declaration prealable des fonctions si elles sont placees dans l'ordre d'utilisation.
int WINAPI WinMain(): celle ci encore moins que les autres(point d'entree, compilo doit la trouver).

WINAPI est alias de __stdcall, protocole ou l'appele depile les params.

HINSTANCE ne dit jamais combien de fois... c'est le handle de processus.

LPSTR lpCmdLine est un pointeur et non une 'chaine de caracteres'.
Rappelons egalement qu'il ne faut jamais tenter de modifier la chaine pointee avec des strcpy, strcat ou autre.

"WinProc ... cette fonction attend un retour", c'est win32 qui attend le retour de la fonction winproc pour savoir quoi faire.

LRESULT est #define de long (32 bits).

un handle n'est pas un pointeur mais une valeur 32 bits identifiant un objet de maniere unique, win32 en maintient une table.

while (!stop) INUTILE !!!
GetMessage retournera 0 quand sera le moment donc:
while(GetMessage(.... fera l'affaire.

Pour les autres points, RegisterClass etc... regarder MSDN toujours.
La meilleure doc sur ce sujet est Petzlod:
http://brunews.free.fr/brunews/download/CP5.zip
http://brunews.free.fr/brunews/download/CP5Sources.zip

ciao...
BruNews, Admin CS, MVP Visual C++

Commentaire de jb60 le 26/06/2004 18:53:54

Je trouve tes commentaires assez pédagogiques, je trouve ça très bien, même si ça se voit que tu n'es pas encore un pro en programmation API (rassure toi, je ne te dis pas ça pour te vexer, car je suis nul aussi, je débute en API)...
Quand tu ne sais pas, tu le dit, et c'est appréciable.

En tout cas, ton petit tuto m'a bien servi, même si j'ai lu pas mal de trucs sur la programmation API peu de temps avant.
Au moins tu expliques avec des mots simples et compréhensibles !!!

Ceci va bien te valloir un 8/10, facile...
Franchement, continue comme ça avec des programmes un peu plus complexes, par exemple en commentant les paramètres WPARAM et LPARAM que j'ai du mal à comprendre aujord'hui :-)

Encouragements

Commentaire de Urgo le 26/06/2004 20:48:01

[quote]Ce langage permet de créer des application répidement sous //Windows[/quote]

Essai de faire gaffe aux fautes, car moi j'ai arreté au bout de deux minutes tellement ça me soule...
Fait aussi une mise à jour grâce aux remarques de BruNews.
Et puis un fichier chm ou doc ne serait pas de refus, car la lisibilité n'est pas très bonne dans ce tableau, on a l'impression d'avoir des oeillères.

Ne prend pas mal mes remarques, elles sont là pour conseiller.
bye

Commentaire de LaPatoshe le 26/06/2004 23:19:17

Salut à tous, et merci pour vos précisions, qui m'aident énormément. J'avais écrit ce tuto un peu pour ceux qui comme moi ont voulu un jour passer de Visual Basic à un langage compilé, et qui après avoir apris le C++ se sont retrouvés devant une usine à gaz qu'est Win32.
Ce tuto était destiné au départ à un site de tutoriaux ou à une page perso, mais j'ai eu pas mal d'ennuis pour retrouver ma page avec des moteurs de recherche, donc, je l'ai adapté à Code Source, site pour lequel j'avais écrit des Démos DirectX en VB. C'est pous cela, qu'au niveau mise en page, c'est pas top , je le reconnais.
En tout cas merci encore pour les précisions que vous avez pu donner à certains points d'ombre du tuto, et également aux corrections apportées et je pense qu'elle sont et seront encore nombreuses.
A plus

Commentaire de LaPatoshe le 26/06/2004 23:53:18

Pour info, je viens pour la mise à jour du tuto de corriger plusieurs fautes dans l'intro et la première partie, et annexer un ZIP au format de WordPad (RTF), comme ça, on peut lire le tuto sans risquer de problèmes occulaires.

Petit message pour BruNews qui je dois le dire a pas mal éclairé ma lanterne : Je n'ai pas mis while(GetMessage(.... car dans ce cas précis, le fait de fermer la fenêtre, ne met pas fin au programme. Je ne sais pas pourquoi, sous Windows 98, il reste en mémoire malgré mon PostQuitMessage(0) dans WinProc. Peut être faut il mettre également une instruction PostQuitMessage (0) avant le return 0 de WinMain, je ne sais pas peut être pourras tu me répondre.
Merci à plus

Commentaire de BlackGoddess le 27/06/2004 01:53:12

LPSTR lpCmdLine est un pointeur et non une 'chaine de caracteres'.
Rappelons egalement qu'il ne faut jamais tenter de modifier la chaine pointee avec des strcpy, strcat ou autre.

&gt;&gt; on peut changer son contenu mais pas sa taille, vu qu'on ne connait pas la taille allouée, est-ce exact ?

Commentaire de BruNews le 27/06/2004 02:10:53 administrateur CS

bien entendu, tant qu'on ne fera que modifier des octets dedans devrait bien se passer mais ce n'est pas a conseiller. Il vaut mieux considerer lpCmdLine comme une 'const char*' et se la recopier dans un buffer s'il y a d'eventuelles manips a faire dessus sinon pourrait etre une source de bug tres difficile a traquer ensuite.

Commentaire de BruNews le 27/06/2004 02:18:10 administrateur CS

Ah oui, il y a aussi ton prog qui reste en memoire sous win98, je jette un oeil demain, pour l'heure ce sera dodo.

Commentaire de Pamaury le 27/06/2004 10:25:50

"un handle n'est pas un pointeur mais une valeur 32 bits identifiant un objet de maniere unique, win32 en maintient une table."

Faux : un handle est un pointeur sur une struture contenant un indentifiant 32 bit(int) dont une table est mainetnu par windows et cela n'est pas du tout les même chose en particulier pour les cast de HANDLE vers HMODULE, HACCEL.... qui ne sont en fait que des alias des HANDLE dont le but est fixé à l'avance pour plus de praticité

Sinon, c'est un bon tuto .


Dernière chose:
"while (!stop)"
&gt;&gt;en plus d'être inutile çà te bouffe le CPU car GetMessage est une fonction bloquante donc le thread est mis en attente et ne consomme rien alors qu'avec un boucle infini(utile dans les jeux mais pas là), tu prend 100% du CPU

Commentaire de BruNews le 27/06/2004 10:44:38 administrateur CS

Pamaury &gt; ok j'ai fait dans l'ultra raccourci mais il vaut mieux qu'on considere un handle en tant que valeur et non pointeur au niveau d'un prog user. On le reçoit, on s'en sert mais on ne va jamais le dereferencer pour lire ou manipuler ce qu'il y a derriere.

Commentaire de BruNews le 27/06/2004 11:19:19 administrateur CS

J'ai verifie ce qu'il y a dessous, rien ne reste en memoire sur un 98.
Compile et verifie chez toi.
-----------------------
#include &lt;windows.h&gt;

HINSTANCE hinst;
HWND hmain;
char szappname[] = "Fenetre";

LRESULT CALLBACK AppWndProc(HWND hwnd, UINT mssg, WPARAM wParam, LPARAM lParam)
{
  switch(mssg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
  }
  return DefWindowProc(hwnd, mssg, wParam, lParam);
}

int InitInstance()
{
  WNDCLASSEX wndcls;
  memset(&wndcls, 0, sizeof(WNDCLASSEX));
  wndcls.cbSize = sizeof(WNDCLASSEX);
  wndcls.lpfnWndProc = AppWndProc;
  wndcls.style = CS_HREDRAW | CS_VREDRAW;
  wndcls.hInstance = hinst;
  wndcls.lpszClassName = szappname;
  wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  wndcls.hCursor = LoadCursor(0, IDC_ARROW);
  if(!RegisterClassEx(&wndcls)) return 0;
  hmain = CreateWindowEx(0, szappname, szappname, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hinst, 0);
  return (int) hmain;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE x, PSTR y, int z)
{
  MSG msg;
  hinst = hInstance;
  if(!InitInstance()) return 0;
  ShowWindow(hmain, SW_NORMAL);
  while(GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return 0;
}

Commentaire de paulo46 le 10/02/2005 11:49:57

Merci beaucoup pour ce tuto !

Commentaire de LaPatoshe le 10/02/2005 20:02:42

de rien, j'espère que cela a pu t'aider.

Commentaire de gamemonde le 20/09/2005 13:55:28

pour pouvoir utiliser keydown faut t'il absolument creer une boite de dialog avec la fonction CreateWindowEx car moi j'utilisais la foncion pour utiliser la resource du dialog. mais si je met un oject comme un edit, la keydown ne fonctionne plus.

Commentaire de BruNews le 20/09/2005 14:12:18 administrateur CS

C'est le controle qui a le focus qui récupère les entrées clavier.
Soit tu détournes les events au niveau de la pompe à messages du WinMain soit tu sous classes les controles.

Commentaire de hugues7E5 le 29/01/2006 18:35:01

J'ai beucoup apprécié ton tuto, et les corrections de BruNews!
Ton language simple permet un apprentissage rapide sans trp grandes réflexions.

message pour BruNews, j'ai vérifié, le programme reste bien en mémoire si l'on met:
while (GetMessage(&MessagesAEnvoyer, hFenetre, 0, 0)) qui est ce qui correspond au tuto.

Il faut remplacer par:
while (GetMessage(&MessagesAEnvoyer, NULL, 0, 0))
Je ne sais pas pourquoi car débutant en C++, éclairez ma lanterne!

Merci à vous deux.

Commentaire de BruNews le 29/01/2006 18:49:29 administrateur CS

oh EXACT, je n'avais pas fait gaffe au hFenetre en second param, faut toujours mettre 0 et laisser DispatchMessage distribuer à la fenêtre cible.

Commentaire de lol55 le 20/06/2006 23:20:04

Merci pour ce tuto SIMPLE et CLAIR !

J'ai enfin compris comment faire une fenêtre en API (une fenêtre de base biensûr ;-)

Je continu la lecture de ce Tuto :-)

Merci pour tout!

Commentaire de encoreUnAutre le 21/02/2008 17:47:26

TROP FORT !!!
Merci beaucoup, tu m'as énormément éclairé.
Super bien foutu, ton tutoriel.  Tu détailles vraiment bien chaque ligne.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Execution d'un programme de Windows a partir d'une interface MFC [ par anas41 ] Bonjour; JE suis debutant en programmation par MFCJ'i réalisé une interface en MFc par la quelle je pourrai executer un logiciel de windows selectionn Signax sous Windows [ par tobbie ] Bonsoir,je voudrais connaître l'équivalent Windows des "signaux" Unix. Mon problème est tout simple : je veux qu'une application MFC soit capable de r afxdb.h [ par keyserkiller ] slt g un programme ki doi gerer des base de donnees,jimporte dc la biblio afxdb.h et g besion de la biblio windows.hor si je l'ai importe dan cette or API [ par LordBob ] Salut a tous,voila je programme des petites application windows en MFC, mais je voudrait savoir le faire avec les API et sans MFC. Ma question est don MFC & API windows [ par 69lion69 ] Salut &#224; tous, alors voila g deux applications une sous MFC (client a base de socket) et une deuxi&#232;me en programmation windows (permet de trc MFC winXP vers win98 [ par esieaa ] Bonjour,j'ai fait un programme MFC avec VC++ .net, compil&#233; sous windows XP et lorsque je l'&#233;x&#233;cute sous windows 98 la moiti&#233; des f Communication entre programme MFC et Programme Windows [ par vaniweb ] Bonjour,J'ai créé une application avec les classes MFC et un autre programme pour Windows avec WndProc et WinMain.Je voudrais que les deux programmes les MFC [ par sonsonbm ] bonjour. Je travaille sur un projet C++. je suis débutante en ce qui concerne l'utilisation des MFC. J'ai écrit un petit programme pour tester et il m [MFC] Interface windows messenger [ par aabhanane ] Bonjour a tous, je suis actuellement sur une application de t&#233;l&#233;phonie ip, et j'ai un petit probl&#232;me. Voil&#224;, je voudrais faire une cree une dll en visual c++ express pour vba [ par assireme81 ] salut tout le monde c'est la premiere fois que j'utilise ce forum donc je ne sais pas comment ca marche vrement voila mon probleme je veux creer une


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,264 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales