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

SommaireDivers bis (19)
précédent sommaire
 

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
LPVOID lpMsgBuf; 
 FormatMessage( 
    FORMAT_MESSAGE_ALLOCATE_BUFFER | 
    FORMAT_MESSAGE_FROM_SYSTEM | 
    FORMAT_MESSAGE_IGNORE_INSERTS, 
    NULL, 
    GetLastError(), 
    0, // Default language 
    (LPTSTR) &lpMsgBuf, 
    0, 
    NULL 
   ); 
   // Process any inserts in lpMsgBuf. 
   // ... 
   // Display the string. 
   AfxMessageBox((LPCTSTR)lpMsgBuf, MB_OK | MB_ICONINFORMATION ); 
   // Free the buffer. 
   LocalFree( lpMsgBuf );

Mis à jour le 5 avril 2013 farscape

Avec la fonction GetComputerName.

Code c++ : Sélectionner tout
1
2
3
4
5
6
  
char szBuffer[MAX_COMPUTERNAME_LENGTH + 1]; 
if(GetComputerName(szBuffer,MAX_COMPUTERNAME_LENGTH)) 
{ 
  AfxMessageBox(szBuffer); 
}

Mis à jour le 5 avril 2013 farscape

Il faut déclarer dans la base de registre une zone de type chaîne correspondant au nom de l'application à l'emplacement suivant :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Ensuite on placera dans la zone le chemin complet de l'exécutable.

Exemple : Valeur chaîne (type REG_SZ) : MonProg
Contenu : C:\Program Files\MonProg\MonProg.exe

Mis à jour le 5 avril 2013 farscape

Utiliser les API : QueryPerformanceFrequency et QueryPerformanceCounter qui donnent respectivement la fréquence du compteur et sa valeur.

voici une classe qui permet de l'utiliser simplement
MesurePrecision.h

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
  
  
#ifndef _MESURE_PRECISION_H 
#define _MESURE_PRECISION_H 
  
#include <windows.h> 
  
class CMesurePrecision   
{ 
public: 
  
    CMesurePrecision(); 
    virtual ~CMesurePrecision(); 
    bool Start(); 
    double GetTimeFromStart(); 
    char * GetLastError(); 
  
private: 
  
    LARGE_INTEGER frequence,debut,fin; 
    char lastError[264]; 
  
}; 
#endif
MesurePrecision.cpp

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  
  
#include "MesurePrecision.h" 
  
CMesurePrecision::CMesurePrecision() 
{ 
    strcpy(lastError,"Pas d'erreur"); 
} 
  
CMesurePrecision::~CMesurePrecision(){} 
  
bool CMesurePrecision::Start() 
{ 
    if (!QueryPerformanceFrequency(&frequence)) 
    { 
        LPVOID lpMsgBuf;  
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM | 
            FORMAT_MESSAGE_IGNORE_INSERTS, NULL,  
            ::GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL);  
        strcpy(lastError,(LPCSTR)lpMsgBuf); 
        LocalFree( lpMsgBuf ); 
        return false; 
  
    } 
    if(!QueryPerformanceCounter (&debut)) 
    { 
        LPVOID lpMsgBuf;  
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |  
            FORMAT_MESSAGE_FROM_SYSTEM |  
            FORMAT_MESSAGE_IGNORE_INSERTS,  
            NULL, ::GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL);  
        strcpy(lastError,(LPCSTR)lpMsgBuf);    
        LocalFree( lpMsgBuf );     
        return false; 
    } 
    strcpy(lastError,"Pas d'erreur"); 
    return true; 
} 
double CMesurePrecision::GetTimeFromStart() 
{ 
    if (!QueryPerformanceCounter (&fin)) 
    { 
  
        LPVOID lpMsgBuf;  
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 
            FORMAT_MESSAGE_IGNORE_INSERTS, NULL,  
            ::GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL); 
        strcpy(lastError,(LPCSTR)lpMsgBuf); 
        LocalFree( lpMsgBuf ); 
        return 0; 
  
    } 
    strcpy(lastError,"Pas d'erreur"); 
    return ((double)((__int64)fin.QuadPart)-((__int64)debut.QuadPart)) /  
            (double)frequence.QuadPart; 
} 
char * CMesurePrecision::GetLastError() 
{ 
return lastError; 
}
Remarque : travaillant sur des entiers de 64 bits, on a malheureusement besoin de se risquer à faire une conversion en nombres à virgules (double). Exemple d'utilisation

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
CMesurePrecision compteur; 
if (!compteur.Start()) 
MessageBox(NULL,compteur.GetLastError(),"",MB_ICONSTOP); 
  
// ************** 
for (long k=0;k<1000000;k++); // code à évaluer 
// ************** 
double temps_execution = compteur.GetTimeFromStart(); 
if (temps_execution==0) 
MessageBox(NULL,compteur.GetLastError(),"",MB_ICONSTOP);
L'utilisation de GetTickCount() aurait donné 0 (précis à la milliseconde seulement)

Mis à jour le 5 avril 2013 nico-pyright(c)

Pour une application réalisée en Visual 6.0 il suffit d'avoir un fichier "manifest" et de procéder comme suit:

  • Remplacer MYAppName par le nom de votre application.
  • Le fichier soit se nommer MyAppName.exe.manifest.
  • Placer le fichier dans le répertoire d'exécution.

Ci-dessous le modèle du fichier manifest

Code xml : 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
  
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">  
<assemblyIdentity  
    version="1.0.0.0"  
    processorArchitecture="X86"  
    name="MYAppName" 
    type="win32"  
/>  
<description>Your app description here</description>  
<dependency>  
    <dependentAssembly>  
        <assemblyIdentity  
            type="win32"  
            name="Microsoft.Windows.Common-Controls"  
            version="6.0.0.0"  
            processorArchitecture="X86"  
            publicKeyToken="6595b64144ccf1df"  
            language="*"  
        />  
    </dependentAssembly>  
</dependency>  
</assembly>

Mis à jour le 5 avril 2013 farscape

Avec le post Comment appliquer le style XP aux fenêtres ? Nous avons vu comment générer un fichier manifest pour donner le style XP à nos applications.
Pour intégrer directement ce fichier dans les ressources procéder comme suit :

Editer le fichierressource .h du projet et rajouter ces deux lignes :

Code c++ : Sélectionner tout
1
2
3
  
#define IDR_MANIFEST  1 
#define RT_MANIFEST  24
éditer le fichier .rc2 situé dans le volume /res de votre application avec notepad ,et rajouter la ligne suivante :

Code c++ : Sélectionner tout
1
2
3
4
  
// Add manually edited resources here... 
IDR_MANIFEST RT_MANIFEST MOVEABLE PURE 
             "res\\MyAppManifestFile"
Ou MyAppManifestFile représente le nom du fichier manifest décrit précédemment enregistré dans le volume/res de votre application avec ce nom.
Recompiler les ressources et procéder à l'édition des liens de votre programme.

Note: Si le SDK est installé et les chemins de recherche de VC mis à jour, la ligne :

Code c++ : Sélectionner tout
1
2
  
#define RT_MANIFEST  24
devra être mise en commentaire pour éviter le warning à la compilation.

Mis à jour le 19 septembre 2005 farscape

En premier lieu au procédera à la création de notre fichier manifeste pour le style XP comme expliqué ici Comment appliquer le style XP aux fenêtres ?

Puis on rajoutera ce manifeste au manifeste principal comme suit :
Sur les propriétés du projet dans :

configuration properties ou propriétés de configuration
Manifest tool ou Outil Manifeste
Input and OutPut ou Entrée et Sortie
Enfin dans additional manifest file ou Fichiers manifestes supplémentaires

On indiquera le fichier manifeste précédemment pour disposer du style xp.

Note : le fichier manifeste que Visual génère n'a donc rien à voir avec le style XP ,il permet de préciser quelles versions de DLL l'application va utiliser …

Mis à jour le 22 janvier 2007 farscape

Il suffit de déclarer un projet « win32 application » puis de sélectionner l'option « a simple win32 application ».
On obtient le code suivant :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
#include "stdafx.h"  
int APIENTRY WinMain(HINSTANCE hInstance,  
                     HINSTANCE hPrevInstance,  
                     LPSTR     lpCmdLine,  
                     int       nCmdShow)  
{  
    // TODO: Place code here.  
  
   return 0;  
}

Mis à jour le 5 avril 2013 farscape

La fonction la plus simple MessageBeep :

Code c++ : Sélectionner tout
1
2
3
  
BOOL MessageBeep( 
UINT uType);
Valeurs possibles avec le Paramètre uType :

  • 0xFFFFFFFF
  • MB_ICONASTERISK
  • MB_ICONEXCLAMATION
  • MB_ICONHAND
  • MB_ICONQUESTION
  • MB_OK

Une solution plus évoluée :
Utiliser la fonction sndPlaySound qui permet de jouer des fichiers au format .wav.

Code c++ : Sélectionner tout
1
2
3
4
  
BOOL sndPlaySound( 
LPCTSTR lpszSoundName,  
UINT fuSound );
Deux manières de l'exploiter :
Lecture d'un fichier externe au programme a un emplacement donné :

Code c++ : Sélectionner tout
1
2
  
sndPlaySound("C:\\WINDOWS\\Media\\notify.wav",SND_SYNC);
Jouer un son à partir des ressources du programme :

Première phase insérer le fichier dans les ressources :
Cliquer dans les ressources sur le dossier le plus haut exemple :"TestMdi Ressources" avec le bouton droit de la souris sélectionner l'option import .
Mettre .wav dans le filtre fichier.
Maintenant on a une section "WAVE" avec l'id IDR_WAVE1 sur IDR_WAVE1 faire click droit propriétés et mettre le nom entre "" on doit avoir "IDR_WAVE1 " .

Deuxième phase lecture du son à partir des ressources :

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
  
#include "Mmsystem.h" 
bool PlaySound(LPCTSTR lpszName) 
{ 
    BOOL bRet=FALSE; 
    LPSTR lpRes; 
    HANDLE hRes; 
    HRSRC hRsrc; 
  
    HINSTANCE hinstance=AfxGetInstanceHandle(); 
  
    if(!(hRsrc=FindResource(hinstance,lpszName,"WAVE")))return false; 
  
    if(!(hRes = LoadResource(hinstance, hRsrc))) return false ; 
  
    if((lpRes=(LPSTR)LockResource(hRes)))  
    { 
        bRet = sndPlaySound(lpRes, SND_MEMORY | SND_SYNC); 
    } 
    FreeResource(hRes); 
    return (bRet >FALSE ); 
}  
PlaySound("IDR_WAVE1");
Note:il faudra inclure la librairie Winmm.lib. au link.

Mis à jour le 5 avril 2013 farscape

Des touches comme la touche Windows, ou la combinaison de ctrl+echap permettent d'afficher le menu démarrer, une touche comme impr écran envoie un bitmap dans le presse-papiers.
Ces touches sont gérées automatiquement par Windows, comment faire pour empêcher leur fonctionnement ?

En installant un hook global clavier et en interceptant les touches de bas niveau.
Un hook est installé obligatoirement dans une dll.
Pour plus de détails sur les hooks, voir SetWindowsHookEx dans MSDN.

Le message à intercepter est le suivant : WH_KEYBOARD_LL, pour le low level keyboard.
En construisant une structure de hook clavier, on peut récupérer le code de la touche, sa répétition, etc.

Code C++ : Sélectionner tout
KBDLLHOOKSTRUCT kbStruct = *((KBDLLHOOKSTRUCT *)lParam);

Puis sur un message de type WM_KEYDOWN, on intercepte les touches VK_LWIN ou VK_RWIN ou VK_SNAPSHOT, etc. en renvoyant 1 à la procédure de callback du hook clavier.
Pour avoir un comportement normal du clavier, il faut appeler la fonction CallNextHookEx.

Ne pas oublier d'arrêter le hook clavier à la fin en appelant UnhookWindowsHookEx.

Un exemple de dll qui installe un hook ainsi qu'un programme pour le tester est disponible ici demoHook.zip
[extrait]

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
LRESULT CALLBACK fonctionIntercepteClavierLowLevel (int nCode, WPARAM wParam, LPARAM lParam)  
{ 
    if(nCode == HC_ACTION)  
    { 
        KBDLLHOOKSTRUCT kbStruct = *((KBDLLHOOKSTRUCT *)lParam); 
        switch(wParam) 
        { 
        case WM_KEYDOWN: 
            if (kbStruct.vkCode == VK_LWIN || kbStruct.vkCode == VK_RWIN) // bloque touches Windows 
                return 1; 
  
            if (kbStruct.vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL)) // bloque control+echap 
                return 1; 
            if (kbStruct.vkCode == VK_SNAPSHOT) // bloque impr écran 
                return 1;  
        } 
    } 
    return CallNextHookEx(hookClavier, nCode, wParam, lParam); 
}

Note : Le hook WH_KEYBOARD_LL ne fonctionne que pour les systèmes d'exploitation NT/2000/XP ou supérieur

Mis à jour le 5 avril 2013 nico-pyright(c)

En utilisant l'API FlashWindowEx Exemple :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
FLASHWINFO flashInfo; 
flashInfo.cbSize = sizeof(FLASHWINFO); 
flashInfo.dwFlags = FLASHW_TRAY; 
flashInfo.uCount = 5; 
flashInfo.dwTimeout = 0; 
flashInfo.hwnd = hwnd; 
FlashWindowEx(&flashInfo);
Le membre dwFlags est FLASHW_TRAY pour faire clignoter la barre des tâches, il peut être FLASHW_CAPTION pour faire clignoter le caption (ou les deux : FLASHW_ALL). (plus de détails dans msdn)
Le membre uCount précise le nombre de répétitions et dwTimeout la fréquence (0 pour celle par défaut).
Bien évidemment, le membre hwnd correspond au handle de la fenêtre à faire clignoter.

Mis à jour le 4 avril 2005 nico-pyright(c)

Un process Win32 n'est rattaché à aucune console à sa création. Il est possible d'en obtenir une au moyen de AllocConsole, mais les flux standards de la bibliothèque C/C++ (stdout, cout, ...) n'y sont pas connectés. Le code suivant montre comment corriger cela:

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
38
39
40
41
42
43
44
45
46
47
  
#include <windows.h> 
  
#include <cstdio> 
#include <iostream> 
  
void InitializeConsoleStdIO() 
{ 
    // si une console est rattachée au processus, alors il existe des fichiers 
    // virtuel CONIN$ et CONOUT$ qui permettent respectivement de lire 
    // et d'écrire depuis / dans cette console (voir la doc de CreateFile). 
  
#if _MSC_VER >= 1400 // VC++ 8  
    {  
    // éviter le warning C4996: 'freopen' was declared deprecated  
    // This function or variable may be unsafe. Consider using freopen_s instead.  
    FILE *stream;  
    freopen_s( &stream, "CONIN$", "r", stdin );  
    freopen_s( &stream, "CONOUT$", "w", stdout );  
    freopen_s( &stream, "CONOUT$", "w", stderr );  
    }  
#else  
    std::freopen( "CONIN$", "r", stdin );  
    std::freopen( "CONOUT$", "w", stdout );  
    std::freopen( "CONOUT$", "w", stderr );  
#endif  
  
    // la ligne suivante synchronise les flux standards C++ (cin, cout, cerr...) 
    std::ios_base::sync_with_stdio();     
} 
  
int WINAPI WinMain(           
    HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, 
    int nCmdShow 
) 
{ 
    // créer une console 
    ::AllocConsole(); 
    // synchroniser la CRT 
    InitializeConsoleStdIO(); 
    // tester 
    std::cout << "Hello World!\n"; 
    std::cout << "Appuyez sur Entree pour quitter..."; 
    std::cin.ignore(); 
}

Mis à jour le 20 mai 2006 Aurelien.Regat-Barrel

Version Win32 : Dans la callback, lors du message WM_CREATE, initialiser la structure et ajouter l'icône

Code c++ : Sélectionner tout
static NOTIFYICONDATA TrayIcon;
la variable est définie en static dans la callback

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
TrayIcon.cbSize = sizeof(NOTIFYICONDATA); 
TrayIcon.hWnd = hwnd; 
TrayIcon.uID = 0; 
TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; 
TrayIcon.uCallbackMessage = WM_MOUSEMOVE; 
TrayIcon.hIcon = LoadIcon(hinst, (LPCTSTR) IDI_ICON1); 
strcpy(TrayIcon.szTip, "Mon info bulle"); 
Shell_NotifyIcon(NIM_ADD, &TrayIcon);
Dans cet exemple, le message à traiter est redirigé vers le message WM_MOUSEMOVE, c'est celui là qu'il faudra traiter.
Dans le traitement de WM_MOUSEMOVE, c'est ici qu'on va vérifier si c'est le bouton droit et afficher un menu

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
case WM_MOUSEMOVE: 
if(lParam == WM_RBUTTONDOWN) 
{ 
POINT pt; 
GetCursorPos(&pt); 
SetForegroundWindow(hwnd); 
TrackPopupMenu(GetSubMenu(LoadMenu(hinst, (LPCTSTR) IDR_MENU1), 0), 
 TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, 0); 
}
Le traitement du clic sur le menu se fera de manière classique dans le traitement du message WM_COMMAND

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
  
case WM_COMMAND: 
switch(wParam) 
{ 
case ID_QUITTER: 
PostMessage(hwnd, WM_DESTROY, 0, 0); 
}
(ici, en admettant que ID_QUITTER soit associé à un item du menu)
Il ne restera plus qu'à enlever l'icône de la barre des tâches système (par exemple, au moment du WM_DESTROY) avec un

Code c++ : Sélectionner tout
Shell_NotifyIcon(NIM_DELETE, &TrayIcon);


Version MFC :

Dans la classe MainFrame, déclarer un attribut privé

Code c++ : Sélectionner tout
NOTIFYICONDATA TrayIcon;
Le plus simple ici est d'associer un message personnalisé pour le traitement du click sur l'icone.
Rajouter la définition du message privé

Code c++ : Sélectionner tout
#define WM_TRAY_MESSAGE (WM_USER + 1)
Rajouter le prototype de la fonction qui va traiter ce message

Code c++ : Sélectionner tout
afx_msg void OnTrayNotify(WPARAM wParam, LPARAM lParam);
Et dans le MESSAGE_MAP

Code c++ : Sélectionner tout
ON_MESSAGE(WM_TRAY_MESSAGE,OnTrayNotify)
Créer la structure et l'icone (par exemple dans le OnCreate)

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
TrayIcon.cbSize = sizeof(NOTIFYICONDATA); 
TrayIcon.hWnd = this->m_hWnd; 
TrayIcon.uID = 1; 
TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; 
TrayIcon.uCallbackMessage = WM_TRAY_MESSAGE; 
TrayIcon.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDI_ICON1)); 
strcpy(TrayIcon.szTip, "Mon info bulle"); 
Shell_NotifyIcon(NIM_ADD, &TrayIcon);
Rajouter l'implémentation de la méthode qui va gérer le clic droit

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
  
afx_msg void CMainFrame::OnTrayNotify(WPARAM wParam, LPARAM lParam) 
{ 
    if ((UINT)wParam != 1) 
        return; 
    POINT pt; 
  
    switch (lParam) 
    {  
    case WM_RBUTTONDOWN: 
    case WM_CONTEXTMENU: 
        GetCursorPos(&pt); 
        CMenu myMenu; 
        myMenu.LoadMenu(IDR_MENU1); 
        myMenu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, 
            pt.x, pt.y, this); 
        break; 
    }  
    return;  
}
Ensuite, le traitement du message d'un menu se fera de manière classique, à l'aide du classWizard

Enfin, il ne faudra pas oublier de supprimer l'icône (par exemple à la fermeture de l'application)

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
  
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)  
{ 
if(nID==SC_CLOSE) 
{ 
Shell_NotifyIcon(NIM_DELETE, &TrayIcon); 
} 
CFrameWnd::OnSysCommand(nID, lParam); 
}
NB : Bien souvent, l'iconification se fait lors d'un minimise, il suffit de faire son traitement dans le OnSize pour le type SIZE_MINIMIZED

NB2 : Pour un menu pop-up, il faut créer un (et un seul) menu pop-up, et utiliser GetSubMenu(0) pour avoir le sous-menu

Mis à jour le 20 mai 2006 nico-pyright(c)

En utilisant les api FindFirstUrlCacheEntry, FindNextUrlCacheEntry, etc ... ex :

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  
#define _WIN32_WINNT 0x0501 
#define _WIN32_IE 0x0501 
#include <windows.h> 
#include <wininet.h> 
  
#pragma comment(lib, "wininet.lib") 
  
#define MEMDISPO      (MEM_RESERVE | MEM_COMMIT |MEM_TOP_DOWN) 
  
bool supprimeFichierDuCacheIE() 
{ 
    bool bResultat = false; 
    bool bFini = false; 
    LPINTERNET_CACHE_ENTRY_INFO lpEntreeDuCache = NULL; 
    DWORD  dwLongueur, dwTaille = 4096; // taille initiale du buffer 
    HANDLE hCache = NULL; 
    DWORD  dwErreur = ERROR_INSUFFICIENT_BUFFER; 
  
    while (!bFini) 
    { 
        // on a besoin d'un plus gros buffer (ou initialisation du buffer) 
        if (dwErreur == ERROR_INSUFFICIENT_BUFFER)  
        { 
            VirtualFree(lpEntreeDuCache, 0, MEM_RELEASE); 
            lpEntreeDuCache = (LPINTERNET_CACHE_ENTRY_INFO) VirtualAlloc(0, dwTaille, MEMDISPO, PAGE_READWRITE); 
            if (!lpEntreeDuCache) 
                bFini = true; 
            lpEntreeDuCache->dwStructSize = dwTaille; 
            dwLongueur = dwTaille; 
            BOOL bRetour; 
            if (!hCache) // première fois 
                bRetour = (hCache = FindFirstUrlCacheEntry(NULL, lpEntreeDuCache, &dwLongueur)) != NULL; 
            else 
                bRetour = FindNextUrlCacheEntry(hCache, lpEntreeDuCache, &dwLongueur); 
            if (bRetour) 
                dwErreur = ERROR_SUCCESS; 
            else 
            { 
                dwErreur = GetLastError(); 
                dwTaille = dwLongueur; // nouvelle taille à utiliser 
            } 
        } 
        else if (dwErreur == ERROR_NO_MORE_ITEMS) // fini 
        { 
            bFini = true; 
            bResultat = true; 
        } 
        else if (dwErreur == ERROR_SUCCESS) // traitement de l'entrée 
        { 
            // on ne supprime pas le cookie de DVP.COM :-) 
            if (!(lpEntreeDuCache->CacheEntryType & COOKIE_CACHE_ENTRY) ||  
                !strstr(lpEntreeDuCache->lpszSourceUrlName,"www.developpez.net"))  
                DeleteUrlCacheEntry(lpEntreeDuCache->lpszSourceUrlName); // suppression 
            dwLongueur = dwTaille; 
            if (FindNextUrlCacheEntry(hCache, lpEntreeDuCache, &dwLongueur)) 
                dwErreur = ERROR_SUCCESS; 
            else 
            { 
                dwErreur = GetLastError(); 
                dwTaille = dwLongueur; // nouvelle taille à utiliser 
            } 
        } 
        else // erreur inconnue 
        { 
            LPVOID lpMsgBuf; 
            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |  
                FORMAT_MESSAGE_FROM_SYSTEM | 
                FORMAT_MESSAGE_IGNORE_INSERTS, 
                NULL, GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL); 
            OutputDebugString((LPCTSTR)lpMsgBuf); 
            LocalFree( lpMsgBuf ); 
            bFini = true; 
        } 
        if (bFini) 
        { 
            VirtualFree(lpEntreeDuCache, 0, MEM_RELEASE); 
            if (hCache) 
                FindCloseUrlCache(hCache); 
        } 
    } 
    return bResultat; 
}
NB : la ligne qui ne supprime pas le cookie de developpez.com est surtout là à titre d'exemple pour montrer comme éviter que certains cookies ne soient supprimés

Mis à jour le 20 mai 2006 nico-pyright(c)

En utilisant l'API SendInput :

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
void envoiChaine(char* sText) 
{ 
    bool bShift, bControl, bAlt; 
    unsigned int nPos, nCpt; 
    char cChar; 
    short nKeyScan; 
    INPUT input[256]; 
    for (nPos=0;nPos<= strlen(sText)-1;nPos++) 
    { 
        ZeroMemory(input, sizeof input); 
        nCpt = 0; 
        cChar = sText[nPos]; 
        nKeyScan = VkKeyScan(cChar); 
        bShift = (HIBYTE(nKeyScan) & 1?1:0); 
        bControl = (HIBYTE(nKeyScan) & 2?1:0); 
        bAlt = (HIBYTE(nKeyScan) & 4?1:0); 
        if (bShift) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_SHIFT; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_SHIFT, 0); 
            nCpt++; 
        } 
        if (bControl) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_CONTROL; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_CONTROL, 0); 
            nCpt++; 
        } 
        if (bAlt) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_MENU; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_MENU, 0); 
            nCpt++; 
        } 
        input[nCpt].type = INPUT_KEYBOARD; 
        input[nCpt].ki.wVk = LOBYTE(nKeyScan); 
        input[nCpt].ki.wScan = MapVirtualKey(LOBYTE(nKeyScan), 0); 
        nCpt++; 
        input[nCpt].type = INPUT_KEYBOARD; 
        input[nCpt].ki.wVk = LOBYTE(nKeyScan); 
        input[nCpt].ki.wScan = MapVirtualKey(LOBYTE(nKeyScan), 0); 
        input[nCpt].ki.dwFlags = KEYEVENTF_KEYUP; 
        nCpt++; 
        if (bShift) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_SHIFT; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_SHIFT, 0); 
            input[nCpt].ki.dwFlags = KEYEVENTF_KEYUP; 
            nCpt++; 
        } 
        if (bControl) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_CONTROL; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_CONTROL, 0); 
            input[nCpt].ki.dwFlags = KEYEVENTF_KEYUP; 
            nCpt++; 
        } 
        if (bAlt) 
        { 
            input[nCpt].type = INPUT_KEYBOARD; 
            input[nCpt].ki.wVk = VK_MENU; 
            input[nCpt].ki.wScan = MapVirtualKey(VK_MENU, 0); 
            input[nCpt].ki.dwFlags = KEYEVENTF_KEYUP; 
            nCpt++; 
        } 
        SendInput(nCpt, input, sizeof INPUT); 
    } 
}
ex :

Code c++ : Sélectionner tout
envoiChaine("Vive le c++");

Mis à jour le 20 mai 2006 nico-pyright(c)

En utilisant les API SetCursorPos et SendInput

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
bool click(int x, int y) 
{ 
SetCursorPos(x,y); 
INPUT in[2] = { {INPUT_MOUSE, {0, 0, 0, MOUSEEVENTF_LEFTDOWN, 0, 0}}, 
{INPUT_MOUSE, {0, 0, 0, MOUSEEVENTF_LEFTUP  , 0, 0}} }; 
return SendInput(2, in, sizeof(INPUT))>0; 
}
Code c++ : Sélectionner tout
if (click(0,0)) // ...

Mis à jour le 20 mai 2006 nico-pyright(c)

En utilisant l'objet COM du shell

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
  
int CreerRaccourci(const char * pathExe, 
                   const char * description, 
                   const char * argument, 
                   const char * repertoireDeTravail, 
                   const char *iconePath,  
                   int iconeIndex, 
                   const char * destination) 
{ 
    HRESULT hr; 
    CoInitialize(NULL); 
    BOOL bRet = FALSE; 
    IShellLink* psl; 
    if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink,  
        NULL,  
        CLSCTX_INPROC_SERVER, 
        IID_IShellLink, 
        (LPVOID*) &psl))) 
    { 
        IPersistFile* ppf; 
        psl->SetPath(pathExe); 
        psl->SetDescription(description); 
        psl->SetArguments(argument); 
        psl->SetWorkingDirectory(repertoireDeTravail); 
        if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf))) 
        { 
            wchar_t wsz[MAX_PATH]; 
            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, destination, -1, wsz, MAX_PATH); 
            hr = psl->SetIconLocation(iconePath, iconeIndex); 
            if(SUCCEEDED(ppf->Save(wsz, TRUE))) 
                bRet = TRUE; 
            ppf->Release(); 
        } 
        psl->Release(); 
    }  
    return bRet; 
}
Cette fonction pourra s'appeller par exemple de cette manière

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
if (CreerRaccourci("c:\\install.exe","l'installation","", "","c:\\monexe.exe",0,"c:\\mon raccourci.lnk")) 
{ 
// reussi 
} 
else 
{ 
// raté 
}

Mis à jour le 20 mai 2006 nico-pyright(c)

Le framework MFC s'occupe d'un traitement par défaut de la ligne de commande, grâce à l'objet CCommandLineInfo et aux fonctions ParseCommandLine et ProcessShellCommand.
Ce mécanisme est décrit rapidement ici
Les plus classiques étant
msdn a écrit:
app --> New file.
app filename --> Open file.
Si l'on veut personnaliser ce traitement, il faut créer une classe dérivée de CCommandLineInfo et surcharger la méthode ParseParam.

Par exemple, on veut démarrer l'application en maximisé, minimisé ou normal suivant un paramètre.
(On crée une variable membre dans notre classe d'application qui va stocker le mode int cmdShow_)

On crée une classe (sans classwizzard, puisqu'il ne propose pas la dérivation de CCommandLineInfo) (appellons là myCommandLineInfo) et on surcharge la méthode ParseParam

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
  
void myCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast) 
{ 
    CString param(pszParam); 
    CTestDeriveLigneCommandeApp *pTheApp = static_cast<CTestDeriveLigneCommandeApp *>(AfxGetApp()); 
    if (param == "runMaximized") 
        pTheApp->cmdShow_ = SW_SOWMAXIMIZED; 
    else if (param == "runMinimized") 
        pTheApp->cmdShow_ = SW_SHOWMINIMIZED; 
    else 
        pTheApp->cmdShow_ = SW_SHOW; 
}
Dans la méthode InitInstance de la classe d'application, il suffira de traiter la ligne de commande avec notre nouvelle classe

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
  
  // Parse command line for standard shell commands, DDE, file open 
    myCommandLineInfo cmdInfo; 
    ParseCommandLine(cmdInfo); 
  
   // Dispatch commands specified on the command line 
    if (!ProcessShellCommand(cmdInfo)) 
        return FALSE; 
  
   // The one and only window has been initialized, so show and update it. 
    m_pMainWnd->ShowWindow(cmdShow_); // ici appel avec notre variable membre 
    m_pMainWnd->UpdateWindow();
Application :

Code c++ : Sélectionner tout
1
2
  
c:\>monApp runMaximized --> lance en maximisé
Remarque : Si on veut éviter d'appeler le mécanisme par défaut, et traiter la ligne de commande soi-même, il ne faudra pas oublier d'appeller OnFileNew() pour créer un document vide, sinon la fenêtre principale ne sera pas initialisée et cela provoquera une assertion.

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

En faisant clic droit propriétés sur un fichier .exe ou .dll dans l'explorateur Windows
On peut visualiser les informations liées à la version du programme.
Ces informations sont disponibles dans le fichier ressources de notre application dans la section Version\VS_VERSION_INFO.

La question qui se pose c'est comment accéder à ces informations à l'intérieur d'un programme ?
Il faudra utiliser les fonctions GetFileVersionInfo et VerQueryValue
La classe qui suit se propose de récupérer l'ensemble de ces informations et d'en fournir l'accès pour chaque élément.
Le paramétrage par défaut de la fonction GetInfosFile permet de retrouver les informations pour l'exécutable en cours pour première page de langue trouvée.
(Il est possible d'avoir plusieurs définitions de langues dans les ressources).
la définition:

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
  
// récupération des informations de version du fichier .exe ou dll. 
// les zones suivantes sont disponibles:/ 
//        "FixedFileVersion","FixedProductVersion" 
//        "Comments","InternalName","ProductName", 
//        "CompanyName","LegalCopyright","ProductVersion", 
//        "FileDescription","LegalTrademarks","PrivateBuild", 
//        "FileVersion","OriginalFilename","SpecialBuild" 
class CVersionFile 
{ 
    private: CVersionFile(const CVersionFile&);      // pas de constructeur de copie 
    private: void operator=(const CVersionFile&); // pas d'operateur de copie. 
  
public: 
  
    CVersionFile(){} 
  
    // la valeur de la clef szLib correspondant a une entrée du dossier version 
    CString GetInfos(const TCHAR *szLib); 
  
    // permet d'itérer les valeurs stockées. 
    // charge la valeur rValue pour la clef correspondante dans rKeyName 
    // rFirstOne doit etre initialisée à true au premier appel de la fonction. 
    bool  GetNextInfos(bool &rFirstOne,CString &rstrKeyName,CString &rstrValue); 
  
  
    // récuperation des valeurs 
    // const char *szFileName  le module spécifié ou si null 'exe en cours d'execution. 
    // WORD wLanguage : le langage à lire ex:SUBLANG_ENGLISH_US ou si 0 le premier langage utilisé 
    // WORD wCodePage : la page code à lire ex:LANG_ENGLISH        ou si 0 la premiere page de code utilisée. 
    bool GetInfosFile(const TCHAR *szFileName=NULL,WORD wLanguage=0,WORD wCodePage=0); 
  
protected: 
    CMap<CString ,const TCHAR *,CString ,const TCHAR *> m_aListInfos;// rajouter include <afxtempl.h> dans stdafx.h 
    POSITION m_pos; 
};


l'implémentation

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  
#pragma comment(lib,"Version.lib") // à rajouter dans le source. 
//----------------------------------------------------------------- 
CString CVersionFile::GetInfos(const TCHAR *szLib) 
{ 
    // 
    CString str; 
    m_aListInfos.Lookup(szLib,str); 
    return str; 
} 
//----------------------------------------------------------------- 
bool CVersionFile::GetNextInfos(bool &rFirstOne,CString &rstrKeyName,CString &rstrValue) 
{ 
    //     
    if(rFirstOne) m_pos = m_aListInfos.GetStartPosition(); 
    rFirstOne=false;     
    if(m_pos!= NULL) 
    { 
        m_aListInfos.GetNextAssoc(m_pos,rstrKeyName,rstrValue); 
        return true; 
    }     
    return false; 
} 
//----------------------------------------------------------------- 
bool CVersionFile::GetInfosFile(const TCHAR *szFileName /*=NULL*/,WORD wLanguage /*=0*/,WORD wCodePage /*=0*/) 
{ 
    // 
    DWORD dwVerInfoSize; 
    DWORD dwHnd; 
    void* pBuffer; 
    VS_FIXEDFILEINFO *pFixedInfo; 
    LPVOID  lpVersionBuffer; 
    UINT    uLen; 
    TCHAR szGetName[500]; 
  
    TCHAR szExeName[MAX_PATH]; 
  
    m_aListInfos.RemoveAll(); 
  
    if(!szFileName)                 
        GetModuleFileName(AfxGetInstanceHandle(), szExeName, sizeof (szExeName)); 
#ifdef _UNICODE 
    else wcscpy(szExeName,szFileName); 
#else 
    else strcpy(szExeName,szFileName); 
#endif 
    dwVerInfoSize = GetFileVersionInfoSize(szExeName, &dwHnd); 
    if(dwVerInfoSize) 
    { 
        CString str; 
  
        pBuffer = new TCHAR[dwVerInfoSize]; 
        if (pBuffer == NULL) return false; 
  
        GetFileVersionInfo(szExeName, dwHnd, dwVerInfoSize, pBuffer); 
  
        // récupère les infos fixes indépendantes du langage. 
        // FixedProductVersion 
        VerQueryValue(pBuffer,_T("\\"),(void**)&pFixedInfo,(UINT *)&uLen); 
        str.Format (_T("%u,%u,%u,%u"), HIWORD (pFixedInfo->dwProductVersionMS), 
            LOWORD (pFixedInfo->dwProductVersionMS), 
            HIWORD (pFixedInfo->dwProductVersionLS), 
            LOWORD (pFixedInfo->dwProductVersionLS)); 
  
        m_aListInfos.SetAt(_T("FixedProductVersion"),str); 
  
        //FixedFileVersion 
        str.Format (_T("%u,%u,%u,%u"),HIWORD (pFixedInfo->dwFileVersionMS), 
            LOWORD (pFixedInfo->dwFileVersionMS), 
            HIWORD (pFixedInfo->dwFileVersionLS), 
            LOWORD (pFixedInfo->dwFileVersionLS)); 
  
        m_aListInfos.SetAt(_T("FixedFileVersion"),str); 
  
        // infos liées au langage. 
        unsigned int cbTranslate; 
        struct LANGANDCODEPAGE 
        { 
            WORD wLanguage; 
            WORD wCodePage; 
        } *lpTranslate; 
  
        // Read the list of languages and code pages. 
        VerQueryValue(pBuffer, 
            TEXT("\\VarFileInfo\\Translation"), 
            (LPVOID*)&lpTranslate, 
            &cbTranslate); 
  
        TCHAR *aszLib[]={_T("Comments"),_T("InternalName"),_T("ProductName"), 
                         _T("CompanyName"),_T("LegalCopyright"),_T("ProductVersion"), 
                         _T("FileDescription"),_T("LegalTrademarks"),_T("PrivateBuild"), 
                         _T("FileVersion"),_T("OriginalFilename"),_T("SpecialBuild") 
                        }; 
        // lecture des infos pour chage langue et page de code             
        for(int i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++ ) 
        { 
            // filtrage langage et page de code désirée ? 
            if(wLanguage && lpTranslate[i].wLanguage!=wLanguage) continue;                 
            if(wCodePage && lpTranslate[i].wCodePage!=wCodePage) continue; 
  
            for(int n=0;n<sizeof(aszLib)/sizeof(char *);n++) 
            { 
                str.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), 
                    lpTranslate[i].wLanguage, 
                    lpTranslate[i].wCodePage, 
                    aszLib[n]); 
  
                lstrcpy(szGetName,str); 
                // recuperation de l'information. 
                if (VerQueryValue(pBuffer,szGetName,(void**)&lpVersionBuffer,(UINT *)&uLen) != 0) 
                { 
                    if(lpVersionBuffer) 
                    { 
                        str = (LPTSTR)lpVersionBuffer; 
                        m_aListInfos.SetAt(aszLib[n],str); 
                    } 
                } 
            }                 
        } 
        delete [] pBuffer; 
    } 
    return (m_aListInfos.GetCount()!=0); 
}
Exemple d'application:

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
  
CVersionFile InfosFile; 
InfosFile.GetInfosFile();         
  
// accés par libellé   
CString str=InfosFile.GetInfos(_T("InternalName")); 
str+=_T(" Version "); 
str+=InfosFile.GetInfos(_T("PrivateBuild")); 
str+=_T(" "); 
str+=InfosFile.GetInfos(_T("LegalCopyright")); 
  
TRACE(_T("\n Version:%s "),static_cast<const TCHAR *>(str)); 
  
// itération 
bool bFirst=true; 
CString strValue,strKeyName; 
while(InfosFile.GetNextInfos(bFirst,strKeyName,strValue)) 
{             
    TRACE(_T("\n KeyName:%s:%s "),static_cast<const TCHAR *>(strKeyName),static_cast<const TCHAR *>(strValue)); 
}

Mis à jour le 22 janvier 2007 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
 

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.