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

FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013  Ajouter une question

 

Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++

Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.

Sur ce, je vous souhaite une bonne lecture. Farscape

SommaireIDE, Environnement de développement (37)
précédent sommaire suivant
 

Avant toute chose vérifier que les includes des classes sont bien situés dans le dossier «headers files» et non dans le dossier « external dependencies » .
Si ce n'est pas le cas procéder à un glisser déplacer avec la souris des fichiers dans le dossier «headers files».
Pour regénérer le « ClassView » la méthode la plus directe consiste à :

  • Fermer le projet.
  • Détruire avec l'explorateur les fichiers : .clw ,.opt ,.ncb situés dans le répertoire du projet.
  • Ouvrir à nouveau le projet lancer le « ClassView ».
  • Il détecte l'absence du fichier et vous ouvre alors une boîte de dialogue vous demandant de lui ré indiquer les fichiers sources.
  • Indiquer le répertoire source du projet.
  • Valider.

Logiquement on doit recouvrer l'usage de « intellisens » et le « ClassView » doit être opérationnel.

Mis à jour le 5 avril 2013 farscape

Plusieurs raisons possibles à ce problème :

Les includes des classes concernées ne sont pas dans le dossier header files mais dans le dossier external dependencies.
Solution faire un glisser déplacer des fichiers en question dans le bon dossier.

La ou les classes en questions ont été rajoutées manuellement ou par l'insertion d'un nouveau fichier include dans le projet sans passer par le générateur de classe.
Reconstruire le classview comme indiquer dans la FAQ :  Que faire si le ClassView n'affiche pas toutes les classes ?

Mis à jour le 19 septembre 2005 farscape

En appliquant la technique suivante :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
#ifndef _COOLTOOLBAR_H  
#define _COOLTOOLBAR_H  
  
class CMyBt;  
class COOlButtonTemplate  
{  
//..................  
//...............  
CMyBt *m_pbt;  
};  
  
class CMyBt  
{  
public: 
COOlButtonTemplate  m_cooltoolbar; 
};  
#endif //_COOLTOOLBAR_H
Cette disposition permet d'éviter l'inclusion répétée du code du fichier dans un autre fichier.
A la première inclusion, le symbole _COOLTOOLBAR_H est défini, ce qui évite les inclusions supplémentaires du même code.
C'est une procédure standard dans les fichiers .h ,il est conseillé de faire de même dans tous vos fichiers .h pour éviter les problèmes liés à la duplication des définitions.
Visual C++ l'incorpore automatiquement dans tous les fichiers de définitions qu'il crée.
La déclaration « class CMyBt ; » au dessus de la classe « COOlButtonTemplate » permet l'utilisation de la classe avant sa déclaration, très pratique dans le cas où deux classes doivent contenir une variable de la classe voisine de manière croisée comme dans l'exemple ci-dessus.

Mis à jour le 5 avril 2013 farscape

Pour indiquer dans visual l'emplacement des includes externes au projet deux possibilités :
headers de librairies privés:
sélectionner le menu tools / options .
Onglet directories.
Voir les différentes catégories de fichiers avec la combobox "show directories for":
Rajouter les différents chemins.
Headers propres au projet:
Sélectionner le menu : projects / settings .
onglet c++
Catégorie : preprocessor
Rajouter les chemins séparés par des ; dans l'édit "additional includes directories".
Notes :les includes référencés dans les sources du projet apparaissent directement dans le dossier headers files.
Le classview s'appuie sur les headers présents à cet emplacement.
Les autres références externes au projet sont placées automatiquement dans "external dependencies" .
Il est possible de déplacer des headers de ce dossier par glisser déplacer dans le dossier header files pour disposer du classview.
Pour rajouter des fichiers dans un dossier spécifique il faut faire add sur le dossier en question.
Il n'y a pas de limitations sur l'emplacement des fichiers à inclure dans un projet il faut juste veiller à fournir les références pour les headers par l'une des deux méthodes précitées

Mis à jour le 5 avril 2013 farscape

L'arborescence d'un projet Visual n'est pas figée ,
On peut créer des sous répertoires par un click droit avec l'option « new folder » sur le dossier sources ou headers files.
Pensez à récupérer la liste des extensions de fichiers gérée par dossier en faisant click droit propriétés sur un dossier existant (sources ou headers) et procéder par copier coller pour recopier les extensions.
Ensuite il suffira de déplacer les fichiers par glisser déplacer ou de les insérer par un click droit « add files ».
On pourra organiser les sources par thèmes exemple :
Les sources concernant les différents outils,
Les gestions de fichiers,
Les traitements etc ...
On procédera de la même manière pour les « includes »

Mis à jour le 5 avril 2013 farscape

Pour disposer du browser de code sélectionner :
Le menu projects option settings puis l'onglet C++ »
Dans la zone category sélectionner listing files .
Puis cocher « generate browse info. ».

Le fichier se construit et suivra l'évolution du projet.
Pour accéder au browser sélectionner le ClassView faire click droit et sélectionner une des trois options :

  • references ;
  • derived classes ;
  • base classes.

Mis à jour le 5 avril 2013 farscape

L'option RTTI ou Run-Time Type Information permet l'utilisation du mot clef dynamic_cast . (Voir documentation MDSN)
Pour l'activer sélectionner le menu Projects option Settings Onglet C++ .
Category : C++ Language.
Cocher :Enable Run-Time Type Information (RTTI).

Mis à jour le 5 avril 2013 farscape

L'environnement de Visual 6.0 peut être sauvegardé en exportant la clef suivante de la base de registre:
HKEY_CURRENT_USER\Software\Microsoft\Devstudio\6.0

Pour sauvegarder uniquement les chemins des includes ,des librairies etc ..:
HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Build System\Components\Platforms\Win32 (x86)\Directories

Mis à jour le 5 avril 2013 farscape

Cette librairie était anciennement connue sous le nom wxWindows.

Pour commencer
Il faut télécharger le fichier wxMSW-2.4.2-setup.zip à l'adresse : http://www.wxwidgets.org/

Lancer le Setup.
Dans visual 6.0 faire :
File Open Workspace :
Ouvrir le fichier C:\wxWindows-2.4.2\src\wxWindows.dsp
Ensuite le menu “project” option “batch Build” et bouton build.

Rajouter les chemins des librairies et includes dans le menu :
Tools Options Directories :
Path Includes:
C:\wxWindows-2.4.2\include
C:\wxWindows-2.4.2\include\wx

Path Lib:
C:\wxWindows-2.4.2\lib

Un exemple pour faire un essai :
C:\wxWindows-2.4.2\samples\grid\grid.dsw

Enjoy.

Mis à jour le 5 avril 2013 farscape

Au niveau de la librairie :
Attention au départ des numéros d'id des contrôles dans le fichier resources.h
Celui-ci doit être renommé pour éviter les conflits avec le projet maître (voir ci-dessous).

Au niveau du projet maître :
il suffira de rajouter dans le menu :
View - ressources includes :
Dans la première partie de la fenêtre après axfres.h le fichier ressource de la librairie (dont il faudra changer le nom pour éviter les conflits :autre chose que resource.h !)
Exemple ici MyLibRes.h

Code c++ : Sélectionner tout
1
2
3
  
#include "afxres.h" 
#include "MyLibRes.h"


Deuxième partie de la fenêtre:
Il faudra rajouter le fichier .rc de la librairie ici MyLib.rc.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  
#define _AFX_NO_SPLITTER_RESOURCES 
#define _AFX_NO_OLE_RESOURCES 
#define _AFX_NO_TRACKER_RESOURCES 
#define _AFX_NO_PROPERTY_RESOURCES 
  
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) 
#ifdef _WIN32 
LANGUAGE 12, 1 
#pragma code_page(1252) 
#endif 
#include "res\MonProjet.rc2"  // non-Microsoft Visual C++ edited resources 
#include "l.fra\afxres.rc"          // Standard components 
#include "l.fra\afxprint.rc"        // printing/print preview resources 
#include "MyLib.rc" 
#endif


Et procéder à la compilation des ressources.

Mis à jour le 5 avril 2013 farscape

Exemple : Prenons le cas d'une fenêtre CDialog où l'on voudrait intercepter le message WM_ACTIVATE.
Il n'apparaît pas par défaut dans la liste des messages de la boîte de dialogue .
Pour y remédier sélectionner l'onglet "Class Info" et mettre dans la liste déroulante "message filter": Windows à la place de Dialog ,revenir ensuite sur l'onglet "message maps" maintenant le message est disponible…

Mis à jour le 5 avril 2013 farscape

Lors de la compilation de sources employant les STL on rencontre souvent le Warning C4786 avec un message à rallonge ressemblant à ceci :

warning C4786: 'blablabla ' : identifier was truncated to '255' characters in the debug information

Ce qui est souvent bénin, la solution pour enlever ce Warning est de rajouter la ligne suivante dans stdafx.h

Code c++ : Sélectionner tout
1
2
  
#pragma warning(disable:4786)

Mis à jour le 5 avril 2013 farscape

Après le lancement de l'option File new, sélectionner l'option Custom AppWizard
Entrer le nom du projet qui servira de modèle dans l'édit Project Name :
Exemple : MyCustomApp.
Valider le choix par le bouton Ok.

Sur le deuxième volet laisser l'option : An existing Projet
Cliquer sur le bouton Next pour choisir le projet source qui servira de modèle de génération.
Valider le choix par le bouton Finish.

Le projet est généré il ne reste plus qu'à le compiler et le linker.
Un nouveau type de projet sera alors disponible dans la boîte de dialogue de création de projets.

Description visuelle du procédé : MakeCustomApp.pdf

Mis à jour le 5 avril 2013 farscape

Il faut choisir le type : projet win32, et dans les paramètres application cocher l'option bibliothèque statique.

Mis à jour le 5 avril 2013 farscape

Après l'installation du setup il ne reste plus qu'à paramétrer les variables d'environnements liées au compilateur.
La distribution du toolkit fournit un fichier vcvars32.bat qui contient les différentes valeurs qui pourront être inscrites pour plus de souplesse dans les variables d'environnements systèmes :

Pour cela il faut accéder à l'icône système (sous Windows XP ou 2000) située dans le panneau de configuration.
Sélectionner ensuite l'onglet avancé puis le bouton : variables d'environnements sur les variables systèmes.
Modifier ou rajouter les valeurs suivantes du fichier de commandes vcvars32.bat situé dans le répertoire
C:\Program Files\Microsoft Visual C++ Toolkit 2003
Set PATH=C:\Program Files\Microsoft Visual C++ Toolkit 2003\bin;%PATH%
Set INCLUDE=C:\Program Files\Microsoft Visual C++ Toolkit 2003\include;%INCLUDE%
Set LIB=C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib;%LIB%

Voilà il ne reste plus qu'à ouvrir une boîte de commande MSDOS et de tester la construction d'un projet fournit pour exemple dans le toolkit
Ou de lancer la construction par un fichier de commandes directement à partir de l'explorateur windows.

Mis à jour le 4 avril 2005 farscape

Visual C++ 6 est sorti en 1998, et donc n'inclus pas la dernière norme du C++ , datant de la même année. Il en résulte certains manques, et des résultats parfois étonnants avec du code pourtant parfaitement valide.

Voici quelques exemples de codes standards mais qui ne compilent pas sous VC++ 6

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
for (int i = 0; i < 50; ++i) 
{ 
   // ... 
} 
  
for (int i = 0; i < 20; ++i) // Erreur : "i : redefinition" 
{ 
   // ... 
}
Ce code est pourtant correct : en effet la portée de la variable i devrait être limitée au bloc de la boucle concernée.
Une solution (de derrière les fagots) pour corriger ce manque : inclure systématiquement nos boucles dans un if, ainsi la portée sera bien limitée

Code c++ : Sélectionner tout
#define for if (true) for
Code c++ : Sélectionner tout
1
2
3
4
5
struct A 
{ 
    static const int Taille = 12; // Erreur : "syntaxe non valide" 
    int Tab[Taille]; 
};
Ce code devrait compiler, car les constantes entières statiques peuvent être initialisées dans leur définition.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
struct A 
{ 
    void Func() 
    { 
    } 
}; 
  
std::vector<A> Tab; 
std::for_each(Tab.begin(), Tab.end(), std::mem_fun_ref(A::Func)); 
  
// Erreur : fonction 'void' renvoyant une valeur
Cette écriture devrait être possible, mais VC6 ne sait pas la gérer du fait de son manque de spécialisation partielle de template.

Code c++ : Sélectionner tout
1
2
3
4
5
std::set<int> s; 
std::vector<int> v(s.begin(), s.end()); // Erreur : "conversion impossible" 
  
std::list<int> l; 
l.sort(std::less<int>()); // Erreur
VC6 ne gère pas correctement les fonctions membres template de classe template, ce qui entre autre vous empêchera d'utiliser les fonctions de la STL prenant en entrée une paire d'itérateurs quelconques, ou list::sort avec un foncteur personnalisé.

Mis à jour le 4 avril 2005 Laurent Gomila

Touche Action
CTRL+F2 marquer une ligne / F2 : passer à la marque suivante
ALT+F8 indentation de la sélection
CTRL+E identifier les accolades, parenthèses, crochets
CTRL+Espace complétion automatique
CTRL+SHIFT+Espace prototype de la fonction
F4 aller à la 1ere erreur de compilation, puis erreur suivante

Mis à jour le 19 septembre 2005 nico-pyright(c)

Le compilateur suivant les cas à l'exécution peut affecter des valeurs spécifiques à une variable pointeur, Connaître ces valeurs peut s'avérer fort utile en mode Debug :

0xFDFDFDFD indique une adresse en dehors de l'espace d'adressage du processus.
0xDDDDDDDD indique que la mémoire vient d'être libérée.
Attention ça ne veut pas dire que l'instruction delete va mettre cette valeur dans un pointeur.
0xCDCDCDCD mémoire globale non initialisée par exemple un pointeur membre d'une classe .
0xCCCCCCCC mémoire locale (pile /stack ) non initialisée par exemple un pointeur déclaré dans une fonction membre d'une classe.

On comprend l'utilité de toujours initialiser les pointeurs à NULL ,et de leur affecter cette valeur après libération de la mémoire.
Ce qui nous amène à l'erreur la plus commune : 0xc0000005 Access Violation
Un exemple simple :
Dans la fonction OnInitialUpdate d'une CFormView je fais la chose suivante :

Code c++ : Sélectionner tout
1
2
3
  
CDialog *pdlg; 
pdlg->ShowWindow(1);
J'ai droit à un beau message de violation d'accès 0xc0000005
En debug si je regarde la valeur de this dans ShowWindow il a la valeur reconnaissable 0xcccccccc et le debugger met des ??? Dans le handle de fenêtre.
Pour résumer lorsque vous tracez un programme en debug et que vous tombez sur ce message,
Pensez à regarder la valeur affectée à this ,
Ou remonter d'un cran dans la pile des appels pour regarder la valeur du pointeur.

Mis à jour le 19 septembre 2005 farscape

Il est tout à fait possible de mélanger des sources en C extension .c et des sources en C++ au sein du même projet.

Détail de la procédure :
Il faudra veiller à enlever au niveau des options de compilation des fichiers en C l'option entêtes pré compilés :

Avec Visual C++6.0 :
Dans la gestion de projet à gauche sélectionner le(s) fichier(s) en C Puis faire clic droit settings .
Dans l'onglet onglet C++ sur la catégorieprecompiled header cocher not using precompiled headers.

Astuce : Pour la multi sélection des fichiers utiliser la touche CTRL+clic gauche.

Enfin tous les prototypes des fonctions en C devront être déclarés avec extern "C" :
Exemple de .h pour déclarer les fonctions en C pour utilisations en C et C++

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
#ifdef __cplusplus  
extern "C" 
{ 
#endif 
  
 void myfct(int c); 
  
#ifdef __cplusplus  
} 
#endif

Mis à jour le 19 septembre 2005 farscape

Microsoft avec un outil gratuit dénommé HTML Help Workshop permet de fabriquer un système d'aide à partir de fichier HTML, remplaçant ainsi avantageusement l'ancien système à base de fichier RTF.
Ceux-ci pouvant être composés avec FrontPage par exemple.
Le fichier d'aide généré aura une extension .chm et peut être entièrement autonome, c'est-à-dire pas forcément rattaché à un programme.
Pour une prise en main du kit voir le tutoriel  Créer un fichier d’aide de type .chm (format html) de Thierry AIM.
Cliquer ici pour le téléchargement du kit sur le site de Microsoft

Maintenant nous allons voir comment établir le lien entre un projet développé avec le kit de Microsoft et un programme MFC .
A terme l'appui de la touche F1 sur une fenêtre particulière (FormView) invoquera l'aide correspondante dans le fichier d'aide.

Génération du fichier de liens entre les formes et l'aide :
Pour établir un lien entre le fichier d'aide et le programme il faut faire un fichier de correspondance qui peut être généré automatiquement par visual .

Sur les propriétés du projet : (menu projects /settings )
Onglet custom build :
Dans la partie gauche des fichiers du projet, sélectionner le fichier resource.h
Dans l'édit descriptions: on renseigne le libellé par exemple : Making HTML Help Include File...
Et dans l'édit Commands:

Code : Sélectionner tout
1
2
3
4
5
6
7
makehm ID_,IDH_,0x10000 IDM_,IDH_,0x10000 resource.h >>"hlp\$(TargetName).hm"  
echo. >>"hlp\$(TargetName).hm"  
makehm IDP_,IDH_,0x30000 resource.h >>"hlp\$(TargetName).hm"  
makehm IDR_,IDH_,0x20000 resource.h >>"hlp\$(TargetName).hm"  
makehm IDD_,IDH_,0x20000 resource.h >>"hlp\$(TargetName).hm"  
makehm IDW_,IDH_,0x50000 resource.h >>"hlp\$(TargetName).hm"  
MakeIDH "hlp\$(TargetName).hm"
makehm va faire le lien entre les différents type de ressources du projet en un identifiant unique commençant par IDH et dont la plage des différents types est reparti.
le fichier généré portera le nom du projet suivi de l'extension .hm.
À indiquer dans l'édit Outputs

Code C++ : Sélectionner tout
hlp\$(TargetName).hm

la première compilation des ressources le fichier .hm va être généré .
Note : le programme MakeIDH doit être présent à la racine du projet.

Compilation automatique du projet d'aide à partir de visual 6: (falcutatif)

Le fichier .hpp doit être inclu dans le projet.

Sur les propriétés du projet : (menu projects /settings )
Onglet custom build :
Dans la partie gauche des fichiers du projet, sélectionner le fichier .hpp
Dans l'édit descriptions : on renseigne le libellé par exemple : Making HTML Help Include File...
Et dans l'édit Commands :

Code : Sélectionner tout
1
2
3
hhc.exe html\$(InputName).hhp  
echo.  
copy html\$(InputName).chm $(OutDir)\$(InputName).chm
Dans l'édit Outputs:

Code : Sélectionner tout
html\$(InputName).chm
cliquer ensuite sur le bouton dependencies et rajouter

Code : Sélectionner tout
html\$(TargetName).hm
Dans l'onglet link :
Object/library modules, rajouter : htmlhelp.lib

Lien du fichier d'aide .chm avec le programme :

Dans la fonction InitInstance de la classe d'application on va modifier le lien de l'aide qui est par défaut sur une extension .HLP

Code C++ : Sélectionner tout
1
2
3
4
5
// Change the extension for the default help file 
CString strHelpFile = m_pszHelpFilePath; 
strHelpFile.Replace(".HLP", ".chm"); 
free((void*)m_pszHelpFilePath); 
m_pszHelpFilePath = _tcsdup(strHelpFile);

Le fichier .chm devra être au même emplacement que le programme.

Appel de l'aide par la touche F1 :

Dans la classe CMainFrame rajouter manuellement le message

Code C++ : Sélectionner tout
1
2
ON COMMAND(IDHELP_CMDIFrameWnd ::OnHelp) 
END_MESSAGE_MAP()

dans le cas d'un projet SDI :

Code C++ : Sélectionner tout
ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)

Au niveau de la classe CMainFrame rajouter avec l'aide classwizard la fonction virtuelle :WinHelp .

Code C++ : Sélectionner tout
virtual void WinHelp(DWORD dwData, UINT nCmd = HELP_CONTEXT);

Et remplacer le contenu par :

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
void CMainFrame::WinHelp(DWORD dwData, UINT nCmd)  
{ 
    CMyApp *pApp=static_cast<CMyApp *>(AfxGetApp()); 
#if _MFC_VER >= 0x0700 
    ::HtmlHelp((pApp->m_bHelpModal?m_hWnd:NULL), AfxGetApp()->m_pszHelpFilePath, HH_HELP_CONTEXT,nCmd==HELP_CONTEXT?dwData:0); 
#else 
    HtmlHelp((pApp->m_bHelpModal?m_hWnd:NULL), AfxGetApp()->m_pszHelpFilePath, HH_HELP_CONTEXT,nCmd==HELP_CONTEXT?dwData:0); 
#endif 
}

la variable est un booleen permettant de choisir si l'appel de l'aide est bloquante ou non .
pour finir dans le hhp on doit avoir les sections suivantes :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
[MAP] 
#include MyApp.hm 
 
[TEXT POPUPS] 
MyApp.hm 
 
[MERGE FILES] 
MyApp.chm
on peut rajouter ces sections avec l'aide de notepad.
c'est au niveau de la section alias dans le programme help workshop que l' on va définir les liens :
on va associer un numéro d'id IDH à une page web.
en faisant double clic sur la section alias on renseignera le nom de l'include :
sur l'onglet map avec l'aide du bouton header file on indiquera le chemin du fichier .hm.
dans l'onglet alias on établira directement le lien entre l'id IDH_ et la page web.

Note :
à la racine du projet on doit avoir les répertoires : html et hlp.

Mis à jour le 19 septembre 2005 farscape

Le détail de l'erreur avec Visual .net :

Fin de fichier inattendue lors de la recherche d'une directive d'en-tête précompilé

Pour Visual 6.0 :
unexpected end of file while looking for precompiled header directive

Explications :
Dans la plupart des cas Visual génère un projet avec l'option en-tête précompilé.
Les en-têtes précompilés représentent des instantanés de compilation pris à un certain emplacement du code source.
Il est pris juste après l'inclusion de la ligne #include "stdafx .h" qui contient les fichiers d'en-têtes des MFC ou template.
Les en-têtes précompilés font donc gagner du temps à la compilation.
À partir du moment où cette option est réglée pour le projet tous les fichiers .CPP du projet doivent avoir en tout début du source la ligne :
Code C++ : Sélectionner tout
#include "stdafx .h"
Sinon le compilateur généra le message C1010 …

Note : il est possible de désactiver spécifiquement par fichier cette option ,c'est le cas par exemple si on veut mixer des fichiers .c et .cpp dans un même projet Voir Comment intégrer des sources C dans un projet C++ ?

Mis à jour le 27 novembre 2005 farscape

En utilisant l'API OutputDebugString et un petit logiciel qui intercepte ces informations de débugage Une fois ce programme lancé, un simple

Code c++ : Sélectionner tout
OutputDebugString("Informations à voir affichées");
permet de voir la ligne dans la fenêtre.

Mis à jour le 27 novembre 2005 nico-pyright(c)

Lors de l'utilisation de grosses variables dans un programme, on se demande souvent comment sont allouées les différentes variables.
On peut résumer rapidement en disant que :
Une déclaration de type

Code c++ : Sélectionner tout
int monTableau[20000];
a une portée locale à la fonction (ou au bloc {} )et est allouée sur la pile (stack)
Une allocation dynamique de type

Code c++ : Sélectionner tout
int * monTableau = new int[20000]
a une portée définie par l'utilisation de new et de delete et est allouée sur le tas (heap)
Les variables globales sont définies dans le segment de données.

La taille par défaut du tas est de 1 Mo. Cette taille par défaut peut être augmentée en réglant une option du linker

Code c++ : Sélectionner tout
/HEAP:reserve[,commit]
C'est bien souvent inutile, car le tas peut augmenter tout seul lorsque l'allocation est supérieure à la mémoire par défaut.
C'est le système d'exploitation qui gère cela tout seul (de la même facon, il préfèrera déléger à VirtualAlloc lorsque l'allocation dépasse un certain seuil).

Cette option est rarement utilisée, sauf pour des questions de performances.

La pile dispose elle aussi d'une taille par défaut d'1 Mo. Cependant, celle-ci est fixe et ne peut augmenter seule. Ainsi, lorsque l'on déclare beaucoup de grosses variables, il peut se produire une erreur de dépassement de mémoire : stack overflow.

On peut de même facilement augmenter la mémoire de la pile par défaut en réglant une option du linker.

Code c++ : Sélectionner tout
/STACK:reserve[,commit]

Le linker utilise par défaut une valeur de 0x100000 (1 Mo) et 0x1000 (4Ko) pour la mémoire commit

donc pour réserver 2 Mo par exemple, il suffit de réserver cette mémoire dans le linker par :

Code c++ : Sélectionner tout
/STACK:0x200000, 0x1000

Remarque : C'est en général une mauvaise idée d'avoir une grosse pile. Il est plus judicieux d'utiliser des allocations dynamiques pour les gros objets.

Mis à jour le 27 novembre 2005 nico-pyright(c)

cette erreur peut apparaitre à l'exécution du programme en mode debug,
Il faudra régler la valeur de génération du manifest à oui dans les options d'édition des liens du projet.
Menu Project / Properties /Configuration Properties /Linker/ Manifest File mettre "Generate Manifest" à Yes. Voir ce lien MSDN pour en savoir plus.

Mis à jour le 20 mai 2006 farscape

Vous avez certainement remarqué qu'il est très pratique de visualiser directement le contenu de certains objets dans la fenêtre de Visual ou encore en passant la souris sur un objet pour inspecter le contenu d'une CString par exemple ?

Et bien cette fonctionnalité de visualiser les données membres importantes d'un objet qu'il soit MFC ou autre est personnalisable.
Ce paramétrage est à mettre en place dans un fichier nommé AUTOEXP.DAT

Il est situé pour Visual 6.0 à l'emplacement :
C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin

Sous Visual 2005 :
C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger

Voici un aperçu de son contenu:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  
; from afxwin.h 
CDC =hDC=<m_hDC> attrib=<m_hAttribDC> 
CPaintDC =<,t> hWnd=<m_hWnd> 
CPoint =x=<x> y=<y> 
CRect =top=<top> bottom=<bottom> left=<left> right=<right> 
CSize =cx=<cx> cy=<cy> 
CWnd =<,t> hWnd=<m_hWnd> 
CWinApp =<,t> <m_pszAppName,s> 
CWinThread =<,t> h=<m_hThread> proc=<m_pfnThreadProc> 
  
; from afx.h 
CArchiveException =cause=<m_cause> 
CFile =hFile=<m_hFile> name=<m_strFileName.m_pchData,s> 
CFileException =cause=<m_cause> OS Error=m_lOsError 
CMemFile =pos=<m_nPosition> size=<m_nFileSize> 
CObject =<,t> 
CRuntimeClass =<m_lpszClassName,s> 
CStdioFile =FILE*=<m_pStream> name=<m_strFilename.m_pchData,s> 
CTimeSpan =time=<m_time> 
CTime =time=<m_time>
On retrouve la liste des objets MFC avec les données membres importantes à visualiser.
Une description des formats d'affichages est disponible dans ce même fichier :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  
   Letter  Description                 Sample         Display 
;   ------  --------------------------  ------------   ------------- 
;   d,i     Signed decimal integer      0xF000F065,d   -268373915 
;   u       Unsigned decimal integer    0x0065,u       101 
;   o       Unsigned octal integer      0xF065,o       0170145 
;   x,X     Hexadecimal integer         61541,X        0X0000F065 
;   l,h     long or short prefix for    00406042,hx    0x0c22 
;             d, i, u, o, x, X 
;   f       Signed floating-point       3./2.,f        1.500000 
;   e       Signed scientific-notation  3./2.,e        1.500000e+000 
;   g       Shorter of e and f          3./2.,g        1.5 
;   c       Single character            0x0065,c       'e' 
;   s       Zero-terminated string      pVar,s         "Hello world" 
;   su      Unicode string              pVar,su        "Hello world"

Pour rajouter vos propres classes il suffit d'éditer ce fichier avec notepad et de rajouter une section pour vos différents objets.

La syntaxe générale est la suivante :
L'objet =leLibelledonnéemembre<donnée membre>
Plusieurs variables membre peuvent être indiquées à la suite.

Les types simples entiers double etc sont correctement interprétés.
Pour une variable membre de type CString il faudra donner le chemin de la chaîne interne :
name=<m_strFilename.m_pchData,s> avec le type s voulant dire chaîne se terminant par un zéro.

Mis à jour le 22 janvier 2007 farscape

Pour inscrire un nouveau type de fichier procéder comme suit:
avec le programme regedit (faire démarrer exécuter, saisir regedit) ouvrir la clef :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Languages\File Extensions
suivant les versions de compilateurs on aura à la place de 8.0 pour VC 2005
7.0 pour .net2002 et 7.1 pour .net 2003
Si on désire que l'extension de fichier .pc soit reconnue comme un .C on créera le répertoire .PC en dessous de la clef File Extensions
Ensuite dans la clef .c copier le contenu de la zone défaut dans le presse papiers
Coller la valeur dans la zone défaut de la clef ajoutée (ici .pc)

Pour intégrer IntelliSense modifier la clef suivante :
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Languages\Language Services\C/C++\NCB Default C/C++ Extensions
il suffit de rajouter aux extensions existantes la nouvelle extension (ici .pc)

Mis à jour le 22 janvier 2007 farscape

Lorsqu'on migre petit à petit son projet en C++.Net ou simplement lorsqu'on veut faire cohabiter l'Api Win32 (ou les MFC) et le framework.Net, on peut rencontrer des problèmes de compilation du style :

Code c++ : Sélectionner tout
1
2
3
  
error C2039: 'GetObjectA' : is not a member of 'System::Resources::ResourceManager'  
error C2653: 'MessageBoxA' : is not a class or namespace name

Le problème vient du fait que lorsqu'on souhaite utiliser la fonction MessageBox par exemple, le compilateur ne sait pas s'il doit utiliser la fonction MessageBox définie dans Windows.h ou bien dans le namespace System::Windows::Forms.

Il faut donc à ce moment dire au compilateur quelle fonction on veut utiliser.
On enlève alors la définition du MessageBox comme ci-dessous

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
#pragma push_macro("MessageBox") 
#undef MessageBox 
  
... 
MessageBox::Show(S"hello"); 
... 
  
#pragma pop_macro("MessageBox")
Ainsi le compilateur saura qu'il faut utiliser le MessageBox de .Net

Mis à jour le 22 janvier 2007 nico-pyright(c)

- Soit en l'ajoutant dans les options du projet, pour VS2005 : propriétés du projet, configuration properties, linker, input, additional dependencies et indiquer ici le .lib à lier.
- Soit par pragma

Code c++ : Sélectionner tout
#pragma comment(lib,"malib.lib")

Mis à jour le 17 septembre 2007 nico-pyright(c)

Lorsque la bibliothèque de runtime (CRT) est utilisée en mode statique /MT (multi-thread statique)
(en opposition au mode dynamique /MD (dll)), il peut apparaitre ce type d'erreurs lorsqu'on utilise plusieurs bibliothèques :

Code c++ : Sélectionner tout
1
2
3
4
5
  
nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj) 
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj) 
nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmtd.lib(newaop.obj) 
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) already defined in LIBCMTD.lib(delete2.obj)
Comment régler ce problème ? , il faut changer l'ordre des liens des bibliothèques incriminées comme suggéré dans cette note MSDN.
Voici comment procéder :
Avec Visual 2005 dans les propriétés du projet, chapitre éditeur de liens.
Rubrique Entrée, zone : "bibliothèque spécifique ignorée", mettre : Nafxcwd.lib Libcmtd.lib (pour le mode debug).
Dans la zone : "dépendances supplémentaires" mettre en dernier à la suite des autres bibliothèques utilisées par le projet: Nafxcwd.lib Libcmtd.lib

Mis à jour le 17 septembre 2007 farscape

Sous Windows Vista avec l'UAC lorsqu'une tâche nécessite un privilège administrateur il faut elever les droits de l'application
Comment gérer la situation ?
Soit on change les droits d'accès sur le programme par clic droit onglet compatibilité : exécuter en tant que administrateur, un peu pénible...
ou bien on rajoutera le fichier manifest suivant à notre application :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  
?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity name="monapplication"  
                    version="1.0.0.0"  
                    processorArchitecture="X86"  
                   type="win32"/> 
  <description>Mon Application</description>  
  <!-- Identify the app's security requirements. --> 
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <security> 
      <requestedPrivileges> 
        <requestedExecutionLevel level="requireAdministrator" /> 
      </requestedPrivileges> 
    </security> 
  </trustInfo> 
</assembly>
On placera le fichier dans le répertoire d'exécution du programme, le fichier portant le nom :
MyAppName.exe.manifest ,MYAppName correspondant au nom de l'application.
Avec Visual 2005 il est préférable d'inclure le manifest à notre programme en respectant la procédure indiquée dans la faq: Comment rajouter le fichier manifeste du style XP au manifeste existant dans Visual 2005 ?
Pour plus de détails sur les options du manifest consultez MSDN.
Voir aussi Comment fonctionne UAC ?

Mis à jour le 17 septembre 2007 farscape

Le dernier SDK valide pour Visual 6.0 date de février 2003.
Il ne faut pas installer le SDK proposé en téléchargement sur MSDN il est prévu pour les versions Visual .Net et Visual 2005.

On peut encore télécharger ce SDK à l'emplacement : http://www.microsoft.com/en-us/downl...d/default.aspx

Mis à jour le 7 juillet 2008 farscape

Au fil des ans et des différentes versions de Windows, nombre d'applications ont été conçues pour avoir un accès direct à des emplacements systèmes ou tout simplement à la base de registres.
Sous Vista ces emplacements sont maintenant verrouillés pour réduire la surface d'attaque du système.
Pour garder une compatibilité avec les anciens programmes Vista implémente un service de virtualisation de l'UAC qui redirige de manière transparente les accès aux parties protégées du système (fichier ,base de registres) vers un emplacement virtualisé et non protégé faisant croire ainsi à l'application qu'elle écrit à l'emplacement d'origine.

Exemple :
Un programme exécuté avec des droits utilisateurs s'installe dans le répertoire :
C:\Program Files\<application>\
L'accès sera automatiquement virtualisé à l'emplacement :
C:\Users\<votre_compte>\AppData\Local\VirtualStore\Program Files\<application>

Si le programme doit impérativement écrire à l'emplacement d'origine il faudra élever les droits de l'application en administrateur.

On procédera comme suit :
Soit on change les droits d'accès sur le programme par clic droit onglet compatibilité : exécuter en tant que administrateur, un peu pénible...
ou bien on rajoutera avec les versions de Visual antérieure à Visual 2008 le fichier manifest suivant à notre application : Comment rajouter le fichier manifeste du style XP au manifeste existant dans Visual 2005 ?

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  
xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity name="monapplication" 
                    version="1.0.0.0" 
                    processorArchitecture="X86" 
                   type="win32"/> 
  <description>Mon Application</description> 
  <!-- Identify the app's security requirements. --> 
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <security> 
      <requestedPrivileges> 
        <requestedExecutionLevel level="requireAdministrator" /> 
      </requestedPrivileges> 
    </security> 
  </trustInfo> 
</assembly>
à intégrer suivant la technique décrite dans la faq : Comment rajouter le fichier manifeste du style XP au manifeste existant dans Visual 2005 ?

Au moment d'exécuter le programme Vista demandera l'acceptation de l'utilisateur pour l'élévation des droits sauf évidemment si vous avez désactivé l'UAC.

Pour conclure :
Il faut bien comprendre que ce mécanisme de virtualisation a été implémenté par Microsoft pour permettre une transition en « douceur » des applications.
Mais il ne faut pas trop compter sur la solution de la virtualisation, car rien ne garantit que ce mécanisme soit encore présent dans les futures versions de Windows…

Mis à jour le 7 juillet 2008 farscape

Visual 2008 permet la gestion du manifest UAC au niveau du projet.


Le réglage de cette option permet de spécifier le niveau d'exécution demandé pour l'application.

Trois options sont disponibles :
AsInvoker : l'application devra s'exécuter avec le jeton actuel de l'appelant sans demander une élévation de privilèges.
highestAvailable : l'application s'exécutera avec le privilège le plus haut que le compte utilisateur possède.
RequireAdministrator: l'application doit s'exécuter avec un jeton complet d'administration.
L'UAC demandera à l'utilisateur l'autorisation de donner l'accès au jeton complet si le compte administrateur fonctionne avec le jeton restreint.

Mis à jour le 7 juillet 2008 farscape

Les classes MFC utilisent l'héritage simple. Dans le cas où l'on voudrait se passer de l'héritage multiple pour enrichir des classes existantes il est possible d'utiliser les classes templates.
Démonstration :

L'exemple ci-dessus montre l'implémentation d'une classe template pour la gestion des couleurs,

Celle-ci est associée à trois classes dialogues.
Technique d'implémentation :
On déclare la classe avec un paramètre qui est aussi utilisé pour spécifier le parent.

Code c++ : Sélectionner tout
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
  
template <class GENERIC_DLGCOLOR /*= CWnd*/> 
class CTplDlgColor : public GENERIC_DLGCOLOR 
{ 
public: 
  
	CTplDlgColor(UINT nID=0,CWnd* pParent=NULL) :GENERIC_DLGCOLOR(nID,pParent) 
	{ 
	/* HBRUSH   */  m_HbrClrCtlBk=NULL ; 
	/* COLORREF */  m_ClrCtlText= RGB(0, 0, 0) ; 
	} 
  
	~CTplDlgColor() 
	{ 
		if(m_HbrClrCtlBk) ::DeleteObject(m_HbrClrCtlBk); 
	} 
virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
	{ 
		if(message==WM_CTLCOLOR) 
		{ 
//&#8230; 
		 return TRUE; 
  
		} 
		return GENERIC_DLGCOLOR::OnWndMsg(message,  wParam, lParam, pResult); 
	} 
//&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 
};
La déclaration pour les classes à enrichir :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
 class CTabInformation : public CTplDlgColor<CDialog> 
{ 
// Construction 
public: 
	CTabInformation(CWnd* pParent = NULL);   // standard constructor 
//&#8230;.. 
} ;
Coté source :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  
CTabInformation::CTabInformation(CWnd* pParent /*=NULL*/) 
	: CTplDlgColor<CDialog>(CTabInformation::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CTabInformation) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	m_pTab = NULL;	 
} 
void CTabInformation::DoDataExchange(CDataExchange* pDX) 
{ 
	CTplDlgColor<CDialog>::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CTabInformation) 
		// NOTE: the ClassWizard will add DDX and DDV calls here 
	//}}AFX_DATA_MAP 
}
Les avantages de la classe patron (template) utilisée de cette manière sur l'héritage multiple sont nombreux.
Les problèmes liés à des méthodes membres qui sont présentes plusieurs fois dans les ancêtres d'une classe peuvent être résolus simplement si ces méthodes sont virtuelles comme dans l'exemple ci-dessus avec la méthode OnWndMsg.
Utilisation native des méthodes sans cast sur la classe de base ici CWnd
Souplesse d'intégration dans une classe existante.
Etc..
Les Inconvénients :
Le fait de devoir mettre le code dans le .h, ce qui nuit à la lisibilité, même en séparant dans un deuxième fichier la partie implémentation, cela peut avoir un impact sur le temps de compilation si cette classe est souvent utilisée ou si le code est conséquent.

Alors les classes patrons solution idéale ?
Presque, j'en viens maintenant au problème qui est apparu avec Visual 2005,
Un bug du ClassView empêche pour des classes dialogues (CFormView, CDialog, CDialogBar) construites à partir de classe patron la reconnaissance de la classe.
Dans ce contexte la demande de génération d'une variable contrôle à partir des ressources échoue, l'option contrôle variable étant grisée.
Pour résumer si vous utilisez une classe patron sur une classe dialogue il faudra vous passer de l'assistant pour associer une variable à son contrôle.
J'ai signalé ce problème au support Microsoft, la réponse est qu'effectivement le problème est constaté mais ce n'est pas une priorité et ne sera pas résolu…
Donc en conclusion tout était parfait avec Visual 6.0 , avec Visual 2005 et 2008 beaucoup moins..
Si l'assistant est indispensable Il faudra donc recourir à l'héritage multiple et se passer des classes patrons.

Mis à jour le 7 juillet 2008 farscape

Dans les propriétés du projet sur l'onglet link/system on trouve l'option /TSAWARE.
Cette option permet de spécifier que l'application est compatible Terminal Serveur et n'apporte pas de modification au chargement du programme.

Quelles sont les conséquences de cette option ?
Dans le cas d'une application non compatible (on parle d'application héritée ou legacy)
Terminal Serveur apporte des modifications pour faire fonctionner correctement l'application dans un environnement multi-utilisateur.
Ainsi il va créer un dossier Windows virtuel pour que chaque utilisateur puisse accéder à ses propres fichiers .ini ou à son paramétrage dans la base de registres dans la clef HKEY_CURRENT_USER
Donc par défaut Visual 2008 considère que l'application est compatible avec Terminal Serveur et que vous n'utilisez pas les .ini ou la clef HKEY_CURRENT_USER
Ce qui signifie que par exemple que l'api32 GetWindowsDirectory renvoie toujours C:\windows quelque soit l'utilisateur, j'en ai fait les frais il n'y pas longtemps…
Ce qui n'était pas le cas sous Visual 6.0

Mis à jour le 7 juillet 2008 farscape

Une application compatible Terminal serveur ne gère plus un emplacement virtualisé pour la gestion des fichiers ini.
Voir ce post de la faq pour plus de renseignements Comment rendre une application compatible terminal serveur ?
Dans ces conditions comment récupérer ce chemin virtualisé ?
On utilisera la fonction SHGetFolderPath avec l'option CSIDL_PROFILE.
L'exemple ci-dessous récupère le chemin du profil utilisateur et crée le répertoire Windows s'il n'existe pas.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
  
TCHAR szPath[MAX_PATH]; 
if(SUCCEEDED(SHGetFolderPath(NULL,  
			CSIDL_PROFILE |CSIDL_FLAG_CREATE,  
			NULL, 0,szPath)))  
{ 
    PathAppend(szPath, TEXT("Windows")); 
    if(!PathIsDirectory(szPath)) CreateDirectory(szPath,NULL); 
}

Mis à jour le 7 juillet 2008 farscape

Le passage de Visual 2005 à Visual 2008 n'est pas sans surprises …
Vous avez dû certainement vous rendre compte que pour de vieux projets issus de Visual6 ou autres Visual définissait par défaut la plateforme système à Windows Vista ?
Laisser ce choix par défaut n'est pas sans danger, en effet certaines API comme SystemParametersInfo ne fonctionneront plus sous windows XP, la fonction renverra NULL!.

Je me sers de cette API pour récupérer la fonte système par défaut, donc par chance je me suis rendu assez vite compte du problème avec le code suivant :

Code c++ : Sélectionner tout
1
2
3
4
5
  
NONCLIENTMETRICS ncm;  
ncm.cbSize = sizeof(NONCLIENTMETRICS);  
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));  
SetFont(&(ncm.lfMessageFont));
à qui La faute ?
Eh bien la structure utilisée a changée de taille sous Vista, en laissant le paramétrage par défaut sur Vista la taille de la structure évaluée par sizeof correspond donc à la version de l'API sous Vista, et l'appel échouera sous Windows XP.
En cherchant un peu dans les sources de Visual 2008 on trouve une référence à l'ancienne structure que vous pouvez comparer à la nouvelle..

Code c++ : Sélectionner tout
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
  
struct AFX_OLDNONCLIENTMETRICS  
  {  
    UINT cbSize;  
    int iBorderWidth;  
    int iScrollWidth;  
    int iScrollHeight;  
    int iCaptionWidth;  
    int iCaptionHeight;  
    LOGFONT lfCaptionFont;  
    int iSmCaptionWidth;  
    int iSmCaptionHeight;  
    LOGFONT lfSmCaptionFont;  
    int iMenuWidth;  
    int iMenuHeight;  
    LOGFONT lfMenuFont;  
    LOGFONT lfStatusFont;  
    LOGFONT lfMessageFont;  
  };  
typedef struct tagNONCLIENTMETRICS {  
  UINT cbSize;  
  int iBorderWidth;  
  int iScrollWidth;  
  int iScrollHeight;  
  int iCaptionWidth;  
  int iCaptionHeight;  
  LOGFONT lfCaptionFont;  
  int iSmCaptionWidth;  
  int iSmCaptionHeight;  
  LOGFONT lfSmCaptionFont;  
  int iMenuWidth;  
  int iMenuHeight;  
  LOGFONT lfMenuFont;  
  LOGFONT lfStatusFont;  
  LOGFONT lfMessageFont;  
  int iPaddedBorderWidth;  
} NONCLIENTMETRICS,
Comment résoudre ce problème ?
Dans les sources de Visual 2008, le problème est résolu pour cette API comme suit :

Code c++ : Sélectionner tout
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
  
struct AFX_OLDNONCLIENTMETRICS  
  {  
    UINT cbSize;  
    int iBorderWidth;  
    int iScrollWidth;  
    int iScrollHeight;  
    int iCaptionWidth;  
    int iCaptionHeight;  
    LOGFONT lfCaptionFont;  
    int iSmCaptionWidth;  
    int iSmCaptionHeight;  
    LOGFONT lfSmCaptionFont;  
    int iMenuWidth;  
    int iMenuHeight;  
    LOGFONT lfMenuFont;  
    LOGFONT lfStatusFont;  
    LOGFONT lfMessageFont;  
  };  
  
const UINT cbProperSize = (_AfxGetComCtlVersion() < MAKELONG(1, 6))  
    ? sizeof(AFX_OLDNONCLIENTMETRICS) : sizeof(NONCLIENTMETRICS);  
  
  NONCLIENTMETRICS NonClientMetrics;  
  NonClientMetrics.cbSize = cbProperSize;  
  
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, cbProperSize, &NonClientMetrics, 0);  
  
m_MenuFont.CreateFontIndirect(&NonClientMetrics.lfMenuFont);
Comme il est difficile de connaître les autres incompatibilités, il est préférable de définir un niveau de plateforme de Windows compatible au plus près de sa cible.
Dans mon cas avec un poste de production sous Windows XP je l'ai défini dans stdafx.h (au sommet)

Code c++ : Sélectionner tout
1
2
3
4
5
  
#if _MSC_VER > 1200   
#define   WINVER 0x0500    // windows 2000  
#define _WIN32_WINNT 0x0501     // xp  
#endif

Mis à jour le 7 juillet 2008 farscape

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.