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
- Comment créer une bibliothèque de liens dynamiques (DLL) ?
- Comment faire une DLL de ressources ?
- Comment faire une version multilingue sans passer par des DLL de ressources ?
- Comment faire un programme multilingue ?
- Comment faire une DLL d'extensions ?
- Comment quitter une application à partir d'une DLL ?
- Comment distribuer une application VC6.0 en DLL partagées ?
- Que puis-je interfacer entre une DLL VC++ et VB ?
- Comment accéder aux ressources d'une DLL d'extensions?
- Comment obtenir le CWinApp du module exe dans une dll régulière liées dynamiquement aux MFC ?
- Comment distribuer une application C++ avec Visual 2005 ?
- Comment distribuer une application MFC avec Visual 2008 ?
- Comment charger une bibliothèque dynamiquement ?
Après avoir lancé AppWizard trois choix possibles sont disponibles à partir du choix MFC AppWizard DLL :
- Regular dll with MFC staticaly linked.
- Regular dll with using shared MFC DLL
- MFC extension DLL (using shared MFC DLL)
Les deux premiers sélectionnent le mode de travail avec les MFC :
une DLL normale liée de manière statique aux MFC et une DLL normale liée de manière dynamique aux MFC (shared MFC DLL)
La troisième solution correspond à la construction d'une DLL d'extension des MFC.
Regular dll with MFC staticaly linked :
La construction d'une DLL liée de manière statique aux MFC permettra l'utilisation de celle-ci quelque soit le programme : WIN32 ou autre qu'il fasse appel ou non aux MFC ,l'inconvénient :la taille de la DLL étant donné que le code des MFC est incorporé dedans .
Regular dll with using shared MFC DLL:
La construction d'une DLL liée de manière dynamique aux MFC peut aussi être utilisée par tout programme WIN32 ou autre par contre la présence des DLL liées aux MFC sera exigée dans l'environnement d'exécution.
L'option sélectionnée ici sera une DLL avec les MFC en DLL partagées.
Après génération du projet par AppWizard il ne reste plus qu'à écrire les fonctions dans la DLL.
Dans mon exemple la définition sera dans le fichier interface.h et le code dans interface.cpp.
Code C++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // interface.h #ifdef _WINDLL #define DLLDEC __declspec(dllexport) #else #define DLLDEC __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif DLLDEC void TestDll(); #ifdef __cplusplus } #endif |
Code C++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | // interface.cpp #include "stdafx.h" #include "interface.h" #define WM_TEST WM_USER+100 void TestDll() { CFrameWnd *pFrame=(CFrameWnd *)AfxGetMainWnd(); CView *pView=pFrame->GetActiveView(); pView->PostMessage(WM_TEST); } |
Pour exporter une fonction d'une DLL il faut employer le mot clef dllexport conjointement avec le mot clef__declspec.
L'exemple ci-dessus permet d'exporter la fonction TestDll , celle-ci sera disponible aussi bien dans un source C++ ou C grâce à l'utilisation de la commande extern "C".
Il ne reste plus qu'à compiler, linker l'ensemble et à placer la DLL dans le répertoire d'exécution du programme appelant.
Insertion de la DLL dans un projet :
Il faudra rajouter dans le fichier testdll.lib dans l'onglet link du projet. Project Settings onglet link.
Et ajouter le fichier interface.h pour utiliser les fonctions de la dll.
Dans quels cas utiliser une DLL de ressources ?
A chaque fois que l'on voudra avoir un programme avec une interface multilingue, ou, par exemple s'adapter à une résolution d'écran :une dll de ressources pour la résolution 800*600 .
Procédure pour créer une DLL de ressources :
Après avoir lancé AppWizard choisir l'option :Win32 dynamic link Library .
Ensuite prendre l'option an empty DLL project.
Insérer le fichier ressource.h et le fichier .rc dans le projet.
Réglages des options de construction de la DLL :
Project setting onglet link :
Cocher les options :
- Doesn't produce.lib
- Ignore all default libraries
Et rajouter dans la partie project options : /noentry pour éviter d'avoir une référence à la fonction _main au link.
Compiler et linker.
1ere étape, Dans la "ResourceView" :
Dans l'onglet "ResourceView" de VC, choisir par exemple une boîte de dialogue, faire bouton droit "insert copy".
Il apparaît alors une boîte de dialogue demandant le langage pour lequel la copie va être affectée.
Imaginons que l'on choisisse "English (UK)" dans le combo, il faut saisir dans l'EditBox dessous une valeur pour le compilateur (pour savoir quelle ressource il va linker dans l'exe) par exemple "_ENG".
Ensuite évidement il faut traduire la ressource.
Il faut faire de même avec toutes les ressources.
Remarque :
Pour la string table il faut faire aussi"insert copy", on choisit la langue mais on ne saisit pas de condition.
On traduit les textes mais là (va savoir pourquoi), le compilo link toutes les stringtable et Windows ira chercher la StringTable de l'exe correspondant à son langage .
Bref, La stringTable est très interessante pour les messagebox :
Dans le Code on fait:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | CString Message; Message.LoadString(IDS_TASTRING_POUR_CE_MESSAGE); //IDS_TASTRING_POUR_CE_MESSAGE est l'id d'une string qui sera en français // dans la StringTable Française (et donc sur un Windows Français) //et en Anglais dans la StringTable en Anglais( et donc sur un Windows Anglais) //ça évite de dupliquer le code de faire 2 worspace ou d'avoir des surprise sur des Messagebox... |
Dans le menu BUILD->Configurations
S'ouvre une boîte de dialogue :
Cliquer sur Add et la rajouter une debug par exemple Debug_ENG et une release : Release_ENG
Enfin taper Alt+F7 ou Menu Projects->Settings
Choisir par exemple le projet Release_ENG
Dans l'onglet "Ressource"
Dans le combo "Language" choisir la langue ici English (UK) et dans l'EditBox "Preprocessor Definition" rajoute",_ENG"
Ainsi seront linké dans l'exe que les ressources avec la condition _ENG
2eme remarque :
du coup il faut faire pareil avec la version Française (Condition _FRA par exemple)
Si l'on teste l'exe anglais sur un windows français on verra que les menus, les messagebox sont française, car les deux versions de la stringtable sont dans l'exe et windows choisit la plus apropriée à la version de Windows .
Bilan :
Il n'y as pas vraiment d'avantages ou d'inconvéniant par rapports aux DLL de resources, si ce n'est que l'Executable peut être plus lourd car si vous faites beaucoup de version il aura toutes les StringTables (pas les boites de dialogues).
C'est une question de goût on va dire...
On utilisera le stockage des ressources dans une DLL pour chaque langue.
Exemple :
Dans un projet existant dont les ressources sont en Anglais on veut implémenter les mêmes ressources mais en Français.
Procédure :
Dans le projet principal on appelle AppWizard pour la création d'un nouveau projet en utilisant l'option add to curent workspace.
Choisir l'option Win32 dynamic link Library .
Donner un nom à la DLL qui correspondra à la langue implémentée Exemple :ResDllFr
Ensuite prendre l'option an empty DLL project.
Réglages des options de construction de la DLL :
Project setting onglet link :
Cocher les options :
- Doesn't produce.lib
- Ignore all default libraries
Et rajouter dans la partie project options :/noentry pour éviter d'avoir une référence à la fonction _main au link.
Copier à partir du projet principal dans le répertoire de la DLL:
Le fichier ressource.h et le fichier .rc .
Copier aussi le répertoire res.
Procédure sous .NET:
Dans l'explorateur de projet (solution) faire click droit :
Ajouter / nouveau projet
Sélectionner le type de projet win32
Sélectionner le répertoire du projet principal
Donner un nom à la DLL qui correspondra à la langue implémentée Exemple :ResDllFr
Faire ok
Sélectionner paramètres de l'application
Cocher DLL et projet vide.
Valider avec le boutonterminer
Réglages des options de construction de la DLL :
Sur le nouveau projet faire click droit propriétés :
Sélectionner le chapitre éditeur de liens :
Option avancée :
Dans la rubrique DLL de ressource uniquementmettre oui
Option Entrée :
Dans la rubrique Toutes les bibliothèques par défaut ignorées mettre oui
Copier à partir du projet principal dans le répertoire de la DLL:
Le fichier ressource.h et le fichier .rc .
Copier aussi le répertoire res.
Ajouter par l'option ajouter un élément existant le .rc et le fichier ressource.h au projet .
Traduire les ressources dans la langue appropriée.
Compiler linker la DLL.
Sélection de la DLL dans le programme principal :
Dans la fonction InitInstance de la classe d'application on lira la DLL concernée :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | m_bFrenchRes=(GetProfileInt("Language","SetInFr",0)==1); if(m_bFrenchRes) { HINSTANCE dll=LoadLibrary("ResDllFr.dll"); if(dll) AfxSetResourceHandle(dll); } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | int CTestResDllApp::ExitInstance() { // TODO: Add your specialized code here and/or call the base class // recuperation du handle de ressource. HMODULE hDLL = AfxGetResourceHandle(); // comparaison avec le handle de l'instance if (hDLL != AfxGetInstanceHandle()) { // si le handle des ressources est <> du handle de l'instance // c'est que les ressouces sont externes ! // restitution et liberation finale. AfxSetResourceHandle(AfxGetInstanceHandle()); FreeLibrary(hDLL); } return CWinApp::ExitInstance(); } |
Une DLL d'extensions permet l'export de classes complètes que le client peut instancier et même dériver.
Note : L'utilisation d'une DLL d'extensions impose l'utilisation des MFC en DLL partagées.
Comment procéder :
Au lancement de AppWizard par le menu file new Project.
Sélectionner l'option MFC AppWizard(dll)
Puis l'option MFC extension DLL (using shared MFC DLL).
Le squelette de la DLL est généré il ne reste plus qu'à implémenter les différentes classes en rajoutant la macro AFX_EXT_CLASS devant chaque nom de classe à exporter, comme dans l'exemple ci-dessous :
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 | ///////////////////////////////////////////////////////////////////////////// // CMyListBox window class AFX_EXT_CLASS CMyListBox : public CListBox { // Construction public: CMyListBox(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyListBox) //}}AFX_VIRTUAL // Implementation public: virtual ~CMyListBox(); // Generated message map functions protected: //{{AFX_MSG(CMyListBox) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; |
On utilisera le même include pour la définition des classes exportées dans la DLL et l'application MFC .
Le .lib de la DLL devra être rajouté au link de l'application MFC.
Pour sortir proprement du programme il ne faut surtout pas faire exit(0) à partir de la DLL mais faire la demande de fermeture sur le thread principal du programme .
Il suffira d'envoyer la commande suivante à partir de la DLL :
Code c++ : | Sélectionner tout |
1 2 | AfxGetMainWnd()->PostMessage(WM_SYSCOMMAND,SC_CLOSE,0); |
La distribution des DLL partagées pour une application Visual VC6.0 est nécessaire pour les systèmes antérieurs à Windows 2000 .
Les principales DLL sont à jour sur les systèmes récents.
Pour infos voici la liste des principales DLL concernées :
- MFC42.DLL
- MSVCRT.DLL
et éventuellement :
- MSVCP60.DLL
- NTDLL.DLL
- MSVCIRT.DLL
il est à noter que la mise à jour de IE 5 ou 6.0 mets à jour un grand de composant sur ces systèmes....
Néanmoins pour distribuer une application en DLL partagées on dispose d'un utilitaire VCREDIST.EXE
consulter la note d'informations MSDN à ce sujet : Redistributing Microsoft Visual C++ 6.0 Applications
Note :VCREDIST.EXE est mis à jour avec la distribution du service pack de Visual 6.0 ,on le trouve généralement dans le répertoire : FRENCH\VS60SP5\VC98\REDIST\VCREDIST.EXE pour le SP5 .
En théorie, seuls les types de base sont passables d'une DLL C++ à VB:
Un petit résumé provenant de l'aide de VC++ et VB sur les types de Base :
EN VB :
Byte | 1 byte | 0 to 255 |
Boolean | 2 bytes | True or False |
Integer | 2 bytes | -32,768 to 32,767 |
Long (long integer) | 4 bytes | -2,147,483,648 to 2,147,483,647 |
Single(single-precision floating-point) | 4 bytes | |
Double (double-precision floating-point) | 8 bytes |
char, unsigned char, signed char | 1 byte |
short, unsigned short | 2 bytes |
int, unsigned int | 4 bytes |
long, unsigned long | 4 bytes |
float | 4 bytes |
double | 8 bytes |
long double 1 | 8 bytes |
C++ | VB |
char | byte |
bool | Boolean |
short | Integer |
int | Long |
long | Long ou rien |
float | Single |
double | Double |
Une fonction déclarée en C++ comme suit :
Code c++ : | Sélectionner tout |
bool TestVB_Cpp(int Entier, double Reel, char Caractere, char* Chaine)
Code c++ : | Sélectionner tout |
1 2 | Public Declare Function TestVB_Cpp Lib "MaDLL.dll" (ByVal Entier As Long, ByVal Reel As Double, ByVal Caractere As Byte, ByVal Chaine As String) As Boolean |
En effet une adresse mémoire étant stockée sur 4 BYTES, on peut déclarer en C++ un pointeur de ce que l'on veut et le récupérer en VB grace à une variable déclarée en ByRef Long.
Par exemple, on peut manipuler les fonctions BMP du GDI
J'avais trouvé ça sur internet sachant que "&H" en VB correspond à "0x" de C++.
La structure BITMAP C++ correspond en VB à :
Code vb.net : | 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 | '**********BITMAP**************** Public Const SRCCOPY = &HCC0020 Public Const DIB_RGB_COLORS = 0 Public Type BITMAP biSize As Long biWidth As Long biHeight As Long biPlanes As Integer biBitCount As Integer biCompression As Long biSizeImage As Long biXPelsPerMeter As Long biYPelsPerMeter As Long biClrUsed As Long biClrImportant As Long End Type '**********WAPI**************** Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Public Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long Public Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long Public Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | typedef struct tagBITMAPINFOHEADER{ // bmih DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; |
Par contre il n'existe pas à ma connaissance de moyen d'exporter un Objet C++ avec ces méthodes afin que VB puisse les appeler depuis une DLL. La seule solution est un ActiveX.
Pour définir l'accès procéder comme suit :
Dans le menu view option ressources includes.
Rajouter l'include des ressources contenant les définitions des identifiants de la DLL à la suite de la ligne
Code c++ : | Sélectionner tout |
1 2 3 | #include "afxres.h" #include "MyLibres.h" // ressources DLL |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #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 //_WIN32 #include "res\TestMdi.rc2" // non-Microsoft Visual C++ edited resources #include "l.fra\afxres.rc" // Standard components #include "l.fra\afxprint.rc" // printing/print preview resources #endif #include « MyLib.rc » // fichier ressources DLL |
Voici un petit rappel pour ce qui est d'une dll normale ou régulière liée de manière dynamique aux MFC
Citation MSDN:
Une DLL normale liée de manière dynamique aux MFC est une DLL qui utilise les MFC en interne,
et les fonctions exportées de la DLL peuvent être appelées par des exécutables MFC ou non-MFC.
Comme son nom l'indique, ce type de DLL est généré à l'aide de la version bibliothèque de
liaisons dynamiques des MFC (appelée également version partagée des MFC).
Les fonctions sont généralement exportées à partir d'une DLL normale à l'aide de l'interface C standard.
Vous devez ajouter la macro AFX_MANAGE_STATE au début de toutes les fonctions exportées des
DLL normales qui sont liées de manière dynamique aux MFC pour définir l'état du module en cours
comme étant celui de la DLL.
Pour cela, ajoutez la ligne de code suivante au début des fonctions exportées à partir de la DLL :
Code c++ : | Sélectionner tout |
1 2 | AFX_MANAGE_STATE(AfxGetStaticModuleState( )) |
Une dll normale ou régulière possède un objet CWinApp comme n'importe quel module exe MFC.
Si nous voulons obtenir l'objet application dans le module exe nous faisons
Code c++ : | Sélectionner tout |
1 2 3 4 | CDuplicataApp* pTheApp = static_cast<CDuplicataApp*>(AfxGetApp()); ATLASSERT(pTheApp); //... |
où Duplicata est le module exe.
Comment obtenir ce même pointeur dans une dll régulière tout en sachant qu'un appel à AfxGetApp()
retourne le CWinApp de la dll.
Voici comment nous pouvons procéder:
Duplicata est un module exe et
Duplicata.Data est une dll régulière liée dynamiquement aux MFC.
Dans ce genre de dll, toute fonction exportée doit inclure la macro
Code c++ : | Sélectionner tout |
1 2 | AFX_MANAGE_STATE(AfxGetStaticModuleState( )) |
Voici du code.
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 | INT_PTR WINAPI ShowQuerySheet(UINT iSelectedPage, bool& bMultiSelectedQueryPage) // est une fonction exportée de Duplicata.Data.dll { // Obtient le CWinApp de l'exécutable donc Duplicata.exe et non de Duplicata.Data.dll // car l'appel à AfxGetApp() précède AFX_MANAGE_STATE(AfxGetStaticModuleState()) CDuplicataApp* pTheApp = static_cast<CDuplicataApp*>(AfxGetApp()); // je suis dans le context du module exe ATLASSERT(pTheApp); AFX_MANAGE_STATE(AfxGetStaticModuleState()); // MFC définit l'état du module en cours // Obtient le CWinApp de la dll donc Duplicata.Data.dll et non de Duplicata.exe // car l'appel à AfxGetApp() est postérieur à AFX_MANAGE_STATE(AfxGetStaticModuleState()) CDuplicataDataApp* pTheDll = static_cast<CDuplicataDataApp*>(AfxGetApp()); // je suis dans le context du module de la dll ATLASSERT(pTheDll); // maintenant dans le code de ma dll, je travaille à la fois avec pTheApp et pTheDll // obtenu à l'aide du seul appel de AfxGetApp() dans des états de modules différents. // ... } |
En demeurant dans le contexte du module exe, avant que MFC rétablisse l'état du module en cours, nous pouvons récupérer
le CWinApp du module exe mais nous ne pouvons utiliser aucun objet de la dll.
Mais une fois que l'état du module en cours est rétabli, alors les objets de la dll sont maintenant disponibles et
à l'aide du même AfxGetApp() nous obtenons le CWinApp de la dll.
Les pointeurs obtenus sont valides et vous pouvez le vérifier avec le débogueur.
Dans le cas d'une dll MFC d'extension nous n'avons pas ce problème de changement de contexte de module d'état
avec AFX_MANAGE_STATE car le CWinApp est unique et est celui du module exe.
Avec Visual 2005 les dll concernant la bibliothèque CRT et MFC ont changé.
De ce fait la plupart des PC récents ne disposent pas des fichiers requis pour exécuter les programmes construits avec Visual 2005.
Vous trouverez sur ce lien l'accès à un setup permettant de distribuer les DLL sur un PC cible vcredist_x86.exe
Ce package installe les composants du runtime des bibliothèques C Runtime (CRT), Standard C++, ATL, MFC, OpenMP et MSDIA.
Note : ce fichier est aussi disponible dans l'environnement de développement à l'emplacement suivant :
C:\Program Files\Microsoft Visual Studio8\SDK\v2.0\BootStrapper\Packages\vcredist_x86\vcredist_x86.exe
Si on ne veut pas distribuer de DLL ,il faudra lier statiquement les MFC et sélectionner dans l'onglet C++ / option génération de code / bibliothèque runtime :Multithread (/MT)
Néanmoins il faudra veiller à ne pas mélanger les modes de fonctionnement avec la CRT en Multithread DLL et statique, pour éviter les problèmes sur les libérations d'objets entre modules ou partage de ressources fichiers.
Il y a deux manières de construire une application MFC :
- La plus utilisée c'est d'utiliser les MFC en dll partagée, ce qui implique que la bibliothèque de runtime C (CRT) soit aussi dans ce mode partagé ( Multithread DLL :/MD ).
Avantage : l'exécutable produit est plus léger puisqu'il ne comporte pas les MFC et la dll de la CRT.
Inconvénient : il faut distribuer un ensemble de DLL sur le poste cible.
Il existe plusieurs manières de procéder :
- Utiliser l'utilitaire vcredist_x86.exe évoqué dans cet autre poste de la faq Comment distribuer une application C++ avec Visual 2005 ?
- Créer un projet de déploiement pour le projet.
- Enfin copier manuellement le programme et ses dépendances dans un répertoire.
Comment procéder :
Créer un répertoire de distribution en dehors de program file (pour éviter les problèmes sous vista).
Copier son exécutable dedans.
Ensuite copier les fichiers contenus dans les répertoires :
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
Et
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.MFC
- La deuxième option de construction du programme consiste à utiliser les MFC dans une bibliothèque statique, la bibliothèque de runtime C (CRT) doit suivre le même mode statique ( Multithread static : /MT ).
Avantage : un exécutable autonome
Inconvénients : taille de l'exécutable non négligeable, surtout si on utilise les nouvelles MFC …
Autre point : difficulté de construction du programme si on dispose d'un ensemble de bibliothèques tierces : il faudra en effet veiller à ce que celles-ci travaillent dans le même mode surtout au niveau de la bibliothèque de runtime C .
En utilisant les méthodes LoadLibrary, GetProcAddress et FreeLibrary.
Exemple pour charger dynamiquement l'API MessageBox :
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 | typedef INT (WINAPI* PFNMESSAGEBOX)(HWND, LPCTSTR , LPCTSTR, UINT); static PFNMESSAGEBOX g_pfnMessageBox = NULL; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HMODULE hmodUser32 = LoadLibrary(TEXT("USER32")); if (hmodUser32 != NULL) { #ifdef UNICODE g_pfnMessageBox = (PFNMESSAGEBOX) GetProcAddress(hmodUser32, "MessageBoxW"); #else g_pfnMessageBox = (PFNMESSAGEBOX) GetProcAddress(hmodUser32, "MessageBoxA"); #endif } g_pfnMessageBox(NULL, TEXT("Test"), TEXT("Titre"), 0); if (hmodUser32 != NULL) FreeLibrary(hmodUser32); return 0; } |
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 çaLes 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.