Partage
  • Partager sur Facebook
  • Partager sur Twitter

Question sur l'API Win32

Création d'une boîte de dialogue sans templates

Sujet résolu
    1 septembre 2021 à 12:30:55

    Bonjour, 

    Je me suis récemment mis à l'API Win32, après 3 ans sous Qt pour me diversifier un peu (je suis sous Windows 10), en suivant ce tutoriel. J'ai réussi jusqu'au moment fatidique de créer des boîtes de dialogues. Je m'explique : Win32 se servant massivement des templates, j'aimerai savoir comment créer une boîte de dialogue sans passer par eux, car cela me permet de n'avoir qu'un exécutable à exporter (pas de fichier ressource donc). Je me suis donc naturellement renseigné via la documentation microsoft (que je trouve au passage assez difficile à appréhender pour le débutant que je suis), et tout pointe vers une fonction : DialogBoxIndirectParamA. Ses paramètres sont tous faciles à comprendre (l'instance de la fenêtre, le handle du parent, une procédure notamment) mais un paramètre bloque : il faut visiblement fournir à la fonction une structure DLGTEMPLATE et définir pour chaque contrôle présent dans la boîte de dialogue une structure DLGITEMTEMPLATE. Or je n'y comprend rien. J'ai lu la documentation comme un forcené mais rien n'y a fait, je n'ai rien compris. Comment associer un DLGITEMTEMPLATE à un DLGTEMPLATE ? Comment définir le titre, le menu de ma boîte de dialogue ? Je peux passer le paramètre WS_CAPTION mais comment définir le titre par la suite ? Comment faire fonctionner ce bazar ?

    Je me tourne donc vers les "experts" Win32, après des heures de recherches infructueuses (je n'ai trouvé aucun code source clair et lisible, la documentation microsoft se gardant d'en fournir).

    Merci d'avoir pris le temps de me lire et d'avance pour vos éclaircissements.

    • Partager sur Facebook
    • Partager sur Twitter
      1 septembre 2021 à 13:58:43

      AristideChartier a écrit:

      J'ai réussi jusqu'au moment fatidique de créer des boîtes de dialogues. Je m'explique : Win32 se servant massivement des templates, j'aimerai savoir comment créer une boîte de dialogue sans passer par eux, car cela me permet de n'avoir qu'un exécutable à exporter (pas de fichier ressource donc). 

      Alors quand tu créés un exécutable avec un fichier ressource (boîte de dialogue ou autre) le fichier ressource est compilé avec le compilateur de ressources et ensuite lié à l'exécutable. Donc tu n'a pas besoin de distribuer le fichier ressource avec l'exécutable puisqu'il est intégré à l'exécutable.

      Tu ne trouvera donc pas de code à ce sujet car personne ne s'amuse à faire des boîtes de dialogue sans fichier ressource.

      • Partager sur Facebook
      • Partager sur Twitter
        1 septembre 2021 à 13:59:43

        Salut !

        L'API Windows est assez lourde à prendre en main. Souvent quand tu ne trouves pas comment remplir une fonction, il faut chercher le nom de la fonction et "exemple", et tu tombes sur stackoverflow avec des mecs qui mettent des exemples.

        https://stackoverflow.com/questions/2270196/c-win32api-creating-a-dialog-box-without-resource

        (A noter que je n'ai pas cherché DialogBoxIndirectParamA mais DialogBoxIndirectParam tout court. Car toutes les fonctions ou presques existent avec la forme A ou W à la fin (pour codage en char ou wchar_t) ).

        Sinon, tu veux ne pas faire de fichier resource car tu veux que ça ne fasse qu'un seul exe : le fichier ressource est intégré à l'exe, tu n'as pas besoin de le trimbaler par la suite.

        • Partager sur Facebook
        • Partager sur Twitter

        Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

          1 septembre 2021 à 14:37:22

          Attention, Win32 est une API qui prend ces racines depuis Win16 (c'est même plus un simple relifting qu'une évolution), donc un machin qui a été conçu au début des années 80, ça fait un bail.

          Je ne vois donc vraiment pas l'intérêt de vous prendre la tête avec cette antiquité (c'est même du paléolithique à ce niveau).

          Il existe bien d'autres API graphiques plus "moderne", même sous Windows spécifiquement (MFC, Winforms, WPF, etc...).

          >Win32 se servant massivement des templates

          Vraiment pas, non, malheureusement : que cela soit des templates (C++) car c'est une API C, pas C++, et le C++ n'existait même pas donc même pas encore normalisé (1998) ; ou que cela soit les "TEMPLATE de boîte de dialogue" qui servent à spécifier des IHM (menus, boites de dialogue et propriétés d'exécutable dans l'immense majorité des cas) sans à les "fourrer" dans du code C imbittable qui sont bien trop limités par rapport à ce qui se fait maintenant.

          >j'aimerai savoir comment créer une boîte de dialogue sans passer par eux

          Avez-vous un "vrai" besoin pour cela, car c'est vraiment vouloir se passer d'une des rares aides que fourni ce vieux clou de Win32 ?

          >car cela me permet de n'avoir qu'un exécutable à exporter (pas de fichier ressource donc)

          Vous n'avez absolument pas compris comment fonctionnent les "ressources" dans l'API Win32.

          Les ressources sont un segment (voir plusieurs mais c'est compliqué) de l'exécutable qui contient des valeurs qui peuvent être utilisées par les API de Windows (pas que Win32). C'est un peu comme la registry ou un fichier de configuration, mais des années 80. L'exécutable généré est donc autonome et c'est bien le problème : contrairement aux alternatives plus récentes, il faut des outils dédiés (éditeurs de ressources) pour modifier ces réglages/valeurs, pour des actions aussi bête que la localisation (support multi-langues) des IHM, et on parle même pas des droits d'accès/modifications de ce type de chose (c'est la fête du slip avec ces choses (droits) qui changent inopinément entre Win3.0, Win95, Win98, etc...).

          Et l'histoire de "l'autonomie" d'un exécutable est un faux problème que les débutants se font, car ils oublient complètement que : sans OS, sans DLL, sans base de registre ou équivalent, leur programme n'est capable de RIEN. Faites un installateur et puis c'est tout.

          Un fichier ".rc" n'est utilisé ni par l'exécutable, ni par l'OS. C'est juste un fichier d'entré pour le compilateur de ressources, comme un .c ou un .cpp est un fichier d'entré pour le compilateur "normal". Il génère des fichiers intermédiaires qui seront fournis à l'éditeur de lien pour remplir le segment des ressources de l'exécutable, comme les .obj servent de fichiers intermédiaires pour les sources "normales" qui rempliront le segment de "code" de l'exécutable.

          Donc, clairement, vous cherchez le dahu et vous vous prenez la tête sur un "faux" problème.

          Clairement, la documentation M$ sur ces trucs du paléozoïque de l'informatique, c'est clairement pas pédagogique, mais c'est une époque que les moins de 50 ne peuvent pas connaitre. :-°

          Mais félicitation, vous vous êtes pas trop perdu dans la documentation, malgré tous.

          Sachant que vous n'avez oas à vous prendre la tête avec cela, je vais quand même vous donnez quelques informations pour pas trop vous perdre, pour la prochaine fois.

          "DialogBoxIndirectParamA" : alors primo, on utilise (quasi) jamais directement les primitives de l'API Win32 qui se terminent par un "A" ou un "W" (en majuscule, c'est important), car ceux les versions respectivement "ASCII" et "Wide" (UNICODE) des API et vous devez n'utiliser que les versions "TCHAR", car cela permet de gérer correctement les 2 types d'exécutables (et la MACRO "T" ou "TEXT" pour les chaines en dur dans le code est obligatoire). Donc "DialogBoxIndirectParam", pas "DialogBoxIndirectParamA".

          "DialogBoxIndirectParam" n'est qu'une version "évoluée" de "DialogBoxIndirect" et je ne vous pas pourquoi vous ne prenez pas la version "simplifiée".

          Pour toutes les autres questions que vous posez, il me semble que la section "Remarks" de la documentation de DLGTEMPLATE y répond à toutes, non ?

          https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate

          C'est assez "bête et méchant" comme "structures" (ou "close to metal"), c'est un truc qui a plus de 30 ans.

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            1 septembre 2021 à 16:40:33

            Bonjour à tous,

            Merci d'avoir été si nombreux à vouloir m'éclairer en si peu de temps (car vous avez réussi !). Je n'avais, au vu de mon statut de jeune débutant dans l'univers Microsoft API (je commence à avoir un assez bon aperçu du C++), pas bien saisi ce que représentait un template, et leur usage par le compilateur. Mon problème était en réalité un non-problème, comme souvent… :p.

            -Fvirtman, rouloude : merci pour vos éclaircissements. Je souligne par ailleurs la grande pertinence de votre recueil de codes Fvirtman (j'ai pris plaisir à consulter la grande variété de possibilités en C++ sous Win32, et l'explication sur les threads n'était pas de trop ! :D).

            -bacelar : n'ayant manifestement pas votre niveau dans le domaine, j'ai eu beaucoup de mal à saisir vos explications poussées. Je tiens néanmoins à revenir sur ce passage : « Pour toutes les autres questions que vous posez, il me semble que la section "Remarks" de la documentation de DLGTEMPLATE y répond à toutes, non ? »; Justement, si la documentation de Microsoft à ce sujet, que j'ai comme précisé dans mon sujet lu maintes et maintes fois, m'avait semblé claire et concise, notamment la fameuse partie "Remarks", je n'aurais en effet jamais sollicité l'aide de ce forum, honnêtement…

            Bonne continuation à tous !

            -
            Edité par AristideChartier 1 septembre 2021 à 16:41:54

            • Partager sur Facebook
            • Partager sur Twitter
              1 septembre 2021 à 17:23:47

              Pouvez-vous être plus "explicite" sur vos difficultés, SVP ?

              C'est justes des structures en mémoires qu'il faut mettre les unes derrières les autres, sans padding, et en respectant scrupuleusement toutes les remarques pour chacune d'elles. Par exemple, le nombre de contrôles dans la boite de dialogue est donné dans le champ "cdit" de DLGTEMPLATE qui donne donc le nombre de DLGITEMTEMPLATE, qui suivra donc directement le DLGTEMPLATE+"MENU_ELEMENT"+"WINDOWCLASS_ELEMENT"+"TITLE_ELEMENT"[+FONTSIZE_ELEMENT+"FONTNAME_ELEMENT"] 

              C'est une documentation, et non un tutoriel, malheureusement. Il faut connaitre les notions de "base" pour la comprendre.

              L'exemple donné par le lien de @Fvirtman est une mise en application de la documentation via MSVC, mais si vous ne comprenez pas les formules comme "#pragma pack(push, 4)" ou "#pragma pack(pop)" dans le dialecte MSVC, vous ne verrez pas pourquoi elles sont là malgré le fait que la section "remarks" en justifie pleinement et explicitement leur utilisation. (Et elle a pas mal de limitations, donc attention (ne gère que la version UNICODE, etc...))

              Si vous maîtrisez assez bien le C (en plus du C++ donc, car c'est une API C, je le répète) et que les remarques de la documentation sont comprises, une implémentation C++ possible devrait être "évidente" pour vous. Mais il faut comprendre les remarques de la documentation AVANT.(alignement mémoire, little endian, arithmétique 16bits, layout mémoire, etc...)

              Il faut juste essayer de comprendre "dans l'ordre". Donc, déjà, avez déjà bien compris la notion de TCHAR et d'alignement sur un DWORD ?

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                1 septembre 2021 à 18:29:40

                Si tu commence tout juste les boîtes de dialogue comme tu semble l'indiquer dans ton 1er message, je te conseilles de laisser les templates en mémoire de coté et d'utiliser les fichiers ressources pour le moment.
                • Partager sur Facebook
                • Partager sur Twitter
                  1 septembre 2021 à 19:38:49

                  Re Bonjour,

                  Je me suis mis au C++ vers 2017 après un tentative infructueuse du côté du langage C (mon manque de persévérance à l'époque m'avait fait abandonner le tuto de M@teo21 au niveau des pointeurs si ma mémoire ne me fait pas défaut, mais c'était en 2015 et j'étais relativement jeune, comprenez-moi :lol:). Le C++ m'ayant beaucoup plus séduit par sa puissance et sa simplicité (les problèmes du C) ainsi que l'ajout de la POO. Après 3 années sous Qt (qui est un excellent framework, je ne suis pas le seul à le dire par ailleurs !), je me suis tourné vers l'API Win32 pour me rapprocher du fonctionnement de la machine et de l'OS Windows. Mon grand blocage a été la gestion des chaînes de caractères, d'une complexité hors-norme pour le débutant que je suis, mais j'ai trouvé la "parade" : au lieu du très simple :

                  string nomDeMaChaine("blablabla");

                  de C++, je suis passé à une définition plus basique :

                  const char *nomDeMaChaine = "blabla";

                  et j'ai ainsi fait habilement une croix sur les T_(), TEXT(), LPCSTR, PWSTR, wchar_t, ect... et toutes ces horreurs, et cela compile à merveille (je suis sous Code::Blocks, un agréable retour aux sources !). Donc non, je ne sais pas ce qu'est la « notion de TCHAR et d'alignement sur un DWORD ». Et je crois vouloir éviter de savoir après m'être battu comme un soldat pour essayer de déchiffrer ça :colere: (je suis pourtant sur que vous y êtes à votre aise). Donc, car je vous le répète, je n'ai pas votre compréhension de ces notions, et comme tout jusqu'à présent (et maintenant aussi grâce aux conseils éclairés de certains membres bienveillants de ce forum :)), s'est très bien passé, je suis relativement satisfait. Maintenant pour clore ce sujet, passons au concret et éclairez pour de bon ma lanterne en me proposant, si vous en avez le temps et l'envie évidemment, un code source en C++ utilisant les structures DLGTEMPLATE, DLGITEMTEMPLATE et DialogBoxIndirectParamA (W ou ce que vous voulez). Je serai ravir de m'en instruire pour la suite.

                  Bonne soirée

                  -
                  Edité par AristideChartier 1 septembre 2021 à 19:43:32

                  • Partager sur Facebook
                  • Partager sur Twitter
                    1 septembre 2021 à 20:52:36

                    Si tu veux aller sur cette piste, c'est donc que tu es déjà très calé avec l'API Win32 ou alors tu n'as pas compris ce qu'on a dit.

                    Tu dois donc avoir une bonne connaissance du C car l'API Win32 abuse des pointeurs.

                    Fvirtman t'a donné un lien ou il y a un code, ça ne te convient pas ?

                    • Partager sur Facebook
                    • Partager sur Twitter
                      1 septembre 2021 à 22:52:13

                      >Mon grand blocage a été la gestion des chaînes de caractères

                      Si tu restes dans les clous (utilisation de MACRO TEXT, etc...) en n'utilisant que des TCHAR et en configurant "correctement" vos projets, je vois pas trop où est la complexité. Vous n'utilisez jamais de chaines ASCII ou UNICODE en dur, mais juste des TCHAR, basta.

                      Mais vous semblez avoir pris une pente glissante, faudrait penser à reprendre le droit chemin, sous peine de vous compliquer la vie INUTILEMENT.

                      C'est une API C, donc, en "close to metal/brutal", on utilise les type C, pas C++. Mais les dernières versions de C++ permettent d'encore plus simplifier cette tâche :

                      https://blogs.msmvps.com/gdicanio/2021/03/26/the-case-of-string_view-and-the-magic-string/

                      https://stackoverflow.com/questions/62558390/how-to-use-the-sv-operator-together-with-the-t-macro-in-visual-c-c

                      Donc, votre "const char *" tout moisi, aux oubliettes, SVP.

                      >et j'ai ainsi fait habilement une croix sur les

                      Alors, vous allez "décroiter" _T et autre TEXT, FISSA.

                      >et toutes ces horreurs

                      C'est votre "const char *" qui est une horreur.

                      >et cela compile à merveille

                      Et respirez pas trop fort, de peur que votre souffle ne change la configuration miraculeuse de cette antiquité de Code;;Blocks qui a fait que votre programme "est tombé en marche".

                      Si vous voulez utiliser une API, vous devez vous soumettre à ces contraintes, et pas imposer les vôtres, sinon, ça le fera pas.

                      L'article de documentation que vous citez donne juste les détails d'implémentation du bidule qui fait qu'il faut toujours utiliser les primitives sans "A" ou de "W" à la fin mais toujours celles sans et donc de toujours utiliser des paramètres/"éléments de struct" de type TCHAR, même si cela compile avec autre chose (avec votre configuration "miraculeuse" de votre Code::Blocks, par exemple).

                      Franchement, je ne vois absolument rien de complexe dans l'article. C'est de l'utilisation "basique" de MACRO, pas de la "rocket science". C'est quoi qui bloque ? (Je suis peut-être atteins de la "cécité du sachant").

                      Je ne suis absolument pas d'accord avec le fait que tout code "actuel" n'utilise que de l'UNICODE (ça c'est plus dans les rêves de M$ que dans la réalité, vous en êtes une illustration parmi plein d'autres ;)). Si vous deviez "suivre" leur precepts "tout UNICODE", vous ne devriez utiliser QUE des primitives finissant par "W", jamais avec "A" ou sans "W" et utilisez systématiquement la MACRO "L" pour vos chaîne en dur (LOL, c'est beau les rêves de M$).

                      Si vous savez que ce mic-mac, c'est juste pour gérer de façon "transparente" la version ASCII et "UNICODE" avec un même code source, je pense que cela sera plus clair pour vous. Mais faut bien comprendre comment fonctionne les MACRO en C (et en C++, c'est pareil, puisque c'est le même pré-processeur pour les 2 langages) pour comprendre comment marche ce "tric" qui casse pas 3 pattes à un canard.

                      N'hésitez pas à me poser des questions sur cet article, il n'y a pas de question bête, mais je ne vois pas où vous bloquez dans cet article. Même si j'ai l'air condescendant, j'ai été à votre place y a bien des années. ;)

                      Soyez plus précis dans vos interrogations, SVP, et acceptez les remarques "désobligeante" (andragogie du marteau : Pour apprendre à un adulte, on commence par défoncer ses préjugés, sinon il réapprend de travers ou pire, il refuse le changement), SVP.

                      Je m'attarde sur ces "détails" car ils ne sont pas liés à "DialogBoxIndirectParamA" mais à toute l'API Win32.

                      Si vous ne voulez pas vous adapter aux contraintes d'une API C, n'utilisez pas Win32, c'est pas les bibliothèques C++ d'IHM qui manquent, même sous Windows.

                      Donc TCHAR, c'est l'astuce pour qu'un même code fonctionne aussi bien en compilation ASCII qu'en compilation UNICODE.

                      DWORD, c'est pour Double WORD. et au temps paléolithique de l'informatique de la conception de Win16, un WORD était un entier sur 16 bits, car c'était la taille la mieux gérée par les processeurs de l'époque (les 8086 d'Intel). Donc quand on vous indique qu'une structure doit commencer (s'aligner) sur une limite de DWORD, c'est juste pour dire que l'adresse mémoire du début de la structure doit être un multiple de 4. (il y a une adresse par octet de 8 bits, donc les WORD commencent à une adresse multiple de 2, un DWORD à une adresse multiple de 4, un QWORD à une adresse multiple de 8, etc...)

                      C'est le sens de la ligne "#pragma pack(push, 4)" qui demande aux compilateurs de faire en sorte que les adresses mémoires des variables s'alignent sur des frontières de DWORD aka une adresse multiple de 4.

                      Maintenant, si vous voulez vraiment vous servir de Win32, vous devez comprendre TOUT le reste des "remarques", sous peine d'avoir un truc qui fonctionne tout les 36 du mois (avec de la chance). Comme l'utilisation systématique de ZeroMemory pour initialiser les éléments des structures, etc...

                      Franchement, Win32 est tellement rudimentaire que je cherche même pas à faire du C++ quand je l'utilise "directement". Si j'avais à m'en servir dans un "vrai" projet, je collerais un wrapper C++ directement au-dessus pour dégager toutes ces cochonneries de pompe à messages et autres trucs qui n'ont rien à faire dans une conception "soignée". Et c'est clairement l'API d'une autre bibliothèque graphique qui servirait de façade au bidule.

                      Donc le code de l'exemple donné par le lien de @Fvirtman est largement suffisant pour faire un jouet. Commencez par comprendre TOUT cet exemple. Pour les limitations, vous devriez les voir assez facilement en comprenant les "remarques" de la documentation.

                      Pour utiliser directement une structure C, faut faire du C. Ou faire en sorte que le layout mémoire de la classe/structure C++ soit exactement la même que celle en C (condition d'utilisation comprise). C'est ce que fait l'exemple, donc, mon code ne vous apprendrait rien de plus.

                      C'est tellement obsolète que j'ai même pas trouvé de codes "jouets" qui utilisent les dernières "innovations" du C++, comme des string_view pour faire un wrapping "propre".

                      Si le C vous donne des boutons, pourquoi s'acharner sur cette antiquité plutôt que sur des bibliothèques bien plus modernes en C++ ?

                      (Les limitations les plus évidentes de l'exemple sont : l'utilisation de la MACRO L à la place de _T et le fait que tout le template est en dur ; c'est pas trop compliquer à corriger/étendre, non ? Après, vous pouvez aussi chercher à remplacer les trucs dialectiques de MSVC par des trucs plus standard, mais faudrait qu'on connaisse la liste des compilateurs que vous voulez supporter.)

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        1 septembre 2021 à 22:56:28

                        Si si, cet extrait de code était très pertinent et je l'avais bien sûr croisé dans mes recherches préliminaires (sans le comprendre intégralement pour autant) avant de venir ici. Je répondais juste à ce cher bacelar qui semblait me prendre pour Bjarne Stroustrup. Mais voilà sinon merci pour vos aides et conseils car je suis maintenant en mesure de créer toutes les boîtes de dialogue et menus que je souhaite (c'est dire ! :p). Sujet résolu donc !

                        Merci pour votre réactivité et votre aide à tous.:ange:

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Question sur l'API Win32

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        • Editeur
                        • Markdown