IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Ouvrir une deuxième fenetre avec un clic bouton (Api windows)


Sujet :

C

  1. #1
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut Ouvrir une deuxième fenetre avec un clic bouton (Api windows)
    Bonjour,

    Je n'arrive pas a trouver de tutoriel assez explicite pour apprendre comment ouvrir une fenetre en cliquant sur un bouton.
    Des boites de dialogue, oui! Mais pas de fenetre !

    Quelles procedures creer, celles de la fenetre principale peuvent-elle re-servir ?

    Voila ce que j'ai fait pour la gestion de mes boutons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    void NotificationControle(HWND fenetrePrincipale,UINT message, WPARAM wParam, LPARAM lParam)
    {
        unsigned int idBouton=LOWORD(wParam); // Quand btn enfoncé, wParam vaut Id du bouton => recup avec LOWORD()
     
        switch(idBouton)
        {
            case ID_PUSHBUTTON_1:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le premier bouton","titre fenetre",MB_ICONINFORMATION);
                break;
            case ID_PUSHBUTTON_2:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le second bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_3:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le troisième bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_4:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le 4e bouton","",MB_OK);
                break;
        }
    }
    Mais je suis dans l'impasse pour savoir ce que je dois mettre à la place de messagebox !

  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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 : 8 389
    Points
    8 389
    Par défaut
    Tu dois juste créer (CreateWindow) la fenêtre qui doit être lancée puis l'afficher (ShowWindow). C'est tout. Tu peux aussi créer la fenêtre en même temps que la fenêtre principale et juste l'afficher quand on clique sur le bouton. C'est même la solution que je te conseille.

    Pour appeler CreateWindow par contre, il faut bien entendu avoir déjà défini une classe de fenêtre, et la procédure de fenêtre associée. Tu peux réutiliser autant de fois que tu souhaites la classe de la fenêtre pricipale, tout comme n'importe quelle classe d'ailleurs.

    Contrairement à ce que tu dis ce principe est expliqué dans n'importe quel tutoriel. Tu n'as juste pas tout bien compris .

  3. #3
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Salut!

    Merci pour ta réponse!
    En effet, la gestion de l'API est un peu embrouillée dans ma tete !

    J'ai bien compris ce que tu m'as dis mais j'ai une difficulté pour afficher la fenetre (avec le bouton, car en meme temps que la fenetre principale ca marche!)

    En fait je fais un CreateWindow() juste en dessous de celui de ma principale, et je mets le ShowWindow() dans le case associé au traitement des boutons de ma fenetre.

    Seulement, il faudrait que je transmette à ma fonction NotificationControle(HWND fenetrePrincipale,UINT message, WPARAM wParam, LPARAM lParam)
    le nom justement de la nouvelle fenetre !

    Tu me diras, assez simple, passe le en parametre ! Sauf que je crois que le prototype est standard et je sais pas si c'est propre de faire comme ca !

    Voici le code :
    serveur.c (dans lequel se trouvent toutes mes fonctions)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    #include <stdlib.h>  
    #include <stdio.h>  
    #include <SDL/SDL.h> // Librairie SDL
    #include <windows.h> // Pour les fonctions de l'API
    #include "client.h" // Header connection ET recherche SRV
    #include "serveur.h" // Header ecoute serveur
     
    int AffFenetre(HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage)
    {
        HWND fenetrePrincipale,fenetreHeberge;
        MSG message;
        WNDCLASS classeFenetre;
     
        classeFenetre.style = 0;
        classeFenetre.style = CS_HREDRAW|CS_VREDRAW;
        classeFenetre.lpfnWndProc = procedureFenetrePrincipale;
        classeFenetre.cbClsExtra = 0;
        classeFenetre.cbWndExtra = 0;
        classeFenetre.hInstance = NULL;
        classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
        classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
        classeFenetre.lpszMenuName =  NULL;
        classeFenetre.lpszClassName = "classeF";  
     
        if(!RegisterClass(&classeFenetre)) return FALSE;
     
     
     
     
        fenetrePrincipale = CreateWindow("classeF", "Jeu multijoueur lan", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 270, 342, NULL, NULL, cetteInstance, NULL);
        if (!fenetrePrincipale) return FALSE;
     
        fenetreHeberge = CreateWindow("classeF", "Heberger une partie", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 200, 342, NULL, NULL, cetteInstance, NULL);
        if (!fenetreHeberge) return FALSE;
     
        ShowWindow(fenetrePrincipale, modeDAffichage);
        UpdateWindow(fenetrePrincipale);
     
     
     
     
        while (GetMessage(&message, NULL, 0, 0))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
     
        return message.wParam;
    }
     
     
     
     
    void RemplieFenetrePrincipale(HWND fenetrePrincipale)
    {
    //    Premier groupe: le push button
    //    HWND hGroup=CreateWindow(
    //        "BUTTON",
    //        "Le push button",
    //        WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
    //        10,10,
    //        120,150,
    //        fenetrePrincipale,
    //        NULL,
    //        instance,
    //        NULL);
    //    {
            HWND hControle;
     
     
            hControle=CreateWindow(
                "BUTTON",
                "Héberger une partie",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110,
                170,27,
                fenetrePrincipale,
                (HMENU)ID_PUSHBUTTON_1,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "Rejoindre une partie",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110+40,
                170,27,
                fenetrePrincipale,
                (HMENU)ID_PUSHBUTTON_2,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "Règles du jeu ...",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110+100,
                170,25,
                fenetrePrincipale,
                (HMENU)ID_PUSHBUTTON_3,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "A propos de ...",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_FLAT,
                140,110+170,
                115,22,
                fenetrePrincipale,
                (HMENU)ID_PUSHBUTTON_4,
                instance,
                NULL);
            HANDLE hIcon=LoadIcon(NULL,IDI_ERROR);
            SendMessage(hControle,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
    //    }
    }
     
     
     
     
    void NotificationControle(HWND fenetrePrincipale,UINT message, WPARAM wParam, LPARAM lParam)
    {
        unsigned int idBouton=LOWORD(wParam); // Quand btn enfoncé, wParam vaut Id du bouton => recup avec LOWORD()
     
        switch(idBouton)
        {
            case ID_PUSHBUTTON_1:
                ShowWindow(fenetreHeberge, modeDAffichage);
                break;
            case ID_PUSHBUTTON_2:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le second bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_3:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le troisième bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_4:
                MessageBox(fenetrePrincipale,"Vous avez appuyé sur le 4e bouton","",MB_OK);
                break;
        }
    }
     
     
     
    LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam)
    {
     
     
        switch (message)
        { 
            case WM_PAINT:
            {
    			  HDC hdc;
    			  POINT pt;
    			  HBITMAP hBitmap;
    			  HDC hMemDC;
    			  PAINTSTRUCT ps;
    			  BITMAP bm;
    			  hdc = BeginPaint(fenetrePrincipale, &ps);
    			  hBitmap = (HBITMAP) LoadImage( NULL, "images/fond.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    			  hMemDC = CreateCompatibleDC (hdc);
    			  SelectObject (hMemDC, hBitmap);
    			  GetObject (hBitmap, sizeof (BITMAP), &bm) ;
    			  pt.x = bm.bmWidth;
    			  pt.y = bm.bmHeight;
    			  BitBlt (hdc, 0, 0, pt.x, pt.y, hMemDC, 0, 0, SRCCOPY) ;
    			  EndPaint (fenetrePrincipale, &ps); 
    			  break;
            }
            case WM_CREATE: // Initialisation de la fenetre
                RemplieFenetrePrincipale(fenetrePrincipale);
                return 0;
            case WM_COMMAND: // Quand un bouton est enfoncé message = WM_COMMAND
                NotificationControle(fenetrePrincipale,message,wParam,lParam);
                return 0;
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
            default:
                return DefWindowProc(fenetrePrincipale,message,wParam,lParam);
        }
    }

    Et le main (a titre d'information)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdlib.h>  
    #include <stdio.h>  
    #include <SDL/SDL.h> // Librairie SDL
    #include <windows.h> // Pour les fonctions de l'API
    #include "client.h" // Header connection ET recherche SRV
    #include "serveur.h" // Header ecoute serveur
     
     
     
    int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage)
    {
     
        AffFenetre(cetteInstance, precedenteInstance, lignesDeCommande, modeDAffichage);
     
     
        return 0;
    }

  4. #4
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Donc voila pour résumer j'ai ma fenetre principale de mon jeu.
    Lorsque je clique sur le bouton "Heberger partie" je souhaite que ca m'ouvre une autre fenetre (enfant?) qui me permettra de spécifier les paramètres de ma partie.

    Donc :
    - Est-ce que je dois recreer une autre fonction AffFenetre (avec une nouvelle classe, gestion des msg, etc..) pour ma nouvelle fenetre ?
    - Et donc une nouvelle fonction CALLBACK ?
    - Si c'est le cas, que dois-je appeller au niveau de mon switch case de mes boutons ?

    Car le prototype de la fenetre principale est : AffFenetre(HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage);
    mais en réalité il ne recoit pas de paramètre d'un appel puisque c'est le main!

    Si je résume ce que je compte faire :

    -Une fonction int AffFenetrePartie()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
    HINSTANCE cetteInstance
    LPSTR lignesDeCommande
    int modeDAffichage
     
    // Definition nouvelle classe
     
    // Enregistrement classe
     
    // CreateWindow
    // SHowWindow
    // UpdateWindow
     
    // boucle messages
    }
    -Une fonction LRESULT CALLBACK procedureFenetrePartie(HWND fenetrePartie, UINT message, WPARAM wParam, LPARAM lParam)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    {
    // gestion du message
    }
    -Dans mon switch(idBouton) case ID_PUSHBUTTON_1: je mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    {
    AffFenetrePartie();
    }

    Est-ce que c'est propre ?
    Est-ce que ca se fait ?

  5. #5
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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 : 8 389
    Points
    8 389
    Par défaut
    Les fenêtres principale et dhébergement sont deux fenêtres différentes (je veux dire d'après leur contenu, leur rôle, etc.) donc chacune doit avoir sa propre procédure de traitement des messages. Pour cela, une solution consisterait à définir une seule classe de fenêtre donc une seule procédure de fenêtre mais du coup deux "sous-procédures" de fenêtre, une pour chaque fenêtre. Une autre solution consiste à définir tout simplement dès le départ deux classes de fenêtre. Celle-ci est plus simple, mais intéressons-nous à la solution 1, plus correcte.

    Dans la fonction AffFenetre, faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    classeFenetre.lpfnWndProc = procedureFenetreCOMMUNE;
     
    /* Attribuons des id number à chacune de nos fenêtres.
    Le numéro 1 à la fenêtre principale,
    et le numéro 2 à la fenêtre d'hébergement.
    */
     
    fenetrePrincipale = CreateWindow(...);
    SetWindowLong(fenetrePrincipale, GWL_USER, 1);
    ...    
    fenetreHeberge = CreateWindow(...);
    SetWindowLong(fenetrePrincipale, GWL_USER, 2);
    Et la gestion des messages devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    LRESULT CALLBACK procedureFenetreCOMMUNE(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        if (fenetre != NULL)
        {
            int idFenetre = GetWindowLong(fenetre, GWL_USER);
            switch(idFenetre)
            {
            case 1:
                return procedureFenetrePRINCIPALE(...);
            case 2:
                return procedureFenetreHEBERGE(...);
            }
        }
     
        /* Tous les autres cas ici. */
    }
     
    LRESULT procedureFenetrePRINCIPALE(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam)
    {
    }
     
    LRESULT procedureFenetreHEBERGE(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam)
    {
    }
    Je ne comprends pas pourquoi t'as besoin de passer le nom de la fenêtre 2 dans NotificationContrôle. Tu ne le connais pas ? Si tu voulais parler du handle, la fonction FindWindow permet de passer d'un nom de fenêtre à un handle ...

  6. #6
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    C'est tout a fait ca, tu as parfaitement compris ce que je voulais faire!

    Je vais tester tout ca, je viens de voirs des choses interessantes dans les tuto de ta signature.

    Merci beaucoup

    Petite question subsidiaire, une fois tous mes paramètres renseignés, je veux tout fermer et ouvrir uniquement la fenetre de mon jeu qui sera en SDL.
    C'est possible d'appeller une fenetre SDL depuis l'API windows ?

    Je sais que l'inverse est faux d'où le fait que je code tout avec l'API dans un premier temps.

  7. #7
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Voila je viens de tester tout ca, franchement ce code me plait vraiment, c'est plus épuré, plus compréhensible merci

    J'ai juste quelques petites questions :
    - Dans SetWindowLong(fenetrePrincipale, GWL_USER, 1); j'avais une erreur de compilation, et en regardant la doc il semble que ce soit plutot DWL_USER. D'ailleurs sur MSDN ils disent que la fonction est obsolete et qu'elle est remplacée par SetWindowLongPtr ?

    - Au lancement du programme rien ne se passe comme si la procedure de fenetre principale n'etait pas lancée, et donc que la fonction qui appelle le callback n'envoie pas 1 comme DWL_USER. J'ai donc du rajouter return procedureFenetrePrincipale() dans ce que tu as appellé /* Autres cas */ ce qui fait pas très propre :/

    - Du coup quand j'appuie sur mon bouton, quelle est la fonction qui me permet de transmettre ce fameux numéro de handle dans le message destiné à la fonction CALLBACK ??

    Ci dessous le nouveau code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    #include <stdlib.h>  
    #include <stdio.h>  
    #include <SDL/SDL.h> // Librairie SDL
    #include <windows.h> // Pour les fonctions de l'API
    #include "client.h" // Header connection ET recherche SRV
    #include "serveur.h" // Header ecoute serveur
     
    int GestionFenetres(HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeAffichage)
    {
        HWND fenetrePrincipale,fenetreHebergePartie;
        MSG message;
        WNDCLASS classeFenetre;
     
        classeFenetre.style = 0;
        classeFenetre.style = CS_HREDRAW|CS_VREDRAW;
        classeFenetre.lpfnWndProc = procedureFenetre;
        classeFenetre.cbClsExtra = 0;
        classeFenetre.cbWndExtra = 0;
        classeFenetre.hInstance = NULL;
        classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
        classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
        classeFenetre.lpszMenuName =  NULL;
        classeFenetre.lpszClassName = "classeF";  
     
        if(!RegisterClass(&classeFenetre)) return FALSE;
     
     
     
     
        fenetrePrincipale = CreateWindow("classeF", "Mon jeu", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 280, 350, NULL, NULL, cetteInstance, NULL);
        if (!fenetrePrincipale) return FALSE;
        SetWindowLong(fenetrePrincipale, DWL_USER, 1);
     
        fenetreHebergePartie = CreateWindow("classeF", "Heberger une partie ...", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 280, 350, NULL, NULL, cetteInstance, NULL);
        if (!fenetreHebergePartie) return FALSE;
        SetWindowLong(fenetreHebergePartie, DWL_USER, 2);
     
     
     
        ShowWindow(fenetrePrincipale, modeAffichage);
        UpdateWindow(fenetrePrincipale);
     
     
     
        while (GetMessage(&message, NULL, 0, 0))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
     
        return message.wParam;
    }
     
     
     
     
    void RemplirFenetrePrincipale(HWND fenetre)
    {
            HWND hControle;
     
            hControle=CreateWindow(
                "BUTTON",
                "Héberger une partie",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110,
                170,27,
                fenetre,
                (HMENU)ID_PUSHBUTTON_1,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "Rejoindre une partie",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110+40,
                170,27,
                fenetre,
                (HMENU)ID_PUSHBUTTON_2,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "Règles du jeu ...",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                50,110+100,
                170,25,
                fenetre,
                (HMENU)ID_PUSHBUTTON_3,
                instance,
                NULL);
            hControle=CreateWindow(
                "BUTTON",
                "A propos de ...",
                WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_FLAT,
                140,110+170,
                115,22,
                fenetre,
                (HMENU)ID_PUSHBUTTON_4,
                instance,
                NULL);
    }
     
     
     
     
    void GestBoutonsFPrincipale(HWND fenetre,UINT message, WPARAM wParam, LPARAM lParam)
    {    
        switch(LOWORD(wParam)) // Quand btn enfoncé, une partie de wParam vaut Id du bouton => recup avec LOWORD()
        {
            case ID_PUSHBUTTON_1:
      // ici !!!!!!!!!
            break;
            case ID_PUSHBUTTON_2:
                MessageBox(fenetre,"Vous avez appuyé sur le second bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_3:
                MessageBox(fenetre,"Vous avez appuyé sur le troisième bouton","",MB_OK);
                break;
            case ID_PUSHBUTTON_4:
                MessageBox(fenetre,"Vous avez appuyé sur le 4e bouton","",MB_OK);
                break;
        }
    }
     
     
     
    LRESULT CALLBACK procedureFenetre(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        if (fenetre != NULL)
        {
            int idFenetre = GetWindowLong(fenetre, DWL_USER);
     
            switch(idFenetre)
            {
            case 1:
                return procedureFenetrePrincipale(fenetre, message, wParam, lParam);
            case 2:
                return procedureFenetreHebergerPartie(fenetre, message, wParam, lParam);
            }
        }
        /* Tous les autres cas ici. */
        return procedureFenetrePrincipale(fenetre, message, wParam, lParam);
     
     
    }
     
     
    LRESULT procedureFenetrePrincipale(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        { 
            case WM_PAINT:
            {
    			  HDC hdc;
    			  POINT pt;
    			  HBITMAP hBitmap;
    			  HDC hMemDC;
    			  PAINTSTRUCT ps;
    			  BITMAP bm;
    			  hdc = BeginPaint(fenetre, &ps);
    			  hBitmap = (HBITMAP) LoadImage(NULL, "images/fond.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    			  hMemDC = CreateCompatibleDC (hdc);
    			  SelectObject (hMemDC, hBitmap);
    			  GetObject (hBitmap, sizeof (BITMAP), &bm) ;
    			  pt.x = bm.bmWidth;
    			  pt.y = bm.bmHeight;
    			  BitBlt (hdc, 0, 0, pt.x, pt.y, hMemDC, 0, 0, SRCCOPY) ;
    			  EndPaint (fenetre, &ps); 
    			  break;
            }
            case WM_CREATE: // Initialisation de la fenetre
                RemplirFenetrePrincipale(fenetre);
                return 0;
            case WM_COMMAND: // Quand un bouton est enfoncé message = WM_COMMAND
                GestBoutonsFPrincipale(fenetre,message,wParam,lParam);
                return 0;
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
            default:
                return DefWindowProc(fenetre,message,wParam,lParam);
        }
    }
     
    LRESULT procedureFenetreHebergerPartie(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        { 
            case WM_CREATE: // Initialisation de la fenetre
                RemplirFenetrePrincipale(fenetre);
                return 0;
            case WM_COMMAND: // Quand un bouton est enfoncé message = WM_COMMAND
                GestBoutonsFPrincipale(fenetre,message,wParam,lParam);
                return 0;
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
            default:
                return DefWindowProc(fenetre,message,wParam,lParam);
        }
    }
    Lors de l'appui sur le bouton 1 il faudrait faire un ShowWindow() de la fenetre fenetreHebergerPartie qui a donc le DWL_USER = 2, mais je ne vois pas comment je peux faire pour donner le bon handle (en lui faisant trouver à partir du DWL_USER ?) en sachant que mes handles ne sont pas en variables globales.

    Autre chose : Que penses-tu de la fonction CreateWindowEx() pour creer une childwindow qui serait peut etre plus adapté ?

  8. #8
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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 : 8 389
    Points
    8 389
    Par défaut
    - Je pensais plutôt à GWL_USERDATA, mais bref.

    - Je crois en effet que j'ai raconté des bétises. Avant de retourner, CreateWindow va générer plusieurs messages importants alors qu'on appelle SetWindowLong après qu'elle ait retourné. Ainsi, plusieurs messages ne sont pas traités correctement. La méthode que je t'ai proposée est donc finalement à proscrire. Définis plutôt directement deux classes de fenêtre.

    - Pour trouver une fenêtre à partir de son GWL_USERDATA, il faut énumérer toutes les fenêtres (EnumWindows) et trouver le bon à moins d'avoir préalablement sauvegardé toutes les correspondances GWL_USERDATA-HANDLE dans un tableau. Il est plus simple de retrouver le handle d'une fenêtre à partir de son nom.

    - CreateWindow ou CreateWindowEx ça revient au même du moment que tu as ce que tu voulais.

    Bref, voici un code qui fait ce que tu veux. Tu peux toujours poser des questions si tu en as encore.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    #include <windows.h>
     
    #define ID_HEBERGER_PARTIE 101
     
    int GestionFenetres(HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeAffichage);
    LRESULT CALLBACK procedureFenetre(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK procedureFenetreHebergerPartie(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam);
    void RemplirFenetrePrincipale(HWND fenetre);
    void GestBoutonsFPrincipale(HWND fenetre,UINT message, WPARAM wParam, LPARAM lParam);
     
    int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage)
    {
        GestionFenetres(cetteInstance, precedenteInstance, lignesDeCommande, modeDAffichage);
        return 0;
    }
     
    int GestionFenetres(HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeAffichage)
    {
        HWND fenetrePrincipale,fenetreHebergePartie;
        MSG message;
        WNDCLASS classeFenetre;
     
        classeFenetre.style = 0;
        classeFenetre.style = CS_HREDRAW|CS_VREDRAW;
        classeFenetre.lpfnWndProc = procedureFenetrePrincipale;
        classeFenetre.cbClsExtra = 0;
        classeFenetre.cbWndExtra = 0;
        classeFenetre.hInstance = NULL;
        classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
        classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
        classeFenetre.lpszMenuName =  NULL;
        classeFenetre.lpszClassName = "classeF";
     
        if(!RegisterClass(&classeFenetre)) return FALSE;
     
        classeFenetre.lpfnWndProc = procedureFenetreHebergerPartie;
        classeFenetre.lpszClassName = "classeF2";
        if(!RegisterClass(&classeFenetre)) return FALSE;
     
        fenetrePrincipale = CreateWindow("classeF", "Mon jeu", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 280, 350, NULL, NULL, cetteInstance, NULL);
        if (!fenetrePrincipale) return FALSE;
     
        fenetreHebergePartie = CreateWindow("classeF2", "Heberger une partie ...", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 280, 350, NULL, NULL, cetteInstance, NULL);
        if (!fenetreHebergePartie) return FALSE;
     
        ShowWindow(fenetrePrincipale, modeAffichage);
        UpdateWindow(fenetrePrincipale);
     
        while (GetMessage(&message, NULL, 0, 0))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
     
        return message.wParam;
    }
     
    LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_CREATE: // Initialisation de la fenetre
            RemplirFenetrePrincipale(fenetre);
            return 0;
        case WM_COMMAND: // Quand un bouton est enfoncé message = WM_COMMAND
            GestBoutonsFPrincipale(fenetre,message,wParam,lParam);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(fenetre,message,wParam,lParam);
        }
    }
     
    LRESULT CALLBACK procedureFenetreHebergerPartie(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(fenetre, &ps);
                RECT rect;
                const char * texte = "Hébergement de partie";
     
                GetClientRect(fenetre, &rect);
                DrawText(hdc, texte, (int)strlen(texte), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
     
                EndPaint(fenetre, &ps);
            }
            return 0;
     
        case WM_CLOSE:
            /* [Melem] Quand l'utilisateur ferme la fenêtre, la fermer seulement. Ne pas la détruire. */
            ShowWindow(fenetre, SW_HIDE);
            return 0;
     
        default:
            return DefWindowProc(fenetre,message,wParam,lParam);
        }
    }
     
    void RemplirFenetrePrincipale(HWND fenetre)
    {
        /* [Melem] Pas besoin de hControle, on ne s'en sert même pas ... */
        CreateWindow(
            "BUTTON",
            "Héberger une partie",
            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
            50,110,
            170,27,
            fenetre,
            (HMENU)ID_HEBERGER_PARTIE,
            NULL,
            NULL);
    }
     
    void GestBoutonsFPrincipale(HWND fenetre,UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HWND fenetreHebergerPartie;
        /* [Melem] Pour les variables static voir : */
        /* http://melem.developpez.com/tutoriels/langage-c/concepts-avances/?page=rappels#LI-A */
     
        if (fenetreHebergerPartie == NULL)
            fenetreHebergerPartie = FindWindow("classeF2", "Heberger une partie ...");
     
        switch(LOWORD(wParam)) // Quand btn enfoncé, une partie de wParam vaut Id du bouton => recup avec LOWORD()
        {
        case ID_HEBERGER_PARTIE:
            ShowWindow(fenetreHebergerPartie, SW_SHOW);
            break;
        }
    }

  9. #9
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Ha ben voila t'es genial !!!

    La fonction que je recherchais était donc fenetreRecherchee = FindWindow("classeDeLaFenetre", "Nom de la fenetre");

    la variable contient donc le handle !

    ce qui est ensuite utilisable pour faire un showwindow !

    Ben ecoute je vais refaire un peu tout ca, du coup oui j'ai quelques questions :

    - Tu as laissé le prototype LRESULT CALLBACK procedureFenetre(....) c'est volontaire car la fonction n'existe pas?
    - On peut voir que cette nouvelle fenetre s'ouvre aussi dans la barre des taches, or elle fait partie quand meme du programme, est-il possible de ne pas l'afficher ici?
    - Depuis le début mon programme utilise 2MB de memoire, c'est coherent pour un petit programme comme ca ?
    - En suivant le cheminement depuis l'appui sur le bouton, je ne comprend pas l'utilisation d'une variable globale pour la fenetre de partie (meme si c'est vrai que ca marche pas sans , mais je vois pas pourquoi !)

    En tout cas encore merci

  10. #10
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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 : 8 389
    Points
    8 389
    Par défaut
    Tu as laissé le prototype LRESULT CALLBACK procedureFenetre(....) c'est volontaire car la fonction n'existe pas?
    C'est juste le vestige d'un vieux copier-coller .

    On peut voir que cette nouvelle fenetre s'ouvre aussi dans la barre des taches, or elle fait partie quand meme du programme, est-il possible de ne pas l'afficher ici?
    Dans ce cas il faut l'associer à la fenêtre princiaple. Le plus simple étant de spécifier fenetrePrincipale dans l'argument hParent de CreateWindow lors de la création de la fenêtre de partie.

    Depuis le début mon programme utilise 2MB de memoire, c'est coherent pour un petit programme comme ca ?
    Je trouve même que 2 mégas c'est trop petit .

    En suivant le cheminement depuis l'appui sur le bouton, je ne comprend pas l'utilisation d'une variable globale pour la fenetre de partie (meme si c'est vrai que ca marche pas sans , mais je vois pas pourquoi !)En suivant le cheminement depuis l'appui sur le bouton, je ne comprend pas l'utilisation d'une variable globale pour la fenetre de partie (meme si c'est vrai que ca marche pas sans , mais je vois pas pourquoi !)
    Avec une variable locale le code devient ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void GestBoutonsFPrincipale(HWND fenetre,UINT message, WPARAM wParam, LPARAM lParam)
    {
        HWND fenetreHebergerPartie = FindWindow("classeF2", "Heberger une partie ...");
     
        switch(LOWORD(wParam)) // Quand btn enfoncé, une partie de wParam vaut Id du bouton => recup avec LOWORD()
        {
        case ID_HEBERGER_PARTIE:
            ShowWindow(fenetreHebergerPartie, SW_SHOW);
            break;
        }
    }
    Là, tu appelles la fonction FindWindow à chaque fois que GestBoutonsFPrincipale est appelée. Dans l'autre version, FindWindow n'est appelée q'une seule fois durant tout le programme. C'est mieux ainsi car un appel de fonction, ça nécessite beaucoup plus d'instructions machine que ça en a l'air ... J'espère que tu as suivi le lien que je t'ai donné au sujet des variables static.

  11. #11
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Merci!

    Oui j'ai lu ca et j'ai finalement compris tu me conseilles donc de mettre les handle de mes fenetres en variables globales ?
    Que penses tu des tutos qui mettent aussi les handle des controles (combobox etc..) en global ??

  12. #12
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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 : 8 389
    Points
    8 389
    Par défaut
    Attention, là on se sert d'une variable static et non globale. Une variable globale aussi aurait pu faire l'affaire, mais tu fais ce que tu veux. Je n'ai aucun avis sur ce sujet. Pour les contrôles par contre, c'est clair que ça ne sert à rien de conserver leurs handles en global car un id de contrôle permet facilement de retrouver son handle, et il est même plus utilisé que ce dernier.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ouvrir une seule JFrame avec un seul clic sur bouton
    Par chemsoun dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 01/02/2014, 17h50
  2. [Flex4] Ouvrir une nouvelle fenetre clique sur un bouton
    Par xclue dans le forum Flex
    Réponses: 4
    Dernier message: 23/12/2010, 15h23
  3. Ouvrir une zone de texte avec un clic bouton
    Par DjBeGi dans le forum Access
    Réponses: 4
    Dernier message: 07/06/2006, 15h28
  4. Réponses: 4
    Dernier message: 03/02/2006, 23h51
  5. Réponses: 4
    Dernier message: 25/04/2005, 19h36

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