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 afficher le message d'erreur correspondant au code d'erreur renvoyé par GetLastError() ?
- Comment récupérer le nom de la machine ?
- Comment lancer une application au démarrage du système ?
- Comment travailler avec le compteur de haute précision ?
- Comment appliquer le style XP aux fenêtres ?
- Comment inclure directement le fichier manifest dans les ressources ?
- Comment rajouter le fichier manifeste du style XP au manifeste existant dans Visual 2005 ?
- Comment faire une application win32 sans fenêtre apparente ?
- Comment émettre un son ?
- Comment bloquer les "touches spéciales" de Windows ?
- Comment faire clignoter une fenêtre dans la barre des tâches ?
- Comment utiliser printf/cout/... avec une console créée dynamiquement ?
- Comment avoir une icône avec un menu pour mon application dans la barre des tâches système (systray) ?
- Comment vider le cache d'Internet Explorer ?
- Comment simuler le clavier pour écrire une phrase complète ?
- Comment simuler un clic de souris à une position donnée ?
- Comment créer un raccourci ?
- Comment personnaliser le traitement par défaut de la ligne de commande ?
- Comment récupérer les informations de version dans un programme Windows ?
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 ); |
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); } |
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
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 |
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; } |
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); |
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> |
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 |
Code c++ : | Sélectionner tout |
1 2 3 4 | // Add manually edited resources here... IDR_MANIFEST RT_MANIFEST MOVEABLE PURE "res\\MyAppManifestFile" |
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 |
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 …
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; } |
La fonction la plus simple MessageBeep :
Code c++ : | Sélectionner tout |
1 2 3 | BOOL MessageBeep( UINT 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 ); |
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); |
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"); |
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
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 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.
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(); } |
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;
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 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); } |
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); } |
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;
Rajouter la définition du message privé
Code c++ : | Sélectionner tout |
#define WM_TRAY_MESSAGE (WM_USER + 1)
Code c++ : | Sélectionner tout |
afx_msg void OnTrayNotify(WPARAM wParam, LPARAM lParam);
Code c++ : | Sélectionner tout |
ON_MESSAGE(WM_TRAY_MESSAGE,OnTrayNotify)
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); |
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; } |
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); } |
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
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; } |
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); } } |
Code c++ : | Sélectionner tout |
envoiChaine("Vive le 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)) // ...
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; } |
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é } |
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; } |
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(); |
Code c++ : | Sélectionner tout |
1 2 | c:\>monApp runMaximized --> lance en maximisé |
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); } |
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)); } |
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.